summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/ChangeLog.16
-rw-r--r--test/Makefile.in229
-rw-r--r--test/README118
-rw-r--r--test/data/decompress/tg.tar.gzbin0 -> 150 bytes
-rw-r--r--test/data/decompress/zg.zipbin0 -> 182 bytes
-rw-r--r--test/data/emacs-module/mod-test.c331
-rw-r--r--test/data/image/black-short.jpgbin0 -> 31779 bytes
-rw-r--r--test/data/image/black.gifbin0 -> 143 bytes
-rw-r--r--test/data/image/black.jpgbin0 -> 52456 bytes
-rw-r--r--test/data/image/black.webpbin0 -> 37780 bytes
-rw-r--r--test/data/xref/file1.txt2
-rw-r--r--test/file-organization.org33
-rw-r--r--test/infra/Dockerfile.emba105
-rw-r--r--test/infra/Makefile.in100
-rw-r--r--test/infra/gitlab-ci.yml279
-rw-r--r--test/infra/test-jobs.yml545
-rw-r--r--test/lib-src/emacsclient-tests.el4
-rw-r--r--test/lisp/abbrev-tests.el120
-rw-r--r--test/lisp/align-resources/align-post.c3
-rw-r--r--test/lisp/align-resources/align-post.java9
-rw-r--r--test/lisp/align-resources/align-pre.c3
-rw-r--r--test/lisp/align-resources/align-pre.java9
-rw-r--r--test/lisp/align-tests.el47
-rw-r--r--test/lisp/allout-tests.el148
-rw-r--r--test/lisp/allout-widgets-tests.el87
-rw-r--r--test/lisp/ansi-color-tests.el196
-rw-r--r--test/lisp/apropos-tests.el133
-rw-r--r--test/lisp/arc-mode-tests.el22
-rw-r--r--test/lisp/auth-source-pass-tests.el532
-rw-r--r--test/lisp/auth-source-resources/authinfo2
-rw-r--r--test/lisp/auth-source-resources/netrc-folding6
-rw-r--r--test/lisp/auth-source-tests.el205
-rw-r--r--test/lisp/autoinsert-tests.el103
-rw-r--r--test/lisp/autorevert-tests.el846
-rw-r--r--test/lisp/battery-tests.el154
-rw-r--r--test/lisp/bookmark-resources/example.txt3
-rw-r--r--test/lisp/bookmark-resources/test-list.bmk20
-rw-r--r--test/lisp/bookmark-resources/test.bmk10
-rw-r--r--test/lisp/bookmark-tests.el656
-rw-r--r--test/lisp/buff-menu-tests.el23
-rw-r--r--test/lisp/button-tests.el104
-rw-r--r--test/lisp/calc/calc-tests.el743
-rw-r--r--test/lisp/calculator-tests.el51
-rw-r--r--test/lisp/calendar/cal-french-tests.el114
-rw-r--r--test/lisp/calendar/cal-julian-tests.el72
-rw-r--r--test/lisp/calendar/icalendar-resources/import-bug-11473.diary-european10
-rw-r--r--test/lisp/calendar/icalendar-resources/import-bug-11473.ics54
-rw-r--r--test/lisp/calendar/icalendar-resources/import-bug-22092.diary-american6
-rw-r--r--test/lisp/calendar/icalendar-resources/import-bug-22092.diary-european6
-rw-r--r--test/lisp/calendar/icalendar-resources/import-bug-22092.diary-iso6
-rw-r--r--test/lisp/calendar/icalendar-resources/import-bug-22092.ics30
-rw-r--r--test/lisp/calendar/icalendar-resources/import-bug-24199.diary-american5
-rw-r--r--test/lisp/calendar/icalendar-resources/import-bug-24199.diary-european5
-rw-r--r--test/lisp/calendar/icalendar-resources/import-bug-24199.diary-iso5
-rw-r--r--test/lisp/calendar/icalendar-resources/import-bug-24199.ics25
-rw-r--r--test/lisp/calendar/icalendar-resources/import-bug-33277.diary-american1
-rw-r--r--test/lisp/calendar/icalendar-resources/import-bug-33277.diary-european1
-rw-r--r--test/lisp/calendar/icalendar-resources/import-bug-33277.diary-iso1
-rw-r--r--test/lisp/calendar/icalendar-resources/import-bug-33277.ics15
-rw-r--r--test/lisp/calendar/icalendar-resources/import-bug-6766.diary-american7
-rw-r--r--test/lisp/calendar/icalendar-resources/import-bug-6766.diary-european7
-rw-r--r--test/lisp/calendar/icalendar-resources/import-bug-6766.diary-iso7
-rw-r--r--test/lisp/calendar/icalendar-resources/import-bug-6766.ics28
-rw-r--r--test/lisp/calendar/icalendar-resources/import-duration-2.diary-american3
-rw-r--r--test/lisp/calendar/icalendar-resources/import-duration-2.diary-european3
-rw-r--r--test/lisp/calendar/icalendar-resources/import-duration-2.diary-iso3
-rw-r--r--test/lisp/calendar/icalendar-resources/import-duration-2.ics17
-rw-r--r--test/lisp/calendar/icalendar-resources/import-duration.diary-american1
-rw-r--r--test/lisp/calendar/icalendar-resources/import-duration.diary-european1
-rw-r--r--test/lisp/calendar/icalendar-resources/import-duration.diary-iso1
-rw-r--r--test/lisp/calendar/icalendar-resources/import-duration.ics10
-rw-r--r--test/lisp/calendar/icalendar-resources/import-multiple-vcalendars.diary-american4
-rw-r--r--test/lisp/calendar/icalendar-resources/import-multiple-vcalendars.diary-european4
-rw-r--r--test/lisp/calendar/icalendar-resources/import-multiple-vcalendars.diary-iso4
-rw-r--r--test/lisp/calendar/icalendar-resources/import-multiple-vcalendars.ics21
-rw-r--r--test/lisp/calendar/icalendar-resources/import-non-recurring-1.diary-american1
-rw-r--r--test/lisp/calendar/icalendar-resources/import-non-recurring-1.diary-european1
-rw-r--r--test/lisp/calendar/icalendar-resources/import-non-recurring-1.diary-iso1
-rw-r--r--test/lisp/calendar/icalendar-resources/import-non-recurring-1.ics10
-rw-r--r--test/lisp/calendar/icalendar-resources/import-non-recurring-all-day.diary-american1
-rw-r--r--test/lisp/calendar/icalendar-resources/import-non-recurring-all-day.diary-european1
-rw-r--r--test/lisp/calendar/icalendar-resources/import-non-recurring-all-day.diary-iso1
-rw-r--r--test/lisp/calendar/icalendar-resources/import-non-recurring-all-day.ics9
-rw-r--r--test/lisp/calendar/icalendar-resources/import-non-recurring-another-example.diary-american4
-rw-r--r--test/lisp/calendar/icalendar-resources/import-non-recurring-another-example.diary-european4
-rw-r--r--test/lisp/calendar/icalendar-resources/import-non-recurring-another-example.diary-iso4
-rw-r--r--test/lisp/calendar/icalendar-resources/import-non-recurring-another-example.ics23
-rw-r--r--test/lisp/calendar/icalendar-resources/import-non-recurring-block.diary-american4
-rw-r--r--test/lisp/calendar/icalendar-resources/import-non-recurring-block.diary-european4
-rw-r--r--test/lisp/calendar/icalendar-resources/import-non-recurring-block.diary-iso4
-rw-r--r--test/lisp/calendar/icalendar-resources/import-non-recurring-block.ics16
-rw-r--r--test/lisp/calendar/icalendar-resources/import-non-recurring-folded-summary.diary-american4
-rw-r--r--test/lisp/calendar/icalendar-resources/import-non-recurring-folded-summary.diary-european4
-rw-r--r--test/lisp/calendar/icalendar-resources/import-non-recurring-folded-summary.diary-iso4
-rw-r--r--test/lisp/calendar/icalendar-resources/import-non-recurring-folded-summary.ics25
-rw-r--r--test/lisp/calendar/icalendar-resources/import-non-recurring-long-summary.diary-american1
-rw-r--r--test/lisp/calendar/icalendar-resources/import-non-recurring-long-summary.diary-european1
-rw-r--r--test/lisp/calendar/icalendar-resources/import-non-recurring-long-summary.diary-iso1
-rw-r--r--test/lisp/calendar/icalendar-resources/import-non-recurring-long-summary.ics10
-rw-r--r--test/lisp/calendar/icalendar-resources/import-real-world-2003-05-29.diary-american6
-rw-r--r--test/lisp/calendar/icalendar-resources/import-real-world-2003-05-29.diary-european6
-rw-r--r--test/lisp/calendar/icalendar-resources/import-real-world-2003-05-29.ics54
-rw-r--r--test/lisp/calendar/icalendar-resources/import-real-world-2003-06-18a.diary-american6
-rw-r--r--test/lisp/calendar/icalendar-resources/import-real-world-2003-06-18a.diary-european6
-rw-r--r--test/lisp/calendar/icalendar-resources/import-real-world-2003-06-18a.ics36
-rw-r--r--test/lisp/calendar/icalendar-resources/import-real-world-2003-06-18b.diary-american6
-rw-r--r--test/lisp/calendar/icalendar-resources/import-real-world-2003-06-18b.diary-european6
-rw-r--r--test/lisp/calendar/icalendar-resources/import-real-world-2003-06-18b.ics55
-rw-r--r--test/lisp/calendar/icalendar-resources/import-real-world-2004-11-19.diary-american19
-rw-r--r--test/lisp/calendar/icalendar-resources/import-real-world-2004-11-19.diary-european19
-rw-r--r--test/lisp/calendar/icalendar-resources/import-real-world-2004-11-19.ics120
-rw-r--r--test/lisp/calendar/icalendar-resources/import-real-world-2005-02-07.diary-american5
-rw-r--r--test/lisp/calendar/icalendar-resources/import-real-world-2005-02-07.diary-european5
-rw-r--r--test/lisp/calendar/icalendar-resources/import-real-world-2005-02-07.ics26
-rw-r--r--test/lisp/calendar/icalendar-resources/import-real-world-2005-03-01.diary-american2
-rw-r--r--test/lisp/calendar/icalendar-resources/import-real-world-2005-03-01.diary-european2
-rw-r--r--test/lisp/calendar/icalendar-resources/import-real-world-2005-03-01.ics11
-rw-r--r--test/lisp/calendar/icalendar-resources/import-real-world-no-dst.diary-american4
-rw-r--r--test/lisp/calendar/icalendar-resources/import-real-world-no-dst.diary-european4
-rw-r--r--test/lisp/calendar/icalendar-resources/import-real-world-no-dst.ics26
-rw-r--r--test/lisp/calendar/icalendar-resources/import-rrule-anniversary.diary-american1
-rw-r--r--test/lisp/calendar/icalendar-resources/import-rrule-anniversary.diary-european1
-rw-r--r--test/lisp/calendar/icalendar-resources/import-rrule-anniversary.diary-iso1
-rw-r--r--test/lisp/calendar/icalendar-resources/import-rrule-anniversary.ics11
-rw-r--r--test/lisp/calendar/icalendar-resources/import-rrule-count-bi-weekly.diary-american1
-rw-r--r--test/lisp/calendar/icalendar-resources/import-rrule-count-bi-weekly.diary-european1
-rw-r--r--test/lisp/calendar/icalendar-resources/import-rrule-count-bi-weekly.diary-iso1
-rw-r--r--test/lisp/calendar/icalendar-resources/import-rrule-count-bi-weekly.ics11
-rw-r--r--test/lisp/calendar/icalendar-resources/import-rrule-count-daily-long.diary-american1
-rw-r--r--test/lisp/calendar/icalendar-resources/import-rrule-count-daily-long.diary-european1
-rw-r--r--test/lisp/calendar/icalendar-resources/import-rrule-count-daily-long.diary-iso1
-rw-r--r--test/lisp/calendar/icalendar-resources/import-rrule-count-daily-long.ics11
-rw-r--r--test/lisp/calendar/icalendar-resources/import-rrule-count-daily-short.diary-american1
-rw-r--r--test/lisp/calendar/icalendar-resources/import-rrule-count-daily-short.diary-european1
-rw-r--r--test/lisp/calendar/icalendar-resources/import-rrule-count-daily-short.diary-iso1
-rw-r--r--test/lisp/calendar/icalendar-resources/import-rrule-count-daily-short.ics11
-rw-r--r--test/lisp/calendar/icalendar-resources/import-rrule-count-every-second-month.diary-american1
-rw-r--r--test/lisp/calendar/icalendar-resources/import-rrule-count-every-second-month.diary-european1
-rw-r--r--test/lisp/calendar/icalendar-resources/import-rrule-count-every-second-month.diary-iso1
-rw-r--r--test/lisp/calendar/icalendar-resources/import-rrule-count-every-second-month.ics11
-rw-r--r--test/lisp/calendar/icalendar-resources/import-rrule-count-every-second-year.diary-american1
-rw-r--r--test/lisp/calendar/icalendar-resources/import-rrule-count-every-second-year.diary-european1
-rw-r--r--test/lisp/calendar/icalendar-resources/import-rrule-count-every-second-year.diary-iso1
-rw-r--r--test/lisp/calendar/icalendar-resources/import-rrule-count-every-second-year.ics10
-rw-r--r--test/lisp/calendar/icalendar-resources/import-rrule-count-monthly.diary-american1
-rw-r--r--test/lisp/calendar/icalendar-resources/import-rrule-count-monthly.diary-european1
-rw-r--r--test/lisp/calendar/icalendar-resources/import-rrule-count-monthly.diary-iso1
-rw-r--r--test/lisp/calendar/icalendar-resources/import-rrule-count-monthly.ics11
-rw-r--r--test/lisp/calendar/icalendar-resources/import-rrule-count-yearly.diary-american1
-rw-r--r--test/lisp/calendar/icalendar-resources/import-rrule-count-yearly.diary-european1
-rw-r--r--test/lisp/calendar/icalendar-resources/import-rrule-count-yearly.diary-iso1
-rw-r--r--test/lisp/calendar/icalendar-resources/import-rrule-count-yearly.ics11
-rw-r--r--test/lisp/calendar/icalendar-resources/import-rrule-daily-two-day.diary-american1
-rw-r--r--test/lisp/calendar/icalendar-resources/import-rrule-daily-two-day.diary-european1
-rw-r--r--test/lisp/calendar/icalendar-resources/import-rrule-daily-two-day.diary-iso1
-rw-r--r--test/lisp/calendar/icalendar-resources/import-rrule-daily-two-day.ics10
-rw-r--r--test/lisp/calendar/icalendar-resources/import-rrule-daily-with-exceptions.diary-american1
-rw-r--r--test/lisp/calendar/icalendar-resources/import-rrule-daily-with-exceptions.diary-european1
-rw-r--r--test/lisp/calendar/icalendar-resources/import-rrule-daily-with-exceptions.diary-iso1
-rw-r--r--test/lisp/calendar/icalendar-resources/import-rrule-daily-with-exceptions.ics12
-rw-r--r--test/lisp/calendar/icalendar-resources/import-rrule-daily.diary-american1
-rw-r--r--test/lisp/calendar/icalendar-resources/import-rrule-daily.diary-european1
-rw-r--r--test/lisp/calendar/icalendar-resources/import-rrule-daily.diary-iso1
-rw-r--r--test/lisp/calendar/icalendar-resources/import-rrule-daily.ics11
-rw-r--r--test/lisp/calendar/icalendar-resources/import-rrule-monthly-no-end.diary-american1
-rw-r--r--test/lisp/calendar/icalendar-resources/import-rrule-monthly-no-end.diary-european1
-rw-r--r--test/lisp/calendar/icalendar-resources/import-rrule-monthly-no-end.diary-iso1
-rw-r--r--test/lisp/calendar/icalendar-resources/import-rrule-monthly-no-end.ics11
-rw-r--r--test/lisp/calendar/icalendar-resources/import-rrule-monthly-with-end.diary-american1
-rw-r--r--test/lisp/calendar/icalendar-resources/import-rrule-monthly-with-end.diary-european1
-rw-r--r--test/lisp/calendar/icalendar-resources/import-rrule-monthly-with-end.diary-iso1
-rw-r--r--test/lisp/calendar/icalendar-resources/import-rrule-monthly-with-end.ics11
-rw-r--r--test/lisp/calendar/icalendar-resources/import-rrule-weekly.diary-american1
-rw-r--r--test/lisp/calendar/icalendar-resources/import-rrule-weekly.diary-european1
-rw-r--r--test/lisp/calendar/icalendar-resources/import-rrule-weekly.diary-iso1
-rw-r--r--test/lisp/calendar/icalendar-resources/import-rrule-weekly.ics11
-rw-r--r--test/lisp/calendar/icalendar-resources/import-rrule-yearly.diary-american1
-rw-r--r--test/lisp/calendar/icalendar-resources/import-rrule-yearly.diary-european1
-rw-r--r--test/lisp/calendar/icalendar-resources/import-rrule-yearly.diary-iso1
-rw-r--r--test/lisp/calendar/icalendar-resources/import-rrule-yearly.ics11
-rw-r--r--test/lisp/calendar/icalendar-resources/import-with-timezone.diary-iso2
-rw-r--r--test/lisp/calendar/icalendar-resources/import-with-timezone.ics27
-rw-r--r--test/lisp/calendar/icalendar-resources/import-with-uid.diary-american2
-rw-r--r--test/lisp/calendar/icalendar-resources/import-with-uid.diary-european2
-rw-r--r--test/lisp/calendar/icalendar-resources/import-with-uid.diary-iso2
-rw-r--r--test/lisp/calendar/icalendar-resources/import-with-uid.ics10
-rw-r--r--test/lisp/calendar/icalendar-tests.el1606
-rw-r--r--test/lisp/calendar/iso8601-tests.el354
-rw-r--r--test/lisp/calendar/lunar-tests.el73
-rw-r--r--test/lisp/calendar/parse-time-tests.el66
-rw-r--r--test/lisp/calendar/solar-tests.el48
-rw-r--r--test/lisp/calendar/time-date-tests.el216
-rw-r--r--test/lisp/calendar/todo-mode-resources/todo-test-1.todo10
-rw-r--r--test/lisp/calendar/todo-mode-tests.el436
-rw-r--r--test/lisp/cedet/cedet-files-tests.el51
-rw-r--r--test/lisp/cedet/semantic-utest-c.el180
-rw-r--r--test/lisp/cedet/semantic-utest-ia-resources/test.mk18
-rw-r--r--test/lisp/cedet/semantic-utest-ia-resources/test.srt64
-rw-r--r--test/lisp/cedet/semantic-utest-ia-resources/test.texi40
-rw-r--r--test/lisp/cedet/semantic-utest-ia-resources/testdoublens.cpp (renamed from test/manual/cedet/tests/testdoublens.cpp)57
-rw-r--r--test/lisp/cedet/semantic-utest-ia-resources/testdoublens.hpp (renamed from test/manual/cedet/tests/testdoublens.hpp)10
-rw-r--r--test/lisp/cedet/semantic-utest-ia-resources/testfriends.cpp (renamed from test/manual/cedet/tests/testfriends.cpp)1
-rw-r--r--test/lisp/cedet/semantic-utest-ia-resources/testjavacomp.java (renamed from test/manual/cedet/tests/testjavacomp.java)20
-rw-r--r--test/lisp/cedet/semantic-utest-ia-resources/testlocalvars.cpp54
-rw-r--r--test/lisp/cedet/semantic-utest-ia-resources/testnsp.cpp122
-rw-r--r--test/lisp/cedet/semantic-utest-ia-resources/testsppcomplete.c66
-rw-r--r--test/lisp/cedet/semantic-utest-ia-resources/teststruct.cpp86
-rw-r--r--test/lisp/cedet/semantic-utest-ia-resources/testsubclass.cpp (renamed from test/manual/cedet/tests/testsubclass.cpp)4
-rw-r--r--test/lisp/cedet/semantic-utest-ia-resources/testsubclass.hh (renamed from test/manual/cedet/tests/testsubclass.hh)4
-rw-r--r--test/lisp/cedet/semantic-utest-ia-resources/testtemplates.cpp149
-rw-r--r--test/lisp/cedet/semantic-utest-ia-resources/testtypedefs.cpp (renamed from test/manual/cedet/tests/testtypedefs.cpp)79
-rw-r--r--test/lisp/cedet/semantic-utest-ia-resources/testusing.cpp265
-rw-r--r--test/lisp/cedet/semantic-utest-ia-resources/testusing.hh176
-rw-r--r--test/lisp/cedet/semantic-utest-ia-resources/testvarnames.c (renamed from test/manual/cedet/tests/testvarnames.c)22
-rw-r--r--test/lisp/cedet/semantic-utest-ia-resources/testvarnames.java60
-rw-r--r--test/lisp/cedet/semantic-utest-ia-resources/testwisent.wy85
-rw-r--r--test/lisp/cedet/semantic-utest-ia.el (renamed from test/manual/cedet/semantic-ia-utest.el)434
-rw-r--r--test/lisp/cedet/semantic-utest.el (renamed from test/manual/cedet/semantic-utest.el)275
-rw-r--r--test/lisp/cedet/semantic/bovine/gcc-tests.el131
-rw-r--r--test/lisp/cedet/semantic/format-resources/test-fmt.cpp108
-rw-r--r--test/lisp/cedet/semantic/format-resources/test-fmt.el65
-rw-r--r--test/lisp/cedet/semantic/format-tests.el95
-rw-r--r--test/lisp/cedet/semantic/fw-tests.el45
-rw-r--r--test/lisp/cedet/srecode-utest-getset.el178
-rw-r--r--test/lisp/cedet/srecode-utest-template.el377
-rw-r--r--test/lisp/cedet/srecode/document-tests.el78
-rw-r--r--test/lisp/cedet/srecode/fields-tests.el (renamed from test/manual/cedet/srecode-tests.el)125
-rw-r--r--test/lisp/char-fold-tests.el157
-rw-r--r--test/lisp/color-tests.el16
-rw-r--r--test/lisp/comint-tests.el58
-rw-r--r--test/lisp/completion-tests.el170
-rw-r--r--test/lisp/cus-edit-tests.el89
-rw-r--r--test/lisp/custom-resources/custom--test-theme.el13
-rw-r--r--test/lisp/custom-tests.el328
-rw-r--r--test/lisp/dabbrev-tests.el41
-rw-r--r--test/lisp/delim-col-tests.el181
-rw-r--r--test/lisp/descr-text-tests.el14
-rw-r--r--test/lisp/desktop-tests.el50
-rw-r--r--test/lisp/dired-aux-tests.el161
-rw-r--r--test/lisp/dired-resources/insert-directory/test_dir/bar0
-rw-r--r--test/lisp/dired-resources/insert-directory/test_dir/foo0
-rw-r--r--test/lisp/dired-resources/insert-directory/test_dir_other/bar0
-rw-r--r--test/lisp/dired-resources/insert-directory/test_dir_other/foo0
-rw-r--r--test/lisp/dired-tests.el549
-rw-r--r--test/lisp/dired-x-tests.el44
-rw-r--r--test/lisp/dnd-tests.el441
-rw-r--r--test/lisp/dom-tests.el19
-rw-r--r--test/lisp/edmacro-tests.el48
-rw-r--r--test/lisp/electric-tests.el430
-rw-r--r--test/lisp/elide-head-tests.el227
-rw-r--r--test/lisp/emacs-lisp/backquote-tests.el47
-rw-r--r--test/lisp/emacs-lisp/backtrace-tests.el485
-rw-r--r--test/lisp/emacs-lisp/benchmark-tests.el32
-rw-r--r--test/lisp/emacs-lisp/bindat-tests.el285
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/bc-test-alpha.el9
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/bc-test-beta.el6
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/error-lexical-var-with-add-hook.el4
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/error-lexical-var-with-remove-hook.el4
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/error-lexical-var-with-run-hook-with-args-until-failure.el3
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/error-lexical-var-with-run-hook-with-args-until-success.el3
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/error-lexical-var-with-run-hook-with-args.el3
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/error-lexical-var-with-symbol-value.el4
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/foo-inlinable.el6
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/fun-attr-warn.el266
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/no-byte-compile.el1
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/nowarn-inline-after-defvar.el17
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/warn-autoload-not-on-top-level.el3
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/warn-callargs-defsubst.el5
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/warn-callargs.el5
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/warn-defcustom-nogroup.el3
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/warn-defcustom-notype.el3
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/warn-defvar-lacks-prefix.el2
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/warn-format.el2
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/warn-free-setq.el2
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/warn-free-variable-reference.el4
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/warn-interactive-only.el3
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/warn-lambda-malformed-interactive-spec.el4
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/warn-make-variable-buffer-local.el4
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/warn-obsolete-defun.el8
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/warn-obsolete-hook.el3
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/warn-obsolete-variable-bound.el7
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/warn-obsolete-variable-same-file.el13
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/warn-obsolete-variable.el4
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/warn-redefine-defun-as-macro.el3
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/warn-redefine-defun.el3
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/warn-redefine-macro-as-defun.el3
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/warn-save-excursion.el5
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/warn-variable-let-bind-constant.el3
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/warn-variable-let-bind-nonvariable.el3
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/warn-variable-set-constant.el3
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/warn-variable-setq-nonvariable.el3
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/warn-variable-setq-odd.el3
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-autoload.el3
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-custom-declare-variable.el4
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-defalias.el3
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-defconst.el3
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-define-abbrev-table.el3
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-define-obsolete-function-alias.el3
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-define-obsolete-variable-alias.el3
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-defun.el3
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-defvar.el6
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-defvaralias.el3
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-ignore-fill-column.el7
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-ignore-function-signature.el4
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-ignore-override.el8
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-ignore-substitutions.el17
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-ignore.el7
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-multiline-first.el5
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-multiline.el6
-rw-r--r--test/lisp/emacs-lisp/bytecomp-tests.el1415
-rw-r--r--test/lisp/emacs-lisp/cconv-tests.el361
-rw-r--r--test/lisp/emacs-lisp/check-declare-tests.el108
-rw-r--r--test/lisp/emacs-lisp/checkdoc-tests.el170
-rw-r--r--test/lisp/emacs-lisp/cl-extra-tests.el39
-rw-r--r--test/lisp/emacs-lisp/cl-generic-tests.el66
-rw-r--r--test/lisp/emacs-lisp/cl-lib-tests.el92
-rw-r--r--test/lisp/emacs-lisp/cl-macs-tests.el340
-rw-r--r--test/lisp/emacs-lisp/cl-preloaded-tests.el33
-rw-r--r--test/lisp/emacs-lisp/cl-print-tests.el162
-rw-r--r--test/lisp/emacs-lisp/cl-seq-tests.el11
-rw-r--r--test/lisp/emacs-lisp/comp-cstr-tests.el233
-rw-r--r--test/lisp/emacs-lisp/copyright-tests.el96
-rw-r--r--test/lisp/emacs-lisp/derived-tests.el64
-rw-r--r--test/lisp/emacs-lisp/easy-mmode-tests.el63
-rw-r--r--test/lisp/emacs-lisp/edebug-resources/edebug-test-code.el59
-rw-r--r--test/lisp/emacs-lisp/edebug-tests.el371
-rw-r--r--test/lisp/emacs-lisp/eieio-tests/eieio-test-methodinvoke.el318
-rw-r--r--test/lisp/emacs-lisp/eieio-tests/eieio-test-persist.el168
-rw-r--r--test/lisp/emacs-lisp/eieio-tests/eieio-tests.el627
-rw-r--r--test/lisp/emacs-lisp/ert-tests.el284
-rw-r--r--test/lisp/emacs-lisp/ert-x-tests.el170
-rw-r--r--test/lisp/emacs-lisp/faceup-resources/faceup-test-mode.el76
-rw-r--r--test/lisp/emacs-lisp/faceup-resources/faceup-test-this-file-directory.el32
-rw-r--r--test/lisp/emacs-lisp/faceup-resources/files/test1.txt15
-rw-r--r--test/lisp/emacs-lisp/faceup-resources/files/test1.txt.faceup15
-rw-r--r--test/lisp/emacs-lisp/faceup-tests/faceup-test-basics.el269
-rw-r--r--test/lisp/emacs-lisp/faceup-tests/faceup-test-files.el63
-rw-r--r--test/lisp/emacs-lisp/find-func-tests.el125
-rw-r--r--test/lisp/emacs-lisp/float-sup-tests.el33
-rw-r--r--test/lisp/emacs-lisp/generator-tests.el58
-rw-r--r--test/lisp/emacs-lisp/gv-tests.el96
-rw-r--r--test/lisp/emacs-lisp/hierarchy-tests.el556
-rw-r--r--test/lisp/emacs-lisp/icons-tests.el63
-rw-r--r--test/lisp/emacs-lisp/let-alist-tests.el11
-rw-r--r--test/lisp/emacs-lisp/lisp-mnt-tests.el44
-rw-r--r--test/lisp/emacs-lisp/lisp-mode-tests.el132
-rw-r--r--test/lisp/emacs-lisp/lisp-tests.el100
-rw-r--r--test/lisp/emacs-lisp/macroexp-resources/m1.el36
-rw-r--r--test/lisp/emacs-lisp/macroexp-resources/m2.el33
-rw-r--r--test/lisp/emacs-lisp/macroexp-resources/vk.el130
-rw-r--r--test/lisp/emacs-lisp/macroexp-tests.el127
-rw-r--r--test/lisp/emacs-lisp/map-tests.el600
-rw-r--r--test/lisp/emacs-lisp/memory-report-tests.el83
-rw-r--r--test/lisp/emacs-lisp/multisession-tests.el207
-rw-r--r--test/lisp/emacs-lisp/nadvice-tests.el23
-rw-r--r--test/lisp/emacs-lisp/oclosure-tests.el166
-rw-r--r--test/lisp/emacs-lisp/package-resources/key.pub29
-rw-r--r--test/lisp/emacs-lisp/package-resources/key.sec44
-rw-r--r--test/lisp/emacs-lisp/package-resources/macro-builtin-package-1.0/macro-builtin-aux.el12
-rw-r--r--test/lisp/emacs-lisp/package-resources/macro-builtin-package-1.0/macro-builtin.el21
-rw-r--r--test/lisp/emacs-lisp/package-resources/macro-builtin-package-2.0/macro-builtin-aux.el16
-rw-r--r--test/lisp/emacs-lisp/package-resources/macro-builtin-package-2.0/macro-builtin.el30
-rw-r--r--test/lisp/emacs-lisp/package-resources/macro-problem-package-1.0/macro-aux.el2
-rw-r--r--test/lisp/emacs-lisp/package-resources/macro-problem-package-1.0/macro-problem.el4
-rw-r--r--test/lisp/emacs-lisp/package-resources/macro-problem-package-2.0/macro-aux.el4
-rw-r--r--test/lisp/emacs-lisp/package-resources/macro-problem-package-2.0/macro-problem.el8
-rw-r--r--test/lisp/emacs-lisp/package-resources/newer-versions/new-pkg-1.0.el2
-rw-r--r--test/lisp/emacs-lisp/package-resources/newer-versions/simple-single-1.4.el8
-rw-r--r--test/lisp/emacs-lisp/package-resources/signed/archive-contents.sigbin287 -> 95 bytes
-rw-r--r--test/lisp/emacs-lisp/package-resources/signed/signed-bad-1.0.el8
-rw-r--r--test/lisp/emacs-lisp/package-resources/signed/signed-good-1.0.el8
-rw-r--r--test/lisp/emacs-lisp/package-resources/signed/signed-good-1.0.el.sigbin287 -> 95 bytes
-rwxr-xr-xtest/lisp/emacs-lisp/package-resources/signed/update-signatures.sh32
-rw-r--r--test/lisp/emacs-lisp/package-resources/simple-depend-1.0.el4
-rw-r--r--test/lisp/emacs-lisp/package-resources/simple-single-1.3.el8
-rw-r--r--test/lisp/emacs-lisp/package-resources/simple-two-depend-1.1.el4
-rw-r--r--test/lisp/emacs-lisp/package-resources/with-nil-entry/archive-contents8
-rw-r--r--test/lisp/emacs-lisp/package-tests.el567
-rw-r--r--test/lisp/emacs-lisp/pcase-tests.el103
-rw-r--r--test/lisp/emacs-lisp/pp-resources/code-formats.erts142
-rw-r--r--test/lisp/emacs-lisp/pp-tests.el6
-rw-r--r--test/lisp/emacs-lisp/range-tests.el65
-rw-r--r--test/lisp/emacs-lisp/regexp-opt-tests.el50
-rw-r--r--test/lisp/emacs-lisp/ring-tests.el41
-rw-r--r--test/lisp/emacs-lisp/rmc-tests.el91
-rw-r--r--test/lisp/emacs-lisp/rx-tests.el564
-rw-r--r--test/lisp/emacs-lisp/seq-tests.el224
-rw-r--r--test/lisp/emacs-lisp/shadow-resources/p1/foo.el1
-rw-r--r--test/lisp/emacs-lisp/shadow-resources/p2/FOO.el1
-rw-r--r--test/lisp/emacs-lisp/shadow-tests.el42
-rw-r--r--test/lisp/emacs-lisp/shortdoc-tests.el60
-rw-r--r--test/lisp/emacs-lisp/subr-x-tests.el314
-rw-r--r--test/lisp/emacs-lisp/syntax-tests.el63
-rw-r--r--test/lisp/emacs-lisp/tabulated-list-tests.el (renamed from test/lisp/emacs-lisp/tabulated-list-test.el)53
-rw-r--r--test/lisp/emacs-lisp/testcover-resources/testcases.el100
-rw-r--r--test/lisp/emacs-lisp/testcover-tests.el152
-rw-r--r--test/lisp/emacs-lisp/text-property-search-tests.el175
-rw-r--r--test/lisp/emacs-lisp/thunk-tests.el52
-rw-r--r--test/lisp/emacs-lisp/timer-tests.el32
-rw-r--r--test/lisp/emacs-lisp/unsafep-tests.el154
-rw-r--r--test/lisp/emacs-lisp/vtable-tests.el42
-rw-r--r--test/lisp/emacs-lisp/warnings-tests.el60
-rw-r--r--test/lisp/emulation/viper-tests.el84
-rw-r--r--test/lisp/env-tests.el40
-rw-r--r--test/lisp/epg-config-tests.el47
-rwxr-xr-xtest/lisp/epg-resources/dummy-pinentry (renamed from test/data/epg/dummy-pinentry)0
-rw-r--r--test/lisp/epg-resources/pubkey.asc (renamed from test/data/epg/pubkey.asc)0
-rw-r--r--test/lisp/epg-resources/seckey.asc (renamed from test/data/epg/seckey.asc)0
-rw-r--r--test/lisp/epg-tests.el119
-rw-r--r--test/lisp/erc/erc-dcc-tests.el167
-rw-r--r--test/lisp/erc/erc-join-tests.el361
-rw-r--r--test/lisp/erc/erc-match-tests.el193
-rw-r--r--test/lisp/erc/erc-networks-tests.el1707
-rw-r--r--test/lisp/erc/erc-scenarios-auth-source.el178
-rw-r--r--test/lisp/erc/erc-scenarios-base-association-nick.el163
-rw-r--r--test/lisp/erc/erc-scenarios-base-association-samenet.el144
-rw-r--r--test/lisp/erc/erc-scenarios-base-association.el192
-rw-r--r--test/lisp/erc/erc-scenarios-base-compat-rename-bouncer.el171
-rw-r--r--test/lisp/erc/erc-scenarios-base-misc-regressions.el126
-rw-r--r--test/lisp/erc/erc-scenarios-base-netid-bouncer-id.el34
-rw-r--r--test/lisp/erc/erc-scenarios-base-netid-bouncer-recon-base.el30
-rw-r--r--test/lisp/erc/erc-scenarios-base-netid-bouncer-recon-both.el32
-rw-r--r--test/lisp/erc/erc-scenarios-base-netid-bouncer-recon-id.el35
-rw-r--r--test/lisp/erc/erc-scenarios-base-netid-bouncer.el35
-rw-r--r--test/lisp/erc/erc-scenarios-base-netid-samenet.el147
-rw-r--r--test/lisp/erc/erc-scenarios-base-reconnect.el227
-rw-r--r--test/lisp/erc/erc-scenarios-base-renick.el305
-rw-r--r--test/lisp/erc/erc-scenarios-base-reuse-buffers.el233
-rw-r--r--test/lisp/erc/erc-scenarios-base-unstable.el134
-rw-r--r--test/lisp/erc/erc-scenarios-base-upstream-recon-soju.el43
-rw-r--r--test/lisp/erc/erc-scenarios-base-upstream-recon-znc.el43
-rw-r--r--test/lisp/erc/erc-scenarios-internal.el27
-rw-r--r--test/lisp/erc/erc-scenarios-join-auth-source.el67
-rw-r--r--test/lisp/erc/erc-scenarios-join-netid-newcmd-id.el50
-rw-r--r--test/lisp/erc/erc-scenarios-join-netid-newcmd.el37
-rw-r--r--test/lisp/erc/erc-scenarios-join-netid-recon-id.el46
-rw-r--r--test/lisp/erc/erc-scenarios-join-netid-recon.el36
-rw-r--r--test/lisp/erc/erc-scenarios-misc.el180
-rw-r--r--test/lisp/erc/erc-scenarios-services-misc.el86
-rw-r--r--test/lisp/erc/erc-services-tests.el574
-rw-r--r--test/lisp/erc/erc-tests.el978
-rw-r--r--test/lisp/erc/erc-track-tests.el11
-rw-r--r--test/lisp/erc/resources/base/assoc/bouncer-history/barnet.eld44
-rw-r--r--test/lisp/erc/resources/base/assoc/bouncer-history/foonet.eld48
-rw-r--r--test/lisp/erc/resources/base/assoc/bumped/again.eld30
-rw-r--r--test/lisp/erc/resources/base/assoc/bumped/foisted.eld30
-rw-r--r--test/lisp/erc/resources/base/assoc/bumped/refoisted.eld31
-rw-r--r--test/lisp/erc/resources/base/assoc/bumped/renicked.eld30
-rw-r--r--test/lisp/erc/resources/base/assoc/multi-net/barnet.eld42
-rw-r--r--test/lisp/erc/resources/base/assoc/multi-net/foonet.eld45
-rw-r--r--test/lisp/erc/resources/base/assoc/reconplay/again.eld42
-rw-r--r--test/lisp/erc/resources/base/assoc/reconplay/foonet.eld52
-rw-r--r--test/lisp/erc/resources/base/assoc/samenet/chester.eld40
-rw-r--r--test/lisp/erc/resources/base/assoc/samenet/tester.eld42
-rw-r--r--test/lisp/erc/resources/base/assoc/samenet/tester2.eld39
-rw-r--r--test/lisp/erc/resources/base/auth-source/foonet.eld23
-rw-r--r--test/lisp/erc/resources/base/auth-source/nopass.eld22
-rw-r--r--test/lisp/erc/resources/base/channel-buffer-revival/foonet.eld45
-rw-r--r--test/lisp/erc/resources/base/flood/soju.eld87
-rw-r--r--test/lisp/erc/resources/base/gapless-connect/barnet.eld40
-rw-r--r--test/lisp/erc/resources/base/gapless-connect/foonet.eld41
-rw-r--r--test/lisp/erc/resources/base/gapless-connect/pass-stub.eld4
-rw-r--r--test/lisp/erc/resources/base/mask-target-routing/foonet.eld45
-rw-r--r--test/lisp/erc/resources/base/netid/bouncer/barnet-again.eld50
-rw-r--r--test/lisp/erc/resources/base/netid/bouncer/barnet-drop.eld41
-rw-r--r--test/lisp/erc/resources/base/netid/bouncer/barnet.eld41
-rw-r--r--test/lisp/erc/resources/base/netid/bouncer/foonet-again.eld50
-rw-r--r--test/lisp/erc/resources/base/netid/bouncer/foonet-drop.eld46
-rw-r--r--test/lisp/erc/resources/base/netid/bouncer/foonet.eld46
-rw-r--r--test/lisp/erc/resources/base/netid/bouncer/stub-again.eld4
-rw-r--r--test/lisp/erc/resources/base/netid/samenet/chester.eld48
-rw-r--r--test/lisp/erc/resources/base/netid/samenet/tester.eld52
-rw-r--r--test/lisp/erc/resources/base/reconnect/aborted-dupe.eld28
-rw-r--r--test/lisp/erc/resources/base/reconnect/aborted.eld45
-rw-r--r--test/lisp/erc/resources/base/reconnect/options-again.eld45
-rw-r--r--test/lisp/erc/resources/base/reconnect/options.eld35
-rw-r--r--test/lisp/erc/resources/base/reconnect/timer-last.eld6
-rw-r--r--test/lisp/erc/resources/base/reconnect/timer.eld6
-rw-r--r--test/lisp/erc/resources/base/renick/queries/bouncer-barnet.eld54
-rw-r--r--test/lisp/erc/resources/base/renick/queries/bouncer-foonet.eld52
-rw-r--r--test/lisp/erc/resources/base/renick/queries/solo.eld55
-rw-r--r--test/lisp/erc/resources/base/renick/self/auto.eld46
-rw-r--r--test/lisp/erc/resources/base/renick/self/manual.eld50
-rw-r--r--test/lisp/erc/resources/base/renick/self/qual-chester.eld40
-rw-r--r--test/lisp/erc/resources/base/renick/self/qual-tester.eld46
-rw-r--r--test/lisp/erc/resources/base/reuse-buffers/channel/barnet.eld68
-rw-r--r--test/lisp/erc/resources/base/reuse-buffers/channel/foonet.eld66
-rw-r--r--test/lisp/erc/resources/base/reuse-buffers/server/barnet.eld24
-rw-r--r--test/lisp/erc/resources/base/reuse-buffers/server/foonet.eld24
-rw-r--r--test/lisp/erc/resources/base/upstream-reconnect/soju-barnet.eld64
-rw-r--r--test/lisp/erc/resources/base/upstream-reconnect/soju-foonet.eld72
-rw-r--r--test/lisp/erc/resources/base/upstream-reconnect/znc-barnet.eld93
-rw-r--r--test/lisp/erc/resources/base/upstream-reconnect/znc-foonet.eld86
-rw-r--r--test/lisp/erc/resources/dcc/chat/accept-dcc.eld3
-rw-r--r--test/lisp/erc/resources/dcc/chat/accept.eld23
-rw-r--r--test/lisp/erc/resources/erc-d/erc-d-i.el124
-rw-r--r--test/lisp/erc/resources/erc-d/erc-d-t.el170
-rw-r--r--test/lisp/erc/resources/erc-d/erc-d-tests.el1373
-rw-r--r--test/lisp/erc/resources/erc-d/erc-d-u.el213
-rw-r--r--test/lisp/erc/resources/erc-d/erc-d.el1009
-rw-r--r--test/lisp/erc/resources/erc-d/resources/basic.eld32
-rw-r--r--test/lisp/erc/resources/erc-d/resources/depleted.eld12
-rw-r--r--test/lisp/erc/resources/erc-d/resources/drop-a.eld4
-rw-r--r--test/lisp/erc/resources/erc-d/resources/drop-b.eld4
-rw-r--r--test/lisp/erc/resources/erc-d/resources/dynamic-barnet.eld33
-rw-r--r--test/lisp/erc/resources/erc-d/resources/dynamic-foonet.eld32
-rw-r--r--test/lisp/erc/resources/erc-d/resources/dynamic-stub.eld4
-rw-r--r--test/lisp/erc/resources/erc-d/resources/dynamic.eld30
-rw-r--r--test/lisp/erc/resources/erc-d/resources/eof.eld33
-rw-r--r--test/lisp/erc/resources/erc-d/resources/foreign.eld5
-rw-r--r--test/lisp/erc/resources/erc-d/resources/fuzzy.eld42
-rw-r--r--test/lisp/erc/resources/erc-d/resources/incremental.eld43
-rw-r--r--test/lisp/erc/resources/erc-d/resources/irc-parser-tests.eld380
-rw-r--r--test/lisp/erc/resources/erc-d/resources/linger-multi-a.eld3
-rw-r--r--test/lisp/erc/resources/erc-d/resources/linger-multi-b.eld3
-rw-r--r--test/lisp/erc/resources/erc-d/resources/linger.eld33
-rw-r--r--test/lisp/erc/resources/erc-d/resources/no-block.eld55
-rw-r--r--test/lisp/erc/resources/erc-d/resources/no-match.eld32
-rw-r--r--test/lisp/erc/resources/erc-d/resources/no-pong.eld27
-rw-r--r--test/lisp/erc/resources/erc-d/resources/nonstandard.eld6
-rw-r--r--test/lisp/erc/resources/erc-d/resources/proxy-barnet.eld24
-rw-r--r--test/lisp/erc/resources/erc-d/resources/proxy-foonet.eld24
-rw-r--r--test/lisp/erc/resources/erc-d/resources/proxy-solo.eld9
-rw-r--r--test/lisp/erc/resources/erc-d/resources/proxy-subprocess.el45
-rw-r--r--test/lisp/erc/resources/erc-d/resources/timeout.eld27
-rw-r--r--test/lisp/erc/resources/erc-d/resources/unexpected.eld28
-rw-r--r--test/lisp/erc/resources/erc-scenarios-common.el516
-rw-r--r--test/lisp/erc/resources/join/auth-source/foonet.eld33
-rw-r--r--test/lisp/erc/resources/join/legacy/foonet.eld38
-rw-r--r--test/lisp/erc/resources/join/network-id/barnet.eld43
-rw-r--r--test/lisp/erc/resources/join/network-id/foonet-again.eld46
-rw-r--r--test/lisp/erc/resources/join/network-id/foonet.eld39
-rw-r--r--test/lisp/erc/resources/join/reconnect/foonet-again.eld45
-rw-r--r--test/lisp/erc/resources/join/reconnect/foonet.eld45
-rw-r--r--test/lisp/erc/resources/networks/announced-missing/foonet.eld8
-rw-r--r--test/lisp/erc/resources/services/auth-source/libera.eld49
-rw-r--r--test/lisp/erc/resources/services/password/libera.eld49
-rw-r--r--test/lisp/eshell/em-alias-tests.el87
-rw-r--r--test/lisp/eshell/em-basic-tests.el71
-rw-r--r--test/lisp/eshell/em-dirs-tests.el102
-rw-r--r--test/lisp/eshell/em-extpipe-tests.el205
-rw-r--r--test/lisp/eshell/em-glob-tests.el197
-rw-r--r--test/lisp/eshell/em-hist-tests.el38
-rw-r--r--test/lisp/eshell/em-ls-tests.el57
-rw-r--r--test/lisp/eshell/em-pred-tests.el566
-rw-r--r--test/lisp/eshell/em-script-tests.el62
-rw-r--r--test/lisp/eshell/em-tramp-tests.el88
-rw-r--r--test/lisp/eshell/esh-cmd-tests.el294
-rw-r--r--test/lisp/eshell/esh-io-tests.el292
-rw-r--r--test/lisp/eshell/esh-opt-tests.el289
-rw-r--r--test/lisp/eshell/esh-proc-tests.el249
-rw-r--r--test/lisp/eshell/esh-var-tests.el569
-rw-r--r--test/lisp/eshell/eshell-tests-helpers.el140
-rw-r--r--test/lisp/eshell/eshell-tests.el234
-rw-r--r--test/lisp/faces-resources/faces-test-dark-theme.el35
-rw-r--r--test/lisp/faces-resources/faces-test-light-theme.el34
-rw-r--r--test/lisp/faces-tests.el177
-rw-r--r--test/lisp/ffap-tests.el143
-rw-r--r--test/lisp/filenotify-tests.el1273
-rw-r--r--test/lisp/files-resources/.dir-locals.el5
-rw-r--r--test/lisp/files-resources/auto-test.zot11
-rw-r--r--test/lisp/files-resources/auto-test.zot21
-rw-r--r--test/lisp/files-resources/auto-test.zot31
-rw-r--r--test/lisp/files-resources/compile-utf8.el12
-rw-r--r--test/lisp/files-resources/file-mode3
-rw-r--r--test/lisp/files-resources/file-mode-multiple5
-rw-r--r--test/lisp/files-resources/file-mode-prop-line1
-rw-r--r--test/lisp/files-resources/files-bug18141.el.gz (renamed from test/data/files-bug18141.el.gz)bin77 -> 77 bytes
-rw-r--r--test/lisp/files-resources/whatever.quux2
-rw-r--r--test/lisp/files-tests.el1721
-rw-r--r--test/lisp/files-x-tests.el171
-rw-r--r--test/lisp/find-cmd-tests.el45
-rw-r--r--test/lisp/font-lock-tests.el41
-rw-r--r--test/lisp/format-spec-tests.el191
-rw-r--r--test/lisp/gnus/gnus-group-tests.el52
-rw-r--r--test/lisp/gnus/gnus-icalendar-tests.el259
-rw-r--r--test/lisp/gnus/gnus-search-tests.el100
-rw-r--r--test/lisp/gnus/gnus-test-headers.el178
-rw-r--r--test/lisp/gnus/gnus-tests.el6
-rw-r--r--test/lisp/gnus/gnus-util-tests.el135
-rw-r--r--test/lisp/gnus/message-tests.el99
-rw-r--r--test/lisp/gnus/mm-decode-resources/8bit-multipart.bin20
-rw-r--r--test/lisp/gnus/mm-decode-resources/win1252-multipart.bin44
-rw-r--r--test/lisp/gnus/mm-decode-tests.el102
-rw-r--r--test/lisp/gnus/mml-sec-resources/.gpg-v21-migrated0
-rw-r--r--test/lisp/gnus/mml-sec-resources/gpg-agent.conf5
-rw-r--r--test/lisp/gnus/mml-sec-resources/private-keys-v1.d/02089CDDC6DFE93B8EA10D9E876F983E61FEC476.keybin0 -> 797 bytes
-rw-r--r--test/lisp/gnus/mml-sec-resources/private-keys-v1.d/171B444DE92BEF997229000D9784118A94EEC1C9.keybin0 -> 526 bytes
-rw-r--r--test/lisp/gnus/mml-sec-resources/private-keys-v1.d/19FFEBC04DF3E037E16F6A4474DCB7984406975D.keybin0 -> 841 bytes
-rw-r--r--test/lisp/gnus/mml-sec-resources/private-keys-v1.d/1E36D27DF9DAB96302D35268DADC5CE73EF45A2A.keybin0 -> 797 bytes
-rw-r--r--test/lisp/gnus/mml-sec-resources/private-keys-v1.d/293109315BE584AB2EFEFCFCAD64666221D8B36C.keybin0 -> 526 bytes
-rw-r--r--test/lisp/gnus/mml-sec-resources/private-keys-v1.d/335689599E1C0F66D73ADCF51E03EE36C97D121F.keybin0 -> 797 bytes
-rw-r--r--test/lisp/gnus/mml-sec-resources/private-keys-v1.d/40BF94E540E3726CB150A1ADF7C1B514444B3FA6.keybin0 -> 797 bytes
-rw-r--r--test/lisp/gnus/mml-sec-resources/private-keys-v1.d/515D4637EFC6C09DB1F78BE8C2F2A3D63E7756C3.keybin0 -> 798 bytes
-rw-r--r--test/lisp/gnus/mml-sec-resources/private-keys-v1.d/5A11B1935C46D0B227A73978DCA1293A85604F1D.keybin0 -> 798 bytes
-rw-r--r--test/lisp/gnus/mml-sec-resources/private-keys-v1.d/62643CEBC7AEBE6817577A34399483700D76BD64.keybin0 -> 526 bytes
-rw-r--r--test/lisp/gnus/mml-sec-resources/private-keys-v1.d/680D01F368916A0021C14E3453B27B3C5F900683.keybin0 -> 710 bytes
-rw-r--r--test/lisp/gnus/mml-sec-resources/private-keys-v1.d/6DF2D9DF7AED06F0524BEB642DF0FB48EFDBDB93.keybin0 -> 798 bytes
-rw-r--r--test/lisp/gnus/mml-sec-resources/private-keys-v1.d/78C17E134E86E691297F7B719B2F2CDF41976234.keybin0 -> 527 bytes
-rw-r--r--test/lisp/gnus/mml-sec-resources/private-keys-v1.d/7F714F4D9D9676638214991E96D45704E4FFC409.keybin0 -> 798 bytes
-rw-r--r--test/lisp/gnus/mml-sec-resources/private-keys-v1.d/854752F5D8090CA36EFBDD79C72BDFF6FA2D1FF0.keybin0 -> 526 bytes
-rw-r--r--test/lisp/gnus/mml-sec-resources/private-keys-v1.d/93FF37C268FDBF0767F5FFDC49409DDAC9388B2C.keybin0 -> 709 bytes
-rw-r--r--test/lisp/gnus/mml-sec-resources/private-keys-v1.d/A3BA94EAE83509CC90DB1B77B54A51959D8DABEA.keybin0 -> 797 bytes
-rw-r--r--test/lisp/gnus/mml-sec-resources/private-keys-v1.d/A73E9D01F0465B518E8E7D5AD529077AAC1603B4.keybin0 -> 710 bytes
-rw-r--r--test/lisp/gnus/mml-sec-resources/private-keys-v1.d/AE6A24B17A8D0CAF9B7E000AA77F0B41D7BFFFCF.keybin0 -> 841 bytes
-rw-r--r--test/lisp/gnus/mml-sec-resources/private-keys-v1.d/C072AF82DCCCB9A7F1B85FFA10B802DC4ED16703.keybin0 -> 841 bytes
-rw-r--r--test/lisp/gnus/mml-sec-resources/private-keys-v1.d/C43E1A079B28DFAEBB39CBA01793BDE11EF4B490.keybin0 -> 527 bytes
-rw-r--r--test/lisp/gnus/mml-sec-resources/private-keys-v1.d/C67DAD345455EAD6D51368008FC3A53B8D195B5A.keybin0 -> 710 bytes
-rw-r--r--test/lisp/gnus/mml-sec-resources/private-keys-v1.d/CB5E00CE582C2645D2573FC16B2F14F85A7F47AA.keybin0 -> 797 bytes
-rw-r--r--test/lisp/gnus/mml-sec-resources/private-keys-v1.d/CC68630A06B048F5A91136C162C7A3273E20DE6F.keybin0 -> 710 bytes
-rw-r--r--test/lisp/gnus/mml-sec-resources/private-keys-v1.d/E7E73903E1BF93481DE0E7C9769D6C31E1863CFF.keybin0 -> 797 bytes
-rw-r--r--test/lisp/gnus/mml-sec-resources/private-keys-v1.d/F0117468BE801ED4B81972E159A98FDD4814DCEC.keybin0 -> 797 bytes
-rw-r--r--test/lisp/gnus/mml-sec-resources/private-keys-v1.d/F4C5EFD5779BE892CAFD5B721D68DED677C9B151.keybin0 -> 841 bytes
-rw-r--r--test/lisp/gnus/mml-sec-resources/pubring.gpgbin0 -> 13883 bytes
-rw-r--r--test/lisp/gnus/mml-sec-resources/pubring.kbxbin0 -> 3076 bytes
-rw-r--r--test/lisp/gnus/mml-sec-resources/secring.gpgbin0 -> 17362 bytes
-rw-r--r--test/lisp/gnus/mml-sec-resources/trustdb.gpgbin0 -> 1880 bytes
-rw-r--r--test/lisp/gnus/mml-sec-resources/trustlist.txt26
-rw-r--r--test/lisp/gnus/mml-sec-tests.el900
-rw-r--r--test/lisp/gnus/nnrss-tests.el45
-rw-r--r--test/lisp/help-fns-tests.el87
-rw-r--r--test/lisp/help-mode-tests.el169
-rw-r--r--test/lisp/help-tests.el486
-rw-r--r--test/lisp/hfy-cmap-resources/rgb.txt4
-rw-r--r--test/lisp/hfy-cmap-tests.el55
-rw-r--r--test/lisp/hi-lock-tests.el181
-rw-r--r--test/lisp/hl-line-tests.el114
-rw-r--r--test/lisp/htmlfontify-tests.el15
-rw-r--r--test/lisp/ibuffer-tests.el16
-rw-r--r--test/lisp/ido-tests.el9
-rw-r--r--test/lisp/image-file-tests.el44
-rw-r--r--test/lisp/image-tests.el156
-rw-r--r--test/lisp/image/exif-tests.el49
-rw-r--r--test/lisp/image/gravatar-tests.el77
-rw-r--r--test/lisp/image/image-dired-tests.el37
-rw-r--r--test/lisp/image/image-dired-util-tests.el54
-rw-r--r--test/lisp/imenu-tests.el19
-rw-r--r--test/lisp/info-tests.el39
-rw-r--r--test/lisp/info-xref-tests.el104
-rw-r--r--test/lisp/international/ccl-tests.el252
-rw-r--r--test/lisp/international/mule-tests.el39
-rw-r--r--test/lisp/international/mule-util-resources/utf-8.txt2
-rw-r--r--test/lisp/international/mule-util-tests.el51
-rw-r--r--test/lisp/international/textsec-tests.el214
-rw-r--r--test/lisp/international/ucs-normalize-tests.el180
-rw-r--r--test/lisp/isearch-tests.el90
-rw-r--r--test/lisp/jit-lock-tests.el6
-rw-r--r--test/lisp/json-tests.el980
-rw-r--r--test/lisp/jsonrpc-tests.el255
-rw-r--r--test/lisp/kmacro-tests.el76
-rw-r--r--test/lisp/loadhist-resources/loadhist--bar.el27
-rw-r--r--test/lisp/loadhist-resources/loadhist--foo.el29
-rw-r--r--test/lisp/loadhist-tests.el104
-rw-r--r--test/lisp/lpr-tests.el41
-rw-r--r--test/lisp/ls-lisp-tests.el78
-rw-r--r--test/lisp/mail/flow-fill-tests.el107
-rw-r--r--test/lisp/mail/footnote-tests.el47
-rw-r--r--test/lisp/mail/ietf-drums-date-tests.el172
-rw-r--r--test/lisp/mail/ietf-drums-tests.el178
-rw-r--r--test/lisp/mail/mail-extr-tests.el41
-rw-r--r--test/lisp/mail/mail-parse-tests.el54
-rw-r--r--test/lisp/mail/mail-utils-tests.el105
-rw-r--r--test/lisp/mail/qp-tests.el74
-rw-r--r--test/lisp/mail/rfc2045-tests.el37
-rw-r--r--test/lisp/mail/rfc2047-tests.el60
-rw-r--r--test/lisp/mail/rfc6068-tests.el52
-rw-r--r--test/lisp/mail/rfc822-tests.el83
-rw-r--r--test/lisp/mail/rmail-tests.el6
-rw-r--r--test/lisp/mail/rmailmm-tests.el (renamed from test/manual/rmailmm.el)62
-rw-r--r--test/lisp/mail/undigest-tests.el359
-rw-r--r--test/lisp/mail/uudecode-resources/uudecoded.txt16
-rw-r--r--test/lisp/mail/uudecode-resources/uuencoded.txt19
-rw-r--r--test/lisp/mail/uudecode-tests.el75
-rw-r--r--test/lisp/man-tests.el56
-rw-r--r--test/lisp/md4-tests.el4
-rw-r--r--test/lisp/mh-e/mh-limit-tests.el35
-rw-r--r--test/lisp/mh-e/mh-thread-tests.el131
-rw-r--r--test/lisp/mh-e/mh-utils-tests.el551
-rw-r--r--test/lisp/mh-e/mh-xface-tests.el50
-rwxr-xr-xtest/lisp/mh-e/test-all-mh-variants.sh102
-rw-r--r--test/lisp/minibuffer-resources/data/minibuffer-test-cttq$tion0
-rw-r--r--test/lisp/minibuffer-resources/lisp/cedet/semantic-utest-c.test0
-rw-r--r--test/lisp/minibuffer-resources/lisp/cedet/semantic-utest.test0
-rw-r--r--test/lisp/minibuffer-tests.el439
-rw-r--r--test/lisp/misc-tests.el138
-rw-r--r--test/lisp/mouse-tests.el199
-rw-r--r--test/lisp/mwheel-tests.el46
-rw-r--r--test/lisp/net/browse-url-tests.el122
-rw-r--r--test/lisp/net/dbus-resources/org.gnu.Emacs.TestDBus.xml49
-rw-r--r--test/lisp/net/dbus-tests.el1906
-rw-r--r--test/lisp/net/dig-tests.el56
-rw-r--r--test/lisp/net/gnutls-tests.el43
-rw-r--r--test/lisp/net/hmac-md5-tests.el80
-rw-r--r--test/lisp/net/mailcap-resources/mailcap9
-rw-r--r--test/lisp/net/mailcap-resources/mime.types (renamed from test/data/mailcap/mime.types)0
-rw-r--r--test/lisp/net/mailcap-resources/test.test1
-rw-r--r--test/lisp/net/mailcap-tests.el484
-rw-r--r--test/lisp/net/network-stream-resources/cert.pem (renamed from test/data/net/cert.pem)0
-rw-r--r--test/lisp/net/network-stream-resources/key.pem (renamed from test/data/net/key.pem)0
-rw-r--r--test/lisp/net/network-stream-tests.el515
-rw-r--r--test/lisp/net/newsticker-tests.el4
-rw-r--r--test/lisp/net/nsm-tests.el79
-rw-r--r--test/lisp/net/ntlm-resources/authinfo1
-rw-r--r--test/lisp/net/ntlm-tests.el427
-rw-r--r--test/lisp/net/puny-resources/IdnaTestV2.txt6344
-rw-r--r--test/lisp/net/puny-tests.el40
-rw-r--r--test/lisp/net/rcirc-tests.el66
-rw-r--r--test/lisp/net/rfc2104-tests.el41
-rw-r--r--test/lisp/net/sasl-cram-tests.el46
-rw-r--r--test/lisp/net/sasl-scram-rfc-tests.el30
-rw-r--r--test/lisp/net/sasl-tests.el59
-rw-r--r--test/lisp/net/secrets-tests.el275
-rw-r--r--test/lisp/net/shr-resources/div-div.html (renamed from test/data/shr/div-div.html)0
-rw-r--r--test/lisp/net/shr-resources/div-div.txt (renamed from test/data/shr/div-div.txt)0
-rw-r--r--test/lisp/net/shr-resources/div-p.html (renamed from test/data/shr/div-p.html)0
-rw-r--r--test/lisp/net/shr-resources/div-p.txt (renamed from test/data/shr/div-p.txt)0
-rw-r--r--test/lisp/net/shr-resources/li-div.html (renamed from test/data/shr/li-div.html)0
-rw-r--r--test/lisp/net/shr-resources/li-div.txt (renamed from test/data/shr/li-div.txt)0
-rw-r--r--test/lisp/net/shr-resources/li-empty.html (renamed from test/data/shr/li-empty.html)0
-rw-r--r--test/lisp/net/shr-resources/li-empty.txt (renamed from test/data/shr/li-empty.txt)0
-rw-r--r--test/lisp/net/shr-resources/nonbr.html (renamed from test/data/shr/nonbr.html)0
-rw-r--r--test/lisp/net/shr-resources/nonbr.txt (renamed from test/data/shr/nonbr.txt)0
-rw-r--r--test/lisp/net/shr-resources/ol.html29
-rw-r--r--test/lisp/net/shr-resources/ol.txt19
-rw-r--r--test/lisp/net/shr-resources/ul-empty.html (renamed from test/data/shr/ul-empty.html)0
-rw-r--r--test/lisp/net/shr-resources/ul-empty.txt (renamed from test/data/shr/ul-empty.txt)0
-rw-r--r--test/lisp/net/shr-tests.el45
-rw-r--r--test/lisp/net/socks-tests.el284
-rw-r--r--test/lisp/net/tramp-archive-resources/foo.iso/foo1
-rw-r--r--test/lisp/net/tramp-archive-resources/foo.tar.gzbin0 -> 274 bytes
-rw-r--r--test/lisp/net/tramp-archive-tests.el1045
-rw-r--r--test/lisp/net/tramp-resources/foo.tar.gzbin0 -> 274 bytes
-rw-r--r--test/lisp/net/tramp-tests.el7192
-rw-r--r--test/lisp/net/webjump-tests.el73
-rw-r--r--test/lisp/newcomment-tests.el39
-rw-r--r--test/lisp/nxml/nxml-mode-tests.el159
-rw-r--r--test/lisp/nxml/xsd-regexp-tests.el32
-rw-r--r--test/lisp/obarray-tests.el2
-rw-r--r--test/lisp/obsolete/cl-tests.el35
-rw-r--r--test/lisp/obsolete/inversion-tests.el80
-rw-r--r--test/lisp/obsolete/makesum-tests.el58
-rw-r--r--test/lisp/obsolete/rfc2368-tests.el39
-rw-r--r--test/lisp/obsolete/thumbs-tests.el32
-rw-r--r--test/lisp/org/org-tests.el33
-rw-r--r--test/lisp/osc-tests.el57
-rw-r--r--test/lisp/paren-tests.el152
-rw-r--r--test/lisp/password-cache-tests.el75
-rw-r--r--test/lisp/pcmpl-linux-resources/fs/ext4/.keep0
-rw-r--r--test/lisp/pcmpl-linux-resources/mtab11
-rw-r--r--test/lisp/pcmpl-linux-tests.el43
-rw-r--r--test/lisp/pcomplete-tests.el100
-rw-r--r--test/lisp/play/animate-tests.el56
-rw-r--r--test/lisp/play/cookie1-resources/cookies8
-rw-r--r--test/lisp/play/cookie1-tests.el40
-rw-r--r--test/lisp/play/dissociate-tests.el38
-rw-r--r--test/lisp/play/fortune-resources/fortunes11
-rw-r--r--test/lisp/play/fortune-tests.el41
-rw-r--r--test/lisp/play/life-tests.el80
-rw-r--r--test/lisp/play/morse-tests.el60
-rw-r--r--test/lisp/play/studly-tests.el52
-rw-r--r--test/lisp/progmodes/asm-mode-tests.el82
-rw-r--r--test/lisp/progmodes/autoconf-tests.el55
-rw-r--r--test/lisp/progmodes/bat-mode-tests.el7
-rw-r--r--test/lisp/progmodes/bug-reference-tests.el128
-rw-r--r--test/lisp/progmodes/cc-mode-tests.el44
-rw-r--r--test/lisp/progmodes/compile-tests.el527
-rw-r--r--test/lisp/progmodes/cperl-mode-resources/cperl-bug-11996.pl8
-rw-r--r--test/lisp/progmodes/cperl-mode-resources/cperl-bug-19709.pl25
-rw-r--r--test/lisp/progmodes/cperl-mode-resources/cperl-bug-22355.pl14
-rw-r--r--test/lisp/progmodes/cperl-mode-resources/cperl-bug-23992.pl10
-rw-r--r--test/lisp/progmodes/cperl-mode-resources/cperl-bug-25098.pl21
-rw-r--r--test/lisp/progmodes/cperl-mode-resources/cperl-bug-26850.pl16
-rw-r--r--test/lisp/progmodes/cperl-mode-resources/cperl-bug-30393.pl19
-rw-r--r--test/lisp/progmodes/cperl-mode-resources/cperl-indent-exp.pl52
-rw-r--r--test/lisp/progmodes/cperl-mode-resources/cperl-indent-styles.pl54
-rw-r--r--test/lisp/progmodes/cperl-mode-resources/cperl-indents.erts26
-rw-r--r--test/lisp/progmodes/cperl-mode-resources/fontify-punctuation-vars.pl20
-rw-r--r--test/lisp/progmodes/cperl-mode-resources/grammar.pl172
-rw-r--r--test/lisp/progmodes/cperl-mode-resources/here-docs.pl143
-rw-r--r--test/lisp/progmodes/cperl-mode-resources/proto-and-attrs.pl50
-rw-r--r--test/lisp/progmodes/cperl-mode-tests.el1151
-rw-r--r--test/lisp/progmodes/elisp-mode-resources/elisp-indents.erts88
-rw-r--r--test/lisp/progmodes/elisp-mode-resources/flet.erts353
-rw-r--r--test/lisp/progmodes/elisp-mode-resources/simple-shorthand-test.el40
-rw-r--r--test/lisp/progmodes/elisp-mode-tests.el471
-rw-r--r--test/lisp/progmodes/etags-tests.el37
-rw-r--r--test/lisp/progmodes/executable-tests.el51
-rw-r--r--test/lisp/progmodes/f90-tests.el44
-rw-r--r--test/lisp/progmodes/flymake-resources/Makefile4
-rw-r--r--test/lisp/progmodes/flymake-resources/another-problematic-file.c5
-rw-r--r--test/lisp/progmodes/flymake-resources/errors-and-warnings.c13
-rw-r--r--test/lisp/progmodes/flymake-resources/no-problems.h1
-rw-r--r--test/lisp/progmodes/flymake-resources/some-problems.h7
-rw-r--r--test/lisp/progmodes/flymake-resources/test.pl2
-rw-r--r--test/lisp/progmodes/flymake-resources/test.rb5
-rw-r--r--test/lisp/progmodes/flymake-tests.el370
-rw-r--r--test/lisp/progmodes/gdb-mi-tests.el50
-rw-r--r--test/lisp/progmodes/glasses-tests.el101
-rw-r--r--test/lisp/progmodes/grep-tests.el69
-rw-r--r--test/lisp/progmodes/hideshow-tests.el374
-rw-r--r--test/lisp/progmodes/js-resources/js-chain.js (renamed from test/manual/indent/js-chain.js)0
-rw-r--r--test/lisp/progmodes/js-resources/js-indent-align-list-continuation-nil.js (renamed from test/manual/indent/js-indent-align-list-continuation-nil.js)0
-rw-r--r--test/lisp/progmodes/js-resources/js-indent-init-dynamic.js (renamed from test/manual/indent/js-indent-init-dynamic.js)0
-rw-r--r--test/lisp/progmodes/js-resources/js-indent-init-t.js (renamed from test/manual/indent/js-indent-init-t.js)0
-rw-r--r--test/lisp/progmodes/js-resources/js.js (renamed from test/manual/indent/js.js)30
-rw-r--r--test/lisp/progmodes/js-resources/jsx-align-gt-with-lt.jsx12
-rw-r--r--test/lisp/progmodes/js-resources/jsx-comment-string.jsx23
-rw-r--r--test/lisp/progmodes/js-resources/jsx-indent-level.jsx13
-rw-r--r--test/lisp/progmodes/js-resources/jsx-quote.jsx16
-rw-r--r--test/lisp/progmodes/js-resources/jsx-self-closing.jsx13
-rw-r--r--test/lisp/progmodes/js-resources/jsx-unclosed-1.jsx13
-rw-r--r--test/lisp/progmodes/js-resources/jsx-unclosed-2.jsx65
-rw-r--r--test/lisp/progmodes/js-resources/jsx.jsx314
-rw-r--r--test/lisp/progmodes/js-tests.el45
-rw-r--r--test/lisp/progmodes/octave-tests.el49
-rw-r--r--test/lisp/progmodes/opascal-tests.el47
-rw-r--r--test/lisp/progmodes/pascal-tests.el67
-rw-r--r--test/lisp/progmodes/perl-mode-tests.el42
-rw-r--r--test/lisp/progmodes/project-tests.el113
-rw-r--r--test/lisp/progmodes/ps-mode-tests.el72
-rw-r--r--test/lisp/progmodes/python-tests.el1463
-rw-r--r--test/lisp/progmodes/ruby-mode-resources/ruby.rb (renamed from test/manual/indent/ruby.rb)31
-rw-r--r--test/lisp/progmodes/ruby-mode-tests.el213
-rw-r--r--test/lisp/progmodes/scheme-tests.el50
-rw-r--r--test/lisp/progmodes/sh-script-resources/sh-indents.erts40
-rw-r--r--test/lisp/progmodes/sh-script-tests.el72
-rw-r--r--test/lisp/progmodes/sql-tests.el456
-rw-r--r--test/lisp/progmodes/subword-tests.el12
-rw-r--r--test/lisp/progmodes/tcl-tests.el86
-rw-r--r--test/lisp/progmodes/xref-resources/file1.txt2
-rw-r--r--test/lisp/progmodes/xref-resources/file2.txt (renamed from test/data/xref/file2.txt)0
-rw-r--r--test/lisp/progmodes/xref-resources/file3.txt1
-rw-r--r--test/lisp/progmodes/xref-tests.el131
-rw-r--r--test/lisp/ps-print-tests.el4
-rw-r--r--test/lisp/register-tests.el2
-rw-r--r--test/lisp/repeat-tests.el141
-rw-r--r--test/lisp/replace-tests.el374
-rw-r--r--test/lisp/rot13-tests.el2
-rw-r--r--test/lisp/saveplace-resources/saveplace4
-rw-r--r--test/lisp/saveplace-tests.el94
-rw-r--r--test/lisp/scroll-lock-tests.el68
-rw-r--r--test/lisp/ses-tests.el151
-rw-r--r--test/lisp/shadowfile-tests.el947
-rw-r--r--test/lisp/shell-tests.el38
-rw-r--r--test/lisp/simple-tests.el557
-rw-r--r--test/lisp/so-long-tests/autoload-longlines-mode-tests.el52
-rw-r--r--test/lisp/so-long-tests/autoload-major-mode-tests.el47
-rw-r--r--test/lisp/so-long-tests/autoload-minor-mode-tests.el51
-rw-r--r--test/lisp/so-long-tests/so-long-tests-helpers.el141
-rw-r--r--test/lisp/so-long-tests/so-long-tests.el645
-rw-r--r--test/lisp/so-long-tests/spelling-tests.el69
-rw-r--r--test/lisp/sort-tests.el12
-rw-r--r--test/lisp/soundex-tests.el2
-rw-r--r--test/lisp/startup-tests.el47
-rw-r--r--test/lisp/subr-tests.el947
-rw-r--r--test/lisp/tab-bar-tests.el51
-rw-r--r--test/lisp/tabify-tests.el79
-rw-r--r--test/lisp/tar-mode-tests.el23
-rw-r--r--test/lisp/tempo-tests.el267
-rw-r--r--test/lisp/term-tests.el406
-rw-r--r--test/lisp/term/tty-colors-tests.el38
-rw-r--r--test/lisp/textmodes/bibtex-tests.el57
-rw-r--r--test/lisp/textmodes/conf-mode-tests.el201
-rw-r--r--test/lisp/textmodes/css-mode-resources/css-selectors.txt56
-rw-r--r--test/lisp/textmodes/css-mode-resources/scss-selectors.txt10
-rw-r--r--test/lisp/textmodes/css-mode-resources/test-indent.css (renamed from test/manual/indent/css-mode.css)16
-rw-r--r--test/lisp/textmodes/css-mode-tests.el220
-rw-r--r--test/lisp/textmodes/dns-mode-tests.el25
-rw-r--r--test/lisp/textmodes/emacs-news-mode-resources/toggle-tag.erts131
-rw-r--r--test/lisp/textmodes/emacs-news-mode-tests.el32
-rw-r--r--test/lisp/textmodes/fill-tests.el126
-rw-r--r--test/lisp/textmodes/mhtml-mode-tests.el4
-rw-r--r--test/lisp/textmodes/page-tests.el115
-rw-r--r--test/lisp/textmodes/paragraphs-resources/mark-paragraph.bin9
-rw-r--r--test/lisp/textmodes/paragraphs-tests.el188
-rw-r--r--test/lisp/textmodes/po-tests.el68
-rw-r--r--test/lisp/textmodes/reftex-tests.el446
-rw-r--r--test/lisp/textmodes/sgml-mode-tests.el106
-rw-r--r--test/lisp/textmodes/texinfo-resources/fill.erts70
-rw-r--r--test/lisp/textmodes/texinfo-tests.el33
-rw-r--r--test/lisp/textmodes/tildify-tests.el4
-rw-r--r--test/lisp/textmodes/underline-tests.el42
-rw-r--r--test/lisp/thingatpt-tests.el166
-rw-r--r--test/lisp/thread-tests.el96
-rw-r--r--test/lisp/time-resources/non-empty1
-rw-r--r--test/lisp/time-stamp-tests.el1118
-rw-r--r--test/lisp/time-tests.el82
-rw-r--r--test/lisp/timezone-tests.el172
-rw-r--r--test/lisp/url/url-auth-tests.el6
-rw-r--r--test/lisp/url/url-domsuf-tests.el51
-rw-r--r--test/lisp/url/url-expand-tests.el11
-rw-r--r--test/lisp/url/url-file-resources/file.txt1
-rw-r--r--test/lisp/url/url-file-tests.el44
-rw-r--r--test/lisp/url/url-future-tests.el26
-rw-r--r--test/lisp/url/url-handlers-tests.el76
-rw-r--r--test/lisp/url/url-misc-tests.el41
-rw-r--r--test/lisp/url/url-parse-tests.el6
-rw-r--r--test/lisp/url/url-tramp-tests.el91
-rw-r--r--test/lisp/url/url-util-tests.el36
-rw-r--r--test/lisp/vc/add-log-tests.el14
-rw-r--r--test/lisp/vc/diff-mode-resources/hello_emacs.c6
-rw-r--r--test/lisp/vc/diff-mode-resources/hello_emacs_1.c1
-rw-r--r--test/lisp/vc/diff-mode-resources/hello_world.c6
-rw-r--r--test/lisp/vc/diff-mode-resources/hello_world_1.c1
-rw-r--r--test/lisp/vc/diff-mode-tests.el341
-rw-r--r--test/lisp/vc/ediff-diff-tests.el2
-rw-r--r--test/lisp/vc/ediff-ptch-tests.el72
-rw-r--r--test/lisp/vc/log-edit-tests.el137
-rw-r--r--test/lisp/vc/smerge-mode-tests.el6
-rw-r--r--test/lisp/vc/vc-bzr-tests.el192
-rw-r--r--test/lisp/vc/vc-git-tests.el67
-rw-r--r--test/lisp/vc/vc-hg-tests.el4
-rw-r--r--test/lisp/vc/vc-tests.el840
-rw-r--r--test/lisp/version-tests.el31
-rw-r--r--test/lisp/wdired-tests.el193
-rw-r--r--test/lisp/whitespace-tests.el239
-rw-r--r--test/lisp/wid-edit-tests.el336
-rw-r--r--test/lisp/x-dnd-tests.el206
-rw-r--r--test/lisp/xdg-resources/l10n.desktop (renamed from test/data/xdg/l10n.desktop)0
-rw-r--r--test/lisp/xdg-resources/malformed.desktop (renamed from test/data/xdg/malformed.desktop)0
-rw-r--r--test/lisp/xdg-resources/mimeapps.list (renamed from test/data/xdg/mimeapps.list)0
-rw-r--r--test/lisp/xdg-resources/mimeinfo.cache (renamed from test/data/xdg/mimeinfo.cache)0
-rw-r--r--test/lisp/xdg-resources/test.desktop (renamed from test/data/xdg/test.desktop)0
-rw-r--r--test/lisp/xdg-resources/wrong.desktop (renamed from test/data/xdg/wrong.desktop)0
-rw-r--r--test/lisp/xdg-tests.el34
-rw-r--r--test/lisp/xml-tests.el45
-rw-r--r--test/lisp/xt-mouse-tests.el60
-rw-r--r--test/lisp/yank-media-tests.el38
-rw-r--r--test/manual/BidiCharacterTest.txt38
-rw-r--r--test/manual/biditest.el18
-rw-r--r--test/manual/cedet/cedet-utests.el239
-rw-r--r--test/manual/cedet/ede-tests.el20
-rw-r--r--test/manual/cedet/semantic-tests.el176
-rw-r--r--test/manual/cedet/semantic-utest-c.el72
-rw-r--r--test/manual/cedet/tests/test.c4
-rw-r--r--test/manual/cedet/tests/test.el46
-rw-r--r--test/manual/cedet/tests/test.make4
-rw-r--r--test/manual/cedet/tests/testnsp.cpp29
-rw-r--r--test/manual/cedet/tests/testpolymorph.cpp4
-rw-r--r--test/manual/cedet/tests/testspp.c4
-rw-r--r--test/manual/cedet/tests/testsppcomplete.c30
-rw-r--r--test/manual/cedet/tests/testsppreplace.c4
-rw-r--r--test/manual/cedet/tests/testsppreplaced.c4
-rw-r--r--test/manual/etags/CTAGS.good101
-rw-r--r--test/manual/etags/ETAGS.good_15218
-rw-r--r--test/manual/etags/ETAGS.good_26255
-rw-r--r--test/manual/etags/ETAGS.good_35840
-rw-r--r--test/manual/etags/ETAGS.good_45544
-rw-r--r--test/manual/etags/ETAGS.good_57203
-rw-r--r--test/manual/etags/ETAGS.good_67203
-rw-r--r--test/manual/etags/Makefile4
-rw-r--r--test/manual/etags/README60
-rw-r--r--test/manual/etags/c-src/abbrev.c16
-rw-r--r--test/manual/etags/c-src/emacs/src/gmalloc.c2
-rw-r--r--test/manual/etags/c-src/emacs/src/keyboard.c6
-rw-r--r--test/manual/etags/c-src/emacs/src/lisp.h4
-rw-r--r--test/manual/etags/c-src/emacs/src/regex.h2
-rw-r--r--test/manual/etags/c-src/etags.c2
-rw-r--r--test/manual/etags/c-src/exit.c2
-rw-r--r--test/manual/etags/c-src/exit.strange_suffix2
-rw-r--r--test/manual/etags/c-src/getopt.h2
-rw-r--r--test/manual/etags/c-src/sysdep.h2
-rw-r--r--test/manual/etags/cp-src/clheir.hpp2
-rw-r--r--test/manual/etags/cp-src/functions.cpp8
-rw-r--r--test/manual/etags/el-src/TAGTEST.EL2
-rw-r--r--test/manual/etags/el-src/emacs/lisp/progmodes/etags.el6
-rw-r--r--test/manual/etags/html-src/software.html4
-rw-r--r--test/manual/etags/merc-src/accumulator.m1962
-rw-r--r--test/manual/etags/perl-src/htlmify-cystic2
-rw-r--r--test/manual/etags/prol-src/natded.prolog2
-rw-r--r--test/manual/etags/prol-src/ordsets.prolog4
-rw-r--r--test/manual/etags/rs-src/test.rs14
-rw-r--r--test/manual/etags/tex-src/gzip.texi2
-rw-r--r--test/manual/etags/tex-src/texinfo.tex6
-rw-r--r--test/manual/etags/y-src/cccp.c2
-rw-r--r--test/manual/etags/y-src/parse.c4
-rw-r--r--test/manual/etags/y-src/parse.y4
-rw-r--r--test/manual/image-circular-tests.el68
-rw-r--r--test/manual/image-size-tests.el15
-rw-r--r--test/manual/image-tests.el288
-rw-r--r--test/manual/image-transforms-tests.el178
-rw-r--r--test/manual/indent/js-jsx.js85
-rw-r--r--test/manual/indent/latex-mode.tex4
-rw-r--r--test/manual/indent/less-css-mode.less10
-rw-r--r--test/manual/indent/nxml.xml10
-rw-r--r--test/manual/indent/octave.m4
-rw-r--r--test/manual/indent/pascal.pas2
-rwxr-xr-xtest/manual/indent/perl.perl32
-rw-r--r--test/manual/indent/ps-mode.ps14
-rw-r--r--test/manual/indent/scheme.scm32
-rw-r--r--test/manual/indent/scss-mode.scss10
-rwxr-xr-xtest/manual/indent/shell.sh7
-rw-r--r--test/manual/indent/tcl.tcl26
-rw-r--r--test/manual/process-callout-tests.el64
-rw-r--r--test/manual/redisplay-testsuite.el6
-rw-r--r--test/manual/scroll-tests.el10
-rw-r--r--test/misc/test-custom-deps.el42
-rw-r--r--test/misc/test-custom-libs.el48
-rw-r--r--test/misc/test-custom-noloads.el45
-rw-r--r--test/misc/test-custom-opts.el39
-rw-r--r--test/src/alloc-tests.el13
-rw-r--r--test/src/buffer-tests.el823
-rw-r--r--test/src/callint-tests.el68
-rw-r--r--test/src/callproc-tests.el42
-rw-r--r--test/src/casefiddle-tests.el46
-rw-r--r--test/src/character-tests.el47
-rw-r--r--test/src/charset-tests.el16
-rw-r--r--test/src/chartab-tests.el32
-rw-r--r--test/src/cmds-tests.el20
-rw-r--r--test/src/coding-tests.el97
-rw-r--r--test/src/comp-resources/comp-test-45603.el29
-rw-r--r--test/src/comp-resources/comp-test-funcs-dyn.el50
-rw-r--r--test/src/comp-resources/comp-test-funcs.el713
-rw-r--r--test/src/comp-resources/comp-test-pure.el40
-rw-r--r--test/src/comp-tests.el1480
-rw-r--r--test/src/data-tests.el344
-rw-r--r--test/src/decompress-tests.el28
-rw-r--r--test/src/doc-tests.el89
-rw-r--r--test/src/editfns-tests.el319
-rw-r--r--test/src/emacs-module-resources/mod-test.c868
-rw-r--r--test/src/emacs-module-tests.el425
-rw-r--r--test/src/emacs-tests.el249
-rw-r--r--test/src/eval-tests.el206
-rw-r--r--test/src/fileio-tests.el127
-rw-r--r--test/src/filelock-tests.el217
-rw-r--r--test/src/floatfns-tests.el168
-rw-r--r--test/src/fns-tests.el1059
-rw-r--r--test/src/font-tests.el34
-rw-r--r--test/src/image-tests.el69
-rw-r--r--test/src/indent-tests.el61
-rw-r--r--test/src/inotify-tests.el39
-rw-r--r--test/src/json-tests.el343
-rw-r--r--test/src/keyboard-tests.el74
-rw-r--r--test/src/keymap-tests.el403
-rw-r--r--test/src/lcms-tests.el13
-rw-r--r--test/src/lread-resources/lazydoc.elbin0 -> 171 bytes
-rw-r--r--test/src/lread-resources/somelib.el (renamed from test/data/somelib.el)0
-rw-r--r--test/src/lread-resources/somelib2.el (renamed from test/data/somelib2.el)0
-rw-r--r--test/src/lread-tests.el242
-rw-r--r--test/src/marker-tests.el4
-rw-r--r--test/src/minibuf-tests.el28
-rw-r--r--test/src/print-tests.el498
-rw-r--r--test/src/process-tests.el991
-rw-r--r--test/src/regex-emacs-tests.el (renamed from test/src/regex-tests.el)256
-rw-r--r--test/src/regex-resources/BOOST.tests4
-rw-r--r--test/src/search-tests.el42
-rw-r--r--test/src/sqlite-tests.el244
-rw-r--r--test/src/syntax-resources/syntax-comments.txt94
-rw-r--r--test/src/syntax-tests.el441
-rw-r--r--test/src/textprop-tests.el6
-rw-r--r--test/src/thread-tests.el218
-rw-r--r--test/src/timefns-tests.el264
-rw-r--r--test/src/undo-tests.el55
-rw-r--r--test/src/xdisp-tests.el182
-rw-r--r--test/src/xfaces-tests.el57
-rw-r--r--test/src/xml-tests.el43
1056 files changed, 125974 insertions, 29238 deletions
diff --git a/test/ChangeLog.1 b/test/ChangeLog.1
index 7b228abd1d9..328609038a7 100644
--- a/test/ChangeLog.1
+++ b/test/ChangeLog.1
@@ -65,7 +65,7 @@
2015-03-10 Paul Eggert <eggert@cs.ucla.edu>
- Prefer "initialize" to "initialise"
+ Prefer "initialize"
* indent/js-indent-init-t.js: Rename from
indent/js-indent-first-initialiser-t.js.
* indent/js-indent-init-dynamic.js: Rename from
@@ -1754,7 +1754,7 @@
* indent/prolog.prolog: Test alignment of ->; with operator at bol.
- * indent/css-mode.css (.x2): Test alignement inside braces.
+ * indent/css-mode.css (.x2): Test alignment inside braces.
2013-10-26 Dmitry Gutov <dgutov@yandex.ru>
@@ -2952,7 +2952,7 @@
;; coding: utf-8
;; End:
- Copyright (C) 2008-2017 Free Software Foundation, Inc.
+ Copyright (C) 2008-2022 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/test/Makefile.in b/test/Makefile.in
index 17ab36f5af5..1fa9d5f7d9d 100644
--- a/test/Makefile.in
+++ b/test/Makefile.in
@@ -1,6 +1,6 @@
### @configure_input@
-# Copyright (C) 2010-2017 Free Software Foundation, Inc.
+# Copyright (C) 2010-2022 Free Software Foundation, Inc.
# This file is part of GNU Emacs.
@@ -31,6 +31,8 @@
SHELL = @SHELL@
srcdir = @srcdir@
+abs_top_srcdir = @abs_top_srcdir@
+top_builddir = @top_builddir@
VPATH = $(srcdir)
FIND_DELETE = @FIND_DELETE@
@@ -45,66 +47,57 @@ SO = @MODULES_SUFFIX@
SEPCHAR = @SEPCHAR@
+HAVE_NATIVE_COMP = @HAVE_NATIVE_COMP@
-# 'make' verbosity.
-AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
-
-AM_V_CCLD = $(am__v_CCLD_@AM_V@)
-am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
-am__v_CCLD_0 = @echo " CCLD " $@;
-am__v_CCLD_1 =
-
-AM_V_ELC = $(am__v_ELC_@AM_V@)
-am__v_ELC_ = $(am__v_ELC_@AM_DEFAULT_V@)
-am__v_ELC_0 = @echo " ELC " $@;
-am__v_ELC_1 =
-
-AM_V_GEN = $(am__v_GEN_@AM_V@)
-am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
-am__v_GEN_0 = @echo " GEN " $@;
-am__v_GEN_1 =
-
-AM_V_at = $(am__v_at_@AM_V@)
-am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
-am__v_at_0 = @
-am__v_at_1 =
-
+-include ${top_builddir}/src/verbose.mk
# We never change directory before running Emacs, so a relative file
# name is fine, and makes life easier. If we need to change
# directory, we can use emacs --chdir.
EMACS = ../src/emacs
-EMACS_EXTRAOPT=
+EMACS_EXTRAOPT =
# Command line flags for Emacs.
# Apparently MSYS bash would convert "-L :" to "-L ;" anyway,
# but we might as well be explicit.
-EMACSOPT = -batch --no-site-file --no-site-lisp -L "$(SEPCHAR)$(srcdir)" $(EMACS_EXTRAOPT)
+EMACSOPT = --no-init-file --no-site-file --no-site-lisp -L "$(SEPCHAR)$(srcdir)" $(EMACS_EXTRAOPT)
# Prevent any settings in the user environment causing problems.
-unexport EMACSDATA EMACSDOC EMACSPATH GREP_OPTIONS
+unexport EMACSDATA EMACSDOC EMACSLOADPATH EMACSPATH GREP_OPTIONS XDG_CONFIG_HOME
-## To run tests under a debugger, set this to eg: "gdb --args".
+# To run tests under a debugger, set this to eg: "gdb --args".
GDB =
-# The locale to run tests under. Tests should work if this is set to
-# any supported locale. Use the C locale by default, as it should be
-# supported everywhere.
-TEST_LOCALE = C
+# Whether a timeout shall be given, writing possibly a core dump.
+ifneq (${EMACS_TEST_TIMEOUT},)
+TEST_TIMEOUT = timeout -s ABRT ${EMACS_TEST_TIMEOUT}
+endif
+
+# Set this to 'yes' to run the tests in an interactive instance.
+TEST_INTERACTIVE ?= no
+
+ifeq ($(TEST_INTERACTIVE),yes)
+TEST_RUN_ERT = --eval '(ert (quote ${SELECTOR_ACTUAL}))'
+else
+TEST_RUN_ERT = --batch --eval '(ert-run-tests-batch-and-exit (quote ${SELECTOR_ACTUAL}))' ${WRITE_LOG}
+endif
# Whether to run tests from .el files in preference to .elc, we do
# this by default since it gives nicer stacktraces.
-TEST_LOAD_EL ?= yes
+# If you just want a pass/fail, setting this to no is much faster.
+export TEST_LOAD_EL ?= \
+ $(if $(findstring $(MAKECMDGOALS), all check check-maybe),no,yes)
+
+# Additional settings for ert.
+ert_opts =
# Maximum length of lines in ert backtraces; nil for no limit.
# (if empty, use the default ert-batch-backtrace-right-margin).
TEST_BACKTRACE_LINE_LENGTH =
-ifeq (${TEST_BACKTRACE_LINE_LENGTH},)
-ert_opts =
-else
-ert_opts = --eval '(setq ert-batch-backtrace-right-margin ${TEST_BACKTRACE_LINE_LENGTH})'
+ifneq (${TEST_BACKTRACE_LINE_LENGTH},)
+ert_opts += --eval '(setq ert-batch-backtrace-right-margin ${TEST_BACKTRACE_LINE_LENGTH})'
endif
ifeq (@HAVE_MODULES@, yes)
@@ -114,19 +107,32 @@ MODULES_EMACSOPT :=
endif
# The actual Emacs command run in the targets below.
-# Prevent any setting of EMACSLOADPATH in user environment causing problems.
-emacs = EMACSLOADPATH= LC_ALL=$(TEST_LOCALE) \
- EMACS_TEST_DIRECTORY=$(abspath $(srcdir)) \
- $(GDB) "$(EMACS)" $(MODULES_EMACSOPT) $(EMACSOPT)
+# Prevent locales influencing the text of the errors we expect to receive.
+emacs = LANG=C EMACS_TEST_DIRECTORY=$(abspath $(srcdir)) \
+ $(GDB) $(TEST_TIMEOUT) "$(EMACS)" $(MODULES_EMACSOPT) $(EMACSOPT)
-test_module_dir := $(srcdir)/data/emacs-module
+# Set HOME to a nonexistent directory to prevent tests from accessing
+# it accidentally (e.g., popping up a gnupg dialog if ~/.authinfo.gpg
+# exists, or writing to ~/.bzr.log when running bzr commands).
+# NOTE if the '/nonexistent' name is changed `normal-top-level' in
+# startup.el must be updated too.
+TEST_HOME = /nonexistent
+
+test_module_dir := src/emacs-module-resources
.PHONY: all check
all: check
-SELECTOR_DEFAULT = (quote (not (tag :expensive-test)))
-SELECTOR_EXPENSIVE = nil
+ifeq ($(HAVE_NATIVE_COMP),yes)
+SELECTOR_DEFAULT = (not (or (tag :expensive-test) (tag :unstable)))
+SELECTOR_EXPENSIVE = (not (tag :unstable))
+SELECTOR_ALL = t
+else
+SELECTOR_DEFAULT = (not (or (tag :expensive-test) (tag :unstable) (tag :nativecomp)))
+SELECTOR_EXPENSIVE = (not (or (tag :unstable) (tag :nativecomp)))
+SELECTOR_ALL = (not (tag :nativecomp))
+endif
ifdef SELECTOR
SELECTOR_ACTUAL=$(SELECTOR)
else ifndef MAKECMDGOALS
@@ -143,11 +149,19 @@ endif
## Byte-compile all test files to test for errors.
%.elc: %.el
- $(AM_V_ELC)$(emacs) -f batch-byte-compile $<
+ $(AM_V_ELC)$(emacs) --batch -f batch-byte-compile $<
+ifdef EMACS_HYDRA_CI
+WRITE_LOG = 2>&1 | tee $@
+else
## Save logs, and show logs for failed tests.
-WRITE_LOG = $(if $(and ${EMACS_HYDRA_CI}, $(findstring tramp, $@)), |& tee $@, > $@ 2>&1) \
- || { STAT=$$?; cat $@; exit $$STAT; }
+WRITE_LOG = > $@ 2>&1 || { STAT=$$?; cat $@; exit $$STAT; }
+endif
+## On Emba, always show logs for certain problematic tests.
+ifdef EMACS_EMBA_CI
+lisp/filenotify-tests.log lisp/net/tramp-tests.log src/emacs-module-tests.log \
+: WRITE_LOG = 2>&1 | tee $@
+endif
ifeq ($(TEST_LOAD_EL), yes)
testloadfile = $*.el
@@ -156,10 +170,10 @@ testloadfile = $*
endif
%.log: %.elc
- $(AM_V_at)${MKDIR_P} $(dir $@)
- $(AM_V_GEN)HOME=/nonexistent $(emacs) \
+ $(AM_V_GEN)${MKDIR_P} $(dir $@)
+ $(AM_V_at)HOME=$(TEST_HOME) $(emacs) \
-l ert ${ert_opts} -l $(testloadfile) \
- --eval "(ert-run-tests-batch-and-exit ${SELECTOR_ACTUAL})" ${WRITE_LOG}
+ $(TEST_RUN_ERT)
ifeq (@HAVE_MODULES@, yes)
maybe_exclude_module_tests :=
@@ -167,11 +181,26 @@ else
maybe_exclude_module_tests := -name emacs-module-tests.el -prune -o
endif
-ELFILES := $(sort $(shell find ${srcdir} -path "${srcdir}/manual" -prune -o \
- -path "${srcdir}/data" -prune -o \
+## Optional list of .el files to exclude from testing.
+## Intended for use in automated testing where one or more files
+## has some problem and needs to be excluded.
+## To avoid writing full name, can use eg %foo-tests.el.
+EXCLUDE_TESTS =
+
+## To speed up parallel builds, put these slow test files (which can
+## take longer than all the rest combined) at the start of the list.
+SLOW_TESTS = ${srcdir}/lisp/net/tramp-tests.el
+
+ELFILES := $(sort $(shell find ${srcdir} -name manual -prune -o \
+ -name data -prune -o \
-name "*resources" -prune -o \
${maybe_exclude_module_tests} \
-name "*.el" ! -name ".*" -print))
+
+$(foreach slow,${SLOW_TESTS},$(eval ELFILES:= ${slow} $(filter-out ${slow},${ELFILES})))
+
+$(foreach exclude,${EXCLUDE_TESTS},$(eval ELFILES:= $(filter-out ${exclude},${ELFILES})))
+
## .log files may be in a different directory for out of source builds
LOGFILES := $(patsubst %.el,%.log, \
$(patsubst $(srcdir)/%,%,$(ELFILES)))
@@ -195,6 +224,7 @@ define test_template
ifeq (,$(patsubst %-tests,,$(1))$(findstring -tests/,$(1)))
$(1).log: $(patsubst %-tests,$(srcdir)/../%,$(1))$(if \
$(patsubst src/%,,$(patsubst lib-src/%,,$(1))),.el,.c)
+ $(notdir $(1).log): $(1).log
endif
## Short aliases that always re-run the tests, with no logging.
@@ -202,12 +232,28 @@ define test_template
.PHONY: $(1) $(notdir $(1))
$(1):
@test ! -f $(1).log || mv $(1).log $(1).log~
- @$(MAKE) $(1).log WRITE_LOG=
+ +@$(MAKE) $(1).log WRITE_LOG=
$(notdir $(1)): $(1)
endef
$(foreach test,${TESTS},$(eval $(call test_template,${test})))
+## Get the tests for only a specific directory.
+SUBDIRS = $(sort $(shell cd ${srcdir} && find lib-src lisp misc src -type d \
+ \( -name '*resources*' -prune \
+ -o ! -name '*auto-save-list' -print \)))
+SUBDIR_TARGETS =
+
+define subdir_template
+ SUBDIR_TARGETS += check-$(subst /,-,$(1))
+ .PHONY: check-$(subst /,-,$(1))
+ check-$(subst /,-,$(1)):
+ @${MAKE} check LOGFILES="$(patsubst %.el,%.log, \
+ $(patsubst $(srcdir)/%,%,$(wildcard ${srcdir}/$(1)/*.el)))"
+endef
+
+$(foreach subdir, $(SUBDIRS), $(eval $(call subdir_template,$(subdir))))
+
ifeq (@HAVE_MODULES@, yes)
# -fPIC is a no-op on Windows, but causes a compiler warning
ifeq ($(SO),.dll)
@@ -216,16 +262,35 @@ else
FPIC_CFLAGS = -fPIC
endif
-MODULE_CFLAGS = -I$(srcdir)/../src $(FPIC_CFLAGS) $(PROFILING_CFLAGS) \
+GMP_H = @GMP_H@
+LIBGMP = @LIBGMP@
+LIB_CLOCK_GETTIME = @LIB_CLOCK_GETTIME@
+LIB_NANOSLEEP = @LIB_NANOSLEEP@
+
+MODULE_CFLAGS = $(and $(GMP_H),-I.) -I../src -I$(srcdir)/../src \
+ $(FPIC_CFLAGS) $(PROFILING_CFLAGS) \
$(WARN_CFLAGS) $(WERROR_CFLAGS) $(CFLAGS)
+gmp.h:
+ echo '#include "$(srcdir)/../lib/mini-gmp.h"' >$@
+
test_module = $(test_module_dir)/mod-test${SO}
-src/emacs-module-tests.log: $(test_module)
-$(test_module): $(test_module:${SO}=.c) $(srcdir)/../src/emacs-module.h
- $(AM_V_CCLD)$(CC) -shared $(CPPFLAGS) $(MODULE_CFLAGS) $(LDFLAGS) \
- -o $@ $<
+src/emacs-module-tests.log src/emacs-module-tests.elc: $(test_module)
+
+# In the compilation command, we can't use any object or archive file
+# as source because those are not compiled with -fPIC. Therefore we
+# use only source files.
+$(test_module): $(test_module:${SO}=.c) ../src/emacs-module.h \
+ ../src/config.h $(and $(GMP_H),gmp.h)
+ $(AM_V_CCLD)${MKDIR_P} $(dir $@)
+ $(AM_V_at)$(CC) -shared $(CPPFLAGS) $(MODULE_CFLAGS) $(LDFLAGS) \
+ -o $@ $< $(LIBGMP) \
+ $(and $(GMP_H),$(srcdir)/../lib/mini-gmp.c) \
+ $(LIB_CLOCK_GETTIME) $(LIB_NANOSLEEP)
endif
+src/emacs-tests.log: ../lib-src/seccomp-filter.c
+
## Check that there is no 'automated' subdirectory, which would
## indicate an incomplete merge from an older version of Emacs where
## the tests were arranged differently.
@@ -242,6 +307,11 @@ check: mostlyclean check-no-automated-subdir
check-expensive: mostlyclean check-no-automated-subdir
@${MAKE} check-doit SELECTOR="${SELECTOR_EXPENSIVE}"
+## Run all tests, regardless of tag.
+.PHONY: check-all
+check-all: mostlyclean check-no-automated-subdir
+ @${MAKE} check-doit SELECTOR="${SELECTOR_ALL}"
+
## Re-run all tests which are outdated. A test is outdated if its
## logfile is out-of-date with either the test file, or the source
## files that the tests depend on. See test_template.
@@ -254,19 +324,37 @@ check-maybe: check-no-automated-subdir
## We can't put LOGFILES as prerequisites, because that would stop the
## summarizing step from running when there is an error.
check-doit:
- -@${MAKE} -k ${LOGFILES}
- @$(emacs) -l ert -f ert-summarize-tests-batch-and-exit ${LOGFILES}
+ifeq ($(TEST_INTERACTIVE), yes)
+ HOME=$(TEST_HOME) $(emacs) \
+ -l ert ${ert_opts} \
+ $(patsubst %,-l %,$(if $(findstring $(TEST_LOAD_EL),yes),$ELFILES,$(ELFILES:.el=))) \
+ $(TEST_RUN_ERT)
+else
+ -@${MAKE} -k ${LOGFILES}
+ @$(emacs) --batch -l ert --eval \
+ "(ert-summarize-tests-batch-and-exit ${SUMMARIZE_TESTS})" ${LOGFILES}
+endif
.PHONY: mostlyclean clean bootstrap-clean distclean maintainer-clean
mostlyclean:
-@for f in ${LOGFILES}; do test ! -f $$f || mv $$f $$f~; done
- rm -f *.tmp
+ rm -f ./*.tmp
+
+# If 'find' supports -delete, it also supports -path. Otherwise, use
+# -prune and $(FIND_DELETE) instead. -prune is incompatible with -delete.
+ifeq ($(FIND_DELETE),-delete)
+CLEAN_XML_FILES = '(' -name '*.xml' -a ! -path '*resources*' ')' -delete
+else
+CLEAN_XML_FILES = -name '*resources*' -prune -o -name '*.xml' $(FIND_DELETE)
+endif
clean:
find . '(' -name '*.log' -o -name '*.log~' ')' $(FIND_DELETE)
+ find . $(CLEAN_XML_FILES)
+ rm -f ${srcdir}/lisp/gnus/mml-sec-resources/random_seed
rm -f $(test_module_dir)/*.o $(test_module_dir)/*.so \
- $(test_module_dir)/*.dll
+ $(test_module_dir)/*.dll gmp.h
bootstrap-clean: clean
find $(srcdir) -name '*.elc' $(FIND_DELETE)
@@ -275,3 +363,20 @@ distclean: clean
rm -f Makefile
maintainer-clean: distclean bootstrap-clean
+
+.PHONY: check-declare
+
+check-declare:
+ $(emacs) --batch -l check-declare \
+ --eval '(check-declare-directory "$(srcdir)")'
+
+.PHONY: subdirs subdir-targets generate-test-jobs
+
+subdirs:
+ @: $(info $(SUBDIRS))
+
+subdir-targets:
+ @: $(info $(SUBDIR_TARGETS))
+
+generate-test-jobs:
+ @$(MAKE) -C infra generate-test-jobs SUBDIRS="$(SUBDIRS)"
diff --git a/test/README b/test/README
index aced1a4414e..17783a4bacf 100644
--- a/test/README
+++ b/test/README
@@ -1,4 +1,4 @@
-Copyright (C) 2008-2017 Free Software Foundation, Inc.
+Copyright (C) 2008-2022 Free Software Foundation, Inc.
See the end of the file for license conditions.
This directory contains files intended to test various aspects of
@@ -7,16 +7,37 @@ Emacs's functionality. Please help add tests!
See the file file-organization.org for the details of the directory
structure and file-naming conventions.
+For tests in the manual/ subdirectory, look there for separate README
+files, or look for instructions in the test files themselves.
+
Emacs uses ERT, Emacs Lisp Regression Testing, for testing. See (info
"(ert)") or https://www.gnu.org/software/emacs/manual/html_node/ert/
for more information on writing and running tests.
-The Makefile in this directory supports the following targets:
+Tests could be tagged by the developer. In this test directory, the
+following tags are recognized:
+
+* :expensive-test
+ The test needs a serious amount of time to run. It is not intended
+ to run on a regular basis by users. Instead, it runs on demand
+ only, or during regression tests.
+
+* :nativecomp
+ The test runs only if Emacs is configured with Lisp native compiler
+ support.
+
+* :unstable
+ The test is under development. It shall run on demand only.
+
+The Makefile sets the environment variable $EMACS_TEST_DIRECTORY,
+which points to this directory. This environment variable does not
+exist when the tests are run outside make. The Makefile supports the
+following targets:
* make check
- Run all tests as defined in the directory. Expensive tests are
- suppressed. The result of the tests for <filename>.el is stored in
- <filename>.log.
+ Run all tests as defined in the directory. Expensive and unstable
+ tests are suppressed. The result of the tests for <filename>.el is
+ stored in <filename>.log.
* make check-maybe
Like "make check", but run only the tests for files which have
@@ -25,11 +46,22 @@ The Makefile in this directory supports the following targets:
* make check-expensive
Like "make check", but run also the tests marked as expensive.
-* make <filename> or make <filename>.log
+* make check-all
+ Like "make check", but run all tests.
+
+* make check-<dirname>
+ Like "make check", but run only the tests in test/<dirname>/*.el.
+ <dirname> is a relative directory path, which has replaced "/" by "-",
+ like in "check-src" or "check-lisp-net".
+
+* make <filename> -or- make <filename>.log
Run all tests declared in <filename>.el. This includes expensive
tests. In the former case the output is shown on the terminal, in
the latter case the output is written to <filename>.log.
+<filename> could be either a relative file name like
+"lisp/files-tests", or a package name like "files-tests".
+
ERT offers selectors, which make it possible to filter out which test
cases shall run. The make variable $(SELECTOR) gives you a simple
mean to use your own selectors. The ERT manual describes how
@@ -38,14 +70,82 @@ https://www.gnu.org/software/emacs/manual/html_node/ert/Test-Selectors.html
You could use predefined selectors of the Makefile. "make <filename>
SELECTOR='$(SELECTOR_DEFAULT)'" runs all tests for <filename>.el
-except the tests tagged as expensive.
+except the tests tagged as expensive or unstable. Other predefined
+selectors are $(SELECTOR_EXPENSIVE) (run all tests except unstable
+ones) and $(SELECTOR_ALL) (run all tests).
If your test file contains the tests "test-foo", "test2-foo" and
"test-foo-remote", and you want to run only the former two tests, you
-could use a selector regexp: "make <filename> SELECTOR='\"foo$$\"'".
+could use a selector regexp (note that the "$" needs to be doubled to
+protect against "make" variable expansion):
+
+ make <filename> SELECTOR='"foo$$"'
+
+In case you want to use the symbol name of a test as selector, you can
+use it directly:
+
+ make <filename> SELECTOR='test-foo-remote'
+
+Note that although the test files are always compiled (unless they set
+no-byte-compile), the source files will be run when expensive or
+unstable tests are involved, to give nicer backtraces. To run the
+compiled version of a test use
+
+ make TEST_LOAD_EL=no ...
+
+Some tests might take long time to run. In order to summarize the
+<nn> tests with the longest duration, call
+
+ make SUMMARIZE_TESTS=<nn> ...
+
+The backtrace of failing tests are truncated to the default value of
+'ert-batch-backtrace-right-margin'. To see more of the backtrace, use
+
+ make TEST_BACKTRACE_LINE_LENGTH=<nn> ...
+
+The tests are run in batch mode by default; sometimes it's useful to
+get precisely the same environment but run in interactive mode for
+debugging. To do that, use
+
+ make TEST_INTERACTIVE=yes ...
+
+By default, ERT test failure summaries are quite brief in batch
+mode--only the names of the failed tests are listed. If the
+$EMACS_TEST_VERBOSE environment variable is set and non-empty, the
+failure summaries will also include the data from the failing test.
+
+If the $EMACS_TEST_JUNIT_REPORT environment variable is set to a file
+name, a JUnit test report is generated under this name.
+
+Some of the tests require a remote temporary directory
+(autorevert-tests.el, dnd-tests.el, filenotify-tests.el,
+shadowfile-tests.el and tramp-tests.el). Per default, a mock-up
+connection method is used (this might not be possible when running on
+MS Windows). If you want to test a real remote connection, set
+$REMOTE_TEMPORARY_FILE_DIRECTORY to a suitable value in order to
+overwrite the default value:
+
+ env REMOTE_TEMPORARY_FILE_DIRECTORY=/ssh:host:/tmp make ...
+
+
+There are also continuous integration tests on
+<https://hydra.nixos.org/jobset/gnu/emacs-trunk> (see
+admin/notes/hydra) and <https://emba.gnu.org/emacs/emacs> (see
+admin/notes/emba). Both environments provide an environment variable,
+which could be used to determine, whether the tests run in one of
+these test environments.
+
+$EMACS_HYDRA_CI indicates the hydra environment, and $EMACS_EMBA_CI
+indicates the emba environment, respectively.
+
+If tests on these premises take too long, and it is needed to create a
+core dump for further analysis, the environment variable
+$EMACS_TEST_TIMEOUT could set a limit (in seconds) when this shall
+happen.
-(Also, see etc/compilation.txt for compilation mode font lock tests.)
+(Also, see etc/compilation.txt for compilation mode font lock tests
+and etc/grep.txt for grep mode font lock tests.)
This file is part of GNU Emacs.
diff --git a/test/data/decompress/tg.tar.gz b/test/data/decompress/tg.tar.gz
new file mode 100644
index 00000000000..3dc8185f56e
--- /dev/null
+++ b/test/data/decompress/tg.tar.gz
Binary files differ
diff --git a/test/data/decompress/zg.zip b/test/data/decompress/zg.zip
new file mode 100644
index 00000000000..c4c998ee63d
--- /dev/null
+++ b/test/data/decompress/zg.zip
Binary files differ
diff --git a/test/data/emacs-module/mod-test.c b/test/data/emacs-module/mod-test.c
deleted file mode 100644
index 4193f21b300..00000000000
--- a/test/data/emacs-module/mod-test.c
+++ /dev/null
@@ -1,331 +0,0 @@
-/* Test GNU Emacs modules.
-
-Copyright 2015-2017 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or (at
-your option) any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
-
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <emacs-module.h>
-
-int plugin_is_GPL_compatible;
-
-/* Always return symbol 't'. */
-static emacs_value
-Fmod_test_return_t (emacs_env *env, ptrdiff_t nargs, emacs_value args[],
- void *data)
-{
- return env->intern (env, "t");
-}
-
-/* Expose simple sum function. */
-static intmax_t
-sum (intmax_t a, intmax_t b)
-{
- return a + b;
-}
-
-static emacs_value
-Fmod_test_sum (emacs_env *env, ptrdiff_t nargs, emacs_value args[], void *data)
-{
- assert (nargs == 2);
-
- intmax_t a = env->extract_integer (env, args[0]);
- intmax_t b = env->extract_integer (env, args[1]);
-
- intmax_t r = sum (a, b);
-
- return env->make_integer (env, r);
-}
-
-
-/* Signal '(error 56). */
-static emacs_value
-Fmod_test_signal (emacs_env *env, ptrdiff_t nargs, emacs_value args[],
- void *data)
-{
- assert (env->non_local_exit_check (env) == emacs_funcall_exit_return);
- env->non_local_exit_signal (env, env->intern (env, "error"),
- env->make_integer (env, 56));
- return env->intern (env, "nil");
-}
-
-
-/* Throw '(tag 65). */
-static emacs_value
-Fmod_test_throw (emacs_env *env, ptrdiff_t nargs, emacs_value args[],
- void *data)
-{
- assert (env->non_local_exit_check (env) == emacs_funcall_exit_return);
- env->non_local_exit_throw (env, env->intern (env, "tag"),
- env->make_integer (env, 65));
- return env->intern (env, "nil");
-}
-
-
-/* Call argument function, catch all non-local exists and return
- either normal result or a list describing the non-local exit. */
-static emacs_value
-Fmod_test_non_local_exit_funcall (emacs_env *env, ptrdiff_t nargs,
- emacs_value args[], void *data)
-{
- assert (nargs == 1);
- emacs_value result = env->funcall (env, args[0], 0, NULL);
- emacs_value non_local_exit_symbol, non_local_exit_data;
- enum emacs_funcall_exit code
- = env->non_local_exit_get (env, &non_local_exit_symbol,
- &non_local_exit_data);
- switch (code)
- {
- case emacs_funcall_exit_return:
- return result;
- case emacs_funcall_exit_signal:
- {
- env->non_local_exit_clear (env);
- emacs_value Flist = env->intern (env, "list");
- emacs_value list_args[] = {env->intern (env, "signal"),
- non_local_exit_symbol, non_local_exit_data};
- return env->funcall (env, Flist, 3, list_args);
- }
- case emacs_funcall_exit_throw:
- {
- env->non_local_exit_clear (env);
- emacs_value Flist = env->intern (env, "list");
- emacs_value list_args[] = {env->intern (env, "throw"),
- non_local_exit_symbol, non_local_exit_data};
- return env->funcall (env, Flist, 3, list_args);
- }
- }
-
- /* Never reached. */
- return env->intern (env, "nil");;
-}
-
-
-/* Return a global reference. */
-static emacs_value
-Fmod_test_globref_make (emacs_env *env, ptrdiff_t nargs, emacs_value args[],
- void *data)
-{
- /* Make a big string and make it global. */
- char str[26 * 100];
- for (int i = 0; i < sizeof str; i++)
- str[i] = 'a' + (i % 26);
-
- /* We don't need to null-terminate str. */
- emacs_value lisp_str = env->make_string (env, str, sizeof str);
- return env->make_global_ref (env, lisp_str);
-}
-
-
-/* Return a copy of the argument string where every 'a' is replaced
- with 'b'. */
-static emacs_value
-Fmod_test_string_a_to_b (emacs_env *env, ptrdiff_t nargs, emacs_value args[],
- void *data)
-{
- emacs_value lisp_str = args[0];
- ptrdiff_t size = 0;
- char * buf = NULL;
-
- env->copy_string_contents (env, lisp_str, buf, &size);
- buf = malloc (size);
- env->copy_string_contents (env, lisp_str, buf, &size);
-
- for (ptrdiff_t i = 0; i + 1 < size; i++)
- if (buf[i] == 'a')
- buf[i] = 'b';
-
- return env->make_string (env, buf, size - 1);
-}
-
-
-/* Embedded pointers in lisp objects. */
-
-/* C struct (pointer to) that will be embedded. */
-struct super_struct
-{
- int amazing_int;
- char large_unused_buffer[512];
-};
-
-/* Return a new user-pointer to a super_struct, with amazing_int set
- to the passed parameter. */
-static emacs_value
-Fmod_test_userptr_make (emacs_env *env, ptrdiff_t nargs, emacs_value args[],
- void *data)
-{
- struct super_struct *p = calloc (1, sizeof *p);
- p->amazing_int = env->extract_integer (env, args[0]);
- return env->make_user_ptr (env, free, p);
-}
-
-/* Return the amazing_int of a passed 'user-pointer to a super_struct'. */
-static emacs_value
-Fmod_test_userptr_get (emacs_env *env, ptrdiff_t nargs, emacs_value args[],
- void *data)
-{
- struct super_struct *p = env->get_user_ptr (env, args[0]);
- return env->make_integer (env, p->amazing_int);
-}
-
-
-/* Fill vector in args[0] with value in args[1]. */
-static emacs_value
-Fmod_test_vector_fill (emacs_env *env, ptrdiff_t nargs, emacs_value args[],
- void *data)
-{
- emacs_value vec = args[0];
- emacs_value val = args[1];
- ptrdiff_t size = env->vec_size (env, vec);
- for (ptrdiff_t i = 0; i < size; i++)
- env->vec_set (env, vec, i, val);
- return env->intern (env, "t");
-}
-
-
-/* Return whether all elements of vector in args[0] are 'eq' to value
- in args[1]. */
-static emacs_value
-Fmod_test_vector_eq (emacs_env *env, ptrdiff_t nargs, emacs_value args[],
- void *data)
-{
- emacs_value vec = args[0];
- emacs_value val = args[1];
- ptrdiff_t size = env->vec_size (env, vec);
- for (ptrdiff_t i = 0; i < size; i++)
- if (!env->eq (env, env->vec_get (env, vec, i), val))
- return env->intern (env, "nil");
- return env->intern (env, "t");
-}
-
-static emacs_value invalid_stored_value;
-
-/* The next two functions perform a possibly-invalid operation: they
- store a value in a static variable and load it. This causes
- undefined behavior if the environment that the value was created
- from is no longer live. The module assertions check for this
- error. */
-
-static emacs_value
-Fmod_test_invalid_store (emacs_env *env, ptrdiff_t nargs, emacs_value *args,
- void *data)
-{
- return invalid_stored_value = env->make_integer (env, 123);
-}
-
-static emacs_value
-Fmod_test_invalid_load (emacs_env *env, ptrdiff_t nargs, emacs_value *args,
- void *data)
-{
- return invalid_stored_value;
-}
-
-/* An invalid finalizer: Finalizers are run during garbage collection,
- where Lisp code can’t be executed. -module-assertions tests for
- this case. */
-
-static emacs_env *current_env;
-
-static void
-invalid_finalizer (void *ptr)
-{
- current_env->intern (current_env, "nil");
-}
-
-static emacs_value
-Fmod_test_invalid_finalizer (emacs_env *env, ptrdiff_t nargs, emacs_value *args,
- void *data)
-{
- current_env = env;
- env->make_user_ptr (env, invalid_finalizer, NULL);
- return env->funcall (env, env->intern (env, "garbage-collect"), 0, NULL);
-}
-
-
-/* Lisp utilities for easier readability (simple wrappers). */
-
-/* Provide FEATURE to Emacs. */
-static void
-provide (emacs_env *env, const char *feature)
-{
- emacs_value Qfeat = env->intern (env, feature);
- emacs_value Qprovide = env->intern (env, "provide");
- emacs_value args[] = { Qfeat };
-
- env->funcall (env, Qprovide, 1, args);
-}
-
-/* Bind NAME to FUN. */
-static void
-bind_function (emacs_env *env, const char *name, emacs_value Sfun)
-{
- emacs_value Qfset = env->intern (env, "fset");
- emacs_value Qsym = env->intern (env, name);
- emacs_value args[] = { Qsym, Sfun };
-
- env->funcall (env, Qfset, 2, args);
-}
-
-/* Module init function. */
-int
-emacs_module_init (struct emacs_runtime *ert)
-{
- if (ert->size < sizeof *ert)
- {
- fprintf (stderr, "Runtime size of runtime structure (%td bytes) "
- "smaller than compile-time size (%zu bytes)",
- ert->size, sizeof *ert);
- return 1;
- }
-
- emacs_env *env = ert->get_environment (ert);
-
- if (env->size < sizeof *env)
- {
- fprintf (stderr, "Runtime size of environment structure (%td bytes) "
- "smaller than compile-time size (%zu bytes)",
- env->size, sizeof *env);
- return 2;
- }
-
-#define DEFUN(lsym, csym, amin, amax, doc, data) \
- bind_function (env, lsym, \
- env->make_function (env, amin, amax, csym, doc, data))
-
- DEFUN ("mod-test-return-t", Fmod_test_return_t, 1, 1, NULL, NULL);
- DEFUN ("mod-test-sum", Fmod_test_sum, 2, 2, "Return A + B\n\n(fn a b)", NULL);
- DEFUN ("mod-test-signal", Fmod_test_signal, 0, 0, NULL, NULL);
- DEFUN ("mod-test-throw", Fmod_test_throw, 0, 0, NULL, NULL);
- DEFUN ("mod-test-non-local-exit-funcall", Fmod_test_non_local_exit_funcall,
- 1, 1, NULL, NULL);
- DEFUN ("mod-test-globref-make", Fmod_test_globref_make, 0, 0, NULL, NULL);
- DEFUN ("mod-test-string-a-to-b", Fmod_test_string_a_to_b, 1, 1, NULL, NULL);
- DEFUN ("mod-test-userptr-make", Fmod_test_userptr_make, 1, 1, NULL, NULL);
- DEFUN ("mod-test-userptr-get", Fmod_test_userptr_get, 1, 1, NULL, NULL);
- DEFUN ("mod-test-vector-fill", Fmod_test_vector_fill, 2, 2, NULL, NULL);
- DEFUN ("mod-test-vector-eq", Fmod_test_vector_eq, 2, 2, NULL, NULL);
- DEFUN ("mod-test-invalid-store", Fmod_test_invalid_store, 0, 0, NULL, NULL);
- DEFUN ("mod-test-invalid-load", Fmod_test_invalid_load, 0, 0, NULL, NULL);
- DEFUN ("mod-test-invalid-finalizer", Fmod_test_invalid_finalizer, 0, 0,
- NULL, NULL);
-
-#undef DEFUN
-
- provide (env, "mod-test");
- return 0;
-}
diff --git a/test/data/image/black-short.jpg b/test/data/image/black-short.jpg
new file mode 100644
index 00000000000..02a5b0b72ef
--- /dev/null
+++ b/test/data/image/black-short.jpg
Binary files differ
diff --git a/test/data/image/black.gif b/test/data/image/black.gif
new file mode 100644
index 00000000000..6ab623e367e
--- /dev/null
+++ b/test/data/image/black.gif
Binary files differ
diff --git a/test/data/image/black.jpg b/test/data/image/black.jpg
new file mode 100644
index 00000000000..be9af2a9a05
--- /dev/null
+++ b/test/data/image/black.jpg
Binary files differ
diff --git a/test/data/image/black.webp b/test/data/image/black.webp
new file mode 100644
index 00000000000..5dbe716415b
--- /dev/null
+++ b/test/data/image/black.webp
Binary files differ
diff --git a/test/data/xref/file1.txt b/test/data/xref/file1.txt
deleted file mode 100644
index 5d7cc544443..00000000000
--- a/test/data/xref/file1.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-foo foo
-bar
diff --git a/test/file-organization.org b/test/file-organization.org
index 4d76c0068e3..d1f92da4324 100644
--- a/test/file-organization.org
+++ b/test/file-organization.org
@@ -1,10 +1,10 @@
-#+TITLE: The Location of Emacs-Lisp Tests
+#+TITLE: The Location of Emacs Lisp Tests
* The Main Emacs Repository
-The Emacs repository contains a very large number of Emacs-Lisp files, many of
+The Emacs repository contains a very large number of Emacs Lisp files, many of
which pre-date both formal package support for Emacs and automated unit
testing.
@@ -17,29 +17,35 @@ Sub-directories are in many cases themed after packages (~gnus~, ~org~,
~calc~), related functionality (~net~, ~emacs-lisp~, ~progmodes~) or status
(~obsolete~).
-C source is stored in the ~src~ directory, which is flat.
+C source is stored in the ~src~ directory, which is flat. Source for
+utility programs is stored in the ~lib-src~ directory.
** Test Files
Automated tests should be stored in the ~test/lisp~ directory for
-tests of functionality implemented in Lisp, and in the ~test/src~
-directory for functionality implemented in C. Tests should reflect
+tests of functionality implemented in Lisp, in the ~test/src~
+directory for functionality implemented in C, and in the
+~test/lib-src~ directory for utility programs. Tests should reflect
the directory structure of the source tree; so tests for files in the
~lisp/emacs-lisp~ source directory should reside in the
~test/lisp/emacs-lisp~ directory.
Tests should normally reside in a file with ~-tests.el~ added to the
base-name of the tested source file; hence ~ert.el~ is tested in
-~ert-tests.el~, and ~pcase.el~ is tested in ~pcase-tests.el~. As n
+~ert-tests.el~, and ~pcase.el~ is tested in ~pcase-tests.el~. As an
exception, tests for a single feature may be placed into multiple
files of any name which are themselves placed in a directory named
after the feature with ~-tests~ appended, such as
~/test/lisp/emacs-lisp/eieio-tests~
-Similarly, features implemented in C should reside in ~/test/src~ and
-be named after the C file with ~-tests.el~ added to the base-name of
-the tested source file. Thus, tests for ~src/fileio.c~ should be in
-~test/src/fileio-tests.el~.
+Similarly, tests of features implemented in C should reside in
+~/test/src~ or in ~test/lib-src~ and be named after the C file with
+~-tests.el~ added to the base-name of the tested source file. Thus,
+tests for ~src/fileio.c~ should be in ~test/src/fileio-tests.el~.
+
+Some tests do not belong to any one particular file. Such tests
+should be put in the ~misc~ directory and be given a descriptive name
+that does /not/ end with ~-tests.el~.
There are also some test materials that cannot be run automatically
(i.e. via ert). These should be placed in ~/test/manual~; they are
@@ -55,5 +61,10 @@ located in the same directory as the feature. Hence, the lisp file
directory called ~test/lisp/progmodes/flymake-resources~.
No guidance is given for the organization of resource files inside the
-~-resource~ directory; files can be organized at the author's
+~-resources~ directory; files can be organized at the author's
discretion.
+
+** Testing Infrastructure Files
+
+Files used to support testing infrastructure such as EMBA should be
+placed in ~infra~.
diff --git a/test/infra/Dockerfile.emba b/test/infra/Dockerfile.emba
new file mode 100644
index 00000000000..d9d963bcfd5
--- /dev/null
+++ b/test/infra/Dockerfile.emba
@@ -0,0 +1,105 @@
+# Copyright (C) 2021-2022 Free Software Foundation, Inc.
+#
+# This file is part of GNU Emacs.
+#
+# GNU Emacs is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# GNU Emacs is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+# GNU Emacs support for the GitLab-specific build of Docker images.
+
+# The presence of this file does not imply any FSF/GNU endorsement of
+# Docker or any other particular tool. Also, it is intended for
+# evaluation purposes, thus possibly temporary.
+
+# Maintainer: Ted Zlatanov <tzz@lifelogs.com>
+# URL: https://emba.gnu.org/emacs/emacs
+
+FROM debian:stretch as emacs-base
+
+RUN apt-get update && \
+ apt-get install -y --no-install-recommends -o=Dpkg::Use-Pty=0 \
+ libc-dev gcc g++ make autoconf automake libncurses-dev gnutls-dev \
+ libdbus-1-dev libacl1-dev acl git texinfo gdb \
+ && rm -rf /var/lib/apt/lists/*
+
+FROM emacs-base as emacs-inotify
+
+RUN apt-get update && \
+ apt-get install -y --no-install-recommends -o=Dpkg::Use-Pty=0 \
+ inotify-tools \
+ && rm -rf /var/lib/apt/lists/*
+
+COPY . /checkout
+WORKDIR /checkout
+RUN ./autogen.sh autoconf
+RUN ./configure
+# 'make -j4 bootstrap' does not work reliably.
+RUN make bootstrap
+
+FROM emacs-base as emacs-filenotify-gio
+
+RUN apt-get update && \
+ apt-get install -y --no-install-recommends -o=Dpkg::Use-Pty=0 \
+ libglib2.0-dev libglib2.0-bin libglib2.0-0 \
+ && rm -rf /var/lib/apt/lists/*
+
+COPY . /checkout
+WORKDIR /checkout
+RUN ./autogen.sh autoconf
+RUN ./configure --with-file-notification=gfile
+RUN make bootstrap
+
+FROM emacs-base as emacs-gnustep
+
+RUN apt-get update && \
+ apt-get install -y --no-install-recommends -o=Dpkg::Use-Pty=0 \
+ gnustep-devel \
+ && rm -rf /var/lib/apt/lists/*
+
+COPY . /checkout
+WORKDIR /checkout
+RUN ./autogen.sh autoconf
+RUN ./configure --with-ns
+RUN make bootstrap
+
+FROM emacs-base as emacs-native-comp
+
+RUN apt-get update && \
+ apt-get install -y --no-install-recommends -o=Dpkg::Use-Pty=0 \
+ libgccjit-6-dev \
+ && rm -rf /var/lib/apt/lists/*
+
+FROM emacs-native-comp as emacs-native-comp-speed0
+
+COPY . /checkout
+WORKDIR /checkout
+RUN ./autogen.sh autoconf
+RUN ./configure --with-native-compilation
+RUN make bootstrap -j2 \
+ NATIVE_FULL_AOT=1 BYTE_COMPILE_EXTRA_FLAGS='--eval "(setq comp-speed 0)"'
+
+FROM emacs-native-comp as emacs-native-comp-speed1
+
+COPY . /checkout
+WORKDIR /checkout
+RUN ./autogen.sh autoconf
+RUN ./configure --with-native-compilation
+RUN make bootstrap -j2 BYTE_COMPILE_EXTRA_FLAGS='--eval "(setq comp-speed 1)"'
+
+FROM emacs-native-comp as emacs-native-comp-speed2
+
+COPY . /checkout
+WORKDIR /checkout
+RUN ./autogen.sh autoconf
+RUN ./configure --with-native-compilation
+RUN make bootstrap -j2
diff --git a/test/infra/Makefile.in b/test/infra/Makefile.in
new file mode 100644
index 00000000000..c251578e6a7
--- /dev/null
+++ b/test/infra/Makefile.in
@@ -0,0 +1,100 @@
+### @configure_input@
+
+# Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+# This file is part of GNU Emacs.
+
+# GNU Emacs is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# GNU Emacs is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+### Commentary:
+
+## Generate the test-jobs.yml file for emba.
+
+### Code:
+
+SHELL = @SHELL@
+
+top_builddir = @top_builddir@
+
+-include ${top_builddir}/src/verbose.mk
+
+## Get the tests for only a specific directory.
+SUBDIRS ?= $(shell make -s -C .. subdirs)
+SUBDIR_TARGETS =
+FILE = test-jobs.yml
+tn = $$$${test_name}
+cps = $$$$CI_PIPELINE_SOURCE
+
+define subdir_template
+ $(eval target = check-$(subst /,-,$(1)))
+ SUBDIR_TARGETS += $(target)
+
+ $(eval
+ ifeq ($(findstring src, $(1)), src)
+ define changes
+ @echo ' - $(1)/*.{h,c}' >>$(FILE)
+ endef
+ else ifeq ($(findstring eieio, $(1)), eieio)
+ define changes
+ @echo ' - lisp/emacs-lisp/eieio*.el' >>$(FILE)
+ endef
+ else ifeq ($(findstring faceup, $(1)), faceup)
+ define changes
+ @echo ' - lisp/emacs-lisp/faceup*.el' >>$(FILE)
+ endef
+ else ifeq ($(findstring so-long, $(1)), so-long)
+ define changes
+ @echo ' - lisp/so-long*.el' >>$(FILE)
+ endef
+ else ifeq ($(findstring misc, $(1)), misc)
+ define changes
+ @echo ' - admin/*.el' >>$(FILE)
+ endef
+ else
+ define changes
+ @echo ' - $(1)/*.el' >>$(FILE)
+ endef
+ endif)
+
+ $(target):
+ @echo >>$(FILE)
+ @echo 'test-$(subst /,-,$(1))-inotify:' >>$(FILE)
+ @echo ' stage: normal' >>$(FILE)
+ @echo ' extends: [.job-template, .test-template]' >>$(FILE)
+ @echo ' needs:' >>$(FILE)
+ @echo ' - job: build-image-inotify' >>$(FILE)
+ @echo ' optional: true' >>$(FILE)
+ @echo ' rules:' >>$(FILE)
+ @echo " - if: '"'${cps} == "schedule"'"'" >>$(FILE)
+ @echo ' when: never' >>$(FILE)
+ @echo ' - changes:' >>$(FILE)
+ $(changes)
+ @echo ' - test/$(1)/*.el' >>$(FILE)
+ @echo ' - test/$(1)/*resources/**' >>$(FILE)
+ @echo ' variables:' >>$(FILE)
+ @echo ' target: emacs-inotify' >>$(FILE)
+ @echo ' make_params: "-k -C test $(target)"' >>$(FILE)
+endef
+
+$(foreach subdir, $(SUBDIRS), $(eval $(call subdir_template,$(subdir))))
+
+all: generate-test-jobs
+
+.PHONY: generate-test-jobs $(FILE) $(SUBDIR_TARGETS)
+
+generate-test-jobs: $(FILE) $(SUBDIR_TARGETS)
+
+$(FILE):
+ $(AM_V_GEN)
+ @echo "# Generated by \"make generate-test-jobs\", don't edit." >$(FILE)
diff --git a/test/infra/gitlab-ci.yml b/test/infra/gitlab-ci.yml
new file mode 100644
index 00000000000..e034430edce
--- /dev/null
+++ b/test/infra/gitlab-ci.yml
@@ -0,0 +1,279 @@
+# Copyright (C) 2017-2022 Free Software Foundation, Inc.
+#
+# This file is part of GNU Emacs.
+#
+# GNU Emacs is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# GNU Emacs is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+# GNU Emacs support for the GitLab protocol for CI.
+
+# The presence of this file does not imply any FSF/GNU endorsement of
+# any particular service that uses that protocol. Also, it is intended for
+# evaluation purposes, thus possibly temporary.
+
+# Maintainer: Ted Zlatanov <tzz@lifelogs.com>
+# URL: https://emba.gnu.org/emacs/emacs
+
+# Never run merge request pipelines, they usually duplicate push pipelines
+# see https://docs.gitlab.com/ee/ci/yaml/README.html#common-if-clauses-for-rules
+
+# Rules: always run tags and branches named master*, emacs*, feature*, fix*
+# Test that it triggers by pushing a tag: `git tag mytag; git push origin mytag`
+# Test that it triggers by pushing to: feature/emba, feature1, master, master-2, fix/emba, emacs-299, fix-2
+# Test that it doesn't trigger by pushing to: scratch-2, scratch/emba, oldbranch, dev
+workflow:
+ rules:
+ - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
+ when: never
+ - if: '$CI_COMMIT_TAG'
+ when: always
+ - if: '$CI_COMMIT_BRANCH !~ /^(master|emacs|feature|fix)/'
+ when: never
+ - when: always
+
+variables:
+ GIT_STRATEGY: fetch
+ EMACS_EMBA_CI: 1
+ EMACS_TEST_JUNIT_REPORT: junit-test-report.xml
+ EMACS_TEST_TIMEOUT: 3600
+ EMACS_TEST_VERBOSE: 1
+ # Use TLS https://docs.gitlab.com/ee/ci/docker/using_docker_build.html#tls-enabled
+ # DOCKER_HOST: tcp://docker:2376
+ # DOCKER_TLS_CERTDIR: "/certs"
+ # Put the configuration for each run in a separate directory to
+ # avoid conflicts.
+ DOCKER_CONFIG: "/.docker-config-${CI_COMMIT_SHA}"
+ DOCKER_BUILDKIT: 1
+ # We don't use ${CI_COMMIT_SHA} to be able to do one bootstrap
+ # across multiple builds.
+ BUILD_TAG: ${CI_COMMIT_REF_SLUG}
+ # Disable if you don't need it, it can be a security risk.
+ # CI_DEBUG_TRACE: "true"
+
+default:
+ image: docker:19.03.12
+ timeout: 3 hours
+ before_script:
+ - docker info
+ - echo "docker registry is ${CI_REGISTRY}"
+ - docker login -u ${CI_REGISTRY_USER} -p ${CI_REGISTRY_PASSWORD} ${CI_REGISTRY}
+
+.job-template:
+ variables:
+ test_name: ${CI_JOB_NAME}-${CI_COMMIT_SHORT_SHA}
+ # These will be cached across builds.
+ cache:
+ key: ${CI_COMMIT_SHA}
+ paths: []
+ policy: pull-push
+ # These will be saved for followup builds.
+ artifacts:
+ expire_in: 24 hrs
+ paths: []
+ # Using the variables for each job.
+ script:
+ - docker pull ${CI_REGISTRY_IMAGE}:${target}-${BUILD_TAG}
+ # TODO: with make -j4 several of the tests were failing, for
+ # example shadowfile-tests, but passed without it.
+ - 'export PWD=$(pwd)'
+ - 'docker run -i -e EMACS_EMBA_CI=${EMACS_EMBA_CI} -e EMACS_TEST_JUNIT_REPORT=${EMACS_TEST_JUNIT_REPORT} -e EMACS_TEST_TIMEOUT=${EMACS_TEST_TIMEOUT} -e EMACS_TEST_VERBOSE=${EMACS_TEST_VERBOSE} --volumes-from $(docker ps -q -f "label=com.gitlab.gitlab-runner.job.id=${CI_JOB_ID}"):ro --name ${test_name} ${CI_REGISTRY_IMAGE}:${target}-${BUILD_TAG} /bin/bash -c "git fetch ${PWD} HEAD && echo checking out these updated files && git diff --name-only FETCH_HEAD && ( git diff --name-only FETCH_HEAD | xargs git checkout -f FETCH_HEAD ) && make -j4 && make ${make_params}"'
+ after_script:
+ # - docker ps -a
+ # - printenv
+ # - test -n "$(docker ps -aq -f name=${test_name})" && ( docker export ${test_name} | tar -tvf - )
+ # Prepare test artifacts.
+ - test -n "$(docker ps -aq -f name=${test_name})" && docker cp ${test_name}:checkout/test ${test_name}
+ - test -n "$(docker ps -aq -f name=${test_name})" && docker rm ${test_name}
+ - find ${test_name} ! \( -name "*.log" -o -name ${EMACS_TEST_JUNIT_REPORT} \) -type f -delete
+ # BusyBox find does not know -empty.
+ - find ${test_name} -type d -depth -exec rmdir {} + 2>/dev/null
+
+.build-template:
+ needs: []
+ rules:
+ - if: '$CI_PIPELINE_SOURCE == "web"'
+ when: always
+ - changes:
+ - "**.in"
+ - GNUmakefile
+ - aclocal.m4
+ - autogen.sh
+ - configure.ac
+ - lib/*.{h,c}
+ - lib/malloc/*.{h,c}
+ - lisp/emacs-lisp/*.el
+ - src/*.{h,c}
+ - test/infra/*
+ - changes:
+ # gfilemonitor, kqueue
+ - src/gfilenotify.c
+ - src/kqueue.c
+ # MS Windows
+ - "**w32*"
+ # GNUstep
+ - lisp/term/ns-win.el
+ - src/ns*.{h,m}
+ - src/macfont.{h,m}
+ when: never
+ script:
+ - docker build --pull --target ${target} -t ${CI_REGISTRY_IMAGE}:${target}-${BUILD_TAG} -f test/infra/Dockerfile.emba .
+ - docker push ${CI_REGISTRY_IMAGE}:${target}-${BUILD_TAG}
+
+.test-template:
+ artifacts:
+ name: ${test_name}
+ public: true
+ expire_in: 1 week
+ when: always
+ paths:
+ - ${test_name}/
+ reports:
+ junit: ${test_name}/${EMACS_TEST_JUNIT_REPORT}
+
+.gnustep-template:
+ rules:
+ - if: '$CI_PIPELINE_SOURCE == "web"'
+ - if: '$CI_PIPELINE_SOURCE == "schedule"'
+ changes:
+ - "**.in"
+ - src/ns*.{h,m}
+ - src/macfont.{h,m}
+ - lisp/term/ns-win.el
+ - nextstep/**
+ - test/infra/*
+
+.filenotify-gio-template:
+ rules:
+ - if: '$CI_PIPELINE_SOURCE == "web"'
+ - if: '$CI_PIPELINE_SOURCE == "schedule"'
+ changes:
+ - "**.in"
+ - lisp/autorevert.el
+ - lisp/filenotify.el
+ - lisp/net/tramp-sh.el
+ - src/gfilenotify.c
+ - test/infra/*
+ - test/lisp/autorevert-tests.el
+ - test/lisp/filenotify-tests.el
+
+.native-comp-template:
+ rules:
+ - if: '$CI_PIPELINE_SOURCE == "web"'
+ - if: '$CI_PIPELINE_SOURCE == "schedule"'
+ changes:
+ - "**.in"
+ - lisp/emacs-lisp/comp.el
+ - lisp/emacs-lisp/comp-cstr.el
+ - src/comp.{h,m}
+ - test/infra/*
+ - test/src/comp-resources/*.el
+ - test/src/comp-tests.el
+ timeout: 8 hours
+
+stages:
+ - build-images
+ - normal
+ - platform-images
+ - platforms
+ - native-comp-images
+ - native-comp
+
+build-image-inotify:
+ stage: build-images
+ extends: [.job-template, .build-template]
+ variables:
+ target: emacs-inotify
+
+include: '/test/infra/test-jobs.yml'
+
+test-all-inotify:
+ # This tests also file monitor libraries inotify and inotifywatch.
+ stage: normal
+ extends: [.job-template, .test-template]
+ needs:
+ - job: build-image-inotify
+ optional: true
+ rules:
+ # Note there's no "changes" section, so this always runs on a schedule.
+ - if: '$CI_PIPELINE_SOURCE == "web"'
+ - if: '$CI_PIPELINE_SOURCE == "schedule"'
+ variables:
+ target: emacs-inotify
+ make_params: check-expensive
+
+build-image-filenotify-gio:
+ stage: platform-images
+ extends: [.job-template, .build-template, .filenotify-gio-template]
+ variables:
+ target: emacs-filenotify-gio
+
+test-filenotify-gio:
+ # This tests file monitor libraries gfilemonitor and gio.
+ stage: platforms
+ extends: [.job-template, .test-template, .filenotify-gio-template]
+ needs:
+ - job: build-image-filenotify-gio
+ optional: true
+ variables:
+ target: emacs-filenotify-gio
+ # This is needed in order to get a JUnit test report.
+ make_params: '-k -C test check-expensive LOGFILES="lisp/autorevert-tests.log lisp/filenotify-tests.log"'
+
+build-image-gnustep:
+ stage: platform-images
+ extends: [.job-template, .build-template, .gnustep-template]
+ variables:
+ target: emacs-gnustep
+
+test-gnustep:
+ # This tests the GNUstep build process.
+ stage: platforms
+ extends: [.job-template, .gnustep-template]
+ needs:
+ - job: build-image-gnustep
+ optional: true
+ variables:
+ target: emacs-gnustep
+ make_params: install
+
+build-native-comp-speed0:
+ stage: native-comp-images
+ extends: [.job-template, .build-template, .native-comp-template]
+ variables:
+ target: emacs-native-comp-speed0
+
+build-native-comp-speed1:
+ stage: native-comp-images
+ extends: [.job-template, .build-template, .native-comp-template]
+ variables:
+ target: emacs-native-comp-speed1
+
+build-native-comp-speed2:
+ stage: native-comp-images
+ extends: [.job-template, .build-template, .native-comp-template]
+ variables:
+ target: emacs-native-comp-speed2
+
+test-native-comp-speed0:
+ stage: native-comp
+ extends: [.job-template, .test-template, .native-comp-template]
+ needs:
+ - job: build-native-comp-speed0
+ optional: true
+ variables:
+ target: emacs-native-comp-speed0
+ make_params: "-k -C test check SELECTOR='(not (tag :unstable))'"
+
+# Local Variables:
+# add-log-current-defun-header-regexp: "^\\([-_.[:alnum:]]+\\)[ \t]*:"
+# End:
diff --git a/test/infra/test-jobs.yml b/test/infra/test-jobs.yml
new file mode 100644
index 00000000000..51707c181b1
--- /dev/null
+++ b/test/infra/test-jobs.yml
@@ -0,0 +1,545 @@
+# Generated by "make generate-test-jobs", don't edit.
+
+test-lib-src-inotify:
+ stage: normal
+ extends: [.job-template, .test-template]
+ needs:
+ - job: build-image-inotify
+ optional: true
+ rules:
+ - if: '$CI_PIPELINE_SOURCE == "schedule"'
+ when: never
+ - changes:
+ - lib-src/*.{h,c}
+ - test/lib-src/*.el
+ - test/lib-src/*resources/**
+ variables:
+ target: emacs-inotify
+ make_params: "-k -C test check-lib-src"
+
+test-lisp-inotify:
+ stage: normal
+ extends: [.job-template, .test-template]
+ needs:
+ - job: build-image-inotify
+ optional: true
+ rules:
+ - if: '$CI_PIPELINE_SOURCE == "schedule"'
+ when: never
+ - changes:
+ - lisp/*.el
+ - test/lisp/*.el
+ - test/lisp/*resources/**
+ variables:
+ target: emacs-inotify
+ make_params: "-k -C test check-lisp"
+
+test-lisp-calc-inotify:
+ stage: normal
+ extends: [.job-template, .test-template]
+ needs:
+ - job: build-image-inotify
+ optional: true
+ rules:
+ - if: '$CI_PIPELINE_SOURCE == "schedule"'
+ when: never
+ - changes:
+ - lisp/calc/*.el
+ - test/lisp/calc/*.el
+ - test/lisp/calc/*resources/**
+ variables:
+ target: emacs-inotify
+ make_params: "-k -C test check-lisp-calc"
+
+test-lisp-calendar-inotify:
+ stage: normal
+ extends: [.job-template, .test-template]
+ needs:
+ - job: build-image-inotify
+ optional: true
+ rules:
+ - if: '$CI_PIPELINE_SOURCE == "schedule"'
+ when: never
+ - changes:
+ - lisp/calendar/*.el
+ - test/lisp/calendar/*.el
+ - test/lisp/calendar/*resources/**
+ variables:
+ target: emacs-inotify
+ make_params: "-k -C test check-lisp-calendar"
+
+test-lisp-cedet-inotify:
+ stage: normal
+ extends: [.job-template, .test-template]
+ needs:
+ - job: build-image-inotify
+ optional: true
+ rules:
+ - if: '$CI_PIPELINE_SOURCE == "schedule"'
+ when: never
+ - changes:
+ - lisp/cedet/*.el
+ - test/lisp/cedet/*.el
+ - test/lisp/cedet/*resources/**
+ variables:
+ target: emacs-inotify
+ make_params: "-k -C test check-lisp-cedet"
+
+test-lisp-cedet-semantic-inotify:
+ stage: normal
+ extends: [.job-template, .test-template]
+ needs:
+ - job: build-image-inotify
+ optional: true
+ rules:
+ - if: '$CI_PIPELINE_SOURCE == "schedule"'
+ when: never
+ - changes:
+ - lisp/cedet/semantic/*.el
+ - test/lisp/cedet/semantic/*.el
+ - test/lisp/cedet/semantic/*resources/**
+ variables:
+ target: emacs-inotify
+ make_params: "-k -C test check-lisp-cedet-semantic"
+
+test-lisp-cedet-semantic-bovine-inotify:
+ stage: normal
+ extends: [.job-template, .test-template]
+ needs:
+ - job: build-image-inotify
+ optional: true
+ rules:
+ - if: '$CI_PIPELINE_SOURCE == "schedule"'
+ when: never
+ - changes:
+ - lisp/cedet/semantic/bovine/*.el
+ - test/lisp/cedet/semantic/bovine/*.el
+ - test/lisp/cedet/semantic/bovine/*resources/**
+ variables:
+ target: emacs-inotify
+ make_params: "-k -C test check-lisp-cedet-semantic-bovine"
+
+test-lisp-cedet-srecode-inotify:
+ stage: normal
+ extends: [.job-template, .test-template]
+ needs:
+ - job: build-image-inotify
+ optional: true
+ rules:
+ - if: '$CI_PIPELINE_SOURCE == "schedule"'
+ when: never
+ - changes:
+ - lisp/cedet/srecode/*.el
+ - test/lisp/cedet/srecode/*.el
+ - test/lisp/cedet/srecode/*resources/**
+ variables:
+ target: emacs-inotify
+ make_params: "-k -C test check-lisp-cedet-srecode"
+
+test-lisp-emacs-lisp-inotify:
+ stage: normal
+ extends: [.job-template, .test-template]
+ needs:
+ - job: build-image-inotify
+ optional: true
+ rules:
+ - if: '$CI_PIPELINE_SOURCE == "schedule"'
+ when: never
+ - changes:
+ - lisp/emacs-lisp/*.el
+ - test/lisp/emacs-lisp/*.el
+ - test/lisp/emacs-lisp/*resources/**
+ variables:
+ target: emacs-inotify
+ make_params: "-k -C test check-lisp-emacs-lisp"
+
+test-lisp-emacs-lisp-eieio-tests-inotify:
+ stage: normal
+ extends: [.job-template, .test-template]
+ needs:
+ - job: build-image-inotify
+ optional: true
+ rules:
+ - if: '$CI_PIPELINE_SOURCE == "schedule"'
+ when: never
+ - changes:
+ - lisp/emacs-lisp/eieio*.el
+ - test/lisp/emacs-lisp/eieio-tests/*.el
+ - test/lisp/emacs-lisp/eieio-tests/*resources/**
+ variables:
+ target: emacs-inotify
+ make_params: "-k -C test check-lisp-emacs-lisp-eieio-tests"
+
+test-lisp-emacs-lisp-faceup-tests-inotify:
+ stage: normal
+ extends: [.job-template, .test-template]
+ needs:
+ - job: build-image-inotify
+ optional: true
+ rules:
+ - if: '$CI_PIPELINE_SOURCE == "schedule"'
+ when: never
+ - changes:
+ - lisp/emacs-lisp/faceup*.el
+ - test/lisp/emacs-lisp/faceup-tests/*.el
+ - test/lisp/emacs-lisp/faceup-tests/*resources/**
+ variables:
+ target: emacs-inotify
+ make_params: "-k -C test check-lisp-emacs-lisp-faceup-tests"
+
+test-lisp-emulation-inotify:
+ stage: normal
+ extends: [.job-template, .test-template]
+ needs:
+ - job: build-image-inotify
+ optional: true
+ rules:
+ - if: '$CI_PIPELINE_SOURCE == "schedule"'
+ when: never
+ - changes:
+ - lisp/emulation/*.el
+ - test/lisp/emulation/*.el
+ - test/lisp/emulation/*resources/**
+ variables:
+ target: emacs-inotify
+ make_params: "-k -C test check-lisp-emulation"
+
+test-lisp-erc-inotify:
+ stage: normal
+ extends: [.job-template, .test-template]
+ needs:
+ - job: build-image-inotify
+ optional: true
+ rules:
+ - if: '$CI_PIPELINE_SOURCE == "schedule"'
+ when: never
+ - changes:
+ - lisp/erc/*.el
+ - test/lisp/erc/*.el
+ - test/lisp/erc/*resources/**
+ variables:
+ target: emacs-inotify
+ make_params: "-k -C test check-lisp-erc"
+
+test-lisp-eshell-inotify:
+ stage: normal
+ extends: [.job-template, .test-template]
+ needs:
+ - job: build-image-inotify
+ optional: true
+ rules:
+ - if: '$CI_PIPELINE_SOURCE == "schedule"'
+ when: never
+ - changes:
+ - lisp/eshell/*.el
+ - test/lisp/eshell/*.el
+ - test/lisp/eshell/*resources/**
+ variables:
+ target: emacs-inotify
+ make_params: "-k -C test check-lisp-eshell"
+
+test-lisp-gnus-inotify:
+ stage: normal
+ extends: [.job-template, .test-template]
+ needs:
+ - job: build-image-inotify
+ optional: true
+ rules:
+ - if: '$CI_PIPELINE_SOURCE == "schedule"'
+ when: never
+ - changes:
+ - lisp/gnus/*.el
+ - test/lisp/gnus/*.el
+ - test/lisp/gnus/*resources/**
+ variables:
+ target: emacs-inotify
+ make_params: "-k -C test check-lisp-gnus"
+
+test-lisp-image-inotify:
+ stage: normal
+ extends: [.job-template, .test-template]
+ needs:
+ - job: build-image-inotify
+ optional: true
+ rules:
+ - if: '$CI_PIPELINE_SOURCE == "schedule"'
+ when: never
+ - changes:
+ - lisp/image/*.el
+ - test/lisp/image/*.el
+ - test/lisp/image/*resources/**
+ variables:
+ target: emacs-inotify
+ make_params: "-k -C test check-lisp-image"
+
+test-lisp-international-inotify:
+ stage: normal
+ extends: [.job-template, .test-template]
+ needs:
+ - job: build-image-inotify
+ optional: true
+ rules:
+ - if: '$CI_PIPELINE_SOURCE == "schedule"'
+ when: never
+ - changes:
+ - lisp/international/*.el
+ - test/lisp/international/*.el
+ - test/lisp/international/*resources/**
+ variables:
+ target: emacs-inotify
+ make_params: "-k -C test check-lisp-international"
+
+test-lisp-mail-inotify:
+ stage: normal
+ extends: [.job-template, .test-template]
+ needs:
+ - job: build-image-inotify
+ optional: true
+ rules:
+ - if: '$CI_PIPELINE_SOURCE == "schedule"'
+ when: never
+ - changes:
+ - lisp/mail/*.el
+ - test/lisp/mail/*.el
+ - test/lisp/mail/*resources/**
+ variables:
+ target: emacs-inotify
+ make_params: "-k -C test check-lisp-mail"
+
+test-lisp-mh-e-inotify:
+ stage: normal
+ extends: [.job-template, .test-template]
+ needs:
+ - job: build-image-inotify
+ optional: true
+ rules:
+ - if: '$CI_PIPELINE_SOURCE == "schedule"'
+ when: never
+ - changes:
+ - lisp/mh-e/*.el
+ - test/lisp/mh-e/*.el
+ - test/lisp/mh-e/*resources/**
+ variables:
+ target: emacs-inotify
+ make_params: "-k -C test check-lisp-mh-e"
+
+test-lisp-net-inotify:
+ stage: normal
+ extends: [.job-template, .test-template]
+ needs:
+ - job: build-image-inotify
+ optional: true
+ rules:
+ - if: '$CI_PIPELINE_SOURCE == "schedule"'
+ when: never
+ - changes:
+ - lisp/net/*.el
+ - test/lisp/net/*.el
+ - test/lisp/net/*resources/**
+ variables:
+ target: emacs-inotify
+ make_params: "-k -C test check-lisp-net"
+
+test-lisp-nxml-inotify:
+ stage: normal
+ extends: [.job-template, .test-template]
+ needs:
+ - job: build-image-inotify
+ optional: true
+ rules:
+ - if: '$CI_PIPELINE_SOURCE == "schedule"'
+ when: never
+ - changes:
+ - lisp/nxml/*.el
+ - test/lisp/nxml/*.el
+ - test/lisp/nxml/*resources/**
+ variables:
+ target: emacs-inotify
+ make_params: "-k -C test check-lisp-nxml"
+
+test-lisp-obsolete-inotify:
+ stage: normal
+ extends: [.job-template, .test-template]
+ needs:
+ - job: build-image-inotify
+ optional: true
+ rules:
+ - if: '$CI_PIPELINE_SOURCE == "schedule"'
+ when: never
+ - changes:
+ - lisp/obsolete/*.el
+ - test/lisp/obsolete/*.el
+ - test/lisp/obsolete/*resources/**
+ variables:
+ target: emacs-inotify
+ make_params: "-k -C test check-lisp-obsolete"
+
+test-lisp-org-inotify:
+ stage: normal
+ extends: [.job-template, .test-template]
+ needs:
+ - job: build-image-inotify
+ optional: true
+ rules:
+ - if: '$CI_PIPELINE_SOURCE == "schedule"'
+ when: never
+ - changes:
+ - lisp/org/*.el
+ - test/lisp/org/*.el
+ - test/lisp/org/*resources/**
+ variables:
+ target: emacs-inotify
+ make_params: "-k -C test check-lisp-org"
+
+test-lisp-play-inotify:
+ stage: normal
+ extends: [.job-template, .test-template]
+ needs:
+ - job: build-image-inotify
+ optional: true
+ rules:
+ - if: '$CI_PIPELINE_SOURCE == "schedule"'
+ when: never
+ - changes:
+ - lisp/play/*.el
+ - test/lisp/play/*.el
+ - test/lisp/play/*resources/**
+ variables:
+ target: emacs-inotify
+ make_params: "-k -C test check-lisp-play"
+
+test-lisp-progmodes-inotify:
+ stage: normal
+ extends: [.job-template, .test-template]
+ needs:
+ - job: build-image-inotify
+ optional: true
+ rules:
+ - if: '$CI_PIPELINE_SOURCE == "schedule"'
+ when: never
+ - changes:
+ - lisp/progmodes/*.el
+ - test/lisp/progmodes/*.el
+ - test/lisp/progmodes/*resources/**
+ variables:
+ target: emacs-inotify
+ make_params: "-k -C test check-lisp-progmodes"
+
+test-lisp-so-long-tests-inotify:
+ stage: normal
+ extends: [.job-template, .test-template]
+ needs:
+ - job: build-image-inotify
+ optional: true
+ rules:
+ - if: '$CI_PIPELINE_SOURCE == "schedule"'
+ when: never
+ - changes:
+ - lisp/so-long*.el
+ - test/lisp/so-long-tests/*.el
+ - test/lisp/so-long-tests/*resources/**
+ variables:
+ target: emacs-inotify
+ make_params: "-k -C test check-lisp-so-long-tests"
+
+test-lisp-term-inotify:
+ stage: normal
+ extends: [.job-template, .test-template]
+ needs:
+ - job: build-image-inotify
+ optional: true
+ rules:
+ - if: '$CI_PIPELINE_SOURCE == "schedule"'
+ when: never
+ - changes:
+ - lisp/term/*.el
+ - test/lisp/term/*.el
+ - test/lisp/term/*resources/**
+ variables:
+ target: emacs-inotify
+ make_params: "-k -C test check-lisp-term"
+
+test-lisp-textmodes-inotify:
+ stage: normal
+ extends: [.job-template, .test-template]
+ needs:
+ - job: build-image-inotify
+ optional: true
+ rules:
+ - if: '$CI_PIPELINE_SOURCE == "schedule"'
+ when: never
+ - changes:
+ - lisp/textmodes/*.el
+ - test/lisp/textmodes/*.el
+ - test/lisp/textmodes/*resources/**
+ variables:
+ target: emacs-inotify
+ make_params: "-k -C test check-lisp-textmodes"
+
+test-lisp-url-inotify:
+ stage: normal
+ extends: [.job-template, .test-template]
+ needs:
+ - job: build-image-inotify
+ optional: true
+ rules:
+ - if: '$CI_PIPELINE_SOURCE == "schedule"'
+ when: never
+ - changes:
+ - lisp/url/*.el
+ - test/lisp/url/*.el
+ - test/lisp/url/*resources/**
+ variables:
+ target: emacs-inotify
+ make_params: "-k -C test check-lisp-url"
+
+test-lisp-vc-inotify:
+ stage: normal
+ extends: [.job-template, .test-template]
+ needs:
+ - job: build-image-inotify
+ optional: true
+ rules:
+ - if: '$CI_PIPELINE_SOURCE == "schedule"'
+ when: never
+ - changes:
+ - lisp/vc/*.el
+ - test/lisp/vc/*.el
+ - test/lisp/vc/*resources/**
+ variables:
+ target: emacs-inotify
+ make_params: "-k -C test check-lisp-vc"
+
+test-misc-inotify:
+ stage: normal
+ extends: [.job-template, .test-template]
+ needs:
+ - job: build-image-inotify
+ optional: true
+ rules:
+ - if: '$CI_PIPELINE_SOURCE == "schedule"'
+ when: never
+ - changes:
+ - admin/*.el
+ - test/misc/*.el
+ - test/misc/*resources/**
+ variables:
+ target: emacs-inotify
+ make_params: "-k -C test check-misc"
+
+test-src-inotify:
+ stage: normal
+ extends: [.job-template, .test-template]
+ needs:
+ - job: build-image-inotify
+ optional: true
+ rules:
+ - if: '$CI_PIPELINE_SOURCE == "schedule"'
+ when: never
+ - changes:
+ - src/*.{h,c}
+ - test/src/*.el
+ - test/src/*resources/**
+ variables:
+ target: emacs-inotify
+ make_params: "-k -C test check-src"
diff --git a/test/lib-src/emacsclient-tests.el b/test/lib-src/emacsclient-tests.el
index f455da718e1..1302fbe30ca 100644
--- a/test/lib-src/emacsclient-tests.el
+++ b/test/lib-src/emacsclient-tests.el
@@ -1,6 +1,6 @@
-;;; emacsclient-tests.el --- Test emacsclient
+;;; emacsclient-tests.el --- Test emacsclient -*- lexical-binding:t -*-
-;; Copyright (C) 2016-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2022 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/abbrev-tests.el b/test/lisp/abbrev-tests.el
index 1f1a7fb6bb6..947178473e4 100644
--- a/test/lisp/abbrev-tests.el
+++ b/test/lisp/abbrev-tests.el
@@ -1,6 +1,6 @@
;;; abbrev-tests.el --- Test suite for abbrevs -*- lexical-binding: t; -*-
-;; Copyright (C) 2015-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2022 Free Software Foundation, Inc.
;; Author: Eli Zaretskii <eliz@gnu.org>
;; Keywords: abbrevs
@@ -28,6 +28,7 @@
;;; Code:
(require 'ert)
+(require 'ert-x)
(require 'abbrev)
(require 'seq)
@@ -38,6 +39,12 @@
(abbrev-table-put ert-test-abbrevs :ert-test "ert-test-value")
ert-test-abbrevs)
+(defun setup-test-abbrev-table-with-props ()
+ (defvar ert-test-abbrevs nil)
+ (define-abbrev-table 'ert-test-abbrevs '(("fb" "fooBar" nil :case-fixed t)))
+ (abbrev-table-put ert-test-abbrevs :ert-test "ert-test-value")
+ ert-test-abbrevs)
+
(ert-deftest abbrev-table-p-test ()
(should-not (abbrev-table-p 42))
(should-not (abbrev-table-p "aoeu"))
@@ -58,6 +65,15 @@
(should (= (length table) obarray-default-size))
(should (eq (abbrev-table-get table 'foo) 'bar))))
+(ert-deftest abbrev--table-symbols-test ()
+ (let ((ert-test-abbrevs (setup-test-abbrev-table)))
+ (define-abbrev ert-test-abbrevs "sys" "system abbrev" nil :system t)
+ (should (equal (mapcar #'symbol-name (abbrev--table-symbols 'ert-test-abbrevs))
+ '("a-e-t")))
+ (let ((syms (abbrev--table-symbols 'ert-test-abbrevs t)))
+ (should (equal (sort (mapcar #'symbol-name syms) #'string<)
+ '("a-e-t" "sys"))))))
+
(ert-deftest abbrev-table-get-put-test ()
(let ((table (make-abbrev-table)))
(should-not (abbrev-table-get table 'foo))
@@ -91,7 +107,7 @@
(should (abbrev-table-empty-p table))))
(ert-deftest kill-all-abbrevs-test ()
- "Test undefining all defined abbrevs"
+ "Test undefining all defined abbrevs."
(unless noninteractive
(ert-skip "Cannot test kill-all-abbrevs in interactive mode"))
@@ -110,14 +126,14 @@
abbrev-table-name-list))))))
(ert-deftest abbrev-table-name-test ()
- "Test returning name of abbrev-table"
+ "Test returning name of abbrev-table."
(let ((ert-test-abbrevs (setup-test-abbrev-table))
(no-such-table nil))
(should (equal 'ert-test-abbrevs (abbrev-table-name ert-test-abbrevs)))
(should (equal nil (abbrev-table-name no-such-table)))))
(ert-deftest clear-abbrev-table-test ()
- "Test clearing single abbrev table"
+ "Test clearing single abbrev table."
(let ((ert-test-abbrevs (setup-test-abbrev-table)))
(should (equal "abbrev-ert-test" (abbrev-expansion "a-e-t" ert-test-abbrevs)))
(clear-abbrev-table ert-test-abbrevs)
@@ -125,7 +141,7 @@
(should (equal t (abbrev-table-empty-p ert-test-abbrevs)))))
(ert-deftest list-abbrevs-test ()
- "Test generation of abbrev list buffer"
+ "Test generation of abbrev list buffer."
;; Somewhat redundant as prepare-abbrev-list-buffer is also tested.
;; all abbrevs
(let ((abbrev-buffer (prepare-abbrev-list-buffer)))
@@ -137,7 +153,7 @@
(kill-buffer abbrev-buffer)))
(ert-deftest prepare-abbrev-list-buffer-test ()
- "Test generation of abbrev list buffer"
+ "Test generation of abbrev list buffer."
;; all abbrevs
(let ((ert-test-abbrevs (setup-test-abbrev-table)))
(with-current-buffer (prepare-abbrev-list-buffer)
@@ -165,7 +181,7 @@
(kill-buffer "*Abbrevs*"))))
(ert-deftest insert-abbrevs-test ()
- "Test inserting abbrev definitions into buffer"
+ "Test inserting abbrev definitions into buffer."
(with-temp-buffer
(insert-abbrevs)
(should (progn
@@ -173,7 +189,7 @@
(search-forward "global-abbrev-table")))))
(ert-deftest edit-abbrevs-test ()
- "Test editing abbrevs from buffer"
+ "Test editing abbrevs from buffer."
(defvar ert-edit-abbrevs-test-table nil)
(let ((ert-test-abbrevs (setup-test-abbrev-table)))
(with-temp-buffer
@@ -190,7 +206,7 @@
(abbrev-expansion "e-a-t" ert-edit-abbrevs-test-table))))))
(ert-deftest define-abbrevs-test ()
- "Test defining abbrevs from buffer"
+ "Test defining abbrevs from buffer."
(defvar ert-bad-abbrev-table nil)
(defvar ert-good-abbrev-table nil)
(defvar ert-redefine-abbrev-table nil)
@@ -220,34 +236,74 @@
(should (equal nil (abbrev-expansion "g-a-t" ert-good-abbrev-table)))))
(ert-deftest read-write-abbrev-file-test ()
- "Test reading and writing abbrevs from file"
- (let ((temp-test-file (make-temp-file "ert-abbrev-test"))
- (ert-test-abbrevs (setup-test-abbrev-table)))
- (write-abbrev-file temp-test-file)
- (clear-abbrev-table ert-test-abbrevs)
- (should (abbrev-table-empty-p ert-test-abbrevs))
- (read-abbrev-file temp-test-file)
- (should (equal "abbrev-ert-test" (abbrev-expansion "a-e-t" ert-test-abbrevs)))
- (delete-file temp-test-file)))
+ "Test reading and writing abbrevs from file."
+ (ert-with-temp-file temp-test-file
+ (let ((ert-test-abbrevs (setup-test-abbrev-table)))
+ (write-abbrev-file temp-test-file)
+ (clear-abbrev-table ert-test-abbrevs)
+ (should (abbrev-table-empty-p ert-test-abbrevs))
+ (read-abbrev-file temp-test-file)
+ (should (equal "abbrev-ert-test" (abbrev-expansion "a-e-t" ert-test-abbrevs))))))
+
+(ert-deftest read-write-abbrev-file-test-with-props ()
+ "Test reading and writing abbrevs from file."
+ (ert-with-temp-file temp-test-file
+ (let ((ert-test-abbrevs (setup-test-abbrev-table-with-props)))
+ (write-abbrev-file temp-test-file)
+ (clear-abbrev-table ert-test-abbrevs)
+ (should (abbrev-table-empty-p ert-test-abbrevs))
+ (read-abbrev-file temp-test-file)
+ (should (equal "fooBar" (abbrev-expansion "fb" ert-test-abbrevs))))))
(ert-deftest abbrev-edit-save-to-file-test ()
- "Test saving abbrev definitions in buffer to file"
+ "Test saving abbrev definitions in buffer to file."
(defvar ert-save-test-table nil)
- (let ((temp-test-file (make-temp-file "ert-abbrev-test"))
- (ert-test-abbrevs (setup-test-abbrev-table)))
+ (ert-with-temp-file temp-test-file
+ (let ((ert-test-abbrevs (setup-test-abbrev-table)))
+ (with-temp-buffer
+ (goto-char (point-min))
+ (insert "(ert-save-test-table)\n")
+ (insert "\n" "\"s-a-t\"\t" "0\t" "\"save-abbrevs-test\"\n")
+ (should (equal "abbrev-ert-test"
+ (abbrev-expansion "a-e-t" ert-test-abbrevs)))
+ ;; clears abbrev tables
+ (abbrev-edit-save-to-file temp-test-file)
+ (should-not (abbrev-expansion "a-e-t" ert-test-abbrevs))
+ (read-abbrev-file temp-test-file)
+ (should (equal "save-abbrevs-test"
+ (abbrev-expansion "s-a-t" ert-save-test-table)))))))
+
+(ert-deftest inverse-add-abbrev-skips-trailing-nonword ()
+ "Test that adding an inverse abbrev skips trailing nonword characters."
+ (let ((table (make-abbrev-table)))
+ (with-temp-buffer
+ (insert "some text foo ")
+ (cl-letf (((symbol-function 'read-string) (lambda (&rest _) "bar")))
+ (inverse-add-abbrev table "Global" 1)))
+ (should (string= (abbrev-expansion "foo" table) "bar"))))
+
+(ert-deftest inverse-add-abbrev-skips-trailing-nonword/positive-arg ()
+ "Test that adding an inverse abbrev skips trailing nonword characters."
+ (let ((table (make-abbrev-table)))
+ (with-temp-buffer
+ (insert "some text foo ")
+ (cl-letf (((symbol-function 'read-string) (lambda (&rest _) "bar")))
+ (inverse-add-abbrev table "Global" 2)))
+ (should (string= (abbrev-expansion "text" table) "bar"))))
+
+(ert-deftest inverse-add-abbrev-skips-trailing-nonword/negative-arg ()
+ "Test that adding an inverse abbrev skips trailing nonword characters."
+ (let ((table (make-abbrev-table)))
(with-temp-buffer
+ (insert "some text foo")
(goto-char (point-min))
- (insert "(ert-save-test-table)\n")
- (insert "\n" "\"s-a-t\"\t" "0\t" "\"save-abbrevs-test\"\n")
- (should (equal "abbrev-ert-test"
- (abbrev-expansion "a-e-t" ert-test-abbrevs)))
- ;; clears abbrev tables
- (abbrev-edit-save-to-file temp-test-file)
- (should-not (abbrev-expansion "a-e-t" ert-test-abbrevs))
- (read-abbrev-file temp-test-file)
- (should (equal "save-abbrevs-test"
- (abbrev-expansion "s-a-t" ert-save-test-table)))
- (delete-file temp-test-file))))
+ (cl-letf (((symbol-function 'read-string) (lambda (&rest _) "bar")))
+ (inverse-add-abbrev table "Global" -1)))
+ (should (string= (abbrev-expansion "text" table) "bar"))))
+
+(ert-deftest test-abbrev-table-p ()
+ (should-not (abbrev-table-p translation-table-vector))
+ (should (abbrev-table-p (make-abbrev-table))))
(provide 'abbrev-tests)
diff --git a/test/lisp/align-resources/align-post.c b/test/lisp/align-resources/align-post.c
new file mode 100644
index 00000000000..157e1d6242a
--- /dev/null
+++ b/test/lisp/align-resources/align-post.c
@@ -0,0 +1,3 @@
+int
+main (int argc,
+ char *argv[]);
diff --git a/test/lisp/align-resources/align-post.java b/test/lisp/align-resources/align-post.java
new file mode 100644
index 00000000000..e0ea8e727f1
--- /dev/null
+++ b/test/lisp/align-resources/align-post.java
@@ -0,0 +1,9 @@
+class X
+{
+ String field1;
+ String[] field2;
+ int field3;
+ int[] field4;
+ X field5;
+ X[] field6;
+}
diff --git a/test/lisp/align-resources/align-pre.c b/test/lisp/align-resources/align-pre.c
new file mode 100644
index 00000000000..b1774181a40
--- /dev/null
+++ b/test/lisp/align-resources/align-pre.c
@@ -0,0 +1,3 @@
+int
+main (int argc,
+ char *argv[]);
diff --git a/test/lisp/align-resources/align-pre.java b/test/lisp/align-resources/align-pre.java
new file mode 100644
index 00000000000..fe7a87a9393
--- /dev/null
+++ b/test/lisp/align-resources/align-pre.java
@@ -0,0 +1,9 @@
+class X
+{
+ String field1;
+ String[] field2;
+ int field3;
+ int[] field4;
+ X field5;
+ X[] field6;
+}
diff --git a/test/lisp/align-tests.el b/test/lisp/align-tests.el
new file mode 100644
index 00000000000..5b964fc5c0f
--- /dev/null
+++ b/test/lisp/align-tests.el
@@ -0,0 +1,47 @@
+;;; align-tests.el --- Test suite for aligns -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2015-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'ert-x)
+(require 'align)
+
+(defun test-align-compare (file function)
+ (should (equal
+ (with-temp-buffer
+ (insert-file-contents (ert-resource-file (format file "pre")))
+ (funcall function)
+ (align (point-min) (point-max))
+ (buffer-substring-no-properties (point-min) (point-max)))
+ (with-temp-buffer
+ (insert-file-contents (ert-resource-file (format file "post")))
+ (buffer-string)))))
+
+(ert-deftest align-java ()
+ (test-align-compare "align-%s.java" #'java-mode))
+
+(ert-deftest align-c ()
+ (test-align-compare "align-%s.c" #'c-mode))
+
+(provide 'align-tests)
+
+;;; align-tests.el ends here
diff --git a/test/lisp/allout-tests.el b/test/lisp/allout-tests.el
new file mode 100644
index 00000000000..4c3fd9c5dc6
--- /dev/null
+++ b/test/lisp/allout-tests.el
@@ -0,0 +1,148 @@
+;;; allout-tests.el --- Tests for allout.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'allout)
+
+(require 'cl-lib)
+
+(defun allout-tests-obliterate-variable (name)
+ "Completely unbind variable with NAME."
+ (if (local-variable-p name (current-buffer)) (kill-local-variable name))
+ (while (boundp name) (makunbound name)))
+
+(defvar allout-tests-globally-unbound nil
+ "Fodder for allout resumptions tests -- defvar just for byte compiler.")
+(defvar allout-tests-globally-true nil
+ "Fodder for allout resumptions tests -- defvar just for byte compiler.")
+(defvar allout-tests-locally-true nil
+ "Fodder for allout resumptions tests -- defvar just for byte compiler.")
+
+;; For each resumption case, we also test that the right local/global
+;; scopes are affected during resumption effects.
+
+(ert-deftest allout-test-resumption-unbound-return-to-unbound ()
+ "Previously unbound variables return to the unbound state."
+ (with-temp-buffer
+ (allout-tests-obliterate-variable 'allout-tests-globally-unbound)
+ (allout-add-resumptions '(allout-tests-globally-unbound t))
+ (should (not (default-boundp 'allout-tests-globally-unbound)))
+ (should (local-variable-p 'allout-tests-globally-unbound (current-buffer)))
+ (should (boundp 'allout-tests-globally-unbound))
+ (should (equal allout-tests-globally-unbound t))
+ (allout-do-resumptions)
+ (should (not (local-variable-p 'allout-tests-globally-unbound
+ (current-buffer))))
+ (should (not (boundp 'allout-tests-globally-unbound)))))
+
+(ert-deftest allout-test-resumption-variable-resumed ()
+ "Ensure that variable with prior global value is resumed."
+ (with-temp-buffer
+ (allout-tests-obliterate-variable 'allout-tests-globally-true)
+ (setq allout-tests-globally-true t)
+ (allout-add-resumptions '(allout-tests-globally-true nil))
+ (should (equal (default-value 'allout-tests-globally-true) t))
+ (should (local-variable-p 'allout-tests-globally-true (current-buffer)))
+ (should (equal allout-tests-globally-true nil))
+ (allout-do-resumptions)
+ (should (not (local-variable-p 'allout-tests-globally-true
+ (current-buffer))))
+ (should (boundp 'allout-tests-globally-true))
+ (should (equal allout-tests-globally-true t))))
+
+(ert-deftest allout-test-resumption-prior-value-resumed ()
+ "Ensure that prior local value is resumed."
+ (with-temp-buffer
+ (allout-tests-obliterate-variable 'allout-tests-locally-true)
+ (setq-local allout-tests-locally-true t)
+ (cl-assert (not (default-boundp 'allout-tests-locally-true))
+ nil (concat "Test setup mistake -- variable supposed to"
+ " not have global binding, but it does."))
+ (cl-assert (local-variable-p 'allout-tests-locally-true (current-buffer))
+ nil (concat "Test setup mistake -- variable supposed to have"
+ " local binding, but it lacks one."))
+ (allout-add-resumptions '(allout-tests-locally-true nil))
+ (should (not (default-boundp 'allout-tests-locally-true)))
+ (should (local-variable-p 'allout-tests-locally-true (current-buffer)))
+ (should (equal allout-tests-locally-true nil))
+ (allout-do-resumptions)
+ (should (boundp 'allout-tests-locally-true))
+ (should (local-variable-p 'allout-tests-locally-true (current-buffer)))
+ (should (equal allout-tests-locally-true t))
+ (should (not (default-boundp 'allout-tests-locally-true)))))
+
+(ert-deftest allout-test-resumption-multiple-holds ()
+ "Ensure that last of multiple resumptions holds, for various scopes."
+ (with-temp-buffer
+ (allout-tests-obliterate-variable 'allout-tests-globally-unbound)
+ (allout-tests-obliterate-variable 'allout-tests-globally-true)
+ (setq allout-tests-globally-true t)
+ (allout-tests-obliterate-variable 'allout-tests-locally-true)
+ (setq-local allout-tests-locally-true t)
+ (allout-add-resumptions '(allout-tests-globally-unbound t)
+ '(allout-tests-globally-true nil)
+ '(allout-tests-locally-true nil))
+ (allout-add-resumptions '(allout-tests-globally-unbound 2)
+ '(allout-tests-globally-true 3)
+ '(allout-tests-locally-true 4))
+ ;; reestablish many of the basic conditions are maintained after re-add:
+ (should (not (default-boundp 'allout-tests-globally-unbound)))
+ (should (local-variable-p 'allout-tests-globally-unbound (current-buffer)))
+ (should (equal allout-tests-globally-unbound 2))
+ (should (default-boundp 'allout-tests-globally-true))
+ (should (local-variable-p 'allout-tests-globally-true (current-buffer)))
+ (should (equal allout-tests-globally-true 3))
+ (should (not (default-boundp 'allout-tests-locally-true)))
+ (should (local-variable-p 'allout-tests-locally-true (current-buffer)))
+ (should (equal allout-tests-locally-true 4))
+ (allout-do-resumptions)
+ (should (not (local-variable-p 'allout-tests-globally-unbound
+ (current-buffer))))
+ (should (not (boundp 'allout-tests-globally-unbound)))
+ (should (not (local-variable-p 'allout-tests-globally-true
+ (current-buffer))))
+ (should (boundp 'allout-tests-globally-true))
+ (should (equal allout-tests-globally-true t))
+ (should (boundp 'allout-tests-locally-true))
+ (should (local-variable-p 'allout-tests-locally-true (current-buffer)))
+ (should (equal allout-tests-locally-true t))
+ (should (not (default-boundp 'allout-tests-locally-true)))))
+
+(ert-deftest allout-test-resumption-unbinding ()
+ "Ensure that deliberately unbinding registered variables doesn't foul things."
+ (with-temp-buffer
+ (allout-tests-obliterate-variable 'allout-tests-globally-unbound)
+ (allout-tests-obliterate-variable 'allout-tests-globally-true)
+ (setq allout-tests-globally-true t)
+ (allout-tests-obliterate-variable 'allout-tests-locally-true)
+ (setq-local allout-tests-locally-true t)
+ (allout-add-resumptions '(allout-tests-globally-unbound t)
+ '(allout-tests-globally-true nil)
+ '(allout-tests-locally-true nil))
+ (allout-tests-obliterate-variable 'allout-tests-globally-unbound)
+ (allout-tests-obliterate-variable 'allout-tests-globally-true)
+ (allout-tests-obliterate-variable 'allout-tests-locally-true)
+ (allout-do-resumptions)))
+
+(provide 'allout-tests)
+;;; allout-tests.el ends here
diff --git a/test/lisp/allout-widgets-tests.el b/test/lisp/allout-widgets-tests.el
new file mode 100644
index 00000000000..c6616922be9
--- /dev/null
+++ b/test/lisp/allout-widgets-tests.el
@@ -0,0 +1,87 @@
+;;; allout-widgets-tests.el --- Tests for allout-widgets.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'allout-widgets)
+
+(require 'cl-lib)
+
+(ert-deftest allout-test-range-overlaps ()
+ "`allout-range-overlaps' unit tests."
+ (let* (ranges
+ got
+ (try (lambda (from to)
+ (setq got (allout-range-overlaps from to ranges))
+ (setq ranges (cadr got))
+ got)))
+;; ;; biggie:
+;; (setq ranges nil)
+;; ;; ~ .02 to .1 seconds for just repeated listing args instead of funcall
+;; ;; ~ 13 seconds for doing repeated funcall
+;; (message "time-trial: %s, resulting size %s"
+;; (time-trial
+;; '(let ((size 10000)
+;; doing)
+;; (dotimes (count size)
+;; (setq doing (random size))
+;; (funcall try doing (+ doing (random 5)))
+;; ;;(list doing (+ doing (random 5)))
+;; )))
+;; (length ranges))
+;; (sit-for 2)
+
+ ;; fresh:
+ (setq ranges nil)
+ (should (equal (funcall try 3 5) '(nil ((3 5)))))
+ ;; add range at end:
+ (should (equal (funcall try 10 12) '(nil ((3 5) (10 12)))))
+ ;; add range at beginning:
+ (should (equal (funcall try 1 2) '(nil ((1 2) (3 5) (10 12)))))
+ ;; insert range somewhere in the middle:
+ (should (equal (funcall try 7 9) '(nil ((1 2) (3 5) (7 9) (10 12)))))
+ ;; consolidate some:
+ (should (equal (funcall try 5 8) '(t ((1 2) (3 9) (10 12)))))
+ ;; add more:
+ (should (equal (funcall try 15 17) '(nil ((1 2) (3 9) (10 12) (15 17)))))
+ ;; add more:
+ (should (equal (funcall try 20 22)
+ '(nil ((1 2) (3 9) (10 12) (15 17) (20 22)))))
+ ;; encompass more:
+ (should (equal (funcall try 4 11) '(t ((1 2) (3 12) (15 17) (20 22)))))
+ ;; encompass all:
+ (should (equal (funcall try 2 25) '(t ((1 25)))))
+
+ ;; fresh slate:
+ (setq ranges nil)
+ (should (equal (funcall try 20 25) '(nil ((20 25)))))
+ (should (equal (funcall try 30 35) '(nil ((20 25) (30 35)))))
+ (should (equal (funcall try 26 28) '(nil ((20 25) (26 28) (30 35)))))
+ (should (equal (funcall try 15 20) '(t ((15 25) (26 28) (30 35)))))
+ (should (equal (funcall try 10 30) '(t ((10 35)))))
+ (should (equal (funcall try 5 6) '(nil ((5 6) (10 35)))))
+ (should (equal (funcall try 2 100) '(t ((2 100)))))
+
+ (setq ranges nil)))
+
+(provide 'allout-widgets-tests)
+;;; allout-widgets-tests.el ends here
diff --git a/test/lisp/ansi-color-tests.el b/test/lisp/ansi-color-tests.el
new file mode 100644
index 00000000000..f672f334914
--- /dev/null
+++ b/test/lisp/ansi-color-tests.el
@@ -0,0 +1,196 @@
+;;; ansi-color-tests.el --- Test suite for ansi-color -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+;; Author: Pablo Barbáchano <pablob@amazon.com>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ansi-color)
+(eval-when-compile (require 'cl-lib))
+
+(defvar ansi-color-tests--strings
+ (let ((bright-yellow (face-foreground 'ansi-color-bright-yellow nil 'default))
+ (yellow (face-foreground 'ansi-color-yellow nil 'default))
+ (custom-color "#87FFFF"))
+ `(("Hello World" "Hello World")
+ ("\e[33mHello World\e[0m" "Hello World"
+ (:foreground ,yellow))
+ ("\e[43mHello World\e[0m" "Hello World"
+ (:background ,yellow))
+ ("\e[93mHello World\e[0m" "Hello World"
+ (:foreground ,bright-yellow))
+ ("\e[103mHello World\e[0m" "Hello World"
+ (:background ,bright-yellow))
+ ("\e[1;33mHello World\e[0m" "Hello World"
+ (ansi-color-bold (:foreground ,yellow))
+ (ansi-color-bold (:foreground ,bright-yellow)))
+ ("\e[33;1mHello World\e[0m" "Hello World"
+ (ansi-color-bold (:foreground ,yellow))
+ (ansi-color-bold (:foreground ,bright-yellow)))
+ ("\e[1m\e[33mHello World\e[0m" "Hello World"
+ (ansi-color-bold (:foreground ,yellow))
+ (ansi-color-bold (:foreground ,bright-yellow)))
+ ("\e[33m\e[1mHello World\e[0m" "Hello World"
+ (ansi-color-bold (:foreground ,yellow))
+ (ansi-color-bold (:foreground ,bright-yellow)))
+ ("\e[1m\e[3m\e[5mbold italics blink\e[0m" "bold italics blink"
+ (ansi-color-bold ansi-color-italic ansi-color-slow-blink))
+ ("\e[10munrecognized\e[0m" "unrecognized")
+ ("\e[38;5;3;1mHello World\e[0m" "Hello World"
+ (ansi-color-bold (:foreground ,yellow))
+ (ansi-color-bold (:foreground ,bright-yellow)))
+ ("\e[48;5;123;1mHello World\e[0m" "Hello World"
+ (ansi-color-bold (:background ,custom-color)))
+ ("\e[48;2;135;255;255;1mHello World\e[0m" "Hello World"
+ (ansi-color-bold (:background ,custom-color))))))
+
+(defun ansi-color-tests-equal-props (o1 o2)
+ "Return t if two Lisp objects have similar structure and contents.
+While `equal-including-properties' compares text properties of
+strings with `eq', this function compares them with `equal'."
+ (or (equal-including-properties o1 o2)
+ (and (stringp o1)
+ (equal o1 o2)
+ (cl-loop for i below (length o1)
+ always (equal (text-properties-at i o1)
+ (text-properties-at i o2))))))
+
+(ert-deftest ansi-color-apply-on-region-test ()
+ (pcase-dolist (`(,input ,text ,face) ansi-color-tests--strings)
+ (with-temp-buffer
+ (insert input)
+ (ansi-color-apply-on-region (point-min) (point-max))
+ (should (equal (buffer-string) text))
+ (should (equal (get-char-property (point-min) 'face) face))
+ (when face
+ (should (overlays-at (point-min)))))))
+
+(ert-deftest ansi-color-apply-on-region-bold-is-bright-test ()
+ (pcase-dolist (`(,input ,text ,normal-face ,bright-face)
+ ansi-color-tests--strings)
+ (with-temp-buffer
+ (let ((ansi-color-bold-is-bright t)
+ (face (or bright-face normal-face)))
+ (insert input)
+ (ansi-color-apply-on-region (point-min) (point-max))
+ (should (equal (buffer-string) text))
+ (should (equal (get-char-property (point-min) 'face) face))
+ (when face
+ (should (overlays-at (point-min))))))))
+
+(ert-deftest ansi-color-apply-on-region-preserving-test ()
+ (dolist (pair ansi-color-tests--strings)
+ (with-temp-buffer
+ (insert (car pair))
+ (ansi-color-apply-on-region (point-min) (point-max) t)
+ (should (equal (buffer-string) (car pair))))))
+
+(ert-deftest ansi-color-incomplete-sequences-test ()
+ (let* ((strs (list "\e[" "2;31m Hello World "
+ "\e" "[108;5;12" "3m" "Greetings"
+ "\e[0m\e[35;6m" "Hello"))
+ (complete-str (apply #'concat strs))
+ (filtered-str)
+ (propertized-str)
+ (ansi-color-apply-face-function
+ #'ansi-color-apply-text-property-face)
+ (ansi-filt (lambda (str) (ansi-color-filter-apply
+ (copy-sequence str))))
+ (ansi-app (lambda (str) (ansi-color-apply
+ (copy-sequence str)))))
+
+ (with-temp-buffer
+ (setq filtered-str
+ (replace-regexp-in-string "\e\\[.*?m" "" complete-str))
+ (setq propertized-str (funcall ansi-app complete-str))
+
+ (should-not (ansi-color-tests-equal-props
+ filtered-str propertized-str))
+ (should (equal filtered-str propertized-str)))
+
+ ;; Tests for `ansi-color-filter-apply'
+ (with-temp-buffer
+ (should (equal-including-properties
+ filtered-str
+ (funcall ansi-filt complete-str))))
+
+ (with-temp-buffer
+ (should (equal-including-properties
+ filtered-str
+ (mapconcat ansi-filt strs))))
+
+ ;; Tests for `ansi-color-filter-region'
+ (with-temp-buffer
+ (insert complete-str)
+ (ansi-color-filter-region (point-min) (point-max))
+ (should (equal-including-properties
+ filtered-str (buffer-string))))
+
+ (with-temp-buffer
+ (dolist (str strs)
+ (let ((opoint (point)))
+ (insert str)
+ (ansi-color-filter-region opoint (point))))
+ (should (equal-including-properties
+ filtered-str (buffer-string))))
+
+ ;; Test for `ansi-color-apply'
+ (with-temp-buffer
+ (should (ansi-color-tests-equal-props
+ propertized-str
+ (mapconcat ansi-app strs))))
+
+ ;; Tests for `ansi-color-apply-on-region'
+ (with-temp-buffer
+ (insert complete-str)
+ (ansi-color-apply-on-region (point-min) (point-max))
+ (should (ansi-color-tests-equal-props
+ propertized-str (buffer-string))))
+
+ (with-temp-buffer
+ (dolist (str strs)
+ (let ((opoint (point)))
+ (insert str)
+ (ansi-color-apply-on-region opoint (point))))
+ (should (ansi-color-tests-equal-props
+ propertized-str (buffer-string))))
+
+ ;; \e not followed by '[' and invalid ANSI escape sequences
+ (dolist (fun (list ansi-filt ansi-app))
+ (with-temp-buffer
+ (should (equal (funcall fun "\e") ""))
+ (should (equal (funcall fun "\e[33m test \e[0m")
+ (with-temp-buffer
+ (concat "\e" (funcall fun "\e[33m test \e[0m"))))))
+ (with-temp-buffer
+ (should (equal (funcall fun "\e[") ""))
+ (should (equal (funcall fun "\e[33m Z \e[0m")
+ (with-temp-buffer
+ (concat "\e[" (funcall fun "\e[33m Z \e[0m"))))))
+ (with-temp-buffer
+ (should (equal (funcall fun "\e a \e\e[\e[") "\e a \e\e["))
+ (should (equal (funcall fun "\e[33m Z \e[0m")
+ (with-temp-buffer
+ (concat "\e[" (funcall fun "\e[33m Z \e[0m")))))))))
+
+(provide 'ansi-color-tests)
+
+;;; ansi-color-tests.el ends here
diff --git a/test/lisp/apropos-tests.el b/test/lisp/apropos-tests.el
new file mode 100644
index 00000000000..289700abf70
--- /dev/null
+++ b/test/lisp/apropos-tests.el
@@ -0,0 +1,133 @@
+;;; apropos-tests.el --- Tests for apropos.el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+;; Author: Simen Heggestøyl <simenheg@gmail.com>
+;; Keywords:
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;
+
+;;; Code:
+
+(require 'apropos)
+(require 'ert)
+
+(ert-deftest apropos-tests-words-to-regexp-1 ()
+ (let ((re (apropos-words-to-regexp '("foo" "bar") "baz")))
+ (should (string-match-p re "foobazbar"))
+ (should (string-match-p re "barbazfoo"))
+ (should-not (string-match-p re "foo-bar"))
+ (should-not (string-match-p re "foobazbazbar"))))
+
+(ert-deftest apropos-tests-words-to-regexp-2 ()
+ (let ((re (apropos-words-to-regexp '("foo" "bar" "baz") "-")))
+ (should-not (string-match-p re "foo"))
+ (should-not (string-match-p re "foobar"))
+ (should (string-match-p re "foo-bar"))
+ (should (string-match-p re "foo-baz"))))
+
+(ert-deftest apropos-tests-parse-pattern-1 ()
+ (apropos-parse-pattern '("foo"))
+ (should (string-match-p apropos-regexp "foo"))
+ (should (string-match-p apropos-regexp "foo-bar"))
+ (should (string-match-p apropos-regexp "bar-foo"))
+ (should (string-match-p apropos-regexp "foo-foo"))
+ (should-not (string-match-p apropos-regexp "bar")))
+
+(ert-deftest apropos-tests-parse-pattern-2 ()
+ (apropos-parse-pattern '("foo" "bar"))
+ (should (string-match-p apropos-regexp "foo-bar"))
+ (should (string-match-p apropos-regexp "bar-foo"))
+ (should-not (string-match-p apropos-regexp "foo"))
+ (should-not (string-match-p apropos-regexp "bar"))
+ (should-not (string-match-p apropos-regexp "baz"))
+ (should-not (string-match-p apropos-regexp "foo-foo"))
+ (should-not (string-match-p apropos-regexp "bar-bar")))
+
+(ert-deftest apropos-tests-parse-pattern-3 ()
+ (apropos-parse-pattern '("foo" "bar" "baz"))
+ (should (string-match-p apropos-regexp "foo-bar"))
+ (should (string-match-p apropos-regexp "foo-baz"))
+ (should (string-match-p apropos-regexp "bar-foo"))
+ (should (string-match-p apropos-regexp "bar-baz"))
+ (should (string-match-p apropos-regexp "baz-foo"))
+ (should (string-match-p apropos-regexp "baz-bar"))
+ (should-not (string-match-p apropos-regexp "foo"))
+ (should-not (string-match-p apropos-regexp "bar"))
+ (should-not (string-match-p apropos-regexp "baz"))
+ (should-not (string-match-p apropos-regexp "foo-foo"))
+ (should-not (string-match-p apropos-regexp "bar-bar"))
+ (should-not (string-match-p apropos-regexp "baz-baz")))
+
+(ert-deftest apropos-tests-parse-pattern-single-regexp ()
+ (apropos-parse-pattern "foo+bar")
+ (should-not (string-match-p apropos-regexp "fobar"))
+ (should (string-match-p apropos-regexp "foobar"))
+ (should (string-match-p apropos-regexp "fooobar")))
+
+(ert-deftest apropos-tests-parse-pattern-synonyms ()
+ (let ((apropos-synonyms '(("find" "open" "edit"))))
+ (apropos-parse-pattern '("open"))
+ (should (string-match-p apropos-regexp "find-file"))
+ (should (string-match-p apropos-regexp "open-file"))
+ (should (string-match-p apropos-regexp "edit-file"))))
+
+(ert-deftest apropos-tests-calc-scores ()
+ (let ((str "Return apropos score for string STR."))
+ (should (equal (apropos-calc-scores str '("apr")) '(7)))
+ (should (equal (apropos-calc-scores str '("apr" "str")) '(25 7)))
+ (should (equal (apropos-calc-scores str '("appr" "str")) '(25)))
+ (should-not (apropos-calc-scores str '("appr" "strr")))))
+
+(ert-deftest apropos-tests-score-str ()
+ (apropos-parse-pattern '("foo" "bar"))
+ (should (< (apropos-score-str "baz")
+ (apropos-score-str "foo baz")
+ (apropos-score-str "foo bar baz"))))
+
+(ert-deftest apropos-tests-score-doc ()
+ (apropos-parse-pattern '("foo" "bar"))
+ (should (< (apropos-score-doc "baz")
+ (apropos-score-doc "foo baz")
+ (apropos-score-doc "foo bar baz"))))
+
+(ert-deftest apropos-tests-score-symbol ()
+ (apropos-parse-pattern '("foo" "bar"))
+ (should (< (apropos-score-symbol 'baz)
+ (apropos-score-symbol 'foo-baz)
+ (apropos-score-symbol 'foo-bar-baz))))
+
+(ert-deftest apropos-tests-true-hit ()
+ (should-not (apropos-true-hit "foo" '("foo" "bar")))
+ (should (apropos-true-hit "foo bar" '("foo" "bar")))
+ (should (apropos-true-hit "foo bar baz" '("foo" "bar"))))
+
+(ert-deftest apropos-tests-format-plist ()
+ (setplist 'foo '(a 1 b (2 3) c nil))
+ (apropos-parse-pattern '("b"))
+ (should (equal (apropos-format-plist 'foo ", ")
+ "a 1, b (2 3), c nil"))
+ (should (equal (apropos-format-plist 'foo ", " t)
+ "b (2 3)"))
+ (apropos-parse-pattern '("d"))
+ (should-not (apropos-format-plist 'foo ", " t)))
+
+(provide 'apropos-tests)
+;;; apropos-tests.el ends here
diff --git a/test/lisp/arc-mode-tests.el b/test/lisp/arc-mode-tests.el
index 63e5579b39b..341a835039e 100644
--- a/test/lisp/arc-mode-tests.el
+++ b/test/lisp/arc-mode-tests.el
@@ -1,6 +1,6 @@
;;; arc-mode-tests.el --- Test suite for arc-mode. -*- lexical-binding: t -*-
-;; Copyright (C) 2017 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2022 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -21,17 +21,31 @@
(require 'ert)
(require 'arc-mode)
+(defvar arc-mode-tests-data-directory
+ (expand-file-name "test/data/decompress" source-directory))
(ert-deftest arc-mode-test-archive-int-to-mode ()
(let ((alist (list (cons 448 "-rwx------")
(cons 420 "-rw-r--r--")
(cons 292 "-r--r--r--")
- (cons 512 "----------")
+ (cons 512 "---------T")
(cons 1024 "------S---") ; Bug#28092
(cons 2048 "---S------"))))
(dolist (x alist)
- (should (equal (cdr x) (archive-int-to-mode (car x)))))))
+ (should (equal (cdr x) (file-modes-number-to-symbolic (car x)))))))
+
+(ert-deftest arc-mode-test-zip-extract-gz ()
+ (skip-unless (and archive-zip-extract (executable-find (car archive-zip-extract))))
+ (skip-unless (executable-find "gzip"))
+ (let* ((zip-file (expand-file-name "zg.zip" arc-mode-tests-data-directory))
+ zip-buffer gz-buffer)
+ (unwind-protect
+ (with-current-buffer (setq zip-buffer (find-file-noselect zip-file))
+ (setq gz-buffer (archive-extract))
+ (should (equal (char-after) ?\N{SNOWFLAKE})))
+ (when (buffer-live-p zip-buffer) (kill-buffer zip-buffer))
+ (when (buffer-live-p gz-buffer) (kill-buffer gz-buffer)))))
(provide 'arc-mode-tests)
-;; arc-mode-tests.el ends here
+;;; arc-mode-tests.el ends here
diff --git a/test/lisp/auth-source-pass-tests.el b/test/lisp/auth-source-pass-tests.el
index 9b6b5687cab..f5147a7ce07 100644
--- a/test/lisp/auth-source-pass-tests.el
+++ b/test/lisp/auth-source-pass-tests.el
@@ -1,6 +1,6 @@
;;; auth-source-pass-tests.el --- Tests for auth-source-pass.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2013, 2017 Free Software Foundation, Inc.
+;; Copyright (C) 2013, 2017-2022 Free Software Foundation, Inc.
;; Author: Damien Cassou <damien.cassou@gmail.com>
@@ -49,126 +49,375 @@
'(("key1" . "val1")
("key2" . "val2"))))))
+(ert-deftest auth-source-pass-parse-with-colons-in-data ()
+ (let ((content "pass\n--\nkey1 :val1\nkey2: please: keep my space after colon\n\n"))
+ (should (equal (auth-source-pass--parse-data content)
+ '(("key1" . "val1")
+ ("key2" . "please: keep my space after colon"))))))
+
(defvar auth-source-pass--debug-log nil
- "Contains a list of all messages passed to `auth-source-do-debug`.")
+ "Contains a list of all messages passed to `auth-source-do-debug'.")
+
+(defun auth-source-pass--have-message-matching (regexp)
+ "Return non-nil iff at least one `auth-source-do-debug' match REGEXP."
+ (seq-find (lambda (message)
+ (string-match regexp message))
+ auth-source-pass--debug-log))
+
+(defun auth-source-pass--explain--have-message-matching (regexp)
+ "Explainer function for `auth-source-pass--have-message-matching'.
+REGEXP is the same as in `auth-source-pass--have-message-matching'."
+ `(regexp
+ ,regexp
+ messages
+ ,(mapconcat #'identity auth-source-pass--debug-log "\n- ")))
-(defun auth-source-pass--should-have-message-containing (regexp)
- "Assert that at least one `auth-source-do-debug` matched REGEXP."
- (should (seq-find (lambda (message)
- (string-match regexp message))
- auth-source-pass--debug-log)))
+(put #'auth-source-pass--have-message-matching 'ert-explainer #'auth-source-pass--explain--have-message-matching)
(defun auth-source-pass--debug (&rest msg)
- "Format MSG and add that to `auth-source-pass--debug-log`.
-This function is intended to be set to `auth-source-debug`."
+ "Format MSG and add that to `auth-source-pass--debug-log'.
+This function is intended to be set to `auth-source-debug'."
(add-to-list 'auth-source-pass--debug-log (apply #'format msg) t))
+(defvar auth-source-pass--parse-log nil)
+
(defmacro auth-source-pass--with-store (store &rest body)
"Use STORE as password-store while executing BODY."
(declare (indent 1))
- `(cl-letf (((symbol-function 'auth-source-pass-parse-entry) (lambda (entry) (cdr (cl-find entry ,store :key #'car :test #'string=))) )
- ((symbol-function 'auth-source-pass-entries) (lambda () (mapcar #'car ,store)))
- ((symbol-function 'auth-source-pass--entry-valid-p) (lambda (_entry) t)))
+ `(cl-letf (((symbol-function 'auth-source-pass-parse-entry)
+ (lambda (entry)
+ (add-to-list 'auth-source-pass--parse-log entry)
+ (cdr (cl-find entry ,store :key #'car :test #'string=))))
+ ((symbol-function 'auth-source-pass-entries) (lambda () (mapcar #'car ,store))))
(let ((auth-source-debug #'auth-source-pass--debug)
- (auth-source-pass--debug-log nil))
+ (auth-source-pass--debug-log nil)
+ (auth-source-pass--parse-log nil))
,@body)))
-(ert-deftest auth-source-pass-find-match-matching-at-entry-name ()
- (auth-source-pass--with-store '(("foo"))
- (should (equal (auth-source-pass--find-match "foo" nil)
- "foo"))))
-
-(ert-deftest auth-source-pass-find-match-matching-at-entry-name-part ()
- (auth-source-pass--with-store '(("foo"))
- (should (equal (auth-source-pass--find-match "https://foo" nil)
- "foo"))))
-
-(ert-deftest auth-source-pass-find-match-matching-at-entry-name-ignoring-user ()
- (auth-source-pass--with-store '(("foo"))
- (should (equal (auth-source-pass--find-match "https://SomeUser@foo" nil)
- "foo"))))
-
-(ert-deftest auth-source-pass-find-match-matching-at-entry-name-with-user ()
- (auth-source-pass--with-store '(("SomeUser@foo"))
- (should (equal (auth-source-pass--find-match "https://SomeUser@foo" nil)
- "SomeUser@foo"))))
-
-(ert-deftest auth-source-pass-find-match-matching-at-entry-name-prefer-full ()
- (auth-source-pass--with-store '(("SomeUser@foo") ("foo"))
- (should (equal (auth-source-pass--find-match "https://SomeUser@foo" nil)
- "SomeUser@foo"))))
-
-(ert-deftest auth-source-pass-find-match-matching-at-entry-name-prefer-full-reversed ()
- (auth-source-pass--with-store '(("foo") ("SomeUser@foo"))
- (should (equal (auth-source-pass--find-match "https://SomeUser@foo" nil)
- "SomeUser@foo"))))
-
-(ert-deftest auth-source-pass-find-match-matching-at-entry-name-without-subdomain ()
+(defun auth-source-pass--explain-match-entry-p (entry hostname &optional user port)
+ "Explainer function for `auth-source-pass-match-entry-p'.
+
+ENTRY, HOSTNAME, USER and PORT are the same as in
+`auth-source-pass-match-entry-p'."
+ `(entry
+ ,entry
+ store
+ ,(auth-source-pass-entries)
+ matching-entries
+ ,(auth-source-pass--matching-entries hostname user port)))
+
+(put 'auth-source-pass-match-entry-p 'ert-explainer #'auth-source-pass--explain-match-entry-p)
+
+(defun auth-source-pass--includes-sorted-entries (entries hostname &optional user port)
+ "Return non-nil iff ENTRIES matching the parameters are found in store.
+ENTRIES should be sorted from most specific to least specific.
+
+HOSTNAME, USER and PORT are passed unchanged to
+`auth-source-pass--matching-entries'."
+ (if (seq-empty-p entries)
+ t
+ (and
+ (auth-source-pass-match-entry-p (car entries) hostname user port)
+ (auth-source-pass--includes-sorted-entries (cdr entries) hostname user port))))
+
+(defun auth-source-pass--explain-includes-sorted-entries (entries hostname &optional user port)
+ "Explainer function for `auth-source-pass--includes-sorted-entries'.
+
+ENTRIES, HOSTNAME, USER and PORT are the same as in
+`auth-source-pass--includes-sorted-entries'."
+ `(store
+ ,(auth-source-pass-entries)
+ matching-entries
+ ,(auth-source-pass--matching-entries hostname user port)
+ entries
+ ,entries))
+
+(put 'auth-source-pass--includes-sorted-entries 'ert-explainer #'auth-source-pass--explain-includes-sorted-entries)
+
+(defun auth-source-pass--explain-match-any-entry-p (hostname &optional user port)
+ "Explainer function for `auth-source-pass-match-any-entry-p'.
+
+HOSTNAME, USER and PORT are the same as in `auth-source-pass-match-any-entry-p'."
+ `(store
+ ,(auth-source-pass-entries)
+ matching-entries
+ ,(auth-source-pass--matching-entries hostname user port)))
+
+(put 'auth-source-pass-match-any-entry-p 'ert-explainer #'auth-source-pass--explain-match-any-entry-p)
+
+(defun auth-source-pass--matching-entries (hostname &optional user port)
+ "Return password-store entries matching HOSTNAME, USER, PORT.
+
+The result is a list of lists of password-store entries. Each
+sublist contains the password-store entries whose names match a
+suffix in `auth-source-pass--generate-entry-suffixes'. The
+result is ordered the same way as the suffixes."
+ (let ((entries (auth-source-pass-entries)))
+ (mapcar (lambda (suffix) (auth-source-pass--entries-matching-suffix suffix entries))
+ (auth-source-pass--generate-entry-suffixes hostname user port))))
+
+(defun auth-source-pass-match-entry-p (entry hostname &optional user port)
+ "Return non-nil iff an ENTRY matching the parameters is found in store.
+
+HOSTNAME, USER and PORT are passed unchanged to
+`auth-source-pass--matching-entries'."
+ (cl-find-if
+ (lambda (entries) (cl-find entry entries :test #'string=))
+ (auth-source-pass--matching-entries hostname user port)))
+
+(defun auth-source-pass-match-any-entry-p (hostname &optional user port)
+ "Return non-nil iff there is at least one entry matching the parameters.
+
+HOSTNAME, USER and PORT are passed unchanged to
+`auth-source-pass--matching-entries'."
+ (cl-find-if #'identity (auth-source-pass--matching-entries hostname user port)))
+
+(ert-deftest auth-source-pass-any-host ()
+ (auth-source-pass--with-store '(("foo" ("port" . "foo-port") ("host" . "foo-user"))
+ ("bar"))
+ (should-not (auth-source-pass-search :host t))))
+
+(ert-deftest auth-source-pass-undefined-host ()
+ (auth-source-pass--with-store '(("foo" ("port" . "foo-port") ("host" . "foo-user"))
+ ("bar"))
+ (should-not (auth-source-pass-search :host nil))))
+
+(ert-deftest auth-source-pass-not-found ()
+ (auth-source-pass--with-store '(("foo" ("port" . "foo-port") ("host" . "foo-user"))
+ ("bar"))
+ (should-not (auth-source-pass-search :host "baz"))))
+
+(ert-deftest auth-source-pass--disambiguate-extract-host-from-hostname ()
+ ;; no user or port
+ (should (equal (cl-first (auth-source-pass--disambiguate "foo")) "foo"))
+ ;; only user
+ (should (equal (cl-first (auth-source-pass--disambiguate "user@foo")) "foo"))
+ ;; only port
+ (should (equal (cl-first (auth-source-pass--disambiguate "https://foo")) "foo"))
+ (should (equal (cl-first (auth-source-pass--disambiguate "foo:80")) "foo"))
+ ;; both user and port
+ (should (equal (cl-first (auth-source-pass--disambiguate "https://user@foo")) "foo"))
+ (should (equal (cl-first (auth-source-pass--disambiguate "user@foo:80")) "foo"))
+ ;; all of the above with a trailing path
+ (should (equal (cl-first (auth-source-pass--disambiguate "foo/path")) "foo"))
+ (should (equal (cl-first (auth-source-pass--disambiguate "user@foo/path")) "foo"))
+ (should (equal (cl-first (auth-source-pass--disambiguate "https://foo/path")) "foo"))
+ (should (equal (cl-first (auth-source-pass--disambiguate "foo:80/path")) "foo"))
+ (should (equal (cl-first (auth-source-pass--disambiguate "https://user@foo/path")) "foo"))
+ (should (equal (cl-first (auth-source-pass--disambiguate "user@foo:80/path")) "foo")))
+
+(ert-deftest auth-source-pass--disambiguate-extract-user-from-hostname ()
+ ;; no user or port
+ (should (equal (cl-second (auth-source-pass--disambiguate "foo")) nil))
+ ;; only user
+ (should (equal (cl-second (auth-source-pass--disambiguate "user@foo")) "user"))
+ ;; only port
+ (should (equal (cl-second (auth-source-pass--disambiguate "https://foo")) nil))
+ (should (equal (cl-second (auth-source-pass--disambiguate "foo:80")) nil))
+ ;; both user and port
+ (should (equal (cl-second (auth-source-pass--disambiguate "https://user@foo")) "user"))
+ (should (equal (cl-second (auth-source-pass--disambiguate "user@foo:80")) "user"))
+ ;; all of the above with a trailing path
+ (should (equal (cl-second (auth-source-pass--disambiguate "foo/path")) nil))
+ (should (equal (cl-second (auth-source-pass--disambiguate "user@foo/path")) "user"))
+ (should (equal (cl-second (auth-source-pass--disambiguate "https://foo/path")) nil))
+ (should (equal (cl-second (auth-source-pass--disambiguate "foo:80/path")) nil))
+ (should (equal (cl-second (auth-source-pass--disambiguate "https://user@foo/path")) "user"))
+ (should (equal (cl-second (auth-source-pass--disambiguate "user@foo:80/path")) "user")))
+
+(ert-deftest auth-source-pass--disambiguate-prefer-user-parameter ()
+ ;; no user or port
+ (should (equal (cl-second (auth-source-pass--disambiguate "foo" "user2")) "user2"))
+ ;; only user
+ (should (equal (cl-second (auth-source-pass--disambiguate "user@foo" "user2")) "user2"))
+ ;; only port
+ (should (equal (cl-second (auth-source-pass--disambiguate "https://foo" "user2")) "user2"))
+ (should (equal (cl-second (auth-source-pass--disambiguate "foo:80" "user2")) "user2"))
+ ;; both user and port
+ (should (equal (cl-second (auth-source-pass--disambiguate "https://user@foo" "user2")) "user2"))
+ (should (equal (cl-second (auth-source-pass--disambiguate "user@foo:80" "user2")) "user2"))
+ ;; all of the above with a trailing path
+ (should (equal (cl-second (auth-source-pass--disambiguate "foo/path" "user2")) "user2"))
+ (should (equal (cl-second (auth-source-pass--disambiguate "user@foo/path" "user2")) "user2"))
+ (should (equal (cl-second (auth-source-pass--disambiguate "https://foo/path" "user2")) "user2"))
+ (should (equal (cl-second (auth-source-pass--disambiguate "foo:80/path" "user2")) "user2"))
+ (should (equal (cl-second (auth-source-pass--disambiguate "https://user@foo/path" "user2")) "user2"))
+ (should (equal (cl-second (auth-source-pass--disambiguate "user@foo:80/path" "user2")) "user2")))
+
+(ert-deftest auth-source-pass--disambiguate-extract-port-from-hostname ()
+ ;; no user or port
+ (should (equal (cl-third (auth-source-pass--disambiguate "foo")) "443"))
+ ;; only user
+ (should (equal (cl-third (auth-source-pass--disambiguate "user@foo")) "443"))
+ ;; only port
+ (should (equal (cl-third (auth-source-pass--disambiguate "https://foo")) "443"))
+ (should (equal (cl-third (auth-source-pass--disambiguate "foo:80")) "80"))
+ ;; both user and port
+ (should (equal (cl-third (auth-source-pass--disambiguate "https://user@foo")) "443"))
+ (should (equal (cl-third (auth-source-pass--disambiguate "user@foo:80")) "80"))
+ ;; all of the above with a trailing path
+ (should (equal (cl-third (auth-source-pass--disambiguate "foo/path")) "443"))
+ (should (equal (cl-third (auth-source-pass--disambiguate "user@foo/path")) "443"))
+ (should (equal (cl-third (auth-source-pass--disambiguate "https://foo/path")) "443"))
+ (should (equal (cl-third (auth-source-pass--disambiguate "foo:80/path")) "80"))
+ (should (equal (cl-third (auth-source-pass--disambiguate "https://user@foo/path")) "443"))
+ (should (equal (cl-third (auth-source-pass--disambiguate "user@foo:80/path")) "80")))
+
+(ert-deftest auth-source-pass--disambiguate-prefer-port-parameter ()
+ ;; no user or port
+ (should (equal (cl-third (auth-source-pass--disambiguate "foo" "user2" "8080")) "8080"))
+ ;; only user
+ (should (equal (cl-third (auth-source-pass--disambiguate "user@foo" "user2" "8080")) "8080"))
+ ;; only port
+ (should (equal (cl-third (auth-source-pass--disambiguate "https://foo" "user2" "8080")) "8080"))
+ (should (equal (cl-third (auth-source-pass--disambiguate "foo:80" "user2" "8080")) "8080"))
+ ;; both user and port
+ (should (equal (cl-third (auth-source-pass--disambiguate "https://user@foo" "user2" "8080")) "8080"))
+ (should (equal (cl-third (auth-source-pass--disambiguate "user@foo:80" "user2" "8080")) "8080"))
+ ;; all of the above with a trailing path
+ (should (equal (cl-third (auth-source-pass--disambiguate "foo/path" "user2" "8080")) "8080"))
+ (should (equal (cl-third (auth-source-pass--disambiguate "user@foo/path" "user2" "8080")) "8080"))
+ (should (equal (cl-third (auth-source-pass--disambiguate "https://foo/path" "user2" "8080")) "8080"))
+ (should (equal (cl-third (auth-source-pass--disambiguate "foo:80/path" "user2" "8080")) "8080"))
+ (should (equal (cl-third (auth-source-pass--disambiguate "https://user@foo/path" "user2" "8080")) "8080"))
+ (should (equal (cl-third (auth-source-pass--disambiguate "user@foo:80/path" "user2" "8080")) "8080")))
+
+(ert-deftest auth-source-pass-find-match-minimal-parsing ()
+ (let ((store-contents
+ '(("baz" ("secret" . "baz password"))
+ ("baz:123" ("secret" . "baz:123 password"))
+ ("baz/foo" ("secret" . "baz/foo password"))
+ ("foo@baz" ("secret" . "foo@baz password"))
+ ("baz:123/foo" ("secret" . "baz:123/foo password"))
+ ("foo@baz:123" ("secret" . "foo@baz:123 password"))
+ ("bar.baz" ("secret" . "bar.baz password"))
+ ("bar.baz:123" ("secret" . "bar.baz:123 password"))
+ ("bar.baz/foo" ("secret" . "bar.baz/foo password"))
+ ("foo@bar.baz" ("secret" . "foo@bar.baz password"))
+ ("bar.baz:123/foo" ("secret" . "bar.baz:123/foo password"))
+ ("foo@bar.baz:123" ("secret" . "foo@bar.baz:123 password")))))
+ (auth-source-pass--with-store store-contents
+ (auth-source-pass--find-match "bar.baz" "foo" "123")
+ (should (equal auth-source-pass--parse-log '("foo@bar.baz:123"))))
+ (auth-source-pass--with-store store-contents
+ (auth-source-pass--find-match "bar.baz" "foo" nil)
+ (should (equal auth-source-pass--parse-log '("foo@bar.baz"))))
+ (auth-source-pass--with-store store-contents
+ (auth-source-pass--find-match "bar.baz" nil "123")
+ (should (equal auth-source-pass--parse-log '("bar.baz:123"))))
+ (auth-source-pass--with-store store-contents
+ (auth-source-pass--find-match "bar.baz" nil nil)
+ (should (equal auth-source-pass--parse-log '("bar.baz"))))
+ (auth-source-pass--with-store store-contents
+ (auth-source-pass--find-match "baz" nil nil)
+ (should (equal auth-source-pass--parse-log '("baz"))))
+ (auth-source-pass--with-store
+ '(("dir1/bar.com" ("key" . "val"))
+ ("dir2/bar.com" ("key" . "val"))
+ ("dir3/bar.com" ("key" . "val")))
+ (auth-source-pass--find-match "bar.com" nil nil)
+ (should (= (length auth-source-pass--parse-log) 1)))))
+
+(ert-deftest auth-source-pass--find-match-return-parsed-data ()
+ (auth-source-pass--with-store '(("bar.com" ("key" . "val")))
+ (should (consp (auth-source-pass--find-match "bar.com" nil nil))))
+ (auth-source-pass--with-store '(("dir1/bar.com" ("key1" . "val1")) ("dir2/bar.com" ("key2" . "val2")))
+ (should (consp (auth-source-pass--find-match "bar.com" nil nil)))))
+
+(ert-deftest auth-source-pass--matching-entries ()
(auth-source-pass--with-store '(("bar.com"))
- (should (equal (auth-source-pass--find-match "foo.bar.com" nil)
- "bar.com"))))
-
-(ert-deftest auth-source-pass-find-match-matching-at-entry-name-without-subdomain-with-user ()
- (auth-source-pass--with-store '(("someone@bar.com"))
- (should (equal (auth-source-pass--find-match "foo.bar.com" "someone")
- "someone@bar.com"))))
-
-(ert-deftest auth-source-pass-find-match-matching-at-entry-name-without-subdomain-with-bad-user ()
- (auth-source-pass--with-store '(("someoneelse@bar.com"))
- (should (equal (auth-source-pass--find-match "foo.bar.com" "someone")
- nil))))
-
-(ert-deftest auth-source-pass-find-match-matching-at-entry-name-without-subdomain-prefer-full ()
- (auth-source-pass--with-store '(("bar.com") ("foo.bar.com"))
- (should (equal (auth-source-pass--find-match "foo.bar.com" nil)
- "foo.bar.com"))))
-
-(ert-deftest auth-source-pass-dont-match-at-folder-name ()
- (auth-source-pass--with-store '(("foo.bar.com/foo"))
- (should (equal (auth-source-pass--find-match "foo.bar.com" nil)
- nil))))
-
-(ert-deftest auth-source-pass-search-with-user-first ()
+ (should (auth-source-pass-match-entry-p "bar.com" "bar.com"))
+ ;; match even if sub-domain is asked for
+ (should (auth-source-pass-match-entry-p "bar.com" "foo.bar.com"))
+ ;; match even if a user is asked for
+ (should (auth-source-pass-match-entry-p "bar.com" "bar.com" "user"))
+ ;; match even if user as an @ sign
+ (should (auth-source-pass-match-entry-p "bar.com" "bar.com" "user@someplace"))
+ ;; match even if a port is asked for
+ (should (auth-source-pass-match-entry-p "bar.com" "bar.com" nil "8080"))
+ ;; match even if a user and a port are asked for
+ (should (auth-source-pass-match-entry-p "bar.com" "bar.com" "user" "8080"))
+ ;; don't match if a '.' is replaced with another character
+ (auth-source-pass--with-store '(("barXcom"))
+ (should-not (auth-source-pass-match-any-entry-p "bar.com" nil nil)))))
+
+(ert-deftest auth-source-pass--matching-entries-find-entries-with-a-username ()
+ (auth-source-pass--with-store '(("user@foo"))
+ (should (auth-source-pass-match-entry-p "user@foo" "foo" "user")))
+ ;; match even if sub-domain is asked for
+ (auth-source-pass--with-store '(("user@bar.com"))
+ (should (auth-source-pass-match-entry-p "user@bar.com" "foo.bar.com" "user")))
+ ;; don't match if no user is asked for
+ (auth-source-pass--with-store '(("user@foo"))
+ (should-not (auth-source-pass-match-any-entry-p "foo")))
+ ;; don't match if user is different
+ (auth-source-pass--with-store '(("user1@foo"))
+ (should-not (auth-source-pass-match-any-entry-p "foo" "user2")))
+ ;; don't match if sub-domain is asked for but user is different
+ (auth-source-pass--with-store '(("user1@bar.com"))
+ (should-not (auth-source-pass-match-any-entry-p "foo.bar.com" "user2"))))
+
+(ert-deftest auth-source-pass--matching-entries-find-entries-with-a-port ()
+ (auth-source-pass--with-store '(("bar.com:8080"))
+ (should (auth-source-pass-match-entry-p "bar.com:8080" "bar.com" nil "8080"))))
+
+(ert-deftest auth-source-pass--matching-entries-find-entries-with-a-port-when-passed-multiple-ports ()
+ (auth-source-pass--with-store '(("bar.com:8080"))
+ (should (auth-source-pass-match-entry-p "bar.com:8080" "bar.com" nil '("http" "https" "80" "8080")))))
+
+(ert-deftest auth-source-pass--matching-entries-find-entries-with-slash ()
+ ;; match if entry filename matches user
+ (auth-source-pass--with-store '(("foo.com/user"))
+ (should (auth-source-pass-match-entry-p "foo.com/user" "foo.com" "user")))
+ ;; match with port if entry filename matches user
+ (auth-source-pass--with-store '(("foo.com:8080/user"))
+ (should (auth-source-pass-match-entry-p "foo.com:8080/user" "foo.com" "user" "8080")))
+ ;; don't match if entry filename doesn't match user
+ (auth-source-pass--with-store '(("foo.com/baz"))
+ (should-not (auth-source-pass-match-any-entry-p "foo.com" "user"))))
+
+(ert-deftest auth-source-pass-matching-entries-with-custom-separator ()
+ (let ((auth-source-pass-port-separator "#"))
+ (auth-source-pass--with-store '(("bar.com#443/someone"))
+ (should (auth-source-pass-match-entry-p "bar.com#443/someone" "bar.com" "someone" "443")))))
+
+(ert-deftest auth-source-pass--matching-entries-sort-results ()
+ (auth-source-pass--with-store '(("user@foo") ("foo"))
+ (should (auth-source-pass--includes-sorted-entries '("user@foo" "foo") "foo" "user")))
+ ;; same, but store is reversed
(auth-source-pass--with-store '(("foo") ("user@foo"))
- (should (equal (auth-source-pass--find-match "foo" "user")
- "user@foo"))
- (auth-source-pass--should-have-message-containing "Found 1 match")))
-
-(ert-deftest auth-source-pass-give-priority-to-desired-user ()
- (auth-source-pass--with-store '(("foo") ("subdir/foo" ("user" . "someone")))
- (should (equal (auth-source-pass--find-match "foo" "someone")
- "subdir/foo"))
- (auth-source-pass--should-have-message-containing "Found 2 matches")
- (auth-source-pass--should-have-message-containing "matching user field")))
-
-(ert-deftest auth-source-pass-give-priority-to-desired-user-reversed ()
- (auth-source-pass--with-store '(("foo" ("user" . "someone")) ("subdir/foo"))
- (should (equal (auth-source-pass--find-match "foo" "someone")
- "foo"))
- (auth-source-pass--should-have-message-containing "Found 2 matches")
- (auth-source-pass--should-have-message-containing "matching user field")))
-
-(ert-deftest auth-source-pass-return-first-when-several-matches ()
- (auth-source-pass--with-store '(("foo") ("subdir/foo"))
- (should (equal (auth-source-pass--find-match "foo" nil)
- "foo"))
- (auth-source-pass--should-have-message-containing "Found 2 matches")
- (auth-source-pass--should-have-message-containing "the first one")))
-
-(ert-deftest auth-source-pass-make-divansantana-happy ()
- (auth-source-pass--with-store '(("host.com"))
- (should (equal (auth-source-pass--find-match "smtp.host.com" "myusername@host.co.za")
- "host.com"))))
-
-(ert-deftest auth-source-pass-hostname ()
- (should (equal (auth-source-pass--hostname "https://foo.bar") "foo.bar"))
- (should (equal (auth-source-pass--hostname "http://foo.bar") "foo.bar"))
- (should (equal (auth-source-pass--hostname "https://SomeUser@foo.bar") "foo.bar")))
-
-(ert-deftest auth-source-pass-hostname-with-user ()
- (should (equal (auth-source-pass--hostname-with-user "https://foo.bar") "foo.bar"))
- (should (equal (auth-source-pass--hostname-with-user "http://foo.bar") "foo.bar"))
- (should (equal (auth-source-pass--hostname-with-user "https://SomeUser@foo.bar") "SomeUser@foo.bar")))
+ (should (auth-source-pass--includes-sorted-entries '("user@foo" "foo") "foo" "user")))
+ ;; with sub-domain
+ (auth-source-pass--with-store '(("bar.com") ("foo.bar.com"))
+ (should (auth-source-pass--includes-sorted-entries '("foo.bar.com" "bar.com") "foo.bar.com")))
+ ;; matching user in the entry data takes priority
+ (auth-source-pass--with-store '(("dir1/bar.com") ("dir2/bar.com" ("user" . "user")))
+ (should (auth-source-pass--includes-sorted-entries
+ '("dir2/bar.com" "dir1/bar.com")
+ "bar.com" "user")))
+ ;; same, but store is reversed
+ (auth-source-pass--with-store '(("dir2/bar.com" ("user" . "user")) ("dir1/bar.com"))
+ (should (auth-source-pass--includes-sorted-entries
+ '("dir2/bar.com" "dir1/bar.com")
+ "bar.com" "user"))))
+
+(ert-deftest auth-source-pass-all-supported-organizations ()
+ ;; test every possible entry to store this data: user=rms host=gnu.org port=22
+ (dolist (entry '(;; only host name
+ "gnu.org"
+ ;; hostname + user
+ "gnu.org/rms" "rms@gnu.org"
+ ;; hostname + port
+ "gnu.org:22"
+ ;; hostname + user + port
+ "gnu.org:22/rms" "rms@gnu.org:22"
+ ;; all of the above in a random folder
+ "a/b/gnu.org"
+ "a/b/gnu.org/rms" "a/b/rms@gnu.org"
+ "a/b/gnu.org:22"
+ "a/b/gnu.org:22/rms" "a/b/rms@gnu.org:22"))
+ (auth-source-pass--with-store `((,entry))
+ (should (auth-source-pass-match-entry-p entry "gnu.org" "rms" "22")))))
(defmacro auth-source-pass--with-store-find-foo (store &rest body)
"Use STORE while executing BODY. \"foo\" is the matched entry."
@@ -180,47 +429,64 @@ This function is intended to be set to `auth-source-debug`."
,@body)))
(ert-deftest auth-source-pass-build-result-return-parameters ()
- (auth-source-pass--with-store-find-foo '(("foo"))
+ (auth-source-pass--with-store-find-foo
+ '(("foo" ("secret" . "foo password")))
(let ((result (auth-source-pass--build-result "foo" 512 "user")))
+ (should (equal (plist-get result :host) "foo"))
(should (equal (plist-get result :port) 512))
(should (equal (plist-get result :user) "user")))))
(ert-deftest auth-source-pass-build-result-return-entry-values ()
(auth-source-pass--with-store-find-foo '(("foo" ("port" . 512) ("user" . "anuser")))
(let ((result (auth-source-pass--build-result "foo" nil nil)))
+ (should (equal (plist-get result :host) "foo"))
(should (equal (plist-get result :port) 512))
(should (equal (plist-get result :user) "anuser")))))
(ert-deftest auth-source-pass-build-result-entry-takes-precedence ()
- (auth-source-pass--with-store-find-foo '(("foo" ("port" . 512) ("user" . "anuser")))
+ (auth-source-pass--with-store-find-foo '(("foo" ("host" . "bar") ("port" . 512) ("user" . "anuser")))
(let ((result (auth-source-pass--build-result "foo" 1024 "anotheruser")))
+ (should (equal (plist-get result :host) "bar"))
(should (equal (plist-get result :port) 512))
(should (equal (plist-get result :user) "anuser")))))
-(ert-deftest auth-source-pass-only-return-entries-that-can-be-open ()
- (cl-letf (((symbol-function 'auth-source-pass-entries)
- (lambda () '("foo.site.com" "bar.site.com"
- "mail/baz.site.com/scott")))
- ((symbol-function 'auth-source-pass--entry-valid-p)
- ;; only foo.site.com and "mail/baz.site.com/scott" are valid
- (lambda (entry) (member entry '("foo.site.com"
- "mail/baz.site.com/scott")))))
- (should (equal (auth-source-pass--find-all-by-entry-name "foo.site.com" "someuser")
- '("foo.site.com")))
- (should (equal (auth-source-pass--find-all-by-entry-name "bar.site.com" "someuser")
- '()))
- (should (equal (auth-source-pass--find-all-by-entry-name "baz.site.com" "scott")
- '("mail/baz.site.com/scott")))))
-
-(ert-deftest auth-source-pass-entry-is-not-valid-when-unreadable ()
- (cl-letf (((symbol-function 'auth-source-pass--read-entry)
- (lambda (entry)
- ;; only foo is a valid entry
- (if (string-equal entry "foo")
- "password"
- nil))))
- (should (auth-source-pass--entry-valid-p "foo"))
- (should-not (auth-source-pass--entry-valid-p "bar"))))
+(ert-deftest auth-source-pass-build-result-with-multiple-hosts ()
+ (auth-source-pass--with-store-find-foo
+ '(("foo" ("secret" . "foo password")))
+ (let ((result (auth-source-pass--build-result '("bar" "foo") 512 "user")))
+ (should (equal (plist-get result :host) "foo"))
+ (should (equal (plist-get result :port) 512))
+ (should (equal (plist-get result :user) "user")))))
+
+(ert-deftest auth-source-pass-build-result-with-multiple-hosts-no-match ()
+ (auth-source-pass--with-store-find-foo
+ '(("foo" ("secret" . "foo password")))
+ (should-not (auth-source-pass--build-result '("bar" "baz") 512 "user"))))
+
+(ert-deftest auth-source-pass-can-start-from-auth-source-search ()
+ (auth-source-pass--with-store '(("gitlab.com" ("user" . "someone")))
+ (auth-source-pass-enable)
+ (let ((result (car (auth-source-search :host "gitlab.com"))))
+ (should (equal (plist-get result :user) "someone"))
+ (should (equal (plist-get result :host) "gitlab.com")))))
+
+(ert-deftest auth-source-pass-prints-meaningful-debug-log ()
+ (auth-source-pass--with-store '()
+ (auth-source-pass--find-match "gitlab.com" nil nil)
+ (should (auth-source-pass--have-message-matching
+ "entries matching hostname=\"gitlab.com\""))
+ (should (auth-source-pass--have-message-matching
+ "corresponding suffixes to search for: .*\"gitlab.com\""))
+ (should (auth-source-pass--have-message-matching
+ "found no entries matching \"gitlab.com\"")))
+ (auth-source-pass--with-store '(("gitlab.com"))
+ (auth-source-pass--find-match "gitlab.com" nil nil)
+ (should (auth-source-pass--have-message-matching
+ "found 1 entry matching \"gitlab.com\": \"gitlab.com\"")))
+ (auth-source-pass--with-store '(("a/gitlab.com") ("b/gitlab.com"))
+ (auth-source-pass--find-match "gitlab.com" nil nil)
+ (should (auth-source-pass--have-message-matching
+ "found 2 entries matching \"gitlab.com\": (\"a/gitlab.com\" \"b/gitlab.com\")"))))
(provide 'auth-source-pass-tests)
diff --git a/test/lisp/auth-source-resources/authinfo b/test/lisp/auth-source-resources/authinfo
new file mode 100644
index 00000000000..88aa1712e9d
--- /dev/null
+++ b/test/lisp/auth-source-resources/authinfo
@@ -0,0 +1,2 @@
+machine imap.example.org login jrh@example.org password "*foobar*"
+machine ftp.example.org login jrh password "*baz*"
diff --git a/test/lisp/auth-source-resources/netrc-folding b/test/lisp/auth-source-resources/netrc-folding
new file mode 100644
index 00000000000..85e5e324cdf
--- /dev/null
+++ b/test/lisp/auth-source-resources/netrc-folding
@@ -0,0 +1,6 @@
+# Foo
+machine XM login XL password XP
+
+machine YM
+ login YL
+ password YP
diff --git a/test/lisp/auth-source-tests.el b/test/lisp/auth-source-tests.el
index 07effa7fbc6..a76e4fb0d2e 100644
--- a/test/lisp/auth-source-tests.el
+++ b/test/lisp/auth-source-tests.el
@@ -1,6 +1,6 @@
;;; auth-source-tests.el --- Tests for auth-source.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2015-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2022 Free Software Foundation, Inc.
;; Author: Damien Cassou <damien@cassou.me>,
;; Nicolas Petton <nicolas@petton.fr>
@@ -27,11 +27,10 @@
;;; Code:
(require 'ert)
+(require 'ert-x)
(require 'cl-lib)
(require 'auth-source)
-
-(defvar secrets-enabled t
- "Enable the secrets backend to test its features.")
+(require 'secrets)
(defun auth-source-ensure-ignored-backend (source)
(auth-source-validate-backend source '((:source . "")
@@ -210,6 +209,25 @@
("login" . "user1")
("machine" . "mymachine1"))))))
+(ert-deftest auth-source-test-netrc-parse-one ()
+ (should (equal (auth-source--test-netrc-parse-one--all
+ "machine host1\n# comment\n")
+ '("machine" "host1")))
+ (should (equal (auth-source--test-netrc-parse-one--all
+ "machine host1\n \n \nmachine host2\n")
+ '("machine" "host1" "machine" "host2"))))
+
+(defun auth-source--test-netrc-parse-one--all (text)
+ "Parse TEXT with `auth-source-netrc-parse-one' until end,return list."
+ (with-temp-buffer
+ (insert text)
+ (goto-char (point-min))
+ (let ((one (auth-source-netrc-parse-one)) all)
+ (while one
+ (push one all)
+ (setq one (auth-source-netrc-parse-one)))
+ (nreverse all))))
+
(ert-deftest auth-source-test-format-prompt ()
(should (equal (auth-source-format-prompt "test %u %h %p" '((?u "user") (?h "host")))
"test user host %p")))
@@ -230,7 +248,7 @@
(should-not (auth-source-remembered-p '(:host t)))))
(ert-deftest auth-source-test-searches ()
- "Test auth-source searches with various parameters"
+ "Test auth-source searches with various parameters."
:tags '(auth-source auth-source/netrc)
(let* ((entries '("machine a1 port a2 user a3 password a4"
"machine b1 port b2 user b3 password b4"
@@ -260,34 +278,161 @@
"((:host \"a1\" :port \"a2\" :user \"a3\" :secret \"a4\") (:host \"b1\" :port \"b2\" :user \"b3\" :secret \"b4\") (:host \"c1\" :port \"c2\" :user \"c3\" :secret \"c4\"))"
:host t :max 4)
("host b1, default max is 1"
- "((:host \"b1\" :port \"b2\" :user \"b3\" :secret \"b4\"))"
+ "((:host \"b1\" :port \"b2\" :user \"b3\" :secret \"b4\"))"
:host "b1")
("host b1, port b2, user b3, default max is 1"
- "((:host \"b1\" :port \"b2\" :user \"b3\" :secret \"b4\"))"
+ "((:host \"b1\" :port \"b2\" :user \"b3\" :secret \"b4\"))"
:host "b1" :port "b2" :user "b3")
- ))
-
- (netrc-file (make-temp-file "auth-source-test" nil nil
- (mapconcat 'identity entries "\n")))
- (auth-sources (list netrc-file))
- (auth-source-do-cache nil)
- found found-as-string)
-
- (dolist (test tests)
- (cl-destructuring-bind (testname needed &rest parameters) test
- (setq found (apply #'auth-source-search parameters))
- (when (listp found)
- (dolist (f found)
- (setf f (plist-put f :secret
- (let ((secret (plist-get f :secret)))
- (if (functionp secret)
- (funcall secret)
- secret))))))
-
- (setq found-as-string (format "%s: %S" testname found))
- ;; (message "With parameters %S found: [%s] needed: [%s]" parameters found-as-string needed)
- (should (equal found-as-string (concat testname ": " needed)))))
- (delete-file netrc-file)))
+ )))
+ (ert-with-temp-file netrc-file
+ :text (mapconcat 'identity entries "\n")
+ (let ((auth-sources (list netrc-file))
+ (auth-source-do-cache nil)
+ found found-as-string)
+
+ (dolist (test tests)
+ (cl-destructuring-bind (testname needed &rest parameters) test
+ (setq found (apply #'auth-source-search parameters))
+ (when (listp found)
+ (dolist (f found)
+ (setf f (plist-put f :secret (auth-info-password f)))))
+
+ (setq found-as-string (format "%s: %S" testname found))
+ ;; (message "With parameters %S found: [%s] needed: [%s]"
+ ;; parameters found-as-string needed)
+ (should (equal found-as-string (concat testname ": " needed)))))))))
+
+(ert-deftest auth-source-test-secrets-create-secret ()
+ (skip-unless secrets-enabled)
+ ;; The "session" collection is temporary for the lifetime of the
+ ;; Emacs process. Therefore, we don't care to delete it.
+ (let ((auth-sources '((:source (:secrets "session"))))
+ (auth-source-save-behavior t)
+ host auth-info auth-passwd)
+ (dolist (passwd '("foo" "" nil))
+ (unwind-protect
+ ;; Redefine `read-*' in order to avoid interactive input.
+ (cl-letf (((symbol-function 'read-passwd) (lambda (_) passwd))
+ ((symbol-function 'read-string)
+ (lambda (_prompt &optional _initial _history default
+ _inherit-input-method)
+ default)))
+ (setq host
+ (md5 (concat (prin1-to-string process-environment) passwd))
+ auth-info
+ (car (auth-source-search
+ :max 1 :host host :require '(:user :secret) :create t))
+ auth-passwd (auth-info-password auth-info))
+ (should (string-equal (plist-get auth-info :user) (user-login-name)))
+ (should (string-equal (plist-get auth-info :host) host))
+ (should (equal auth-passwd passwd))
+ (when (functionp (plist-get auth-info :save-function))
+ (funcall (plist-get auth-info :save-function)))
+
+ ;; Check, that the item has been created indeed.
+ (auth-source-forget+ :host t)
+ (setq auth-info (car (auth-source-search :host host))
+ auth-passwd (auth-info-password auth-info))
+ (if (zerop (length passwd))
+ (progn
+ (should-not (plist-get auth-info :user))
+ (should-not (plist-get auth-info :host))
+ (should-not auth-passwd))
+ (should
+ (string-equal (plist-get auth-info :user) (user-login-name)))
+ (should (string-equal (plist-get auth-info :host) host))
+ (should (string-equal auth-passwd passwd)))))
+
+ ;; Cleanup.
+ ;; Should use `auth-source-delete' when implemented for :secrets backend.
+ (secrets-delete-item
+ "session"
+ (format "%s@%s" (plist-get auth-info :user) (plist-get auth-info :host))))))
+
+(ert-deftest auth-source-test-netrc-create-secret ()
+ (ert-with-temp-file netrc-file
+ :suffix "auth-source-test"
+ (let* ((auth-sources (list netrc-file))
+ (auth-source-save-behavior t)
+ host auth-info auth-passwd)
+ (dolist (passwd '("foo" "" nil))
+ ;; Redefine `read-*' in order to avoid interactive input.
+ (cl-letf (((symbol-function 'read-passwd) (lambda (_) passwd))
+ ((symbol-function 'read-string)
+ (lambda (_prompt &optional _initial _history default
+ _inherit-input-method)
+ default)))
+ (setq host
+ (md5 (concat (prin1-to-string process-environment) passwd))
+ auth-info
+ (car (auth-source-search
+ :max 1 :host host :require '(:user :secret) :create t))
+ auth-passwd (auth-info-password auth-info))
+ (should (string-equal (plist-get auth-info :user) (user-login-name)))
+ (should (string-equal (plist-get auth-info :host) host))
+ (should (equal auth-passwd passwd))
+ (when (functionp (plist-get auth-info :save-function))
+ (funcall (plist-get auth-info :save-function)))
+
+ ;; Check, that the item has been created indeed.
+ (auth-source-forget+ :host t)
+ (setq auth-source-netrc-cache nil)
+ (setq auth-info (car (auth-source-search :host host))
+ auth-passwd (auth-info-password auth-info))
+ (with-temp-buffer
+ (insert-file-contents netrc-file)
+ (if (zerop (length passwd))
+ (progn
+ (should-not (plist-get auth-info :user))
+ (should-not (plist-get auth-info :host))
+ (should-not auth-passwd)
+ (should-not (search-forward host nil 'noerror)))
+ (should
+ (string-equal (plist-get auth-info :user) (user-login-name)))
+ (should (string-equal (plist-get auth-info :host) host))
+ (should (string-equal auth-passwd passwd))
+ (should (search-forward host nil 'noerror)))))))))
+
+(ert-deftest auth-source-delete ()
+ (ert-with-temp-file netrc-file
+ :suffix "auth-source-test" :text "\
+machine a1 port a2 user a3 password a4
+machine b1 port b2 user b3 password b4
+machine c1 port c2 user c3 password c4\n"
+ (let* ((auth-sources (list netrc-file))
+ (auth-source-do-cache nil)
+ (expected '((:host "a1" :port "a2" :user "a3" :secret "a4")))
+ (parameters '(:max 1 :host t))
+ (found (apply #'auth-source-delete parameters)))
+ (dolist (f found)
+ (setf f (plist-put f :secret (auth-info-password f))))
+ ;; Note: The netrc backend doesn't delete anything, so
+ ;; this is actually the same as `auth-source-search'.
+ (should (equal found expected)))))
+
+(ert-deftest test-netrc-credentials ()
+ (let ((data (auth-source-netrc-parse-all (ert-resource-file "authinfo"))))
+ (should data)
+ (let ((imap (seq-find (lambda (elem)
+ (equal (cdr (assoc "machine" elem))
+ "imap.example.org"))
+ data)))
+ (should (equal (cdr (assoc "login" imap)) "jrh@example.org"))
+ (should (equal (cdr (assoc "password" imap)) "*foobar*")))
+ (let ((imap (seq-find (lambda (elem)
+ (equal (cdr (assoc "machine" elem))
+ "ftp.example.org"))
+ data)))
+ (should (equal (cdr (assoc "login" imap)) "jrh"))
+ (should (equal (cdr (assoc "password" imap)) "*baz*")))))
+
+(ert-deftest test-netrc-credentials-2 ()
+ (let ((data (auth-source-netrc-parse-all
+ (ert-resource-file "netrc-folding"))))
+ (should
+ (equal data
+ '((("machine" . "XM") ("login" . "XL") ("password" . "XP"))
+ (("machine" . "YM") ("login" . "YL") ("password" . "YP")))))))
(provide 'auth-source-tests)
;;; auth-source-tests.el ends here
diff --git a/test/lisp/autoinsert-tests.el b/test/lisp/autoinsert-tests.el
new file mode 100644
index 00000000000..722215cb7e4
--- /dev/null
+++ b/test/lisp/autoinsert-tests.el
@@ -0,0 +1,103 @@
+;;; autoinsert-tests.el --- Tests for autoinsert.el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2019-2022 Free Software Foundation, Inc.
+
+;; Author: Simen Heggestøyl <simenheg@gmail.com>
+;; Keywords:
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;
+
+;;; Code:
+
+(require 'autoinsert)
+(require 'ert)
+(require 'ert-x)
+
+(ert-deftest autoinsert-tests-auto-insert-skeleton ()
+ (let ((auto-insert-alist '((text-mode nil "f" _ "oo")))
+ (auto-insert-query nil))
+ (with-temp-buffer
+ (text-mode)
+ (auto-insert)
+ (should (equal (buffer-string) "foo"))
+ (should (equal (point) (+ (point-min) 1))))))
+
+(ert-deftest autoinsert-tests-auto-insert-file ()
+ (ert-with-temp-file temp-file
+ :text "foo"
+ (let ((auto-insert-alist `((text-mode . ,temp-file)))
+ (auto-insert-query nil))
+ (with-temp-buffer
+ (text-mode)
+ (auto-insert)
+ (should (equal (buffer-string) "foo"))))))
+
+(ert-deftest autoinsert-tests-auto-insert-function ()
+ (let ((auto-insert-alist '((text-mode . (lambda () (insert "foo")))))
+ (auto-insert-query nil))
+ (with-temp-buffer
+ (text-mode)
+ (auto-insert)
+ (should (equal (buffer-string) "foo")))))
+
+(ert-deftest autoinsert-tests-auto-insert-vector ()
+ (let ((auto-insert-alist '((text-mode . [(nil "f" _ "bar")
+ (lambda () (insert "oo"))])))
+ (auto-insert-query nil))
+ (with-temp-buffer
+ (text-mode)
+ (auto-insert)
+ (should (equal (buffer-string) "foobar")))))
+
+(ert-deftest autoinsert-tests-auto-insert-regexp-match ()
+ (let ((auto-insert-alist '(("foobar" nil "1st")
+ ("fo+bar" nil "2nd")
+ ("fo*bar" nil "3rd")))
+ (auto-insert-query nil))
+ (with-temp-buffer
+ (setq-local buffer-file-name "fooobar")
+ (auto-insert)
+ (should (equal (buffer-string) "2nd")))))
+
+(ert-deftest autoinsert-tests-define-auto-insert-before ()
+ (let ((auto-insert-alist
+ (list (cons 'text-mode (lambda () (insert "foo")))))
+ (auto-insert-query nil))
+ (define-auto-insert 'text-mode
+ (lambda () (insert "bar")))
+ (with-temp-buffer
+ (text-mode)
+ (auto-insert)
+ (should (equal (buffer-string) "barfoo")))))
+
+(ert-deftest autoinsert-tests-define-auto-insert-after ()
+ (let ((auto-insert-alist
+ (list (cons 'text-mode (lambda () (insert "foo")))))
+ (auto-insert-query nil))
+ (define-auto-insert 'text-mode
+ (lambda () (insert "bar"))
+ t)
+ (with-temp-buffer
+ (text-mode)
+ (auto-insert)
+ (should (equal (buffer-string) "foobar")))))
+
+(provide 'autoinsert-tests)
+;;; autoinsert-tests.el ends here
diff --git a/test/lisp/autorevert-tests.el b/test/lisp/autorevert-tests.el
index 55dbb341aa0..4bbff6d0578 100644
--- a/test/lisp/autorevert-tests.el
+++ b/test/lisp/autorevert-tests.el
@@ -1,305 +1,661 @@
-;;; auto-revert-tests.el --- Tests of auto-revert
+;;; autorevert-tests.el --- Tests of auto-revert -*- lexical-binding: t -*-
-;; Copyright (C) 2015-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2022 Free Software Foundation, Inc.
;; Author: Michael Albinus <michael.albinus@gmx.de>
-;; This program is free software: you can redistribute it and/or
+;; This file is part of GNU Emacs.
+;;
+;; GNU Emacs is free software: you can redistribute it and/or
;; modify it under the terms of the GNU General Public License as
;; published by the Free Software Foundation, either version 3 of the
;; License, or (at your option) any later version.
;;
-;; This program is distributed in the hope that it will be useful, but
+;; GNU Emacs is distributed in the hope that it will be useful, but
;; WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
;; General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
-;; along with this program. If not, see `https://www.gnu.org/licenses/'.
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
+;; Some of the tests require access to a remote host files. Since
+;; this could be problematic, a mock-up connection method "mock" is
+;; used. Emulating a remote connection, it simply calls "sh -i".
+;; Tramp's file name handlers still run, so this test is sufficient
+;; except for connection establishing.
+
+;; If you want to test a real Tramp connection, set
+;; $REMOTE_TEMPORARY_FILE_DIRECTORY to a suitable value in order to
+;; overwrite the default value. If you want to skip tests accessing a
+;; remote host, set this environment variable to "/dev/null" or
+;; whatever is appropriate on your system.
+
+;; For the remote file-notify library, Tramp checks for the existence
+;; of a respective command. The first command found is used. In
+;; order to use a dedicated one, the environment variable
+;; $REMOTE_FILE_NOTIFY_LIBRARY shall be set, possible values are
+;; "inotifywait", "gio-monitor" and "gvfs-monitor-dir".
+
+;; Local file-notify libraries are auto-detected during Emacs
+;; configuration. This can be changed with a respective configuration
+;; argument, like
+;;
+;; --with-file-notification=inotify
+;; --with-file-notification=kqueue
+;; --with-file-notification=gfile
+;; --with-file-notification=w32
+
;; A whole test run can be performed calling the command `auto-revert-test-all'.
;;; Code:
-(require 'ert)
+(require 'tramp)
(require 'ert-x)
(require 'autorevert)
-(setq auto-revert-notify-exclude-dir-regexp "nothing-to-be-excluded"
- auto-revert-stop-on-user-input nil)
-(defconst auto-revert--timeout 10
- "Time to wait for a message.")
+(setq auto-revert-debug nil
+ auto-revert-notify-exclude-dir-regexp "nothing-to-be-excluded"
+ auto-revert-stop-on-user-input nil
+ file-notify-debug nil
+ tramp-verbose 0)
+
+(defun auto-revert--timeout ()
+ "Time to wait for a message."
+ (+ auto-revert-interval 0.1))
(defvar auto-revert--messages nil
"Used to collect messages issued during a section of a test.")
+;; Filter suppressed remote file-notify libraries.
+(when (stringp (getenv "REMOTE_FILE_NOTIFY_LIBRARY"))
+ (dolist (lib '("inotifywait" "gio-monitor" "gvfs-monitor-dir"))
+ (unless (string-equal (getenv "REMOTE_FILE_NOTIFY_LIBRARY") lib)
+ (add-to-list 'tramp-connection-properties `(nil ,lib nil)))))
+
+(defvar auto-revert--test-enabled-remote-checked nil
+ "Cached result of `auto-revert--test-enabled-remote'.
+If the function did run, the value is a cons cell, the `cdr'
+being the result.")
+
+(defun auto-revert--test-enabled-remote ()
+ "Whether remote file access is enabled."
+ (unless (consp auto-revert--test-enabled-remote-checked)
+ (setq
+ auto-revert--test-enabled-remote-checked
+ (cons
+ t (ignore-errors
+ (and
+ (not (getenv "EMACS_HYDRA_CI"))
+ (file-remote-p ert-remote-temporary-file-directory)
+ (file-directory-p ert-remote-temporary-file-directory)
+ (file-writable-p ert-remote-temporary-file-directory))))))
+ ;; Return result.
+ (cdr auto-revert--test-enabled-remote-checked))
+
(defun auto-revert--wait-for-revert (buffer)
"Wait until a message reports reversion of BUFFER.
This expects `auto-revert--messages' to be bound by
`ert-with-message-capture' before calling."
- (with-timeout (auto-revert--timeout nil)
- (while
- (null (string-match
- (format-message "Reverting buffer `%s'." (buffer-name buffer))
- auto-revert--messages))
- (if (with-current-buffer buffer auto-revert-use-notify)
- (read-event nil nil 0.1)
- (sleep-for 0.1)))))
+ ;; Remote files do not cooperate well with timers. So we count ourselves.
+ (let ((ct (current-time)))
+ (while (and (< (float-time (time-subtract nil ct))
+ (auto-revert--timeout))
+ (null (string-match
+ (format-message
+ "Reverting buffer `%s'" (buffer-name buffer))
+ (or auto-revert--messages ""))))
+ (if (and (or file-notify--library
+ (file-remote-p temporary-file-directory))
+ (with-current-buffer buffer auto-revert-use-notify))
+ (read-event nil nil 0.05)
+ (sleep-for 0.05)))))
+
+(defmacro auto-revert--deftest-remote (test docstring)
+ "Define ert `TEST-remote' for remote files."
+ (declare (indent 1))
+ `(ert-deftest ,(intern (concat (symbol-name test) "-remote")) ()
+ ,docstring
+ :tags '(:expensive-test :unstable)
+ (let ((temporary-file-directory
+ ert-remote-temporary-file-directory)
+ (auto-revert-remote-files t)
+ (ert-test (ert-get-test ',test))
+ vc-handled-backends)
+ (skip-unless (auto-revert--test-enabled-remote))
+ (tramp-cleanup-connection
+ (tramp-dissect-file-name temporary-file-directory) nil 'keep-password)
+ (condition-case err
+ (funcall (ert-test-body ert-test))
+ (error (message "%s" err) (signal (car err) (cdr err)))))))
+
+(defmacro with-auto-revert-test (&rest body)
+ `(let ((auto-revert-interval-orig auto-revert-interval))
+ (unwind-protect
+ (progn
+ (customize-set-variable 'auto-revert-interval 0.1)
+ ,@body)
+ (customize-set-variable 'auto-revert-interval auto-revert-interval-orig))))
+
+(defun auto-revert-tests--write-file (text file time-delta &optional append)
+ (write-region text nil file append 'no-message)
+ (set-file-times file (time-subtract nil time-delta)))
(ert-deftest auto-revert-test00-auto-revert-mode ()
"Check autorevert for a file."
;; `auto-revert-buffers' runs every 5". And we must wait, until the
;; file has been reverted.
- (let ((tmpfile (make-temp-file "auto-revert-test"))
- buf)
- (unwind-protect
- (progn
- (write-region "any text" nil tmpfile nil 'no-message)
- (setq buf (find-file-noselect tmpfile))
- (with-current-buffer buf
- (ert-with-message-capture auto-revert--messages
- (should (string-equal (buffer-string) "any text"))
- ;; `buffer-stale--default-function' checks for
- ;; `verify-visited-file-modtime'. We must ensure that it
- ;; returns nil.
- (sleep-for 1)
- (auto-revert-mode 1)
- (should auto-revert-mode)
-
- ;; Modify file. We wait for a second, in order to have
- ;; another timestamp.
- (sleep-for 1)
- (write-region "another text" nil tmpfile nil 'no-message)
-
- ;; Check, that the buffer has been reverted.
- (auto-revert--wait-for-revert buf))
- (should (string-match "another text" (buffer-string)))
-
- ;; When the buffer is modified, it shall not be reverted.
- (ert-with-message-capture auto-revert--messages
- (set-buffer-modified-p t)
- (sleep-for 1)
- (write-region "any text" nil tmpfile nil 'no-message)
-
- ;; Check, that the buffer hasn't been reverted.
- (auto-revert--wait-for-revert buf))
- (should-not (string-match "any text" (buffer-string)))))
-
- ;; Exit.
- (ignore-errors
- (with-current-buffer buf (set-buffer-modified-p nil))
- (kill-buffer buf))
- (ignore-errors (delete-file tmpfile)))))
+ (with-auto-revert-test
+ (ert-with-temp-file tmpfile
+ (let ((times '(60 30 15))
+ buf)
+ (unwind-protect
+ (progn
+ (auto-revert-tests--write-file "any text" tmpfile (pop times))
+ (setq buf (find-file-noselect tmpfile))
+ (with-current-buffer buf
+ (ert-with-message-capture auto-revert--messages
+ (should (string-equal (buffer-string) "any text"))
+ ;; `buffer-stale--default-function' checks for
+ ;; `verify-visited-file-modtime'. We must ensure that it
+ ;; returns nil.
+ (auto-revert-mode 1)
+ (should auto-revert-mode)
+
+ (auto-revert-tests--write-file "another text" tmpfile (pop times))
+
+ ;; Check, that the buffer has been reverted.
+ (auto-revert--wait-for-revert buf))
+ (should (string-match "another text" (buffer-string)))
+
+ ;; When the buffer is modified, it shall not be reverted.
+ (ert-with-message-capture auto-revert--messages
+ (set-buffer-modified-p t)
+ (auto-revert-tests--write-file "any text" tmpfile (pop times))
+
+ ;; Check, that the buffer hasn't been reverted.
+ (auto-revert--wait-for-revert buf))
+ (should-not (string-match "any text" (buffer-string)))))
+
+ ;; Exit.
+ (ignore-errors
+ (with-current-buffer buf (set-buffer-modified-p nil))
+ (kill-buffer buf)))))))
+
+(auto-revert--deftest-remote auto-revert-test00-auto-revert-mode
+ "Check autorevert for a remote file.")
;; This is inspired by Bug#21841.
(ert-deftest auto-revert-test01-auto-revert-several-files ()
"Check autorevert for several files at once."
- :tags '(:expensive-test)
- (skip-unless (executable-find "cp"))
-
- (let* ((cp (executable-find "cp"))
- (tmpdir1 (make-temp-file "auto-revert-test" 'dir))
- (tmpdir2 (make-temp-file "auto-revert-test" 'dir))
- (tmpfile1
- (make-temp-file (expand-file-name "auto-revert-test" tmpdir1)))
- (tmpfile2
- (make-temp-file (expand-file-name "auto-revert-test" tmpdir1)))
- buf1 buf2)
- (unwind-protect
- (ert-with-message-capture auto-revert--messages
- (write-region "any text" nil tmpfile1 nil 'no-message)
- (setq buf1 (find-file-noselect tmpfile1))
- (write-region "any text" nil tmpfile2 nil 'no-message)
- (setq buf2 (find-file-noselect tmpfile2))
-
- (dolist (buf (list buf1 buf2))
- (with-current-buffer buf
- (should (string-equal (buffer-string) "any text"))
- ;; `buffer-stale--default-function' checks for
- ;; `verify-visited-file-modtime'. We must ensure that
- ;; it returns nil.
- (sleep-for 1)
- (auto-revert-mode 1)
- (should auto-revert-mode)))
-
- ;; Modify files. We wait for a second, in order to have
- ;; another timestamp.
- (sleep-for 1)
- (write-region
- "another text" nil
- (expand-file-name (file-name-nondirectory tmpfile1) tmpdir2)
- nil 'no-message)
- (write-region
- "another text" nil
- (expand-file-name (file-name-nondirectory tmpfile2) tmpdir2)
- nil 'no-message)
- ;;(copy-directory tmpdir2 tmpdir1 nil 'copy-contents)
- ;; Strange, that `copy-directory' does not work as expected.
- ;; The following shell command is not portable on all
- ;; platforms, unfortunately.
- (shell-command (format "%s -f %s/* %s" cp tmpdir2 tmpdir1))
-
- ;; Check, that the buffers have been reverted.
- (dolist (buf (list buf1 buf2))
- (with-current-buffer buf
- (auto-revert--wait-for-revert buf)
- (should (string-match "another text" (buffer-string))))))
-
- ;; Exit.
- (ignore-errors
- (dolist (buf (list buf1 buf2))
- (with-current-buffer buf (set-buffer-modified-p nil))
- (kill-buffer buf)))
- (ignore-errors (delete-directory tmpdir1 'recursive))
- (ignore-errors (delete-directory tmpdir2 'recursive)))))
+ (skip-unless (executable-find "cp" (file-remote-p temporary-file-directory)))
+
+ (ert-with-temp-directory tmpdir1
+ (ert-with-temp-directory tmpdir2
+ (ert-with-temp-file tmpfile1
+ :prefix (expand-file-name "auto-revert-test" tmpdir1)
+ (ert-with-temp-file tmpfile2
+ :prefix (expand-file-name "auto-revert-test" tmpdir1)
+ (with-auto-revert-test
+ (let* ((cp (executable-find "cp" (file-remote-p temporary-file-directory)))
+ (times '(120 60 30 15))
+ buf1 buf2)
+ (unwind-protect
+ (ert-with-message-capture auto-revert--messages
+ (auto-revert-tests--write-file "any text" tmpfile1 (pop times))
+ (setq buf1 (find-file-noselect tmpfile1))
+ (auto-revert-tests--write-file "any text" tmpfile2 (pop times))
+ (setq buf2 (find-file-noselect tmpfile2))
+
+ (dolist (buf (list buf1 buf2))
+ (with-current-buffer buf
+ (should (string-equal (buffer-string) "any text"))
+ ;; `buffer-stale--default-function' checks for
+ ;; `verify-visited-file-modtime'. We must ensure that
+ ;; it returns nil.
+ (auto-revert-mode 1)
+ (should auto-revert-mode)))
+
+ ;; Modify files. We wait for a second, in order to have
+ ;; another timestamp.
+ (auto-revert-tests--write-file
+ "another text"
+ (expand-file-name (file-name-nondirectory tmpfile1) tmpdir2)
+ (pop times))
+ (auto-revert-tests--write-file
+ "another text"
+ (expand-file-name (file-name-nondirectory tmpfile2) tmpdir2)
+ (pop times))
+ ;;(copy-directory tmpdir2 tmpdir1 nil 'copy-contents)
+ ;; Strange, that `copy-directory' does not work as expected.
+ ;; The following shell command is not portable on all
+ ;; platforms, unfortunately.
+ (shell-command
+ (format "%s -f %s/* %s"
+ cp (file-local-name tmpdir2) (file-local-name tmpdir1)))
+
+ ;; Check, that the buffers have been reverted.
+ (dolist (buf (list buf1 buf2))
+ (with-current-buffer buf
+ (auto-revert--wait-for-revert buf)
+ (should (string-match "another text" (buffer-string))))))
+
+ ;; Exit.
+ (ignore-errors
+ (dolist (buf (list buf1 buf2))
+ (with-current-buffer buf (set-buffer-modified-p nil))
+ (kill-buffer buf)))))))))))
+
+(auto-revert--deftest-remote auto-revert-test01-auto-revert-several-files
+ "Check autorevert for several remote files at once.")
;; This is inspired by Bug#23276.
(ert-deftest auto-revert-test02-auto-revert-deleted-file ()
"Check autorevert for a deleted file."
- :tags '(:expensive-test)
-
- (let ((tmpfile (make-temp-file "auto-revert-test"))
- buf)
- (unwind-protect
- (progn
- (write-region "any text" nil tmpfile nil 'no-message)
- (setq buf (find-file-noselect tmpfile))
- (with-current-buffer buf
- (should (string-equal (buffer-string) "any text"))
- ;; `buffer-stale--default-function' checks for
- ;; `verify-visited-file-modtime'. We must ensure that
- ;; it returns nil.
- (sleep-for 1)
- (auto-revert-mode 1)
- (should auto-revert-mode)
-
- ;; Remove file while reverting. We simulate this by
- ;; modifying `before-revert-hook'.
- (add-hook
- 'before-revert-hook
- (lambda () (delete-file buffer-file-name))
- nil t)
-
- (ert-with-message-capture auto-revert--messages
- (sleep-for 1)
- (write-region "another text" nil tmpfile nil 'no-message)
- (auto-revert--wait-for-revert buf))
- ;; Check, that the buffer hasn't been reverted. File
- ;; notification should be disabled, falling back to
- ;; polling.
- (should (string-match "any text" (buffer-string)))
- ;; With w32notify, the 'stopped' events are not sent.
- (or (eq file-notify--library 'w32notify)
- (should-not auto-revert-use-notify))
-
- ;; Once the file has been recreated, the buffer shall be
- ;; reverted.
- (kill-local-variable 'before-revert-hook)
- (ert-with-message-capture auto-revert--messages
- (sleep-for 1)
- (write-region "another text" nil tmpfile nil 'no-message)
- (auto-revert--wait-for-revert buf))
- ;; Check, that the buffer has been reverted.
- (should (string-match "another text" (buffer-string)))
-
- ;; An empty file shall still be reverted.
- (ert-with-message-capture auto-revert--messages
- (sleep-for 1)
- (write-region "" nil tmpfile nil 'no-message)
- (auto-revert--wait-for-revert buf))
- ;; Check, that the buffer has been reverted.
- (should (string-equal "" (buffer-string)))))
-
- ;; Exit.
- (ignore-errors
- (with-current-buffer buf (set-buffer-modified-p nil))
- (kill-buffer buf))
- (ignore-errors (delete-file tmpfile)))))
+ ;; Repeated unpredictable failures, bug#32645.
+ :tags '(:unstable)
+ ;; Unlikely to be hydra-specific?
+ ;; (skip-unless (not (getenv "EMACS_HYDRA_CI")))
+ (with-auto-revert-test
+ (ert-with-temp-file tmpfile
+ (let (;; Try to catch bug#32645.
+ (auto-revert-debug (getenv "EMACS_HYDRA_CI"))
+ (file-notify-debug (getenv "EMACS_HYDRA_CI"))
+ (times '(120 60 30 15))
+ buf desc)
+ (unwind-protect
+ (progn
+ (auto-revert-tests--write-file "any text" tmpfile (pop times))
+ (setq buf (find-file-noselect tmpfile))
+ (with-current-buffer buf
+ (should-not
+ (file-notify-valid-p auto-revert-notify-watch-descriptor))
+ (should (string-equal (buffer-string) "any text"))
+ ;; `buffer-stale--default-function' checks for
+ ;; `verify-visited-file-modtime'. We must ensure that
+ ;; it returns nil.
+ (auto-revert-mode 1)
+ (should auto-revert-mode)
+ (setq desc auto-revert-notify-watch-descriptor)
+
+ ;; Remove file while reverting. We simulate this by
+ ;; modifying `before-revert-hook'.
+ (add-hook
+ 'before-revert-hook
+ (lambda ()
+ (when auto-revert-debug
+ (message "%s deleted" buffer-file-name))
+ (delete-file buffer-file-name))
+ nil t)
+
+ (ert-with-message-capture auto-revert--messages
+ (auto-revert-tests--write-file "another text" tmpfile (pop times))
+ (auto-revert--wait-for-revert buf))
+ ;; Check, that the buffer hasn't been reverted. File
+ ;; notification should be disabled, falling back to
+ ;; polling.
+ (should (string-match "any text" (buffer-string)))
+ ;; With w32notify, and on emba, the `stopped' events are not sent.
+ (or (eq file-notify--library 'w32notify)
+ (getenv "EMACS_EMBA_CI")
+ (should-not
+ (file-notify-valid-p auto-revert-notify-watch-descriptor)))
+
+ ;; Once the file has been recreated, the buffer shall be
+ ;; reverted.
+ (kill-local-variable 'before-revert-hook)
+ (ert-with-message-capture auto-revert--messages
+ (auto-revert-tests--write-file "another text" tmpfile (pop times))
+ (auto-revert--wait-for-revert buf))
+ ;; Check, that the buffer has been reverted.
+ (should (string-match "another text" (buffer-string)))
+ ;; When file notification is used, it must be reenabled
+ ;; after recreation of the file. We cannot expect that
+ ;; the descriptor is the same, so we just check the
+ ;; existence.
+ (should (eq (null desc) (null auto-revert-notify-watch-descriptor)))
+
+ ;; An empty file shall still be reverted.
+ (ert-with-message-capture auto-revert--messages
+ (auto-revert-tests--write-file "" tmpfile (pop times))
+ (auto-revert--wait-for-revert buf))
+ ;; Check, that the buffer has been reverted.
+ (should (string-equal "" (buffer-string)))))
+
+ ;; Exit.
+ (ignore-errors
+ (with-current-buffer buf (set-buffer-modified-p nil))
+ (kill-buffer buf)))))))
+
+(auto-revert--deftest-remote auto-revert-test02-auto-revert-deleted-file
+ "Check autorevert for a deleted remote file.")
(ert-deftest auto-revert-test03-auto-revert-tail-mode ()
"Check autorevert tail mode."
;; `auto-revert-buffers' runs every 5". And we must wait, until the
;; file has been reverted.
- (let ((tmpfile (make-temp-file "auto-revert-test"))
- buf)
- (unwind-protect
- (ert-with-message-capture auto-revert--messages
- (write-region "any text" nil tmpfile nil 'no-message)
- (setq buf (find-file-noselect tmpfile))
- (with-current-buffer buf
- ;; `buffer-stale--default-function' checks for
- ;; `verify-visited-file-modtime'. We must ensure that it
- ;; returns nil.
- (sleep-for 1)
- (auto-revert-tail-mode 1)
- (should auto-revert-tail-mode)
- (erase-buffer)
- (insert "modified text\n")
- (set-buffer-modified-p nil)
-
- ;; Modify file. We wait for a second, in order to have
- ;; another timestamp.
- (sleep-for 1)
- (write-region "another text" nil tmpfile 'append 'no-message)
-
- ;; Check, that the buffer has been reverted.
- (auto-revert--wait-for-revert buf)
- (should
- (string-match "modified text\nanother text" (buffer-string)))))
-
- ;; Exit.
- (ignore-errors (kill-buffer buf))
- (ignore-errors (delete-file tmpfile)))))
+ (ert-with-temp-file tmpfile
+ (let ((times '(30 15))
+ buf)
+ (unwind-protect
+ (ert-with-message-capture auto-revert--messages
+ (auto-revert-tests--write-file "any text" tmpfile (pop times))
+ (setq buf (find-file-noselect tmpfile))
+ (with-current-buffer buf
+ ;; `buffer-stale--default-function' checks for
+ ;; `verify-visited-file-modtime'. We must ensure that it
+ ;; returns nil.
+ (auto-revert-tail-mode 1)
+ (should auto-revert-tail-mode)
+ (erase-buffer)
+ (insert "modified text\n")
+ (set-buffer-modified-p nil)
+
+ ;; Modify file.
+ (auto-revert-tests--write-file "another text" tmpfile (pop times) 'append)
+
+ ;; Check, that the buffer has been reverted.
+ (auto-revert--wait-for-revert buf)
+ (should
+ (string-match "modified text\nanother text" (buffer-string)))))
+
+ ;; Exit.
+ (ignore-errors (kill-buffer buf))))))
+
+(auto-revert--deftest-remote auto-revert-test03-auto-revert-tail-mode
+ "Check remote autorevert tail mode.")
(ert-deftest auto-revert-test04-auto-revert-mode-dired ()
"Check autorevert for dired."
;; `auto-revert-buffers' runs every 5". And we must wait, until the
;; file has been reverted.
- (let* ((tmpfile (make-temp-file "auto-revert-test"))
- (name (file-name-nondirectory tmpfile))
- buf)
- (unwind-protect
- (progn
- (setq buf (dired-noselect temporary-file-directory))
- (with-current-buffer buf
- ;; `buffer-stale--default-function' checks for
- ;; `verify-visited-file-modtime'. We must ensure that it
- ;; returns nil.
- (sleep-for 1)
- (auto-revert-mode 1)
- (should auto-revert-mode)
- (should
- (string-match name (substring-no-properties (buffer-string))))
-
- (ert-with-message-capture auto-revert--messages
- ;; Delete file. We wait for a second, in order to have
- ;; another timestamp.
- (sleep-for 1)
- (delete-file tmpfile)
- (auto-revert--wait-for-revert buf))
+ (with-auto-revert-test
+ (ert-with-temp-file tmpfile
+ (let* ((name (file-name-nondirectory tmpfile))
+ (times '(30))
+ buf)
+ (unwind-protect
+ (progn
+ (setq buf (dired-noselect temporary-file-directory))
+ (with-current-buffer buf
+ ;; `buffer-stale--default-function' checks for
+ ;; `verify-visited-file-modtime'. We must ensure that it
+ ;; returns nil.
+ (auto-revert-mode 1)
+ (should auto-revert-mode)
+ (should
+ (string-match name (substring-no-properties (buffer-string))))
+
+ (ert-with-message-capture auto-revert--messages
+ ;; Delete file.
+ (delete-file tmpfile)
+ (auto-revert--wait-for-revert buf))
+ ;; Check, that the buffer has been reverted.
+ (should-not
+ (string-match name (substring-no-properties (buffer-string))))
+
+ (ert-with-message-capture auto-revert--messages
+ ;; Make dired buffer modified. Check, that the buffer has
+ ;; been still reverted.
+ (set-buffer-modified-p t)
+ (auto-revert-tests--write-file "any text" tmpfile (pop times))
+
+ (auto-revert--wait-for-revert buf))
+ ;; Check, that the buffer has been reverted.
+ (should
+ (string-match name (substring-no-properties (buffer-string))))))
+
+ ;; Exit.
+ (ignore-errors
+ (with-current-buffer buf (set-buffer-modified-p nil))
+ (kill-buffer buf)))))))
+
+(auto-revert--deftest-remote auto-revert-test04-auto-revert-mode-dired
+ "Check remote autorevert for dired.")
+
+(defun auto-revert-test--write-file (string file)
+ "Write STRING to FILE."
+ (write-region string nil file nil 'no-message))
+
+(defun auto-revert-test--buffer-string (buffer)
+ "Contents of BUFFER as a string."
+ (with-current-buffer buffer
+ (buffer-string)))
+
+(defun auto-revert-test--wait-for (pred max-wait)
+ "Wait until PRED is true, or MAX-WAIT seconds elapsed."
+ (let ((ct (current-time)))
+ (while (and (< (float-time (time-subtract nil ct)) max-wait)
+ (not (funcall pred)))
+ (read-event nil nil 0.1))))
+
+(defun auto-revert-test--wait-for-buffer-text (buffer string max-wait)
+ "Wait until BUFFER has the contents STRING, or MAX-WAIT seconds elapsed."
+ (auto-revert-test--wait-for
+ (lambda () (string-equal (auto-revert-test--buffer-string buffer) string))
+ max-wait))
+
+(defun auto-revert-test--instrument-kill-buffer-hook (buffer)
+ "Instrument local `kill-buffer-hook' with messages."
+ (when auto-revert-debug
+ (with-current-buffer buffer
+ (add-hook
+ 'kill-buffer-hook
+ (lambda ()
+ (message
+ "%s killed\n%s" (current-buffer) (with-output-to-string (backtrace))))
+ nil 'local))))
+
+(ert-deftest auto-revert-test05-global-notify ()
+ "Test `global-auto-revert-mode' without polling."
+ (skip-unless (or file-notify--library
+ (file-remote-p temporary-file-directory)))
+ (with-auto-revert-test
+ (ert-with-temp-file file-1
+ (ert-with-temp-file file-2
+ (ert-with-temp-file file-3
+ (let* ((auto-revert-use-notify t)
+ (auto-revert-avoid-polling t)
+ (was-in-global-auto-revert-mode global-auto-revert-mode)
+ (file-2b (concat file-2 "-b"))
+ require-final-newline buf-1 buf-2 buf-3)
+ (unwind-protect
+ (progn
+ (setq buf-1 (find-file-noselect file-1))
+ (auto-revert-test--instrument-kill-buffer-hook buf-1)
+ (setq buf-2 (find-file-noselect file-2))
+ (auto-revert-test--instrument-kill-buffer-hook buf-2)
+ (auto-revert-test--write-file "1-a" file-1)
+ (should (equal (auto-revert-test--buffer-string buf-1) ""))
+
+ (global-auto-revert-mode 1) ; Turn it on.
+
+ (should (buffer-local-value
+ 'auto-revert-notify-watch-descriptor buf-1))
+ (should (buffer-local-value
+ 'auto-revert-notify-watch-descriptor buf-2))
+
+ ;; buf-1 should have been reverted immediately when the mode
+ ;; was enabled.
+ (should (equal (auto-revert-test--buffer-string buf-1) "1-a"))
+
+ ;; Alter a file.
+ (auto-revert-test--write-file "2-a" file-2)
+ ;; Allow for some time to handle notification events.
+ (auto-revert-test--wait-for-buffer-text buf-2 "2-a" 1)
+ (should (equal (auto-revert-test--buffer-string buf-2) "2-a"))
+
+ ;; Visit a file, and modify it on disk.
+ (setq buf-3 (find-file-noselect file-3))
+ (auto-revert-test--instrument-kill-buffer-hook buf-3)
+ ;; Newly opened buffers won't be use notification until the
+ ;; first poll cycle; wait for it.
+ (auto-revert-test--wait-for
+ (lambda () (buffer-local-value
+ 'auto-revert-notify-watch-descriptor buf-3))
+ (auto-revert--timeout))
+ (should (buffer-local-value
+ 'auto-revert-notify-watch-descriptor buf-3))
+ (auto-revert-test--write-file "3-a" file-3)
+ (auto-revert-test--wait-for-buffer-text buf-3 "3-a" 1)
+ (should (equal (auto-revert-test--buffer-string buf-3) "3-a"))
+
+ ;; Delete a visited file, and re-create it with new contents.
+ (delete-file file-1)
+ (should (equal (auto-revert-test--buffer-string buf-1) "1-a"))
+ (auto-revert-test--write-file "1-b" file-1)
+ ;; Since the file is deleted, it needs at least
+ ;; `autorevert-interval' to recognize the new file,
+ ;; while polling. So increase the timeout.
+ (auto-revert-test--wait-for-buffer-text
+ buf-1 "1-b" (* 2 (auto-revert--timeout)))
+ (should (buffer-local-value
+ 'auto-revert-notify-watch-descriptor buf-1))
+
+ ;; Write a buffer to a new file, then modify the new file on disk.
+ (with-current-buffer buf-2
+ (write-file file-2b))
+ (should (equal (auto-revert-test--buffer-string buf-2) "2-a"))
+ (auto-revert-test--write-file "2-b" file-2b)
+ (auto-revert-test--wait-for-buffer-text
+ buf-2 "2-b" (auto-revert--timeout))
+ (should (buffer-local-value
+ 'auto-revert-notify-watch-descriptor buf-2)))
+
+ ;; Clean up.
+ (unless was-in-global-auto-revert-mode
+ (global-auto-revert-mode 0)) ; Turn it off.
+ (dolist (buf (list buf-1 buf-2 buf-3))
+ (with-current-buffer buf (setq-local kill-buffer-hook nil))
+ (ignore-errors (kill-buffer buf)))
+ (ignore-errors (delete-file file-2b)))))))))
+
+(auto-revert--deftest-remote auto-revert-test05-global-notify
+ "Test `global-auto-revert-mode' without polling for remote buffers.")
+
+(ert-deftest auto-revert-test06-write-file ()
+ "Verify that notification follows `write-file' correctly."
+ (skip-unless (or file-notify--library
+ (file-remote-p temporary-file-directory)))
+ (with-auto-revert-test
+ (ert-with-temp-file file-1
+ (let* ((auto-revert-use-notify t)
+ (file-2 (concat file-1 "-2"))
+ require-final-newline buf)
+ (unwind-protect
+ (progn
+ (setq buf (find-file-noselect file-1))
+ (with-current-buffer buf
+ (insert "A")
+ (save-buffer)
+
+ (auto-revert-mode 1)
+
+ (insert "B")
+ (write-file file-2)
+
+ (auto-revert-test--write-file "C" file-2)
+ (auto-revert-test--wait-for-buffer-text
+ buf "C" (auto-revert--timeout))
+ (should (equal (buffer-string) "C"))))
+
+ ;; Clean up.
+ (ignore-errors (kill-buffer buf))
+ (ignore-errors (delete-file file-2)))))))
+
+(auto-revert--deftest-remote auto-revert-test06-write-file
+ "Test `write-file' in `auto-revert-mode' for remote buffers.")
+
+;; This is inspired by Bug#44638.
+(ert-deftest auto-revert-test07-auto-revert-several-buffers ()
+ "Check autorevert for several buffers visiting the same file."
+ ;; (with-auto-revert-test
+ (ert-with-temp-file tmpfile
+ (let ((auto-revert-use-notify t)
+ (times '(120 60 30 15))
+ (num-buffers 10)
+ require-final-newline buffers)
+
+ (unwind-protect
+ ;; Check indirect buffers.
+ (ert-with-message-capture auto-revert--messages
+ (auto-revert-tests--write-file "any text" tmpfile (pop times))
+ (push (find-file-noselect tmpfile) buffers)
+ (with-current-buffer (car buffers)
+ (should (string-equal (buffer-string) "any text"))
+ ;; `buffer-stale--default-function' checks for
+ ;; `verify-visited-file-modtime'. We must ensure that
+ ;; it returns nil.
+ (auto-revert-mode 1)
+ (should auto-revert-mode))
+
+ (dotimes (i num-buffers)
+ (push (make-indirect-buffer
+ (car buffers)
+ (format "%s-%d" (buffer-file-name (car buffers)) i)
+ 'clone)
+ buffers))
+ (setq buffers (nreverse buffers))
+ (dolist (buf buffers)
+ (with-current-buffer buf
+ (should (string-equal (buffer-string) "any text"))
+ (should auto-revert-mode)))
+
+ (auto-revert-tests--write-file "another text" tmpfile (pop times))
;; Check, that the buffer has been reverted.
- (should-not
- (string-match name (substring-no-properties (buffer-string))))
+ (auto-revert--wait-for-revert (car buffers))
+ (dolist (buf buffers)
+ (with-current-buffer buf
+ (should (string-equal (buffer-string) "another text")))))
+
+ ;; Exit.
+ (ignore-errors
+ (dolist (buf buffers)
+ (with-current-buffer buf (set-buffer-modified-p nil))
+ (kill-buffer buf)))
+ (setq buffers nil)
+ (ignore-errors (delete-file tmpfile)))
+
+ ;; Check direct buffers.
+ (unwind-protect
+ (ert-with-message-capture auto-revert--messages
+ (auto-revert-tests--write-file "any text" tmpfile (pop times))
+
+ (dotimes (i num-buffers)
+ (push (generate-new-buffer
+ (format "%s-%d" (file-name-nondirectory tmpfile) i))
+ buffers))
+ (setq buffers (nreverse buffers))
+ (dolist (buf buffers)
+ (with-current-buffer buf
+ (insert-file-contents tmpfile 'visit)
+ (should (string-equal (buffer-string) "any text"))
+ (auto-revert-mode 1)
+ (should auto-revert-mode)))
+
+ (auto-revert-tests--write-file "another text" tmpfile (pop times))
+ ;; Check, that the buffers have been reverted.
+ (dolist (buf buffers)
+ (auto-revert--wait-for-revert buf)
+ (with-current-buffer buf
+ (should (string-equal (buffer-string) "another text")))))
- (ert-with-message-capture auto-revert--messages
- ;; Make dired buffer modified. Check, that the buffer has
- ;; been still reverted.
- (set-buffer-modified-p t)
- (sleep-for 1)
- (write-region "any text" nil tmpfile nil 'no-message)
+ ;; Exit.
+ (ignore-errors
+ (dolist (buf buffers)
+ (with-current-buffer buf (set-buffer-modified-p nil))
+ (kill-buffer buf)))))));)
- (auto-revert--wait-for-revert buf))
- ;; Check, that the buffer has been reverted.
- (should
- (string-match name (substring-no-properties (buffer-string))))))
+(auto-revert--deftest-remote auto-revert-test07-auto-revert-several-buffers
+ "Check autorevert for several buffers visiting the same remote file.")
- ;; Exit.
- (ignore-errors
- (with-current-buffer buf (set-buffer-modified-p nil))
- (kill-buffer buf))
- (ignore-errors (delete-file tmpfile)))))
+;; Mark all tests as unstable on Cygwin (bug#49665).
+(when (eq system-type 'cygwin)
+ (dolist (test (apropos-internal "^auto-revert" #'ert-test-boundp))
+ (setf (ert-test-tags (ert-get-test test))
+ (cons :unstable (ert-test-tags (ert-get-test test))))))
(defun auto-revert-test-all (&optional interactive)
"Run all tests for \\[auto-revert]."
@@ -309,4 +665,4 @@ This expects `auto-revert--messages' to be bound by
(ert-run-tests-batch "^auto-revert-")))
(provide 'auto-revert-tests)
-;;; auto-revert-tests.el ends here
+;;; autorevert-tests.el ends here
diff --git a/test/lisp/battery-tests.el b/test/lisp/battery-tests.el
new file mode 100644
index 00000000000..1f9cfaee01f
--- /dev/null
+++ b/test/lisp/battery-tests.el
@@ -0,0 +1,154 @@
+;;; battery-tests.el --- tests for battery.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'battery)
+
+(ert-deftest battery-linux-proc-apm-regexp ()
+ "Test `rx' definition `battery--linux-proc-apm'."
+ (let ((str "1.16 1.2 0x07 0x01 0xff 0x80 -1% -1 ?"))
+ (should (string-match (rx battery--linux-proc-apm) str))
+ (should (equal (match-string 0 str) str))
+ (should (equal (match-string 1 str) "1.16"))
+ (should (equal (match-string 2 str) "1.2"))
+ (should (equal (match-string 3 str) "07"))
+ (should (equal (match-string 4 str) "01"))
+ (should (equal (match-string 5 str) "ff"))
+ (should (equal (match-string 6 str) "80"))
+ (should (equal (match-string 7 str) "-1"))
+ (should (equal (match-string 8 str) "-1"))
+ (should (equal (match-string 9 str) "?")))
+ (let ((str "1.16 1.2 0x03 0x00 0x00 0x01 99% 1792 min"))
+ (should (string-match (rx battery--linux-proc-apm) str))
+ (should (equal (match-string 0 str) str))
+ (should (equal (match-string 1 str) "1.16"))
+ (should (equal (match-string 2 str) "1.2"))
+ (should (equal (match-string 3 str) "03"))
+ (should (equal (match-string 4 str) "00"))
+ (should (equal (match-string 5 str) "00"))
+ (should (equal (match-string 6 str) "01"))
+ (should (equal (match-string 7 str) "99"))
+ (should (equal (match-string 8 str) "1792"))
+ (should (equal (match-string 9 str) "min"))))
+
+(ert-deftest battery-acpi-rate-regexp ()
+ "Test `rx' definition `battery--acpi-rate'."
+ (let ((str "01 mA"))
+ (should (string-match (rx (battery--acpi-rate)) str))
+ (should (equal (match-string 0 str) str))
+ (should (equal (match-string 1 str) "01"))
+ (should (equal (match-string 2 str) "mA")))
+ (let ((str "23 mW"))
+ (should (string-match (rx (battery--acpi-rate)) str))
+ (should (equal (match-string 0 str) str))
+ (should (equal (match-string 1 str) "23"))
+ (should (equal (match-string 2 str) "mW")))
+ (let ((str "23 mWh"))
+ (should (string-match (rx (battery--acpi-rate)) str))
+ (should (equal (match-string 0 str) "23 mW"))
+ (should (equal (match-string 1 str) "23"))
+ (should (equal (match-string 2 str) "mW")))
+ (should-not (string-match (rx (battery--acpi-rate) eos) "45 mWh")))
+
+(ert-deftest battery-acpi-capacity-regexp ()
+ "Test `rx' definition `battery--acpi-capacity'."
+ (let ((str "01 mAh"))
+ (should (string-match (rx battery--acpi-capacity) str))
+ (should (equal (match-string 0 str) str))
+ (should (equal (match-string 1 str) "01"))
+ (should (equal (match-string 2 str) "mAh")))
+ (let ((str "23 mWh"))
+ (should (string-match (rx battery--acpi-capacity) str))
+ (should (equal (match-string 0 str) str))
+ (should (equal (match-string 1 str) "23"))
+ (should (equal (match-string 2 str) "mWh")))
+ (should-not (string-match (rx battery--acpi-capacity eos) "45 mW")))
+
+(ert-deftest battery-upower-state ()
+ "Test `battery--upower-state'."
+ ;; Charging.
+ (dolist (total '(nil charging discharging empty fully-charged
+ pending-charge pending-discharge))
+ (should (eq (battery--upower-state '(("State" . 1)) total) 'charging)))
+ (dolist (state '(nil 0 1 2 3 4 5 6))
+ (should (eq (battery--upower-state `(("State" . ,state)) 'charging)
+ 'charging)))
+ ;; Discharging.
+ (dolist (total '(nil discharging empty fully-charged
+ pending-charge pending-discharge))
+ (should (eq (battery--upower-state '(("State" . 2)) total) 'discharging)))
+ (dolist (state '(nil 0 2 3 4 5 6))
+ (should (eq (battery--upower-state `(("State" . ,state)) 'discharging)
+ 'discharging)))
+ ;; Pending charge.
+ (dolist (total '(nil empty fully-charged pending-charge pending-discharge))
+ (should (eq (battery--upower-state '(("State" . 5)) total)
+ 'pending-charge)))
+ (dolist (state '(nil 0 3 4 5 6))
+ (should (eq (battery--upower-state `(("State" . ,state)) 'pending-charge)
+ 'pending-charge)))
+ ;; Pending discharge.
+ (dolist (total '(nil empty fully-charged pending-discharge))
+ (should (eq (battery--upower-state '(("State" . 6)) total)
+ 'pending-discharge)))
+ (dolist (state '(nil 0 3 4 6))
+ (should (eq (battery--upower-state `(("State" . ,state)) 'pending-discharge)
+ 'pending-discharge)))
+ ;; Empty.
+ (dolist (total '(nil empty))
+ (should (eq (battery--upower-state '(("State" . 3)) total) 'empty)))
+ (dolist (state '(nil 0 3))
+ (should (eq (battery--upower-state `(("State" . ,state)) 'empty) 'empty)))
+ ;; Fully charged.
+ (dolist (total '(nil fully-charged))
+ (should (eq (battery--upower-state '(("State" . 4)) total) 'fully-charged)))
+ (dolist (state '(nil 0 4))
+ (should (eq (battery--upower-state `(("State" . ,state)) 'fully-charged)
+ 'fully-charged))))
+
+(ert-deftest battery-upower-state-unknown ()
+ "Test `battery--upower-state' with unknown states."
+ ;; Unknown running total retains new state.
+ (should-not (battery--upower-state () nil))
+ (should-not (battery--upower-state '(("State" . state)) nil))
+ (should-not (battery--upower-state '(("State" . 0)) nil))
+ (should (eq (battery--upower-state '(("State" . 1)) nil) 'charging))
+ (should (eq (battery--upower-state '(("State" . 2)) nil) 'discharging))
+ (should (eq (battery--upower-state '(("State" . 3)) nil) 'empty))
+ (should (eq (battery--upower-state '(("State" . 4)) nil) 'fully-charged))
+ (should (eq (battery--upower-state '(("State" . 5)) nil) 'pending-charge))
+ (should (eq (battery--upower-state '(("State" . 6)) nil) 'pending-discharge))
+ ;; Unknown new state retains running total.
+ (dolist (props '(() (("State" . state)) (("State" . 0))))
+ (dolist (total '(nil charging discharging empty fully-charged
+ pending-charge pending-discharge))
+ (should (eq (battery--upower-state props total) total))))
+ ;; Conflicting empty and fully-charged.
+ (should-not (battery--upower-state '(("State" . 3)) 'fully-charged))
+ (should-not (battery--upower-state '(("State" . 4)) 'empty)))
+
+(ert-deftest battery-format ()
+ "Test `battery-format'."
+ (should (equal (battery-format "" ()) ""))
+ (should (equal (battery-format "" '((?b . "-"))) ""))
+ (should (equal (battery-format "%2a%-3b%.1p%%" '((?b . "-") (?p . "99")))
+ "- 9%")))
+
+;;; battery-tests.el ends here
diff --git a/test/lisp/bookmark-resources/example.txt b/test/lisp/bookmark-resources/example.txt
new file mode 100644
index 00000000000..b66fc078269
--- /dev/null
+++ b/test/lisp/bookmark-resources/example.txt
@@ -0,0 +1,3 @@
+This text file is used by bookmark-tests.el
+
+;; example.txt ends here.
diff --git a/test/lisp/bookmark-resources/test-list.bmk b/test/lisp/bookmark-resources/test-list.bmk
new file mode 100644
index 00000000000..696d64979b8
--- /dev/null
+++ b/test/lisp/bookmark-resources/test-list.bmk
@@ -0,0 +1,20 @@
+;;;; Emacs Bookmark Format Version 1 ;;;; -*- coding: utf-8-emacs -*-
+;;; This format is meant to be slightly human-readable;
+;;; nevertheless, you probably don't want to edit it.
+;;; -*- End Of Bookmark File Format Version Stamp -*-
+(("name-0"
+ (filename . "/some/file-0")
+ (front-context-string . "abc")
+ (rear-context-string . "def")
+ (position . 3))
+("name-1"
+ (filename . "/some/file-1")
+ (front-context-string . "abc")
+ (rear-context-string . "def")
+ (position . 3))
+("name-2"
+ (filename . "/some/file-2")
+ (front-context-string . "abc")
+ (rear-context-string . "def")
+ (position . 3))
+)
diff --git a/test/lisp/bookmark-resources/test.bmk b/test/lisp/bookmark-resources/test.bmk
new file mode 100644
index 00000000000..c238fe1c8d4
--- /dev/null
+++ b/test/lisp/bookmark-resources/test.bmk
@@ -0,0 +1,10 @@
+;;;; Emacs Bookmark Format Version 1 ;;;; -*- coding: utf-8-emacs -*-
+;;; This format is meant to be slightly human-readable;
+;;; nevertheless, you probably don't want to edit it.
+;;; -*- End Of Bookmark File Format Version Stamp -*-
+(("name"
+ (filename . "/some/file")
+ (front-context-string . "abc")
+ (rear-context-string . "def")
+ (position . 3))
+)
diff --git a/test/lisp/bookmark-tests.el b/test/lisp/bookmark-tests.el
new file mode 100644
index 00000000000..3bea08bc37a
--- /dev/null
+++ b/test/lisp/bookmark-tests.el
@@ -0,0 +1,656 @@
+;;; bookmark-tests.el --- Tests for bookmark.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2019-2022 Free Software Foundation, Inc.
+
+;; Author: Stefan Kangas <stefankangas@gmail.com>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'ert-x)
+(require 'bookmark)
+(require 'cl-lib)
+
+(defvar bookmark-tests-bookmark-file (ert-resource-file "test.bmk")
+ "Bookmark file used for testing.")
+
+(defvar bookmark-tests-example-file
+ ;; We use abbreviate-file-name here to match the behavior of
+ ;; `bookmark-buffer-file-name'.
+ (abbreviate-file-name (ert-resource-file "example.txt"))
+ "Example file used for testing.")
+
+;; The values below should match `bookmark-tests-bookmark-file'. We cache
+;; these values to speed up tests by avoiding unnecessary I/O. This
+;; makes tests run 5-10 times faster on my system.
+(eval-and-compile ; needed by `with-bookmark-test' macro
+ (defvar bookmark-tests-bookmark '("name"
+ (filename . "/some/file")
+ (front-context-string . "abc")
+ (rear-context-string . "def")
+ (position . 3))
+ "Cached value used in bookmark-tests.el."))
+
+(defvar bookmark-tests-cache-timestamp
+ (cons bookmark-tests-bookmark-file
+ (nth 5 (file-attributes
+ bookmark-tests-bookmark-file)))
+ "Cached value used in bookmark-tests.el.")
+
+(defmacro with-bookmark-test (&rest body)
+ "Create environment for testing bookmark.el and evaluate BODY.
+Ensure a clean environment for testing, and do not change user
+data when running tests interactively."
+ `(with-temp-buffer
+ (let ((bookmark-alist (quote (,(copy-sequence bookmark-tests-bookmark))))
+ (bookmark-default-file bookmark-tests-bookmark-file)
+ (bookmark-bookmarks-timestamp bookmark-tests-cache-timestamp)
+ bookmark-save-flag)
+ ,@body)))
+
+(defmacro with-bookmark-test-file (&rest body)
+ "Create environment for testing bookmark.el and evaluate BODY.
+Same as `with-bookmark-test' but also opens the resource file
+example.txt in a buffer, which can be accessed by callers through
+the lexically-bound variable `buffer'."
+ `(let ((buffer (find-file-noselect bookmark-tests-example-file)))
+ (unwind-protect
+ (with-bookmark-test
+ ,@body)
+ (kill-buffer buffer))))
+
+(defvar bookmark-tests-bookmark-file-list (ert-resource-file "test-list.bmk")
+ "Bookmark file used for testing a list of bookmarks.")
+
+;; The values below should match `bookmark-tests-bookmark-file-list'
+;; content. We cache these values to speed up tests.
+(eval-and-compile ; needed by `with-bookmark-test-list' macro
+ (defvar bookmark-tests-bookmark-list-0 '("name-0"
+ (filename . "/some/file-0")
+ (front-context-string . "ghi")
+ (rear-context-string . "jkl")
+ (position . 4))
+ "Cached value used in bookmark-tests.el."))
+
+;; The values below should match `bookmark-tests-bookmark-file-list'
+;; content. We cache these values to speed up tests.
+(eval-and-compile ; needed by `with-bookmark-test-list' macro
+ (defvar bookmark-tests-bookmark-list-1 '("name-1"
+ (filename . "/some/file-1")
+ (front-context-string . "mno")
+ (rear-context-string . "pqr")
+ (position . 5))
+ "Cached value used in bookmark-tests.el."))
+
+;; The values below should match `bookmark-tests-bookmark-file-list'
+;; content. We cache these values to speed up tests.
+(eval-and-compile ; needed by `with-bookmark-test-list' macro
+ (defvar bookmark-tests-bookmark-list-2 '("name-2"
+ (filename . "/some/file-2")
+ (front-context-string . "stu")
+ (rear-context-string . "vwx")
+ (position . 6))
+ "Cached value used in bookmark-tests.el."))
+
+(defvar bookmark-tests-cache-timestamp-list
+ (cons bookmark-tests-bookmark-file-list
+ (nth 5 (file-attributes
+ bookmark-tests-bookmark-file-list)))
+ "Cached value used in bookmark-tests.el.")
+
+(defmacro with-bookmark-test-list (&rest body)
+ "Create environment for testing bookmark.el and evaluate BODY.
+Ensure a clean environment for testing, and do not change user
+data when running tests interactively."
+ `(with-temp-buffer
+ (let ((bookmark-alist (quote (,(copy-sequence bookmark-tests-bookmark-list-0)
+ ,(copy-sequence bookmark-tests-bookmark-list-1)
+ ,(copy-sequence bookmark-tests-bookmark-list-2))))
+ (bookmark-default-file bookmark-tests-bookmark-file-list)
+ (bookmark-bookmarks-timestamp bookmark-tests-cache-timestamp-list)
+ bookmark-save-flag)
+ ,@body)))
+
+(defmacro with-bookmark-test-file-list (&rest body)
+ "Create environment for testing bookmark.el and evaluate BODY.
+Same as `with-bookmark-test-list' but also opens the resource file
+example.txt in a buffer, which can be accessed by callers through
+the lexically-bound variable `buffer'."
+ `(let ((buffer (find-file-noselect bookmark-tests-example-file)))
+ (unwind-protect
+ (with-bookmark-test-list
+ ,@body)
+ (kill-buffer buffer))))
+
+(ert-deftest bookmark-tests-all-names ()
+ (with-bookmark-test
+ (should (equal (bookmark-all-names) '("name")))))
+
+(ert-deftest bookmark-tests-get-bookmark ()
+ (with-bookmark-test
+ (should (equal (bookmark-get-bookmark "name") bookmark-tests-bookmark))))
+
+(ert-deftest bookmark-tests-get-bookmark-record ()
+ (with-bookmark-test
+ (should (equal (bookmark-get-bookmark-record "name") (cdr bookmark-tests-bookmark)))))
+
+(ert-deftest bookmark-tests-all-names-list ()
+ (with-bookmark-test-list
+ (should (equal (bookmark-all-names) '("name-0"
+ "name-1"
+ "name-2")))))
+
+(ert-deftest bookmark-tests-get-bookmark-list ()
+ (with-bookmark-test-list
+ (should (equal (bookmark-get-bookmark "name-0")
+ bookmark-tests-bookmark-list-0))
+ (should (equal (bookmark-get-bookmark "name-1")
+ bookmark-tests-bookmark-list-1))
+ (should (equal (bookmark-get-bookmark "name-2")
+ bookmark-tests-bookmark-list-2))))
+
+(ert-deftest bookmark-tests-get-bookmark-record-list ()
+ (with-bookmark-test-list
+ (should (equal (bookmark-get-bookmark-record "name-0")
+ (cdr bookmark-tests-bookmark-list-0)))
+ (should (equal (bookmark-get-bookmark-record "name-1")
+ (cdr bookmark-tests-bookmark-list-1)))
+ (should (equal (bookmark-get-bookmark-record "name-2")
+ (cdr bookmark-tests-bookmark-list-2)))))
+
+(ert-deftest bookmark-tests-record-getters-and-setters-new ()
+ (with-temp-buffer
+ (let* ((buffer-file-name "test")
+ (bmk (bookmark-make-record)))
+ (bookmark-set-name bmk "foobar")
+ (should (equal (bookmark-name-from-full-record bmk) "foobar"))
+ (bookmark-set-filename bmk "file/name")
+ (should (equal (bookmark-get-filename bmk) "file/name"))
+ (bookmark-set-position bmk 123)
+ (should (equal (bookmark-get-position bmk) 123))
+ (bookmark-set-front-context-string bmk "front")
+ (should (equal (bookmark-get-front-context-string bmk) "front"))
+ (bookmark-set-rear-context-string bmk "rear")
+ (should (equal (bookmark-get-rear-context-string bmk) "rear"))
+ (bookmark-prop-set bmk 'filename "prop")
+ (should (equal (bookmark-prop-get bmk 'filename) "prop")))))
+
+(ert-deftest bookmark-tests-maybe-historicize-string ()
+ (let ((bookmark-history))
+ (bookmark-maybe-historicize-string "foo")
+ (should (equal (car bookmark-history) "foo"))))
+
+(defun bookmark-remove-last-modified (bmk)
+ (assoc-delete-all 'last-modified bmk))
+
+(ert-deftest bookmark-tests-make-record ()
+ (with-bookmark-test-file
+ (let* ((record `("example.txt" (filename . ,bookmark-tests-example-file)
+ (front-context-string . "is text file is ")
+ (rear-context-string)
+ (position . 3)
+ (defaults "example.txt"))))
+ (with-current-buffer buffer
+ (goto-char 3)
+ (should (equal (bookmark-remove-last-modified (bookmark-make-record))
+ record))
+ ;; calling twice gives same record
+ (should (equal (bookmark-remove-last-modified (bookmark-make-record))
+ record))))))
+
+(ert-deftest bookmark-tests-make-record-list ()
+ (with-bookmark-test-file-list
+ (let* ((record `("example.txt" (filename . ,bookmark-tests-example-file)
+ (front-context-string . "is text file is ")
+ (rear-context-string)
+ (position . 3)
+ (defaults "example.txt"))))
+ (with-current-buffer buffer
+ (goto-char 3)
+ (should (equal (bookmark-remove-last-modified (bookmark-make-record))
+ record))
+ ;; calling twice gives same record
+ (should (equal (bookmark-remove-last-modified (bookmark-make-record))
+ record))))))
+
+(ert-deftest bookmark-tests-make-record-function ()
+ (with-bookmark-test
+ (let ((buffer-file-name "test"))
+ ;; Named bookmark
+ (let ((bookmark-make-record-function (lambda () '("<name>"))))
+ (should (equal (bookmark-make-record)
+ '("<name>"))))
+ ;; SECOND format
+ (let ((bookmark-make-record-function (lambda () '(((position . 2))))))
+ (should (equal (bookmark-make-record)
+ '("test" ((position . 2) (defaults "test"))))))
+ ;; CURRENT format
+ (let ((bookmark-make-record-function (lambda () '((position . 2)))))
+ (should (equal (bookmark-make-record)
+ '("test" (position . 2) (defaults "test"))))))))
+
+(ert-deftest bookmark-tests-set ()
+ (with-bookmark-test-file
+ (let ((bmk1 `("foo" (filename . ,bookmark-tests-example-file)
+ (front-context-string . "This text file i")
+ (rear-context-string)
+ (position . 1)))
+ (bmk2 `("foo" (filename . ,bookmark-tests-example-file)
+ (front-context-string)
+ (rear-context-string . ".txt ends here.\n")
+ (position . 72)))
+ bookmark-alist)
+ (with-current-buffer buffer
+ ;; 1. bookmark-set
+ ;; Set first bookmark
+ (goto-char (point-min))
+ (bookmark-set "foo")
+ (should (equal (mapcar #'bookmark-remove-last-modified bookmark-alist)
+ (list bmk1)))
+ ;; Replace that bookmark
+ (goto-char (point-max))
+ (bookmark-set "foo")
+ (should (equal (mapcar #'bookmark-remove-last-modified bookmark-alist)
+ (list bmk2)))
+ ;; Push another bookmark with the same name
+ (goto-char (point-min))
+ (bookmark-set "foo" t) ; NO-OVERWRITE is t
+ (should (equal (mapcar #'bookmark-remove-last-modified bookmark-alist)
+ (list bmk1 bmk2)))
+
+ ;; 2. bookmark-set-no-overwrite
+ ;; Don't overwrite
+ (should-error (bookmark-set-no-overwrite "foo"))
+ ;; Set new bookmark
+ (setq bookmark-alist nil)
+ (bookmark-set-no-overwrite "foo")
+ (should (equal (mapcar #'bookmark-remove-last-modified bookmark-alist)
+ (list bmk1)))
+ ;; Push another bookmark with the same name
+ (goto-char (point-max))
+ (bookmark-set-no-overwrite "foo" t) ; PUSH-BOOKMARK is t
+ (should (equal (mapcar #'bookmark-remove-last-modified bookmark-alist)
+ (list bmk2 bmk1)))
+
+ ;; 3. bookmark-set-internal
+ (should-error (bookmark-set-internal "foo" "bar" t))))))
+
+(ert-deftest bookmark-tests-set/bookmark-use-annotations-t ()
+ (with-bookmark-test-file
+ (let ((bookmark-use-annotations t))
+ (save-window-excursion
+ (switch-to-buffer buffer)
+ ;; Should jump to edit annotation buffer
+ (bookmark-set "foo")
+ (should (equal major-mode 'bookmark-edit-annotation-mode))
+ ;; Should return to the original buffer
+ (bookmark-edit-annotation-confirm)
+ (should (equal (current-buffer) buffer))))))
+
+(ert-deftest bookmark-tests-kill-line ()
+ (with-temp-buffer
+ (insert "foobar\n")
+ (goto-char (point-min))
+ (bookmark-kill-line)
+ (should (equal (buffer-string) "\n")))
+ (with-temp-buffer
+ (insert "foobar\n")
+ (goto-char (point-min))
+ (bookmark-kill-line t) ; including newline
+ (should (equal (buffer-string) ""))))
+
+(ert-deftest bookmark-tests-default-annotation-text ()
+ (should (stringp (bookmark-default-annotation-text "foo")))
+ (should (string-match "foo" (bookmark-default-annotation-text "foo"))))
+
+(ert-deftest bookmark-tests-insert-annotation ()
+ (with-bookmark-test
+ (should-error (bookmark-insert-annotation "a missing bookmark"))
+ (bookmark-insert-annotation "name")
+ (should (string-match "Type the annotation" (buffer-string))))
+ (with-bookmark-test
+ (bookmark-set-annotation "name" "some stuff")
+ (bookmark-insert-annotation "name")
+ (should (string-match "some stuff" (buffer-string)))))
+
+(ert-deftest bookmark-tests-edit-annotation ()
+ (with-bookmark-test
+ (bookmark-edit-annotation "name")
+ (insert "new text")
+ (bookmark-edit-annotation-confirm)
+ (should (equal (bookmark-get-annotation "name") "new text"))))
+
+(ert-deftest bookmark-tests-jump ()
+ (with-bookmark-test-file
+ (with-current-buffer buffer
+ (bookmark-set "test"))
+ (bookmark-jump "test")
+ (should (equal (current-buffer) buffer))
+ (should-error (bookmark-jump nil))))
+
+(ert-deftest bookmark-tests-insert-location ()
+ (with-bookmark-test
+ (bookmark-insert-location "name")
+ (should (equal (buffer-string) "/some/file"))))
+
+(ert-deftest bookmark-tests-location ()
+ (with-bookmark-test
+ (should (equal (bookmark-location "name") "/some/file"))))
+
+(ert-deftest bookmark-tests-rename ()
+ (with-bookmark-test
+ (bookmark-rename "name" "newname")
+ (should (equal (bookmark-all-names) '("newname")))))
+
+(ert-deftest bookmark-tests-insert ()
+ (with-bookmark-test-file
+ (with-current-buffer buffer
+ (bookmark-set "test"))
+ (bookmark-insert "test")
+ (should (string-match "^This text file is used by bookmark-tests.el"
+ (buffer-string)))))
+
+(ert-deftest bookmark-tests-delete ()
+ (with-bookmark-test
+ (bookmark-delete "name")
+ (should (equal bookmark-alist nil))))
+
+(ert-deftest bookmark-tests-delete-all ()
+ (with-bookmark-test-list
+ (bookmark-delete-all t)
+ (should (equal bookmark-alist nil))))
+
+(defmacro with-bookmark-test-save-load (&rest body)
+ "Create environment for testing bookmark.el and evaluate BODY.
+Same as `with-bookmark-test' but also sets a temporary
+`bookmark-default-file', evaluates BODY, and then runs the test
+that saves and then loads the bookmark file."
+ `(with-bookmark-test
+ (ert-with-temp-file file
+ (let ((bookmark-default-file file)
+ (old-alist bookmark-alist))
+ ,@body
+ (bookmark-save nil file t)
+ (setq bookmark-alist nil)
+ (bookmark-load file nil t)
+ (should (equal bookmark-alist old-alist))))))
+
+(defvar bookmark-tests-non-ascii-data
+ (concat "Здра́вствуйте!" "中文,普通话,汉语" "åäöøñ"
+ "こんにちは" "你好" "Dobrý deň"
+ "∀ p ∈ world • hello p □"
+ ;; These do not yield valid UTF-8 byte sequences.
+ ;; WARNING: If you try to evaluate the first one of these,
+ ;; there is a risk that Emacs will crash. Buyer beware.
+ (decode-coding-string "\xE3\x32\x9A\x36" 'chinese-gb18030)
+ (char-to-string (decode-char 'eight-bit #x81))))
+
+(ert-deftest bookmark-tests-save ()
+ (with-bookmark-test-save-load
+ ;; Just run the default test according to the macro.
+ t))
+
+(ert-deftest bookmark-tests-save/non-ascii-bookmark-name ()
+ (with-bookmark-test-save-load
+ (bookmark-set-name "name" bookmark-tests-non-ascii-data)))
+
+(ert-deftest bookmark-tests-save/non-ascii-annotation ()
+ (with-bookmark-test-save-load
+ (bookmark-set-annotation "name" bookmark-tests-non-ascii-data)))
+
+(ert-deftest bookmark-tests-maybe-rename ()
+ (let ((bookmark '("foo")))
+ (bookmark-maybe-rename bookmark '("foo"))
+ (should (equal bookmark '("foo<2>")))))
+
+(ert-deftest bookmark-tests-load ()
+ (with-bookmark-test
+ (should-error (bookmark-load "no/such/file"))
+ (let* ((bookmark-alist '()))
+ (bookmark-load bookmark-tests-bookmark-file nil t)
+ (should (equal bookmark-alist (list bookmark-tests-bookmark)))
+ (bookmark-load bookmark-tests-bookmark-file t t) ; OVERWRITE is t
+ (should (equal bookmark-alist (list bookmark-tests-bookmark)))
+ ;; Append
+ (bookmark-load bookmark-tests-bookmark-file nil t) ; OVERWRITE is nil
+ (should (equal bookmark-alist
+ (list bookmark-tests-bookmark
+ (cons "name<2>" (cdr bookmark-tests-bookmark))))))))
+
+;; TODO: Add more tests for bookmark-bmenu.
+
+(defmacro with-bookmark-bmenu-test (&rest body)
+ "Create environment for testing `bookmark-bmenu-list' and evaluate BODY.
+Same as `with-bookmark-test' but with additions suitable for
+testing `bookmark-bmenu-list'."
+ `(with-bookmark-test
+ (let ((bookmark-bmenu-buffer "*Bookmark List - Testing*"))
+ (unwind-protect
+ (save-window-excursion
+ (bookmark-bmenu-list)
+ ,@body)
+ (kill-buffer bookmark-bmenu-buffer)))))
+
+(defmacro with-bookmark-bmenu-test-list (&rest body)
+ "Create environment for testing `bookmark-bmenu-list' and evaluate BODY.
+Same as `with-bookmark-test-list' but with additions suitable for
+testing `bookmark-bmenu-list'."
+ `(with-bookmark-test-list
+ (let ((bookmark-bmenu-buffer "*Bookmark List - Testing*"))
+ (unwind-protect
+ (save-window-excursion
+ (bookmark-bmenu-list)
+ ,@body)
+ (kill-buffer bookmark-bmenu-buffer)))))
+
+(ert-deftest bookmark-test-bmenu-edit-annotation/show-annotation ()
+ (with-bookmark-bmenu-test
+ (bookmark-set-annotation "name" "foo")
+ (bookmark-bmenu-edit-annotation)
+ (should (string-match "foo" (buffer-string)))
+ (kill-buffer (current-buffer))))
+
+(ert-deftest bookmark-test-bmenu-send-edited-annotation ()
+ (with-bookmark-bmenu-test
+ (bookmark-bmenu-edit-annotation)
+ (insert "foo")
+ (bookmark-edit-annotation-confirm)
+ (should (equal (bookmark-get-annotation "name") "foo"))))
+
+(ert-deftest bookmark-test-bmenu-send-edited-annotation/restore-focus ()
+ "Test for https://debbugs.gnu.org/20150 ."
+ (with-bookmark-bmenu-test
+ (bookmark-bmenu-edit-annotation)
+ (insert "foo")
+ (bookmark-edit-annotation-confirm)
+ (should (equal (buffer-name (current-buffer)) bookmark-bmenu-buffer))
+ (beginning-of-line)
+ (forward-char 4)
+ (should (looking-at "name"))))
+
+(ert-deftest bookmark-test-bmenu-toggle-filenames ()
+ (with-bookmark-bmenu-test
+ (should (re-search-forward "/some/file" nil t))
+ (bookmark-bmenu-toggle-filenames)
+ (goto-char (point-min))
+ (should-not (re-search-forward "/some/file" nil t))))
+
+(ert-deftest bookmark-test-bmenu-toggle-filenames/show ()
+ (with-bookmark-bmenu-test
+ (bookmark-bmenu-toggle-filenames t)
+ (should (re-search-forward "/some/file"))))
+
+(ert-deftest bookmark-test-bmenu-show-filenames ()
+ (with-bookmark-bmenu-test
+ (bookmark-bmenu-show-filenames)
+ (should (re-search-forward "/some/file"))))
+
+(ert-deftest bookmark-test-bmenu-hide-filenames ()
+ (with-bookmark-bmenu-test
+ (bookmark-bmenu-hide-filenames)
+ (goto-char (point-min))
+ (should-not (re-search-forward "/some/file" nil t))))
+
+(ert-deftest bookmark-test-bmenu-bookmark ()
+ (with-bookmark-bmenu-test
+ (should (equal (bookmark-bmenu-bookmark) "name"))))
+
+(ert-deftest bookmark-test-bmenu-mark ()
+ (with-bookmark-bmenu-test
+ (bookmark-bmenu-mark)
+ (forward-line -1)
+ (beginning-of-line)
+ (should (looking-at "^>"))))
+
+(ert-deftest bookmark-test-bmenu-any-marks ()
+ (with-bookmark-bmenu-test
+ (bookmark-bmenu-mark)
+ (beginning-of-line)
+ (should (bookmark-bmenu-any-marks))))
+
+(ert-deftest bookmark-test-bmenu-mark-all ()
+ (with-bookmark-bmenu-test-list
+ (let ((here (point-max)))
+ ;; Expect to not move the point
+ (goto-char here)
+ (bookmark-bmenu-mark-all)
+ (should (equal here (point)))
+ ;; Verify that all bookmarks are marked
+ (goto-char (point-min))
+ (bookmark-bmenu-ensure-position)
+ (should (looking-at "^> "))
+ (should (equal bookmark-tests-bookmark-list-0
+ (bookmark-get-bookmark (bookmark-bmenu-bookmark))))
+ (forward-line 1)
+ (should (looking-at "^> "))
+ (should (equal bookmark-tests-bookmark-list-1
+ (bookmark-get-bookmark (bookmark-bmenu-bookmark))))
+ (forward-line 1)
+ (should (looking-at "^> "))
+ (should (equal bookmark-tests-bookmark-list-2
+ (bookmark-get-bookmark (bookmark-bmenu-bookmark)))))))
+
+(ert-deftest bookmark-test-bmenu-any-marks-list ()
+ (with-bookmark-bmenu-test-list
+ ;; Mark just the second item
+ (goto-char (point-min))
+ (bookmark-bmenu-ensure-position)
+ (forward-line 1)
+ (bookmark-bmenu-mark)
+ ;; Verify that only the second item is marked
+ (goto-char (point-min))
+ (bookmark-bmenu-ensure-position)
+ (should (looking-at "^ "))
+ (should (equal bookmark-tests-bookmark-list-0
+ (bookmark-get-bookmark (bookmark-bmenu-bookmark))))
+ (forward-line 1)
+ (should (looking-at "^> "))
+ (should (equal bookmark-tests-bookmark-list-1
+ (bookmark-get-bookmark (bookmark-bmenu-bookmark))))
+ (forward-line 1)
+ (should (looking-at "^ "))
+ (should (equal bookmark-tests-bookmark-list-2
+ (bookmark-get-bookmark (bookmark-bmenu-bookmark))))
+ ;; There should be at least one mark
+ (should (bookmark-bmenu-any-marks))))
+
+(ert-deftest bookmark-test-bmenu-unmark ()
+ (with-bookmark-bmenu-test
+ (bookmark-bmenu-mark)
+ (goto-char (point-min))
+ (bookmark-bmenu-unmark)
+ (forward-line -1)
+ (beginning-of-line)
+ (should (looking-at "^ "))))
+
+(ert-deftest bookmark-test-bmenu-unmark-all ()
+ (with-bookmark-bmenu-test-list
+ (bookmark-bmenu-mark-all)
+ (let ((here (point-max)))
+ ;; Expect to not move the point
+ (goto-char here)
+ (bookmark-bmenu-unmark-all)
+ (should (equal here (point)))
+ ;; Verify that all bookmarks are unmarked
+ (goto-char (point-min))
+ (bookmark-bmenu-ensure-position)
+ (should (looking-at "^ "))
+ (should (equal bookmark-tests-bookmark-list-0
+ (bookmark-get-bookmark (bookmark-bmenu-bookmark))))
+ (forward-line 1)
+ (should (looking-at "^ "))
+ (should (equal bookmark-tests-bookmark-list-1
+ (bookmark-get-bookmark (bookmark-bmenu-bookmark))))
+ (forward-line 1)
+ (should (looking-at "^ "))
+ (should (equal bookmark-tests-bookmark-list-2
+ (bookmark-get-bookmark (bookmark-bmenu-bookmark)))))))
+
+(ert-deftest bookmark-test-bmenu-delete ()
+ (with-bookmark-bmenu-test
+ (bookmark-bmenu-delete)
+ (bookmark-bmenu-execute-deletions)
+ (should (equal (length bookmark-alist) 0))))
+
+(ert-deftest bookmark-test-bmenu-delete-all ()
+ (with-bookmark-bmenu-test-list
+ ;; Verify that unmarked bookmarks aren't deleted
+ (bookmark-bmenu-execute-deletions)
+ (should-not (eq bookmark-alist nil))
+ (let ((here (point-max)))
+ ;; Expect to not move the point
+ (goto-char here)
+ (bookmark-bmenu-delete-all)
+ (should (equal here (point)))
+ ;; Verify that all bookmarks are marked for deletion
+ (goto-char (point-min))
+ (bookmark-bmenu-ensure-position)
+ (should (looking-at "^D "))
+ (should (equal bookmark-tests-bookmark-list-0
+ (bookmark-get-bookmark (bookmark-bmenu-bookmark))))
+ (forward-line 1)
+ (should (looking-at "^D "))
+ (should (equal bookmark-tests-bookmark-list-1
+ (bookmark-get-bookmark (bookmark-bmenu-bookmark))))
+ (forward-line 1)
+ (should (looking-at "^D "))
+ (should (equal bookmark-tests-bookmark-list-2
+ (bookmark-get-bookmark (bookmark-bmenu-bookmark))))
+ ;; Verify that all bookmarks are deleted
+ (bookmark-bmenu-execute-deletions)
+ (should (eq bookmark-alist nil)))))
+
+(ert-deftest bookmark-test-bmenu-locate ()
+ (let (msg)
+ (cl-letf (((symbol-function 'message)
+ (lambda (&rest args)
+ (setq msg (apply #'format args)))))
+ (with-bookmark-bmenu-test
+ (bookmark-bmenu-locate)
+ (should (equal msg "/some/file"))))))
+
+(ert-deftest bookmark-test-bmenu-filter-alist-by-regexp ()
+ (with-bookmark-bmenu-test
+ (bookmark-bmenu-filter-alist-by-regexp regexp-unmatchable)
+ (goto-char (point-min))
+ (should (looking-at "^$"))))
+
+(provide 'bookmark-tests)
+;;; bookmark-tests.el ends here
diff --git a/test/lisp/buff-menu-tests.el b/test/lisp/buff-menu-tests.el
index 82b34d35d64..8e7981e6999 100644
--- a/test/lisp/buff-menu-tests.el
+++ b/test/lisp/buff-menu-tests.el
@@ -1,6 +1,6 @@
;;; buff-menu-tests.el --- Test suite for buff-menu.el -*- lexical-binding: t -*-
-;; Copyright (C) 2016-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2022 Free Software Foundation, Inc.
;; Author: Tino Calancha <tino.calancha@gmail.com>
@@ -24,19 +24,20 @@
;;; Code:
(require 'ert)
+(eval-when-compile (require 'ert-x))
(ert-deftest buff-menu-24962 ()
"Test for https://debbugs.gnu.org/24962 ."
- (let* ((file (make-temp-file "foo"))
- (buf (find-file file)))
- (unwind-protect
- (progn
- (rename-buffer " foo")
- (list-buffers)
- (with-current-buffer "*Buffer List*"
- (should (string= " foo" (buffer-name (Buffer-menu-buffer))))))
- (and (buffer-live-p buf) (kill-buffer buf))
- (and (file-exists-p file) (delete-file file)))))
+ (ert-with-temp-file file
+ :suffix "foo"
+ (let ((buf (find-file file)))
+ (unwind-protect
+ (progn
+ (rename-buffer " foo")
+ (list-buffers)
+ (with-current-buffer "*Buffer List*"
+ (should (string= " foo" (buffer-name (Buffer-menu-buffer))))))
+ (and (buffer-live-p buf) (kill-buffer buf))))))
(provide 'buff-menu-tests)
diff --git a/test/lisp/button-tests.el b/test/lisp/button-tests.el
new file mode 100644
index 00000000000..99d1ee3de46
--- /dev/null
+++ b/test/lisp/button-tests.el
@@ -0,0 +1,104 @@
+;;; button-tests.el --- tests for button.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2019-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+
+(defvar-keymap button-tests--map
+ :doc "Keymap for testing command substitution."
+ "x" #'ignore)
+
+(ert-deftest button-at ()
+ "Test `button-at' behavior."
+ (with-temp-buffer
+ (should-not (button-at (point)))
+ (let ((button (insert-text-button "text button"))
+ (marker (button-at (1- (point)))))
+ (should (markerp marker))
+ (should (= (button-end button) (button-end marker) (point))))
+ (let ((button (insert-button "overlay button"))
+ (overlay (button-at (1- (point)))))
+ (should (overlayp overlay))
+ (should (eq button overlay)))
+ ;; Buttons and widgets are incompatible (bug#34506).
+ (widget-create 'link "link widget")
+ (should-not (button-at (1- (point))))))
+
+(ert-deftest button--help-echo-string ()
+ "Test `button--help-echo' with strings."
+ (with-temp-buffer
+ ;; Text property buttons.
+ (let ((button (insert-text-button
+ "text" 'help-echo "text: \\<button-tests--map>\\[ignore]")))
+ (should (equal (button--help-echo button) "text: x")))
+ ;; Overlay buttons.
+ (let ((button (insert-button "overlay" 'help-echo
+ "overlay: \\<button-tests--map>\\[ignore]")))
+ (should (equal (button--help-echo button) "overlay: x")))))
+
+(ert-deftest button--help-echo-form ()
+ "Test `button--help-echo' with forms."
+ (with-temp-buffer
+ ;; Test text property buttons with dynamic scoping.
+ (setq lexical-binding nil)
+ (let* ((help (make-symbol "help"))
+ (form `(funcall (let ((,help "lexical form"))
+ (lambda () ,help))))
+ (button (insert-text-button "text" 'help-echo form)))
+ (set help "dynamic: \\<button-tests--map>\\[ignore]")
+ (should (equal (button--help-echo button) "dynamic: x")))
+ ;; Test overlay buttons with lexical scoping.
+ (setq lexical-binding t)
+ (let* ((help (make-symbol "help"))
+ (form `(funcall
+ (let ((,help "lexical: \\<button-tests--map>\\[ignore]"))
+ (lambda () ,help))))
+ (button (insert-button "overlay" 'help-echo form)))
+ (set help "dynamic form")
+ (should (equal (button--help-echo button) "lexical: x")))))
+
+(ert-deftest button--help-echo-function ()
+ "Test `button--help-echo' with functions."
+ (with-temp-buffer
+ ;; Text property buttons.
+ (let* ((owin (selected-window))
+ (obuf (current-buffer))
+ (opos (point))
+ (help (lambda (win obj pos)
+ (should (eq win owin))
+ (should (eq obj obuf))
+ (should (= pos opos))
+ "text: \\<button-tests--map>\\[ignore]"))
+ (button (insert-text-button "text" 'help-echo help)))
+ (should (equal (button--help-echo button) "text: x"))
+ ;; Overlay buttons.
+ (setq help (lambda (win obj pos)
+ (should (eq win owin))
+ (should (overlayp obj))
+ (should (eq obj button))
+ (should (eq (overlay-buffer obj) obuf))
+ (should (= (overlay-start obj) opos))
+ (should (= pos opos))
+ "overlay: \\<button-tests--map>\\[ignore]"))
+ (setq opos (point))
+ (setq button (insert-button "overlay" 'help-echo help))
+ (should (equal (button--help-echo button) "overlay: x")))))
+
+;;; button-tests.el ends here
diff --git a/test/lisp/calc/calc-tests.el b/test/lisp/calc/calc-tests.el
index 727ab049a52..cd984f7ff7e 100644
--- a/test/lisp/calc/calc-tests.el
+++ b/test/lisp/calc/calc-tests.el
@@ -1,6 +1,6 @@
;;; calc-tests.el --- tests for calc -*- lexical-binding: t; -*-
-;; Copyright (C) 2014-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2022 Free Software Foundation, Inc.
;; Author: Leo Liu <sdl.web@gmail.com>
;; Keywords: maint
@@ -29,6 +29,7 @@
(require 'calc)
(require 'calc-ext)
(require 'calc-units)
+(require 'calc-forms)
;; XXX The order in which calc libraries (in particular calc-units)
;; are loaded influences whether a calc integer in an expression
@@ -37,7 +38,7 @@
;; be used to compare such calc expressions.
(defun calc-tests-equal (a b)
"Like `equal' but allow for different representations of numbers.
-For example: (calc-tests-equal 10 '(float 1 1)) => t.
+For example: (calc-tests-equal 10 \\='(float 1 1)) => t.
A and B should be calc expressions."
(cond ((math-numberp a)
(and (math-numberp b)
@@ -52,7 +53,7 @@ A and B should be calc expressions."
(defun calc-tests-simple (fun string &rest args)
"Push STRING on the calc stack, then call FUN and return the new top.
-The result is a calc (i.e., lisp) expression, not its string representation.
+The result is a calc (i.e., Lisp) expression, not its string representation.
Also pop the entire stack afterwards.
An existing calc stack is reused, otherwise a new one is created."
(calc-eval string 'push)
@@ -62,33 +63,37 @@ An existing calc stack is reused, otherwise a new one is created."
(calc-top-n 1))
(calc-pop 0)))
-(ert-deftest test-math-bignum ()
- ;; bug#17556
- (let ((n (math-bignum most-negative-fixnum)))
- (should (math-negp n))
- (should (cl-notany #'cl-minusp (cdr n)))))
-
-(ert-deftest test-calc-remove-units ()
+(ert-deftest calc-remove-units ()
(should (calc-tests-equal (calc-tests-simple #'calc-remove-units "-1 m") -1)))
-(ert-deftest test-calc-extract-units ()
- (should (calc-tests-equal (calc-tests-simple #'calc-extract-units "-1 m")
- '(var m var-m)))
- (should (calc-tests-equal (calc-tests-simple #'calc-extract-units "-1 m*cm")
- '(* (float 1 -2) (^ (var m var-m) 2)))))
-
-(ert-deftest test-calc-convert-units ()
- ;; Used to ask for `(The expression is unitless when simplified) Old Units: '.
- (should (calc-tests-equal (calc-tests-simple #'calc-convert-units "-1 m" nil "cm")
- '(* -100 (var cm var-cm))))
- ;; Gave wrong result.
- (should (calc-tests-equal (calc-tests-simple #'calc-convert-units "-1 m"
- (math-read-expr "1m") "cm")
- '(* -100 (var cm var-cm)))))
-
-(ert-deftest test-calc-23889 ()
+(ert-deftest calc-extract-units ()
+ (let ((calc-display-working-message nil))
+ (should (calc-tests-equal (calc-tests-simple #'calc-extract-units "-1 m")
+ '(var m var-m)))
+ (should (calc-tests-equal (calc-tests-simple #'calc-extract-units "-1 m*cm")
+ '(* (float 1 -2) (^ (var m var-m) 2))))))
+
+(ert-deftest calc-convert-units ()
+ (let ((calc-display-working-message nil))
+ ;; Used to ask `(The expression is unitless when simplified) Old Units: '.
+ (should (calc-tests-equal (calc-tests-simple #'calc-convert-units "-1 m"
+ nil "cm")
+ '(* -100 (var cm var-cm))))
+ ;; Gave wrong result.
+ (should (calc-tests-equal (calc-tests-simple #'calc-convert-units "-1 m"
+ (math-read-expr "1m") "cm")
+ '(* -100 (var cm var-cm))))))
+
+(ert-deftest calc-imaginary-i ()
+ "Test `math-imaginary-i' for non-special-const values."
+ (let ((var-i (calcFunc-polar (calcFunc-sqrt -1))))
+ (should (math-imaginary-i)))
+ (let ((var-i (calcFunc-sqrt -1)))
+ (should (math-imaginary-i))))
+
+(ert-deftest calc-bug-23889 ()
"Test for https://debbugs.gnu.org/23889 and 25652."
- (skip-unless (>= math-bignum-digit-length 9))
+ (skip-unless t) ;; (>= math-bignum-digit-length 9))
(dolist (mode '(deg rad))
(let ((calc-angle-mode mode))
;; If user inputs angle units, then should ignore `calc-angle-mode'.
@@ -131,9 +136,685 @@ An existing calc stack is reused, otherwise a new one is created."
(nth 1 (calcFunc-cos 1)))
0 4))))))
+(ert-deftest calc-trig ()
+ "Trigonometric simplification; bug#33052."
+ (let ((calc-angle-mode 'rad))
+ (let ((calc-symbolic-mode t))
+ (should (equal (math-simplify '(calcFunc-sin (/ (var pi var-pi) 4)))
+ '(/ (calcFunc-sqrt 2) 2)))
+ (should (equal (math-simplify '(calcFunc-cos (/ (var pi var-pi) 4)))
+ '(/ (calcFunc-sqrt 2) 2)))
+ (should (equal (math-simplify '(calcFunc-sec (/ (var pi var-pi) 4)))
+ '(calcFunc-sqrt 2)))
+ (should (equal (math-simplify '(calcFunc-csc (/ (var pi var-pi) 4)))
+ '(calcFunc-sqrt 2)))
+ (should (equal (math-simplify '(calcFunc-tan (/ (var pi var-pi) 3)))
+ '(calcFunc-sqrt 3)))
+ (should (equal (math-simplify '(calcFunc-cot (/ (var pi var-pi) 3)))
+ '(/ (calcFunc-sqrt 3) 3))))
+ (let ((calc-symbolic-mode nil))
+ (should (equal (math-simplify '(calcFunc-sin (/ (var pi var-pi) 4)))
+ '(calcFunc-sin (/ (var pi var-pi) 4))))
+ (should (equal (math-simplify '(calcFunc-cos (/ (var pi var-pi) 4)))
+ '(calcFunc-cos (/ (var pi var-pi) 4))))
+ (should (equal (math-simplify '(calcFunc-sec (/ (var pi var-pi) 4)))
+ '(calcFunc-sec (/ (var pi var-pi) 4))))
+ (should (equal (math-simplify '(calcFunc-csc (/ (var pi var-pi) 4)))
+ '(calcFunc-csc (/ (var pi var-pi) 4))))
+ (should (equal (math-simplify '(calcFunc-tan (/ (var pi var-pi) 3)))
+ '(calcFunc-tan (/ (var pi var-pi) 3))))
+ (should (equal (math-simplify '(calcFunc-cot (/ (var pi var-pi) 3)))
+ '(calcFunc-cot (/ (var pi var-pi) 3)))))))
+
+(ert-deftest calc-format-radix ()
+ "Test integer formatting (bug#36689)."
+ (let ((calc-group-digits nil))
+ (let ((calc-number-radix 10))
+ (should (equal (math-format-number 12345678901) "12345678901")))
+ (let ((calc-number-radix 2))
+ (should (equal (math-format-number 12345) "2#11000000111001")))
+ (let ((calc-number-radix 8))
+ (should (equal (math-format-number 12345678901) "8#133767016065")))
+ (let ((calc-number-radix 16))
+ (should (equal (math-format-number 12345678901) "16#2DFDC1C35")))
+ (let ((calc-number-radix 36))
+ (should (equal (math-format-number 12345678901) "36#5O6AQT1"))))
+ (let ((calc-group-digits t))
+ (let ((calc-number-radix 10))
+ (should (equal (math-format-number 12345678901) "12,345,678,901")))
+ (let ((calc-number-radix 2))
+ (should (equal (math-format-number 12345) "2#11,0000,0011,1001")))
+ (let ((calc-number-radix 8))
+ (should (equal (math-format-number 12345678901) "8#133,767,016,065")))
+ (let ((calc-number-radix 16))
+ (should (equal (math-format-number 12345678901) "16#2,DFDC,1C35")))
+ (let ((calc-number-radix 36))
+ (should (equal (math-format-number 12345678901) "36#5,O6A,QT1")))))
+
+(ert-deftest calc-digit-after-point ()
+ "Test display of trailing 0 after decimal point (bug#47302)."
+ (let ((calc-digit-after-point nil))
+ ;; Integral floats have no digits after the decimal point (default).
+ (should (equal (math-format-number '(float 0 0)) "0."))
+ (should (equal (math-format-number '(float 5 0)) "5."))
+ (should (equal (math-format-number '(float 3 1)) "30."))
+ (should (equal (math-format-number '(float 23 0)) "23."))
+ (should (equal (math-format-number '(float 123 0)) "123."))
+ (should (equal (math-format-number '(float 1 -1)) "0.1"))
+ (should (equal (math-format-number '(float 54 -1)) "5.4"))
+ (should (equal (math-format-number '(float 1 -4)) "1e-4"))
+ (should (equal (math-format-number '(float 1 14)) "1e14"))
+ (should (equal (math-format-number 12) "12")))
+ (let ((calc-digit-after-point t))
+ ;; Integral floats have at least one digit after the decimal point.
+ (should (equal (math-format-number '(float 0 0)) "0.0"))
+ (should (equal (math-format-number '(float 5 0)) "5.0"))
+ (should (equal (math-format-number '(float 3 1)) "30.0"))
+ (should (equal (math-format-number '(float 23 0)) "23.0"))
+ (should (equal (math-format-number '(float 123 0)) "123.0"))
+ (should (equal (math-format-number '(float 1 -1)) "0.1"))
+ (should (equal (math-format-number '(float 54 -1)) "5.4"))
+ (should (equal (math-format-number '(float 1 -4)) "1e-4"))
+ (should (equal (math-format-number '(float 1 14)) "1e14"))
+ (should (equal (math-format-number 12) "12"))))
+
+(ert-deftest calc-calendar ()
+ "Test calendar conversions (bug#36822)."
+ (should (equal (calcFunc-julian (math-parse-date "2019-07-27")) 2458692))
+ (should (equal (math-parse-date "2019-07-27") '(date 737267)))
+ (should (equal (calcFunc-julian '(date 0)) 1721425))
+ (should (equal (math-date-to-gregorian-dt 1) '(1 1 1)))
+ (should (equal (math-date-to-gregorian-dt 0) '(-1 12 31)))
+ (should (equal (math-date-to-gregorian-dt -1721425) '(-4714 11 24)))
+ (should (equal (math-absolute-from-gregorian-dt 2019 7 27) 737267))
+ (should (equal (math-absolute-from-gregorian-dt 1 1 1) 1))
+ (should (equal (math-absolute-from-gregorian-dt -1 12 31) 0))
+ (should (equal (math-absolute-from-gregorian-dt -99 12 31) -35795))
+ (should (equal (math-absolute-from-gregorian-dt -4714 11 24) -1721425))
+ (should (equal (calcFunc-julian '(date -1721425)) 0))
+ (should (equal (math-date-to-julian-dt 1) '(1 1 3)))
+ (should (equal (math-date-to-julian-dt -1721425) '(-4713 1 1)))
+ (should (equal (math-absolute-from-julian-dt 2019 1 1) 737073))
+ (should (equal (math-absolute-from-julian-dt 1 1 3) 1))
+ (should (equal (math-absolute-from-julian-dt -101 1 1) -36892))
+ (should (equal (math-absolute-from-julian-dt -101 3 1) -36832))
+ (should (equal (math-absolute-from-julian-dt -4713 1 1) -1721425)))
+
+(ert-deftest calc-solve-linear-system ()
+ "Test linear system solving (bug#35374)."
+ ;; x + y = 3
+ ;; 2x - 3y = -4
+ ;; with the unique solution x=1, y=2
+ (should (equal
+ (calcFunc-solve
+ '(vec
+ (calcFunc-eq (+ (var x var-x) (var y var-y)) 3)
+ (calcFunc-eq (- (* 2 (var x var-x)) (* 3 (var y var-y))) -4))
+ '(vec (var x var-x) (var y var-y)))
+ '(vec (calcFunc-eq (var x var-x) 1)
+ (calcFunc-eq (var y var-y) 2))))
+
+ ;; x + y = 1
+ ;; x + y = 2
+ ;; has no solution
+ (should (equal
+ (calcFunc-solve
+ '(vec
+ (calcFunc-eq (+ (var x var-x) (var y var-y)) 1)
+ (calcFunc-eq (+ (var x var-x) (var y var-y)) 2))
+ '(vec (var x var-x) (var y var-y)))
+ '(calcFunc-solve
+ (vec
+ (calcFunc-eq (+ (var x var-x) (var y var-y)) 1)
+ (calcFunc-eq (+ (var x var-x) (var y var-y)) 2))
+ (vec (var x var-x) (var y var-y)))))
+ ;; x - y = 1
+ ;; x + y = 1
+ ;; with the unique solution x=1, y=0
+ (should (equal
+ (calcFunc-solve
+ '(vec
+ (calcFunc-eq (- (var x var-x) (var y var-y)) 1)
+ (calcFunc-eq (+ (var x var-x) (var y var-y)) 1))
+ '(vec (var x var-x) (var y var-y)))
+ '(vec (calcFunc-eq (var x var-x) 1)
+ (calcFunc-eq (var y var-y) 0))))
+ ;; 2x - 3y + z = 5
+ ;; x + y - 2z = 0
+ ;; -x + 2y + 3z = -3
+ ;; with the unique solution x=1, y=-1, z=0
+ (should (equal
+ (calcFunc-solve
+ '(vec
+ (calcFunc-eq
+ (+ (- (* 2 (var x var-x)) (* 3 (var y var-y))) (var z var-z))
+ 5)
+ (calcFunc-eq
+ (- (+ (var x var-x) (var y var-y)) (* 2 (var z var-z)))
+ 0)
+ (calcFunc-eq
+ (+ (- (* 2 (var y var-y)) (var x var-x)) (* 3 (var z var-z)))
+ -3))
+ '(vec (var x var-x) (var y var-y) (var z var-z)))
+ ;; The `float' forms in the result are just artifacts of Calc's
+ ;; current solver; it should be fixed to produce exact (integral)
+ ;; results in this case.
+ '(vec (calcFunc-eq (var x var-x) (float 1 0))
+ (calcFunc-eq (var y var-y) (float -1 0))
+ (calcFunc-eq (var z var-z) 0))))
+ ;; x = y + 1
+ ;; x = y
+ ;; has no solution
+ (should (equal
+ (calcFunc-solve
+ '(vec
+ (calcFunc-eq (var x var-x) (+ (var y var-y) 1))
+ (calcFunc-eq (var x var-x) (var y var-y)))
+ '(vec (var x var-x) (var y var-y)))
+ '(calcFunc-solve
+ (vec
+ (calcFunc-eq (var x var-x) (+ (var y var-y) 1))
+ (calcFunc-eq (var x var-x) (var y var-y)))
+ (vec (var x var-x) (var y var-y)))))
+ ;; x + y + z = 6
+ ;; x + y = 3
+ ;; x - y = 1
+ ;; with the unique solution x=2, y=1, z=3
+ (should (equal
+ (calcFunc-solve
+ '(vec
+ (calcFunc-eq (+ (+ (var x var-x) (var y var-y)) (var z var-z)) 6)
+ (calcFunc-eq (+ (var x var-x) (var y var-y)) 3)
+ (calcFunc-eq (- (var x var-x) (var y var-y)) 1))
+ '(vec (var x var-x) (var y var-y) (var z var-z)))
+ '(vec
+ (calcFunc-eq (var x var-x) 2)
+ (calcFunc-eq (var y var-y) 1)
+ (calcFunc-eq (var z var-z) 3))))
+ ;; x = 3
+ ;; x + 4y^2 = 3 (ok, so this one isn't linear)
+ ;; with the unique (double) solution x=3, y=0
+ (should (equal
+ (calcFunc-solve
+ '(vec
+ (calcFunc-eq (var x var-x) 3)
+ (calcFunc-eq (+ (var x var-x) (* 4 (^ (var y var-y) 2))) 3))
+ '(vec (var x var-x) (var y var-y)))
+ '(vec (calcFunc-eq (var x var-x) 3)
+ (calcFunc-eq (var y var-y) 0)))))
+
+(ert-deftest calc-poly-div ()
+ "Test polynomial division, and that the remainder is recorded in the trail."
+ (with-current-buffer (calc-trail-buffer)
+ (let ((inhibit-read-only t))
+ (erase-buffer)
+
+ (calc-eval "2x**3+1" 'push)
+ (calc-eval "x**2+2x" 'push)
+ (calc-poly-div nil)
+ (let ((tos (calc-top-n 1))
+ (trail (buffer-string)))
+ (calc-pop 0)
+ (should (equal tos '(- (* 2 (var x var-x)) 4)))
+ (should (equal trail "pdiv 2 * x - 4\nprem 8 * x + 1\n"))))))
+
+(ert-deftest calc-Math-integerp ()
+ (should (Math-integerp -7))
+ (should (Math-integerp (ash 1 65)))
+ (should-not (Math-integerp '(float 1 0)))
+ (should-not (Math-integerp nil))
+
+ (should (Math-num-integerp -7))
+ (should (Math-num-integerp (ash 1 65)))
+ (should (Math-num-integerp '(float 1 0)))
+ (should-not (Math-num-integerp nil)))
+
+(ert-deftest calc-matrix-determinant ()
+ (let ((calc-display-working-message nil))
+ (should (equal (calcFunc-det '(vec (vec 3)))
+ 3))
+ (should (equal (calcFunc-det '(vec (vec 2 3) (vec 6 7)))
+ -4))
+ (should (equal (calcFunc-det '(vec (vec 1 2 3) (vec 4 5 7) (vec 9 6 2)))
+ 15))
+ (should (equal (calcFunc-det '(vec (vec 0 5 7 3)
+ (vec 0 0 2 0)
+ (vec 1 2 3 4)
+ (vec 0 0 0 3)))
+ 30))
+ (should (equal (calcFunc-det '(vec (vec (var a var-a))))
+ '(var a var-a)))
+ (should (equal (calcFunc-det '(vec (vec 2 (var a var-a))
+ (vec 7 (var a var-a))))
+ '(* -5 (var a var-a))))
+ (should (equal (calcFunc-det '(vec (vec 1 0 0 0)
+ (vec 0 1 0 0)
+ (vec 0 0 0 1)
+ (vec 0 0 (var a var-a) 0)))
+ '(neg (var a var-a))))))
+
+(ert-deftest calc-gcd ()
+ (should (equal (calcFunc-gcd 3 4) 1))
+ (should (equal (calcFunc-gcd 12 15) 3))
+ (should (equal (calcFunc-gcd -12 15) 3))
+ (should (equal (calcFunc-gcd 12 -15) 3))
+ (should (equal (calcFunc-gcd -12 -15) 3))
+ (should (equal (calcFunc-gcd 0 5) 5))
+ (should (equal (calcFunc-gcd 5 0) 5))
+ (should (equal (calcFunc-gcd 0 -5) 5))
+ (should (equal (calcFunc-gcd -5 0) 5))
+ (should (equal (calcFunc-gcd 0 0) 0))
+ (should (equal (calcFunc-gcd 0 '(var x var-x))
+ '(calcFunc-abs (var x var-x))))
+ (should (equal (calcFunc-gcd '(var x var-x) 0)
+ '(calcFunc-abs (var x var-x)))))
+
+(ert-deftest calc-sum-gcd ()
+ ;; sum(gcd(0,n),n,-1,-1)
+ (should (equal (math-simplify '(calcFunc-sum (calcFunc-gcd 0 (var n var-n))
+ (var n var-n) -1 -1))
+ 1))
+ ;; sum(sum(gcd(n,k),k,-1,1),n,-1,1)
+ (should (equal (math-simplify
+ '(calcFunc-sum
+ (calcFunc-sum (calcFunc-gcd (var n var-n) (var k var-k))
+ (var k var-k) -1 1)
+ (var n var-n) -1 1))
+ 8)))
+
+(defun calc-tests--fac (n)
+ (apply #'* (number-sequence 1 n)))
+
+(defun calc-tests--choose (n k)
+ "N choose K, reference implementation."
+ (cond
+ ((and (integerp n) (integerp k))
+ (if (<= 0 n)
+ (if (<= 0 k n)
+ (/ (calc-tests--fac n)
+ (* (calc-tests--fac k) (calc-tests--fac (- n k))))
+ 0) ; 0≤n<k
+ ;; n<0, n and k integers: use extension from M. J. Kronenburg
+ (cond
+ ((<= 0 k)
+ (* (expt -1 k)
+ (calc-tests--choose (+ (- n) k -1) k)))
+ ((<= k n)
+ (* (expt -1 (- n k))
+ (calc-tests--choose (+ (- k) -1) (- n k))))
+ (t ; n<k<0
+ 0))))
+ ((natnump k)
+ ;; Generalization for any n, integral k≥0: use falling product
+ (/ (apply '* (number-sequence n (- n (1- k)) -1))
+ (calc-tests--fac k)))
+ (t (error "Case not covered"))))
+
+(defun calc-tests--calc-to-number (x)
+ "Convert a Calc object to a Lisp number."
+ (pcase x
+ ((pred numberp) x)
+ (`(frac ,p ,q) (/ (float p) q))
+ (`(float ,m ,e) (* m (expt 10 e)))
+ (_ (error "calc object not converted: %S" x))))
+
+(ert-deftest calc-choose ()
+ "Test computation of binomial coefficients (bug#16999)."
+ (let ((calc-display-working-message nil))
+ ;; Integral arguments
+ (dolist (n (number-sequence -6 6))
+ (dolist (k (number-sequence -6 6))
+ (should (equal (calcFunc-choose n k)
+ (calc-tests--choose n k)))))
+
+ ;; Fractional n, natural k
+ (should (equal (calc-tests--calc-to-number
+ (calcFunc-choose '(frac 15 2) 3))
+ (calc-tests--choose 7.5 3)))
+
+ (should (equal (calc-tests--calc-to-number
+ (calcFunc-choose '(frac 1 2) 2))
+ (calc-tests--choose 0.5 2)))
+
+ (should (equal (calc-tests--calc-to-number
+ (calcFunc-choose '(frac -15 2) 3))
+ (calc-tests--choose -7.5 3)))))
+
+(ert-deftest calc-business-days ()
+ (cl-flet ((m (s) (math-parse-date s))
+ (b+ (a b) (calcFunc-badd a b))
+ (b- (a b) (calcFunc-bsub a b)))
+ ;; Sanity check.
+ (should (equal (m "2020-09-07") '(date 737675)))
+
+ ;; Test with standard business days (Mon-Fri):
+ (should (equal (b+ (m "2020-09-07") 1) (m "2020-09-08"))) ; Mon->Tue
+ (should (equal (b+ (m "2020-09-08") 1) (m "2020-09-09"))) ; Tue->Wed
+ (should (equal (b+ (m "2020-09-09") 1) (m "2020-09-10"))) ; Wed->Thu
+ (should (equal (b+ (m "2020-09-10") 1) (m "2020-09-11"))) ; Thu->Fri
+ (should (equal (b+ (m "2020-09-11") 1) (m "2020-09-14"))) ; Fri->Mon
+
+ (should (equal (b+ (m "2020-09-07") 4) (m "2020-09-11"))) ; Mon->Fri
+ (should (equal (b+ (m "2020-09-07") 6) (m "2020-09-15"))) ; Mon->Tue
+
+ (should (equal (b+ (m "2020-09-12") 1) (m "2020-09-14"))) ; Sat->Mon
+ (should (equal (b+ (m "2020-09-13") 1) (m "2020-09-14"))) ; Sun->Mon
+
+ (should (equal (b- (m "2020-09-11") 1) (m "2020-09-10"))) ; Fri->Thu
+ (should (equal (b- (m "2020-09-10") 1) (m "2020-09-09"))) ; Thu->Wed
+ (should (equal (b- (m "2020-09-09") 1) (m "2020-09-08"))) ; Wed->Tue
+ (should (equal (b- (m "2020-09-08") 1) (m "2020-09-07"))) ; Tue->Mon
+ (should (equal (b- (m "2020-09-07") 1) (m "2020-09-04"))) ; Mon->Fri
+
+ (should (equal (b- (m "2020-09-11") 4) (m "2020-09-07"))) ; Fri->Mon
+ (should (equal (b- (m "2020-09-15") 6) (m "2020-09-07"))) ; Tue->Mon
+
+ (should (equal (b- (m "2020-09-12") 1) (m "2020-09-11"))) ; Sat->Fri
+ (should (equal (b- (m "2020-09-13") 1) (m "2020-09-11"))) ; Sun->Fri
+
+ ;; Stepping fractional days
+ (should (equal (b+ (m "2020-09-08 21:00") '(frac 1 2))
+ (m "2020-09-09 09:00")))
+ (should (equal (b+ (m "2020-09-11 21:00") '(frac 1 2))
+ (m "2020-09-14 09:00")))
+ (should (equal (b- (m "2020-09-08 21:00") '(frac 1 2))
+ (m "2020-09-08 09:00")))
+ (should (equal (b- (m "2020-09-14 06:00") '(frac 1 2))
+ (m "2020-09-11 18:00")))
+
+ ;; Test with a couple of extra days off:
+ (let ((var-Holidays (list 'vec
+ '(var sat var-sat) '(var sun var-sun)
+ (m "2020-09-09") (m "2020-09-11"))))
+
+ (should (equal (b+ (m "2020-09-07") 1) (m "2020-09-08"))) ; Mon->Tue
+ (should (equal (b+ (m "2020-09-08") 1) (m "2020-09-10"))) ; Tue->Thu
+ (should (equal (b+ (m "2020-09-10") 1) (m "2020-09-14"))) ; Thu->Mon
+ (should (equal (b+ (m "2020-09-14") 1) (m "2020-09-15"))) ; Mon->Tue
+ (should (equal (b+ (m "2020-09-15") 1) (m "2020-09-16"))) ; Tue->Wed
+
+ (should (equal (b- (m "2020-09-16") 1) (m "2020-09-15"))) ; Wed->Tue
+ (should (equal (b- (m "2020-09-15") 1) (m "2020-09-14"))) ; Tue->Mon
+ (should (equal (b- (m "2020-09-14") 1) (m "2020-09-10"))) ; Mon->Thu
+ (should (equal (b- (m "2020-09-10") 1) (m "2020-09-08"))) ; Thu->Tue
+ (should (equal (b- (m "2020-09-08") 1) (m "2020-09-07"))) ; Tue->Mon
+ )
+
+ ;; Test with odd non-business weekdays (Tue, Wed, Sat):
+ (let ((var-Holidays '(vec (var tue var-tue)
+ (var wed var-wed)
+ (var sat var-sat))))
+ (should (equal (b+ (m "2020-09-07") 1) (m "2020-09-10"))) ; Mon->Thu
+ (should (equal (b+ (m "2020-09-10") 1) (m "2020-09-11"))) ; Thu->Fri
+ (should (equal (b+ (m "2020-09-11") 1) (m "2020-09-13"))) ; Fri->Sun
+ (should (equal (b+ (m "2020-09-13") 1) (m "2020-09-14"))) ; Sun->Mon
+
+ (should (equal (b- (m "2020-09-14") 1) (m "2020-09-13"))) ; Mon->Sun
+ (should (equal (b- (m "2020-09-13") 1) (m "2020-09-11"))) ; Sun->Fri
+ (should (equal (b- (m "2020-09-11") 1) (m "2020-09-10"))) ; Fri->Thu
+ (should (equal (b- (m "2020-09-10") 1) (m "2020-09-07"))) ; Thu->Mon
+ )
+ ))
+
+(ert-deftest calc-unix-date ()
+ (let* ((d-1970-01-01 (math-parse-date "1970-01-01"))
+ (d-2020-09-07 (math-parse-date "2020-09-07"))
+ (d-1991-01-09-0600 (math-parse-date "1991-01-09 06:00")))
+ ;; calcFunc-unixtime (command "t U") converts a date value to Unix time,
+ ;; and a number to a date.
+ (should (equal d-1970-01-01 '(date 719163)))
+ (should (equal (calcFunc-unixtime d-1970-01-01 0) 0))
+ (should (equal (calc-tests--calc-to-number (cadr (calcFunc-unixtime 0 0)))
+ (cadr d-1970-01-01)))
+ (should (equal (calcFunc-unixtime d-2020-09-07 0)
+ (* (- (cadr d-2020-09-07)
+ (cadr d-1970-01-01))
+ 86400)))
+ (should (equal (calcFunc-unixtime d-1991-01-09-0600 0)
+ 663400800))
+ (should (equal (calc-tests--calc-to-number
+ (cadr (calcFunc-unixtime 663400800 0)))
+ 726841.25))
+
+ (let ((calc-date-format '(U)))
+ ;; Test parsing Unix time.
+ (should (equal (calc-tests--calc-to-number
+ (cadr (math-parse-date "0")))
+ 719163))
+ (should (equal (calc-tests--calc-to-number
+ (cadr (math-parse-date "469324800")))
+ (+ 719163 (/ 469324800 86400))))
+ (should (equal (calc-tests--calc-to-number
+ (cadr (math-parse-date "663400800")))
+ 726841.25))
+
+ ;; Test formatting Unix time.
+ (should (equal (math-format-date d-1970-01-01) "0"))
+ (should (equal (math-format-date d-2020-09-07)
+ (number-to-string (* (- (cadr d-2020-09-07)
+ (cadr d-1970-01-01))
+ 86400))))
+ (should (equal (math-format-date d-1991-01-09-0600) "663400800")))))
+
+;; Reference implementations of bit operations:
+
+(defun calc-tests--clip (x w)
+ "Clip X to W bits, signed if W is negative, otherwise unsigned."
+ (cond ((zerop w) x)
+ ((> w 0) (logand x (- (ash 1 w) 1)))
+ (t (let ((y (calc-tests--clip x (- w)))
+ (msb (ash 1 (- (- w) 1))))
+ (- y (ash (logand y msb) 1))))))
+
+(defun calc-tests--not (x w)
+ "Bitwise complement of X, word size W."
+ (calc-tests--clip (lognot x) w))
+
+(defun calc-tests--and (x y w)
+ "Bitwise AND of X and W, word size W."
+ (calc-tests--clip (logand x y) w))
+
+(defun calc-tests--or (x y w)
+ "Bitwise OR of X and Y, word size W."
+ (calc-tests--clip (logior x y) w))
+
+(defun calc-tests--xor (x y w)
+ "Bitwise XOR of X and Y, word size W."
+ (calc-tests--clip (logxor x y) w))
+
+(defun calc-tests--diff (x y w)
+ "Bitwise AND of X and NOT Y, word size W."
+ (calc-tests--clip (logand x (lognot y)) w))
+
+(defun calc-tests--lsh (x n w)
+ "Logical shift left X by N steps, word size W."
+ (if (< n 0)
+ (calc-tests--rsh x (- n) w)
+ (calc-tests--clip (ash x n) w)))
+
+(defun calc-tests--rsh (x n w)
+ "Logical shift right X by N steps, word size W."
+ (if (< n 0)
+ (calc-tests--lsh x (- n) w)
+ ;; First zero-extend, then shift.
+ (calc-tests--clip
+ (ash (calc-tests--clip x (abs w)) (- n))
+ w)))
+
+(defun calc-tests--ash (x n w)
+ "Arithmetic shift left X by N steps, word size W."
+ (if (< n 0)
+ (calc-tests--rash x (- n) w)
+ (calc-tests--clip (ash x n) w)))
+
+(defun calc-tests--rash (x n w)
+ "Arithmetic shift right X by N steps, word size W."
+ (if (< n 0)
+ (calc-tests--ash x (- n) w)
+ ;; First sign-extend, then shift.
+ (calc-tests--clip
+ (ash (calc-tests--clip x (- (abs w))) (- n))
+ w)))
+
+(defun calc-tests--rot (x n w)
+ "Rotate X left by N steps, word size W."
+ (when (zerop w)
+ (error "Undefined"))
+ (let* ((aw (abs w))
+ (y (calc-tests--clip x aw))
+ (steps (mod n aw)))
+ (calc-tests--clip (logior (ash y steps) (ash y (- steps aw)))
+ w)))
+
+(ert-deftest calc-shift-binary ()
+ (dolist (w '(16 32 -16 -32 0))
+ (dolist (x '(0 1 #x1234 #x8000 #xabcd #xffff
+ #x12345678 #xabcdef12 #x80000000 #xffffffff
+ #x1234567890ab #x1234967890ab
+ -1 -14 #x-8000 #x-ffff #x-8001 #x-10000
+ #x-80000000 #x-ffffffff #x-80000001 #x-100000000))
+ (dolist (n '(0 1 4 16 32 -1 -4 -16 -32))
+ (should (equal (calcFunc-lsh x n w)
+ (calc-tests--lsh x n w)))
+ (should (equal (calcFunc-rsh x n w)
+ (calc-tests--rsh x n w)))
+ (should (equal (calcFunc-ash x n w)
+ (calc-tests--ash x n w)))
+ (should (equal (calcFunc-rash x n w)
+ (calc-tests--rash x n w)))
+ (unless (zerop w)
+ (should (equal (calcFunc-rot x n w)
+ (calc-tests--rot x n w)))))))
+ (should-error (calcFunc-rot 1 1 0)))
+
+(ert-deftest calc-bit-ops ()
+ (dolist (w '(16 32 -16 -32 0))
+ (dolist (x '(0 1 #x1234 #x8000 #xabcd #xffff
+ #x12345678 #xabcdef12 #x80000000 #xffffffff
+ #x1234567890ab #x1234967890ab
+ -1 -14 #x-8000 #x-ffff #x-8001 #x-10000
+ #x-80000000 #x-ffffffff #x-80000001 #x-100000000))
+ (should (equal (calcFunc-not x w)
+ (calc-tests--not x w)))
+
+ (dolist (n '(0 1 4 16 32 -1 -4 -16 -32))
+ (equal (calcFunc-clip x n)
+ (calc-tests--clip x n)))
+
+ (dolist (y '(0 1 #x1234 #x8000 #xabcd #xffff
+ #x12345678 #xabcdef12 #x80000000 #xffffffff
+ #x1234567890ab #x1234967890ab
+ -1 -14 #x-8000 #x-ffff #x-8001 #x-10000
+ #x-80000000 #x-ffffffff #x-80000001 #x-100000000))
+ (should (equal (calcFunc-and x y w)
+ (calc-tests--and x y w)))
+ (should (equal (calcFunc-or x y w)
+ (calc-tests--or x y w)))
+ (should (equal (calcFunc-xor x y w)
+ (calc-tests--xor x y w)))
+ (should (equal (calcFunc-diff x y w)
+ (calc-tests--diff x y w)))))))
+
+(ert-deftest calc-latex-input ()
+ ;; Check precedence of "/" in LaTeX input mode.
+ (should (equal (math-read-exprs "a+b/c*d")
+ '((+ (var a var-a) (/ (var b var-b)
+ (* (var c var-c) (var d var-d)))))))
+ (unwind-protect
+ (progn
+ (calc-set-language 'latex)
+ (should (equal (math-read-exprs "a+b/c*d")
+ '((+ (var a var-a) (/ (var b var-b)
+ (* (var c var-c) (var d var-d)))))))
+ (should (equal (math-read-exprs "a+b\\over c*d")
+ '((/ (+ (var a var-a) (var b var-b))
+ (* (var c var-c) (var d var-d))))))
+ (should (equal (math-read-exprs "a/b/c")
+ '((/ (/ (var a var-a) (var b var-b))
+ (var c var-c))))))
+ (calc-set-language nil)))
+
+(defvar var-g)
+
+;; Test `let'.
+(defmath test1 (x)
+ (let ((x (+ x 1))
+ (y (+ x 3)))
+ (let ((z (+ y 6)))
+ (* x y z g))))
+
+;; Test `let*'.
+(defmath test2 (x)
+ (let* ((y (+ x 1))
+ (z (+ y 3)))
+ (let* ((u (+ z 6)))
+ (* x y z u g))))
+
+;; Test `for'.
+(defmath test3 (x)
+ (let ((s 0))
+ (for ((ii 1 x)
+ (jj 1 ii))
+ (setq s (+ s (* ii jj))))
+ s))
+
+;; Test `for' with non-unit stride.
+(defmath test4 (x)
+ (let ((l nil))
+ (for ((ii 1 x 1)
+ (jj 1 10 ii))
+ (setq l ('cons jj l))) ; Use Lisp `cons', not `calcFunc-cons'.
+ (reverse l)))
+
+;; Test `foreach'.
+(defmath test5 (x)
+ (let ((s 0))
+ (foreach ((a x)
+ (b a))
+ (setq s (+ s b)))
+ s))
+
+;; Test `break'.
+(defmath test6 (x)
+ (let ((a (for ((ii 1 10))
+ (when (= ii x)
+ (break (* ii 2)))))
+ (b (foreach ((e '(9 3 6)))
+ (when (= e x)
+ (break (- e 1))))))
+ (* a b)))
+
+;; Test `return' from `for'.
+(defmath test7 (x)
+ (for ((ii 1 10))
+ (when (= ii x)
+ (return (* ii 2))))
+ 5)
+
+(ert-deftest calc-defmath ()
+ (let ((var-g 17))
+ (should (equal (calcFunc-test1 2) (* 3 5 11 17)))
+ (should (equal (calcFunc-test2 2) (* 2 3 6 12 17))))
+ (should (equal (calcFunc-test3 3)
+ (+ (* 1 1)
+ (* 2 1) (* 2 2)
+ (* 3 1) (* 3 2) (* 3 3))))
+ (should (equal (calcFunc-test4 5)
+ '( 1 2 3 4 5 6 7 8 9 10
+ 1 3 5 7 9
+ 1 4 7 10
+ 1 5 9
+ 1 6)))
+ (should (equal (calcFunc-test5 '((2 3) (5) (7 11 13)))
+ (+ 2 3 5 7 11 13)))
+ (should (equal (calcFunc-test6 3) (* (* 3 2) (- 3 1))))
+ (should (equal (calcFunc-test7 3) (* 3 2))))
+
+(ert-deftest calc-nth-root ()
+ ;; bug#51209
+ (let* ((calc-display-working-message nil)
+ (x (calc-tests--calc-to-number (math-pow 8 '(frac 1 6)))))
+ (should (< (abs (- x (sqrt 2.0))) 1.0e-10))))
+
(provide 'calc-tests)
;;; calc-tests.el ends here
-
-;; Local Variables:
-;; bug-reference-url-format: "https://debbugs.gnu.org/%s"
-;; End:
diff --git a/test/lisp/calculator-tests.el b/test/lisp/calculator-tests.el
new file mode 100644
index 00000000000..c1a1942cf7c
--- /dev/null
+++ b/test/lisp/calculator-tests.el
@@ -0,0 +1,51 @@
+;;; calculator-tests.el --- Test suite for calculator. -*- lexical-binding: t -*-
+
+;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+(require 'ert)
+(require 'calculator)
+
+(ert-deftest calculator-test-calculator-string-to-number ()
+ (dolist (x '(("" 0.0)
+ ("+" 0.0)
+ ("-" 0.0)
+ ("." 0.0)
+ ("+." 0.0)
+ ("-." -0.0)
+ (".-" 0.0)
+ ("--." 0.0)
+ ("-0.0e" -0.0)
+ ("1e1" 10.0)
+ ("1e+1" 10.0)
+ ("1e-1" 0.1)
+ ("+1e1" 10.0)
+ ("-1e1" -10.0)
+ ("+1e-1" 0.1)
+ ("-1e-1" -0.1)
+ (".1.e1" 0.1)
+ (".1..e1" 0.1)
+ ("1e+1.1" 10.0)
+ ("-2e-1.1" -0.2)))
+ (pcase x
+ (`(,str ,expected)
+ (let ((calculator-input-radix nil))
+ (should (equal (calculator-string-to-number str) expected)))))))
+
+(provide 'calculator-tests)
+;;; calculator-tests.el ends here
diff --git a/test/lisp/calendar/cal-french-tests.el b/test/lisp/calendar/cal-french-tests.el
new file mode 100644
index 00000000000..771681228e6
--- /dev/null
+++ b/test/lisp/calendar/cal-french-tests.el
@@ -0,0 +1,114 @@
+;;; cal-french-tests.el --- tests for cal-french.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'cal-french)
+
+(defconst cal-french-test-cases
+ '(
+ (1792 9 22 "Primidi 1 Vendémiaire an 1 de la Révolution, jour du Raisin")
+ (1793 10 23 "Duodi 2 Brumaire an 2 de la Révolution, jour du Céleri")
+ (1794 7 27 "Nonidi 9 Thermidor an 2 de la Révolution, jour de la Mûre")
+ (1794 11 23 "Tridi 3 Frimaire an 3 de la Révolution, jour de la Chicorée")
+ (1795 10 5 "Tridi 13 Vendémiaire an 4 de la Révolution, jour du Potiron")
+ (1795 12 25 "Quartidi 4 Nivôse an 4 de la Révolution, jour du Soufre")
+ (1797 1 24 "Quintidi 5 Pluviôse an 5 de la Révolution, jour du Taureau")
+ (1798 2 24 "Sextidi 6 Ventôse an 6 de la Révolution, jour de l'Asaret")
+ (1799 11 9 "Octidi 18 Brumaire an 8 de la Révolution, jour de la Dentelaire")
+ (1801 3 29 "Octidi 8 Germinal an 9 de la Révolution, jour de la Jonquille")
+ (1804 4 30 "Décadi 10 Floréal an 12 de la Révolution, jour du Rateau")
+ (1807 6 1 "Duodi 12 Prairial an 15 de la Révolution, jour de la Bétoine")
+ (1810 7 3 "Quartidi 14 Messidor an 18 de la Révolution, jour de la Lavande")
+ (1813 8 4 "Sextidi 16 Thermidor an 21 de la Révolution, jour de la Guimauve")
+ (1816 9 4 "Octidi 18 Fructidor an 24 de la Révolution, jour du Nerprun")
+ (2000 1 1 "Duodi 12 Nivôse an 208 de la Révolution, jour de l'Argile")
+ (2021 7 11 "Tridi 23 Messidor an 229 de la Révolution, jour du Haricot")
+ (2001 5 11 "Duodi 22 Floréal an 209 de la Révolution, jour de la Fritillaire")
+ (1792 9 22 "Primidi 1 Vendémiaire an 1 de la Révolution, jour du Raisin")
+ (1793 9 21 "Quintidi 5 jour complémentaire an 1 de la Révolution, jour des Récompenses")
+ (1793 9 22 "Primidi 1 Vendémiaire an 2 de la Révolution, jour du Raisin")
+ (1794 9 21 "Quintidi 5 jour complémentaire an 2 de la Révolution, jour des Récompenses")
+ (1794 9 22 "Primidi 1 Vendémiaire an 3 de la Révolution, jour du Raisin")
+ (1795 9 22 "Sextidi 6 jour complémentaire an 3 de la Révolution, jour de la Révolution")
+ (1795 9 23 "Primidi 1 Vendémiaire an 4 de la Révolution, jour du Raisin")
+ (1796 9 21 "Quintidi 5 jour complémentaire an 4 de la Révolution, jour des Récompenses")
+ (1796 9 22 "Primidi 1 Vendémiaire an 5 de la Révolution, jour du Raisin")
+ (1797 9 21 "Quintidi 5 jour complémentaire an 5 de la Révolution, jour des Récompenses")
+ (1797 9 22 "Primidi 1 Vendémiaire an 6 de la Révolution, jour du Raisin")
+ (1799 9 22 "Sextidi 6 jour complémentaire an 7 de la Révolution, jour de la Révolution")
+ (1799 9 23 "Primidi 1 Vendémiaire an 8 de la Révolution, jour du Raisin")
+ (1800 9 22 "Quintidi 5 jour complémentaire an 8 de la Révolution, jour des Récompenses")
+ (1800 9 23 "Primidi 1 Vendémiaire an 9 de la Révolution, jour du Raisin")
+ (1801 9 22 "Quintidi 5 jour complémentaire an 9 de la Révolution, jour des Récompenses")
+ (1801 9 23 "Primidi 1 Vendémiaire an 10 de la Révolution, jour du Raisin")
+ (1823 9 22 "Quintidi 5 jour complémentaire an 31 de la Révolution, jour des Récompenses")
+ (1823 9 23 "Primidi 1 Vendémiaire an 32 de la Révolution, jour du Raisin")
+ (1824 9 22 "Sextidi 6 jour complémentaire an 32 de la Révolution, jour de la Révolution")
+ (1824 9 23 "Primidi 1 Vendémiaire an 33 de la Révolution, jour du Raisin")
+ (1825 9 22 "Quintidi 5 jour complémentaire an 33 de la Révolution, jour des Récompenses")
+ (1825 9 23 "Primidi 1 Vendémiaire an 34 de la Révolution, jour du Raisin")
+ (1892 9 21 "Quintidi 5 jour complémentaire an 100 de la Révolution, jour des Récompenses")
+ (1892 9 22 "Primidi 1 Vendémiaire an 101 de la Révolution, jour du Raisin")
+ (1900 9 22 "Sextidi 6 jour complémentaire an 108 de la Révolution, jour de la Révolution")
+ (1900 9 23 "Primidi 1 Vendémiaire an 109 de la Révolution, jour du Raisin")
+ (1992 9 21 "Quintidi 5 jour complémentaire an 200 de la Révolution, jour des Récompenses")
+ (1992 9 22 "Primidi 1 Vendémiaire an 201 de la Révolution, jour du Raisin")
+ (2000 9 21 "Sextidi 6 jour complémentaire an 208 de la Révolution, jour de la Révolution")
+ (2000 9 22 "Primidi 1 Vendémiaire an 209 de la Révolution, jour du Raisin")
+ (2092 9 20 "Quintidi 5 jour complémentaire an 300 de la Révolution, jour des Récompenses")
+ (2092 9 21 "Primidi 1 Vendémiaire an 301 de la Révolution, jour du Raisin")
+ (2100 9 21 "Sextidi 6 jour complémentaire an 308 de la Révolution, jour de la Révolution")
+ (2100 9 22 "Primidi 1 Vendémiaire an 309 de la Révolution, jour du Raisin")
+ (2192 9 21 "Sextidi 6 jour complémentaire an 400 de la Révolution, jour de la Révolution")
+ (2192 9 22 "Primidi 1 Vendémiaire an 401 de la Révolution, jour du Raisin")
+ (2193 9 21 "Quintidi 5 jour complémentaire an 401 de la Révolution, jour des Récompenses")
+ (2199 9 22 "Primidi 1 Vendémiaire an 408 de la Révolution, jour du Raisin")
+ (2200 9 22 "Sextidi 6 jour complémentaire an 408 de la Révolution, jour de la Révolution")
+ (2791 9 23 "Primidi 1 Vendémiaire an 1000 de la Révolution, jour du Raisin")
+ (2792 9 22 "Primidi 1 Vendémiaire an 1001 de la Révolution, jour du Raisin")
+ (3000 1 1 "Duodi 12 Nivôse an 1208 de la Révolution, jour de l'Argile")
+ (3001 1 1 "Primidi 11 Nivôse an 1209 de la Révolution, jour du Granit")
+ (3791 9 22 "Primidi 1 Vendémiaire an 2000 de la Révolution, jour du Raisin")
+ (3792 9 22 "Primidi 1 Vendémiaire an 2001 de la Révolution, jour du Raisin")
+ (4000 1 1 "Duodi 12 Nivôse an 2208 de la Révolution, jour de l'Argile")
+ (4001 1 1 "Duodi 12 Nivôse an 2209 de la Révolution, jour de l'Argile")
+ (4320 9 10 "Quartidi 24 Fructidor an 2528 de la Révolution, jour du Sorgho")
+ (4320 9 11 "Quintidi 25 Fructidor an 2528 de la Révolution, jour de l'Écrevisse")
+ (4791 9 23 "Primidi 1 Vendémiaire an 3000 de la Révolution, jour du Raisin")
+ (4792 9 22 "Primidi 1 Vendémiaire an 3001 de la Révolution, jour du Raisin")
+ (5000 1 1 "Duodi 12 Nivôse an 3208 de la Révolution, jour de l'Argile")
+ (5001 1 1 "Primidi 11 Nivôse an 3209 de la Révolution, jour du Granit")
+ (5791 9 22 "Primidi 1 Vendémiaire an 4000 de la Révolution, jour du Raisin")
+ (5792 9 21 "Primidi 1 Vendémiaire an 4001 de la Révolution, jour du Raisin")
+ (6000 1 1 "Tridi 13 Nivôse an 4208 de la Révolution, jour de l'Ardoise")
+ (6001 1 1 "Tridi 13 Nivôse an 4209 de la Révolution, jour de l'Ardoise")
+ (6791 9 22 "Primidi 1 Vendémiaire an 5000 de la Révolution, jour du Raisin")
+ (6792 9 21 "Primidi 1 Vendémiaire an 5001 de la Révolution, jour du Raisin")
+ (7791 9 21 "Primidi 1 Vendémiaire an 6000 de la Révolution, jour du Raisin")
+ (7792 9 21 "Primidi 1 Vendémiaire an 6001 de la Révolution, jour du Raisin")
+ ))
+
+(ert-deftest cal-french-tests ()
+ (pcase-dolist (`(,y ,m ,d ,str) cal-french-test-cases)
+ (should (equal (calendar-french-date-string (list m d y)) str))))
+
+(provide 'cal-french-tests)
+;;; cal-french-tests.el ends here
diff --git a/test/lisp/calendar/cal-julian-tests.el b/test/lisp/calendar/cal-julian-tests.el
new file mode 100644
index 00000000000..46d49c68c1e
--- /dev/null
+++ b/test/lisp/calendar/cal-julian-tests.el
@@ -0,0 +1,72 @@
+;;; cal-julian-tests.el --- tests for calendar/cal-julian.el -*- lexical-binding:t -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+;; Author: Stefan Kangas <stefankangas@gmail.com>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'cal-julian)
+
+(ert-deftest cal-julian-test-to-absolute ()
+ (should (equal (calendar-gregorian-from-absolute
+ (calendar-julian-to-absolute
+ '(10 25 1917)))
+ '(11 7 1917))))
+
+(ert-deftest cal-julian-test-from-absolute ()
+ (should (equal (calendar-julian-from-absolute
+ (calendar-absolute-from-gregorian
+ '(11 7 1917)))
+ '(10 25 1917))))
+
+(ert-deftest cal-julian-test-date-string ()
+ (should (equal (let ((calendar-date-display-form calendar-iso-date-display-form))
+ (calendar-julian-date-string '(11 7 1917)))
+ "1917-10-25")))
+
+(defmacro with-cal-julian-test (&rest body)
+ `(save-window-excursion
+ (unwind-protect
+ (progn
+ (calendar)
+ ,@body)
+ (kill-buffer "*Calendar*"))))
+
+(ert-deftest cal-julian-test-goto-date ()
+ (with-cal-julian-test
+ (calendar-julian-goto-date '(10 25 1917))
+ (should (looking-at "7"))))
+
+(ert-deftest cal-julian-test-astro-to-and-from-absolute ()
+ (should (= (+ (calendar-astro-to-absolute 0.0)
+ (calendar-astro-from-absolute 0.0))
+ 0.0)))
+
+(ert-deftest cal-julian-calendar-astro-date-string ()
+ (should (equal (calendar-astro-date-string '(10 25 1917)) "2421527")))
+
+(ert-deftest calendar-astro-goto-day-number ()
+ (with-cal-julian-test
+ (calendar-astro-goto-day-number 2421527)
+ (backward-char)
+ (should (looking-at "25"))))
+
+(provide 'cal-julian-tests)
+;;; cal-julian-tests.el ends here
diff --git a/test/lisp/calendar/icalendar-resources/import-bug-11473.diary-european b/test/lisp/calendar/icalendar-resources/import-bug-11473.diary-european
new file mode 100644
index 00000000000..97348ae0498
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-bug-11473.diary-european
@@ -0,0 +1,10 @@
+&15/5/2012 15:00-15:30 Query
+ Desc:
+ Whassup?
+
+
+ Location: phone
+ Organizer: MAILTO:a.luser@foo.com
+ Status: CONFIRMED
+ Class: PUBLIC
+ UID: 040000008200E00074C5B7101A82E0080000000020FFAED0CFEFCC01000000000000000010000000575268034ECDB649A15349B1BF240F15
diff --git a/test/lisp/calendar/icalendar-resources/import-bug-11473.ics b/test/lisp/calendar/icalendar-resources/import-bug-11473.ics
new file mode 100644
index 00000000000..bc3a6c69fb7
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-bug-11473.ics
@@ -0,0 +1,54 @@
+BEGIN:VCALENDAR
+METHOD:REQUEST
+PRODID:Microsoft Exchange Server 2007
+VERSION:2.0
+BEGIN:VTIMEZONE
+TZID:(UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna
+BEGIN:STANDARD
+DTSTART:16010101T030000
+TZOFFSETFROM:+0200
+TZOFFSETTO:+0100
+RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=-1SU;BYMONTH=10
+END:STANDARD
+BEGIN:DAYLIGHT
+DTSTART:16010101T020000
+TZOFFSETFROM:+0100
+TZOFFSETTO:+0200
+RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=-1SU;BYMONTH=3
+END:DAYLIGHT
+END:VTIMEZONE
+BEGIN:VEVENT
+ORGANIZER;CN="A. Luser":MAILTO:a.luser@foo.com
+ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN="Luser, Oth
+ er":MAILTO:other.luser@foo.com
+DESCRIPTION;LANGUAGE=en-US:\nWhassup?\n\n
+SUMMARY;LANGUAGE=en-US:Query
+DTSTART;TZID="(UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna"
+ :20120515T150000
+DTEND;TZID="(UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna":2
+ 0120515T153000
+UID:040000008200E00074C5B7101A82E0080000000020FFAED0CFEFCC01000000000000000
+ 010000000575268034ECDB649A15349B1BF240F15
+RECURRENCE-ID;TZID="(UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, V
+ ienna":20120515T170000
+CLASS:PUBLIC
+PRIORITY:5
+DTSTAMP:20120514T153645Z
+TRANSP:OPAQUE
+STATUS:CONFIRMED
+SEQUENCE:15
+LOCATION;LANGUAGE=en-US:phone
+X-MICROSOFT-CDO-APPT-SEQUENCE:15
+X-MICROSOFT-CDO-OWNERAPPTID:1907632092
+X-MICROSOFT-CDO-BUSYSTATUS:TENTATIVE
+X-MICROSOFT-CDO-INTENDEDSTATUS:BUSY
+X-MICROSOFT-CDO-ALLDAYEVENT:FALSE
+X-MICROSOFT-CDO-IMPORTANCE:1
+X-MICROSOFT-CDO-INSTTYPE:3
+BEGIN:VALARM
+ACTION:DISPLAY
+DESCRIPTION:REMINDER
+TRIGGER;RELATED=START:-PT15M
+END:VALARM
+END:VEVENT
+END:VCALENDAR \ No newline at end of file
diff --git a/test/lisp/calendar/icalendar-resources/import-bug-22092.diary-american b/test/lisp/calendar/icalendar-resources/import-bug-22092.diary-american
new file mode 100644
index 00000000000..392345fe0a2
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-bug-22092.diary-american
@@ -0,0 +1,6 @@
+&12/8/2014 18:30-22:55 Norwegian til Tromsoe-Langnes -
+ Desc: Fly med Norwegian, reservasjon. Fra Stavanger til Troms&#248; 8. des 2014 18:30, DY545Fly med Norwegian, reservasjon . Fra Stavanger til Troms&#248; 8. des 2014 21:00, DY390
+ Location: Stavanger-Sola
+ Organizer: noreply@norwegian.no
+ Class: PUBLIC
+ UID: RFCALITEM1
diff --git a/test/lisp/calendar/icalendar-resources/import-bug-22092.diary-european b/test/lisp/calendar/icalendar-resources/import-bug-22092.diary-european
new file mode 100644
index 00000000000..6a64cf6a8e9
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-bug-22092.diary-european
@@ -0,0 +1,6 @@
+&8/12/2014 18:30-22:55 Norwegian til Tromsoe-Langnes -
+ Desc: Fly med Norwegian, reservasjon. Fra Stavanger til Troms&#248; 8. des 2014 18:30, DY545Fly med Norwegian, reservasjon . Fra Stavanger til Troms&#248; 8. des 2014 21:00, DY390
+ Location: Stavanger-Sola
+ Organizer: noreply@norwegian.no
+ Class: PUBLIC
+ UID: RFCALITEM1
diff --git a/test/lisp/calendar/icalendar-resources/import-bug-22092.diary-iso b/test/lisp/calendar/icalendar-resources/import-bug-22092.diary-iso
new file mode 100644
index 00000000000..e0fadbf94dc
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-bug-22092.diary-iso
@@ -0,0 +1,6 @@
+&2014/12/8 18:30-22:55 Norwegian til Tromsoe-Langnes -
+ Desc: Fly med Norwegian, reservasjon. Fra Stavanger til Troms&#248; 8. des 2014 18:30, DY545Fly med Norwegian, reservasjon . Fra Stavanger til Troms&#248; 8. des 2014 21:00, DY390
+ Location: Stavanger-Sola
+ Organizer: noreply@norwegian.no
+ Class: PUBLIC
+ UID: RFCALITEM1
diff --git a/test/lisp/calendar/icalendar-resources/import-bug-22092.ics b/test/lisp/calendar/icalendar-resources/import-bug-22092.ics
new file mode 100644
index 00000000000..4a4c679da9c
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-bug-22092.ics
@@ -0,0 +1,30 @@
+BEGIN:VCALENDAR
+PRODID:-//www.norwegian.no//iCalendar MIMEDIR//EN
+VERSION:2.0
+METHOD:REQUEST
+BEGIN:VEVENT
+UID:RFCALITEM1
+SEQUENCE:1512040950
+DTSTAMP:20141204T095043Z
+ORGANIZER:noreply@norwegian.no
+DTSTART:20141208T173000Z
+
+DTEND:20141208T215500Z
+
+LOCATION:Stavanger-Sola
+
+DESCRIPTION:Fly med Norwegian, reservasjon. Fra Stavanger til Troms&#248; 8. des 2014 18:30, DY545Fly med Norwegian, reservasjon . Fra Stavanger til Troms&#248; 8. des 2014 21:00, DY390
+
+X-ALT-DESC;FMTTYPE=text/html:<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN"><html><head><META NAME="Generator" CONTENT="MS Exchange Server version 08.00.0681.000"><title></title></head><body><b><font face="Calibri" size="3">Reisereferanse</p></body></html>
+SUMMARY:Norwegian til Tromsoe-Langnes -
+
+CATEGORIES:Appointment
+
+
+PRIORITY:5
+
+CLASS:PUBLIC
+
+TRANSP:OPAQUE
+END:VEVENT
+END:VCALENDAR
diff --git a/test/lisp/calendar/icalendar-resources/import-bug-24199.diary-american b/test/lisp/calendar/icalendar-resources/import-bug-24199.diary-american
new file mode 100644
index 00000000000..b3308f1fcfa
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-bug-24199.diary-american
@@ -0,0 +1,5 @@
+&%%(and (not (diary-date 1 6 2016)) (not (diary-date 2 3 2016)) (not (diary-date 3 2 2016)) (not (diary-date 5 4 2016)) (not (diary-date 6 1 2016)) (diary-float t 3 1) (diary-block 12 2 2015 1 1 9999)) 12:46-16:00 Summary
+ Desc: Desc
+ Location: Loc
+ Class: DEFAULT
+ UID: 9188710a-08a7-4061-bae3-d4cf4972599a
diff --git a/test/lisp/calendar/icalendar-resources/import-bug-24199.diary-european b/test/lisp/calendar/icalendar-resources/import-bug-24199.diary-european
new file mode 100644
index 00000000000..acba714b527
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-bug-24199.diary-european
@@ -0,0 +1,5 @@
+&%%(and (not (diary-date 6 1 2016)) (not (diary-date 3 2 2016)) (not (diary-date 2 3 2016)) (not (diary-date 4 5 2016)) (not (diary-date 1 6 2016)) (diary-float t 3 1) (diary-block 2 12 2015 1 1 9999)) 12:46-16:00 Summary
+ Desc: Desc
+ Location: Loc
+ Class: DEFAULT
+ UID: 9188710a-08a7-4061-bae3-d4cf4972599a
diff --git a/test/lisp/calendar/icalendar-resources/import-bug-24199.diary-iso b/test/lisp/calendar/icalendar-resources/import-bug-24199.diary-iso
new file mode 100644
index 00000000000..2c18395dea8
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-bug-24199.diary-iso
@@ -0,0 +1,5 @@
+&%%(and (not (diary-date 2016 1 6)) (not (diary-date 2016 2 3)) (not (diary-date 2016 3 2)) (not (diary-date 2016 5 4)) (not (diary-date 2016 6 1)) (diary-float t 3 1) (diary-block 2015 12 2 9999 1 1)) 12:46-16:00 Summary
+ Desc: Desc
+ Location: Loc
+ Class: DEFAULT
+ UID: 9188710a-08a7-4061-bae3-d4cf4972599a
diff --git a/test/lisp/calendar/icalendar-resources/import-bug-24199.ics b/test/lisp/calendar/icalendar-resources/import-bug-24199.ics
new file mode 100644
index 00000000000..a307c2da3ca
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-bug-24199.ics
@@ -0,0 +1,25 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+SUMMARY:Summary
+DESCRIPTION:Desc
+LOCATION:Loc
+DTSTART:20151202T124600
+DTEND:20151202T160000
+RRULE:FREQ=MONTHLY;BYDAY=1WE;INTERVAL=1
+EXDATE:20160106T114600Z
+EXDATE:20160203T114600Z
+EXDATE:20160302T114600Z
+EXDATE:20160504T104600Z
+EXDATE:20160601T104600Z
+CLASS:DEFAULT
+TRANSP:OPAQUE
+BEGIN:VALARM
+ACTION:DISPLAY
+TRIGGER;VALUE=DURATION:-PT3H
+END:VALARM
+LAST-MODIFIED:20160805T191040Z
+UID:9188710a-08a7-4061-bae3-d4cf4972599a
+END:VEVENT
+END:VCALENDAR
diff --git a/test/lisp/calendar/icalendar-resources/import-bug-33277.diary-american b/test/lisp/calendar/icalendar-resources/import-bug-33277.diary-american
new file mode 100644
index 00000000000..c546fa9a97c
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-bug-33277.diary-american
@@ -0,0 +1 @@
+&11/5/2018 21:00 event with same start/end time
diff --git a/test/lisp/calendar/icalendar-resources/import-bug-33277.diary-european b/test/lisp/calendar/icalendar-resources/import-bug-33277.diary-european
new file mode 100644
index 00000000000..28e53960536
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-bug-33277.diary-european
@@ -0,0 +1 @@
+&5/11/2018 21:00 event with same start/end time
diff --git a/test/lisp/calendar/icalendar-resources/import-bug-33277.diary-iso b/test/lisp/calendar/icalendar-resources/import-bug-33277.diary-iso
new file mode 100644
index 00000000000..faa7aeafeb5
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-bug-33277.diary-iso
@@ -0,0 +1 @@
+&2018/11/5 21:00 event with same start/end time
diff --git a/test/lisp/calendar/icalendar-resources/import-bug-33277.ics b/test/lisp/calendar/icalendar-resources/import-bug-33277.ics
new file mode 100644
index 00000000000..a4122a28007
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-bug-33277.ics
@@ -0,0 +1,15 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+DTSTART:20181105T200000Z
+DTSTAMP:20181105T181652Z
+DESCRIPTION:
+LAST-MODIFIED:20181105T181646Z
+LOCATION:
+SEQUENCE:0
+SUMMARY:event with same start/end time
+TRANSP:OPAQUE
+END:VEVENT
+END:VCALENDAR
+
diff --git a/test/lisp/calendar/icalendar-resources/import-bug-6766.diary-american b/test/lisp/calendar/icalendar-resources/import-bug-6766.diary-american
new file mode 100644
index 00000000000..30deea9911a
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-bug-6766.diary-american
@@ -0,0 +1,7 @@
+&%%(and (memq (calendar-day-of-week date) '(1 3 4 5)) (diary-cyclic 1 4 21 2010)) 11:30-12:00 Scrum
+ Status: CONFIRMED
+ Class: PUBLIC
+ UID: 8814e3f9-7482-408f-996c-3bfe486a1262
+&%%(and (memq (calendar-day-of-week date) '(2 4)) (diary-cyclic 1 4 22 2010)) Tues + Thurs thinking
+ Class: PUBLIC
+ UID: 8814e3f9-7482-408f-996c-3bfe486a1263
diff --git a/test/lisp/calendar/icalendar-resources/import-bug-6766.diary-european b/test/lisp/calendar/icalendar-resources/import-bug-6766.diary-european
new file mode 100644
index 00000000000..ba16c02305a
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-bug-6766.diary-european
@@ -0,0 +1,7 @@
+&%%(and (memq (calendar-day-of-week date) '(1 3 4 5)) (diary-cyclic 1 21 4 2010)) 11:30-12:00 Scrum
+ Status: CONFIRMED
+ Class: PUBLIC
+ UID: 8814e3f9-7482-408f-996c-3bfe486a1262
+&%%(and (memq (calendar-day-of-week date) '(2 4)) (diary-cyclic 1 22 4 2010)) Tues + Thurs thinking
+ Class: PUBLIC
+ UID: 8814e3f9-7482-408f-996c-3bfe486a1263
diff --git a/test/lisp/calendar/icalendar-resources/import-bug-6766.diary-iso b/test/lisp/calendar/icalendar-resources/import-bug-6766.diary-iso
new file mode 100644
index 00000000000..7794e586f37
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-bug-6766.diary-iso
@@ -0,0 +1,7 @@
+&%%(and (memq (calendar-day-of-week date) '(1 3 4 5)) (diary-cyclic 1 2010 4 21)) 11:30-12:00 Scrum
+ Status: CONFIRMED
+ Class: PUBLIC
+ UID: 8814e3f9-7482-408f-996c-3bfe486a1262
+&%%(and (memq (calendar-day-of-week date) '(2 4)) (diary-cyclic 1 2010 4 22)) Tues + Thurs thinking
+ Class: PUBLIC
+ UID: 8814e3f9-7482-408f-996c-3bfe486a1263
diff --git a/test/lisp/calendar/icalendar-resources/import-bug-6766.ics b/test/lisp/calendar/icalendar-resources/import-bug-6766.ics
new file mode 100644
index 00000000000..451391be025
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-bug-6766.ics
@@ -0,0 +1,28 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+CLASS:PUBLIC
+DTEND;TZID=America/New_York:20100421T120000
+DTSTAMP:20100525T141214Z
+DTSTART;TZID=America/New_York:20100421T113000
+RRULE:FREQ=WEEKLY;INTERVAL=1;BYDAY=MO,WE,TH,FR
+SEQUENCE:1
+STATUS:CONFIRMED
+SUMMARY:Scrum
+TRANSP:OPAQUE
+UID:8814e3f9-7482-408f-996c-3bfe486a1262
+END:VEVENT
+BEGIN:VEVENT
+CLASS:PUBLIC
+DTSTAMP:20100525T141214Z
+DTSTART;VALUE=DATE:20100422
+DTEND;VALUE=DATE:20100423
+RRULE:FREQ=WEEKLY;INTERVAL=1;BYDAY=TU,TH
+SEQUENCE:1
+SUMMARY:Tues + Thurs thinking
+TRANSP:OPAQUE
+UID:8814e3f9-7482-408f-996c-3bfe486a1263
+END:VEVENT
+END:VCALENDAR
+
diff --git a/test/lisp/calendar/icalendar-resources/import-duration-2.diary-american b/test/lisp/calendar/icalendar-resources/import-duration-2.diary-american
new file mode 100644
index 00000000000..56f41d6ad9e
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-duration-2.diary-american
@@ -0,0 +1,3 @@
+&%%(and (diary-cyclic 1 12 21 2001) (diary-block 12 21 2001 12 29 2001)) Urlaub
+ Class: PUBLIC
+ UID: 20041127T183329Z-18215-1001-4536-49109@andromeda
diff --git a/test/lisp/calendar/icalendar-resources/import-duration-2.diary-european b/test/lisp/calendar/icalendar-resources/import-duration-2.diary-european
new file mode 100644
index 00000000000..999102ab6b4
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-duration-2.diary-european
@@ -0,0 +1,3 @@
+&%%(and (diary-cyclic 1 21 12 2001) (diary-block 21 12 2001 29 12 2001)) Urlaub
+ Class: PUBLIC
+ UID: 20041127T183329Z-18215-1001-4536-49109@andromeda
diff --git a/test/lisp/calendar/icalendar-resources/import-duration-2.diary-iso b/test/lisp/calendar/icalendar-resources/import-duration-2.diary-iso
new file mode 100644
index 00000000000..393937e6cd9
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-duration-2.diary-iso
@@ -0,0 +1,3 @@
+&%%(and (diary-cyclic 1 2001 12 21) (diary-block 2001 12 21 2001 12 29)) Urlaub
+ Class: PUBLIC
+ UID: 20041127T183329Z-18215-1001-4536-49109@andromeda
diff --git a/test/lisp/calendar/icalendar-resources/import-duration-2.ics b/test/lisp/calendar/icalendar-resources/import-duration-2.ics
new file mode 100644
index 00000000000..eb8a03ba36f
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-duration-2.ics
@@ -0,0 +1,17 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+UID:20041127T183329Z-18215-1001-4536-49109@andromeda
+DTSTAMP:20041127T183315Z
+LAST-MODIFIED:20041127T183329
+SUMMARY:Urlaub
+DTSTART;VALUE=DATE:20011221
+DTEND;VALUE=DATE:20011221
+RRULE:FREQ=DAILY;UNTIL=20011229;INTERVAL=1;WKST=SU
+CLASS:PUBLIC
+SEQUENCE:1
+CREATED:20041127T183329
+END:VEVENT
+END:VCALENDAR
+
diff --git a/test/lisp/calendar/icalendar-resources/import-duration.diary-american b/test/lisp/calendar/icalendar-resources/import-duration.diary-american
new file mode 100644
index 00000000000..268736a8cd0
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-duration.diary-american
@@ -0,0 +1 @@
+&%%(and (diary-block 2 17 2005 2 23 2005)) duration
diff --git a/test/lisp/calendar/icalendar-resources/import-duration.diary-european b/test/lisp/calendar/icalendar-resources/import-duration.diary-european
new file mode 100644
index 00000000000..7d852ddcd3c
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-duration.diary-european
@@ -0,0 +1 @@
+&%%(and (diary-block 17 2 2005 23 2 2005)) duration
diff --git a/test/lisp/calendar/icalendar-resources/import-duration.diary-iso b/test/lisp/calendar/icalendar-resources/import-duration.diary-iso
new file mode 100644
index 00000000000..5d3a714284e
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-duration.diary-iso
@@ -0,0 +1 @@
+&%%(and (diary-block 2005 2 17 2005 2 23)) duration
diff --git a/test/lisp/calendar/icalendar-resources/import-duration.ics b/test/lisp/calendar/icalendar-resources/import-duration.ics
new file mode 100644
index 00000000000..67f5c73571b
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-duration.ics
@@ -0,0 +1,10 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20050217
+SUMMARY:duration
+DURATION:P7D
+END:VEVENT
+END:VCALENDAR
+
diff --git a/test/lisp/calendar/icalendar-resources/import-multiple-vcalendars.diary-american b/test/lisp/calendar/icalendar-resources/import-multiple-vcalendars.diary-american
new file mode 100644
index 00000000000..d1b1992a022
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-multiple-vcalendars.diary-american
@@ -0,0 +1,4 @@
+&7/23/2011 event-1
+&7/24/2011 event-2
+&7/25/2011 event-3a
+&7/25/2011 event-3b
diff --git a/test/lisp/calendar/icalendar-resources/import-multiple-vcalendars.diary-european b/test/lisp/calendar/icalendar-resources/import-multiple-vcalendars.diary-european
new file mode 100644
index 00000000000..f068354220c
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-multiple-vcalendars.diary-european
@@ -0,0 +1,4 @@
+&23/7/2011 event-1
+&24/7/2011 event-2
+&25/7/2011 event-3a
+&25/7/2011 event-3b
diff --git a/test/lisp/calendar/icalendar-resources/import-multiple-vcalendars.diary-iso b/test/lisp/calendar/icalendar-resources/import-multiple-vcalendars.diary-iso
new file mode 100644
index 00000000000..5685e4708a7
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-multiple-vcalendars.diary-iso
@@ -0,0 +1,4 @@
+&2011/7/23 event-1
+&2011/7/24 event-2
+&2011/7/25 event-3a
+&2011/7/25 event-3b
diff --git a/test/lisp/calendar/icalendar-resources/import-multiple-vcalendars.ics b/test/lisp/calendar/icalendar-resources/import-multiple-vcalendars.ics
new file mode 100644
index 00000000000..69a02c09b1b
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-multiple-vcalendars.ics
@@ -0,0 +1,21 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20110723
+SUMMARY:event-1
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20110724
+SUMMARY:event-2
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20110725
+SUMMARY:event-3a
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20110725
+SUMMARY:event-3b
+END:VEVENT
+END:VCALENDAR
+
diff --git a/test/lisp/calendar/icalendar-resources/import-non-recurring-1.diary-american b/test/lisp/calendar/icalendar-resources/import-non-recurring-1.diary-american
new file mode 100644
index 00000000000..780e3a8ce64
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-non-recurring-1.diary-american
@@ -0,0 +1 @@
+&9/19/2003 09:00-11:30 non-recurring
diff --git a/test/lisp/calendar/icalendar-resources/import-non-recurring-1.diary-european b/test/lisp/calendar/icalendar-resources/import-non-recurring-1.diary-european
new file mode 100644
index 00000000000..7e0cd21b784
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-non-recurring-1.diary-european
@@ -0,0 +1 @@
+&19/9/2003 09:00-11:30 non-recurring
diff --git a/test/lisp/calendar/icalendar-resources/import-non-recurring-1.diary-iso b/test/lisp/calendar/icalendar-resources/import-non-recurring-1.diary-iso
new file mode 100644
index 00000000000..c7311286619
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-non-recurring-1.diary-iso
@@ -0,0 +1 @@
+&2003/9/19 09:00-11:30 non-recurring
diff --git a/test/lisp/calendar/icalendar-resources/import-non-recurring-1.ics b/test/lisp/calendar/icalendar-resources/import-non-recurring-1.ics
new file mode 100644
index 00000000000..cd471efc861
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-non-recurring-1.ics
@@ -0,0 +1,10 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+SUMMARY:non-recurring
+DTSTART;VALUE=DATE-TIME:20030919T090000
+DTEND;VALUE=DATE-TIME:20030919T113000
+END:VEVENT
+END:VCALENDAR
+
diff --git a/test/lisp/calendar/icalendar-resources/import-non-recurring-all-day.diary-american b/test/lisp/calendar/icalendar-resources/import-non-recurring-all-day.diary-american
new file mode 100644
index 00000000000..1d4bb6a337e
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-non-recurring-all-day.diary-american
@@ -0,0 +1 @@
+&9/19/2003 non-recurring allday
diff --git a/test/lisp/calendar/icalendar-resources/import-non-recurring-all-day.diary-european b/test/lisp/calendar/icalendar-resources/import-non-recurring-all-day.diary-european
new file mode 100644
index 00000000000..b56c7f4e17f
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-non-recurring-all-day.diary-european
@@ -0,0 +1 @@
+&19/9/2003 non-recurring allday
diff --git a/test/lisp/calendar/icalendar-resources/import-non-recurring-all-day.diary-iso b/test/lisp/calendar/icalendar-resources/import-non-recurring-all-day.diary-iso
new file mode 100644
index 00000000000..f1c70ab34c3
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-non-recurring-all-day.diary-iso
@@ -0,0 +1 @@
+&2003/9/19 non-recurring allday
diff --git a/test/lisp/calendar/icalendar-resources/import-non-recurring-all-day.ics b/test/lisp/calendar/icalendar-resources/import-non-recurring-all-day.ics
new file mode 100644
index 00000000000..4efa8ffa133
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-non-recurring-all-day.ics
@@ -0,0 +1,9 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+SUMMARY:non-recurring allday
+DTSTART;VALUE=DATE-TIME:20030919
+END:VEVENT
+END:VCALENDAR
+
diff --git a/test/lisp/calendar/icalendar-resources/import-non-recurring-another-example.diary-american b/test/lisp/calendar/icalendar-resources/import-non-recurring-another-example.diary-american
new file mode 100644
index 00000000000..2eb8c0ab686
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-non-recurring-another-example.diary-american
@@ -0,0 +1,4 @@
+&11/23/2004 14:45-15:45 another example
+ Status: TENTATIVE
+ Class: PRIVATE
+ UID: 6161a312-3902-11d9-b512-f764153bb28b
diff --git a/test/lisp/calendar/icalendar-resources/import-non-recurring-another-example.diary-european b/test/lisp/calendar/icalendar-resources/import-non-recurring-another-example.diary-european
new file mode 100644
index 00000000000..394eae8bb77
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-non-recurring-another-example.diary-european
@@ -0,0 +1,4 @@
+&23/11/2004 14:45-15:45 another example
+ Status: TENTATIVE
+ Class: PRIVATE
+ UID: 6161a312-3902-11d9-b512-f764153bb28b
diff --git a/test/lisp/calendar/icalendar-resources/import-non-recurring-another-example.diary-iso b/test/lisp/calendar/icalendar-resources/import-non-recurring-another-example.diary-iso
new file mode 100644
index 00000000000..5e8bdf417d5
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-non-recurring-another-example.diary-iso
@@ -0,0 +1,4 @@
+&2004/11/23 14:45-15:45 another example
+ Status: TENTATIVE
+ Class: PRIVATE
+ UID: 6161a312-3902-11d9-b512-f764153bb28b
diff --git a/test/lisp/calendar/icalendar-resources/import-non-recurring-another-example.ics b/test/lisp/calendar/icalendar-resources/import-non-recurring-another-example.ics
new file mode 100644
index 00000000000..b145e418791
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-non-recurring-another-example.ics
@@ -0,0 +1,23 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+UID
+ :6161a312-3902-11d9-b512-f764153bb28b
+SUMMARY
+ :another example
+STATUS
+ :TENTATIVE
+CLASS
+ :PRIVATE
+X-MOZILLA-ALARM-DEFAULT-LENGTH
+ :0
+DTSTART
+ :20041123T144500
+DTEND
+ :20041123T154500
+DTSTAMP
+ :20041118T013641Z
+END:VEVENT
+END:VCALENDAR
+
diff --git a/test/lisp/calendar/icalendar-resources/import-non-recurring-block.diary-american b/test/lisp/calendar/icalendar-resources/import-non-recurring-block.diary-american
new file mode 100644
index 00000000000..b22234229cf
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-non-recurring-block.diary-american
@@ -0,0 +1,4 @@
+&%%(and (diary-block 7 19 2004 8 27 2004)) Sommerferien
+ Status: TENTATIVE
+ Class: PRIVATE
+ UID: 748f2da0-0d9b-11d8-97af-b4ec8686ea61
diff --git a/test/lisp/calendar/icalendar-resources/import-non-recurring-block.diary-european b/test/lisp/calendar/icalendar-resources/import-non-recurring-block.diary-european
new file mode 100644
index 00000000000..8043482442f
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-non-recurring-block.diary-european
@@ -0,0 +1,4 @@
+&%%(and (diary-block 19 7 2004 27 8 2004)) Sommerferien
+ Status: TENTATIVE
+ Class: PRIVATE
+ UID: 748f2da0-0d9b-11d8-97af-b4ec8686ea61
diff --git a/test/lisp/calendar/icalendar-resources/import-non-recurring-block.diary-iso b/test/lisp/calendar/icalendar-resources/import-non-recurring-block.diary-iso
new file mode 100644
index 00000000000..e0f1896114f
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-non-recurring-block.diary-iso
@@ -0,0 +1,4 @@
+&%%(and (diary-block 2004 7 19 2004 8 27)) Sommerferien
+ Status: TENTATIVE
+ Class: PRIVATE
+ UID: 748f2da0-0d9b-11d8-97af-b4ec8686ea61
diff --git a/test/lisp/calendar/icalendar-resources/import-non-recurring-block.ics b/test/lisp/calendar/icalendar-resources/import-non-recurring-block.ics
new file mode 100644
index 00000000000..0c52ba3d66a
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-non-recurring-block.ics
@@ -0,0 +1,16 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+UID:748f2da0-0d9b-11d8-97af-b4ec8686ea61
+SUMMARY:Sommerferien
+STATUS:TENTATIVE
+CLASS:PRIVATE
+X-MOZILLA-ALARM-DEFAULT-UNITS:Minuten
+X-MOZILLA-RECUR-DEFAULT-INTERVAL:0
+DTSTART;VALUE=DATE:20040719
+DTEND;VALUE=DATE:20040828
+DTSTAMP:20031103T011641Z
+END:VEVENT
+END:VCALENDAR
+
diff --git a/test/lisp/calendar/icalendar-resources/import-non-recurring-folded-summary.diary-american b/test/lisp/calendar/icalendar-resources/import-non-recurring-folded-summary.diary-american
new file mode 100644
index 00000000000..2954d0c4fd1
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-non-recurring-folded-summary.diary-american
@@ -0,0 +1,4 @@
+&11/23/2004 14:00-14:30 folded summary
+ Status: TENTATIVE
+ Class: PRIVATE
+ UID: 04979712-3902-11d9-93dd-8f9f4afe08da
diff --git a/test/lisp/calendar/icalendar-resources/import-non-recurring-folded-summary.diary-european b/test/lisp/calendar/icalendar-resources/import-non-recurring-folded-summary.diary-european
new file mode 100644
index 00000000000..7745fc811b4
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-non-recurring-folded-summary.diary-european
@@ -0,0 +1,4 @@
+&23/11/2004 14:00-14:30 folded summary
+ Status: TENTATIVE
+ Class: PRIVATE
+ UID: 04979712-3902-11d9-93dd-8f9f4afe08da
diff --git a/test/lisp/calendar/icalendar-resources/import-non-recurring-folded-summary.diary-iso b/test/lisp/calendar/icalendar-resources/import-non-recurring-folded-summary.diary-iso
new file mode 100644
index 00000000000..8c19a95ed2d
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-non-recurring-folded-summary.diary-iso
@@ -0,0 +1,4 @@
+&2004/11/23 14:00-14:30 folded summary
+ Status: TENTATIVE
+ Class: PRIVATE
+ UID: 04979712-3902-11d9-93dd-8f9f4afe08da
diff --git a/test/lisp/calendar/icalendar-resources/import-non-recurring-folded-summary.ics b/test/lisp/calendar/icalendar-resources/import-non-recurring-folded-summary.ics
new file mode 100644
index 00000000000..e3ecee9dae8
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-non-recurring-folded-summary.ics
@@ -0,0 +1,25 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+UID
+ :04979712-3902-11d9-93dd-8f9f4afe08da
+SUMMARY
+ :folded summary
+STATUS
+ :TENTATIVE
+CLASS
+ :PRIVATE
+X-MOZILLA-ALARM-DEFAULT-LENGTH
+ :0
+DTSTART
+ :20041123T140000
+DTEND
+ :20041123T143000
+DTSTAMP
+ :20041118T013430Z
+LAST-MODIFIED
+ :20041118T013640Z
+END:VEVENT
+END:VCALENDAR
+
diff --git a/test/lisp/calendar/icalendar-resources/import-non-recurring-long-summary.diary-american b/test/lisp/calendar/icalendar-resources/import-non-recurring-long-summary.diary-american
new file mode 100644
index 00000000000..84cd464c568
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-non-recurring-long-summary.diary-american
@@ -0,0 +1 @@
+&9/19/2003 long summary
diff --git a/test/lisp/calendar/icalendar-resources/import-non-recurring-long-summary.diary-european b/test/lisp/calendar/icalendar-resources/import-non-recurring-long-summary.diary-european
new file mode 100644
index 00000000000..5d6524202c3
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-non-recurring-long-summary.diary-european
@@ -0,0 +1 @@
+&19/9/2003 long summary
diff --git a/test/lisp/calendar/icalendar-resources/import-non-recurring-long-summary.diary-iso b/test/lisp/calendar/icalendar-resources/import-non-recurring-long-summary.diary-iso
new file mode 100644
index 00000000000..d2300522d9a
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-non-recurring-long-summary.diary-iso
@@ -0,0 +1 @@
+&2003/9/19 long summary
diff --git a/test/lisp/calendar/icalendar-resources/import-non-recurring-long-summary.ics b/test/lisp/calendar/icalendar-resources/import-non-recurring-long-summary.ics
new file mode 100644
index 00000000000..39ae02f10ca
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-non-recurring-long-summary.ics
@@ -0,0 +1,10 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+SUMMARY:long
+ summary
+DTSTART;VALUE=DATE:20030919
+END:VEVENT
+END:VCALENDAR
+
diff --git a/test/lisp/calendar/icalendar-resources/import-real-world-2003-05-29.diary-american b/test/lisp/calendar/icalendar-resources/import-real-world-2003-05-29.diary-american
new file mode 100644
index 00000000000..e6c8712d254
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-real-world-2003-05-29.diary-american
@@ -0,0 +1,6 @@
+&5/9/2003 07:00-12:00 On-Site Interview
+ Desc: 10:30am - Blah
+ Location: Cccc
+ Organizer: MAILTO:aaaaaaa@aaaaaaa.com
+ Status: CONFIRMED
+ UID: 040000008200E00074C5B7101A82E0080000000080B6DE661216C301000000000000000010000000DB823520692542408ED02D7023F9DFF9
diff --git a/test/lisp/calendar/icalendar-resources/import-real-world-2003-05-29.diary-european b/test/lisp/calendar/icalendar-resources/import-real-world-2003-05-29.diary-european
new file mode 100644
index 00000000000..cecca070a51
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-real-world-2003-05-29.diary-european
@@ -0,0 +1,6 @@
+&9/5/2003 07:00-12:00 On-Site Interview
+ Desc: 10:30am - Blah
+ Location: Cccc
+ Organizer: MAILTO:aaaaaaa@aaaaaaa.com
+ Status: CONFIRMED
+ UID: 040000008200E00074C5B7101A82E0080000000080B6DE661216C301000000000000000010000000DB823520692542408ED02D7023F9DFF9
diff --git a/test/lisp/calendar/icalendar-resources/import-real-world-2003-05-29.ics b/test/lisp/calendar/icalendar-resources/import-real-world-2003-05-29.ics
new file mode 100644
index 00000000000..decc8df5451
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-real-world-2003-05-29.ics
@@ -0,0 +1,54 @@
+BEGIN:VCALENDAR
+METHOD:REQUEST
+PRODID:Microsoft CDO for Microsoft Exchange
+VERSION:2.0
+BEGIN:VTIMEZONE
+TZID:Kolkata, Chennai, Mumbai, New Delhi
+X-MICROSOFT-CDO-TZID:23
+BEGIN:STANDARD
+DTSTART:16010101T000000
+TZOFFSETFROM:+0530
+TZOFFSETTO:+0530
+END:STANDARD
+BEGIN:DAYLIGHT
+DTSTART:16010101T000000
+TZOFFSETFROM:+0530
+TZOFFSETTO:+0530
+END:DAYLIGHT
+END:VTIMEZONE
+BEGIN:VEVENT
+DTSTAMP:20030509T043439Z
+DTSTART;TZID="Kolkata, Chennai, Mumbai, New Delhi":20030509T103000
+SUMMARY:On-Site Interview
+UID:040000008200E00074C5B7101A82E0080000000080B6DE661216C301000000000000000
+ 010000000DB823520692542408ED02D7023F9DFF9
+ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN="Xxxxx
+ xxx Xxxxxxxxxxxx":MAILTO:xxxxxxxx@xxxxxxx.com
+ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN="Yyyyyyy Y
+ yyyy":MAILTO:yyyyyyy@yyyyyyy.com
+ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN="Zzzz Zzzz
+ zz":MAILTO:zzzzzz@zzzzzzz.com
+ORGANIZER;CN="Aaaaaa Aaaaa":MAILTO:aaaaaaa@aaaaaaa.com
+LOCATION:Cccc
+DTEND;TZID="Kolkata, Chennai, Mumbai, New Delhi":20030509T153000
+DESCRIPTION:10:30am - Blah
+SEQUENCE:0
+PRIORITY:5
+CLASS:
+CREATED:20030509T043439Z
+LAST-MODIFIED:20030509T043459Z
+STATUS:CONFIRMED
+TRANSP:OPAQUE
+X-MICROSOFT-CDO-BUSYSTATUS:BUSY
+X-MICROSOFT-CDO-INSTTYPE:0
+X-MICROSOFT-CDO-INTENDEDSTATUS:BUSY
+X-MICROSOFT-CDO-ALLDAYEVENT:FALSE
+X-MICROSOFT-CDO-IMPORTANCE:1
+X-MICROSOFT-CDO-OWNERAPPTID:126441427
+BEGIN:VALARM
+ACTION:DISPLAY
+DESCRIPTION:REMINDER
+TRIGGER;RELATED=START:-PT00H15M00S
+END:VALARM
+END:VEVENT
+END:VCALENDAR
diff --git a/test/lisp/calendar/icalendar-resources/import-real-world-2003-06-18a.diary-american b/test/lisp/calendar/icalendar-resources/import-real-world-2003-06-18a.diary-american
new file mode 100644
index 00000000000..f2c914184e7
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-real-world-2003-06-18a.diary-american
@@ -0,0 +1,6 @@
+&6/23/2003 11:00-12:00 Dress Rehearsal for XXXX-XXXX
+ Desc: 753 Zeichen hier radiert
+ Location: 555 or TN 555-5555 ID 5555 & NochWas (see below)
+ Organizer: MAILTO:xxx@xxxxx.com
+ Status: CONFIRMED
+ UID: 040000008200E00074C5B7101A82E00800000000608AA7DA9835C3010000000000000000100000007C3A6D65EE726E40B7F3D69A23BD567E
diff --git a/test/lisp/calendar/icalendar-resources/import-real-world-2003-06-18a.diary-european b/test/lisp/calendar/icalendar-resources/import-real-world-2003-06-18a.diary-european
new file mode 100644
index 00000000000..89cff58af42
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-real-world-2003-06-18a.diary-european
@@ -0,0 +1,6 @@
+&23/6/2003 11:00-12:00 Dress Rehearsal for XXXX-XXXX
+ Desc: 753 Zeichen hier radiert
+ Location: 555 or TN 555-5555 ID 5555 & NochWas (see below)
+ Organizer: MAILTO:xxx@xxxxx.com
+ Status: CONFIRMED
+ UID: 040000008200E00074C5B7101A82E00800000000608AA7DA9835C3010000000000000000100000007C3A6D65EE726E40B7F3D69A23BD567E
diff --git a/test/lisp/calendar/icalendar-resources/import-real-world-2003-06-18a.ics b/test/lisp/calendar/icalendar-resources/import-real-world-2003-06-18a.ics
new file mode 100644
index 00000000000..6bb5b05af17
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-real-world-2003-06-18a.ics
@@ -0,0 +1,36 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+DTSTAMP:20030618T195512Z
+DTSTART;TZID="Mountain Time (US & Canada)":20030623T110000
+SUMMARY:Dress Rehearsal for XXXX-XXXX
+UID:040000008200E00074C5B7101A82E00800000000608AA7DA9835C301000000000000000
+ 0100000007C3A6D65EE726E40B7F3D69A23BD567E
+ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN="AAAAA,AAA
+ AA (A-AAAAAAA,ex1)":MAILTO:aaaaa_aaaaa@aaaaa.com
+ORGANIZER;CN="ABCD,TECHTRAINING
+ (A-Americas,exgen1)":MAILTO:xxx@xxxxx.com
+LOCATION:555 or TN 555-5555 ID 5555 & NochWas (see below)
+DTEND;TZID="Mountain Time (US & Canada)":20030623T120000
+DESCRIPTION:753 Zeichen hier radiert
+SEQUENCE:0
+PRIORITY:5
+CLASS:
+CREATED:20030618T195518Z
+LAST-MODIFIED:20030618T195527Z
+STATUS:CONFIRMED
+TRANSP:OPAQUE
+X-MICROSOFT-CDO-BUSYSTATUS:BUSY
+X-MICROSOFT-CDO-INSTTYPE:0
+X-MICROSOFT-CDO-INTENDEDSTATUS:BUSY
+X-MICROSOFT-CDO-ALLDAYEVENT:FALSE
+X-MICROSOFT-CDO-IMPORTANCE:1
+X-MICROSOFT-CDO-OWNERAPPTID:1022519251
+BEGIN:VALARM
+ACTION:DISPLAY
+DESCRIPTION:REMINDER
+TRIGGER;RELATED=START:-PT00H15M00S
+END:VALARM
+END:VEVENT
+END:VCALENDAR
diff --git a/test/lisp/calendar/icalendar-resources/import-real-world-2003-06-18b.diary-american b/test/lisp/calendar/icalendar-resources/import-real-world-2003-06-18b.diary-american
new file mode 100644
index 00000000000..2c0774cdd83
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-real-world-2003-06-18b.diary-american
@@ -0,0 +1,6 @@
+&6/23/2003 17:00-18:00 Updated: Dress Rehearsal for ABC01-15
+ Desc: Viele Zeichen standen hier früher
+ Location: 123 or TN 123-1234 ID abcd & SonstWo (see below)
+ Organizer: MAILTO:bbb@bbbbb.com
+ Status: CONFIRMED
+ UID: 040000008200E00074C5B7101A82E00800000000608AA7DA9835C3010000000000000000100000007C3A6D65EE726E40B7F3D69A23BD567E
diff --git a/test/lisp/calendar/icalendar-resources/import-real-world-2003-06-18b.diary-european b/test/lisp/calendar/icalendar-resources/import-real-world-2003-06-18b.diary-european
new file mode 100644
index 00000000000..95aac168699
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-real-world-2003-06-18b.diary-european
@@ -0,0 +1,6 @@
+&23/6/2003 17:00-18:00 Updated: Dress Rehearsal for ABC01-15
+ Desc: Viele Zeichen standen hier früher
+ Location: 123 or TN 123-1234 ID abcd & SonstWo (see below)
+ Organizer: MAILTO:bbb@bbbbb.com
+ Status: CONFIRMED
+ UID: 040000008200E00074C5B7101A82E00800000000608AA7DA9835C3010000000000000000100000007C3A6D65EE726E40B7F3D69A23BD567E
diff --git a/test/lisp/calendar/icalendar-resources/import-real-world-2003-06-18b.ics b/test/lisp/calendar/icalendar-resources/import-real-world-2003-06-18b.ics
new file mode 100644
index 00000000000..1523135adf3
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-real-world-2003-06-18b.ics
@@ -0,0 +1,55 @@
+BEGIN:VCALENDAR
+METHOD:REQUEST
+PRODID:Microsoft CDO for Microsoft Exchange
+VERSION:2.0
+BEGIN:VTIMEZONE
+TZID:Mountain Time (US & Canada)
+X-MICROSOFT-CDO-TZID:12
+BEGIN:STANDARD
+DTSTART:16010101T020000
+TZOFFSETFROM:-0600
+TZOFFSETTO:-0700
+RRULE:FREQ=YEARLY;WKST=MO;INTERVAL=1;BYMONTH=10;BYDAY=-1SU
+END:STANDARD
+BEGIN:DAYLIGHT
+DTSTART:16010101T020000
+TZOFFSETFROM:-0700
+TZOFFSETTO:-0600
+RRULE:FREQ=YEARLY;WKST=MO;INTERVAL=1;BYMONTH=4;BYDAY=1SU
+END:DAYLIGHT
+END:VTIMEZONE
+BEGIN:VEVENT
+DTSTAMP:20030618T230323Z
+DTSTART;TZID="Mountain Time (US & Canada)":20030623T090000
+SUMMARY:Updated: Dress Rehearsal for ABC01-15
+UID:040000008200E00074C5B7101A82E00800000000608AA7DA9835C301000000000000000
+ 0100000007C3A6D65EE726E40B7F3D69A23BD567E
+ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;X-REPLYTIME=20030618T20
+ 0700Z;RSVP=TRUE;CN="AAAAA,AAAAAA
+\(A-AAAAAAA,ex1)":MAILTO:aaaaaa_aaaaa@aaaaa
+ .com
+ORGANIZER;CN="ABCD,TECHTRAINING
+\(A-Americas,exgen1)":MAILTO:bbb@bbbbb.com
+LOCATION:123 or TN 123-1234 ID abcd & SonstWo (see below)
+DTEND;TZID="Mountain Time (US & Canada)":20030623T100000
+DESCRIPTION:Viele Zeichen standen hier früher
+SEQUENCE:0
+PRIORITY:5
+CLASS:
+CREATED:20030618T230326Z
+LAST-MODIFIED:20030618T230335Z
+STATUS:CONFIRMED
+TRANSP:OPAQUE
+X-MICROSOFT-CDO-BUSYSTATUS:BUSY
+X-MICROSOFT-CDO-INSTTYPE:0
+X-MICROSOFT-CDO-INTENDEDSTATUS:BUSY
+X-MICROSOFT-CDO-ALLDAYEVENT:FALSE
+X-MICROSOFT-CDO-IMPORTANCE:1
+X-MICROSOFT-CDO-OWNERAPPTID:1022519251
+BEGIN:VALARM
+ACTION:DISPLAY
+DESCRIPTION:REMINDER
+TRIGGER;RELATED=START:-PT00H15M00S
+END:VALARM
+END:VEVENT
+END:VCALENDAR \ No newline at end of file
diff --git a/test/lisp/calendar/icalendar-resources/import-real-world-2004-11-19.diary-american b/test/lisp/calendar/icalendar-resources/import-real-world-2004-11-19.diary-american
new file mode 100644
index 00000000000..a986f700ba2
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-real-world-2004-11-19.diary-american
@@ -0,0 +1,19 @@
+&11/23/2004 14:00-14:30 Jjjjj & Wwwww
+ Status: TENTATIVE
+ Class: PRIVATE
+&11/23/2004 14:45-15:45 BB Aaaaaaaa Bbbbb
+ Status: TENTATIVE
+ Class: PRIVATE
+&11/23/2004 11:00-12:00 Hhhhhhhh
+ Status: TENTATIVE
+ Class: PRIVATE
+&%%(and (diary-cyclic 14 11 12 2004)) 14:00-18:30 MMM Aaaaaaaaa
+ Status: TENTATIVE
+ Class: PRIVATE
+&%%(and (diary-block 11 19 2004 11 19 2004)) Rrrr/Cccccc ii Aaaaaaaa
+ Desc: Vvvvv Rrrr aaa Cccccc
+ Status: TENTATIVE
+ Class: PRIVATE
+&%%(and (diary-cyclic 7 11 1 2004)) Wwww aa hhhh
+ Status: TENTATIVE
+ Class: PRIVATE
diff --git a/test/lisp/calendar/icalendar-resources/import-real-world-2004-11-19.diary-european b/test/lisp/calendar/icalendar-resources/import-real-world-2004-11-19.diary-european
new file mode 100644
index 00000000000..cbfe99eb8e3
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-real-world-2004-11-19.diary-european
@@ -0,0 +1,19 @@
+&23/11/2004 14:00-14:30 Jjjjj & Wwwww
+ Status: TENTATIVE
+ Class: PRIVATE
+&23/11/2004 14:45-15:45 BB Aaaaaaaa Bbbbb
+ Status: TENTATIVE
+ Class: PRIVATE
+&23/11/2004 11:00-12:00 Hhhhhhhh
+ Status: TENTATIVE
+ Class: PRIVATE
+&%%(and (diary-cyclic 14 12 11 2004)) 14:00-18:30 MMM Aaaaaaaaa
+ Status: TENTATIVE
+ Class: PRIVATE
+&%%(and (diary-block 19 11 2004 19 11 2004)) Rrrr/Cccccc ii Aaaaaaaa
+ Desc: Vvvvv Rrrr aaa Cccccc
+ Status: TENTATIVE
+ Class: PRIVATE
+&%%(and (diary-cyclic 7 1 11 2004)) Wwww aa hhhh
+ Status: TENTATIVE
+ Class: PRIVATE
diff --git a/test/lisp/calendar/icalendar-resources/import-real-world-2004-11-19.ics b/test/lisp/calendar/icalendar-resources/import-real-world-2004-11-19.ics
new file mode 100644
index 00000000000..9edb682fcad
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-real-world-2004-11-19.ics
@@ -0,0 +1,120 @@
+BEGIN:VCALENDAR
+VERSION
+ :2.0
+PRODID
+ :-//Mozilla.org/NONSGML Mozilla Calendar V1.0//EN
+BEGIN:VEVENT
+SUMMARY
+ :Jjjjj & Wwwww
+STATUS
+ :TENTATIVE
+CLASS
+ :PRIVATE
+X-MOZILLA-ALARM-DEFAULT-LENGTH
+ :0
+DTSTART
+ :20041123T140000
+DTEND
+ :20041123T143000
+DTSTAMP
+ :20041118T013430Z
+LAST-MODIFIED
+ :20041118T013640Z
+END:VEVENT
+BEGIN:VEVENT
+SUMMARY
+ :BB Aaaaaaaa Bbbbb
+STATUS
+ :TENTATIVE
+CLASS
+ :PRIVATE
+X-MOZILLA-ALARM-DEFAULT-LENGTH
+ :0
+DTSTART
+ :20041123T144500
+DTEND
+ :20041123T154500
+DTSTAMP
+ :20041118T013641Z
+END:VEVENT
+BEGIN:VEVENT
+SUMMARY
+ :Hhhhhhhh
+STATUS
+ :TENTATIVE
+CLASS
+ :PRIVATE
+X-MOZILLA-ALARM-DEFAULT-LENGTH
+ :0
+DTSTART
+ :20041123T110000
+DTEND
+ :20041123T120000
+DTSTAMP
+ :20041118T013831Z
+END:VEVENT
+BEGIN:VEVENT
+SUMMARY
+ :MMM Aaaaaaaaa
+STATUS
+ :TENTATIVE
+CLASS
+ :PRIVATE
+X-MOZILLA-ALARM-DEFAULT-LENGTH
+ :0
+X-MOZILLA-RECUR-DEFAULT-INTERVAL
+ :2
+RRULE
+ :FREQ=WEEKLY;INTERVAL=2;BYDAY=FR
+DTSTART
+ :20041112T140000
+DTEND
+ :20041112T183000
+DTSTAMP
+ :20041118T014117Z
+END:VEVENT
+BEGIN:VEVENT
+SUMMARY
+ :Rrrr/Cccccc ii Aaaaaaaa
+DESCRIPTION
+ :Vvvvv Rrrr aaa Cccccc
+STATUS
+ :TENTATIVE
+CLASS
+ :PRIVATE
+X-MOZILLA-ALARM-DEFAULT-LENGTH
+ :0
+DTSTART
+ ;VALUE=DATE
+ :20041119
+DTEND
+ ;VALUE=DATE
+ :20041120
+DTSTAMP
+ :20041118T013107Z
+LAST-MODIFIED
+ :20041118T014203Z
+END:VEVENT
+BEGIN:VEVENT
+SUMMARY
+ :Wwww aa hhhh
+STATUS
+ :TENTATIVE
+CLASS
+ :PRIVATE
+X-MOZILLA-ALARM-DEFAULT-LENGTH
+ :0
+RRULE
+ :FREQ=WEEKLY;INTERVAL=1;BYDAY=MO
+DTSTART
+ ;VALUE=DATE
+ :20041101
+DTEND
+ ;VALUE=DATE
+ :20041102
+DTSTAMP
+ :20041118T014045Z
+LAST-MODIFIED
+ :20041118T023846Z
+END:VEVENT
+END:VCALENDAR
diff --git a/test/lisp/calendar/icalendar-resources/import-real-world-2005-02-07.diary-american b/test/lisp/calendar/icalendar-resources/import-real-world-2005-02-07.diary-american
new file mode 100644
index 00000000000..ce7d835d96b
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-real-world-2005-02-07.diary-american
@@ -0,0 +1,5 @@
+&%%(and (diary-block 2 6 2005 2 6 2005)) Waitangi Day
+ Desc: abcdef
+ Status: CONFIRMED
+ Class: PRIVATE
+ UID: b60d398e-1dd1-11b2-a159-cf8cb05139f4
diff --git a/test/lisp/calendar/icalendar-resources/import-real-world-2005-02-07.diary-european b/test/lisp/calendar/icalendar-resources/import-real-world-2005-02-07.diary-european
new file mode 100644
index 00000000000..3a52b0ab271
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-real-world-2005-02-07.diary-european
@@ -0,0 +1,5 @@
+&%%(and (diary-block 6 2 2005 6 2 2005)) Waitangi Day
+ Desc: abcdef
+ Status: CONFIRMED
+ Class: PRIVATE
+ UID: b60d398e-1dd1-11b2-a159-cf8cb05139f4
diff --git a/test/lisp/calendar/icalendar-resources/import-real-world-2005-02-07.ics b/test/lisp/calendar/icalendar-resources/import-real-world-2005-02-07.ics
new file mode 100644
index 00000000000..9eec71fe751
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-real-world-2005-02-07.ics
@@ -0,0 +1,26 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+UID
+ :b60d398e-1dd1-11b2-a159-cf8cb05139f4
+SUMMARY
+ :Waitangi Day
+DESCRIPTION
+ :abcdef
+CATEGORIES
+ :Public Holiday
+STATUS
+ :CONFIRMED
+CLASS
+ :PRIVATE
+DTSTART
+ ;VALUE=DATE
+ :20050206
+DTEND
+ ;VALUE=DATE
+ :20050207
+DTSTAMP
+ :20050128T011209Z
+END:VEVENT
+END:VCALENDAR
diff --git a/test/lisp/calendar/icalendar-resources/import-real-world-2005-03-01.diary-american b/test/lisp/calendar/icalendar-resources/import-real-world-2005-03-01.diary-american
new file mode 100644
index 00000000000..23c93d45d9a
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-real-world-2005-03-01.diary-american
@@ -0,0 +1,2 @@
+&%%(and (diary-block 2 17 2005 2 23 2005)) Hhhhhh Aaaaa ii Aaaaaaaa
+ UID: 6AFA7558-6994-11D9-8A3A-000A95A0E830-RID
diff --git a/test/lisp/calendar/icalendar-resources/import-real-world-2005-03-01.diary-european b/test/lisp/calendar/icalendar-resources/import-real-world-2005-03-01.diary-european
new file mode 100644
index 00000000000..106e9f3cdd0
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-real-world-2005-03-01.diary-european
@@ -0,0 +1,2 @@
+&%%(and (diary-block 17 2 2005 23 2 2005)) Hhhhhh Aaaaa ii Aaaaaaaa
+ UID: 6AFA7558-6994-11D9-8A3A-000A95A0E830-RID
diff --git a/test/lisp/calendar/icalendar-resources/import-real-world-2005-03-01.ics b/test/lisp/calendar/icalendar-resources/import-real-world-2005-03-01.ics
new file mode 100644
index 00000000000..ed9faa9b0bd
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-real-world-2005-03-01.ics
@@ -0,0 +1,11 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20050217
+SUMMARY:Hhhhhh Aaaaa ii Aaaaaaaa
+UID:6AFA7558-6994-11D9-8A3A-000A95A0E830-RID
+DTSTAMP:20050118T210335Z
+DURATION:P7D
+END:VEVENT
+END:VCALENDAR
diff --git a/test/lisp/calendar/icalendar-resources/import-real-world-no-dst.diary-american b/test/lisp/calendar/icalendar-resources/import-real-world-no-dst.diary-american
new file mode 100644
index 00000000000..290edb88760
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-real-world-no-dst.diary-american
@@ -0,0 +1,4 @@
+&11/16/2014 04:30-05:30 NoDST
+ Desc: Test event from timezone without DST
+ Location: Everywhere
+ UID: 20141116T171439Z-678877132@marudot.com
diff --git a/test/lisp/calendar/icalendar-resources/import-real-world-no-dst.diary-european b/test/lisp/calendar/icalendar-resources/import-real-world-no-dst.diary-european
new file mode 100644
index 00000000000..c56b7a6547a
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-real-world-no-dst.diary-european
@@ -0,0 +1,4 @@
+&16/11/2014 04:30-05:30 NoDST
+ Desc: Test event from timezone without DST
+ Location: Everywhere
+ UID: 20141116T171439Z-678877132@marudot.com
diff --git a/test/lisp/calendar/icalendar-resources/import-real-world-no-dst.ics b/test/lisp/calendar/icalendar-resources/import-real-world-no-dst.ics
new file mode 100644
index 00000000000..5f147af4f37
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-real-world-no-dst.ics
@@ -0,0 +1,26 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//www.marudot.com//iCal Event Maker
+X-WR-CALNAME:Test
+CALSCALE:GREGORIAN
+BEGIN:VTIMEZONE
+TZID:Asia/Tehran
+TZURL:http://tzurl.org/zoneinfo-outlook/Asia/Tehran
+X-LIC-LOCATION:Asia/Tehran
+BEGIN:STANDARD
+TZOFFSETFROM:+0330
+TZOFFSETTO:+0330
+TZNAME:IRST
+DTSTART:19700101T000000
+END:STANDARD
+END:VTIMEZONE
+BEGIN:VEVENT
+DTSTAMP:20141116T171439Z
+UID:20141116T171439Z-678877132@marudot.com
+DTSTART;TZID="Asia/Tehran":20141116T070000
+DTEND;TZID="Asia/Tehran":20141116T080000
+SUMMARY:NoDST
+DESCRIPTION:Test event from timezone without DST
+LOCATION:Everywhere
+END:VEVENT
+END:VCALENDAR \ No newline at end of file
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-anniversary.diary-american b/test/lisp/calendar/icalendar-resources/import-rrule-anniversary.diary-american
new file mode 100644
index 00000000000..2f7026a0bde
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-anniversary.diary-american
@@ -0,0 +1 @@
+&%%(diary-anniversary 8 15 2003) Maria Himmelfahrt
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-anniversary.diary-european b/test/lisp/calendar/icalendar-resources/import-rrule-anniversary.diary-european
new file mode 100644
index 00000000000..fa652dbb92e
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-anniversary.diary-european
@@ -0,0 +1 @@
+&%%(diary-anniversary 15 8 2003) Maria Himmelfahrt
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-anniversary.diary-iso b/test/lisp/calendar/icalendar-resources/import-rrule-anniversary.diary-iso
new file mode 100644
index 00000000000..803dd36de0a
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-anniversary.diary-iso
@@ -0,0 +1 @@
+&%%(diary-anniversary 2003 8 15) Maria Himmelfahrt
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-anniversary.ics b/test/lisp/calendar/icalendar-resources/import-rrule-anniversary.ics
new file mode 100644
index 00000000000..2996f494167
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-anniversary.ics
@@ -0,0 +1,11 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20040815
+DTEND;VALUE=DATE:20040816
+SUMMARY:Maria Himmelfahrt
+RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=8
+END:VEVENT
+END:VCALENDAR
+
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-count-bi-weekly.diary-american b/test/lisp/calendar/icalendar-resources/import-rrule-count-bi-weekly.diary-american
new file mode 100644
index 00000000000..84b6d109953
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-count-bi-weekly.diary-american
@@ -0,0 +1 @@
+&%%(and (diary-cyclic 14 9 19 2003) (diary-block 9 19 2003 10 31 2003)) 09:00-11:30 rrule count bi-weekly 3 times
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-count-bi-weekly.diary-european b/test/lisp/calendar/icalendar-resources/import-rrule-count-bi-weekly.diary-european
new file mode 100644
index 00000000000..0bebdf8872f
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-count-bi-weekly.diary-european
@@ -0,0 +1 @@
+&%%(and (diary-cyclic 14 19 9 2003) (diary-block 19 9 2003 31 10 2003)) 09:00-11:30 rrule count bi-weekly 3 times
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-count-bi-weekly.diary-iso b/test/lisp/calendar/icalendar-resources/import-rrule-count-bi-weekly.diary-iso
new file mode 100644
index 00000000000..11429081abe
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-count-bi-weekly.diary-iso
@@ -0,0 +1 @@
+&%%(and (diary-cyclic 14 2003 9 19) (diary-block 2003 9 19 2003 10 31)) 09:00-11:30 rrule count bi-weekly 3 times
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-count-bi-weekly.ics b/test/lisp/calendar/icalendar-resources/import-rrule-count-bi-weekly.ics
new file mode 100644
index 00000000000..888b85bb331
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-count-bi-weekly.ics
@@ -0,0 +1,11 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+SUMMARY:rrule count bi-weekly 3 times
+DTSTART;VALUE=DATE-TIME:20030919T090000
+DTEND;VALUE=DATE-TIME:20030919T113000
+RRULE:FREQ=WEEKLY;COUNT=3;INTERVAL=2
+END:VEVENT
+END:VCALENDAR
+
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-count-daily-long.diary-american b/test/lisp/calendar/icalendar-resources/import-rrule-count-daily-long.diary-american
new file mode 100644
index 00000000000..23fe9fcaf32
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-count-daily-long.diary-american
@@ -0,0 +1 @@
+&%%(and (diary-cyclic 1 9 19 2003) (diary-block 9 19 2003 10 2 2003)) 09:00-11:30 rrule count daily long
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-count-daily-long.diary-european b/test/lisp/calendar/icalendar-resources/import-rrule-count-daily-long.diary-european
new file mode 100644
index 00000000000..0d4ab669058
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-count-daily-long.diary-european
@@ -0,0 +1 @@
+&%%(and (diary-cyclic 1 19 9 2003) (diary-block 19 9 2003 2 10 2003)) 09:00-11:30 rrule count daily long
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-count-daily-long.diary-iso b/test/lisp/calendar/icalendar-resources/import-rrule-count-daily-long.diary-iso
new file mode 100644
index 00000000000..8cecda5c879
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-count-daily-long.diary-iso
@@ -0,0 +1 @@
+&%%(and (diary-cyclic 1 2003 9 19) (diary-block 2003 9 19 2003 10 2)) 09:00-11:30 rrule count daily long
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-count-daily-long.ics b/test/lisp/calendar/icalendar-resources/import-rrule-count-daily-long.ics
new file mode 100644
index 00000000000..73df19a8196
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-count-daily-long.ics
@@ -0,0 +1,11 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+SUMMARY:rrule count daily long
+DTSTART;VALUE=DATE-TIME:20030919T090000
+DTEND;VALUE=DATE-TIME:20030919T113000
+RRULE:FREQ=DAILY;COUNT=14;INTERVAL=1
+END:VEVENT
+END:VCALENDAR
+
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-count-daily-short.diary-american b/test/lisp/calendar/icalendar-resources/import-rrule-count-daily-short.diary-american
new file mode 100644
index 00000000000..d69bb08c318
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-count-daily-short.diary-american
@@ -0,0 +1 @@
+&%%(and (diary-cyclic 1 9 19 2003) (diary-block 9 19 2003 9 19 2003)) 09:00-11:30 rrule count daily short
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-count-daily-short.diary-european b/test/lisp/calendar/icalendar-resources/import-rrule-count-daily-short.diary-european
new file mode 100644
index 00000000000..33a1ce4cf51
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-count-daily-short.diary-european
@@ -0,0 +1 @@
+&%%(and (diary-cyclic 1 19 9 2003) (diary-block 19 9 2003 19 9 2003)) 09:00-11:30 rrule count daily short
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-count-daily-short.diary-iso b/test/lisp/calendar/icalendar-resources/import-rrule-count-daily-short.diary-iso
new file mode 100644
index 00000000000..a06bcba0dc1
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-count-daily-short.diary-iso
@@ -0,0 +1 @@
+&%%(and (diary-cyclic 1 2003 9 19) (diary-block 2003 9 19 2003 9 19)) 09:00-11:30 rrule count daily short
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-count-daily-short.ics b/test/lisp/calendar/icalendar-resources/import-rrule-count-daily-short.ics
new file mode 100644
index 00000000000..92ffe8be654
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-count-daily-short.ics
@@ -0,0 +1,11 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+SUMMARY:rrule count daily short
+DTSTART;VALUE=DATE-TIME:20030919T090000
+DTEND;VALUE=DATE-TIME:20030919T113000
+RRULE:FREQ=DAILY;COUNT=1;INTERVAL=1
+END:VEVENT
+END:VCALENDAR
+
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-count-every-second-month.diary-american b/test/lisp/calendar/icalendar-resources/import-rrule-count-every-second-month.diary-american
new file mode 100644
index 00000000000..4ce8ef842f8
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-count-every-second-month.diary-american
@@ -0,0 +1 @@
+&%%(and (diary-date t 19 t) (diary-block 9 19 2003 5 19 2004)) 09:00-11:30 rrule count every second month
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-count-every-second-month.diary-european b/test/lisp/calendar/icalendar-resources/import-rrule-count-every-second-month.diary-european
new file mode 100644
index 00000000000..09ec3756295
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-count-every-second-month.diary-european
@@ -0,0 +1 @@
+&%%(and (diary-date 19 t t) (diary-block 19 9 2003 19 5 2004)) 09:00-11:30 rrule count every second month
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-count-every-second-month.diary-iso b/test/lisp/calendar/icalendar-resources/import-rrule-count-every-second-month.diary-iso
new file mode 100644
index 00000000000..ae6feb70d4c
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-count-every-second-month.diary-iso
@@ -0,0 +1 @@
+&%%(and (diary-date t t 19) (diary-block 2003 9 19 2004 5 19)) 09:00-11:30 rrule count every second month
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-count-every-second-month.ics b/test/lisp/calendar/icalendar-resources/import-rrule-count-every-second-month.ics
new file mode 100644
index 00000000000..3b27b665498
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-count-every-second-month.ics
@@ -0,0 +1,11 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+SUMMARY:rrule count every second month
+DTSTART;VALUE=DATE-TIME:20030919T090000
+DTEND;VALUE=DATE-TIME:20030919T113000
+RRULE:FREQ=MONTHLY;INTERVAL=2;COUNT=5
+END:VEVENT
+END:VCALENDAR
+
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-count-every-second-year.diary-american b/test/lisp/calendar/icalendar-resources/import-rrule-count-every-second-year.diary-american
new file mode 100644
index 00000000000..99543aa9596
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-count-every-second-year.diary-american
@@ -0,0 +1 @@
+&%%(and (diary-date 9 19 t) (diary-block 9 19 2003 9 19 2011)) 09:00-11:30 rrule count every second year
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-count-every-second-year.diary-european b/test/lisp/calendar/icalendar-resources/import-rrule-count-every-second-year.diary-european
new file mode 100644
index 00000000000..3b330886ce0
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-count-every-second-year.diary-european
@@ -0,0 +1 @@
+&%%(and (diary-date 19 9 t) (diary-block 19 9 2003 19 9 2011)) 09:00-11:30 rrule count every second year
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-count-every-second-year.diary-iso b/test/lisp/calendar/icalendar-resources/import-rrule-count-every-second-year.diary-iso
new file mode 100644
index 00000000000..16af52ea91c
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-count-every-second-year.diary-iso
@@ -0,0 +1 @@
+&%%(and (diary-date t 9 19) (diary-block 2003 9 19 2011 9 19)) 09:00-11:30 rrule count every second year
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-count-every-second-year.ics b/test/lisp/calendar/icalendar-resources/import-rrule-count-every-second-year.ics
new file mode 100644
index 00000000000..ce21c34d09a
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-count-every-second-year.ics
@@ -0,0 +1,10 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+SUMMARY:rrule count every second year
+DTSTART;VALUE=DATE-TIME:20030919T090000
+DTEND;VALUE=DATE-TIME:20030919T113000
+RRULE:FREQ=YEARLY;INTERVAL=2;COUNT=5
+END:VEVENT
+END:VCALENDAR
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-count-monthly.diary-american b/test/lisp/calendar/icalendar-resources/import-rrule-count-monthly.diary-american
new file mode 100644
index 00000000000..ad5ca0b0ed4
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-count-monthly.diary-american
@@ -0,0 +1 @@
+&%%(and (diary-date t 19 t) (diary-block 9 19 2003 1 19 2004)) 09:00-11:30 rrule count monthly
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-count-monthly.diary-european b/test/lisp/calendar/icalendar-resources/import-rrule-count-monthly.diary-european
new file mode 100644
index 00000000000..709de3a3fd5
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-count-monthly.diary-european
@@ -0,0 +1 @@
+&%%(and (diary-date 19 t t) (diary-block 19 9 2003 19 1 2004)) 09:00-11:30 rrule count monthly
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-count-monthly.diary-iso b/test/lisp/calendar/icalendar-resources/import-rrule-count-monthly.diary-iso
new file mode 100644
index 00000000000..9fc2a2def94
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-count-monthly.diary-iso
@@ -0,0 +1 @@
+&%%(and (diary-date t t 19) (diary-block 2003 9 19 2004 1 19)) 09:00-11:30 rrule count monthly
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-count-monthly.ics b/test/lisp/calendar/icalendar-resources/import-rrule-count-monthly.ics
new file mode 100644
index 00000000000..3391ca24252
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-count-monthly.ics
@@ -0,0 +1,11 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+SUMMARY:rrule count monthly
+DTSTART;VALUE=DATE-TIME:20030919T090000
+DTEND;VALUE=DATE-TIME:20030919T113000
+RRULE:FREQ=MONTHLY;INTERVAL=1;COUNT=5
+END:VEVENT
+END:VCALENDAR
+
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-count-yearly.diary-american b/test/lisp/calendar/icalendar-resources/import-rrule-count-yearly.diary-american
new file mode 100644
index 00000000000..8c1f95b0c05
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-count-yearly.diary-american
@@ -0,0 +1 @@
+&%%(and (diary-date 9 19 t) (diary-block 9 19 2003 9 19 2007)) 09:00-11:30 rrule count yearly
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-count-yearly.diary-european b/test/lisp/calendar/icalendar-resources/import-rrule-count-yearly.diary-european
new file mode 100644
index 00000000000..e216e224eae
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-count-yearly.diary-european
@@ -0,0 +1 @@
+&%%(and (diary-date 19 9 t) (diary-block 19 9 2003 19 9 2007)) 09:00-11:30 rrule count yearly
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-count-yearly.diary-iso b/test/lisp/calendar/icalendar-resources/import-rrule-count-yearly.diary-iso
new file mode 100644
index 00000000000..3801192ee60
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-count-yearly.diary-iso
@@ -0,0 +1 @@
+&%%(and (diary-date t 9 19) (diary-block 2003 9 19 2007 9 19)) 09:00-11:30 rrule count yearly
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-count-yearly.ics b/test/lisp/calendar/icalendar-resources/import-rrule-count-yearly.ics
new file mode 100644
index 00000000000..d8569933e0c
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-count-yearly.ics
@@ -0,0 +1,11 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+SUMMARY:rrule count yearly
+DTSTART;VALUE=DATE-TIME:20030919T090000
+DTEND;VALUE=DATE-TIME:20030919T113000
+RRULE:FREQ=YEARLY;INTERVAL=1;COUNT=5
+END:VEVENT
+END:VCALENDAR
+
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-daily-two-day.diary-american b/test/lisp/calendar/icalendar-resources/import-rrule-daily-two-day.diary-american
new file mode 100644
index 00000000000..495fca5f8df
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-daily-two-day.diary-american
@@ -0,0 +1 @@
+&%%(and (diary-cyclic 2 9 19 2003)) 09:00-11:30 rrule daily
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-daily-two-day.diary-european b/test/lisp/calendar/icalendar-resources/import-rrule-daily-two-day.diary-european
new file mode 100644
index 00000000000..61db14ab24a
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-daily-two-day.diary-european
@@ -0,0 +1 @@
+&%%(and (diary-cyclic 2 19 9 2003)) 09:00-11:30 rrule daily
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-daily-two-day.diary-iso b/test/lisp/calendar/icalendar-resources/import-rrule-daily-two-day.diary-iso
new file mode 100644
index 00000000000..0e0a4b19781
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-daily-two-day.diary-iso
@@ -0,0 +1 @@
+&%%(and (diary-cyclic 2 2003 9 19)) 09:00-11:30 rrule daily
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-daily-two-day.ics b/test/lisp/calendar/icalendar-resources/import-rrule-daily-two-day.ics
new file mode 100644
index 00000000000..8c9cb3b2845
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-daily-two-day.ics
@@ -0,0 +1,10 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+SUMMARY:rrule daily
+DTSTART;VALUE=DATE-TIME:20030919T090000
+DTEND;VALUE=DATE-TIME:20030919T113000
+RRULE:FREQ=DAILY;INTERVAL=2
+END:VEVENT
+END:VCALENDAR
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-daily-with-exceptions.diary-american b/test/lisp/calendar/icalendar-resources/import-rrule-daily-with-exceptions.diary-american
new file mode 100644
index 00000000000..83e5f582d5f
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-daily-with-exceptions.diary-american
@@ -0,0 +1 @@
+&%%(and (not (diary-date 9 25 2003)) (not (diary-date 9 21 2003)) (diary-cyclic 2 9 19 2003)) 09:00-11:30 rrule daily with exceptions
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-daily-with-exceptions.diary-european b/test/lisp/calendar/icalendar-resources/import-rrule-daily-with-exceptions.diary-european
new file mode 100644
index 00000000000..a3c7fdd4177
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-daily-with-exceptions.diary-european
@@ -0,0 +1 @@
+&%%(and (not (diary-date 25 9 2003)) (not (diary-date 21 9 2003)) (diary-cyclic 2 19 9 2003)) 09:00-11:30 rrule daily with exceptions
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-daily-with-exceptions.diary-iso b/test/lisp/calendar/icalendar-resources/import-rrule-daily-with-exceptions.diary-iso
new file mode 100644
index 00000000000..88b4c892d16
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-daily-with-exceptions.diary-iso
@@ -0,0 +1 @@
+&%%(and (not (diary-date 2003 9 25)) (not (diary-date 2003 9 21)) (diary-cyclic 2 2003 9 19)) 09:00-11:30 rrule daily with exceptions
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-daily-with-exceptions.ics b/test/lisp/calendar/icalendar-resources/import-rrule-daily-with-exceptions.ics
new file mode 100644
index 00000000000..5284bf42d8b
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-daily-with-exceptions.ics
@@ -0,0 +1,12 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+SUMMARY:rrule daily with exceptions
+DTSTART;VALUE=DATE-TIME:20030919T090000
+DTEND;VALUE=DATE-TIME:20030919T113000
+RRULE:FREQ=DAILY;INTERVAL=2
+EXDATE:20030921,20030925
+END:VEVENT
+END:VCALENDAR
+
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-daily.diary-american b/test/lisp/calendar/icalendar-resources/import-rrule-daily.diary-american
new file mode 100644
index 00000000000..9213270fa41
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-daily.diary-american
@@ -0,0 +1 @@
+&%%(and (diary-cyclic 1 9 19 2003)) 09:00-11:30 rrule daily
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-daily.diary-european b/test/lisp/calendar/icalendar-resources/import-rrule-daily.diary-european
new file mode 100644
index 00000000000..2c70cd7da55
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-daily.diary-european
@@ -0,0 +1 @@
+&%%(and (diary-cyclic 1 19 9 2003)) 09:00-11:30 rrule daily
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-daily.diary-iso b/test/lisp/calendar/icalendar-resources/import-rrule-daily.diary-iso
new file mode 100644
index 00000000000..b201cb44308
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-daily.diary-iso
@@ -0,0 +1 @@
+&%%(and (diary-cyclic 1 2003 9 19)) 09:00-11:30 rrule daily
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-daily.ics b/test/lisp/calendar/icalendar-resources/import-rrule-daily.ics
new file mode 100644
index 00000000000..6d013b0b4f6
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-daily.ics
@@ -0,0 +1,11 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+SUMMARY:rrule daily
+DTSTART;VALUE=DATE-TIME:20030919T090000
+DTEND;VALUE=DATE-TIME:20030919T113000
+RRULE:FREQ=DAILY;
+END:VEVENT
+END:VCALENDAR
+
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-monthly-no-end.diary-american b/test/lisp/calendar/icalendar-resources/import-rrule-monthly-no-end.diary-american
new file mode 100644
index 00000000000..bc5453fe425
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-monthly-no-end.diary-american
@@ -0,0 +1 @@
+&%%(and (diary-date t 19 t) (diary-block 9 19 2003 1 1 9999)) 09:00-11:30 rrule monthly no end
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-monthly-no-end.diary-european b/test/lisp/calendar/icalendar-resources/import-rrule-monthly-no-end.diary-european
new file mode 100644
index 00000000000..f071519701d
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-monthly-no-end.diary-european
@@ -0,0 +1 @@
+&%%(and (diary-date 19 t t) (diary-block 19 9 2003 1 1 9999)) 09:00-11:30 rrule monthly no end
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-monthly-no-end.diary-iso b/test/lisp/calendar/icalendar-resources/import-rrule-monthly-no-end.diary-iso
new file mode 100644
index 00000000000..3709e933337
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-monthly-no-end.diary-iso
@@ -0,0 +1 @@
+&%%(and (diary-date t t 19) (diary-block 2003 9 19 9999 1 1)) 09:00-11:30 rrule monthly no end
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-monthly-no-end.ics b/test/lisp/calendar/icalendar-resources/import-rrule-monthly-no-end.ics
new file mode 100644
index 00000000000..b871658600a
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-monthly-no-end.ics
@@ -0,0 +1,11 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+SUMMARY:rrule monthly no end
+DTSTART;VALUE=DATE-TIME:20030919T090000
+DTEND;VALUE=DATE-TIME:20030919T113000
+RRULE:FREQ=MONTHLY;
+END:VEVENT
+END:VCALENDAR
+
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-monthly-with-end.diary-american b/test/lisp/calendar/icalendar-resources/import-rrule-monthly-with-end.diary-american
new file mode 100644
index 00000000000..638ab8b2327
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-monthly-with-end.diary-american
@@ -0,0 +1 @@
+&%%(and (diary-date t 19 t) (diary-block 9 19 2003 8 19 2005)) 09:00-11:30 rrule monthly with end
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-monthly-with-end.diary-european b/test/lisp/calendar/icalendar-resources/import-rrule-monthly-with-end.diary-european
new file mode 100644
index 00000000000..c70cde25f32
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-monthly-with-end.diary-european
@@ -0,0 +1 @@
+&%%(and (diary-date 19 t t) (diary-block 19 9 2003 19 8 2005)) 09:00-11:30 rrule monthly with end
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-monthly-with-end.diary-iso b/test/lisp/calendar/icalendar-resources/import-rrule-monthly-with-end.diary-iso
new file mode 100644
index 00000000000..ee51a2142a4
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-monthly-with-end.diary-iso
@@ -0,0 +1 @@
+&%%(and (diary-date t t 19) (diary-block 2003 9 19 2005 8 19)) 09:00-11:30 rrule monthly with end
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-monthly-with-end.ics b/test/lisp/calendar/icalendar-resources/import-rrule-monthly-with-end.ics
new file mode 100644
index 00000000000..d8a1fe2e5af
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-monthly-with-end.ics
@@ -0,0 +1,11 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+SUMMARY:rrule monthly with end
+DTSTART;VALUE=DATE-TIME:20030919T090000
+DTEND;VALUE=DATE-TIME:20030919T113000
+RRULE:FREQ=MONTHLY;UNTIL=20050819;
+END:VEVENT
+END:VCALENDAR
+
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-weekly.diary-american b/test/lisp/calendar/icalendar-resources/import-rrule-weekly.diary-american
new file mode 100644
index 00000000000..d8bf2eba104
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-weekly.diary-american
@@ -0,0 +1 @@
+&%%(and (diary-cyclic 7 9 19 2003)) 09:00-11:30 rrule weekly
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-weekly.diary-european b/test/lisp/calendar/icalendar-resources/import-rrule-weekly.diary-european
new file mode 100644
index 00000000000..e368fde9709
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-weekly.diary-european
@@ -0,0 +1 @@
+&%%(and (diary-cyclic 7 19 9 2003)) 09:00-11:30 rrule weekly
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-weekly.diary-iso b/test/lisp/calendar/icalendar-resources/import-rrule-weekly.diary-iso
new file mode 100644
index 00000000000..49cd9d8ace6
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-weekly.diary-iso
@@ -0,0 +1 @@
+&%%(and (diary-cyclic 7 2003 9 19)) 09:00-11:30 rrule weekly
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-weekly.ics b/test/lisp/calendar/icalendar-resources/import-rrule-weekly.ics
new file mode 100644
index 00000000000..c3f0b8ae933
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-weekly.ics
@@ -0,0 +1,11 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+SUMMARY:rrule weekly
+DTSTART;VALUE=DATE-TIME:20030919T090000
+DTEND;VALUE=DATE-TIME:20030919T113000
+RRULE:FREQ=WEEKLY;
+END:VEVENT
+END:VCALENDAR
+
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-yearly.diary-american b/test/lisp/calendar/icalendar-resources/import-rrule-yearly.diary-american
new file mode 100644
index 00000000000..bc485d8a6c4
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-yearly.diary-american
@@ -0,0 +1 @@
+&%%(diary-anniversary 9 19 2002) 09:00-11:30 rrule yearly
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-yearly.diary-european b/test/lisp/calendar/icalendar-resources/import-rrule-yearly.diary-european
new file mode 100644
index 00000000000..42509d42bc8
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-yearly.diary-european
@@ -0,0 +1 @@
+&%%(diary-anniversary 19 9 2002) 09:00-11:30 rrule yearly
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-yearly.diary-iso b/test/lisp/calendar/icalendar-resources/import-rrule-yearly.diary-iso
new file mode 100644
index 00000000000..72fe6e12cbd
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-yearly.diary-iso
@@ -0,0 +1 @@
+&%%(diary-anniversary 2002 9 19) 09:00-11:30 rrule yearly
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-yearly.ics b/test/lisp/calendar/icalendar-resources/import-rrule-yearly.ics
new file mode 100644
index 00000000000..21cca097f7e
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-yearly.ics
@@ -0,0 +1,11 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+SUMMARY:rrule yearly
+DTSTART;VALUE=DATE-TIME:20030919T090000
+DTEND;VALUE=DATE-TIME:20030919T113000
+RRULE:FREQ=YEARLY;INTERVAL=2
+END:VEVENT
+END:VCALENDAR
+
diff --git a/test/lisp/calendar/icalendar-resources/import-with-timezone.diary-iso b/test/lisp/calendar/icalendar-resources/import-with-timezone.diary-iso
new file mode 100644
index 00000000000..f99b59213e5
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-with-timezone.diary-iso
@@ -0,0 +1,2 @@
+&2012/1/15 15:00-15:30 standardtime
+&2012/12/15 11:00-11:30 daylightsavingtime
diff --git a/test/lisp/calendar/icalendar-resources/import-with-timezone.ics b/test/lisp/calendar/icalendar-resources/import-with-timezone.ics
new file mode 100644
index 00000000000..110a9835e41
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-with-timezone.ics
@@ -0,0 +1,27 @@
+BEGIN:VCALENDAR
+BEGIN:VTIMEZONE
+TZID:fictional, nonexistent, arbitrary
+BEGIN:STANDARD
+DTSTART:20100101T000000
+TZOFFSETFROM:+0200
+TZOFFSETTO:-0200
+RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=1SU;BYMONTH=01
+END:STANDARD
+BEGIN:DAYLIGHT
+DTSTART:20101201T000000
+TZOFFSETFROM:-0200
+TZOFFSETTO:+0200
+RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=1SU;BYMONTH=11
+END:DAYLIGHT
+END:VTIMEZONE
+BEGIN:VEVENT
+SUMMARY:standardtime
+DTSTART;TZID="fictional, nonexistent, arbitrary":20120115T120000
+DTEND;TZID="fictional, nonexistent, arbitrary":20120115T123000
+END:VEVENT
+BEGIN:VEVENT
+SUMMARY:daylightsavingtime
+DTSTART;TZID="fictional, nonexistent, arbitrary":20121215T120000
+DTEND;TZID="fictional, nonexistent, arbitrary":20121215T123000
+END:VEVENT
+END:VCALENDAR
diff --git a/test/lisp/calendar/icalendar-resources/import-with-uid.diary-american b/test/lisp/calendar/icalendar-resources/import-with-uid.diary-american
new file mode 100644
index 00000000000..9b2f06afc26
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-with-uid.diary-american
@@ -0,0 +1,2 @@
+&9/19/2003 09:00-11:30 non-recurring
+ UID: 1234567890uid
diff --git a/test/lisp/calendar/icalendar-resources/import-with-uid.diary-european b/test/lisp/calendar/icalendar-resources/import-with-uid.diary-european
new file mode 100644
index 00000000000..95db4d40151
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-with-uid.diary-european
@@ -0,0 +1,2 @@
+&19/9/2003 09:00-11:30 non-recurring
+ UID: 1234567890uid
diff --git a/test/lisp/calendar/icalendar-resources/import-with-uid.diary-iso b/test/lisp/calendar/icalendar-resources/import-with-uid.diary-iso
new file mode 100644
index 00000000000..d372e5a3d1f
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-with-uid.diary-iso
@@ -0,0 +1,2 @@
+&2003/9/19 09:00-11:30 non-recurring
+ UID: 1234567890uid
diff --git a/test/lisp/calendar/icalendar-resources/import-with-uid.ics b/test/lisp/calendar/icalendar-resources/import-with-uid.ics
new file mode 100644
index 00000000000..db412d9d9f5
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-with-uid.ics
@@ -0,0 +1,10 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+UID:1234567890uid
+SUMMARY:non-recurring
+DTSTART;VALUE=DATE-TIME:20030919T090000
+DTEND;VALUE=DATE-TIME:20030919T113000
+END:VEVENT
+END:VCALENDAR
diff --git a/test/lisp/calendar/icalendar-tests.el b/test/lisp/calendar/icalendar-tests.el
index 80a79db75cf..7f8cd479146 100644
--- a/test/lisp/calendar/icalendar-tests.el
+++ b/test/lisp/calendar/icalendar-tests.el
@@ -1,6 +1,6 @@
-;; icalendar-tests.el --- Test suite for icalendar.el
+;;; icalendar-tests.el --- Test suite for icalendar.el -*- lexical-binding:t -*-
-;; Copyright (C) 2005, 2008-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2005, 2008-2022 Free Software Foundation, Inc.
;; Author: Ulf Jasper <ulf.jasper@web.de>
;; Created: March 2005
@@ -32,6 +32,7 @@
;;; Code:
(require 'ert)
+(require 'ert-x)
(require 'icalendar)
;; ======================================================================
@@ -51,23 +52,31 @@
(replace-regexp-in-string "[ \t\n]+\\'" ""
(replace-regexp-in-string "\\`[ \t\n]+" "" string)))
+(defun icalendar-tests--get-file-contents (filename)
+ "Return contents of file in test data directory named FILENAME."
+ (with-temp-buffer
+ (let ((coding-system-for-read 'raw-text)
+ (inhibit-eol-conversion t))
+ (insert-file-contents-literally
+ (ert-resource-file filename))
+ (buffer-string))))
+
;; ======================================================================
;; Tests of functions
;; ======================================================================
(ert-deftest icalendar--create-uid ()
"Test for `icalendar--create-uid'."
- (let* ((icalendar-uid-format "xxx-%t-%c-%h-%u-%s")
+ (let* ((icalendar-uid-format "xxx-%c-%h-%u-%s")
(icalendar--uid-count 77)
(entry-full "30.06.1964 07:01 blahblah")
(hash (format "%d" (abs (sxhash entry-full))))
(contents "DTSTART:19640630T070100\nblahblah")
(username (or user-login-name "UNKNOWN_USER")))
- (cl-letf (((symbol-function 'current-time) (lambda () '(1 2 3))))
- (should (= 77 icalendar--uid-count))
- (should (string= (concat "xxx-123-77-" hash "-" username "-19640630")
- (icalendar--create-uid entry-full contents)))
- (should (= 78 icalendar--uid-count)))
+ (should (= 77 icalendar--uid-count))
+ (should (string= (concat "xxx-77-" hash "-" username "-19640630")
+ (icalendar--create-uid entry-full contents)))
+ (should (= 78 icalendar--uid-count))
(setq contents "blahblah")
(setq icalendar-uid-format "yyy%syyy")
(should (string= (concat "yyyDTSTARTyyy")
@@ -78,7 +87,7 @@
(let* ((calendar-date-style 'iso)
result)
(setq result (icalendar--convert-anniversary-to-ical
- "" "%%(diary-anniversary 1964 6 30) g"))
+ "" "%%(diary-anniversary 1963 6 30) g"))
(should (consp result))
(should (string= (concat
"\nDTSTART;VALUE=DATE:19640630"
@@ -184,6 +193,7 @@
(ert-deftest icalendar--parse-vtimezone ()
"Test method for `icalendar--parse-vtimezone'."
(let (vtimezone result)
+ ;; testcase: valid timezone with rrule
(setq vtimezone (icalendar-tests--get-ical-event "BEGIN:VTIMEZONE
TZID:thename
BEGIN:STANDARD
@@ -205,6 +215,8 @@ END:VTIMEZONE
(message (cdr result))
(should (string= "STD-02:00DST-03:00,M3.5.0/03:00:00,M10.5.0/04:00:00"
(cdr result)))
+
+ ;; testcase: name of tz contains comma
(setq vtimezone (icalendar-tests--get-ical-event "BEGIN:VTIMEZONE
TZID:anothername, with a comma
BEGIN:STANDARD
@@ -226,7 +238,8 @@ END:VTIMEZONE
(message (cdr result))
(should (string= "STD-02:00DST-03:00,M3.2.1/03:00:00,M10.2.1/04:00:00"
(cdr result)))
- ;; offsetfrom = offsetto
+
+ ;; testcase: offsetfrom = offsetto
(setq vtimezone (icalendar-tests--get-ical-event "BEGIN:VTIMEZONE
TZID:Kolkata, Chennai, Mumbai, New Delhi
X-MICROSOFT-CDO-TZID:23
@@ -246,7 +259,10 @@ END:VTIMEZONE
(should (string= "Kolkata, Chennai, Mumbai, New Delhi" (car result)))
(message (cdr result))
(should (string= "STD-05:30DST-05:30,M1.1.1/00:00:00,M1.1.1/00:00:00"
- (cdr result)))))
+ (cdr result)))
+
+ ;; FIXME: add testcase that covers changes for fix of bug#34315
+ ))
(ert-deftest icalendar--convert-ordinary-to-ical ()
"Test method for `icalendar--convert-ordinary-to-ical'."
@@ -337,7 +353,7 @@ END:VTIMEZONE
(let ((calendar-date-style 'iso))
;; numeric iso
(should (string= "20080511"
- (icalendar--datestring-to-isodate "2008 05 11")))
+ (icalendar--datestring-to-isodate "2008 05 11")))
(should (string= "20080531"
(icalendar--datestring-to-isodate "2008 05 31")))
(should (string= "20080602"
@@ -368,7 +384,19 @@ END:VTIMEZONE
(should (string= "20081105"
(icalendar--datestring-to-isodate "05 Nov 2008")))
(should (string= "20081105"
- (icalendar--datestring-to-isodate "2008 Nov 05")))))
+ (icalendar--datestring-to-isodate "2008 Nov 05")))
+
+ ;; non-numeric with day-shift and year-shift
+ (setq calendar-date-style nil) ;not necessary for conversion
+ (should (string= "20210212"
+ (icalendar--datestring-to-isodate "2021 Feb 11" 1)))
+ (should (string= "20210131"
+ (icalendar--datestring-to-isodate "2021 Feb 11" -11)))
+ (should (string= "20200211"
+ (icalendar--datestring-to-isodate "2021 Feb 11" nil -1)))
+ (should (string= "21010211"
+ (icalendar--datestring-to-isodate "2021 Feb 11" nil 80)))
+ ))
(ert-deftest icalendar--first-weekday-of-year ()
"Test method for `icalendar-first-weekday-of-year'."
@@ -420,11 +448,11 @@ END:VEVENT
")))
(should (string= "SUM sum DES des LOC loc ORG org"
(icalendar--format-ical-event event)))
- (setq icalendar-import-format (lambda (&rest ignore)
+ (setq icalendar-import-format (lambda (&rest _ignore)
"helloworld"))
(should (string= "helloworld" (icalendar--format-ical-event event)))
(setq icalendar-import-format
- (lambda (e)
+ (lambda (event)
(format "-%s-%s-%s-%s-%s-%s-%s-"
(icalendar--get-event-property event 'SUMMARY)
(icalendar--get-event-property event 'DESCRIPTION)
@@ -466,8 +494,7 @@ END:VEVENT
(ert-deftest icalendar--decode-isodatetime ()
"Test `icalendar--decode-isodatetime'."
- (let ((tz (getenv "TZ"))
- result)
+ (let ((tz (getenv "TZ")))
(unwind-protect
(progn
;; Use Eastern European Time (UTC+2, UTC+3 daylight saving)
@@ -484,17 +511,132 @@ END:VEVENT
(should (equal '(0 0 10 1 8 2013 4 t 10800)
(icalendar--decode-isodatetime "20130801T100000")))
+ ;; testcase: no time zone in input, shift by -1 days
+ ;; 1 Jan 2013 10:00 -> 31 Dec 2012
+ (should (equal '(0 0 10 31 12 2012 1 nil 7200)
+ (icalendar--decode-isodatetime "20130101T100000" -1)))
+ ;; 1 Aug 2013 10:00 (DST) -> 31 Jul 2012 (DST)
+ (should (equal '(0 0 10 31 7 2013 3 t 10800)
+ (icalendar--decode-isodatetime "20130801T100000" -1)))
+
+
;; testcase: UTC time zone specifier in input -> convert to local time
- ;; 31 Dec 2013 23:00 UTC -> 1 Jan 2013 01:00 EET
+ ;; 31 Dec 2013 23:00 UTC -> 1 Jan 2014 01:00 EET
(should (equal '(0 0 1 1 1 2014 3 nil 7200)
(icalendar--decode-isodatetime "20131231T230000Z")))
;; 1 Aug 2013 10:00 UTC -> 1 Aug 2013 13:00 EEST
(should (equal '(0 0 13 1 8 2013 4 t 10800)
(icalendar--decode-isodatetime "20130801T100000Z")))
+ ;; testcase: override timezone with Central European Time, 1 Jan 2013 10:00 -> 1 Jan 2013 11:00
+ (should (equal '(0 0 11 1 1 2013 2 nil 7200)
+ (icalendar--decode-isodatetime "20130101T100000" nil
+ '(3600 "CET"))))
+ ;; testcase: override timezone (UTC-02:00), 1 Jan 2013 10:00 -> 1 Jan 2013 14:00
+ (should (equal '(0 0 14 1 1 2013 2 nil 7200)
+ (icalendar--decode-isodatetime "20130101T100000" nil -7200)))
+
+ ;; FIXME: add testcase that covers changes for fix of bug#34315
+
+ )
+ ;; restore time-zone even if something went terribly wrong
+ (setenv "TZ" tz))))
+
+(ert-deftest icalendar--convert-tz-offset ()
+ "Test `icalendar--convert-tz-offset'."
+ (let ((tz (getenv "TZ")))
+ (unwind-protect
+ (progn
+ ;; Use Eastern European Time (UTC+2, UTC+3 daylight saving)
+ (setenv "TZ" "EET-2EEST,M3.5.0/3,M10.5.0/4")
+
+ ;; testcase: artificial input
+ (should (equal '("DST-03:00" . "M5.1.1/01:23:45")
+ (icalendar--convert-tz-offset
+ '((DTSTART nil "________T012345") ;
+ (TZOFFSETFROM nil "+0200")
+ (TZOFFSETTO nil "+0300")
+ (RRULE nil "FREQ=YEARLY;INTERVAL=1;BYDAY=1MO;BYMONTH=5"))
+ t)))
+
+ ;; testcase: Europe/Berlin Standard
+ (should (equal '("STD-01:00" . "M10.5.0/03:00:00")
+ (icalendar--convert-tz-offset
+ '((TZOFFSETFROM nil "+0200")
+ (TZOFFSETTO nil "+0100")
+ (TZNAME nil CET)
+ (DTSTART nil "19701025T030000")
+ (RRULE nil "FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU"))
+ nil)))
+
+ ;; testcase: Europe/Berlin DST
+ (should (equal '("DST-02:00" . "M3.5.0/02:00:00")
+ (icalendar--convert-tz-offset
+ '((TZOFFSETFROM nil "+0100")
+ (TZOFFSETTO nil "+0200")
+ (TZNAME nil CEST)
+ (DTSTART nil "19700329T020000")
+ (RRULE nil "FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU"))
+ t)))
+
+ ;; testcase: dtstart is mandatory
+ (should (null (icalendar--convert-tz-offset
+ '((TZOFFSETFROM nil "+0100")
+ (TZOFFSETTO nil "+0200")
+ (RRULE nil "FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU"))
+ t)))
+
+ ;; FIXME: rrule and rdate are NOT mandatory! Must fix code
+ ;; before activating these testcases
+ ;; ;; testcase: no rrule and no rdate => no result
+ ;; (should (null (icalendar--convert-tz-offset
+ ;; '((TZOFFSETFROM nil "+0100")
+ ;; (TZOFFSETTO nil "+0200")
+ ;; (DTSTART nil "19700329T020000"))
+ ;; t)))
+ ;; ;; testcase: no rrule with rdate => no result
+ ;; (should (null (icalendar--convert-tz-offset
+ ;; '((TZOFFSETFROM nil "+0100")
+ ;; (TZOFFSETTO nil "+0200")
+ ;; (DTSTART nil "18840101T000000")
+ ;; (RDATE nil "18840101T000000"))
+ ;; t)))
)
;; restore time-zone even if something went terribly wrong
- (setenv "TZ" tz))) )
+ (setenv "TZ" tz))))
+
+(ert-deftest icalendar--decode-isoduration ()
+ "Test `icalendar--decode-isoduration'."
+
+ ;; testcase: 7 days
+ (should (equal '(0 0 0 7 0 0)
+ (icalendar--decode-isoduration "P7D")))
+
+ ;; testcase: 7 days, one second -- see bug#34315
+ (should (equal '(1 0 0 7 0 0)
+ (icalendar--decode-isoduration "P7DT1S")))
+
+ ;; testcase: 3 hours, 2 minutes, one second
+ (should (equal '(1 2 3 0 0 0)
+ (icalendar--decode-isoduration "PT3H2M1S")))
+
+ ;; testcase: 99 days, 3 hours, 2 minutes, one second -- see bug#34315
+ (should (equal '(1 2 3 99 0 0)
+ (icalendar--decode-isoduration "P99DT3H2M1S")))
+
+ ;; testcase: 2 weeks
+ (should (equal '(0 0 0 14 0 0)
+ (icalendar--decode-isoduration "P2W")))
+
+ ;; testcase: rfc2445, section 4.3.6: 15 days, 5 hours and 20 seconds -- see bug#34315
+ (should (equal '(20 0 5 15 0 0)
+ (icalendar--decode-isoduration "P15DT5H0M20S")))
+
+ ;; testcase: rfc2445, section 4.3.6: 7 weeks
+ (should (equal '(0 0 0 49 0 0)
+ (icalendar--decode-isoduration "P7W")))
+ )
+
;; ======================================================================
;; Export tests
@@ -509,8 +651,8 @@ Argument INPUT-AMERICAN american style diary string.
Argument EXPECTED-OUTPUT expected iCalendar result string.
Optional argument ALARMS the value of `icalendar-export-alarms' for this test.
-European style input data must use german month names. American
-and ISO style input data must use english month names."
+European style input data must use German month names. American
+and ISO style input data must use English month names."
(let ((tz (getenv "TZ"))
(calendar-date-style 'iso)
(icalendar-recurring-start-year 2000)
@@ -556,17 +698,18 @@ and ISO style input data must use english month names."
"Actually perform export test.
Argument INPUT input diary string.
Argument EXPECTED-OUTPUT expected iCalendar result string."
- (let ((temp-file (make-temp-file "icalendar-tests-ics")))
+ (ert-with-temp-file temp-file
+ :suffix "icalendar-tests-ics"
(unwind-protect
- (progn
- (with-temp-buffer
- (insert input)
- (icalendar-export-region (point-min) (point-max) temp-file))
- (save-excursion
- (find-file temp-file)
- (goto-char (point-min))
- (cond (expected-output
- (should (re-search-forward "^\\s-*BEGIN:VCALENDAR
+ (progn
+ (with-temp-buffer
+ (insert input)
+ (icalendar-export-region (point-min) (point-max) temp-file))
+ (save-excursion
+ (find-file temp-file)
+ (goto-char (point-min))
+ (cond (expected-output
+ (should (re-search-forward "^\\s-*BEGIN:VCALENDAR
PRODID:-//Emacs//NONSGML icalendar.el//EN
VERSION:2.0
BEGIN:VEVENT
@@ -575,23 +718,22 @@ UID:emacs[0-9]+
END:VEVENT
END:VCALENDAR
\\s-*$"
- nil t))
- (should (string-match
- (concat "^\\s-*"
- (regexp-quote (buffer-substring-no-properties
- (match-beginning 1) (match-end 1)))
- "\\s-*$")
- expected-output)))
- (t
- (should (re-search-forward "^\\s-*BEGIN:VCALENDAR
+ nil t))
+ (should (string-match
+ (concat "^\\s-*"
+ (regexp-quote (buffer-substring-no-properties
+ (match-beginning 1) (match-end 1)))
+ "\\s-*$")
+ expected-output)))
+ (t
+ (should (re-search-forward "^\\s-*BEGIN:VCALENDAR
PRODID:-//Emacs//NONSGML icalendar.el//EN
VERSION:2.0
END:VCALENDAR
\\s-*$"
- nil t))))))
+ nil t))))))
;; cleanup!!
- (kill-buffer (find-buffer-visiting temp-file))
- (delete-file temp-file))))
+ (kill-buffer (find-buffer-visiting temp-file)))))
(ert-deftest icalendar-export-ordinary-no-time ()
"Perform export test."
@@ -700,18 +842,18 @@ SUMMARY:yearly no time
"Perform export test."
;; anniversaries
(icalendar-tests--test-export
- "%%(diary-anniversary 1989 10 3) anniversary no time"
- "%%(diary-anniversary 3 10 1989) anniversary no time"
- "%%(diary-anniversary 10 3 1989) anniversary no time"
+ "%%(diary-anniversary 1988 10 3) anniversary no time"
+ "%%(diary-anniversary 3 10 1988) anniversary no time"
+ "%%(diary-anniversary 10 3 1988) anniversary no time"
"DTSTART;VALUE=DATE:19891003
DTEND;VALUE=DATE:19891004
RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=10;BYMONTHDAY=03
SUMMARY:anniversary no time
")
(icalendar-tests--test-export
- "%%(diary-anniversary 1989 10 3) 19:00-20:00 anniversary with time"
- "%%(diary-anniversary 3 10 1989) 19:00-20:00 anniversary with time"
- "%%(diary-anniversary 10 3 1989) 19:00-20:00 anniversary with time"
+ "%%(diary-anniversary 1988 10 3) 19:00-20:00 anniversary with time"
+ "%%(diary-anniversary 3 10 1988) 19:00-20:00 anniversary with time"
+ "%%(diary-anniversary 10 3 1988) 19:00-20:00 anniversary with time"
"DTSTART;VALUE=DATE-TIME:19891003T190000
DTEND;VALUE=DATE-TIME:19891004T200000
RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=10;BYMONTHDAY=03
@@ -761,12 +903,12 @@ SUMMARY:no alarm
"
nil)
- ;; 10 minutes in advance, audio
- (icalendar-tests--test-export
- "2014 Nov 17 19:30 audio alarm"
- "17 Nov 2014 19:30 audio alarm"
- "Nov 17 2014 19:30 audio alarm"
- "DTSTART;VALUE=DATE-TIME:20141117T193000
+ ;; 10 minutes in advance, audio
+ (icalendar-tests--test-export
+ "2014 Nov 17 19:30 audio alarm"
+ "17 Nov 2014 19:30 audio alarm"
+ "Nov 17 2014 19:30 audio alarm"
+ "DTSTART;VALUE=DATE-TIME:20141117T193000
DTEND;VALUE=DATE-TIME:20141117T203000
SUMMARY:audio alarm
BEGIN:VALARM
@@ -774,14 +916,14 @@ ACTION:AUDIO
TRIGGER:-PT10M
END:VALARM
"
- '(10 ((audio))))
+ '(10 ((audio))))
- ;; 20 minutes in advance, display
- (icalendar-tests--test-export
- "2014 Nov 17 19:30 display alarm"
- "17 Nov 2014 19:30 display alarm"
- "Nov 17 2014 19:30 display alarm"
- "DTSTART;VALUE=DATE-TIME:20141117T193000
+ ;; 20 minutes in advance, display
+ (icalendar-tests--test-export
+ "2014 Nov 17 19:30 display alarm"
+ "17 Nov 2014 19:30 display alarm"
+ "Nov 17 2014 19:30 display alarm"
+ "DTSTART;VALUE=DATE-TIME:20141117T193000
DTEND;VALUE=DATE-TIME:20141117T203000
SUMMARY:display alarm
BEGIN:VALARM
@@ -790,14 +932,14 @@ TRIGGER:-PT20M
DESCRIPTION:display alarm
END:VALARM
"
- '(20 ((display))))
+ '(20 ((display))))
- ;; 66 minutes in advance, email
- (icalendar-tests--test-export
- "2014 Nov 17 19:30 email alarm"
- "17 Nov 2014 19:30 email alarm"
- "Nov 17 2014 19:30 email alarm"
- "DTSTART;VALUE=DATE-TIME:20141117T193000
+ ;; 66 minutes in advance, email
+ (icalendar-tests--test-export
+ "2014 Nov 17 19:30 email alarm"
+ "17 Nov 2014 19:30 email alarm"
+ "Nov 17 2014 19:30 email alarm"
+ "DTSTART;VALUE=DATE-TIME:20141117T193000
DTEND;VALUE=DATE-TIME:20141117T203000
SUMMARY:email alarm
BEGIN:VALARM
@@ -809,14 +951,14 @@ ATTENDEE:MAILTO:att.one@email.com
ATTENDEE:MAILTO:att.two@email.com
END:VALARM
"
- '(66 ((email ("att.one@email.com" "att.two@email.com")))))
+ '(66 ((email ("att.one@email.com" "att.two@email.com")))))
- ;; 2 minutes in advance, all alarms
- (icalendar-tests--test-export
- "2014 Nov 17 19:30 all alarms"
- "17 Nov 2014 19:30 all alarms"
- "Nov 17 2014 19:30 all alarms"
- "DTSTART;VALUE=DATE-TIME:20141117T193000
+ ;; 2 minutes in advance, all alarms
+ (icalendar-tests--test-export
+ "2014 Nov 17 19:30 all alarms"
+ "17 Nov 2014 19:30 all alarms"
+ "Nov 17 2014 19:30 all alarms"
+ "DTSTART;VALUE=DATE-TIME:20141117T193000
DTEND;VALUE=DATE-TIME:20141117T203000
SUMMARY:all alarms
BEGIN:VALARM
@@ -837,19 +979,22 @@ TRIGGER:-PT2M
DESCRIPTION:all alarms
END:VALARM
"
- '(2 ((email ("att.one@email.com" "att.two@email.com")) (audio) (display)))))
+ '(2 ((email ("att.one@email.com" "att.two@email.com")) (audio) (display)))))
;; ======================================================================
;; Import tests
;; ======================================================================
-(defun icalendar-tests--test-import (input expected-iso expected-european
- expected-american)
+(defun icalendar-tests--test-import (filename expected-iso expected-european
+ expected-american)
"Perform import test.
-Argument INPUT icalendar event string.
-Argument EXPECTED-ISO expected iso style diary string.
-Argument EXPECTED-EUROPEAN expected european style diary string.
-Argument EXPECTED-AMERICAN expected american style diary string.
+Argument FILENAME ics file to import.
+Argument EXPECTED-ISO diary-file containing expected
+iso-calendar-style result.
+Argument EXPECTED-EUROPEAN diary-file containing expected
+european-calendar-style result.
+Argument EXPECTED-AMERICAN diary-file containing expected
+american-calendar-style result.
During import test the timezone is set to Central European Time."
(let ((timezone (getenv "TZ")))
(unwind-protect
@@ -858,14 +1003,7 @@ During import test the timezone is set to Central European Time."
;; Eg hydra.nixos.org.
(setenv "TZ" "CET-1CEST,M3.5.0/2,M10.5.0/3")
(with-temp-buffer
- (if (string-match "^BEGIN:VCALENDAR" input)
- (insert input)
- (insert "BEGIN:VCALENDAR\nPRODID:-//Emacs//NONSGML icalendar.el//EN\n")
- (insert "VERSION:2.0\nBEGIN:VEVENT\n")
- (insert input)
- (unless (eq (char-before) ?\n)
- (insert "\n"))
- (insert "END:VEVENT\nEND:VCALENDAR\n"))
+ (insert (icalendar-tests--get-file-contents filename))
(let ((icalendar-import-format "%s%d%l%o%t%u%c%U")
(icalendar-import-format-summary "%s")
(icalendar-import-format-location "\n Location: %s")
@@ -878,26 +1016,30 @@ During import test the timezone is set to Central European Time."
calendar-date-style)
(when expected-iso
(setq calendar-date-style 'iso)
- (icalendar-tests--do-test-import input expected-iso))
+ (icalendar-tests--do-test-import
+ (icalendar-tests--get-file-contents expected-iso)))
(when expected-european
(setq calendar-date-style 'european)
- (icalendar-tests--do-test-import input expected-european))
+ (icalendar-tests--do-test-import
+ (icalendar-tests--get-file-contents expected-european)))
(when expected-american
(setq calendar-date-style 'american)
- (icalendar-tests--do-test-import input expected-american)))))
+ (icalendar-tests--do-test-import
+ (icalendar-tests--get-file-contents expected-american))))))
(setenv "TZ" timezone))))
-(defun icalendar-tests--do-test-import (input expected-output)
+(defun icalendar-tests--do-test-import (expected-output)
"Actually perform import test.
-Argument INPUT input icalendar string.
-Argument EXPECTED-OUTPUT expected diary string."
- (let ((temp-file (make-temp-file "icalendar-test-diary")))
+Argument EXPECTED-OUTPUT file containing expected diary string."
+ (ert-with-temp-file temp-file
+ :suffix "icalendar-test-diary"
;; Test the Catch-the-mysterious-coding-header logic below.
;; Ruby-mode adds an after-save-hook which inserts the header!
;; (save-excursion
;; (find-file temp-file)
;; (ruby-mode))
- (icalendar-import-buffer temp-file t t)
+ (let ((coding-system-for-write 'raw-text))
+ (icalendar-import-buffer temp-file t t))
(save-excursion
(find-file temp-file)
;; Check for the mysterious "# coding: ..." header, remove it
@@ -920,439 +1062,139 @@ Argument EXPECTED-OUTPUT expected diary string."
(let ((result (buffer-substring-no-properties (point-min) (point-max))))
(should (string= expected-output result)))
- (kill-buffer (find-buffer-visiting temp-file))
- (delete-file temp-file))))
+ (kill-buffer (find-buffer-visiting temp-file)))))
(ert-deftest icalendar-import-non-recurring ()
"Perform standard import tests."
- (icalendar-tests--test-import
- "SUMMARY:non-recurring
-DTSTART;VALUE=DATE-TIME:20030919T090000
-DTEND;VALUE=DATE-TIME:20030919T113000"
- "&2003/9/19 09:00-11:30 non-recurring\n"
- "&19/9/2003 09:00-11:30 non-recurring\n"
- "&9/19/2003 09:00-11:30 non-recurring\n")
- (icalendar-tests--test-import
- "SUMMARY:non-recurring allday
-DTSTART;VALUE=DATE-TIME:20030919"
- "&2003/9/19 non-recurring allday\n"
- "&19/9/2003 non-recurring allday\n"
- "&9/19/2003 non-recurring allday\n")
- (icalendar-tests--test-import
- ;; Checkdoc removes trailing blanks. Therefore: format!
- (format "%s\n%s\n%s" "SUMMARY:long " " summary"
- "DTSTART;VALUE=DATE:20030919")
- "&2003/9/19 long summary\n"
- "&19/9/2003 long summary\n"
- "&9/19/2003 long summary\n")
- (icalendar-tests--test-import
- "UID:748f2da0-0d9b-11d8-97af-b4ec8686ea61
-SUMMARY:Sommerferien
-STATUS:TENTATIVE
-CLASS:PRIVATE
-X-MOZILLA-ALARM-DEFAULT-UNITS:Minuten
-X-MOZILLA-RECUR-DEFAULT-INTERVAL:0
-DTSTART;VALUE=DATE:20040719
-DTEND;VALUE=DATE:20040828
-DTSTAMP:20031103T011641Z
-"
- "&%%(and (diary-block 2004 7 19 2004 8 27)) Sommerferien
- Status: TENTATIVE
- Class: PRIVATE
- UID: 748f2da0-0d9b-11d8-97af-b4ec8686ea61
-"
- "&%%(and (diary-block 19 7 2004 27 8 2004)) Sommerferien
- Status: TENTATIVE
- Class: PRIVATE
- UID: 748f2da0-0d9b-11d8-97af-b4ec8686ea61
-"
- "&%%(and (diary-block 7 19 2004 8 27 2004)) Sommerferien
- Status: TENTATIVE
- Class: PRIVATE
- UID: 748f2da0-0d9b-11d8-97af-b4ec8686ea61
-")
- (icalendar-tests--test-import
- "UID
- :04979712-3902-11d9-93dd-8f9f4afe08da
-SUMMARY
- :folded summary
-STATUS
- :TENTATIVE
-CLASS
- :PRIVATE
-X-MOZILLA-ALARM-DEFAULT-LENGTH
- :0
-DTSTART
- :20041123T140000
-DTEND
- :20041123T143000
-DTSTAMP
- :20041118T013430Z
-LAST-MODIFIED
- :20041118T013640Z
-"
- "&2004/11/23 14:00-14:30 folded summary
- Status: TENTATIVE
- Class: PRIVATE
- UID: 04979712-3902-11d9-93dd-8f9f4afe08da\n"
- "&23/11/2004 14:00-14:30 folded summary
- Status: TENTATIVE
- Class: PRIVATE
- UID: 04979712-3902-11d9-93dd-8f9f4afe08da\n"
- "&11/23/2004 14:00-14:30 folded summary
- Status: TENTATIVE
- Class: PRIVATE
- UID: 04979712-3902-11d9-93dd-8f9f4afe08da\n")
-
- (icalendar-tests--test-import
- "UID
- :6161a312-3902-11d9-b512-f764153bb28b
-SUMMARY
- :another example
-STATUS
- :TENTATIVE
-CLASS
- :PRIVATE
-X-MOZILLA-ALARM-DEFAULT-LENGTH
- :0
-DTSTART
- :20041123T144500
-DTEND
- :20041123T154500
-DTSTAMP
- :20041118T013641Z
-"
- "&2004/11/23 14:45-15:45 another example
- Status: TENTATIVE
- Class: PRIVATE
- UID: 6161a312-3902-11d9-b512-f764153bb28b\n"
- "&23/11/2004 14:45-15:45 another example
- Status: TENTATIVE
- Class: PRIVATE
- UID: 6161a312-3902-11d9-b512-f764153bb28b\n"
- "&11/23/2004 14:45-15:45 another example
- Status: TENTATIVE
- Class: PRIVATE
- UID: 6161a312-3902-11d9-b512-f764153bb28b\n"))
+ (icalendar-tests--test-import "import-non-recurring-1.ics"
+ "import-non-recurring-1.diary-iso"
+ "import-non-recurring-1.diary-european"
+ "import-non-recurring-1.diary-american")
+ (icalendar-tests--test-import "import-non-recurring-all-day.ics"
+ "import-non-recurring-all-day.diary-iso"
+ "import-non-recurring-all-day.diary-european"
+ "import-non-recurring-all-day.diary-american")
+ (icalendar-tests--test-import "import-non-recurring-long-summary.ics"
+ "import-non-recurring-long-summary.diary-iso"
+ "import-non-recurring-long-summary.diary-european"
+ "import-non-recurring-long-summary.diary-american")
+ (icalendar-tests--test-import "import-non-recurring-block.ics"
+ "import-non-recurring-block.diary-iso"
+ "import-non-recurring-block.diary-european"
+ "import-non-recurring-block.diary-american")
+ (icalendar-tests--test-import "import-non-recurring-folded-summary.ics"
+ "import-non-recurring-folded-summary.diary-iso"
+ "import-non-recurring-folded-summary.diary-european"
+ "import-non-recurring-folded-summary.diary-american")
+ (icalendar-tests--test-import "import-non-recurring-another-example.ics"
+ "import-non-recurring-another-example.diary-iso"
+ "import-non-recurring-another-example.diary-european"
+ "import-non-recurring-another-example.diary-american"))
+
(ert-deftest icalendar-import-rrule ()
- (icalendar-tests--test-import
- "SUMMARY:rrule daily
-DTSTART;VALUE=DATE-TIME:20030919T090000
-DTEND;VALUE=DATE-TIME:20030919T113000
-RRULE:FREQ=DAILY;
-"
- "&%%(and (diary-cyclic 1 2003 9 19)) 09:00-11:30 rrule daily\n"
- "&%%(and (diary-cyclic 1 19 9 2003)) 09:00-11:30 rrule daily\n"
- "&%%(and (diary-cyclic 1 9 19 2003)) 09:00-11:30 rrule daily\n")
- ;; RRULE examples
- (icalendar-tests--test-import
- "SUMMARY:rrule daily
-DTSTART;VALUE=DATE-TIME:20030919T090000
-DTEND;VALUE=DATE-TIME:20030919T113000
-RRULE:FREQ=DAILY;INTERVAL=2
-"
- "&%%(and (diary-cyclic 2 2003 9 19)) 09:00-11:30 rrule daily\n"
- "&%%(and (diary-cyclic 2 19 9 2003)) 09:00-11:30 rrule daily\n"
- "&%%(and (diary-cyclic 2 9 19 2003)) 09:00-11:30 rrule daily\n")
- (icalendar-tests--test-import
- "SUMMARY:rrule daily with exceptions
-DTSTART;VALUE=DATE-TIME:20030919T090000
-DTEND;VALUE=DATE-TIME:20030919T113000
-RRULE:FREQ=DAILY;INTERVAL=2
-EXDATE:20030921,20030925
-"
- "&%%(and (not (diary-date 2003 9 25)) (not (diary-date 2003 9 21)) (diary-cyclic 2 2003 9 19)) 09:00-11:30 rrule daily with exceptions\n"
- "&%%(and (not (diary-date 25 9 2003)) (not (diary-date 21 9 2003)) (diary-cyclic 2 19 9 2003)) 09:00-11:30 rrule daily with exceptions\n"
- "&%%(and (not (diary-date 9 25 2003)) (not (diary-date 9 21 2003)) (diary-cyclic 2 9 19 2003)) 09:00-11:30 rrule daily with exceptions\n")
- (icalendar-tests--test-import
- "SUMMARY:rrule weekly
-DTSTART;VALUE=DATE-TIME:20030919T090000
-DTEND;VALUE=DATE-TIME:20030919T113000
-RRULE:FREQ=WEEKLY;
-"
- "&%%(and (diary-cyclic 7 2003 9 19)) 09:00-11:30 rrule weekly\n"
- "&%%(and (diary-cyclic 7 19 9 2003)) 09:00-11:30 rrule weekly\n"
- "&%%(and (diary-cyclic 7 9 19 2003)) 09:00-11:30 rrule weekly\n")
- (icalendar-tests--test-import
- "SUMMARY:rrule monthly no end
-DTSTART;VALUE=DATE-TIME:20030919T090000
-DTEND;VALUE=DATE-TIME:20030919T113000
-RRULE:FREQ=MONTHLY;
-"
- "&%%(and (diary-date t t 19) (diary-block 2003 9 19 9999 1 1)) 09:00-11:30 rrule monthly no end\n"
- "&%%(and (diary-date 19 t t) (diary-block 19 9 2003 1 1 9999)) 09:00-11:30 rrule monthly no end\n"
- "&%%(and (diary-date t 19 t) (diary-block 9 19 2003 1 1 9999)) 09:00-11:30 rrule monthly no end\n")
- (icalendar-tests--test-import
- "SUMMARY:rrule monthly with end
-DTSTART;VALUE=DATE-TIME:20030919T090000
-DTEND;VALUE=DATE-TIME:20030919T113000
-RRULE:FREQ=MONTHLY;UNTIL=20050819;
-"
- "&%%(and (diary-date t t 19) (diary-block 2003 9 19 2005 8 19)) 09:00-11:30 rrule monthly with end\n"
- "&%%(and (diary-date 19 t t) (diary-block 19 9 2003 19 8 2005)) 09:00-11:30 rrule monthly with end\n"
- "&%%(and (diary-date t 19 t) (diary-block 9 19 2003 8 19 2005)) 09:00-11:30 rrule monthly with end\n")
- (icalendar-tests--test-import
- "DTSTART;VALUE=DATE:20040815
-DTEND;VALUE=DATE:20040816
-SUMMARY:Maria Himmelfahrt
-RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=8
-"
- "&%%(and (diary-anniversary 2004 8 15)) Maria Himmelfahrt\n"
- "&%%(and (diary-anniversary 15 8 2004)) Maria Himmelfahrt\n"
- "&%%(and (diary-anniversary 8 15 2004)) Maria Himmelfahrt\n")
- (icalendar-tests--test-import
- "SUMMARY:rrule yearly
-DTSTART;VALUE=DATE-TIME:20030919T090000
-DTEND;VALUE=DATE-TIME:20030919T113000
-RRULE:FREQ=YEARLY;INTERVAL=2
-"
- "&%%(and (diary-anniversary 2003 9 19)) 09:00-11:30 rrule yearly\n" ;FIXME
- "&%%(and (diary-anniversary 19 9 2003)) 09:00-11:30 rrule yearly\n" ;FIXME
- "&%%(and (diary-anniversary 9 19 2003)) 09:00-11:30 rrule yearly\n") ;FIXME
- (icalendar-tests--test-import
- "SUMMARY:rrule count daily short
-DTSTART;VALUE=DATE-TIME:20030919T090000
-DTEND;VALUE=DATE-TIME:20030919T113000
-RRULE:FREQ=DAILY;COUNT=1;INTERVAL=1
-"
- "&%%(and (diary-cyclic 1 2003 9 19) (diary-block 2003 9 19 2003 9 19)) 09:00-11:30 rrule count daily short\n"
- "&%%(and (diary-cyclic 1 19 9 2003) (diary-block 19 9 2003 19 9 2003)) 09:00-11:30 rrule count daily short\n"
- "&%%(and (diary-cyclic 1 9 19 2003) (diary-block 9 19 2003 9 19 2003)) 09:00-11:30 rrule count daily short\n")
- (icalendar-tests--test-import
- "SUMMARY:rrule count daily long
-DTSTART;VALUE=DATE-TIME:20030919T090000
-DTEND;VALUE=DATE-TIME:20030919T113000
-RRULE:FREQ=DAILY;COUNT=14;INTERVAL=1
-"
- "&%%(and (diary-cyclic 1 2003 9 19) (diary-block 2003 9 19 2003 10 2)) 09:00-11:30 rrule count daily long\n"
- "&%%(and (diary-cyclic 1 19 9 2003) (diary-block 19 9 2003 2 10 2003)) 09:00-11:30 rrule count daily long\n"
- "&%%(and (diary-cyclic 1 9 19 2003) (diary-block 9 19 2003 10 2 2003)) 09:00-11:30 rrule count daily long\n")
- (icalendar-tests--test-import
- "SUMMARY:rrule count bi-weekly 3 times
-DTSTART;VALUE=DATE-TIME:20030919T090000
-DTEND;VALUE=DATE-TIME:20030919T113000
-RRULE:FREQ=WEEKLY;COUNT=3;INTERVAL=2
-"
- "&%%(and (diary-cyclic 14 2003 9 19) (diary-block 2003 9 19 2003 10 31)) 09:00-11:30 rrule count bi-weekly 3 times\n"
- "&%%(and (diary-cyclic 14 19 9 2003) (diary-block 19 9 2003 31 10 2003)) 09:00-11:30 rrule count bi-weekly 3 times\n"
- "&%%(and (diary-cyclic 14 9 19 2003) (diary-block 9 19 2003 10 31 2003)) 09:00-11:30 rrule count bi-weekly 3 times\n")
- (icalendar-tests--test-import
- "SUMMARY:rrule count monthly
-DTSTART;VALUE=DATE-TIME:20030919T090000
-DTEND;VALUE=DATE-TIME:20030919T113000
-RRULE:FREQ=MONTHLY;INTERVAL=1;COUNT=5
-"
- "&%%(and (diary-date t t 19) (diary-block 2003 9 19 2004 1 19)) 09:00-11:30 rrule count monthly\n"
- "&%%(and (diary-date 19 t t) (diary-block 19 9 2003 19 1 2004)) 09:00-11:30 rrule count monthly\n"
- "&%%(and (diary-date t 19 t) (diary-block 9 19 2003 1 19 2004)) 09:00-11:30 rrule count monthly\n")
- (icalendar-tests--test-import
- "SUMMARY:rrule count every second month
-DTSTART;VALUE=DATE-TIME:20030919T090000
-DTEND;VALUE=DATE-TIME:20030919T113000
-RRULE:FREQ=MONTHLY;INTERVAL=2;COUNT=5
-"
- "&%%(and (diary-date t t 19) (diary-block 2003 9 19 2004 5 19)) 09:00-11:30 rrule count every second month\n" ;FIXME
- "&%%(and (diary-date 19 t t) (diary-block 19 9 2003 19 5 2004)) 09:00-11:30 rrule count every second month\n" ;FIXME
- "&%%(and (diary-date t 19 t) (diary-block 9 19 2003 5 19 2004)) 09:00-11:30 rrule count every second month\n") ;FIXME
- (icalendar-tests--test-import
- "SUMMARY:rrule count yearly
-DTSTART;VALUE=DATE-TIME:20030919T090000
-DTEND;VALUE=DATE-TIME:20030919T113000
-RRULE:FREQ=YEARLY;INTERVAL=1;COUNT=5
-"
- "&%%(and (diary-date t 9 19) (diary-block 2003 9 19 2007 9 19)) 09:00-11:30 rrule count yearly\n"
- "&%%(and (diary-date 19 9 t) (diary-block 19 9 2003 19 9 2007)) 09:00-11:30 rrule count yearly\n"
- "&%%(and (diary-date 9 19 t) (diary-block 9 19 2003 9 19 2007)) 09:00-11:30 rrule count yearly\n")
- (icalendar-tests--test-import
- "SUMMARY:rrule count every second year
-DTSTART;VALUE=DATE-TIME:20030919T090000
-DTEND;VALUE=DATE-TIME:20030919T113000
-RRULE:FREQ=YEARLY;INTERVAL=2;COUNT=5
-"
- "&%%(and (diary-date t 9 19) (diary-block 2003 9 19 2011 9 19)) 09:00-11:30 rrule count every second year\n" ;FIXME!!!
- "&%%(and (diary-date 19 9 t) (diary-block 19 9 2003 19 9 2011)) 09:00-11:30 rrule count every second year\n" ;FIXME!!!
- "&%%(and (diary-date 9 19 t) (diary-block 9 19 2003 9 19 2011)) 09:00-11:30 rrule count every second year\n") ;FIXME!!!
-)
+ (icalendar-tests--test-import "import-rrule-daily.ics"
+ "import-rrule-daily.diary-iso"
+ "import-rrule-daily.diary-european"
+ "import-rrule-daily.diary-american")
+ (icalendar-tests--test-import "import-rrule-daily-two-day.ics"
+ "import-rrule-daily-two-day.diary-iso"
+ "import-rrule-daily-two-day.diary-european"
+ "import-rrule-daily-two-day.diary-american")
+ (icalendar-tests--test-import "import-rrule-daily-with-exceptions.ics"
+ "import-rrule-daily-with-exceptions.diary-iso"
+ "import-rrule-daily-with-exceptions.diary-european"
+ "import-rrule-daily-with-exceptions.diary-american")
+ (icalendar-tests--test-import "import-rrule-weekly.ics"
+ "import-rrule-weekly.diary-iso"
+ "import-rrule-weekly.diary-european"
+ "import-rrule-weekly.diary-american")
+ (icalendar-tests--test-import "import-rrule-monthly-no-end.ics"
+ "import-rrule-monthly-no-end.diary-iso"
+ "import-rrule-monthly-no-end.diary-european"
+ "import-rrule-monthly-no-end.diary-american")
+ (icalendar-tests--test-import "import-rrule-monthly-with-end.ics"
+ "import-rrule-monthly-with-end.diary-iso"
+ "import-rrule-monthly-with-end.diary-european"
+ "import-rrule-monthly-with-end.diary-american")
+ (icalendar-tests--test-import "import-rrule-anniversary.ics"
+ "import-rrule-anniversary.diary-iso"
+ "import-rrule-anniversary.diary-european"
+ "import-rrule-anniversary.diary-american")
+ (icalendar-tests--test-import "import-rrule-yearly.ics"
+ "import-rrule-yearly.diary-iso"
+ "import-rrule-yearly.diary-european"
+ "import-rrule-yearly.diary-american")
+ (icalendar-tests--test-import "import-rrule-count-daily-short.ics"
+ "import-rrule-count-daily-short.diary-iso"
+ "import-rrule-count-daily-short.diary-european"
+ "import-rrule-count-daily-short.diary-american")
+ (icalendar-tests--test-import "import-rrule-count-daily-long.ics"
+ "import-rrule-count-daily-long.diary-iso"
+ "import-rrule-count-daily-long.diary-european"
+ "import-rrule-count-daily-long.diary-american")
+ (icalendar-tests--test-import "import-rrule-count-monthly.ics"
+ "import-rrule-count-monthly.diary-iso"
+ "import-rrule-count-monthly.diary-european"
+ "import-rrule-count-monthly.diary-american")
+ (icalendar-tests--test-import "import-rrule-count-every-second-month.ics"
+ "import-rrule-count-every-second-month.diary-iso"
+ "import-rrule-count-every-second-month.diary-european"
+ "import-rrule-count-every-second-month.diary-american")
+ (icalendar-tests--test-import "import-rrule-count-yearly.ics"
+ "import-rrule-count-yearly.diary-iso"
+ "import-rrule-count-yearly.diary-european"
+ "import-rrule-count-yearly.diary-american")
+ (icalendar-tests--test-import "import-rrule-count-every-second-year.ics"
+ "import-rrule-count-every-second-year.diary-iso"
+ "import-rrule-count-every-second-year.diary-european"
+ "import-rrule-count-every-second-year.diary-american")
+ )
(ert-deftest icalendar-import-duration ()
- ;; duration
- (icalendar-tests--test-import
- "DTSTART;VALUE=DATE:20050217
-SUMMARY:duration
-DURATION:P7D
-"
- "&%%(and (diary-block 2005 2 17 2005 2 23)) duration\n"
- "&%%(and (diary-block 17 2 2005 23 2 2005)) duration\n"
- "&%%(and (diary-block 2 17 2005 2 23 2005)) duration\n")
- (icalendar-tests--test-import
- "UID:20041127T183329Z-18215-1001-4536-49109@andromeda
-DTSTAMP:20041127T183315Z
-LAST-MODIFIED:20041127T183329
-SUMMARY:Urlaub
-DTSTART;VALUE=DATE:20011221
-DTEND;VALUE=DATE:20011221
-RRULE:FREQ=DAILY;UNTIL=20011229;INTERVAL=1;WKST=SU
-CLASS:PUBLIC
-SEQUENCE:1
-CREATED:20041127T183329
-"
- "&%%(and (diary-cyclic 1 2001 12 21) (diary-block 2001 12 21 2001 12 29)) Urlaub
- Class: PUBLIC
- UID: 20041127T183329Z-18215-1001-4536-49109@andromeda\n"
- "&%%(and (diary-cyclic 1 21 12 2001) (diary-block 21 12 2001 29 12 2001)) Urlaub
- Class: PUBLIC
- UID: 20041127T183329Z-18215-1001-4536-49109@andromeda\n"
- "&%%(and (diary-cyclic 1 12 21 2001) (diary-block 12 21 2001 12 29 2001)) Urlaub
- Class: PUBLIC
- UID: 20041127T183329Z-18215-1001-4536-49109@andromeda\n"))
+ (icalendar-tests--test-import "import-duration.ics"
+ "import-duration.diary-iso"
+ "import-duration.diary-european"
+ "import-duration.diary-american")
+ ;; duration-2: this is actually an rrule test
+ (icalendar-tests--test-import "import-duration-2.ics"
+ "import-duration-2.diary-iso"
+ "import-duration-2.diary-european"
+ "import-duration-2.diary-american"))
(ert-deftest icalendar-import-bug-6766 ()
;;bug#6766 -- multiple byday values in a weekly rrule
- (icalendar-tests--test-import
-"CLASS:PUBLIC
-DTEND;TZID=America/New_York:20100421T120000
-DTSTAMP:20100525T141214Z
-DTSTART;TZID=America/New_York:20100421T113000
-RRULE:FREQ=WEEKLY;INTERVAL=1;BYDAY=MO,WE,TH,FR
-SEQUENCE:1
-STATUS:CONFIRMED
-SUMMARY:Scrum
-TRANSP:OPAQUE
-UID:8814e3f9-7482-408f-996c-3bfe486a1262
-END:VEVENT
-BEGIN:VEVENT
-CLASS:PUBLIC
-DTSTAMP:20100525T141214Z
-DTSTART;VALUE=DATE:20100422
-DTEND;VALUE=DATE:20100423
-RRULE:FREQ=WEEKLY;INTERVAL=1;BYDAY=TU,TH
-SEQUENCE:1
-SUMMARY:Tues + Thurs thinking
-TRANSP:OPAQUE
-UID:8814e3f9-7482-408f-996c-3bfe486a1263
-"
-"&%%(and (memq (calendar-day-of-week date) '(1 3 4 5)) (diary-cyclic 1 2010 4 21)) 11:30-12:00 Scrum
- Status: CONFIRMED
- Class: PUBLIC
- UID: 8814e3f9-7482-408f-996c-3bfe486a1262
-&%%(and (memq (calendar-day-of-week date) '(2 4)) (diary-cyclic 1 2010 4 22)) Tues + Thurs thinking
- Class: PUBLIC
- UID: 8814e3f9-7482-408f-996c-3bfe486a1263
-"
-"&%%(and (memq (calendar-day-of-week date) '(1 3 4 5)) (diary-cyclic 1 21 4 2010)) 11:30-12:00 Scrum
- Status: CONFIRMED
- Class: PUBLIC
- UID: 8814e3f9-7482-408f-996c-3bfe486a1262
-&%%(and (memq (calendar-day-of-week date) '(2 4)) (diary-cyclic 1 22 4 2010)) Tues + Thurs thinking
- Class: PUBLIC
- UID: 8814e3f9-7482-408f-996c-3bfe486a1263
-"
-"&%%(and (memq (calendar-day-of-week date) '(1 3 4 5)) (diary-cyclic 1 4 21 2010)) 11:30-12:00 Scrum
- Status: CONFIRMED
- Class: PUBLIC
- UID: 8814e3f9-7482-408f-996c-3bfe486a1262
-&%%(and (memq (calendar-day-of-week date) '(2 4)) (diary-cyclic 1 4 22 2010)) Tues + Thurs thinking
- Class: PUBLIC
- UID: 8814e3f9-7482-408f-996c-3bfe486a1263
-"))
+ (icalendar-tests--test-import "import-bug-6766.ics"
+ "import-bug-6766.diary-iso"
+ "import-bug-6766.diary-european"
+ "import-bug-6766.diary-american"))
(ert-deftest icalendar-import-bug-24199 ()
;;bug#24199 -- monthly rule with byday-clause
- (icalendar-tests--test-import
-"
-SUMMARY:Summary
-DESCRIPTION:Desc
-LOCATION:Loc
-DTSTART:20151202T124600
-DTEND:20151202T160000
-RRULE:FREQ=MONTHLY;BYDAY=1WE;INTERVAL=1
-EXDATE:20160106T114600Z
-EXDATE:20160203T114600Z
-EXDATE:20160302T114600Z
-EXDATE:20160504T104600Z
-EXDATE:20160601T104600Z
-CLASS:DEFAULT
-TRANSP:OPAQUE
-BEGIN:VALARM
-ACTION:DISPLAY
-TRIGGER;VALUE=DURATION:-PT3H
-END:VALARM
-LAST-MODIFIED:20160805T191040Z
-UID:9188710a-08a7-4061-bae3-d4cf4972599a
-"
-"&%%(and (not (diary-date 2016 1 6)) (not (diary-date 2016 2 3)) (not (diary-date 2016 3 2)) (not (diary-date 2016 5 4)) (not (diary-date 2016 6 1)) (diary-float t 3 1) (diary-block 2015 12 2 9999 1 1)) 12:46-16:00 Summary
- Desc: Desc
- Location: Loc
- Class: DEFAULT
- UID: 9188710a-08a7-4061-bae3-d4cf4972599a
-"
-"&%%(and (not (diary-date 6 1 2016)) (not (diary-date 3 2 2016)) (not (diary-date 2 3 2016)) (not (diary-date 4 5 2016)) (not (diary-date 1 6 2016)) (diary-float t 3 1) (diary-block 2 12 2015 1 1 9999)) 12:46-16:00 Summary
- Desc: Desc
- Location: Loc
- Class: DEFAULT
- UID: 9188710a-08a7-4061-bae3-d4cf4972599a
-"
-"&%%(and (not (diary-date 1 6 2016)) (not (diary-date 2 3 2016)) (not (diary-date 3 2 2016)) (not (diary-date 5 4 2016)) (not (diary-date 6 1 2016)) (diary-float t 3 1) (diary-block 12 2 2015 1 1 9999)) 12:46-16:00 Summary
- Desc: Desc
- Location: Loc
- Class: DEFAULT
- UID: 9188710a-08a7-4061-bae3-d4cf4972599a
-"
-))
+ (icalendar-tests--test-import "import-bug-24199.ics"
+ "import-bug-24199.diary-iso"
+ "import-bug-24199.diary-european"
+ "import-bug-24199.diary-american"))
+
+(ert-deftest icalendar-import-bug-33277 ()
+ ;;bug#33277 -- start time equals end time
+ (icalendar-tests--test-import "import-bug-33277.ics"
+ "import-bug-33277.diary-iso"
+ "import-bug-33277.diary-european"
+ "import-bug-33277.diary-american"))
(ert-deftest icalendar-import-multiple-vcalendars ()
- (icalendar-tests--test-import
- "DTSTART;VALUE=DATE:20110723
-SUMMARY:event-1
-"
- "&2011/7/23 event-1\n"
- "&23/7/2011 event-1\n"
- "&7/23/2011 event-1\n")
-
- (icalendar-tests--test-import
- "BEGIN:VCALENDAR
-PRODID:-//Emacs//NONSGML icalendar.el//EN
-VERSION:2.0\nBEGIN:VEVENT
-DTSTART;VALUE=DATE:20110723
-SUMMARY:event-1
-END:VEVENT
-END:VCALENDAR
-BEGIN:VCALENDAR
-PRODID:-//Emacs//NONSGML icalendar.el//EN
-VERSION:2.0
-BEGIN:VEVENT
-DTSTART;VALUE=DATE:20110724
-SUMMARY:event-2
-END:VEVENT
-END:VCALENDAR
-BEGIN:VCALENDAR
-PRODID:-//Emacs//NONSGML icalendar.el//EN
-VERSION:2.0
-BEGIN:VEVENT
-DTSTART;VALUE=DATE:20110725
-SUMMARY:event-3a
-END:VEVENT
-BEGIN:VEVENT
-DTSTART;VALUE=DATE:20110725
-SUMMARY:event-3b
-END:VEVENT
-END:VCALENDAR
-"
- "&2011/7/23 event-1\n&2011/7/24 event-2\n&2011/7/25 event-3a\n&2011/7/25 event-3b\n"
- "&23/7/2011 event-1\n&24/7/2011 event-2\n&25/7/2011 event-3a\n&25/7/2011 event-3b\n"
- "&7/23/2011 event-1\n&7/24/2011 event-2\n&7/25/2011 event-3a\n&7/25/2011 event-3b\n"))
+ (icalendar-tests--test-import "import-multiple-vcalendars.ics"
+ "import-multiple-vcalendars.diary-iso"
+ "import-multiple-vcalendars.diary-european"
+ "import-multiple-vcalendars.diary-american"))
(ert-deftest icalendar-import-with-uid ()
"Perform import test with uid."
- (icalendar-tests--test-import
- "UID:1234567890uid
-SUMMARY:non-recurring
-DTSTART;VALUE=DATE-TIME:20030919T090000
-DTEND;VALUE=DATE-TIME:20030919T113000"
- "&2003/9/19 09:00-11:30 non-recurring\n UID: 1234567890uid\n"
- "&19/9/2003 09:00-11:30 non-recurring\n UID: 1234567890uid\n"
- "&9/19/2003 09:00-11:30 non-recurring\n UID: 1234567890uid\n"))
+ (icalendar-tests--test-import "import-with-uid.ics"
+ "import-with-uid.diary-iso"
+ "import-with-uid.diary-european"
+ "import-with-uid.diary-american"))
(ert-deftest icalendar-import-with-timezone ()
;; This is known to fail on MS-Windows, because the test assumes
@@ -1361,42 +1203,13 @@ DTEND;VALUE=DATE-TIME:20030919T113000"
:failed
:passed)
;; bug#11473
- (icalendar-tests--test-import
- "BEGIN:VCALENDAR
-BEGIN:VTIMEZONE
-TZID:fictional, nonexistent, arbitrary
-BEGIN:STANDARD
-DTSTART:20100101T000000
-TZOFFSETFROM:+0200
-TZOFFSETTO:-0200
-RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=1SU;BYMONTH=01
-END:STANDARD
-BEGIN:DAYLIGHT
-DTSTART:20101201T000000
-TZOFFSETFROM:-0200
-TZOFFSETTO:+0200
-RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=1SU;BYMONTH=11
-END:DAYLIGHT
-END:VTIMEZONE
-BEGIN:VEVENT
-SUMMARY:standardtime
-DTSTART;TZID=\"fictional, nonexistent, arbitrary\":20120115T120000
-DTEND;TZID=\"fictional, nonexistent, arbitrary\":20120115T123000
-END:VEVENT
-BEGIN:VEVENT
-SUMMARY:daylightsavingtime
-DTSTART;TZID=\"fictional, nonexistent, arbitrary\":20121215T120000
-DTEND;TZID=\"fictional, nonexistent, arbitrary\":20121215T123000
-END:VEVENT
-END:VCALENDAR"
- ;; "standardtime" begins first sunday in january and is 4 hours behind CET
- ;; "daylightsavingtime" begins first sunday in november and is 1 hour before CET
- "&2012/1/15 15:00-15:30 standardtime
-&2012/12/15 11:00-11:30 daylightsavingtime
-"
- nil
- nil)
- )
+ ;; "standardtime" begins first sunday in january and is 4 hours behind CET
+ ;; "daylightsavingtime" begins first sunday in november and is 1 hour before CET
+ (icalendar-tests--test-import "import-with-timezone.ics"
+ "import-with-timezone.diary-iso"
+ nil
+ nil))
+
;; ======================================================================
;; Cycle
;; ======================================================================
@@ -1427,35 +1240,33 @@ Argument INPUT icalendar event string."
(defun icalendar-tests--do-test-cycle ()
"Actually perform import/export cycle test."
- (let ((temp-diary (make-temp-file "icalendar-test-diary"))
- (temp-ics (make-temp-file "icalendar-test-ics"))
- (org-input (buffer-substring-no-properties (point-min) (point-max))))
-
- (unwind-protect
- (progn
- ;; step 1: import
- (icalendar-import-buffer temp-diary t t)
-
- ;; step 2: export what was just imported
- (save-excursion
- (find-file temp-diary)
- (icalendar-export-region (point-min) (point-max) temp-ics))
-
- ;; compare the output of step 2 with the input of step 1
- (save-excursion
- (find-file temp-ics)
- (goto-char (point-min))
- ;;(when (re-search-forward "\nUID:.*\n" nil t)
- ;;(replace-match "\n"))
- (let ((cycled (buffer-substring-no-properties (point-min) (point-max))))
- (should (string= org-input cycled)))))
- ;; clean up
- (kill-buffer (find-buffer-visiting temp-diary))
- (with-current-buffer (find-buffer-visiting temp-ics)
- (set-buffer-modified-p nil)
- (kill-buffer (current-buffer)))
- (delete-file temp-diary)
- (delete-file temp-ics))))
+ (ert-with-temp-file temp-diary
+ (ert-with-temp-file temp-ics
+ (let ((org-input (buffer-substring-no-properties (point-min) (point-max))))
+
+ (unwind-protect
+ (progn
+ ;; step 1: import
+ (icalendar-import-buffer temp-diary t t)
+
+ ;; step 2: export what was just imported
+ (save-excursion
+ (find-file temp-diary)
+ (icalendar-export-region (point-min) (point-max) temp-ics))
+
+ ;; compare the output of step 2 with the input of step 1
+ (save-excursion
+ (find-file temp-ics)
+ (goto-char (point-min))
+ ;;(when (re-search-forward "\nUID:.*\n" nil t)
+ ;;(replace-match "\n"))
+ (let ((cycled (buffer-substring-no-properties (point-min) (point-max))))
+ (should (string= org-input cycled)))))
+ ;; clean up
+ (kill-buffer (find-buffer-visiting temp-diary))
+ (with-current-buffer (find-buffer-visiting temp-ics)
+ (set-buffer-modified-p nil)
+ (kill-buffer (current-buffer))))))))
(ert-deftest icalendar-cycle ()
"Perform cycling tests.
@@ -1475,8 +1286,8 @@ DESCRIPTION:beschreibung!
LOCATION:nowhere
ORGANIZER:ulf
")
- (icalendar-tests--test-cycle
- "UID:4711
+ (icalendar-tests--test-cycle
+ "UID:4711
DTSTART;VALUE=DATE:19190909
DTEND;VALUE=DATE:19190910
RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=09;BYMONTHDAY=09
@@ -1494,237 +1305,27 @@ SUMMARY:and diary-anniversary
:failed
:passed)
;; 2003-05-29
- (icalendar-tests--test-import
- "BEGIN:VCALENDAR
-METHOD:REQUEST
-PRODID:Microsoft CDO for Microsoft Exchange
-VERSION:2.0
-BEGIN:VTIMEZONE
-TZID:Kolkata, Chennai, Mumbai, New Delhi
-X-MICROSOFT-CDO-TZID:23
-BEGIN:STANDARD
-DTSTART:16010101T000000
-TZOFFSETFROM:+0530
-TZOFFSETTO:+0530
-END:STANDARD
-BEGIN:DAYLIGHT
-DTSTART:16010101T000000
-TZOFFSETFROM:+0530
-TZOFFSETTO:+0530
-END:DAYLIGHT
-END:VTIMEZONE
-BEGIN:VEVENT
-DTSTAMP:20030509T043439Z
-DTSTART;TZID=\"Kolkata, Chennai, Mumbai, New Delhi\":20030509T103000
-SUMMARY:On-Site Interview
-UID:040000008200E00074C5B7101A82E0080000000080B6DE661216C301000000000000000
- 010000000DB823520692542408ED02D7023F9DFF9
-ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN=\"Xxxxx
- xxx Xxxxxxxxxxxx\":MAILTO:xxxxxxxx@xxxxxxx.com
-ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN=\"Yyyyyyy Y
- yyyy\":MAILTO:yyyyyyy@yyyyyyy.com
-ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN=\"Zzzz Zzzz
- zz\":MAILTO:zzzzzz@zzzzzzz.com
-ORGANIZER;CN=\"Aaaaaa Aaaaa\":MAILTO:aaaaaaa@aaaaaaa.com
-LOCATION:Cccc
-DTEND;TZID=\"Kolkata, Chennai, Mumbai, New Delhi\":20030509T153000
-DESCRIPTION:10:30am - Blah
-SEQUENCE:0
-PRIORITY:5
-CLASS:
-CREATED:20030509T043439Z
-LAST-MODIFIED:20030509T043459Z
-STATUS:CONFIRMED
-TRANSP:OPAQUE
-X-MICROSOFT-CDO-BUSYSTATUS:BUSY
-X-MICROSOFT-CDO-INSTTYPE:0
-X-MICROSOFT-CDO-INTENDEDSTATUS:BUSY
-X-MICROSOFT-CDO-ALLDAYEVENT:FALSE
-X-MICROSOFT-CDO-IMPORTANCE:1
-X-MICROSOFT-CDO-OWNERAPPTID:126441427
-BEGIN:VALARM
-ACTION:DISPLAY
-DESCRIPTION:REMINDER
-TRIGGER;RELATED=START:-PT00H15M00S
-END:VALARM
-END:VEVENT
-END:VCALENDAR"
- nil
- "&9/5/2003 07:00-12:00 On-Site Interview
- Desc: 10:30am - Blah
- Location: Cccc
- Organizer: MAILTO:aaaaaaa@aaaaaaa.com
- Status: CONFIRMED
- UID: 040000008200E00074C5B7101A82E0080000000080B6DE661216C301000000000000000010000000DB823520692542408ED02D7023F9DFF9
-"
- "&5/9/2003 07:00-12:00 On-Site Interview
- Desc: 10:30am - Blah
- Location: Cccc
- Organizer: MAILTO:aaaaaaa@aaaaaaa.com
- Status: CONFIRMED
- UID: 040000008200E00074C5B7101A82E0080000000080B6DE661216C301000000000000000010000000DB823520692542408ED02D7023F9DFF9
-")
+ (icalendar-tests--test-import "import-real-world-2003-05-29.ics"
+ nil
+ "import-real-world-2003-05-29.diary-european"
+ "import-real-world-2003-05-29.diary-american")
;; created with http://apps.marudot.com/ical/
- (icalendar-tests--test-import
- "BEGIN:VCALENDAR
-VERSION:2.0
-PRODID:-//www.marudot.com//iCal Event Maker
-X-WR-CALNAME:Test
-CALSCALE:GREGORIAN
-BEGIN:VTIMEZONE
-TZID:Asia/Tehran
-TZURL:http://tzurl.org/zoneinfo-outlook/Asia/Tehran
-X-LIC-LOCATION:Asia/Tehran
-BEGIN:STANDARD
-TZOFFSETFROM:+0330
-TZOFFSETTO:+0330
-TZNAME:IRST
-DTSTART:19700101T000000
-END:STANDARD
-END:VTIMEZONE
-BEGIN:VEVENT
-DTSTAMP:20141116T171439Z
-UID:20141116T171439Z-678877132@marudot.com
-DTSTART;TZID=\"Asia/Tehran\":20141116T070000
-DTEND;TZID=\"Asia/Tehran\":20141116T080000
-SUMMARY:NoDST
-DESCRIPTION:Test event from timezone without DST
-LOCATION:Everywhere
-END:VEVENT
-END:VCALENDAR"
- nil
- "&16/11/2014 04:30-05:30 NoDST
- Desc: Test event from timezone without DST
- Location: Everywhere
- UID: 20141116T171439Z-678877132@marudot.com
-"
- "&11/16/2014 04:30-05:30 NoDST
- Desc: Test event from timezone without DST
- Location: Everywhere
- UID: 20141116T171439Z-678877132@marudot.com
-")
-
+ (icalendar-tests--test-import "import-real-world-no-dst.ics"
+ nil
+ "import-real-world-no-dst.diary-european"
+ "import-real-world-no-dst.diary-american")
;; 2003-06-18 a
- (icalendar-tests--test-import
- "DTSTAMP:20030618T195512Z
-DTSTART;TZID=\"Mountain Time (US & Canada)\":20030623T110000
-SUMMARY:Dress Rehearsal for XXXX-XXXX
-UID:040000008200E00074C5B7101A82E00800000000608AA7DA9835C301000000000000000
- 0100000007C3A6D65EE726E40B7F3D69A23BD567E
-ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN=\"AAAAA,AAA
- AA (A-AAAAAAA,ex1)\":MAILTO:aaaaa_aaaaa@aaaaa.com
-ORGANIZER;CN=\"ABCD,TECHTRAINING
- (A-Americas,exgen1)\":MAILTO:xxx@xxxxx.com
-LOCATION:555 or TN 555-5555 ID 5555 & NochWas (see below)
-DTEND;TZID=\"Mountain Time (US & Canada)\":20030623T120000
-DESCRIPTION:753 Zeichen hier radiert
-SEQUENCE:0
-PRIORITY:5
-CLASS:
-CREATED:20030618T195518Z
-LAST-MODIFIED:20030618T195527Z
-STATUS:CONFIRMED
-TRANSP:OPAQUE
-X-MICROSOFT-CDO-BUSYSTATUS:BUSY
-X-MICROSOFT-CDO-INSTTYPE:0
-X-MICROSOFT-CDO-INTENDEDSTATUS:BUSY
-X-MICROSOFT-CDO-ALLDAYEVENT:FALSE
-X-MICROSOFT-CDO-IMPORTANCE:1
-X-MICROSOFT-CDO-OWNERAPPTID:1022519251
-BEGIN:VALARM
-ACTION:DISPLAY
-DESCRIPTION:REMINDER
-TRIGGER;RELATED=START:-PT00H15M00S
-END:VALARM"
- nil
- "&23/6/2003 11:00-12:00 Dress Rehearsal for XXXX-XXXX
- Desc: 753 Zeichen hier radiert
- Location: 555 or TN 555-5555 ID 5555 & NochWas (see below)
- Organizer: MAILTO:xxx@xxxxx.com
- Status: CONFIRMED
- UID: 040000008200E00074C5B7101A82E00800000000608AA7DA9835C3010000000000000000100000007C3A6D65EE726E40B7F3D69A23BD567E
-"
- "&6/23/2003 11:00-12:00 Dress Rehearsal for XXXX-XXXX
- Desc: 753 Zeichen hier radiert
- Location: 555 or TN 555-5555 ID 5555 & NochWas (see below)
- Organizer: MAILTO:xxx@xxxxx.com
- Status: CONFIRMED
- UID: 040000008200E00074C5B7101A82E00800000000608AA7DA9835C3010000000000000000100000007C3A6D65EE726E40B7F3D69A23BD567E
-")
+ (icalendar-tests--test-import "import-real-world-2003-06-18a.ics"
+ nil
+ "import-real-world-2003-06-18a.diary-european"
+ "import-real-world-2003-06-18a.diary-american")
;; 2003-06-18 b -- uses timezone
- (icalendar-tests--test-import
- "BEGIN:VCALENDAR
-METHOD:REQUEST
-PRODID:Microsoft CDO for Microsoft Exchange
-VERSION:2.0
-BEGIN:VTIMEZONE
-TZID:Mountain Time (US & Canada)
-X-MICROSOFT-CDO-TZID:12
-BEGIN:STANDARD
-DTSTART:16010101T020000
-TZOFFSETFROM:-0600
-TZOFFSETTO:-0700
-RRULE:FREQ=YEARLY;WKST=MO;INTERVAL=1;BYMONTH=10;BYDAY=-1SU
-END:STANDARD
-BEGIN:DAYLIGHT
-DTSTART:16010101T020000
-TZOFFSETFROM:-0700
-TZOFFSETTO:-0600
-RRULE:FREQ=YEARLY;WKST=MO;INTERVAL=1;BYMONTH=4;BYDAY=1SU
-END:DAYLIGHT
-END:VTIMEZONE
-BEGIN:VEVENT
-DTSTAMP:20030618T230323Z
-DTSTART;TZID=\"Mountain Time (US & Canada)\":20030623T090000
-SUMMARY:Updated: Dress Rehearsal for ABC01-15
-UID:040000008200E00074C5B7101A82E00800000000608AA7DA9835C301000000000000000
- 0100000007C3A6D65EE726E40B7F3D69A23BD567E
-ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;X-REPLYTIME=20030618T20
- 0700Z;RSVP=TRUE;CN=\"AAAAA,AAAAAA
-\(A-AAAAAAA,ex1)\":MAILTO:aaaaaa_aaaaa@aaaaa
- .com
-ORGANIZER;CN=\"ABCD,TECHTRAINING
-\(A-Americas,exgen1)\":MAILTO:bbb@bbbbb.com
-LOCATION:123 or TN 123-1234 ID abcd & SonstWo (see below)
-DTEND;TZID=\"Mountain Time (US & Canada)\":20030623T100000
-DESCRIPTION:Viele Zeichen standen hier früher
-SEQUENCE:0
-PRIORITY:5
-CLASS:
-CREATED:20030618T230326Z
-LAST-MODIFIED:20030618T230335Z
-STATUS:CONFIRMED
-TRANSP:OPAQUE
-X-MICROSOFT-CDO-BUSYSTATUS:BUSY
-X-MICROSOFT-CDO-INSTTYPE:0
-X-MICROSOFT-CDO-INTENDEDSTATUS:BUSY
-X-MICROSOFT-CDO-ALLDAYEVENT:FALSE
-X-MICROSOFT-CDO-IMPORTANCE:1
-X-MICROSOFT-CDO-OWNERAPPTID:1022519251
-BEGIN:VALARM
-ACTION:DISPLAY
-DESCRIPTION:REMINDER
-TRIGGER;RELATED=START:-PT00H15M00S
-END:VALARM
-END:VEVENT
-END:VCALENDAR"
- nil
- "&23/6/2003 17:00-18:00 Updated: Dress Rehearsal for ABC01-15
- Desc: Viele Zeichen standen hier früher
- Location: 123 or TN 123-1234 ID abcd & SonstWo (see below)
- Organizer: MAILTO:bbb@bbbbb.com
- Status: CONFIRMED
- UID: 040000008200E00074C5B7101A82E00800000000608AA7DA9835C3010000000000000000100000007C3A6D65EE726E40B7F3D69A23BD567E
-"
- "&6/23/2003 17:00-18:00 Updated: Dress Rehearsal for ABC01-15
- Desc: Viele Zeichen standen hier früher
- Location: 123 or TN 123-1234 ID abcd & SonstWo (see below)
- Organizer: MAILTO:bbb@bbbbb.com
- Status: CONFIRMED
- UID: 040000008200E00074C5B7101A82E00800000000608AA7DA9835C3010000000000000000100000007C3A6D65EE726E40B7F3D69A23BD567E
-")
+ (icalendar-tests--test-import "import-real-world-2003-06-18b.ics"
+ nil
+ "import-real-world-2003-06-18b.diary-european"
+ "import-real-world-2003-06-18b.diary-american")
;; export 2004-10-28 block entries
(icalendar-tests--test-export
nil
@@ -1786,7 +1387,7 @@ SUMMARY:ff")
"
>>> anniversaries:
-%%(diary-anniversary 3 28 1991) aa birthday (%d years old)"
+%%(diary-anniversary 3 28 1990) aa birthday (%d years old)"
"DTSTART;VALUE=DATE:19910328
DTEND;VALUE=DATE:19910329
RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=03;BYMONTHDAY=28
@@ -1796,7 +1397,7 @@ SUMMARY:aa birthday (%d years old)
(icalendar-tests--test-export
nil
nil
- "%%(diary-anniversary 5 17 1957) bb birthday (%d years old)"
+ "%%(diary-anniversary 5 17 1956) bb birthday (%d years old)"
"DTSTART;VALUE=DATE:19570517
DTEND;VALUE=DATE:19570518
RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=05;BYMONTHDAY=17
@@ -1805,7 +1406,7 @@ SUMMARY:bb birthday (%d years old)")
(icalendar-tests--test-export
nil
nil
- "%%(diary-anniversary 6 8 1997) cc birthday (%d years old)"
+ "%%(diary-anniversary 6 8 1996) cc birthday (%d years old)"
"DTSTART;VALUE=DATE:19970608
DTEND;VALUE=DATE:19970609
RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=06;BYMONTHDAY=08
@@ -1814,7 +1415,7 @@ SUMMARY:cc birthday (%d years old)")
(icalendar-tests--test-export
nil
nil
- "%%(diary-anniversary 7 22 1983) dd (%d years ago...!)"
+ "%%(diary-anniversary 7 22 1982) dd (%d years ago...!)"
"DTSTART;VALUE=DATE:19830722
DTEND;VALUE=DATE:19830723
RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=07;BYMONTHDAY=22
@@ -1823,7 +1424,7 @@ SUMMARY:dd (%d years ago...!)")
(icalendar-tests--test-export
nil
nil
- "%%(diary-anniversary 8 1 1988) ee birthday (%d years old)"
+ "%%(diary-anniversary 8 1 1987) ee birthday (%d years old)"
"DTSTART;VALUE=DATE:19880801
DTEND;VALUE=DATE:19880802
RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=08;BYMONTHDAY=01
@@ -1832,13 +1433,20 @@ SUMMARY:ee birthday (%d years old)")
(icalendar-tests--test-export
nil
nil
- "%%(diary-anniversary 9 21 1957) ff birthday (%d years old)"
+ "%%(diary-anniversary 9 21 1956) ff birthday (%d years old)"
"DTSTART;VALUE=DATE:19570921
DTEND;VALUE=DATE:19570922
RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=09;BYMONTHDAY=21
SUMMARY:ff birthday (%d years old)")
+ (icalendar-tests--test-export
+ nil
+ nil
+ "%%(diary-offset '(diary-float t 3 4) 1) asdf"
+ nil)
+
+
;; FIXME!
;; export 2004-10-28 monthly, weekly entries
@@ -1940,169 +1548,10 @@ DTEND;VALUE=DATE-TIME:20041012T150000
SUMMARY:Tue: [2004-10-12] q1")
;; 2004-11-19
- (icalendar-tests--test-import
- "BEGIN:VCALENDAR
-VERSION
- :2.0
-PRODID
- :-//Mozilla.org/NONSGML Mozilla Calendar V1.0//EN
-BEGIN:VEVENT
-SUMMARY
- :Jjjjj & Wwwww
-STATUS
- :TENTATIVE
-CLASS
- :PRIVATE
-X-MOZILLA-ALARM-DEFAULT-LENGTH
- :0
-DTSTART
- :20041123T140000
-DTEND
- :20041123T143000
-DTSTAMP
- :20041118T013430Z
-LAST-MODIFIED
- :20041118T013640Z
-END:VEVENT
-BEGIN:VEVENT
-SUMMARY
- :BB Aaaaaaaa Bbbbb
-STATUS
- :TENTATIVE
-CLASS
- :PRIVATE
-X-MOZILLA-ALARM-DEFAULT-LENGTH
- :0
-DTSTART
- :20041123T144500
-DTEND
- :20041123T154500
-DTSTAMP
- :20041118T013641Z
-END:VEVENT
-BEGIN:VEVENT
-SUMMARY
- :Hhhhhhhh
-STATUS
- :TENTATIVE
-CLASS
- :PRIVATE
-X-MOZILLA-ALARM-DEFAULT-LENGTH
- :0
-DTSTART
- :20041123T110000
-DTEND
- :20041123T120000
-DTSTAMP
- :20041118T013831Z
-END:VEVENT
-BEGIN:VEVENT
-SUMMARY
- :MMM Aaaaaaaaa
-STATUS
- :TENTATIVE
-CLASS
- :PRIVATE
-X-MOZILLA-ALARM-DEFAULT-LENGTH
- :0
-X-MOZILLA-RECUR-DEFAULT-INTERVAL
- :2
-RRULE
- :FREQ=WEEKLY;INTERVAL=2;BYDAY=FR
-DTSTART
- :20041112T140000
-DTEND
- :20041112T183000
-DTSTAMP
- :20041118T014117Z
-END:VEVENT
-BEGIN:VEVENT
-SUMMARY
- :Rrrr/Cccccc ii Aaaaaaaa
-DESCRIPTION
- :Vvvvv Rrrr aaa Cccccc
-STATUS
- :TENTATIVE
-CLASS
- :PRIVATE
-X-MOZILLA-ALARM-DEFAULT-LENGTH
- :0
-DTSTART
- ;VALUE=DATE
- :20041119
-DTEND
- ;VALUE=DATE
- :20041120
-DTSTAMP
- :20041118T013107Z
-LAST-MODIFIED
- :20041118T014203Z
-END:VEVENT
-BEGIN:VEVENT
-SUMMARY
- :Wwww aa hhhh
-STATUS
- :TENTATIVE
-CLASS
- :PRIVATE
-X-MOZILLA-ALARM-DEFAULT-LENGTH
- :0
-RRULE
- :FREQ=WEEKLY;INTERVAL=1;BYDAY=MO
-DTSTART
- ;VALUE=DATE
- :20041101
-DTEND
- ;VALUE=DATE
- :20041102
-DTSTAMP
- :20041118T014045Z
-LAST-MODIFIED
- :20041118T023846Z
-END:VEVENT
-END:VCALENDAR
-"
- nil
- "&23/11/2004 14:00-14:30 Jjjjj & Wwwww
- Status: TENTATIVE
- Class: PRIVATE
-&23/11/2004 14:45-15:45 BB Aaaaaaaa Bbbbb
- Status: TENTATIVE
- Class: PRIVATE
-&23/11/2004 11:00-12:00 Hhhhhhhh
- Status: TENTATIVE
- Class: PRIVATE
-&%%(and (diary-cyclic 14 12 11 2004)) 14:00-18:30 MMM Aaaaaaaaa
- Status: TENTATIVE
- Class: PRIVATE
-&%%(and (diary-block 19 11 2004 19 11 2004)) Rrrr/Cccccc ii Aaaaaaaa
- Desc: Vvvvv Rrrr aaa Cccccc
- Status: TENTATIVE
- Class: PRIVATE
-&%%(and (diary-cyclic 7 1 11 2004)) Wwww aa hhhh
- Status: TENTATIVE
- Class: PRIVATE
-"
- "&11/23/2004 14:00-14:30 Jjjjj & Wwwww
- Status: TENTATIVE
- Class: PRIVATE
-&11/23/2004 14:45-15:45 BB Aaaaaaaa Bbbbb
- Status: TENTATIVE
- Class: PRIVATE
-&11/23/2004 11:00-12:00 Hhhhhhhh
- Status: TENTATIVE
- Class: PRIVATE
-&%%(and (diary-cyclic 14 11 12 2004)) 14:00-18:30 MMM Aaaaaaaaa
- Status: TENTATIVE
- Class: PRIVATE
-&%%(and (diary-block 11 19 2004 11 19 2004)) Rrrr/Cccccc ii Aaaaaaaa
- Desc: Vvvvv Rrrr aaa Cccccc
- Status: TENTATIVE
- Class: PRIVATE
-&%%(and (diary-cyclic 7 11 1 2004)) Wwww aa hhhh
- Status: TENTATIVE
- Class: PRIVATE
-")
+ (icalendar-tests--test-import "import-real-world-2004-11-19.ics"
+ nil
+ "import-real-world-2004-11-19.diary-european"
+ "import-real-world-2004-11-19.diary-american")
;; 2004-09-09 pg
(icalendar-tests--test-export
@@ -2132,53 +1581,16 @@ DTEND;VALUE=DATE-TIME:20041102T163000
SUMMARY:Zahnarzt")
;; 2005-02-07 lt
- (icalendar-tests--test-import
- "UID
- :b60d398e-1dd1-11b2-a159-cf8cb05139f4
-SUMMARY
- :Waitangi Day
-DESCRIPTION
- :abcdef
-CATEGORIES
- :Public Holiday
-STATUS
- :CONFIRMED
-CLASS
- :PRIVATE
-DTSTART
- ;VALUE=DATE
- :20050206
-DTEND
- ;VALUE=DATE
- :20050207
-DTSTAMP
- :20050128T011209Z"
- nil
- "&%%(and (diary-block 6 2 2005 6 2 2005)) Waitangi Day
- Desc: abcdef
- Status: CONFIRMED
- Class: PRIVATE
- UID: b60d398e-1dd1-11b2-a159-cf8cb05139f4
-"
- "&%%(and (diary-block 2 6 2005 2 6 2005)) Waitangi Day
- Desc: abcdef
- Status: CONFIRMED
- Class: PRIVATE
- UID: b60d398e-1dd1-11b2-a159-cf8cb05139f4
-")
+ (icalendar-tests--test-import "import-real-world-2005-02-07.ics"
+ nil
+ "import-real-world-2005-02-07.diary-european"
+ "import-real-world-2005-02-07.diary-american")
;; 2005-03-01 lt
- (icalendar-tests--test-import
- "DTSTART;VALUE=DATE:20050217
-SUMMARY:Hhhhhh Aaaaa ii Aaaaaaaa
-UID:6AFA7558-6994-11D9-8A3A-000A95A0E830-RID
-DTSTAMP:20050118T210335Z
-DURATION:P7D"
- nil
- "&%%(and (diary-block 17 2 2005 23 2 2005)) Hhhhhh Aaaaa ii Aaaaaaaa
- UID: 6AFA7558-6994-11D9-8A3A-000A95A0E830-RID\n"
- "&%%(and (diary-block 2 17 2005 2 23 2005)) Hhhhhh Aaaaa ii Aaaaaaaa
- UID: 6AFA7558-6994-11D9-8A3A-000A95A0E830-RID\n")
+ (icalendar-tests--test-import "import-real-world-2005-03-01.ics"
+ nil
+ "import-real-world-2005-03-01.diary-european"
+ "import-real-world-2005-03-01.diary-american")
;; 2005-03-23 lt
(icalendar-tests--test-export
@@ -2205,126 +1617,46 @@ SUMMARY:NNN Wwwwwwww Wwwww - Aaaaaa Pppppppp rrrrrr ddd oo Nnnnnnnn 30
")
;; bug#11473
- (icalendar-tests--test-import
- "BEGIN:VCALENDAR
-METHOD:REQUEST
-PRODID:Microsoft Exchange Server 2007
-VERSION:2.0
-BEGIN:VTIMEZONE
-TZID:(UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna
-BEGIN:STANDARD
-DTSTART:16010101T030000
-TZOFFSETFROM:+0200
-TZOFFSETTO:+0100
-RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=-1SU;BYMONTH=10
-END:STANDARD
-BEGIN:DAYLIGHT
-DTSTART:16010101T020000
-TZOFFSETFROM:+0100
-TZOFFSETTO:+0200
-RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=-1SU;BYMONTH=3
-END:DAYLIGHT
-END:VTIMEZONE
-BEGIN:VEVENT
-ORGANIZER;CN=\"A. Luser\":MAILTO:a.luser@foo.com
-ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN=\"Luser, Oth
- er\":MAILTO:other.luser@foo.com
-DESCRIPTION;LANGUAGE=en-US:\nWhassup?\n\n
-SUMMARY;LANGUAGE=en-US:Query
-DTSTART;TZID=\"(UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna\"
- :20120515T150000
-DTEND;TZID=\"(UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna\":2
- 0120515T153000
-UID:040000008200E00074C5B7101A82E0080000000020FFAED0CFEFCC01000000000000000
- 010000000575268034ECDB649A15349B1BF240F15
-RECURRENCE-ID;TZID=\"(UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, V
- ienna\":20120515T170000
-CLASS:PUBLIC
-PRIORITY:5
-DTSTAMP:20120514T153645Z
-TRANSP:OPAQUE
-STATUS:CONFIRMED
-SEQUENCE:15
-LOCATION;LANGUAGE=en-US:phone
-X-MICROSOFT-CDO-APPT-SEQUENCE:15
-X-MICROSOFT-CDO-OWNERAPPTID:1907632092
-X-MICROSOFT-CDO-BUSYSTATUS:TENTATIVE
-X-MICROSOFT-CDO-INTENDEDSTATUS:BUSY
-X-MICROSOFT-CDO-ALLDAYEVENT:FALSE
-X-MICROSOFT-CDO-IMPORTANCE:1
-X-MICROSOFT-CDO-INSTTYPE:3
-BEGIN:VALARM
-ACTION:DISPLAY
-DESCRIPTION:REMINDER
-TRIGGER;RELATED=START:-PT15M
-END:VALARM
-END:VEVENT
-END:VCALENDAR"
- nil
- "&15/5/2012 15:00-15:30 Query
- Location: phone
- Organizer: MAILTO:a.luser@foo.com
- Status: CONFIRMED
- Class: PUBLIC
- UID: 040000008200E00074C5B7101A82E0080000000020FFAED0CFEFCC01000000000000000010000000575268034ECDB649A15349B1BF240F15
-" nil)
+ (icalendar-tests--test-import "import-bug-11473.ics"
+ nil
+ "import-bug-11473.diary-european"
+ nil)
;; 2015-12-05, mixed line endings and empty lines, see Bug#22092.
- (icalendar-tests--test-import
- "BEGIN:VCALENDAR\r
-PRODID:-//www.norwegian.no//iCalendar MIMEDIR//EN\r
-VERSION:2.0\r
-METHOD:REQUEST\r
-BEGIN:VEVENT\r
-UID:RFCALITEM1\r
-SEQUENCE:1512040950\r
-DTSTAMP:20141204T095043Z\r
-ORGANIZER:noreply@norwegian.no\r
-DTSTART:20141208T173000Z\r
-
-DTEND:20141208T215500Z\r
-
-LOCATION:Stavanger-Sola\r
-
-DESCRIPTION:Fly med Norwegian, reservasjon. Fra Stavanger til Troms&#248; 8. des 2014 18:30, DY545Fly med Norwegian, reservasjon . Fra Stavanger til Troms&#248; 8. des 2014 21:00, DY390\r
-
-X-ALT-DESC;FMTTYPE=text/html:<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2//EN\"><html><head><META NAME=\"Generator\" CONTENT=\"MS Exchange Server version 08.00.0681.000\"><title></title></head><body><b><font face=\"Calibri\" size=\"3\">Reisereferanse</p></body></html>
-SUMMARY:Norwegian til Tromsoe-Langnes -\r
-
-CATEGORIES:Appointment\r
-
-
-PRIORITY:5\r
+ (icalendar-tests--test-import "import-bug-22092.ics"
+ "import-bug-22092.diary-iso"
+ "import-bug-22092.diary-european"
+ "import-bug-22092.diary-american"))
-CLASS:PUBLIC\r
+(defun icalendar-test--format (string &optional day zone)
+ "Decode and format STRING with DAY and ZONE."
+ (let ((time (icalendar--decode-isodatetime string day zone)))
+ (format-time-string "%FT%T%z" (encode-time time) 0)))
-TRANSP:OPAQUE\r
-END:VEVENT\r
-END:VCALENDAR
-"
-"&2014/12/8 18:30-22:55 Norwegian til Tromsoe-Langnes -
- Desc: Fly med Norwegian, reservasjon. Fra Stavanger til Troms&#248; 8. des 2014 18:30, DY545Fly med Norwegian, reservasjon . Fra Stavanger til Troms&#248; 8. des 2014 21:00, DY390
- Location: Stavanger-Sola
- Organizer: noreply@norwegian.no
- Class: PUBLIC
- UID: RFCALITEM1
-"
-"&8/12/2014 18:30-22:55 Norwegian til Tromsoe-Langnes -
- Desc: Fly med Norwegian, reservasjon. Fra Stavanger til Troms&#248; 8. des 2014 18:30, DY545Fly med Norwegian, reservasjon . Fra Stavanger til Troms&#248; 8. des 2014 21:00, DY390
- Location: Stavanger-Sola
- Organizer: noreply@norwegian.no
- Class: PUBLIC
- UID: RFCALITEM1
-"
-"&12/8/2014 18:30-22:55 Norwegian til Tromsoe-Langnes -
- Desc: Fly med Norwegian, reservasjon. Fra Stavanger til Troms&#248; 8. des 2014 18:30, DY545Fly med Norwegian, reservasjon . Fra Stavanger til Troms&#248; 8. des 2014 21:00, DY390
- Location: Stavanger-Sola
- Organizer: noreply@norwegian.no
- Class: PUBLIC
- UID: RFCALITEM1
-"
-)
- )
+(ert-deftest icalendar-tests--decode-isodatetime ()
+ "Test `icalendar--decode-isodatetime'."
+ (should (equal (icalendar-test--format "20040917T050910-02:00")
+ "2004-09-17T03:09:10+0000"))
+ (let ((orig (icalendar-test--format "20040917T050910")))
+ (unwind-protect
+ (let ((zone "XXX-02"))
+ (should (equal (icalendar-test--format "20040917T050910" nil zone)
+ "2004-09-17T03:09:10+0000"))
+ (should (equal (icalendar-test--format "20040917T0509" nil zone)
+ "2004-09-17T03:09:00+0000"))
+ (should (equal (icalendar-test--format "20040917" nil zone)
+ "2004-09-16T22:00:00+0000"))
+ (should (equal (icalendar-test--format "20040917T050910" 1 zone)
+ "2004-09-18T03:09:10+0000"))
+ (should (equal (icalendar-test--format "20040917T050910" 30 zone)
+ "2004-10-17T03:09:10+0000")))
+ (should (equal orig (icalendar-test--format "20040917T050910")))))
+ (should (equal (icalendar-test--format "20040917T050910Z")
+ "2004-09-17T05:09:10+0000"))
+ (should (equal (icalendar-test--format "20040917T050910" -1 0)
+ "2004-09-16T05:09:10+0000"))
+ (should (equal (icalendar-test--format "20040917T050910" nil -3600)
+ "2004-09-17T06:09:10+0000")))
(provide 'icalendar-tests)
;;; icalendar-tests.el ends here
diff --git a/test/lisp/calendar/iso8601-tests.el b/test/lisp/calendar/iso8601-tests.el
new file mode 100644
index 00000000000..f64c498c027
--- /dev/null
+++ b/test/lisp/calendar/iso8601-tests.el
@@ -0,0 +1,354 @@
+;;; iso8601-tests.el --- tests for calendar/iso8601.el -*- lexical-binding:t -*-
+
+;; Copyright (C) 2019-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'iso8601)
+
+(ert-deftest test-iso8601-date-years ()
+ (should (equal (iso8601-parse-date "1985")
+ '(nil nil nil nil nil 1985 nil -1 nil)))
+ (should (equal (iso8601-parse-date "-0003")
+ '(nil nil nil nil nil -3 nil -1 nil)))
+ (should (equal (iso8601-parse-date "+1985")
+ '(nil nil nil nil nil 1985 nil -1 nil))))
+
+(ert-deftest test-iso8601-date-dates ()
+ (should (equal (iso8601-parse-date "1985-03-14")
+ '(nil nil nil 14 3 1985 nil -1 nil)))
+ (should (equal (iso8601-parse-date "19850314")
+ '(nil nil nil 14 3 1985 nil -1 nil)))
+ (should (equal (iso8601-parse-date "1985-02")
+ '(nil nil nil nil 2 1985 nil -1 nil))))
+
+(ert-deftest test-iso8601-date-obsolete ()
+ (should (equal (iso8601-parse-date "--02-01")
+ '(nil nil nil 1 2 nil nil -1 nil)))
+ (should (equal (iso8601-parse-date "--0201")
+ '(nil nil nil 1 2 nil nil -1 nil))))
+
+(ert-deftest test-iso8601-date-obsolete-2000 ()
+ ;; These are forms in 5.2.1.3 of the 2000 version of the standard,
+ ;; e) and f).
+ (should (equal (iso8601-parse-date "--12")
+ '(nil nil nil nil 12 nil nil -1 nil)))
+ (should (equal (iso8601-parse "--12T14")
+ '(0 0 14 nil 12 nil nil -1 nil)))
+ (should (equal (iso8601-parse-date "---12")
+ '(nil nil nil 12 nil nil nil -1 nil)))
+ (should (equal (iso8601-parse "---12T14:10:12")
+ '(12 10 14 12 nil nil nil -1 nil))))
+
+(ert-deftest test-iso8601-date-weeks ()
+ (should (equal (iso8601-parse-date "2008W39-6")
+ '(nil nil nil 27 9 2008 nil -1 nil)))
+ (should (equal (iso8601-parse-date "2009W01-1")
+ '(nil nil nil 29 12 2008 nil -1 nil)))
+ (should (equal (iso8601-parse-date "2009W53-7")
+ '(nil nil nil 3 1 2010 nil -1 nil))))
+
+(ert-deftest test-iso8601-date-ordinals ()
+ (should (equal (iso8601-parse-date "1981-095")
+ '(nil nil nil 5 4 1981 nil -1 nil))))
+
+(ert-deftest test-iso8601-time ()
+ (should (equal (iso8601-parse-time "13:47:30")
+ '(30 47 13 nil nil nil nil -1 nil)))
+ (should (equal (iso8601-parse-time "134730")
+ '(30 47 13 nil nil nil nil -1 nil)))
+ (should (equal (iso8601-parse-time "1347")
+ '(0 47 13 nil nil nil nil -1 nil))))
+
+(ert-deftest test-iso8601-combined ()
+ (should (equal (iso8601-parse "2008-03-02T13:47:30")
+ '(30 47 13 2 3 2008 nil -1 nil)))
+ (should (equal (iso8601-parse "2008-03-02T13:47:30Z")
+ '(30 47 13 2 3 2008 nil nil 0)))
+ (should (equal (iso8601-parse "2008-03-02T13:47:30+01:00")
+ '(30 47 13 2 3 2008 nil -1 3600)))
+ (should (equal (iso8601-parse "2008-03-02T13:47:30-01")
+ '(30 47 13 2 3 2008 nil -1 -3600))))
+
+(ert-deftest test-iso8601-duration ()
+ (should (equal (iso8601-parse-duration "P3Y6M4DT12H30M5S")
+ '(5 30 12 4 6 3 nil -1 nil)))
+ (should (equal (iso8601-parse-duration "P1M")
+ '(0 0 0 0 1 0 nil -1 nil)))
+ (should (equal (iso8601-parse-duration "PT1M")
+ '(0 1 0 0 0 0 nil -1 nil)))
+ (should (equal (iso8601-parse-duration "P0003-06-04T12:30:05")
+ '(5 30 12 4 6 3 nil -1 nil))))
+
+(ert-deftest test-iso8601-invalid ()
+ (should-not (iso8601-valid-p " 2008-03-02T13:47:30-01"))
+ (should-not (iso8601-valid-p "2008-03-02T13:47:30-01:200"))
+ (should-not (iso8601-valid-p "2008-03-02T13:47:30-01 "))
+ (should-not (iso8601-valid-p "2008-03-02 T 13:47:30-01 "))
+ (should-not (iso8601-valid-p "20008-03-02T13:47:30-01")))
+
+(ert-deftest test-iso8601-intervals ()
+ (should (equal
+ (iso8601-parse-interval "2007-03-01T13:00:00Z/2008-05-11T15:30:00Z")
+ '((0 0 13 1 3 2007 nil nil 0)
+ (0 30 15 11 5 2008 nil nil 0)
+ ;; Hm... can't really use decode-time for time differences...
+ (0 30 2 14 3 1971 0 nil 0))))
+ (should (equal (iso8601-parse-interval "2007-03-01T13:00:00Z/P1Y2M10DT2H30M")
+ '((0 0 13 1 3 2007 nil nil 0)
+ (0 30 15 11 5 2008 nil nil 0)
+ (0 30 2 10 2 1 nil -1 nil))))
+ (should (equal (iso8601-parse-interval "P1Y2M10DT2H30M/2008-05-11T15:30:00Z")
+ '((0 0 13 1 3 2007 nil nil 0)
+ (0 30 15 11 5 2008 nil nil 0)
+ (0 30 2 10 2 1 nil -1 nil)))))
+
+(ert-deftest standard-test-dates ()
+ (should (equal (iso8601-parse-date "19850412")
+ '(nil nil nil 12 4 1985 nil -1 nil)))
+ (should (equal (iso8601-parse-date "1985-04-12")
+ '(nil nil nil 12 4 1985 nil -1 nil)))
+
+ (should (equal (iso8601-parse-date "1985102")
+ '(nil nil nil 12 4 1985 nil -1 nil)))
+ (should (equal (iso8601-parse-date "1985-102")
+ '(nil nil nil 12 4 1985 nil -1 nil)))
+
+ (should (equal (iso8601-parse-date "1985W155")
+ '(nil nil nil 12 4 1985 nil -1 nil)))
+ (should (equal (iso8601-parse-date "1985-W15-5")
+ '(nil nil nil 12 4 1985 nil -1 nil)))
+
+ (should (equal (iso8601-parse-date "1985W15")
+ '(nil nil nil 7 4 1985 nil -1 nil)))
+ (should (equal (iso8601-parse-date "1985-W15")
+ '(nil nil nil 7 4 1985 nil -1 nil)))
+
+ (should (equal (iso8601-parse-date "1985-04")
+ '(nil nil nil nil 4 1985 nil -1 nil)))
+
+ (should (equal (iso8601-parse-date "1985")
+ '(nil nil nil nil nil 1985 nil -1 nil)))
+
+ (should (equal (iso8601-parse-date "+1985-04-12")
+ '(nil nil nil 12 4 1985 nil -1 nil)))
+ (should (equal (iso8601-parse-date "+19850412")
+ '(nil nil nil 12 4 1985 nil -1 nil))))
+
+(ert-deftest standard-test-time-of-day-local-time ()
+ (should (equal (iso8601-parse-time "152746")
+ '(46 27 15 nil nil nil nil -1 nil)))
+ (should (equal (iso8601-parse-time "15:27:46")
+ '(46 27 15 nil nil nil nil -1 nil)))
+
+ (should (equal (iso8601-parse-time "1528")
+ '(0 28 15 nil nil nil nil -1 nil)))
+ (should (equal (iso8601-parse-time "15:28")
+ '(0 28 15 nil nil nil nil -1 nil)))
+
+ (should (equal (iso8601-parse-time "15")
+ '(0 0 15 nil nil nil nil -1 nil))))
+
+(ert-deftest standard-test-time-of-day-fractions ()
+ (should (equal (iso8601-parse-time "152735,5" t)
+ '((355 . 10) 27 15 nil nil nil nil -1 nil)))
+ (should (equal (iso8601-parse-time "15:27:35,5" t)
+ '((355 . 10) 27 15 nil nil nil nil -1 nil)))
+
+ (should (equal (iso8601-parse-time "2320,5" t)
+ '(30 20 23 nil nil nil nil -1 nil)))
+ (should (equal (iso8601-parse-time "23:20,8" t)
+ '(48 20 23 nil nil nil nil -1 nil)))
+
+ (should (equal (iso8601-parse-time "23,3" t)
+ '(0 18 23 nil nil nil nil -1 nil))))
+
+(ert-deftest nonstandard-test-time-of-day-decimals ()
+ (should (equal (iso8601-parse-time "15:27:35.123" t)
+ '((35123 . 1000) 27 15 nil nil nil nil -1 nil)))
+ (should (equal (iso8601-parse-time "15:27:35.123456789" t)
+ '((35123456789 . 1000000000) 27 15 nil nil nil nil -1 nil)))
+ (should (equal (iso8601-parse-time "15:27:35.012345678" t)
+ '((35012345678 . 1000000000) 27 15 nil nil nil nil -1 nil)))
+ (should (equal (iso8601-parse-time "15:27:35.00001" t)
+ '((3500001 . 100000) 27 15 nil nil nil nil -1 nil)))
+ (should (equal (iso8601-parse-time "15:27:35.0000100" t)
+ '((3500001 . 100000) 27 15 nil nil nil nil -1 nil)))
+ (should (equal (iso8601-parse-time "15:27:35.0" t)
+ '(35 27 15 nil nil nil nil -1 nil))))
+
+(ert-deftest standard-test-time-of-day-beginning-of-day ()
+ (should (equal (iso8601-parse-time "000000")
+ '(0 0 0 nil nil nil nil -1 nil)))
+ (should (equal (iso8601-parse-time "00:00:00")
+ '(0 0 0 nil nil nil nil -1 nil)))
+
+ (should (equal (iso8601-parse-time "0000")
+ '(0 0 0 nil nil nil nil -1 nil)))
+ (should (equal (iso8601-parse-time "00:00")
+ '(0 0 0 nil nil nil nil -1 nil))))
+
+(ert-deftest standard-test-time-of-day-utc ()
+ (should (equal (iso8601-parse-time "232030Z")
+ '(30 20 23 nil nil nil nil nil 0)))
+ (should (equal (iso8601-parse-time "23:20:30Z")
+ '(30 20 23 nil nil nil nil nil 0)))
+
+ (should (equal (iso8601-parse-time "2320Z")
+ '(0 20 23 nil nil nil nil nil 0)))
+ (should (equal (iso8601-parse-time "23:20Z")
+ '(0 20 23 nil nil nil nil nil 0)))
+
+ (should (equal (iso8601-parse-time "23Z")
+ '(0 0 23 nil nil nil nil nil 0))))
+
+
+(ert-deftest standard-test-time-of-day-zone ()
+ (should (equal (iso8601-parse-time "152746+0100")
+ '(46 27 15 nil nil nil nil -1 3600)))
+ (should (equal (iso8601-parse-time "15:27:46+0100")
+ '(46 27 15 nil nil nil nil -1 3600)))
+
+ (should (equal (iso8601-parse-time "152746+01")
+ '(46 27 15 nil nil nil nil -1 3600)))
+ (should (equal (iso8601-parse-time "15:27:46+01")
+ '(46 27 15 nil nil nil nil -1 3600)))
+
+ (should (equal (iso8601-parse-time "152746-0500")
+ '(46 27 15 nil nil nil nil -1 -18000)))
+ (should (equal (iso8601-parse-time "15:27:46-0500")
+ '(46 27 15 nil nil nil nil -1 -18000)))
+
+ (should (equal (iso8601-parse-time "152746-05")
+ '(46 27 15 nil nil nil nil -1 -18000)))
+ (should (equal (iso8601-parse-time "15:27:46-05")
+ '(46 27 15 nil nil nil nil -1 -18000))))
+
+
+(defun test-iso8601-format-time-string-zone-round-trip (offset-minutes z-format)
+ "Pass OFFSET-MINUTES to format-time-string with Z-FORMAT, a %z variation,
+and then to iso8601-parse-zone. The result should be the original offset."
+ (let* ((offset-seconds (* 60 offset-minutes))
+ (zone-string (format-time-string z-format 0 offset-seconds))
+ (offset-rt
+ (condition-case nil
+ (iso8601-parse-zone zone-string)
+ (wrong-type-argument (format "(failed to parse %S)" zone-string))))
+ ;; compare strings that contain enough info to debug failures
+ (success (format "%s(%s) -> %S -> %s"
+ z-format offset-minutes zone-string offset-minutes))
+ (actual (format "%s(%s) -> %S -> %s"
+ z-format offset-minutes zone-string offset-rt)))
+ (should (equal success actual))))
+
+(ert-deftest iso8601-format-time-string-zone-round-trip ()
+ "Round trip zone offsets through format-time-string and iso8601-parse-zone.
+Passing a time zone created by format-time-string %z to
+iso8601-parse-zone should yield the original offset."
+ (dolist (offset-minutes
+ (list
+ ;; compare hours (1- and 2-digit), minutes, both, neither
+ (* 5 60) (* 11 60) 5 11 (+ (* 5 60) 30) (+ (* 11 60) 30) 0
+ ;; do negative values, too
+ (* -5 60) (* -11 60) -5 -11 (- (* -5 60) 30) (- (* -11 60) 30)))
+ (dolist (z-format '("%z" "%:z" "%:::z"))
+ (test-iso8601-format-time-string-zone-round-trip
+ offset-minutes z-format))))
+
+(ert-deftest standard-test-date-and-time-of-day ()
+ (should (equal (iso8601-parse "19850412T101530")
+ '(30 15 10 12 4 1985 nil -1 nil)))
+ (should (equal (iso8601-parse "1985-04-12T10:15:30")
+ '(30 15 10 12 4 1985 nil -1 nil)))
+
+ (should (equal (iso8601-parse "1985102T235030Z")
+ '(30 50 23 12 4 1985 nil nil 0)))
+ (should (equal (iso8601-parse "1985-102T23:50:30Z")
+ '(30 50 23 12 4 1985 nil nil 0)))
+
+ (should (equal (iso8601-parse "1985W155T235030")
+ '(30 50 23 12 4 1985 nil -1 nil)))
+ (should (equal (iso8601-parse "1985-W155T23:50:30")
+ '(30 50 23 12 4 1985 nil -1 nil))))
+
+(ert-deftest standard-test-interval ()
+ ;; A time interval starting at 20 minutes and 50 seconds past 23
+ ;; hours on 12 April 1985 and ending at 30 minutes past 10 hours on
+ ;; 25 June 1985.
+ (should (equal (iso8601-parse-interval "19850412T232050Z/19850625T103000Z")
+ '((50 20 23 12 4 1985 nil nil 0)
+ (0 30 10 25 6 1985 nil nil 0)
+ (10 9 11 15 3 1970 0 nil 0))))
+ (should (equal (iso8601-parse-interval
+ "1985-04-12T23:20:50Z/1985-06-25T10:30:00Z")
+ '((50 20 23 12 4 1985 nil nil 0)
+ (0 30 10 25 6 1985 nil nil 0)
+ (10 9 11 15 3 1970 0 nil 0))))
+
+ ;; A time interval starting at 12 April 1985 and ending on 25 June
+ ;; 1985.
+
+ ;; This example doesn't seem valid according to the standard.
+ ;; "0625" is unambiguous, and means "the year 625". Weird.
+ ;; (should (equal (iso8601-parse-interval "19850412/0625")
+ ;; '((nil nil nil 12 4 1985 nil -1 nil)
+ ;; (nil nil nil nil nil 625 nil -1 nil)
+ ;; (0 17 0 22 9 609 5 nil 0))))
+
+ ;; A time interval of 2 years, 10 months, 15 days, 10 hours, 20
+ ;; minutes and 30 seconds.
+ (should (equal (iso8601-parse-duration "P2Y10M15DT10H20M30S")
+ '(30 20 10 15 10 2 nil -1 nil)))
+
+ (should (equal (iso8601-parse-duration "P00021015T102030")
+ '(30 20 10 15 10 2 nil -1 nil)))
+ (should (equal (iso8601-parse-duration "P0002-10-15T10:20:30")
+ '(30 20 10 15 10 2 nil -1 nil)))
+
+ ;; A time interval of 1 year and 6 months.
+ (should (equal (iso8601-parse-duration "P1Y6M")
+ '(0 0 0 0 6 1 nil -1 nil)))
+ (should (equal (iso8601-parse-duration "P0001-06")
+ '(nil nil nil nil 6 1 nil -1 nil)))
+
+ ;; A time interval of seventy-two hours.
+ (should (equal (iso8601-parse-duration "PT72H")
+ '(0 0 72 0 0 0 nil -1 nil)))
+
+ ;; Defined by start and duration
+ ;; A time interval of 1 year, 2 months, 15 days and 12 hours,
+ ;; beginning on 12 April 1985 at 20 minutes past 23 hours.
+ (should (equal (iso8601-parse-interval "19850412T232000/P1Y2M15DT12H")
+ '((0 20 23 12 4 1985 nil -1 nil)
+ (0 20 11 28 6 1986 nil -1 nil)
+ (0 0 12 15 2 1 nil -1 nil))))
+ (should (equal (iso8601-parse-interval "1985-04-12T23:20:00/P1Y2M15DT12H")
+ '((0 20 23 12 4 1985 nil -1 nil)
+ (0 20 11 28 6 1986 nil -1 nil)
+ (0 0 12 15 2 1 nil -1 nil))))
+
+ ;; Defined by duration and end
+ ;; A time interval of 1 year, 2 months, 15 days and 12 hours, ending
+ ;; on 12 April 1985 at 20 minutes past 23 hour.
+ (should (equal (iso8601-parse-interval "P1Y2M15DT12H/19850412T232000")
+ '((0 20 11 28 1 1984 nil -1 nil)
+ (0 20 23 12 4 1985 nil -1 nil)
+ (0 0 12 15 2 1 nil -1 nil)))))
+
+;;; iso8601-tests.el ends here
diff --git a/test/lisp/calendar/lunar-tests.el b/test/lisp/calendar/lunar-tests.el
new file mode 100644
index 00000000000..846a749eb5f
--- /dev/null
+++ b/test/lisp/calendar/lunar-tests.el
@@ -0,0 +1,73 @@
+;;; lunar-tests.el --- tests for calendar/lunar.el -*- lexical-binding:t -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+;; Author: Stefan Kangas <stefankangas@gmail.com>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'lunar)
+
+(defmacro with-lunar-test (&rest body)
+ `(let ((calendar-latitude 40.1)
+ (calendar-longitude -88.2)
+ (calendar-location-name "Paris")
+ (calendar-time-zone 0)
+ (calendar-standard-time-zone-name "UTC")
+ ;; Make sure daylight saving is disabled to avoid interference
+ ;; from the system settings (see bug#45818).
+ (calendar-daylight-savings-starts nil)
+ (calendar-time-display-form '(24-hours ":" minutes)))
+ ,@body))
+
+(ert-deftest lunar-test-phase ()
+ (with-lunar-test
+ (should (equal (lunar-phase 1)
+ '((1 8 1900) "05:40" 1 "")))))
+
+(ert-deftest lunar-test-eclipse-check ()
+ (with-lunar-test
+ (should (equal (eclipse-check 1 1) "** Eclipse **"))))
+
+(ert-deftest lunar-test-phase-list ()
+ (with-lunar-test
+ (should (equal (lunar-phase-list 3 1871)
+ '(((3 21 1871) "04:03" 0 "")
+ ((3 29 1871) "06:46" 1 "** Eclipse **")
+ ((4 5 1871) "14:20" 2 "")
+ ((4 12 1871) "05:57" 3 "** Eclipse possible **")
+ ((4 19 1871) "19:06" 0 "")
+ ((4 27 1871) "23:49" 1 "")
+ ((5 4 1871) "22:57" 2 "")
+ ((5 11 1871) "14:29" 3 "")
+ ((5 19 1871) "10:46" 0 "")
+ ((5 27 1871) "13:02" 1 ""))))))
+
+(ert-deftest lunar-test-new-moon-time ()
+ (with-lunar-test
+ (should (= (round (lunar-new-moon-time 1))
+ 2451580))))
+
+(ert-deftest lunar-test-new-moon-on-or-after ()
+ (with-lunar-test
+ (should (= (round (lunar-new-moon-on-or-after (calendar-absolute-from-gregorian '(5 5 1818))))
+ 664525))))
+
+(provide 'lunar-tests)
+;;; lunar-tests.el ends here
diff --git a/test/lisp/calendar/parse-time-tests.el b/test/lisp/calendar/parse-time-tests.el
index 0ad0b36438f..3fd53c6c1eb 100644
--- a/test/lisp/calendar/parse-time-tests.el
+++ b/test/lisp/calendar/parse-time-tests.el
@@ -1,6 +1,6 @@
-;; parse-time-tests.el --- Test suite for parse-time.el
+;;; parse-time-tests.el --- Test suite for parse-time.el -*- lexical-binding:t -*-
-;; Copyright (C) 2016-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2022 Free Software Foundation, Inc.
;; Author: Lars Ingebrigtsen <larsi@gnus.org>
@@ -28,35 +28,51 @@
(ert-deftest parse-time-tests ()
(should (equal (parse-time-string "Mon, 22 Feb 2016 19:35:42 +0100")
- '(42 35 19 22 2 2016 1 nil 3600)))
+ '(42 35 19 22 2 2016 1 -1 3600)))
(should (equal (parse-time-string "22 Feb 2016 19:35:42 +0100")
- '(42 35 19 22 2 2016 nil nil 3600)))
+ '(42 35 19 22 2 2016 nil -1 3600)))
(should (equal (parse-time-string "22 Feb 2016 +0100")
- '(nil nil nil 22 2 2016 nil nil 3600)))
+ '(nil nil nil 22 2 2016 nil -1 3600)))
(should (equal (parse-time-string "Mon, 22 Feb 16 19:35:42 +0100")
- '(42 35 19 22 2 2016 1 nil 3600)))
+ '(42 35 19 22 2 2016 1 -1 3600)))
(should (equal (parse-time-string "Mon, 22 February 2016 19:35:42 +0100")
- '(42 35 19 22 2 2016 1 nil 3600)))
+ '(42 35 19 22 2 2016 1 -1 3600)))
(should (equal (parse-time-string "Mon, 22 feb 2016 19:35:42 +0100")
- '(42 35 19 22 2 2016 1 nil 3600)))
+ '(42 35 19 22 2 2016 1 -1 3600)))
(should (equal (parse-time-string "Monday, 22 february 2016 19:35:42 +0100")
- '(42 35 19 22 2 2016 1 nil 3600)))
- (should (equal (parse-time-string "Monday, 22 february 2016 19:35:42 PDT")
- '(42 35 19 22 2 2016 1 t -25200)))
- (should (equal (parse-iso8601-time-string "1998-09-12T12:21:54-0200")
- '(13818 33666)))
- (should (equal (parse-iso8601-time-string "1998-09-12T12:21:54-0230")
- '(13818 35466)))
- (should (equal (parse-iso8601-time-string "1998-09-12T12:21:54-02:00")
- '(13818 33666)))
- (should (equal (parse-iso8601-time-string "1998-09-12T12:21:54-02")
- '(13818 33666)))
- (should (equal (parse-iso8601-time-string "1998-09-12T12:21:54+0230")
- '(13818 17466)))
- (should (equal (parse-iso8601-time-string "1998-09-12T12:21:54+02")
- '(13818 19266)))
- (should (equal (parse-iso8601-time-string "1998-09-12T12:21:54Z")
- '(13818 26466)))
+ '(42 35 19 22 2 2016 1 -1 3600)))
+ (should (equal (parse-time-string "Monday, 22 february 2016 19:35:42 PST")
+ '(42 35 19 22 2 2016 1 nil -28800)))
+ (should (equal (parse-time-string "Friday, 21 Sep 2018 13:47:58 PDT")
+ '(58 47 13 21 9 2018 5 t -25200)))
+ (should (equal (format-time-string
+ "%Y-%m-%d %H:%M:%S"
+ (parse-iso8601-time-string "1998-09-12T12:21:54-0200") t)
+ "1998-09-12 14:21:54"))
+ (should (equal (format-time-string
+ "%Y-%m-%d %H:%M:%S"
+ (parse-iso8601-time-string "1998-09-12T12:21:54-0230") t)
+ "1998-09-12 14:51:54"))
+ (should (equal (format-time-string
+ "%Y-%m-%d %H:%M:%S"
+ (parse-iso8601-time-string "1998-09-12T12:21:54-02:00") t)
+ "1998-09-12 14:21:54"))
+ (should (equal (format-time-string
+ "%Y-%m-%d %H:%M:%S"
+ (parse-iso8601-time-string "1998-09-12T12:21:54-02") t)
+ "1998-09-12 14:21:54"))
+ (should (equal (format-time-string
+ "%Y-%m-%d %H:%M:%S"
+ (parse-iso8601-time-string "1998-09-12T12:21:54+0230") t)
+ "1998-09-12 09:51:54"))
+ (should (equal (format-time-string
+ "%Y-%m-%d %H:%M:%S"
+ (parse-iso8601-time-string "1998-09-12T12:21:54+02") t)
+ "1998-09-12 10:21:54"))
+ (should (equal (format-time-string
+ "%Y-%m-%d %H:%M:%S"
+ (parse-iso8601-time-string "1998-09-12T12:21:54Z") t)
+ "1998-09-12 12:21:54"))
(should (equal (parse-iso8601-time-string "1998-09-12T12:21:54")
(encode-time 54 21 12 12 9 1998))))
diff --git a/test/lisp/calendar/solar-tests.el b/test/lisp/calendar/solar-tests.el
new file mode 100644
index 00000000000..9f79fed7c7b
--- /dev/null
+++ b/test/lisp/calendar/solar-tests.el
@@ -0,0 +1,48 @@
+;;; solar-tests.el --- tests for solar.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'solar)
+
+(ert-deftest solar-sunrise-sunset ()
+ ;; Bug#44237: wrong sunrise time on Dec 30 and 31, 2020 for Jaipur.
+ (let ((calendar-latitude 26.9)
+ (calendar-longitude 75.8)
+ (calendar-time-zone +330)
+ (calendar-standard-time-zone-name "IST")
+ ;; Make sure our clockwork isn't confused by daylight saving rules
+ ;; in effect for any other time zone (bug#45818).
+ (calendar-daylight-savings-starts nil)
+ (epsilon (/ 60.0))) ; Minute accuracy is good enough.
+ (let* ((sunrise-sunset (solar-sunrise-sunset '(12 30 2020)))
+ (sunrise (car (nth 0 sunrise-sunset)))
+ (sunset (car (nth 1 sunrise-sunset))))
+ (should (< (abs (- sunrise 7.27)) epsilon))
+ (should (< (abs (- sunset 17.72)) epsilon)))
+ (let* ((sunrise-sunset (solar-sunrise-sunset '(12 31 2020)))
+ (sunrise (car (nth 0 sunrise-sunset)))
+ (sunset (car (nth 1 sunrise-sunset))))
+ (should (< (abs (- sunrise 7.28)) epsilon))
+ (should (< (abs (- sunset 17.72)) epsilon)))))
+
+(provide 'solar-tests)
+
+;;; solar-tests.el ends here
diff --git a/test/lisp/calendar/time-date-tests.el b/test/lisp/calendar/time-date-tests.el
new file mode 100644
index 00000000000..fd4d5ac8a1b
--- /dev/null
+++ b/test/lisp/calendar/time-date-tests.el
@@ -0,0 +1,216 @@
+;;; time-date-tests.el --- tests for calendar/time-date.el -*- lexical-binding:t -*-
+
+;; Copyright (C) 2019-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'time-date)
+
+(ert-deftest test-obsolete-with-decoded-time-value ()
+ (with-suppressed-warnings ((obsolete with-decoded-time-value))
+ (with-decoded-time-value ((high low micro pico type '(1 2 3 4 5 6 8 8)))
+ (should (equal (list high low micro pico type) '(1 2 3 4 3))))))
+
+(ert-deftest test-obsolete-encode-time-value ()
+ (should (equal (with-suppressed-warnings ((obsolete encode-time-value))
+ (encode-time-value 1 2 3 4 0))
+ '(1 . 2)))
+ (should (equal (with-suppressed-warnings ((obsolete encode-time-value))
+ (encode-time-value 1 2 3 4 1))
+ '(1 2)))
+ (should (equal (with-suppressed-warnings ((obsolete encode-time-value))
+ (encode-time-value 1 2 3 4 2))
+ '(1 2 3)))
+ (should (equal (with-suppressed-warnings ((obsolete encode-time-value))
+ (encode-time-value 1 2 3 4 3))
+ '(1 2 3 4))))
+
+(ert-deftest test-date-to-time ()
+ (should (equal (format-time-string "%F %T" (date-to-time "2021-12-04"))
+ "2021-12-04 00:00:00")))
+
+(ert-deftest test-days-between ()
+ (should (equal (days-between "2021-10-22" "2020-09-29") 388)))
+
+(ert-deftest test-leap-year ()
+ (should-not (date-leap-year-p 1999))
+ (should-not (date-leap-year-p 1900))
+ (should (date-leap-year-p 2000))
+ (should (date-leap-year-p 2004)))
+
+(ert-deftest test-days-to-time ()
+ (should (time-equal-p (days-to-time 0) '(0 0)))
+ (should (time-equal-p (days-to-time 1) '(1 20864)))
+ (should (time-equal-p (days-to-time 999) '(1317 2688)))
+ (should (time-equal-p (days-to-time 0.0) '(0 0 0 0)))
+ (should (time-equal-p (days-to-time 0.5) '(0 43200 0 0)))
+ (should (time-equal-p (days-to-time 1.0) '(1 20864 0 0)))
+ (should (time-equal-p (days-to-time 999.0) '(1317 2688 0 0))))
+
+(ert-deftest test-seconds-to-string ()
+ (should (equal (seconds-to-string 0) "0s"))
+ (should (equal (seconds-to-string 9) "9.00s"))
+ (should (equal (seconds-to-string 99) "99.00s"))
+ (should (equal (seconds-to-string 999) "16.65m"))
+ (should (equal (seconds-to-string 9999) "2.78h"))
+ (should (equal (seconds-to-string 99999) "27.78h"))
+ (should (equal (seconds-to-string 999999) "11.57d"))
+ (should (equal (seconds-to-string 9999999) "115.74d"))
+ (should (equal (seconds-to-string 99999999) "3.17y"))
+ (should (equal (seconds-to-string 999999999) "31.69y")))
+
+(ert-deftest test-days-in-month ()
+ (should (= (date-days-in-month 2004 2) 29))
+ (should (= (date-days-in-month 2004 3) 31))
+ (should (= (date-days-in-month 2019 2) 28))
+ (should (= (date-days-in-month 2020 12) 31))
+ (should-not (= (date-days-in-month 1900 3) 28))
+ (should-error (date-days-in-month 2020 0))
+ (should-error (date-days-in-month 2020 15))
+ (should-error (date-days-in-month 2020 'foo)))
+
+(ert-deftest test-format-seconds ()
+ (should (equal (format-seconds "%y %d %h %m %s %%" 0) "0 0 0 0 0 %"))
+ (should (equal (format-seconds "%y %d %h %m %s %%" 9999999) "0 115 17 46 39 %"))
+ (should (equal (format-seconds "%y %d %h %m %z %s %%" 1) "1 %"))
+ (should (equal (format-seconds "%mm %ss" 66) "1m 6s"))
+ (should (equal (format-seconds "%mm %5ss" 66) "1m 6s"))
+ (should (equal (format-seconds "%mm %.5ss" 66.4) "1m 00006s"))
+
+ (should (equal (format-seconds "%mm %,1ss" 66.4) "1m 6.4s"))
+ (should (equal (format-seconds "%mm %5,1ss" 66.4) "1m 6.4s"))
+ (should (equal (format-seconds "%mm %.5,1ss" 66.4) "1m 006.4s"))
+
+ (should (equal (format-seconds "%hh %z%x%mm %ss" (* 60 2)) "2m"))
+ (should (equal (format-seconds "%hh %z%mm %ss" (* 60 2)) "2m 0s"))
+ (should (equal (format-seconds "%hh %x%mm %ss" (* 60 2)) "0h 2m"))
+ (should (equal (format-seconds "%hh %x%mm %ss" 0) "0h 0m 0s")))
+
+(ert-deftest test-ordinal ()
+ (should (equal (date-ordinal-to-time 2008 271)
+ '(nil nil nil 27 9 2008 nil nil nil)))
+ (should (equal (date-ordinal-to-time 2008 1)
+ '(nil nil nil 1 1 2008 nil nil nil)))
+ (should (equal (date-ordinal-to-time 2008 32)
+ '(nil nil nil 1 2 2008 nil nil nil)))
+ (should (equal (date-ordinal-to-time 1981 095)
+ '(nil nil nil 5 4 1981 nil nil nil))))
+
+(cl-defmethod mdec (&key second minute hour
+ day month year
+ dst zone)
+ (list second minute hour day month year nil dst zone))
+
+(ert-deftest test-decoded-add ()
+ (let ((time '(12 15 16 8 7 2019 1 t 7200)))
+ (should (equal (decoded-time-add time (mdec :year 1))
+ '(12 15 16 8 7 2020 1 t 7200)))
+
+ (should (equal (decoded-time-add time (mdec :year -2))
+ '(12 15 16 8 7 2017 1 t 7200)))
+
+ (should (equal (decoded-time-add time (mdec :month 1))
+ '(12 15 16 8 8 2019 1 t 7200)))
+
+ (should (equal (decoded-time-add time (mdec :month 10))
+ '(12 15 16 8 5 2020 1 t 7200)))
+
+ (should (equal (decoded-time-add time (mdec :day 1))
+ '(12 15 16 9 7 2019 1 t 7200)))
+
+ (should (equal (decoded-time-add time (mdec :day -1))
+ '(12 15 16 7 7 2019 1 t 7200)))
+
+ (should (equal (decoded-time-add time (mdec :day 30))
+ '(12 15 16 7 8 2019 1 t 7200)))
+
+ (should (equal (decoded-time-add time (mdec :day -365))
+ '(12 15 16 8 7 2018 1 t 7200)))
+
+ (should (equal (decoded-time-add time (mdec :day 365))
+ '(12 15 16 7 7 2020 1 t 7200)))
+
+ ;; 2020 is a leap year.
+ (should (equal (decoded-time-add time (mdec :day 366))
+ '(12 15 16 8 7 2020 1 t 7200)))
+
+ (should (equal (decoded-time-add time (mdec :second 1))
+ '(13 15 16 8 7 2019 1 t 7200)))
+
+ (should (equal (decoded-time-add time (mdec :second -1))
+ '(11 15 16 8 7 2019 1 t 7200)))
+
+ (should (equal (decoded-time-add time (mdec :second 61))
+ '(13 16 16 8 7 2019 1 t 7200)))
+
+ (should (equal (decoded-time-add time (mdec :hour 1 :minute 2 :second 3))
+ '(15 17 17 8 7 2019 1 t 7200)))
+
+ (should (equal (decoded-time-add time (mdec :hour 24))
+ '(12 15 16 9 7 2019 1 t 7200)))
+ ))
+
+(ert-deftest test-decoded-add-zone ()
+ (let ((time '(12 15 16 8 7 2019 1 t 7200)))
+ (should (equal (decoded-time-add time (mdec :zone -3600))
+ '(12 15 15 8 7 2019 1 t 7200)))
+ (should (equal (decoded-time-add time (mdec :zone -7200))
+ '(12 15 14 8 7 2019 1 t 7200)))))
+
+(ert-deftest test-time-since ()
+ (should (time-equal-p 0 (time-since nil)))
+ (should (time-equal-p 1 (time-convert (time-since (time-subtract nil 1))
+ 'integer))))
+
+(ert-deftest test-time-decoded-period ()
+ (should (equal (decoded-time-period '(nil nil 1 nil nil nil nil nil nil))
+ 3600))
+
+ (should (equal (decoded-time-period '(1 0 0 0 0 0 nil nil nil)) 1))
+ (should (equal (decoded-time-period '(0 1 0 0 0 0 nil nil nil)) 60))
+ (should (equal (decoded-time-period '(0 0 1 0 0 0 nil nil nil)) 3600))
+ (should (equal (decoded-time-period '(0 0 0 1 0 0 nil nil nil)) 86400))
+ (should (equal (decoded-time-period '(0 0 0 0 1 0 nil nil nil)) 2592000))
+ (should (equal (decoded-time-period '(0 0 0 0 0 1 nil nil nil)) 31536000))
+ (should (equal (decoded-time-period '(1 2 3 4 5 6 nil nil nil)) 202532521))
+
+ (should (equal (decoded-time-period '((135 . 10) 0 0 0 0 0 nil nil nil))
+ 13.5)))
+
+(ert-deftest test-time-wrap-addition ()
+ (should (equal (decoded-time-add '(0 0 0 1 11 2008 nil nil nil)
+ (make-decoded-time :month 1))
+ '(0 0 0 1 12 2008 nil nil nil)))
+ (should (equal (decoded-time-add '(0 0 0 1 12 2008 nil nil nil)
+ (make-decoded-time :month 1))
+ '(0 0 0 1 1 2009 nil nil nil)))
+ (should (equal (decoded-time-add '(0 0 0 1 11 2008 nil nil nil)
+ (make-decoded-time :month 12))
+ '(0 0 0 1 11 2009 nil nil nil)))
+ (should (equal (decoded-time-add '(0 0 0 1 11 2008 nil nil nil)
+ (make-decoded-time :month 13))
+ '(0 0 0 1 12 2009 nil nil nil)))
+ (should (equal (decoded-time-add '(0 0 0 30 12 2008 nil nil nil)
+ (make-decoded-time :day 1))
+ '(0 0 0 31 12 2008 nil nil nil)))
+ (should (equal (decoded-time-add '(0 0 0 30 12 2008 nil nil nil)
+ (make-decoded-time :day 2))
+ '(0 0 0 1 1 2009 nil nil nil))))
+
+;;; time-date-tests.el ends here
diff --git a/test/lisp/calendar/todo-mode-resources/todo-test-1.todo b/test/lisp/calendar/todo-mode-resources/todo-test-1.todo
index 598d487cad9..2375772fbe7 100644
--- a/test/lisp/calendar/todo-mode-resources/todo-test-1.todo
+++ b/test/lisp/calendar/todo-mode-resources/todo-test-1.todo
@@ -1,8 +1,8 @@
-(("testcat1" . [2 0 2 1]) ("testcat2" . [3 0 1 1]) ("testcat3" . [0 0 0 0]))
+(("testcat1" . [2 0 2 1]) ("testcat2" . [3 0 1 1]) ("testcat3" . [0 0 0 0]) ("testcat4" . [1 0 0 0]))
--==-- testcat1
[May 29, 2017] testcat1 item3
- has more than one line
- to test item highlighting
+ has more than one line
+ to test item highlighting
[Jul 3, 2017] testcat1 item4
==--== DONE
@@ -18,3 +18,7 @@
--==-- testcat3
==--== DONE
+--==-- testcat4
+[Jan 1, 2020] testcat4 item1
+
+==--== DONE
diff --git a/test/lisp/calendar/todo-mode-tests.el b/test/lisp/calendar/todo-mode-tests.el
index 66ddbbcc964..95855d1e639 100644
--- a/test/lisp/calendar/todo-mode-tests.el
+++ b/test/lisp/calendar/todo-mode-tests.el
@@ -1,6 +1,6 @@
;;; todo-mode-tests.el --- tests for todo-mode.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2017 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2022 Free Software Foundation, Inc.
;; Author: Stephen Berman <stephen.berman@gmx.net>
;; Keywords: calendar
@@ -25,45 +25,36 @@
;;; Code:
(require 'ert)
+(require 'ert-x)
(require 'todo-mode)
-(defvar todo-test-data-dir
- (file-truename
- (expand-file-name "todo-mode-resources/"
- (file-name-directory (or load-file-name
- buffer-file-name))))
- "Base directory of todo-mode.el test data files.")
-
-(defvar todo-test-file-1 (expand-file-name "todo-test-1.todo"
- todo-test-data-dir)
+(defvar todo-test-file-1 (ert-resource-file "todo-test-1.todo")
"Todo mode test file.")
-(defvar todo-test-archive-1 (expand-file-name "todo-test-1.toda"
- todo-test-data-dir)
+(defvar todo-test-archive-1 (ert-resource-file "todo-test-1.toda")
"Todo Archive mode test file.")
(defmacro with-todo-test (&rest body)
- "Set up an isolated todo-mode test environment."
+ "Set up an isolated `todo-mode' test environment."
(declare (debug (body)))
- `(let* ((todo-test-home (make-temp-file "todo-test-home-" t))
- ;; Since we change HOME, clear this to avoid a conflict
- ;; e.g. if Emacs runs within the user's home directory.
- (abbreviated-home-dir nil)
- (process-environment (cons (format "HOME=%s" todo-test-home)
- process-environment))
- (todo-directory todo-test-data-dir)
- (todo-default-todo-file (todo-short-file-name
- (car (funcall todo-files-function)))))
- (unwind-protect
- (progn ,@body)
- ;; Restore pre-test-run state of test files.
- (dolist (f (directory-files todo-directory))
- (let ((buf (get-file-buffer f)))
- (when buf
- (with-current-buffer buf
- (restore-buffer-modified-p nil)
- (kill-buffer)))))
- (delete-directory todo-test-home t))))
+ `(ert-with-temp-directory todo-test-home
+ (let* (;; Since we change HOME, clear this to avoid a conflict
+ ;; e.g. if Emacs runs within the user's home directory.
+ (abbreviated-home-dir nil)
+ (process-environment (cons (format "HOME=%s" todo-test-home)
+ process-environment))
+ (todo-directory (ert-resource-directory))
+ (todo-default-todo-file (todo-short-file-name
+ (car (funcall todo-files-function)))))
+ (unwind-protect
+ (progn ,@body)
+ ;; Restore pre-test-run state of test files.
+ (dolist (f (directory-files todo-directory))
+ (let ((buf (get-file-buffer f)))
+ (when buf
+ (with-current-buffer buf
+ (restore-buffer-modified-p nil)
+ (kill-buffer)))))))))
(defun todo-test--show (num &optional archive)
"Display category NUM of test todo file.
@@ -384,7 +375,7 @@ priority and the done item should be the first done item."
(ert-deftest todo-test-move-item05 () ; bug#27609
"Test moving multiple todo and done items to another category.
Both types of item should be moved en bloc to the new category,
-and the the top todo item should have the provided priority and
+and the top todo item should have the provided priority and
the top done item should be the first done item."
(with-todo-test
(todo-test--show 1)
@@ -413,8 +404,15 @@ the top done item should be the first done item."
(should (todo-done-item-p))
(forward-line -1)
(should (looking-at todo-category-done))
- ;; Make sure marked items are no longer in first category.
- (todo-backward-category)
+ ;; Make sure marked items are no longer in first category. Since
+ ;; cat1 now contains no todo or done items but does have archived
+ ;; items, todo-backward-category would skip it by default, so
+ ;; prevent this. (FIXME: Without this let-binding,
+ ;; todo-backward-category selects the nonempty cat4 and this test
+ ;; fails as expected when run interactively but not in a batch
+ ;; run -- why?)
+ (let (todo-skip-archived-categories)
+ (todo-backward-category))
(should (eq (point-min) (point-max))) ; All todo items were moved.
;; This passes when run interactively but fails in a batch run:
;; the message is displayed but (current-message) evaluates to
@@ -461,7 +459,7 @@ the top done item should be the first done item."
todo-date-pattern
"\\( " diary-time-regexp "\\)?"
(regexp-quote todo-nondiary-end) "?")
- (line-end-position) t)
+ (pos-eol) t)
(forward-char)
(point)))
(start1 (save-excursion (funcall find-start)))
@@ -561,16 +559,17 @@ source file is different."
;; Headers in the todo file are still hidden.
(should (equal (overlay-get (todo-get-overlay 'header) 'display) "")))))
-(defun todo-test--insert-item (item &optional priority)
+(defun todo-test--insert-item (item &optional priority
+ _arg diary-type date-type time where)
"Insert string ITEM into current category with priority PRIORITY.
-Use defaults for all other item insertion parameters. This
-provides a noninteractive API for todo-insert-item for use in
-automatic testing."
+The remaining arguments (except _ARG, which is ignored) specify
+item insertion parameters. This provides a noninteractive API
+for todo-insert-item for use in automatic testing."
(cl-letf (((symbol-function 'read-from-minibuffer)
- (lambda (_prompt) item))
+ (lambda (_prompt &rest _) item))
((symbol-function 'read-number) ; For todo-set-item-priority
(lambda (_prompt &optional _default) (or priority 1))))
- (todo-insert-item--basic)))
+ (todo-insert-item--basic nil diary-type date-type time where)))
(ert-deftest todo-test-toggle-item-header07 () ; bug#27609
"Test display of hidden item header under todo-insert-item."
@@ -581,6 +580,359 @@ automatic testing."
(todo-test--insert-item item 1)
(should (equal (overlay-get (todo-get-overlay 'header) 'display) "")))))
+(defun todo-test--done-items-separator (&optional eol)
+ "Set up test of command interaction with done items separator.
+With non-nil argument EOL, return the position at the end of the
+separator, otherwise, return the position at the beginning."
+ (todo-test--show 1)
+ (goto-char (point-max))
+ ;; See comment about recentering in todo-test-raise-lower-priority.
+ (set-window-buffer nil (current-buffer))
+ (todo-toggle-view-done-items)
+ ;; FIXME: Point should now be on the first done item, and in batch
+ ;; testing it is, so we have to move back one line to the done items
+ ;; separator; but for some reason, in the graphical test
+ ;; environment, it stays on the last empty line of the todo items
+ ;; section, so there we have to advance one character to the done
+ ;; items separator.
+ (if (display-graphic-p)
+ (forward-char)
+ (forward-line -1))
+ (if eol (forward-char)))
+
+(ert-deftest todo-test-done-items-separator01-bol () ; bug#32343
+ "Test item copying and here insertion at BOL of separator.
+Both should be user errors."
+ (with-todo-test
+ (todo-test--done-items-separator)
+ (let* ((copy-err "Item copying is not valid here")
+ (here-err "Item insertion is not valid here")
+ (insert-item-test (lambda (where)
+ (should-error (todo-insert-item--basic
+ nil nil nil nil where)))))
+ (should (string= copy-err (cadr (funcall insert-item-test 'copy))))
+ (should (string= here-err (cadr (funcall insert-item-test 'here)))))))
+
+(ert-deftest todo-test-done-items-separator01-eol () ; bug#32343
+ "Test item copying and here insertion at EOL of separator.
+Both should be user errors."
+ (with-todo-test
+ (todo-test--done-items-separator 'eol)
+ (let* ((copy-err "Item copying is not valid here")
+ (here-err "Item insertion is not valid here")
+ (insert-item-test (lambda (where)
+ (should-error (todo-insert-item--basic
+ nil nil nil nil where)))))
+ (should (string= copy-err (cadr (funcall insert-item-test 'copy))))
+ (should (string= here-err (cadr (funcall insert-item-test 'here)))))))
+
+(ert-deftest todo-test-done-items-separator02-bol () ; bug#32343
+ "Test item editing commands at BOL of done items separator.
+They should all be noops."
+ (with-todo-test
+ (todo-test--done-items-separator)
+ (should-not (todo-item-done))
+ (should-not (todo-raise-item-priority))
+ (should-not (todo-lower-item-priority))
+ (should-not (called-interactively-p #'todo-set-item-priority))
+ (should-not (called-interactively-p #'todo-move-item))
+ (should-not (called-interactively-p #'todo-delete-item))
+ (should-not (called-interactively-p #'todo-edit-item))))
+
+(ert-deftest todo-test-done-items-separator02-eol () ; bug#32343
+ "Test item editing command at EOL of done items separator.
+They should all be noops."
+ (with-todo-test
+ (todo-test--done-items-separator 'eol)
+ (should-not (todo-item-done))
+ (should-not (todo-raise-item-priority))
+ (should-not (todo-lower-item-priority))
+ (should-not (called-interactively-p #'todo-set-item-priority))
+ (should-not (called-interactively-p #'todo-move-item))
+ (should-not (called-interactively-p #'todo-delete-item))
+ (should-not (called-interactively-p #'todo-edit-item))))
+
+(ert-deftest todo-test-done-items-separator03-bol () ; bug#32343
+ "Test item marking at BOL of done items separator.
+This should be a noop, adding no marks to the category."
+ (with-todo-test
+ (todo-test--done-items-separator)
+ (call-interactively #'todo-toggle-mark-item)
+ (should-not (assoc (todo-current-category) todo-categories-with-marks))))
+
+(ert-deftest todo-test-done-items-separator03-eol () ; bug#32343
+ "Test item marking at EOL of done items separator.
+This should be a noop, adding no marks to the category."
+ (with-todo-test
+ (todo-test--done-items-separator 'eol)
+ (call-interactively #'todo-toggle-mark-item)
+ (should-not (assoc (todo-current-category) todo-categories-with-marks))))
+
+(ert-deftest todo-test-done-items-separator04-bol () ; bug#32343
+ "Test moving to previous item from BOL of done items separator.
+This should move point to the last not done todo item."
+ (with-todo-test
+ (todo-test--done-items-separator)
+ (let ((last-item (save-excursion
+ ;; Move to empty line after last todo item.
+ (forward-line -1)
+ (todo-previous-item)
+ (todo-item-string))))
+ (should (string= last-item (save-excursion
+ (todo-previous-item)
+ (todo-item-string)))))))
+
+(ert-deftest todo-test-done-items-separator04-eol () ; bug#32343
+ "Test moving to previous item from EOL of done items separator.
+This should move point to the last not done todo item."
+ (with-todo-test
+ (todo-test--done-items-separator 'eol)
+ (let ((last-item (save-excursion
+ ;; Move to empty line after last todo item.
+ (forward-line -1)
+ (todo-previous-item)
+ (todo-item-string))))
+ (should (string= last-item (save-excursion
+ (todo-previous-item)
+ (todo-item-string)))))))
+
+(ert-deftest todo-test-done-items-separator05-bol () ; bug#32343
+ "Test moving to next item from BOL of done items separator.
+This should move point to the first done todo item."
+ (with-todo-test
+ (todo-test--done-items-separator)
+ (let ((first-done (save-excursion
+ ;; Move to empty line after last todo item.
+ (forward-line -1)
+ (todo-next-item)
+ (todo-item-string))))
+ (should (string= first-done (save-excursion
+ (todo-next-item)
+ (todo-item-string)))))))
+
+(ert-deftest todo-test-done-items-separator05-eol () ; bug#32343
+ "Test moving to next item from EOL of done items separator.
+This should move point to the first done todo item."
+ (with-todo-test
+ (todo-test--done-items-separator 'eol)
+ (let ((first-done (save-excursion
+ ;; Move to empty line after last todo item.
+ (forward-line -1)
+ (todo-next-item)
+ (todo-item-string))))
+ (should (string= first-done (save-excursion
+ (todo-next-item)
+ (todo-item-string)))))))
+
+;; Item highlighting uses hl-line-mode, which enables highlighting in
+;; post-command-hook. For some reason, in the test environment, the
+;; hook function is not automatically run, so after enabling item
+;; highlighting, use ert-simulate-command around the next command,
+;; which explicitly runs the hook function.
+(ert-deftest todo-test-done-items-separator06-bol () ; bug#32343
+ "Test enabling item highlighting at BOL of done items separator.
+Subsequently moving to an item should show it highlighted."
+ (with-todo-test
+ (todo-test--done-items-separator)
+ (call-interactively #'todo-toggle-item-highlighting)
+ (ert-simulate-command '(todo-previous-item))
+ (should (eq 'hl-line (get-char-property (point) 'face)))))
+
+(ert-deftest todo-test-done-items-separator06-eol () ; bug#32343
+ "Test enabling item highlighting at EOL of done items separator.
+Subsequently moving to an item should show it highlighted."
+ (with-todo-test
+ (todo-test--done-items-separator 'eol)
+ (todo-toggle-item-highlighting)
+ (forward-line -1)
+ (ert-simulate-command '(todo-previous-item))
+ (should (eq 'hl-line (get-char-property (point) 'face)))))
+
+(ert-deftest todo-test-done-items-separator07 () ; bug#32343
+ "Test item highlighting when crossing done items separator.
+The highlighting should remain enabled."
+ (with-todo-test
+ (todo-test--done-items-separator)
+ (todo-previous-item)
+ (todo-toggle-item-highlighting)
+ (todo-next-item) ; Now on empty line above separator.
+ (forward-line) ; Now on separator.
+ (ert-simulate-command '(forward-line)) ; Now on first done item.
+ (should (eq 'hl-line (get-char-property (point) 'face)))))
+
+(ert-deftest todo-test-current-file-in-edit-mode () ; bug#32437
+ "Test the value of todo-current-todo-file in todo-edit-mode."
+ (with-todo-test
+ (todo-test--show 1)
+ ;; The preceding calls todo-mode but does not run pre-command-hook
+ ;; in the test environment, thus failing to set
+ ;; todo-global-current-todo-file, which is needed for the test
+ ;; after todo-edit-item--text. So force the hook function to run.
+ (ert-simulate-command '(todo-mode))
+ (let ((curfile todo-current-todo-file))
+ (should (equal curfile todo-test-file-1))
+ (todo-edit-item--text 'multiline)
+ (should (equal todo-current-todo-file curfile))
+ (todo-edit-quit)
+ (todo-edit-file)
+ (should (equal todo-current-todo-file curfile))
+ (todo-edit-quit))
+ (todo-find-archive)
+ (let ((curfile todo-current-todo-file))
+ (should (equal curfile todo-test-archive-1))
+ (todo-edit-file)
+ (should (equal todo-current-todo-file curfile)))))
+
+(ert-deftest todo-test-edit-quit () ; bug#32437
+ "Test result of exiting todo-edit-mode on a whole file.
+Exiting should return to the same todo-mode or todo-archive-mode
+buffer from which the editing command was invoked."
+ (with-todo-test
+ (todo-test--show 1)
+ (let ((buf (current-buffer)))
+ (todo-edit-file)
+ (todo-edit-quit)
+ (should (eq (current-buffer) buf))
+ (should (eq major-mode 'todo-mode))
+ (todo-find-archive)
+ (let ((buf (current-buffer)))
+ (todo-edit-file)
+ (todo-edit-quit)
+ (should (eq (current-buffer) buf))
+ (should (eq major-mode 'todo-archive-mode))))))
+
+(defun todo-test--add-file (file cat)
+ "Add file FILE with category CAT to todo-files and show it.
+This provides a noninteractive API for todo-add-file for use in
+automatic testing."
+ (let ((file0 (ert-resource-file (concat file ".todo")))
+ todo-add-item-if-new-category) ; Don't need an item in cat.
+ (cl-letf (((symbol-function 'todo-read-file-name)
+ (lambda (_prompt) file0))
+ ((symbol-function 'todo-read-category)
+ (lambda (_prompt &optional _match-type _file) (cons cat file0))))
+ (call-interactively 'todo-add-file) ; Interactive to call todo-show.
+ (todo-add-category file0 cat))))
+
+(defun todo-test--delete-file ()
+ "Delete current todo file without prompting."
+ (cl-letf (((symbol-function 'yes-or-no-p)
+ (lambda (_prompt) t)))
+ (todo-delete-file)))
+
+(ert-deftest todo-test-add-and-delete-file () ; bug#32627
+ "Test adding a new todo file and then deleting it.
+Calling todo-show should display the last current todo file, not
+necessarily the new file. After deleting the new file, todo-show
+should display the previously current (or default) todo file."
+ (with-todo-test
+ (todo-show)
+ (should (equal todo-current-todo-file todo-test-file-1))
+ (let* ((file (concat todo-directory "todo-test-2.todo"))
+ (file-nb (file-name-base file))
+ (cat "cat21"))
+ (todo-test--add-file file-nb cat) ; Add new file and show it.
+ (should (equal todo-current-todo-file file))
+ (todo-quit) ; Quitting todo-mode displays previous buffer.
+ (should (equal todo-current-todo-file todo-test-file-1))
+ (switch-to-buffer "*scratch*")
+ (todo-show) ; Show the last current todo-file (not the new one).
+ (should (equal todo-current-todo-file todo-test-file-1))
+ (switch-to-buffer (get-file-buffer file)) ; Back to new file.
+ (should (equal todo-current-todo-file file))
+ (todo-test--delete-file)
+ (todo-show) ; Back to old file.
+ (should (equal todo-current-todo-file todo-test-file-1))
+ (delete-file (concat file "~")))))
+
+(ert-deftest todo-test-edit-item-date-month () ; bug#42976 #3 and #4
+ "Test incrementing and decrementing the month of an item's date.
+If the change in month crosses a year boundary, the year of the
+item's date should be adjusted accordingly."
+ (with-todo-test
+ (todo-test--show 4)
+ (let ((current-prefix-arg t) ; For todo-edit-item--header.
+ (get-date (lambda ()
+ (save-excursion
+ (todo-date-string-matcher (pos-eol))
+ (buffer-substring-no-properties (match-beginning 1)
+ (match-end 0))))))
+ (should (equal (funcall get-date) "Jan 1, 2020"))
+ (todo-edit-item--header 'month 0)
+ (should (equal (funcall get-date) "Jan 1, 2020"))
+ (todo-edit-item--header 'month 1)
+ (should (equal (funcall get-date) "Feb 1, 2020"))
+ (todo-edit-item--header 'month -1)
+ (should (equal (funcall get-date) "Jan 1, 2020"))
+ (todo-edit-item--header 'month -1)
+ (should (equal (funcall get-date) "Dec 1, 2019"))
+ (todo-edit-item--header 'month 1)
+ (should (equal (funcall get-date) "Jan 1, 2020"))
+ (todo-edit-item--header 'month 12)
+ (should (equal (funcall get-date) "Jan 1, 2021"))
+ (todo-edit-item--header 'month -12)
+ (should (equal (funcall get-date) "Jan 1, 2020"))
+ (todo-edit-item--header 'month -13)
+ (should (equal (funcall get-date) "Dec 1, 2018"))
+ (todo-edit-item--header 'month 7)
+ (should (equal (funcall get-date) "Jul 1, 2019"))
+ (todo-edit-item--header 'month 6)
+ (should (equal (funcall get-date) "Jan 1, 2020"))
+ (todo-edit-item--header 'month 23)
+ (should (equal (funcall get-date) "Dec 1, 2021"))
+ (todo-edit-item--header 'month -23)
+ (should (equal (funcall get-date) "Jan 1, 2020"))
+ (todo-edit-item--header 'month 24)
+ (should (equal (funcall get-date) "Jan 1, 2022"))
+ (todo-edit-item--header 'month -24)
+ (should (equal (funcall get-date) "Jan 1, 2020"))
+ (todo-edit-item--header 'month 25)
+ (should (equal (funcall get-date) "Feb 1, 2022"))
+ (todo-edit-item--header 'month -25)
+ (should (equal (funcall get-date) "Jan 1, 2020")))))
+
+(ert-deftest todo-test-multiline-item-indentation-1 ()
+ "Test inserting a multine item containing a hard line break.
+After insertion the second line of the item should begin with a
+tab character."
+ (with-todo-test
+ (let* ((item0 "Test inserting a multine item")
+ (item1 "containing a hard line break.")
+ (item (concat item0 "\n" item1)))
+ (todo-test--show 1)
+ (todo-test--insert-item item 1)
+ (re-search-forward (concat todo-date-string-start todo-date-pattern
+ (regexp-quote todo-nondiary-end) " ")
+ (pos-eol) t)
+ (should (looking-at (regexp-quote (concat item0 "\n\t" item1)))))))
+
+(ert-deftest todo-test-multiline-item-indentation-2 () ; bug#43068
+ "Test editing an item by adding text on a new line.
+After quitting todo-edit-mode the second line of the item should
+begin with a tab character."
+ (with-todo-test
+ (todo-test--show 2)
+ (let* ((item0 (todo-item-string))
+ (item1 "Second line."))
+ (todo-edit-item--text 'multiline)
+ (insert (concat "\n" item1))
+ (todo-edit-quit)
+ (goto-char (pos-bol))
+ (should (looking-at (regexp-quote (concat item0 "\n\t" item1)))))))
+
+(ert-deftest todo-test-multiline-item-indentation-3 ()
+ "Test adding an unindented new line to an item using todo-edit-file.
+Attempting to quit todo-edit-mode should signal a user-error,
+since all non-initial item lines must begin with whitespace."
+ (with-todo-test
+ (todo-test--show 2)
+ (let* ((item0 (todo-item-string))
+ (item1 "Second line."))
+ (todo-edit-file)
+ (should (looking-at (regexp-quote item0)))
+ (goto-char (pos-eol))
+ (insert (concat "\n" item1))
+ (should-error (todo-edit-quit) :type 'user-error))))
(provide 'todo-mode-tests)
;;; todo-mode-tests.el ends here
diff --git a/test/lisp/cedet/cedet-files-tests.el b/test/lisp/cedet/cedet-files-tests.el
new file mode 100644
index 00000000000..daaf3edfc4e
--- /dev/null
+++ b/test/lisp/cedet/cedet-files-tests.el
@@ -0,0 +1,51 @@
+;;; cedet-files-tests.el --- Tests for cedet-files.el -*- lexical-binding:t -*-
+
+;; Copyright (C) 2008-2022 Free Software Foundation, Inc.
+
+;; Author: Eric M. Ludlam <zappo@gnu.org>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Moved here from test/manual/cedet/cedet-utests.el
+
+;;; Code:
+
+(require 'ert)
+(require 'cedet-files)
+
+(defvar cedet-files-utest-list
+ '(("/home/me/src/myproj/src/foo.c" . "!home!me!src!myproj!src!foo.c")
+ ("c:/work/myproj/foo.el" . "!drive_c!work!myproj!foo.el")
+ ("//windows/proj/foo.java" . "!!windows!proj!foo.java")
+ ("/home/me/proj!bang/foo.c" . "!home!me!proj!!bang!foo.c"))
+ "List of file names to test.
+Each entry is a cons cell of (FNAME . CONVERTED)
+where FNAME is some file name, and CONVERTED is what it should be
+converted into.")
+
+(ert-deftest cedet-files-utest ()
+ "Test some file name conversions."
+ (dolist (FT cedet-files-utest-list)
+ (let ((dir->file (cedet-directory-name-to-file-name (car FT) t))
+ (file->dir (cedet-file-name-to-directory-name (cdr FT) t)))
+ (should (string= (cdr FT) dir->file))
+ (should (string= file->dir (car FT))))))
+
+(provide 'cedet-files-tests)
+
+;;; cedet-files-tests.el ends here
diff --git a/test/lisp/cedet/semantic-utest-c.el b/test/lisp/cedet/semantic-utest-c.el
new file mode 100644
index 00000000000..87d754968f9
--- /dev/null
+++ b/test/lisp/cedet/semantic-utest-c.el
@@ -0,0 +1,180 @@
+;;; semantic-utest-c.el --- C based parsing tests. -*- lexical-binding:t -*-
+
+;; Copyright (C) 2008-2022 Free Software Foundation, Inc.
+
+;; Author: Eric M. Ludlam <zappo@gnu.org>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+;;
+;; Run some C based parsing tests.
+
+(require 'ert)
+(require 'semantic)
+
+(defvar semantic-utest-c-comparisons
+ '( ("testsppreplace.c" . "testsppreplaced.c")
+ )
+ "List of files to parse and compare against each other.")
+
+(defvar cedet-utest-directory
+ (let* ((C (file-name-directory (locate-library "cedet")))
+ (D (expand-file-name "../../test/manual/cedet/" C)))
+ D)
+ "Location of test files for this test suite.")
+
+(defvar semantic-utest-c-test-directory (expand-file-name "tests" cedet-utest-directory)
+ "Location of test files.")
+
+(defvar semantic-lex-c-nested-namespace-ignore-second)
+
+;;; Code:
+(ert-deftest semantic-test-c-preprocessor-simulation ()
+ "Run parsing test for C from the test directory."
+ :tags '(:expensive-test)
+ (semantic-mode 1)
+ (dolist (fp semantic-utest-c-comparisons)
+ (let* ((semantic-lex-c-nested-namespace-ignore-second nil)
+ (tags-actual
+ (with-current-buffer
+ (find-file-noselect (expand-file-name (car fp) semantic-utest-c-test-directory))
+ (semantic-clear-toplevel-cache)
+ (semantic-fetch-tags)))
+ (tags-expected
+ (with-current-buffer (find-file-noselect (expand-file-name (cdr fp) semantic-utest-c-test-directory))
+ (semantic-clear-toplevel-cache)
+ (semantic-fetch-tags))))
+ (when (or (not tags-expected) (not tags-actual))
+ (message "Tried to find test files in: %s" semantic-utest-c-test-directory)
+ (error "Failed: Discovered no tags in test files or test file not found"))
+
+ ;; Now that we have the tags, compare them for SPP accuracy.
+ (dolist (tag tags-actual)
+ (if (and (semantic-tag-of-class-p tag 'variable)
+ (semantic-tag-variable-constant-p tag))
+ nil ; skip the macros.
+
+ (if (semantic-tag-similar-with-subtags-p tag (car tags-expected))
+ (setq tags-expected (cdr tags-expected))
+ (with-mode-local c-mode
+ (should nil) ;; this is a fail condition
+ (message "Error: Found: >> %s << Expected: >> %s <<"
+ (semantic-format-tag-prototype tag nil t)
+ (semantic-format-tag-prototype (car tags-expected) nil t)
+ )))
+ ))
+ )))
+
+(require 'semantic/bovine/gcc)
+
+;; Example output of "gcc -v"
+(defvar semantic-gcc-test-strings
+ '(;; My old box:
+ "Reading specs from /usr/lib/gcc-lib/i386-redhat-linux/3.2.2/specs
+Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --disable-checking --with-system-zlib --enable-__cxa_atexit --host=i386-redhat-linux
+Thread model: posix
+gcc version 3.2.2 20030222 (Red Hat Linux 3.2.2-5)"
+ ;; Alex Ott:
+ "Using built-in specs.
+Target: i486-linux-gnu
+Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.3.1-9ubuntu1' --with-bugurl=file:///usr/share/doc/gcc-4.3/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --enable-nls --with-gxx-include-dir=/usr/include/c++/4.3 --program-suffix=-4.3 --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --enable-mpfr --enable-targets=all --enable-checking=release --build=i486-linux-gnu --host=i486-linux-gnu --target=i486-linux-gnu
+Thread model: posix
+gcc version 4.3.1 (Ubuntu 4.3.1-9ubuntu1)"
+ ;; My Debian box:
+ "Using built-in specs.
+Target: x86_64-unknown-linux-gnu
+Configured with: ../../../sources/gcc/configure --prefix=/usr/local/glibc-2.3.6/x86_64/apps/gcc-4.2.3 --with-gmp=/usr/local/gcc/gmp --with-mpfr=/usr/local/gcc/mpfr --enable-languages=c,c++,fortran --with-as=/usr/local/glibc-2.3.6/x86_64/apps/gcc-4.2.3/bin/as --with-ld=/usr/local/glibc-2.3.6/x86_64/apps/gcc-4.2.3/bin/ld --disable-multilib
+Thread model: posix
+gcc version 4.2.3"
+ ;; My mac:
+ "Using built-in specs.
+Target: i686-apple-darwin8
+Configured with: /private/var/tmp/gcc/gcc-5341.obj~1/src/configure --disable-checking -enable-werror --prefix=/usr --mandir=/share/man --enable-languages=c,objc,c++,obj-c++ --program-transform-name=/^[cg][^.-]*$/s/$/-4.0/ --with-gxx-include-dir=/include/c++/4.0.0 --with-slibdir=/usr/lib --build=powerpc-apple-darwin8 --with-arch=pentium-m --with-tune=prescott --program-prefix= --host=i686-apple-darwin8 --target=i686-apple-darwin8
+Thread model: posix
+gcc version 4.0.1 (Apple Computer, Inc. build 5341)"
+ ;; Ubuntu Intrepid
+ "Using built-in specs.
+Target: x86_64-linux-gnu
+Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.3.2-1ubuntu12' --with-bugurl=file:///usr/share/doc/gcc-4.3/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --enable-nls --with-gxx-include-dir=/usr/include/c++/4.3 --program-suffix=-4.3 --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --enable-mpfr --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
+Thread model: posix
+gcc version 4.3.2 (Ubuntu 4.3.2-1ubuntu12)"
+ ;; Red Hat EL4
+ "Reading specs from /usr/lib/gcc/x86_64-redhat-linux/3.4.6/specs
+Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --disable-checking --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-java-awt=gtk --host=x86_64-redhat-linux
+Thread model: posix
+gcc version 3.4.6 20060404 (Red Hat 3.4.6-10)"
+ ;; Red Hat EL5
+ "Using built-in specs.
+Target: x86_64-redhat-linux
+Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-libgcj-multifile --enable-languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk --disable-dssi --enable-plugin --with-java-home=/usr/lib/jvm/java-1.4.2-gcj-1.4.2.0/jre --with-cpu=generic --host=x86_64-redhat-linux
+Thread model: posix
+gcc version 4.1.2 20080704 (Red Hat 4.1.2-44)"
+ ;; David Engster's German gcc on Ubuntu 4.3
+ "Es werden eingebaute Spezifikationen verwendet.
+Ziel: i486-linux-gnu
+Konfiguriert mit: ../src/configure -v --with-pkgversion='Ubuntu 4.3.2-1ubuntu12' --with-bugurl=file:///usr/share/doc/gcc-4.3/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --enable-nls --with-gxx-include-dir=/usr/include/c++/4.3 --program-suffix=-4.3 --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --enable-mpfr --enable-targets=all --enable-checking=release --build=i486-linux-gnu --host=i486-linux-gnu --target=i486-linux-gnu
+Thread-Modell: posix
+gcc-Version 4.3.2 (Ubuntu 4.3.2-1ubuntu12)"
+ ;; Damien Deville BSD
+ "Using built-in specs.
+Target: i386-undermydesk-freebsd
+Configured with: FreeBSD/i386 system compiler
+Thread model: posix
+gcc version 4.2.1 20070719 [FreeBSD]"
+ )
+ "A bunch of sample gcc -v outputs from different machines.")
+
+(defvar semantic-gcc-test-strings-fail
+ '(;; A really old Solaris box I found
+ "Reading specs from /usr/local/gcc-2.95.2/lib/gcc-lib/sparc-sun-solaris2.6/2.95.2/specs
+gcc version 2.95.2 19991024 (release)"
+ )
+ "A bunch of sample gcc -v outputs that fail to provide the info we want.")
+
+(ert-deftest semantic-test-gcc-output-parser ()
+ "Test the output parser against some collected strings."
+ (dolist (S semantic-gcc-test-strings)
+ (let* ((fields (semantic-gcc-fields S))
+ (v (cdr (assoc 'version fields)))
+ (h (or (cdr (assoc 'target fields))
+ (cdr (assoc '--target fields))
+ (cdr (assoc '--host fields))))
+ (p (cdr (assoc '--prefix fields)))
+ )
+ ;; No longer test for prefixes.
+ (when (not (and v h))
+ (let ((strs (split-string S "\n")))
+ (message "Test failed on %S\nV H P:\n%S %S %S" (car strs) v h p)
+ ))
+ (should (and v h))
+ ))
+ (dolist (S semantic-gcc-test-strings-fail)
+ (let* ((fields (semantic-gcc-fields S))
+ (v (cdr (assoc 'version fields)))
+ (h (or (cdr (assoc '--host fields))
+ (cdr (assoc 'target fields))))
+ (p (cdr (assoc '--prefix fields)))
+ )
+ ;; negative test
+ (should-not (and v h p))
+ ))
+ )
+
+
+(provide 'semantic-utest-c)
+
+;;; semantic-utest-c.el ends here
diff --git a/test/lisp/cedet/semantic-utest-ia-resources/test.mk b/test/lisp/cedet/semantic-utest-ia-resources/test.mk
new file mode 100644
index 00000000000..edea97e7b98
--- /dev/null
+++ b/test/lisp/cedet/semantic-utest-ia-resources/test.mk
@@ -0,0 +1,18 @@
+# A Test Makefile. -*-makefile-*-
+
+# This test is for a file in this test directory. Just a random one.
+FILES=testdoub # -1-
+# #1# ("testdoublens.cpp" "testdoublens.hpp" )
+
+all: optional
+
+# This one completes on a variable name.
+optional: $FIL # -2-
+ # #2# ("FILES")
+ compile $@
+
+notoptional: opt # -3-
+ # #3# ("optional")
+ echo "Done."
+
+#end
diff --git a/test/lisp/cedet/semantic-utest-ia-resources/test.srt b/test/lisp/cedet/semantic-utest-ia-resources/test.srt
new file mode 100644
index 00000000000..46f14d8480f
--- /dev/null
+++ b/test/lisp/cedet/semantic-utest-ia-resources/test.srt
@@ -0,0 +1,64 @@
+;; test.srt --- unit test support file for semantic-utest-ia
+
+;; Copyright (C) 2008-2022 Free Software Foundation, Inc.
+
+;; Author: Eric M. Ludlam <zappo@gnu.org>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+;;
+
+set mode "c++-mode"
+set escape_start "{{"
+set escape_end "}}"
+
+context file
+
+template class :blank
+"A test template for emacs lisp"
+----
+----
+
+template classic :blank
+"A test template for emacs lisp"
+----
+----
+
+template variable :blank
+"A test template for emacs lisp"
+----
+----
+
+template function :blank
+"A test template for emacs lisp"
+----
+----
+
+template testarea :blank
+"A test template for emacs lisp"
+----
+{{<A:cla}} -1-
+ }} #1# ( "class" "classic" )
+ {{^}}
+
+{{/A}}
+----
+
+;; This is a bad hack - In order for the text to parse, but also get a completion
+;; moniker into the right spot, we need to pretend a comment is the same as the
+;; escape_end.
+;; Local variables:
+;; comment-start-skip: "}}"
+;; End:
diff --git a/test/lisp/cedet/semantic-utest-ia-resources/test.texi b/test/lisp/cedet/semantic-utest-ia-resources/test.texi
new file mode 100644
index 00000000000..37d303c8b48
--- /dev/null
+++ b/test/lisp/cedet/semantic-utest-ia-resources/test.texi
@@ -0,0 +1,40 @@
+\input texinfo
+@setfilename test.info
+@set TITLE TEST
+@set AUTHOR Eric Ludlam
+@settitle @value{TITLE}
+
+@ifinfo
+@format
+START-INFO-DIR-ENTRY
+* test: (test). TEST
+END-INFO-DIR-ENTRY
+@end format
+@end ifinfo
+
+@titlepage
+@sp 10
+@center @titlefont{test}
+@vskip 0pt plus 1 fill
+Copyright @copyright{} 2015 Eric Ludlam
+@end titlepage
+
+@node Top
+@top @value{TITLE}
+
+This is a simple manual filled with stuff that should test completion in texinfo mode.
+
+@m@c -1-
+@c #1# ( "@majorheading" "@macro" "@menu" "@multitable" )
+
+@menu
+* Index::
+@end menu
+
+
+@node Index
+@chapter Index
+
+@contents
+
+@bye
diff --git a/test/manual/cedet/tests/testdoublens.cpp b/test/lisp/cedet/semantic-utest-ia-resources/testdoublens.cpp
index c9a2f99f545..54941fa974a 100644
--- a/test/manual/cedet/tests/testdoublens.cpp
+++ b/test/lisp/cedet/semantic-utest-ia-resources/testdoublens.cpp
@@ -1,8 +1,8 @@
// testdoublens.cpp --- semantic-ia-utest completion engine unit tests
-// Copyright (C) 2008-2017 Free Software Foundation, Inc.
+// Copyright (C) 2008-2022 Free Software Foundation, Inc.
-// Author: Eric M. Ludlam <eric@siege-engine.com>
+// Author: Eric M. Ludlam <zappo@gnu.org>
// This file is part of GNU Emacs.
@@ -39,12 +39,27 @@ namespace Name1 {
return 0;
}
- void Foo::publishStuff(int /* a */, int /* b */) // ^2^
+ void Foo::publishStuff(int a, int b) // ^2^
{
+ int foo = a;
+ int bar = b;
}
- void Foo::sendStuff(int /* a */, int /* b */) // ^3^
+ // Test polymorphism on arg types. Note that order is
+ // mixed to maximize failure cases
+ void Foo::publishStuff(char a, char b) // ^4^
{
+ int foo = a;
+ int bar = b;
+ }
+
+ void Foo::sendStuff(int a, int b) // ^3^
+ {
+ int foo = a;
+ int bar = b;
+
+ Foo::publishStuff(1,2)
+
}
} // namespace Name2
@@ -163,3 +178,37 @@ namespace d {
} // namespace f
} // namespace d
+
+// Fully qualified const struct function arguments
+class ContainsStruct
+{
+ struct TheStruct
+ {
+ int memberOne;
+ int memberTwo;
+ };
+};
+
+void someFunc(const struct ContainsStruct::TheStruct *foo)
+{
+ foo->// -9-
+ // #9# ("memberOne" "memberTwo")
+}
+
+// Class with structure tag
+class ContainsNamedStruct
+{
+ struct _fooStruct
+ {
+ int memberOne;
+ int memberTwo;
+ } member;
+};
+
+void someOtherFunc(void)
+{
+ ContainsNamedStruct *someClass;
+ // This has to find ContainsNamedStruct::_fooStruct
+ someClass->member.// -10-
+ // #10# ("memberOne" "memberTwo")
+}
diff --git a/test/manual/cedet/tests/testdoublens.hpp b/test/lisp/cedet/semantic-utest-ia-resources/testdoublens.hpp
index 59eec741667..6157af42121 100644
--- a/test/manual/cedet/tests/testdoublens.hpp
+++ b/test/lisp/cedet/semantic-utest-ia-resources/testdoublens.hpp
@@ -1,8 +1,8 @@
// testdoublens.hpp --- Header file used in one of the Semantic tests
-// Copyright (C) 2008-2017 Free Software Foundation, Inc.
+// Copyright (C) 2008-2022 Free Software Foundation, Inc.
-// Author: Eric M. Ludlam <eric@siege-engine.com>
+// Author: Eric M. Ludlam <zappo@gnu.org>
// This file is part of GNU Emacs.
@@ -31,7 +31,9 @@ namespace Name1 {
int get();
private:
- void publishStuff(int a, int b);
+ void publishStuff(char /* a */, char /* b */);
+
+ void publishStuff(int q, int r); // Purposely different names.
void sendStuff(int a, int b);
@@ -58,7 +60,7 @@ namespace a {
class Foo
{
struct Dum {
- int diDum;
+ int diDum;
};
protected:
diff --git a/test/manual/cedet/tests/testfriends.cpp b/test/lisp/cedet/semantic-utest-ia-resources/testfriends.cpp
index 20425f93afa..f84ed5a2190 100644
--- a/test/manual/cedet/tests/testfriends.cpp
+++ b/test/lisp/cedet/semantic-utest-ia-resources/testfriends.cpp
@@ -35,4 +35,3 @@ int B::testB() {
int B::testAB() { // %1% ( ( "testfriends.cpp" ) ( "B" "B::testAB" ) )
}
-
diff --git a/test/manual/cedet/tests/testjavacomp.java b/test/lisp/cedet/semantic-utest-ia-resources/testjavacomp.java
index 743aaca8547..10735a5aa97 100644
--- a/test/manual/cedet/tests/testjavacomp.java
+++ b/test/lisp/cedet/semantic-utest-ia-resources/testjavacomp.java
@@ -1,8 +1,8 @@
// testjavacomp.java --- Semantic unit test for Java
-// Copyright (C) 2009-2017 Free Software Foundation, Inc.
+// Copyright (C) 2009-2022 Free Software Foundation, Inc.
-// Author: Eric M. Ludlam <eric@siege-engine.com>
+// Author: Eric M. Ludlam <zappo@gnu.org>
// This file is part of GNU Emacs.
@@ -24,6 +24,10 @@ package tests.testjavacomp;
class secondClass {
private void scFuncOne() { }
public void scFuncOne() { }
+
+ int package_protected_field;
+ public int public_protected_field;
+ private int private_protected_field;
}
@@ -52,15 +56,21 @@ public class testjavacomp {
secondClass SC;
- SC.//-3-
+ SC.s//-3-
// #3# ( "scFuncOne" )
;
+ // @TODO - to make this test complete, we need an import
+ // with a package protected field that is excluded
+ // from the completion list.
+ SC.p//-4-
+ // #4# ( "package_protected_field" "public_protected_field" )
+
nestedClass NC;
// @todo - need to fix this? I don't know if this is legal java.
- NC.// - 4-
- // #4# ( "ncFuncOne" )
+ NC.// - 5-
+ // #5# ( "ncFuncOne" )
;
}
diff --git a/test/lisp/cedet/semantic-utest-ia-resources/testlocalvars.cpp b/test/lisp/cedet/semantic-utest-ia-resources/testlocalvars.cpp
new file mode 100644
index 00000000000..920022648f7
--- /dev/null
+++ b/test/lisp/cedet/semantic-utest-ia-resources/testlocalvars.cpp
@@ -0,0 +1,54 @@
+// testlocalvars.java --- Semantic unit test for Java
+
+// Copyright (C) 2009-2022 Free Software Foundation, Inc.
+
+// Author: Eric M. Ludlam <zappo@gnu.org>
+
+// This file is part of GNU Emacs.
+
+// GNU Emacs is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// GNU Emacs is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+
+class foo {
+ foo *member;
+ char anArray[10];
+};
+
+void func()
+{
+ foo local1;
+ foo* local2 = localvar.member;
+ foo* local3 = new foo();
+ foo local4[10];
+ char local5[5] = {'1','2','3','4','5'};
+ char *local6 = "12345";
+ char local7 = local.anArray[0];
+ char local8 = true ? 10 : 11 ;
+
+ // Check that all of the above was parsed
+ local//-1-
+ ; //#1# ("local1" "local2" "local3" "local4" "local5" "local6" "local7" "local8" )
+
+ local1.//-2-
+ ; //#2# ("anArray" "member")
+
+ local2->//-3-
+ ; //#3# ("anArray" "member")
+
+ local3->//-4-
+ ; //#4# ("anArray" "member")
+
+ local4[0].//-5-
+ ; //#5# ("anArray" "member")
+}
diff --git a/test/lisp/cedet/semantic-utest-ia-resources/testnsp.cpp b/test/lisp/cedet/semantic-utest-ia-resources/testnsp.cpp
new file mode 100644
index 00000000000..05f8f54afd0
--- /dev/null
+++ b/test/lisp/cedet/semantic-utest-ia-resources/testnsp.cpp
@@ -0,0 +1,122 @@
+/* testnsp.cpp --- semantic-ia-utest completion engine unit tests
+
+ Copyright (C) 2008-2022 Free Software Foundation, Inc.
+
+ Author: Eric M. Ludlam <zappo@gnu.org>
+
+ This file is part of GNU Emacs.
+
+ GNU Emacs is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ GNU Emacs is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+*/
+
+namespace nsp {
+
+ class rootclass {
+ public:
+ int fromroot() {};
+ };
+
+}
+
+namespace nsp {
+ class childclass : public rootclass {
+ public:
+ int fromchild() {};
+ };
+}
+
+void myfcn_not_in_ns (void) {
+ nsp::childclass test;
+
+ test.// -1-
+ ; // #1# ( "fromchild" "fromroot" )
+}
+
+// Test a class declared in a class, where the contents
+// are in a qualified name.
+//
+// Thanks Michael Reiher for the concise example.
+
+class AAA
+{
+public:
+ AAA();
+
+ void aaa();
+
+private:
+ class Private;
+ Private * const d;
+};
+
+class AAA::Private
+{
+ Private() : bbb(0) {
+ }
+
+ BBB* bbb;
+};
+
+void AAA::aaa()
+{
+ d->// -2-
+ ; // #2# ( "bbb" )
+}
+
+// #include files inside a namespace
+// David Engster <deng@randomsample.de>
+// See revisions 8034-8037 which implement this.
+
+namespace another {
+ #include "testdoublens.hpp"
+}
+
+void foo(void) {
+
+ another::// -3-
+ ; // #3# ( "Name1" "a" "stage3_Foo" )
+
+ another::Name1::Name2::Foo a;
+
+ a.// -4-
+ ; // #4# ( "Mumble" "get" )
+}
+
+// What happens if a type your looking for is scoped within a type,
+// but you are one level into the completion so the originating scope
+// excludes the type of the variable you are completing through?
+// Thanks Martin Stein for this nice example.
+
+namespace ms_structs
+{
+ struct ms_aaa
+ {
+ int xx;
+ };
+
+ struct ms_bbb
+ {
+ struct ms_aaa yy;
+ };
+};
+
+int fun()
+{
+ using namespace ms_structs;
+ struct ms_bbb mszz;
+ int uu = mszz.// -5-
+ ; // #5# ( "yy" )
+ int kk = mszz.yy.// - 6- @TODO - bring in patch from SF
+ ; // #6# ( "xx" )
+}
diff --git a/test/lisp/cedet/semantic-utest-ia-resources/testsppcomplete.c b/test/lisp/cedet/semantic-utest-ia-resources/testsppcomplete.c
new file mode 100644
index 00000000000..1d2c51e3652
--- /dev/null
+++ b/test/lisp/cedet/semantic-utest-ia-resources/testsppcomplete.c
@@ -0,0 +1,66 @@
+/* testesppcomplete.cpp --- semantic-ia-utest completion engine unit tests
+
+ Copyright (C) 2008-2022 Free Software Foundation, Inc.
+
+ Author: Eric M. Ludlam <zappo@gnu.org>
+
+ This file is part of GNU Emacs.
+
+ GNU Emacs is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ GNU Emacs is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+*/
+
+/* Example provided by Hannes Janetzek */
+
+struct Test { int test; };
+
+#define BLA(_type) \
+ _type *bla = (_type*) malloc(sizeof(_type));
+
+#define BLUB(_type) \
+ (_type*)malloc(sizeof(_type));
+
+#define FOO(_type) \
+ _type *foo = BLUB(_type);
+
+#define BAR(_type) \
+ _type *bar = (*_type)BLUB(_type);
+
+int main(int argc, char *argv[]) {
+ BLA(Test);
+ bla->// -1-
+ ; // #1# ( "test" )
+
+ FOO(Test);
+ foo->// -2-
+ ; // #2# ( "test" )
+
+ BAR(Test);
+ bar->// -3-
+ ; // #3# ( "test" )
+}
+
+/* Test symref and macros together. */
+
+// This function exists only so we can have a comment in a tag with this name.
+void function_with_macro_name ()
+// %1% ( ( "testsppcomplete.c" ) ( "function_with_macro_name" "function_with_macro_name" "use_macro") )
+// Note: fwmn is in twice, once for function, and once for the constant macro below.
+{
+}
+
+#define function_with_macro_name 1
+
+int use_macro () {
+ int a = function_with_macro_name;
+}
diff --git a/test/lisp/cedet/semantic-utest-ia-resources/teststruct.cpp b/test/lisp/cedet/semantic-utest-ia-resources/teststruct.cpp
new file mode 100644
index 00000000000..f5b6d641842
--- /dev/null
+++ b/test/lisp/cedet/semantic-utest-ia-resources/teststruct.cpp
@@ -0,0 +1,86 @@
+// teststruct.cpp --- semantic-ia-utest completion engine unit tests
+
+// Copyright (C) 2008-2022 Free Software Foundation, Inc.
+
+// Author: Eric M. Ludlam <zappo@gnu.org>
+
+// This file is part of GNU Emacs.
+
+// GNU Emacs is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// GNU Emacs is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+
+// Note: initially provided by Alex Ott.
+
+template <typename DerivedT>
+struct grammar {
+public:
+ typedef grammar<DerivedT> self_t;
+ typedef DerivedT const& embed_t;
+ grammar() {}
+ ~grammar() { }
+ void use_parser() const { }
+ void test1() { }
+};
+
+struct PDFbool_parser : public grammar<PDFbool_parser> {
+ PDFbool_parser() {}
+ template <typename scannerT> struct definition {
+ typedef typename scannerT::iterator_t iterator_t;
+ int top;
+ definition(const PDFbool_parser& /*self*/) {
+ return ;
+ }
+ const int start() const {
+ return top;
+ }
+ };
+};
+
+int main(void) {
+ PDFbool_parser PDFbool_p = PDFbool_parser();
+ PDFbool_p.//-1-
+ ;
+ // #1# ("definition" "embed_t" "self_t" "test1" "use_parser")
+}
+
+// ----------------------------------------------------------------------
+
+template <class Derived> struct Base {
+public:
+ void interface()
+ {
+ // ...
+ static_cast<Derived*>(this)->implementation();
+ // ...
+ }
+
+ static void static_func()
+ {
+ // ...
+ Derived::static_sub_func();
+ // ...
+ }
+};
+
+struct Derived : Base<Derived> {
+ void implementation() { }
+ static void static_sub_func() { }
+};
+
+int foo () {
+ Derived d;
+ d.//-2-
+ ;
+ // #2# ("implementation" "interface" "static_func" "static_sub_func")
+}
diff --git a/test/manual/cedet/tests/testsubclass.cpp b/test/lisp/cedet/semantic-utest-ia-resources/testsubclass.cpp
index df8399e8d11..4c56d34c90d 100644
--- a/test/manual/cedet/tests/testsubclass.cpp
+++ b/test/lisp/cedet/semantic-utest-ia-resources/testsubclass.cpp
@@ -1,8 +1,8 @@
// testsubclass.cpp --- unit test for analyzer and complex C++ inheritance
-// Copyright (C) 2007-2017 Free Software Foundation, Inc.
+// Copyright (C) 2007-2022 Free Software Foundation, Inc.
-// Author: Eric M. Ludlam <eric@siege-engine.com>
+// Author: Eric M. Ludlam <zappo@gnu.org>
// This file is part of GNU Emacs.
diff --git a/test/manual/cedet/tests/testsubclass.hh b/test/lisp/cedet/semantic-utest-ia-resources/testsubclass.hh
index fe07b6fcb05..870da66aded 100644
--- a/test/manual/cedet/tests/testsubclass.hh
+++ b/test/lisp/cedet/semantic-utest-ia-resources/testsubclass.hh
@@ -1,8 +1,8 @@
// testsubclass.hh --- unit test for analyzer and complex C++ inheritance
-// Copyright (C) 2007-2017 Free Software Foundation, Inc.
+// Copyright (C) 2007-2022 Free Software Foundation, Inc.
-// Author: Eric M. Ludlam <eric@siege-engine.com>
+// Author: Eric M. Ludlam <zappo@gnu.org>
// This file is part of GNU Emacs.
diff --git a/test/lisp/cedet/semantic-utest-ia-resources/testtemplates.cpp b/test/lisp/cedet/semantic-utest-ia-resources/testtemplates.cpp
new file mode 100644
index 00000000000..d2b0f5d3c37
--- /dev/null
+++ b/test/lisp/cedet/semantic-utest-ia-resources/testtemplates.cpp
@@ -0,0 +1,149 @@
+// testtemplates.cpp --- semantic-ia-utest completion engine unit tests
+
+// Copyright (C) 2008-2022 Free Software Foundation, Inc.
+
+// Author: Eric M. Ludlam <zappo@gnu.org>
+
+// This file is part of GNU Emacs.
+
+// GNU Emacs is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// GNU Emacs is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+
+// TODO - this probably means can't be part of emacs, as I don't know who this guy is.
+// Written by 'Raf'
+
+template <class T, int U, class V>
+class read_ref {
+public:
+ const T* read_ref_member_one( T);
+ const V* read_ref_member_two();
+};
+
+namespace NS {
+ template <class T, int U, class V>
+ class ref {
+ public:
+ read_ref<T,10,V> operator->() {
+ m_// -1-
+ ;
+ // #1# ( "m_datas" )
+ }
+
+ private:
+ T m_datas[U];
+ };
+
+}
+
+class FooOne {
+public:
+ int fooOneMember();
+};
+
+class FooTwo {
+public:
+ int fooTwoMember();
+};
+
+class FooThree {
+public:
+ int fooThreeMember();
+
+ FooOne * operator->();
+};
+
+typedef ref<FooOne, 10,FooTwo> Test;
+
+using NS;
+
+void
+main(void) {
+ ref<FooOne, 10, FooTwo> v;
+
+ v->read_ref_member_one()-> // -2-
+ ;
+ // #2# ( "fooOneMember" )
+
+ v->read_ref_member_two()-> // -3-
+ ;
+ // #3# ( "fooTwoMember" )
+
+ v-> // -4-
+ ;
+ // #4# ( "read_ref_member_one" "read_ref_member_two" )
+
+ Test t;
+
+ t->read_ref_member_two()-> // -5-
+ ;
+ // #5# ( "fooTwoMember" )
+
+ ref<FooOne, 10, FooThree> v2;
+
+ v2->read_ref_member_two()-> // -6-
+ ;
+ // #6# ( "fooOneMember" )
+
+ /* Try all these things by also specifying the namespace in the name. */
+ NS::ref<FooOne, 10, FooTwo> v3;
+
+ v3->read_ref_member_one()-> // -7-
+ ;
+ // #7# ( "fooOneMember" )
+
+ v3->read_ref_member_two()-> // -8-
+ ;
+ // #8# ( "fooTwoMember" )
+
+ v3->read_ref_member_two// @1@ 5
+ ;
+
+}
+
+// More Namespace Magic using member constants.
+
+template<typename T>
+struct isFooLike {
+ static const bool value = false;
+};
+
+template <>
+struct isFooLike<int> {
+ static const bool value = true;
+};
+
+
+template <typename T, bool isFoo>
+class A {
+public:
+ A();
+ void foo() {};
+};
+
+
+template <typename T>
+class FooFour : public A<T, isPodLike<T>::value> {
+public:
+ bool bar() {}
+};
+
+
+int main2() {
+
+ FooFour<int> ff;
+
+ ff.// - 9- @ TODO - bring over patch from SF
+ ; // #9# ( "bar" "foo" );
+
+}
diff --git a/test/manual/cedet/tests/testtypedefs.cpp b/test/lisp/cedet/semantic-utest-ia-resources/testtypedefs.cpp
index 5bc79fc8856..09ab78942e6 100644
--- a/test/manual/cedet/tests/testtypedefs.cpp
+++ b/test/lisp/cedet/semantic-utest-ia-resources/testtypedefs.cpp
@@ -1,8 +1,8 @@
// testtypedefs.cpp --- Sample with some fake bits out of std::string
-// Copyright (C) 2008-2017 Free Software Foundation, Inc.
+// Copyright (C) 2008-2022 Free Software Foundation, Inc.
-// Author: Eric M. Ludlam <eric@siege-engine.com>
+// Author: Eric M. Ludlam <zappo@gnu.org>
// This file is part of GNU Emacs.
@@ -76,5 +76,80 @@ int main()
ntb.// -4-
;
// #4# ("otherFunc")
+
+ return 0;
+}
+
+// ------------------
+// Example from Yupeng.
+
+typedef struct epd_info {
+ int a;
+} epd_info_t;
+
+static int epd_probe(struct platform_device *pdev)
+{
+ struct epd_info *db;
+ epd_info_t db1;
+
+ db.// -5-
+ ; // #5# ("a")
+ db1.// -6-
+ ;// #6# ("a")
+
+ return 1;
+}
+
+// ------------------
+// Example from Michel LAFON-PUYO
+
+typedef enum
+{
+ ENUM1,
+ ENUM2
+} e_toto;
+
+typedef struct
+{
+ int field_a;
+ int field_b;
+} t_toto;
+
+// Note: Error condition from anonymous types in a typedef
+// was that the first (ie - the enum) would be used in
+// place of the struct.
+int func(void)
+{
+ t_toto t;
+ t. // -7-
+ ; // #7# ( "field_a" "field_b" )
+ return 0;
+}
+
+
+// ------------------
+// Example from Dixon Ryan
+
+
+namespace NS2 {
+ class MyClass {
+
+ public:
+ void myFunction() { }
+ };
+}
+
+typedef class NS2::MyClass* MyClassHandle;
+
+int dixon ( void ) {
+ MyClassHandle mch = getMyClassHandle();
+ NS2::MyClass* mcptr = getMyClassHandle();
+
+ mcptr-> // -8-
+ ; // #8# ( "myFunction" )
+ mch-> // - 9- TODO bring over patch from SF
+ ; // #9# ( "myFunction" )
+ deleteMyClassHandle(mch);
+
return 0;
}
diff --git a/test/lisp/cedet/semantic-utest-ia-resources/testusing.cpp b/test/lisp/cedet/semantic-utest-ia-resources/testusing.cpp
new file mode 100644
index 00000000000..661c09b01bb
--- /dev/null
+++ b/test/lisp/cedet/semantic-utest-ia-resources/testusing.cpp
@@ -0,0 +1,265 @@
+// testusing.cpp --- semantic-ia-utest completion engine unit tests
+
+// Copyright (C) 2008-2022 Free Software Foundation, Inc.
+
+// Author: Eric M. Ludlam <zappo@gnu.org>
+
+// This file is part of GNU Emacs.
+
+// GNU Emacs is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// GNU Emacs is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+
+#include <adstdio.h>
+
+#include <testusing.hh>
+
+namespace moose {
+
+ class MyClass;
+ class Point;
+
+ typedef MyClass snerk;
+}
+
+namespace moose {
+
+ class Point;
+ class MyClass;
+
+}
+
+namespace {
+
+ int global_variable = 0;
+
+};
+
+using moose::MyClass;
+
+void someFcn() {
+
+ MyClass f;
+
+ f.//-1-
+ ; //#1# ( "getVal" "setVal" )
+
+}
+
+// Code from Zhiqiu Kong
+
+namespace panda {
+
+ using namespace bread_name;
+
+ int func()
+ {
+ bread test;
+ test.//-2-
+ ;// #2# ( "geta" )
+ return 0;
+ }
+}
+
+namespace togglemoose {
+
+ MyOtherClass::testToggle1() { //^1^
+ // Impl for testToggle1
+ }
+}
+
+togglemoose::MyOtherClass::testToggle2() { //^3^
+ // Impl for testToggle2
+}
+
+using togglemoose;
+
+MyOtherClass::testToggle3() { //^3^
+ // Impl for testToggle3
+}
+
+// Local using statements and aliased types
+// Code from David Engster
+
+void func2()
+{
+ using namespace somestuff;
+ OneClass f;
+ f.//-3-
+ ; //#3# ( "aFunc" "anInt" )
+}
+
+void func3()
+{
+ using somestuff::OneClass;
+ OneClass f;
+ f.//-4-
+ ; //#4# ( "aFunc" "anInt" )
+}
+
+// Dereferencing alias types created through 'using' statements
+
+// Alias with fully qualified name
+void func4()
+{
+ otherstuff::OneClass f;
+ f. //-5-
+ ; //#5# ( "aFunc" "anInt" )
+}
+
+// Alias through namespace directive
+void func5()
+{
+ using namespace otherstuff;
+ OneClass f;
+ f. //-6-
+ ; //#6# ( "aFunc" "anInt" )
+}
+
+// Check name hiding
+void func6()
+{
+ using namespace morestuff;
+ OneClass f; // Alias for somestuff::OneClass
+ f. //-7-
+ ; //#7# ( "aFunc" "anInt" )
+ aStruct g; // This however is morestuff::aStruct !
+ g. //-8-
+ ; //#8# ( "anotherBar" "anotherFoo" )
+}
+
+// Alias of an alias
+// Currently doesn't work interactively for some reason.
+void func6()
+{
+ using namespace evenmorestuff;
+ OneClass f;
+ f. //-7-
+ ; //#7# ( "aFunc" "anInt" )
+}
+
+// Alias for struct in nested namespace, fully qualified
+void func7()
+{
+ outer::StructNested f;
+ f.//-8-
+ ; //#8# ( "one" "two" )
+}
+
+// Alias for nested namespace
+void func8()
+{
+ using namespace outerinner;
+ StructNested f;
+ AnotherStruct g;
+ f.//-9-
+ ; //#9# ( "one" "two" )
+ g.//-10-
+ ; //#10# ( "four" "three" )
+}
+
+// Check conventional namespace aliases
+// - fully qualified -
+void func9()
+{
+ alias_for_somestuff::OneClass c;
+ c.//-11-
+ ; //#11# ( "aFunc" "anInt" )
+ alias_for_outerinner::AnotherStruct s;
+ s. //-12-
+ ; //#12# ( "four" "three" )
+}
+
+// - unqualified -
+void func10()
+{
+ using namespace alias_for_somestuff;
+ OneClass c2;
+ c2.//-13-
+ ; //#13# ( "aFunc" "anInt" )
+ using namespace alias_for_outerinner;
+ AnotherStruct s2;
+ s2.//-14-
+ ; //#14# ( "four" "three" )
+}
+
+// Completion on namespace aliases
+void func11()
+{
+ alias_for_somestuff:://-15-
+ ; //#15# ( "OneClass" "aStruct")
+ alias_for_outerinner:://-16-
+ ; //#16# ( "AnotherStruct" "StructNested" )
+}
+
+// make sure unfound using statements don't crash stuff.
+using something::cantbe::Found;
+
+void unfoundfunc()
+{
+ NotFound notfound; // Variable can't be found.
+
+ notfound.//-17-
+ ; //#17# ( ) Nothing here since this is an undefined class
+
+}
+
+// Using statements can depend on previous ones...
+
+void acc_using()
+{
+ using namespace outer;
+ // This is effectively like 'using namespace outer::inner'
+ using namespace inner;
+
+ StructNested sn;
+ sn.//-18-
+ ; //#18# ( "one" "two" )
+}
+
+// Check the same outside of function scope
+
+using namespace outer;
+using namespace inner;
+
+void acc_using2()
+{
+ StructNested sn;
+ sn.//-19-
+ ; //#19# ( "one" "two" )
+}
+
+// Check if scope gets correctly generated, i.e., without us providing any
+// hints in the form of an existing type
+
+void check_scope()
+{
+ using namespace first;
+ AAA//-20-
+ ; //#20# ( "AAA1" "AAA2" )
+}
+
+void check_scope2()
+{
+ using namespace third;
+ AAA//-21-
+ ; //#21# ( "AAA1" "AAA2" "AAA3" )
+}
+
+// Make sure this also works not only in functions
+
+namespace check_scope3 {
+ using namespace first;
+ AAA//-22-
+ ; //#22# ( "AAA1" "AAA2" )
+}
diff --git a/test/lisp/cedet/semantic-utest-ia-resources/testusing.hh b/test/lisp/cedet/semantic-utest-ia-resources/testusing.hh
new file mode 100644
index 00000000000..e438e62e294
--- /dev/null
+++ b/test/lisp/cedet/semantic-utest-ia-resources/testusing.hh
@@ -0,0 +1,176 @@
+// testusing.hh --- semantic-ia-utest completion engine unit tests
+
+// Copyright (C) 2008-2022 Free Software Foundation, Inc.
+
+// Author: Eric M. Ludlam <zappo@gnu.org>
+
+// This file is part of GNU Emacs.
+
+// GNU Emacs is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// GNU Emacs is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+namespace moose {
+
+ class Point;
+
+ class MyClass;
+
+}
+
+
+namespace moose {
+
+ class Point;
+
+ class MyClass {
+ public:
+ MyClass() : fVal(0) {
+ }
+
+ ~MyClass() {};
+
+ /**
+ * fVal Accessors
+ * @{
+ */
+ int getVal() const {
+ return fVal;
+ }
+ void setVal(int Val) const {
+ fVal = Val;
+ }
+ /**
+ * @}
+ */
+
+ private:
+ int fVal;
+ };
+
+}
+
+namespace togglemoose {
+
+ class MyOtherClass {
+ public:
+ int testToggle1();
+ int testToggle2();
+ int testToggle3();
+ };
+}
+
+namespace deer {
+
+ class Pickle;
+
+};
+
+// Code from Zhiqiu Kong
+
+#ifndef BREAD_H
+#define BREAD_H
+
+namespace bread_name {
+ class bread
+ {
+ public:
+ void geta();
+ private:
+ int m_a;
+ int m_b;
+ };
+}
+
+#endif
+
+// Code from David Engster
+// Creating alias types through 'using' trickery
+
+namespace somestuff {
+ class OneClass {
+ public:
+ void aFunc();
+ int anInt;
+ };
+ struct aStruct {
+ int foo;
+ int bar;
+ };
+}
+
+namespace otherstuff {
+ // make otherstuff::OneClass an alias for somestuff::OneClass
+ using somestuff::OneClass;
+}
+
+namespace morestuff {
+ // make morestuff an alias namespace for somestuff
+ using namespace somestuff;
+ // but hide aStruct with own type
+ struct aStruct {
+ int anotherFoo;
+ int anotherBar;
+ };
+}
+
+// We can also create an alias for an alias
+namespace evenmorestuff {
+ using otherstuff::OneClass;
+}
+
+// Now with nested namespaces
+namespace outer {
+ namespace inner {
+ struct StructNested {
+ int one;
+ int two;
+ };
+ struct AnotherStruct {
+ int three;
+ int four;
+ };
+ }
+}
+
+// Namespace which pulls in one of its own nested namespaces
+namespace first {
+ class AAA1;
+ namespace second {
+ class AAA2;
+ }
+ // Elevate nested namespace into first one
+ using namespace second;
+}
+
+namespace third {
+ using namespace first;
+ class AAA3;
+}
+
+
+// Elevate the first struct into 'outer'
+// so that we can access it via 'outer::StructNested'
+namespace outer {
+ using outer::inner::StructNested;
+}
+
+// Create an alias for a nested namespace
+namespace outerinner {
+ // equivalent to 'namespace outerinner = outer::inner;'
+ using namespace outer::inner;
+}
+
+// Create namespace alias
+namespace alias_for_somestuff = somestuff;
+// Same for nested namespace
+namespace alias_for_outerinner = outer::inner;
diff --git a/test/manual/cedet/tests/testvarnames.c b/test/lisp/cedet/semantic-utest-ia-resources/testvarnames.c
index a328f97a741..00c877a182d 100644
--- a/test/manual/cedet/tests/testvarnames.c
+++ b/test/lisp/cedet/semantic-utest-ia-resources/testvarnames.c
@@ -1,9 +1,8 @@
-/* testvarnames.cpp
- Test variable and function names, lists of variables on one line, etc.
+/* testvarnames.cpp --- semantic-ia-utest completion engine unit tests
- Copyright (C) 2008-2017 Free Software Foundation, Inc.
+ Copyright (C) 2008-2022 Free Software Foundation, Inc.
- Author: Eric M. Ludlam <eric@siege-engine.com>
+ Author: Eric M. Ludlam <zappo@gnu.org>
This file is part of GNU Emacs.
@@ -19,6 +18,7 @@
You should have received a copy of the GNU General Public License
along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
*/
struct independent {
@@ -56,6 +56,17 @@ struct inline2struct {
struct inlinestruct in_var1;
struct inline2struct in_var2;
+/*
+ * Structures (or any types) could have the same name as a variable.
+ * Make sure we complete vars over types.
+ *
+ * See cedet-devel mailing list Dec 23, 2013 for details.
+ */
+struct varorstruct {};
+int varorstruct;
+
+int assigntovarorstruct;
+
int test_1(int var_arg1) {
var_// -1-
@@ -87,4 +98,7 @@ int test_1(int var_arg1) {
; // #10# ( "named_1" "named_2")
in_var2.// -11-
; // #11# ( "named_3" "named_4")
+
+ varorstruct = assign// -12-
+ ; // #12# ( "assigntovarorstruct" )
}
diff --git a/test/lisp/cedet/semantic-utest-ia-resources/testvarnames.java b/test/lisp/cedet/semantic-utest-ia-resources/testvarnames.java
new file mode 100644
index 00000000000..323e2059c40
--- /dev/null
+++ b/test/lisp/cedet/semantic-utest-ia-resources/testvarnames.java
@@ -0,0 +1,60 @@
+// testvarnames.java --- Semantic unit test for Java
+
+// Copyright (C) 2009-2022 Free Software Foundation, Inc.
+
+// Author: Eric M. Ludlam <zappo@gnu.org>
+
+// This file is part of GNU Emacs.
+
+// GNU Emacs is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// GNU Emacs is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+package tests;
+
+/**
+ *
+ *
+ * Created: 02/17/14
+ *
+ * @author Eric M. Ludlam
+ * @version
+ * @since
+ */
+public class testvarnames {
+
+ public class varorclass {
+ public static long misclongvalue;
+ };
+
+ public static varorclass varoftypevarorclass = NULL;
+
+ public static long varorclass = 1;
+
+ public static long assignintovar = 1;
+
+ public static varorclass classassign = NULL;
+
+ static public void main(String [] args) {
+
+ varorclass = assign// -1-
+ // #1# ( "assignintovar" )
+ ;
+
+ varoftypevarorclass = clas// -2-
+ // #2# ( "classassign" )
+
+ varoftypevarorclass.misc//-3-
+ // #3# ( "misclongvalue" )
+ }
+
+} // testvarnames
diff --git a/test/lisp/cedet/semantic-utest-ia-resources/testwisent.wy b/test/lisp/cedet/semantic-utest-ia-resources/testwisent.wy
new file mode 100644
index 00000000000..901a662e799
--- /dev/null
+++ b/test/lisp/cedet/semantic-utest-ia-resources/testwisent.wy
@@ -0,0 +1,85 @@
+;; testwisent.wy --- unit test support file for semantic-utest-ia
+
+;; Copyright (C) 2008-2022 Free Software Foundation, Inc.
+
+;; Author: Eric M. Ludlam <zappo@gnu.org>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+;;
+;; Parser for nothing in particular mode
+
+%languagemode nothing-mode
+%parsetable wisent-nothing-parser-tables
+%keywordtable wisent-nothing-keywords
+%tokentable wisent-nothing-tokens
+%languagemode nothing-mode
+%setupfunction wisent-nothing-default-setup
+
+%start goal
+
+;;; Punctuation
+%type <punctuation> ;;syntax "\\(\\s.\\|\\s$\\|\\s'\\)+" matchdatatype string
+
+%token <punctuation> DOT "."
+%token <punctuation> COMA ","
+%token <punctuation> COLONCOLON "::"
+%token <punctuation> COLON ":"
+%token <punctuation> SEMICOLON ";"
+
+;;; KEYWORDS
+%type <keyword>
+
+%keyword COLONOSCOPY "colonoscopy"
+%keyword SEMISOMETHING "semisomething"
+
+%%
+
+goal
+ ;; Misc
+ : COLON ;; -1-
+ ;; #1# ( "COLONCOLON" "COLON" "COLONOSCOPY" )
+ | SEMI ;; -2-
+ ;; #2# ( "SEMI_useless_rule" "SEMICOLON" "SEMISOMETHING" )
+ | thing ;; -3-
+ ;; #3# ( "thing_term_1" "thing_term_2" )
+ ;
+
+SEMI_useless_rule
+ :
+ ;
+
+thing_term_1
+ :
+ ;
+
+thing_term_2
+ :
+ ;
+
+%%
+(define-lex wisent-nothing-lexer
+ "Lexical analyzer to handle nothing in particular buffers."
+ ;; semantic-lex-newline
+ semantic-lex-ignore-whitespace
+ semantic-lex-ignore-newline
+ semantic-lex-ignore-comments
+
+ semantic-lex-default-action
+ )
+
+;; testwisent.wy ends here \ No newline at end of file
diff --git a/test/manual/cedet/semantic-ia-utest.el b/test/lisp/cedet/semantic-utest-ia.el
index 7861fd73949..fa3b3185ed5 100644
--- a/test/manual/cedet/semantic-ia-utest.el
+++ b/test/lisp/cedet/semantic-utest-ia.el
@@ -1,8 +1,8 @@
-;;; semantic-ia-utest.el --- Analyzer unit tests
+;;; semantic-utest-ia.el --- Analyzer unit tests -*- lexical-binding:t -*-
-;; Copyright (C) 2008-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2022 Free Software Foundation, Inc.
-;; Author: Eric M. Ludlam <eric@siege-engine.com>
+;; Author: Eric M. Ludlam <zappo@gnu.org>
;; This file is part of GNU Emacs.
@@ -27,109 +27,121 @@
;; Each file has cursor keys in them of the form:
;; // -#- ("ans1" "ans2" )
;; where # is 1, 2, 3, etc, and some sort of answer list.
+;; (Replace // with contents of comment-start for the language being tested.)
;;; Code:
+(require 'ert)
+(require 'ert-x)
(require 'semantic)
(require 'semantic/analyze)
(require 'semantic/analyze/refs)
(require 'semantic/symref)
(require 'semantic/symref/filter)
-(load-file "cedet-utests.el")
-
-(defvar semantic-ia-utest-file-list
- '(
- "tests/testdoublens.cpp"
- "tests/testsubclass.cpp"
- "tests/testtypedefs.cpp"
- "tests/testfriends.cpp"
- "tests/testnsp.cpp"
- "tests/testsppcomplete.c"
- "tests/testvarnames.c"
- "tests/testjavacomp.java"
- )
- "List of files with analyzer completion test points.")
-
-(defvar semantic-ia-utest-error-log-list nil
- "List of errors occurring during a run.")
-
-;;;###autoload
-(defun semantic-ia-utest (&optional arg)
- "Run the semantic ia unit test against stored sources.
-Argument ARG specifies which set of tests to run.
- 1 - ia utests
- 2 - regs utests
- 3 - symrefs utests
- 4 - symref count utests"
- (interactive "P")
- (save-excursion
-
- (let ((fl semantic-ia-utest-file-list)
- (semantic-ia-utest-error-log-list nil)
- )
-
- (cedet-utest-log-setup "ANALYZER")
-
- (set-buffer (semantic-find-file-noselect
- (or (locate-library "semantic-ia-utest.el")
- "semantic-ia-utest.el")))
-
- (while fl
-
- ;; Make sure we have the files we think we have.
- (when (not (file-exists-p (car fl)))
- (error "Cannot find unit test file: %s" (car fl)))
-
- ;; Run the tests.
- (let ((fb (find-buffer-visiting (car fl)))
- (b (semantic-find-file-noselect (car fl) t)))
-
- ;; Run the test on it.
- (save-excursion
- (set-buffer b)
-
- ;; This line will also force the include, scope, and typecache.
- (semantic-clear-toplevel-cache)
- ;; Force tags to be parsed.
- (semantic-fetch-tags)
-
- (semantic-ia-utest-log " ** Starting tests in %s"
- (buffer-name))
-
- (when (or (not arg) (= arg 1))
- (semantic-ia-utest-buffer))
-
- (when (or (not arg) (= arg 2))
- (set-buffer b)
- (semantic-ia-utest-buffer-refs))
-
- (when (or (not arg) (= arg 3))
- (set-buffer b)
- (semantic-sr-utest-buffer-refs))
-
- (when (or (not arg) (= arg 4))
- (set-buffer b)
- (semantic-src-utest-buffer-refs))
-
- (semantic-ia-utest-log " ** Completed tests in %s\n"
- (buffer-name))
- )
+(ert-deftest semantic-utest-ia-doublens.cpp ()
+ (let ((tst (ert-resource-file "testdoublens.cpp")))
+ (should-not (semantic-ia-utest tst))))
+
+(ert-deftest semantic-utest-ia-subclass.cpp ()
+ (let ((tst (ert-resource-file "testsubclass.cpp")))
+ (should-not (semantic-ia-utest tst))))
+
+(ert-deftest semantic-utest-ia-typedefs.cpp ()
+ (let ((tst (ert-resource-file "testtypedefs.cpp")))
+ (should-not (semantic-ia-utest tst))))
+
+(ert-deftest semantic-utest-ia-struct.cpp ()
+ (let ((tst (ert-resource-file "teststruct.cpp")))
+ (should-not (semantic-ia-utest tst))))
+
+;;(ert-deftest semantic-utest-ia-union.cpp ()
+;; (let ((tst (ert-resource-file "testunion.cpp")))
+;; (should-not (semantic-ia-utest tst))))
+
+(ert-deftest semantic-utest-ia-templates.cpp ()
+ (let ((tst (ert-resource-file "testtemplates.cpp")))
+ (should-not (semantic-ia-utest tst))))
+
+;;(ert-deftest semantic-utest-ia-friends.cpp ()
+;; (let ((tst (ert-resource-file "testfriends.cpp")))
+;; (should-not (semantic-ia-utest tst))))
+
+(ert-deftest semantic-utest-ia-using.cpp ()
+ (let ((tst (ert-resource-file "testusing.cpp")))
+ (should-not (semantic-ia-utest tst))))
+
+(ert-deftest semantic-utest-ia-nsp.cpp ()
+ (skip-unless (executable-find "g++"))
+ (let ((tst (ert-resource-file "testnsp.cpp")))
+ (should-not (semantic-ia-utest tst))))
+
+(ert-deftest semantic-utest-ia-localvars.cpp ()
+ (let ((tst (ert-resource-file "testlocalvars.cpp")))
+ (should-not (semantic-ia-utest tst))))
+
+(ert-deftest semantic-utest-ia-namespace.cpp ()
+ (skip-unless (executable-find "g++"))
+ (let ((tst (ert-resource-file "testnsp.cpp")))
+ (should-not (semantic-ia-utest tst))))
+
+(ert-deftest semantic-utest-ia-sppcomplete.c ()
+ (let ((tst (ert-resource-file "testsppcomplete.c")))
+ (should-not (semantic-ia-utest tst))))
+
+(ert-deftest semantic-utest-ia-varnames.c ()
+ (let ((tst (ert-resource-file "testvarnames.c")))
+ (should-not (semantic-ia-utest tst))))
+
+(ert-deftest semantic-utest-ia-javacomp.java ()
+ (let ((tst (ert-resource-file "testjavacomp.java")))
+ (should-not (semantic-ia-utest tst))))
+
+(ert-deftest semantic-utest-ia-varnames.java ()
+ (let ((tst (ert-resource-file "testvarnames.java")))
+ (should-not (semantic-ia-utest tst))))
+
+;;(ert-deftest semantic-utest-ia-f90.f90 ()
+;; (let ((tst (ert-resource-file "testf90.f90")))
+;; (should-not (semantic-ia-utest tst))))
+
+(ert-deftest semantic-utest-ia-wisent.wy ()
+ (let ((tst (ert-resource-file "testwisent.wy")))
+ (should-not (semantic-ia-utest tst))))
+
+(ert-deftest semantic-utest-ia-texi ()
+ (let ((tst (ert-resource-file "test.texi")))
+ (should-not (semantic-ia-utest tst))))
+
+(ert-deftest semantic-utest-ia-make ()
+ (let ((tst (ert-resource-file "test.mk")))
+ (should-not (semantic-ia-utest tst))))
+
+(ert-deftest semantic-utest-ia-srecoder ()
+ (let ((tst (ert-resource-file "test.srt")))
+ (should-not (semantic-ia-utest tst))))
+
+;;; Core testing utility
+(defun semantic-ia-utest (testfile)
+ "Run the semantic ia unit test against stored sources."
+ (semantic-mode 1)
+ (let ((b (semantic-find-file-noselect testfile t)))
+
+ ;; Run the test on it.
+ (with-current-buffer b
+
+ ;; This line will also force the include, scope, and typecache.
+ (semantic-clear-toplevel-cache)
+ ;; Force tags to be parsed.
+ (semantic-fetch-tags)
- ;; If it wasn't already in memory, whack it.
- (when (not fb)
- (kill-buffer b))
- )
- (setq fl (cdr fl)))
-
- (cedet-utest-log-shutdown
- "ANALYZER"
- (when semantic-ia-utest-error-log-list
- (format "%s Failures found."
- (length semantic-ia-utest-error-log-list))))
- (when semantic-ia-utest-error-log-list
- (error "Failures found during analyzer unit tests"))
- ))
- )
+ (prog1
+ (or (semantic-ia-utest-buffer)
+ (semantic-ia-utest-buffer-refs)
+ (semantic-sr-utest-buffer-refs)
+ (semantic-src-utest-buffer-refs))
+
+ (kill-buffer b)
+ ))))
(defun semantic-ia-utest-buffer ()
"Run analyzer completion unit-test pass in the current buffer."
@@ -148,10 +160,13 @@ Argument ARG specifies which set of tests to run.
(semanticdb-find-default-throttle
(remq 'system semanticdb-find-default-throttle))
)
+
;; Keep looking for test points until we run out.
(while (save-excursion
- (setq regex-p (concat "//\\s-*-" (number-to-string idx) "-" )
- regex-a (concat "//\\s-*#" (number-to-string idx) "#" ))
+ (setq regex-p (concat "\\(" comment-start-skip "\\)\\s-*-"
+ (number-to-string idx) "-" )
+ regex-a (concat "\\(" comment-start-skip "\\)\\s-*#"
+ (number-to-string idx) "#" ))
(goto-char (point-min))
(save-match-data
(when (re-search-forward regex-p nil t)
@@ -164,47 +179,48 @@ Argument ARG specifies which set of tests to run.
(save-excursion
(goto-char p)
+ (skip-chars-backward " ") ;; some languages need a space.
(let* ((ctxt (semantic-analyze-current-context))
+ ;; TODO - fix the NOTFOUND case to be nil and not an error when finding
+ ;; completions, then remove the below debug-on-error setting.
+ (debug-on-error nil)
(acomp
- (condition-case nil
+ (condition-case _err
(semantic-analyze-possible-completions ctxt)
- (error nil))))
- (setq actual (mapcar 'semantic-tag-name acomp)))
+ ((error user-error) nil))
+ ))
+ (setq actual (mapcar 'semantic-format-tag-name acomp)))
(goto-char a)
- (let ((bss (buffer-substring-no-properties (point) (point-at-eol))))
+ (let ((bss (buffer-substring-no-properties (point) (pos-eol))))
(condition-case nil
(setq desired (read bss))
(error (setq desired (format " FAILED TO PARSE: %S"
bss)))))
+ (setq actual (sort actual 'string<))
+ (setq desired (sort desired 'string<))
+
(if (equal actual desired)
- (setq pass (cons idx pass))
- (setq fail (cons idx fail))
- (semantic-ia-utest-log
- " Failed %d. Desired: %S Actual %S"
- idx desired actual)
- (add-to-list 'semantic-ia-utest-error-log-list
- (list (buffer-name) idx desired actual)
- )
-
- )
- )
-
- (setq p nil a nil)
- (setq idx (1+ idx)))
-
- (if fail
- (progn
- (semantic-ia-utest-log
- " Unit tests (completions) failed tests %S"
- (reverse fail))
- )
- (semantic-ia-utest-log " Unit tests (completions) passed (%d total)"
- (- idx 1)))
+ (prog1
+ (setq pass (cons idx pass))
+ ;;(message "PASS: %S" actual)
+ )
+ (setq fail (cons
+ (list
+ (format "Failed %d. Desired: %S Actual %S"
+ idx desired actual)
+ )
+ fail)))
+
+ (setq p nil a nil)
+ (setq idx (1+ idx)))
+ )
+ (when fail
+ (cons "COMPLETION SUBTEST" (reverse fail)))
))
(defun semantic-ia-utest-buffer-refs ()
@@ -222,7 +238,8 @@ Argument ARG specifies which set of tests to run.
)
;; Keep looking for test points until we run out.
(while (save-excursion
- (setq regex-p (concat "//\\s-*\\^" (number-to-string idx) "^" )
+ (setq regex-p (concat "\\(" comment-start-skip
+ "\\)\\s-*\\^" (number-to-string idx) "^" )
)
(goto-char (point-min))
(save-match-data
@@ -287,34 +304,22 @@ Argument ARG specifies which set of tests to run.
(throw 'failed t)
)))
- (if (not pf)
+ (if (not pf)
;; We passed
(setq pass (cons idx pass))
;; We failed.
- (setq fail (cons idx fail))
- (semantic-ia-utest-log
- " Failed %d. For %s (Num impls %d) (Num protos %d)"
- idx (if ct (semantic-tag-name ct) "<No tag found>")
- (length impl) (length proto))
- (add-to-list 'semantic-ia-utest-error-log-list
- (list (buffer-name) idx)
- )
+ (setq fail (cons
+ (list
+ (message "Test id %d. For %s (Num impls %d) (Num protos %d)"
+ idx (if ct (semantic-tag-name ct) "<No tag found>")
+ (length impl) (length proto))
+ )
+ fail))
))
-
(setq p nil)
- (setq idx (1+ idx))
-
- ))
-
- (if fail
- (progn
- (semantic-ia-utest-log
- " Unit tests (refs) failed tests")
- )
- (semantic-ia-utest-log " Unit tests (refs) passed (%d total)"
- (- idx 1)))
-
- ))
+ (setq idx (1+ idx))))
+ (when fail
+ (cons "ANALYZER REF COUNTING SUBTEST" fail))))
(defun semantic-sr-utest-buffer-refs ()
"Run a symref unit-test pass in the current buffer."
@@ -340,32 +345,26 @@ Argument ARG specifies which set of tests to run.
)
;; Keep looking for test points until we run out.
(while (save-excursion
- (setq regex-p (concat "//\\s-*\\%" (number-to-string idx) "%" )
+ (setq regex-p (concat "\\(" comment-start-skip "\\)\\s-*\\%"
+ (number-to-string idx) "%" )
)
(goto-char (point-min))
(save-match-data
(when (re-search-forward regex-p nil t)
(setq tag (semantic-current-tag))
(goto-char (match-end 0))
- (setq desired (read (buffer-substring (point) (point-at-eol))))
+ (setq desired (read (buffer-substring (point) (pos-eol))))
))
tag)
(setq actual-result (semantic-symref-find-references-by-name
- (semantic-tag-name tag) 'target
+ (semantic-format-tag-name tag) 'target
'symref-tool-used))
(if (not actual-result)
(progn
(setq fail (cons idx fail))
- (semantic-ia-utest-log
- " Failed FNames %d: No results." idx)
- (semantic-ia-utest-log
- " Failed Tool: %s" (object-name symref-tool-used))
-
- (add-to-list 'semantic-ia-utest-error-log-list
- (list (buffer-name) idx)
- )
+ (message "Failed Tool: %s" (eieio-object-name symref-tool-used))
)
(setq actual (list (sort (mapcar
@@ -383,38 +382,28 @@ Argument ARG specifies which set of tests to run.
;; We passed
(setq pass (cons idx pass))
;; We failed.
- (setq fail (cons idx fail))
- (when (not (equal (car actual) (car desired)))
- (semantic-ia-utest-log
- " Failed FNames %d: Actual: %S Desired: %S"
- idx (car actual) (car desired))
- (semantic-ia-utest-log
- " Failed Tool: %s" (object-name symref-tool-used))
- )
- (when (not (equal (car (cdr actual)) (car (cdr desired))))
- (semantic-ia-utest-log
- " Failed TNames %d: Actual: %S Desired: %S"
- idx (car (cdr actual)) (car (cdr desired)))
- (semantic-ia-utest-log
- " Failed Tool: %s" (object-name symref-tool-used))
- )
- (add-to-list 'semantic-ia-utest-error-log-list
- (list (buffer-name) idx)
- )
+ (setq fail
+ (cons (list
+ (when (not (equal (car actual) (car desired)))
+ (list
+ (format "Actual: %S Desired: %S"
+ (car actual) (car desired))
+ (format "Failed Tool: %s" (eieio-object-name symref-tool-used))
+ ))
+ (when (not (equal (car (cdr actual)) (car (cdr desired))))
+ (list (format
+ "Actual: %S Desired: %S"
+ (car (cdr actual)) (car (cdr desired)))
+ (format
+ "Failed Tool: %s" (eieio-object-name symref-tool-used)))))
+ fail))
))
(setq idx (1+ idx))
(setq tag nil))
- (if fail
- (progn
- (semantic-ia-utest-log
- " Unit tests (symrefs) failed tests")
- )
- (semantic-ia-utest-log " Unit tests (symrefs) passed (%d total)"
- (- idx 1)))
-
- ))
+ (when fail
+ (cons "SYMREF SUBTEST" fail))))
(defun semantic-symref-test-count-hits-in-tag ()
"Lookup in the current tag the symbol under point.
@@ -424,17 +413,12 @@ tag that contains point, and return that."
(let* ((ctxt (semantic-analyze-current-context))
(target (car (reverse (oref ctxt prefix))))
(tag (semantic-current-tag))
- (start (current-time))
(Lcount 0))
(when (semantic-tag-p target)
(semantic-symref-hits-in-region
- target (lambda (start end prefix) (setq Lcount (1+ Lcount)))
+ target (lambda (_start _end _prefix) (setq Lcount (1+ Lcount)))
(semantic-tag-start tag)
(semantic-tag-end tag))
- (when (interactive-p)
- (message "Found %d occurrences of %s in %.2f seconds"
- Lcount (semantic-tag-name target)
- (semantic-elapsed-time start (current-time))))
Lcount)))
(defun semantic-src-utest-buffer-refs ()
@@ -459,14 +443,15 @@ tag that contains point, and return that."
)
;; Keep looking for test points until we run out.
(while (save-excursion
- (setq regex-p (concat "//\\s-*@"
+ (setq regex-p (concat "\\(" comment-start-skip "\\)\\s-*@"
(number-to-string idx)
- "@\\s-+\\(\\w+\\)" ))
+ "@\\s-+\\w+" ))
(goto-char (point-min))
(save-match-data
(when (re-search-forward regex-p nil t)
- (goto-char (match-beginning 1))
- (setq desired (read (buffer-substring (point) (point-at-eol))))
+ (goto-char (match-end 0))
+ (skip-syntax-backward "w")
+ (setq desired (read (buffer-substring (point) (pos-eol))))
(setq start (match-beginning 0))
(goto-char start)
(setq actual (semantic-symref-test-count-hits-in-tag))
@@ -474,55 +459,34 @@ tag that contains point, and return that."
(if (not actual)
(progn
- (setq fail (cons idx fail))
- (semantic-ia-utest-log
- " Failed symref count %d: No results." idx)
+ (setq fail (cons
+ (list
+ (format
+ "Symref id %d: No results." idx))
+ fail))
- (add-to-list 'semantic-ia-utest-error-log-list
- (list (buffer-name) idx)
- )
)
(if (equal desired actual)
;; We passed
(setq pass (cons idx pass))
;; We failed.
- (setq fail (cons idx fail))
- (when (not (equal actual desired))
- (semantic-ia-utest-log
- " Failed symref count %d: Actual: %S Desired: %S"
- idx actual desired)
- )
-
- (add-to-list 'semantic-ia-utest-error-log-list
- (list (buffer-name) idx)
- )
+ (setq fail (cons (list
+ (when (not (equal actual desired))
+ (format
+ "Symref id %d: Actual: %S Desired: %S"
+ idx actual desired)
+ )
+ )
+ fail))
))
(setq idx (1+ idx))
)
- (if fail
- (progn
- (semantic-ia-utest-log
- " Unit tests (symrefs counter) failed tests")
- )
- (semantic-ia-utest-log " Unit tests (symrefs counter) passed (%d total)"
- (- idx 1)))
-
- ))
-
-(defun semantic-ia-utest-start-log ()
- "Start up a testlog for a run."
- ;; Redo w/ CEDET utest framework.
- (cedet-utest-log-start "semantic: analyzer tests"))
-
-(defun semantic-ia-utest-log (&rest args)
- "Log some test results.
-Pass ARGS to format to create the log message."
- ;; Forward to CEDET utest framework.
- (apply 'cedet-utest-log args))
+ (when fail
+ (cons "SYMREF COUNTING SUBTEST" fail))))
(provide 'semantic-ia-utest)
-;;; semantic-ia-utest.el ends here
+;;; semantic-utest-ia.el ends here
diff --git a/test/manual/cedet/semantic-utest.el b/test/lisp/cedet/semantic-utest.el
index 6d499eeba44..24a467474b9 100644
--- a/test/manual/cedet/semantic-utest.el
+++ b/test/lisp/cedet/semantic-utest.el
@@ -1,6 +1,6 @@
-;;; semantic-utest.el --- Tests for semantic's parsing system.
+;;; semantic-utest.el --- Tests for semantic's parsing system. -*- lexical-binding:t -*-
-;;; Copyright (C) 2003-2004, 2007-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2022 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
@@ -26,18 +26,23 @@
;; and full reparsing system, and anything else I may feel the urge
;; to write a test for.
+(require 'cedet)
(require 'semantic)
-(load-file "cedet-utests.el")
+;;; Code:
-(defvar semantic-utest-temp-directory (if (fboundp 'temp-directory)
- (temp-directory)
- temporary-file-directory)
- "Temporary directory to use when creating files.")
+(defvar cedet-utest-directory
+ (let* ((C (file-name-directory (locate-library "cedet")))
+ (D (expand-file-name "../../test/manual/cedet/" C)))
+ D)
+ "Location of test files for this test suite.")
+
+(defvar semantic-utest-test-directory (expand-file-name "tests" cedet-utest-directory)
+ "Location of test files.")
(defun semantic-utest-fname (name)
"Create a filename for NAME in /tmp."
- (expand-file-name name semantic-utest-temp-directory))
+ (expand-file-name name temporary-file-directory))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Data for C tests
@@ -100,7 +105,7 @@ int calc_sv(int);
(defvar semantic-utest-C-filename-h
(concat (file-name-sans-extension semantic-utest-C-filename)
".h")
- "Header file filename for C")
+ "Header file filename for C.")
(defvar semantic-utest-C-name-contents
@@ -332,8 +337,8 @@ t2:t1 #1
"
(define fun1 2)
- (define fun2 3 ;1
- )
+ (define fun2 3) ;1
+
")
(defvar semantic-utest-Scheme-name-contents
@@ -421,8 +426,7 @@ class aClass {
nil
(overlay 135 262 "phptest.php"))
)
- "Expected results from the PHP Unit test"
- )
+ "Expected results from the PHP Unit test.")
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -484,7 +488,7 @@ Pre-fill the buffer with CONTENTS."
(set-buffer buff)
(setq buffer-offer-save nil)
(font-lock-mode -1) ;; Font lock has issues in Emacs 23
- (toggle-read-only -1) ;; In case /tmp doesn't exist.
+ (read-only-mode -1) ;; In case /tmp doesn't exist
(erase-buffer)
(insert contents)
;(semantic-fetch-tags) ;JAVE could this go here?
@@ -493,9 +497,9 @@ Pre-fill the buffer with CONTENTS."
)
)
-(defun semantic-utest-C ()
+(ert-deftest semantic-utest-C ()
"Run semantic's C unit test."
- (interactive)
+ (semantic-mode 1)
(save-excursion
(let ((buff (semantic-utest-makebuffer semantic-utest-C-filename semantic-utest-C-buffer-contents))
(buff2 (semantic-utest-makebuffer semantic-utest-C-filename-h semantic-utest-C-h-buffer-contents))
@@ -512,38 +516,33 @@ Pre-fill the buffer with CONTENTS."
;; Update tags, and show it.
(semantic-fetch-tags)
- (switch-to-buffer buff)
- (sit-for 0)
-
;; Run the tests.
;;(message "First parsing test.")
- (semantic-utest-verify-names semantic-utest-C-name-contents)
+ (should (semantic-utest-verify-names semantic-utest-C-name-contents))
;;(message "Invalid tag test.")
(semantic-utest-last-invalid semantic-utest-C-name-contents '("fun2") "/\\*1\\*/" "/* Deleted this line */")
- (semantic-utest-verify-names semantic-utest-C-name-contents)
+ (should (semantic-utest-verify-names semantic-utest-C-name-contents))
(set-buffer-modified-p nil)
;; Clean up
- ;; (kill-buffer buff)
- ;; (kill-buffer buff2)
- ))
- (message "All C tests passed.")
- )
+ (kill-buffer buff)
+ (kill-buffer buff2)
+ )))
-(defun semantic-utest-generic (testname filename contents name-contents names-removed killme insertme)
+(defun semantic-utest-generic (filename contents name-contents names-removed killme insertme)
"Generic unit test according to template.
Should work for languages without .h files, python javascript java.
-TESTNAME is the name of the test.
FILENAME is the name of the file to create.
CONTENTS is the contents of the file to test.
NAME-CONTENTS is the list of names that should be in the contents.
NAMES-REMOVED is the list of names that gets removed in the removal step.
KILLME is the name of items to be killed.
INSERTME is the text to be inserted after the deletion."
+ (semantic-mode 1)
(save-excursion
(let ((buff (semantic-utest-makebuffer filename contents))
)
@@ -554,79 +553,66 @@ INSERTME is the text to be inserted after the deletion."
(semantic-highlight-edits-mode 1)
;; Update tags, and show it.
+ (semantic-clear-toplevel-cache)
(semantic-fetch-tags)
(switch-to-buffer buff)
(sit-for 0)
;; Run the tests.
- ;;(message "First parsing test %s." testname)
- (semantic-utest-verify-names name-contents)
+ (should (semantic-utest-verify-names name-contents))
- ;;(message "Invalid tag test %s." testname)
(semantic-utest-last-invalid name-contents names-removed killme insertme)
- (semantic-utest-verify-names name-contents)
+ (should (semantic-utest-verify-names name-contents))
(set-buffer-modified-p nil)
;; Clean up
- ;; (kill-buffer buff)
- ))
- (message "All %s tests passed." testname)
- )
-
-(defun semantic-utest-Python()
- (interactive)
- (if (fboundp 'python-mode)
- (semantic-utest-generic "Python" (semantic-utest-fname "pytest.py") semantic-utest-Python-buffer-contents semantic-utest-Python-name-contents '("fun2") "#1" "#deleted line")
- (message "Skilling Python test: NO major mode."))
- )
+ (kill-buffer buff)
+ )))
+
+(defvar python-indent-guess-indent-offset) ; Silence byte-compiler.
+(ert-deftest semantic-utest-Python()
+ (skip-unless (fboundp 'python-mode))
+ (let ((python-indent-guess-indent-offset nil))
+ (semantic-utest-generic (semantic-utest-fname "pytest.py") semantic-utest-Python-buffer-contents semantic-utest-Python-name-contents '("fun2") "#1" "#deleted line")
+ ))
-(defun semantic-utest-Javascript()
- (interactive)
- (if (fboundp 'javascript-mode)
- (semantic-utest-generic "Javascript" (semantic-utest-fname "javascripttest.js") semantic-utest-Javascript-buffer-contents semantic-utest-Javascript-name-contents '("fun2") "//1" "//deleted line")
- (message "Skipping JavaScript test: NO major mode."))
- )
+(ert-deftest semantic-utest-Javascript()
+ (skip-unless (fboundp 'javascript-mode))
+ (semantic-utest-generic (semantic-utest-fname "javascripttest.js") semantic-utest-Javascript-buffer-contents semantic-utest-Javascript-name-contents '("fun2") "//1" "//deleted line"))
-(defun semantic-utest-Java()
- (interactive)
+(ert-deftest semantic-utest-Java()
;; If JDE is installed, it might mess things up depending on the version
;; that was installed.
(let ((auto-mode-alist '(("\\.java\\'" . java-mode))))
- (semantic-utest-generic "Java" (semantic-utest-fname "JavaTest.java") semantic-utest-Java-buffer-contents semantic-utest-Java-name-contents '("fun2") "//1" "//deleted line")
+ (semantic-utest-generic (semantic-utest-fname "JavaTest.java") semantic-utest-Java-buffer-contents semantic-utest-Java-name-contents '("fun2") "//1" "//deleted line")
))
-(defun semantic-utest-Makefile()
- (interactive)
- (semantic-utest-generic "Makefile" (semantic-utest-fname "Makefile") semantic-utest-Makefile-buffer-contents semantic-utest-Makefile-name-contents '("fun2") "#1" "#deleted line")
+(ert-deftest semantic-utest-Makefile()
+ (semantic-utest-generic (semantic-utest-fname "Makefile") semantic-utest-Makefile-buffer-contents semantic-utest-Makefile-name-contents '("fun2") "#1" "#deleted line")
)
-(defun semantic-utest-Scheme()
- (interactive)
- (semantic-utest-generic "Scheme" (semantic-utest-fname "tst.scm") semantic-utest-Scheme-buffer-contents semantic-utest-Scheme-name-contents '("fun2") ";1" ";deleted line")
+(ert-deftest semantic-utest-Scheme()
+ (skip-unless nil) ;; There is a bug w/ scheme parser. Skip this for now.
+ (semantic-utest-generic (semantic-utest-fname "tst.scm") semantic-utest-Scheme-buffer-contents semantic-utest-Scheme-name-contents '("fun2") ";1" ";deleted line")
)
-
-(defun semantic-utest-Html()
- (interactive)
+(defvar html-helper-build-new-buffer) ; Silence byte-compiler.
+(ert-deftest semantic-utest-Html()
;; Disable html-helper auto-fill-in mode.
- (let ((html-helper-build-new-buffer nil))
- (semantic-utest-generic "HTML" (semantic-utest-fname "tst.html") semantic-utest-Html-buffer-contents semantic-utest-Html-name-contents '("fun2") "<!--1-->" "<!--deleted line-->")
+ (let ((html-helper-build-new-buffer nil)) ; FIXME: Why is this bound?
+ (semantic-utest-generic (semantic-utest-fname "tst.html") semantic-utest-Html-buffer-contents semantic-utest-Html-name-contents '("fun2") "<!--1-->" "<!--deleted line-->")
))
-(defun semantic-utest-PHP()
- (interactive)
- (if (fboundp 'php-mode)
- (semantic-utest-generic "PHP" (semantic-utest-fname "phptest.php") semantic-utest-PHP-buffer-contents semantic-utest-PHP-name-contents '("fun1") "fun2" "%^@")
- (message "Skipping PHP Test. No php-mode loaded."))
+(ert-deftest semantic-utest-PHP()
+ (skip-unless (featurep 'php-mode))
+ (semantic-utest-generic (semantic-utest-fname "phptest.php") semantic-utest-PHP-buffer-contents semantic-utest-PHP-name-contents '("fun1") "fun2" "%^@")
)
;look at http://mfgames.com/linux/csharp-mode
-(defun semantic-utest-Csharp() ;; hmm i don't even know how to edit a scharp file. need a csharp mode implementation i suppose
- (interactive)
- (if (fboundp 'csharp-mode)
- (semantic-utest-generic "C#" (semantic-utest-fname "csharptest.cs") semantic-utest-Csharp-buffer-contents semantic-utest-Csharp-name-contents '("fun2") "//1" "//deleted line")
- (message "Skipping C# test. No csharp-mode loaded."))
+(ert-deftest semantic-utest-Csharp() ;; hmm i don't even know how to edit a scharp file. need a csharp mode implementation i suppose
+ (skip-unless (featurep 'csharp-mode))
+ (semantic-utest-generic (semantic-utest-fname "csharptest.cs") semantic-utest-Csharp-buffer-contents semantic-utest-Csharp-name-contents '("fun2") "//1" "//deleted line")
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -653,32 +639,6 @@ INSERTME is the text to be inserted after the deletion."
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;;###autoload
-(defun semantic-utest-main()
- (interactive)
- "call all utests"
- (cedet-utest-log-start "multi-lang parsing")
- (cedet-utest-log " * C tests...")
- (semantic-utest-C)
- (cedet-utest-log " * Python tests...")
- (semantic-utest-Python)
- (cedet-utest-log " * Java tests...")
- (semantic-utest-Java)
- (cedet-utest-log " * Javascript tests...")
- (semantic-utest-Javascript)
- (cedet-utest-log " * Makefile tests...")
- (semantic-utest-Makefile)
- (cedet-utest-log " * Scheme tests...")
- (semantic-utest-Scheme)
- (cedet-utest-log " * Html tests...")
- (semantic-utest-Html)
- (cedet-utest-log " * PHP tests...")
- (semantic-utest-PHP)
- (cedet-utest-log " * Csharp tests...")
- (semantic-utest-Csharp)
-
- (cedet-utest-log-shutdown "multi-lang parsing")
- )
;;; Buffer contents validation
;;
@@ -724,21 +684,25 @@ SKIPNAMES is a list of names that should be skipped in the NAMES list."
(while SN
(setq names (remove (car SN) names))
(setq SN (cdr SN))))
- (while (and names table)
- (if (not (semantic-utest-equivalent-tag-p (car names)
- (car table)
- skipnames))
- (error "Expected %s, found %s"
- (semantic-format-tag-prototype (car names))
- (semantic-format-tag-prototype (car table))))
- (setq names (cdr names)
- table (cdr table)))
- (when names (error "Items forgotten: %S"
- (mapcar 'semantic-tag-name names)
- ))
- (when table (error "Items extra: %S"
- (mapcar 'semantic-tag-name table)))
- t)
+ (catch 'utest-err
+ (while (and names table)
+ (when (not (semantic-utest-equivalent-tag-p (car names)
+ (car table)
+ skipnames))
+ (message "Semantic Parse Test Fail: Expected %s, found %s"
+ (semantic-format-tag-prototype (car names))
+ (semantic-format-tag-prototype (car table)))
+ (throw 'utest-err nil)
+ )
+ (setq names (cdr names)
+ table (cdr table)))
+ (when names
+ (message "Semantic Parse Test Fail: Items forgotten: %S" (mapcar 'semantic-tag-name names))
+ (throw 'utest-err nil))
+ (when table
+ (message "Semantic parse Test Fail: Items extra: %S" (mapcar 'semantic-tag-name table))
+ (throw 'utest-err nil))
+ t))
(defun semantic-utest-verify-names (name-contents &optional skipnames)
"Verify the names of the test buffer from NAME-CONTENTS.
@@ -752,32 +716,12 @@ JAVE this thing would need to be recursive to handle java and csharp"
(semantic-utest-taglists-equivalent-p table names skipnames)
))
-;;;;;;;;;;;;;;;;;;;;;;;;
-; JAVE redefine a new validation function
-; is not quite as good as the old one yet
-(defun semantic-utest-verify-names-jave (name-contents &optional skipnames)
- "JAVE version of `semantic-utest-verify-names'.
-NAME-CONTENTS is a sample of the tags buffer to test against.
-SKIPNAMES is a list of names to remove from NAME-CONTENTS"
- (assert (semantic-utest-verify-names-2 name-contents (semantic-fetch-tags))
- nil "failed test")
-)
-
-(defun semantic-utest-verify-names-2 (l1 l2)
- (cond ( (and (consp l1) (equal (car l1) 'overlay))
- (overlayp l2))
- ((not (consp l1))
- (equal l1 l2))
- ((consp l1)
- (and (semantic-utest-verify-names-2 (car l1) (car l2)) (semantic-utest-verify-names-2 (cdr l1) (cdr l2))))
- (t (error "internal error"))))
-
-
-
-
;;; Kill indicator line
;;
+;; Utilities to modify the buffer for reparse, making sure a specific tag is deleted
+;; via the incremental parser.
+
(defvar semantic-utest-last-kill-text nil
"The text from the last kill.")
@@ -792,8 +736,8 @@ SKIPNAMES is a list of names to remove from NAME-CONTENTS"
(beginning-of-line)
(setq semantic-utest-last-kill-pos (point))
(setq semantic-utest-last-kill-text
- (buffer-substring (point) (point-at-eol)))
- (delete-region (point) (point-at-eol))
+ (buffer-substring (point) (pos-eol)))
+ (delete-region (point) (pos-eol))
(insert insertme)
(sit-for 0)
)
@@ -801,15 +745,12 @@ SKIPNAMES is a list of names to remove from NAME-CONTENTS"
(defun semantic-utest-unkill-indicator ()
"Unkill the last indicator."
(goto-char semantic-utest-last-kill-pos)
- (delete-region (point) (point-at-eol))
+ (delete-region (point) (pos-eol))
(insert semantic-utest-last-kill-text)
(sit-for 0)
)
-;;; EDITING TESTS
-;;
-
-(defun semantic-utest-last-invalid (name-contents names-removed killme insertme)
+(defun semantic-utest-last-invalid (_name-contents _names-removed killme insertme)
"Make the last fcn invalid."
(semantic-utest-kill-indicator killme insertme)
; (semantic-utest-verify-names name-contents names-removed); verify its gone ;new validator doesn't handle skipnames yet
@@ -818,50 +759,4 @@ SKIPNAMES is a list of names to remove from NAME-CONTENTS"
-
-;"#<overlay from \\([0-9]+\\) to \\([0-9]+\\) in \\([^>]*\\)>"
-;#<overlay from \([0-9]+\) to \([0-9]+\) in \([^>]*\)>
-;(overlay \1 \2 "\3")
-
-
-;; JAVE
-;; these are some unit tests for cedet that I got from Eric and modified a bit for:
-;; python
-;; javascript
-;; java
-;; I tried to generalize the structure of the tests a bit to make it easier to add languages
-
-;; Mail from Eric:
-;; Many items in the checklist look like:
-
-;; M-x global-semantic-highlight-edits-mode RET
-;; - Edit a file. See the highlight of newly inserted text.
-;; - Customize `semantic-edits-verbose-flag' to be non-nil.
-;; - Wait for the idle scheduler, it should clean up the edits.
-;; - observe messages from incremental parser. Do they relate
-;; to the edits?
-;; - M-x bovinate RET - verify your changes are reflected.
-
-;; It's all about watching the behavior. Timers go off, things get
-;; cleaned up, you type in new changes, etc. An example I tried to
-;; do is below, but covers only 1 language, and not very well at that.
-;; I seem to remember seeing a unit test framework going by one of the
-;; lists. I'm not sure if that would help.
-
-;; Another that might be automatable:
-
-;; M-x semantic-analyze-current-context RET
-;; - Do this in different contexts in your language
-;; files. Verify that reasonable results are returned
-;; such as identification of assignments, function arguments, etc.
-
-;; Anyway, those are some ideas. Any effort you put it will be helpful!
-
-;; Thanks
-;; Eric
-
-;; -----------
-
-
-
;;; semantic-utest.el ends here
diff --git a/test/lisp/cedet/semantic/bovine/gcc-tests.el b/test/lisp/cedet/semantic/bovine/gcc-tests.el
new file mode 100644
index 00000000000..041773a0c80
--- /dev/null
+++ b/test/lisp/cedet/semantic/bovine/gcc-tests.el
@@ -0,0 +1,131 @@
+;;; gcc-tests.el --- Tests for semantic/bovine/gcc.el -*- lexical-binding:t -*-
+
+;; Copyright (C) 2003-2022 Free Software Foundation, Inc.
+
+;; Author: Eric M. Ludlam <zappo@gnu.org>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Moved here from test/manual/cedet/semantic-tests.el
+
+;;; Code:
+
+(require 'ert)
+(require 'ert-x)
+(require 'semantic/bovine/gcc)
+
+;;; From bovine-gcc:
+
+;; Example output of "gcc -v"
+(defvar semantic-gcc-test-strings
+ '(;; My old box:
+ "Reading specs from /usr/lib/gcc-lib/i386-redhat-linux/3.2.2/specs
+Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --disable-checking --with-system-zlib --enable-__cxa_atexit --host=i386-redhat-linux
+Thread model: posix
+gcc version 3.2.2 20030222 (Red Hat Linux 3.2.2-5)"
+ ;; Alex Ott:
+ "Using built-in specs.
+Target: i486-linux-gnu
+Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.3.1-9ubuntu1' --with-bugurl=file:///usr/share/doc/gcc-4.3/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --enable-nls --with-gxx-include-dir=/usr/include/c++/4.3 --program-suffix=-4.3 --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --enable-mpfr --enable-targets=all --enable-checking=release --build=i486-linux-gnu --host=i486-linux-gnu --target=i486-linux-gnu
+Thread model: posix
+gcc version 4.3.1 (Ubuntu 4.3.1-9ubuntu1)"
+ ;; My debian box:
+ "Using built-in specs.
+Target: x86_64-unknown-linux-gnu
+Configured with: ../../../sources/gcc/configure --prefix=/usr/local/glibc-2.3.6/x86_64/apps/gcc-4.2.3 --with-gmp=/usr/local/gcc/gmp --with-mpfr=/usr/local/gcc/mpfr --enable-languages=c,c++,fortran --with-as=/usr/local/glibc-2.3.6/x86_64/apps/gcc-4.2.3/bin/as --with-ld=/usr/local/glibc-2.3.6/x86_64/apps/gcc-4.2.3/bin/ld --disable-multilib
+Thread model: posix
+gcc version 4.2.3"
+ ;; My mac:
+ "Using built-in specs.
+Target: i686-apple-darwin8
+Configured with: /private/var/tmp/gcc/gcc-5341.obj~1/src/configure --disable-checking -enable-werror --prefix=/usr --mandir=/share/man --enable-languages=c,objc,c++,obj-c++ --program-transform-name=/^[cg][^.-]*$/s/$/-4.0/ --with-gxx-include-dir=/include/c++/4.0.0 --with-slibdir=/usr/lib --build=powerpc-apple-darwin8 --with-arch=pentium-m --with-tune=prescott --program-prefix= --host=i686-apple-darwin8 --target=i686-apple-darwin8
+Thread model: posix
+gcc version 4.0.1 (Apple Computer, Inc. build 5341)"
+ ;; Ubuntu Intrepid
+ "Using built-in specs.
+Target: x86_64-linux-gnu
+Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.3.2-1ubuntu12' --with-bugurl=file:///usr/share/doc/gcc-4.3/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --enable-nls --with-gxx-include-dir=/usr/include/c++/4.3 --program-suffix=-4.3 --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --enable-mpfr --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
+Thread model: posix
+gcc version 4.3.2 (Ubuntu 4.3.2-1ubuntu12)"
+ ;; Red Hat EL4
+ "Reading specs from /usr/lib/gcc/x86_64-redhat-linux/3.4.6/specs
+Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --disable-checking --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-java-awt=gtk --host=x86_64-redhat-linux
+Thread model: posix
+gcc version 3.4.6 20060404 (Red Hat 3.4.6-10)"
+ ;; Red Hat EL5
+ "Using built-in specs.
+Target: x86_64-redhat-linux
+Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-libgcj-multifile --enable-languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk --disable-dssi --enable-plugin --with-java-home=/usr/lib/jvm/java-1.4.2-gcj-1.4.2.0/jre --with-cpu=generic --host=x86_64-redhat-linux
+Thread model: posix
+gcc version 4.1.2 20080704 (Red Hat 4.1.2-44)"
+ ;; David Engster's german gcc on ubuntu 4.3
+ "Es werden eingebaute Spezifikationen verwendet.
+Ziel: i486-linux-gnu
+Konfiguriert mit: ../src/configure -v --with-pkgversion='Ubuntu 4.3.2-1ubuntu12' --with-bugurl=file:///usr/share/doc/gcc-4.3/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --enable-nls --with-gxx-include-dir=/usr/include/c++/4.3 --program-suffix=-4.3 --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --enable-mpfr --enable-targets=all --enable-checking=release --build=i486-linux-gnu --host=i486-linux-gnu --target=i486-linux-gnu
+Thread-Modell: posix
+gcc-Version 4.3.2 (Ubuntu 4.3.2-1ubuntu12)"
+ ;; Damien Deville bsd
+ "Using built-in specs.
+Target: i386-undermydesk-freebsd
+Configured with: FreeBSD/i386 system compiler
+Thread model: posix
+gcc version 4.2.1 20070719 [FreeBSD]"
+ )
+ "A bunch of sample gcc -v outputs from different machines.")
+
+(defvar semantic-gcc-test-strings-fail
+ '(;; A really old solaris box I found
+ "Reading specs from /usr/local/gcc-2.95.2/lib/gcc-lib/sparc-sun-solaris2.6/2.95.2/specs
+gcc version 2.95.2 19991024 (release)"
+ )
+ "A bunch of sample gcc -v outputs that fail to provide the info we want.")
+
+(defun semantic-gcc-test-output-parser ()
+ "Test the output parser against some collected strings."
+ (dolist (S semantic-gcc-test-strings)
+ (let* ((fields (semantic-gcc-fields S))
+ (v (cdr (assoc 'version fields)))
+ (h (or (cdr (assoc 'target fields))
+ (cdr (assoc '--target fields))
+ (cdr (assoc '--host fields))))
+ (p (cdr (assoc '--prefix fields))))
+ ;; No longer test for prefixes.
+ (when (not (and v h))
+ (let ((strs (split-string S "\n")))
+ (error "Test failed on %S\nV H P:\n%S %S %S" (car strs) v h p)))))
+ (dolist (S semantic-gcc-test-strings-fail)
+ (let* ((fields (semantic-gcc-fields S))
+ (v (cdr (assoc 'version fields)))
+ (h (or (cdr (assoc '--host fields))
+ (cdr (assoc 'target fields))))
+ (p (cdr (assoc '--prefix fields)))
+ )
+ (when (and v h p)
+ (error "Negative test failed on %S" S)))))
+
+(ert-deftest semantic-gcc-test-output-parser ()
+ (semantic-gcc-test-output-parser))
+
+(ert-deftest semantic-gcc-test-output-parser-this-machine ()
+ "Test the output parser against the machine currently running Emacs."
+ (skip-unless (and (executable-find "gcc")
+ (not (ert-gcc-is-clang-p))))
+ (let ((semantic-gcc-test-strings (list (semantic-gcc-query "gcc" "-v"))))
+ (semantic-gcc-test-output-parser)))
+
+;;; gcc-tests.el ends here
diff --git a/test/lisp/cedet/semantic/format-resources/test-fmt.cpp b/test/lisp/cedet/semantic/format-resources/test-fmt.cpp
new file mode 100644
index 00000000000..39843a22194
--- /dev/null
+++ b/test/lisp/cedet/semantic/format-resources/test-fmt.cpp
@@ -0,0 +1,108 @@
+/** test-fmt.cpp --- Signatures, and format answers for testing
+ *
+ * Copyright (C) 2012, 2016, 2019-2022 Free Software Foundation, Inc.
+ *
+ * Author: Eric M. Ludlam <zappo@gnu.org>
+ *
+ * This file is part of GNU Emacs.
+ *
+ * GNU Emacs is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GNU Emacs is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+/*
+ * About semantic-fmt-utest :
+ *
+ * These tests validate two features:
+ * 1) The C++ parser can parse the different signatures
+ * 2) The semantic-tag-format-* functions can recreate them.
+ *
+ */
+
+void basic_fcn() { }
+/*
+ * ## name "basic_fcn"
+ * ## abbreviate "basic_fcn()"
+ * ## prototype "void basic_fcn ()"
+ * ## uml-prototype "basic_fcn () : void"
+ */
+
+int twoargs_fcn(int a, char b) { }
+/*
+ * ## name "twoargs_fcn"
+ * ## abbreviate "twoargs_fcn()"
+ * ## prototype "int twoargs_fcn (int a,char b)"
+ * ## uml-prototype "twoargs_fcn (a : int,b : char) : int"
+ */
+
+struct moose {
+ int field1;
+ char field2;
+};
+/*
+ * ## name "moose"
+ * ## abbreviate "moose{}"
+ * ## prototype "struct moose {}"
+ * ## uml-prototype "moose{} : struct"
+ */
+
+struct moose struct_fcn ( struct moose in, char *out);
+/*
+ * ## name "struct_fcn"
+ * ## abbreviate "struct_fcn()"
+ * ## prototype "struct moose struct_fcn (struct moose in,char* out)"
+ * ## uml-prototype "struct_fcn (in : struct moose,out : char*) : struct moose"
+ */
+
+struct moose *var_one = NULL;
+/*
+ * ## name "var_one"
+ * ## summarize "Variables: struct moose* var_one[=NULL]"
+ * ## prototype "struct moose* var_one[=NULL]"
+ * ## uml-prototype "var_one : struct moose*"
+ */
+
+const int var_two = 1;
+/*
+ * ## name "var_two"
+ * ## summarize "Variables: const int var_two[=1]"
+ * ## prototype "const int var_two[=1]"
+ * ## uml-prototype "var_two : int"
+ */
+
+namespace NS {
+ enum TestEnum {a,b};
+}
+/*
+ * ## name "NS"
+ * ## summarize "Types: namespace NS {}"
+ * ## prototype "namespace NS {}"
+ * ## uml-prototype "NS{} : namespace"
+ */
+
+
+// void func_ns_arg(NS::TestEnum v = NS::a); <<--- TODO - bring FIX from CEDET on SF
+/*
+ * # # name "func_ns_arg"
+ * # # summarize "Functions: void func_ns_arg (NS::TestEnum v[=NS::a])"
+ * # # prototype "void func_ns_arg (NS::TestEnum v[=NS::a])"
+ * # # uml-prototype "func_ns_arg (v : NS::TestEnum) : void"
+ */
+
+//int const var_three = 1;
+/*
+ * # # name "var_three"
+ * # # summarize "Variables: int const var_three" <-- this fails
+ * # # prototype "int const var_three" <-- this fails
+ * # # uml-prototype "var_three : int"
+ */
diff --git a/test/lisp/cedet/semantic/format-resources/test-fmt.el b/test/lisp/cedet/semantic/format-resources/test-fmt.el
new file mode 100644
index 00000000000..5fcb8ef3c36
--- /dev/null
+++ b/test/lisp/cedet/semantic/format-resources/test-fmt.el
@@ -0,0 +1,65 @@
+;;; test-fmt.el --- test semantic tag formatting -*- lexical-binding: t -*-
+
+;; Copyright (C) 2012-2022 Free Software Foundation, Inc.
+
+;; Author: Eric M. Ludlam <zappo@gnu.org>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+;;
+;;
+
+;;; Code:
+(require 'semantic)
+;;
+;; ## name "semantic"
+;; ## abbreviate "semantic<>"
+;; ## summarize "Requires: semantic"
+
+(defun test-fmt-1 (a)
+ "Function with 1 arg.")
+;;
+;; ## name "test-fmt-1"
+;; ## abbreviate "(test-fmt-1)"
+;; ## summarize "Defuns: (test-fmt-1 a)"
+;; ## short-doc "Function with 1 arg."
+;; ## uml-prototype "(test-fmt-1 a)" <-- That is probably wrong.
+
+(defvar test-fmt-var nil
+ "Variable test.")
+;;
+;; ## name "test-fmt-var"
+;; ## abbreviate "test-fmt-var"
+;; ## summarize "Variables: test-fmt-var"
+;; ## short-doc "Variable test."
+;; ## uml-prototype "test-fmt-var"
+
+(defclass test-fmt-class ()
+ ((slot1 :initarg :slot1))
+ "Class for testing.")
+;;
+;; ## name "test-fmt-class"
+;; ## abbreviate "test-fmt-class{}"
+;; ## summarize "Types: class test-fmt-class {}"
+;; ## short-doc "Class for testing."
+;; ## uml-prototype "class test-fmt-class {}"
+
+
+
+(provide 'test-fmt)
+
+;;; test-fmt.el ends here
diff --git a/test/lisp/cedet/semantic/format-tests.el b/test/lisp/cedet/semantic/format-tests.el
new file mode 100644
index 00000000000..f698d865c3c
--- /dev/null
+++ b/test/lisp/cedet/semantic/format-tests.el
@@ -0,0 +1,95 @@
+;;; semantic/format-tests.el --- Parsing / Formatting tests -*- lexical-binding:t -*-
+
+;; Copyright (C) 2003-2022 Free Software Foundation, Inc.
+
+;; Author: Eric M. Ludlam <zappo@gnu.org>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Unit tests for the formatting feature.
+;;
+;; Using test code from the tests source directory, parse the source
+;; file. After parsing, read the comments for each signature, and
+;; make sure that the semantic-tag-format-* functions in question
+;; created the desired output.
+
+;;; Code:
+
+(require 'ert)
+(require 'ert-x)
+(require 'semantic/format)
+
+(defvar semantic-fmt-utest-file-list
+ (list (ert-resource-file "test-fmt.cpp")
+ ;; "tests/test-fmt.el" - add this when elisp is support by dflt in Emacs
+ )
+ "List of files to run unit tests in.")
+
+(ert-deftest semantic-fmt-utest ()
+ "Visit all file entries, and run formatting test. "
+ (save-current-buffer
+ (semantic-mode 1)
+ (dolist (fname semantic-fmt-utest-file-list)
+ (let ((fb (find-buffer-visiting fname))
+ (b (semantic-find-file-noselect fname))
+ (tags nil))
+ (save-current-buffer
+ (set-buffer b)
+ (should (semantic-active-p))
+ ;;(error "Cannot open %s for format tests" fname))
+
+ ;; This will force a reparse, removing any chance of semanticdb cache
+ ;; using stale data.
+ (semantic-clear-toplevel-cache)
+ ;; Force the reparse
+ (setq tags (semantic-fetch-tags))
+
+ (save-excursion
+ (while tags
+ (let* ((T (car tags))
+ (start (semantic-tag-end T))
+ (end (if (cdr tags)
+ (semantic-tag-start (car (cdr tags)))
+ (point-max)))
+ (TESTS nil))
+ (goto-char start)
+ ;; Scan the space between tags for all test condition matches.
+ (while (re-search-forward "## \\([a-z-]+\\) \"\\([^\n\"]+\\)\"$" end t)
+ (push (cons (match-string 1) (match-string 2)) TESTS))
+ (setq TESTS (nreverse TESTS))
+
+ (dolist (TST TESTS)
+ (let* ( ;; For each test, convert CAR into a semantic-format-tag* fcn
+ (sym (intern (concat "semantic-format-tag-" (car TST))))
+ ;; Convert the desired result from a string syntax to a string.
+ (desired (cdr TST))
+ ;; What does the fmt function do?
+ (actual (funcall sym T)))
+ (when (not (string= desired actual))
+ (should-not (list "Desired" desired
+ "Actual" actual
+ "Formatter" (car TST)))))))
+ (setq tags (cdr tags)))))
+
+ ;; If it wasn't already in memory, whack it.
+ (when (and b (not fb))
+ (kill-buffer b))))))
+
+(provide 'format-tests)
+
+;;; format-tests.el ends here
diff --git a/test/lisp/cedet/semantic/fw-tests.el b/test/lisp/cedet/semantic/fw-tests.el
new file mode 100644
index 00000000000..c8bfffb3cf5
--- /dev/null
+++ b/test/lisp/cedet/semantic/fw-tests.el
@@ -0,0 +1,45 @@
+;;; fw-tests.el --- Tests for semantic/fw.el -*- lexical-binding:t -*-
+
+;; Copyright (C) 2003-2022 Free Software Foundation, Inc.
+
+;; Author: Eric M. Ludlam <zappo@gnu.org>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Moved here from test/manual/cedet/semantic-tests.el
+
+;;; Code:
+
+(require 'ert)
+(require 'semantic/fw)
+
+;;; From semantic-fw:
+
+(ert-deftest semantic-test-data-cache ()
+ "Test the data cache."
+ (let ((data '(a b c)))
+ (with-current-buffer (get-buffer-create " *semantic-test-data-cache*")
+ (erase-buffer)
+ (insert "The Moose is Loose")
+ (goto-char (point-min))
+ (semantic-cache-data-to-buffer (current-buffer) (point) (+ (point) 5)
+ data 'moose 'exit-cache-zone)
+ ;; retrieve cached data
+ (should (equal (semantic-get-cache-data 'moose) data)))))
+
+;;; fw-tests.el ends here
diff --git a/test/lisp/cedet/srecode-utest-getset.el b/test/lisp/cedet/srecode-utest-getset.el
new file mode 100644
index 00000000000..fbcb0ad4cf1
--- /dev/null
+++ b/test/lisp/cedet/srecode-utest-getset.el
@@ -0,0 +1,178 @@
+;;; srecode/test-getset.el --- Test the getset inserter. -*- lexical-binding:t -*-
+
+;; Copyright (C) 2008-2009, 2011, 2019-2022 Free Software Foundation,
+;; Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+;;
+;; Unit tests for the getset inserter application.
+
+(require 'srecode/semantic)
+
+;;; Code:
+(defvar srecode-utest-getset-pre-fill
+ "// Test Class for getset tests in c++.
+
+class myClass {
+public:
+ myClass() { };
+ ~myClass() { };
+ /** miscFunction
+ */
+ int miscFunction(int);
+
+private:
+ int fStartingField;
+
+};
+
+"
+ "The pre-fill class for the getset tests.")
+
+
+;;; Master Harness
+;;
+(defvar srecode-utest-getset-testfile
+ (expand-file-name
+ (concat (make-temp-name "srecode-utest-getset-") ".cpp")
+ temporary-file-directory)
+ "File used to do testing.")
+
+(defvar srecode-insert-getset-fully-automatic-flag) ; Silence byte-compiler.
+(ert-deftest srecode-utest-getset-output ()
+ "Test various template insertion options."
+ :tags '(:expensive-test)
+ (save-excursion
+ (let ((testbuff (find-file-noselect srecode-utest-getset-testfile))
+ (srecode-insert-getset-fully-automatic-flag t))
+
+ (set-buffer testbuff)
+ (semantic-mode 1)
+ (srecode-load-tables-for-mode major-mode)
+ (srecode-load-tables-for-mode major-mode 'getset)
+
+ (should (srecode-table))
+ ;;(error "No template table found for mode %s" major-mode))
+
+ (condition-case nil
+ (erase-buffer)
+ (error nil))
+
+ (insert srecode-utest-getset-pre-fill)
+ (goto-char (point-min))
+
+ ;; Test PRE FILL
+ (should-not
+ (srecode-utest-getset-tagcheck '("public"
+ "myClass"
+ "myClass"
+ "miscFunction"
+ "private"
+ "fStartingField")))
+ (should-not
+ (srecode-utest-getset-jumptotag "fStartingField"))
+
+ ;; Startup with fully automatic selection.
+ (srecode-insert-getset)
+
+ ;; * Post get-set "StartingField"
+ (should-not
+ (srecode-utest-getset-tagcheck '("public"
+ "myClass"
+ "myClass"
+ "getStartingField"
+ "setStartingField"
+ "miscFunction"
+ "private"
+ "fStartingField")))
+
+ ;; Now try convenience args.
+ (goto-char (point-min))
+ (should-not
+ (srecode-utest-getset-jumptotag "fStartingField"))
+ (end-of-line)
+ (insert "\n")
+
+ (srecode-insert-getset nil "AutoInsertField")
+
+ ;; * Post get-set "AutoInsertField"
+ (should-not
+ (srecode-utest-getset-tagcheck '("public"
+ "myClass"
+ "myClass"
+ "getStartingField"
+ "setStartingField"
+ "getAutoInsertField"
+ "setAutoInsertField"
+ "miscFunction"
+ "private"
+ "fStartingField"
+ "fAutoInsertField")))
+
+ ;; Make sure all the comments are in the right place.
+ (should-not
+ (srecode-utest-getset-jumptotag "miscFunction"))
+
+ (let ((pos (point)))
+ (forward-comment -1)
+ (re-search-forward "miscFunction" pos))
+
+ ))
+ (when (file-exists-p srecode-utest-getset-testfile)
+ (delete-file srecode-utest-getset-testfile))
+ )
+
+(defun srecode-utest-getset-tagcheck (expected-members)
+ "Make sure that the tags in myClass have EXPECTED-MEMBERS."
+ (semantic-fetch-tags)
+ (let* ((mc (semantic-find-tags-by-name "myClass" (current-buffer)))
+ (mem (semantic-tag-type-members (car mc)))
+ (fail nil))
+ (catch 'fail-early
+ (while (and mem expected-members)
+ (when (not (string= (semantic-tag-name (car mem))
+ (car expected-members)))
+ (switch-to-buffer (current-buffer))
+ (setq fail (format "Did not find %s in %s" (car expected-members)
+ (buffer-file-name)))
+ (throw 'fail-early nil))
+ (setq mem (cdr mem)
+ expected-members (cdr expected-members)))
+ (when expected-members
+ (switch-to-buffer (current-buffer))
+ (setq fail (format "Did not find all expected tags in class: %s" (buffer-file-name)))
+ (throw 'fail-early t))
+ (when mem
+ (switch-to-buffer (current-buffer))
+ (setq fail (format "Found extra tags in class: %s" (buffer-file-name)))))
+
+ (when fail (message "%s" (buffer-string)))
+ fail))
+
+(defun srecode-utest-getset-jumptotag (tagname)
+ "Jump to the tag named TAGNAME."
+ (semantic-fetch-tags)
+ (let ((fail nil)
+ (tag (semantic-deep-find-tags-by-name tagname (current-buffer))))
+ (if tag
+ (semantic-go-to-tag (car tag))
+ (setq fail (format "Failed to jump to tag %s" tagname)))
+ fail))
+
+(provide 'cedet/srecode/test-getset)
+;;; srecode/test-getset.el ends here
diff --git a/test/lisp/cedet/srecode-utest-template.el b/test/lisp/cedet/srecode-utest-template.el
new file mode 100644
index 00000000000..87c28c6af12
--- /dev/null
+++ b/test/lisp/cedet/srecode-utest-template.el
@@ -0,0 +1,377 @@
+;;; srecode-utest-template.el --- SRecode Core Template tests. -*- lexical-binding:t -*-
+
+;; Copyright (C) 2008-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+;;
+;; Tests of SRecode template insertion routines and tricks.
+;;
+
+
+(require 'srecode/map)
+(require 'srecode/insert)
+(require 'srecode/dictionary)
+
+
+;;; Code:
+
+;;; MAP DUMP TESTING
+(defun srecode-utest-map-reset ()
+ "Reset, then dump the map of SRecoder templates.
+Probably should be called `describe-srecode-maps'."
+ (interactive)
+ (message "SRecode Template Path: %S" srecode-map-load-path)
+ ;; Interactive call allows us to dump.
+ (call-interactively 'srecode-get-maps)
+ (switch-to-buffer "*SRECODE MAP*")
+ (message (buffer-string))
+ )
+
+;;; OUTPUT TESTING
+;;
+(defclass srecode-utest-output ()
+ ((point :initarg :point
+ :type string
+ :documentation
+ "Name of this test point.")
+ (name :initarg :name
+ :type string
+ :documentation
+ "Name of the template tested.")
+ (output :initarg :output
+ :type string
+ :documentation
+ "Expected output of the template.")
+ (dict-entries :initarg :dict-entries
+ :initform nil
+ :type list
+ :documentation
+ "Additional dictionary entries to specify.")
+ (pre-fill :initarg :pre-fill
+ :type (or null string)
+ :initform nil
+ :documentation
+ "Text to prefill a buffer with.
+Place cursor on the ! and delete it.
+If there is a second !, the put the mark there."))
+ "A single template test.")
+
+(cl-defmethod srecode-utest-test ((o srecode-utest-output))
+ "Perform the insertion and test the output.
+Assumes that the current buffer is the testing buffer.
+Return NIL on success, or a diagnostic on failure."
+ (let ((fail nil))
+ (catch 'fail-early
+ (with-slots (name (output-1 output) dict-entries pre-fill) o
+ ;; Prepare buffer: erase content and maybe insert pre-fill
+ ;; content.
+ (erase-buffer)
+ (insert (or pre-fill ""))
+ (goto-char (point-min))
+ (let ((start nil))
+ (when (re-search-forward "!" nil t)
+ (goto-char (match-beginning 0))
+ (setq start (point))
+ (replace-match ""))
+ (when (re-search-forward "!" nil t)
+ (push-mark (match-beginning 0) t t)
+ (replace-match ""))
+ (when start (goto-char start)))
+
+ ;; Find a template, perform an insertion and validate the output.
+ (let ((dict (srecode-create-dictionary))
+ (temp (or (srecode-template-get-table
+ (srecode-table) name "test" 'tests)
+ (progn
+ (srecode-map-update-map)
+ (srecode-template-get-table
+ (srecode-table) name "test" 'tests))
+ (progn
+ (setq fail (format "Test template \"%s\" for `%s' not loaded!"
+ name major-mode))
+ (throw 'fail-early t)
+ )))
+ (srecode-handle-region-when-non-active-flag t))
+
+ ;; RESOLVE AND INSERT
+ (let ((entry dict-entries))
+ (while entry
+ (srecode-dictionary-set-value
+ dict (nth 0 entry) (nth 1 entry))
+ (setq entry (nthcdr 1 entry))))
+
+ (srecode-insert-fcn temp dict)
+
+ ;; COMPARE THE OUTPUT
+ (let ((actual (buffer-substring-no-properties
+ (point-min) (point-max))))
+ (if (string= output-1 actual)
+ nil
+
+ (goto-char (point-max))
+ (insert "\n\n ------------- ^^ actual ^^ ------------\n\n
+ ------------- vv expected vv ------------\n\n"
+ output-1)
+ (setq fail
+ (list (format "Entry %s failed:" (oref o point))
+ (buffer-string))
+ )))))
+ )
+ fail))
+
+;;; ARG HANDLER
+;;
+(defun srecode-semantic-handle-:utest (dict)
+ "Add macros into the dictionary DICT for unit testing purposes."
+ (srecode-dictionary-set-value dict "UTESTVAR1" "ARG HANDLER ONE")
+ (srecode-dictionary-set-value dict "UTESTVAR2" "ARG HANDLER TWO")
+ )
+
+(defun srecode-semantic-handle-:utestwitharg (dict)
+ "Add macros into the dictionary DICT based on other vars in DICT."
+ (let ((val1 (srecode-dictionary-lookup-name dict "UTWA"))
+ (nval1 nil))
+ ;; If there is a value, mutate it
+ (if (and val1 (stringp val1))
+ (setq nval1 (upcase val1))
+ ;; No value, make stuff up
+ (setq nval1 "NO VALUE"))
+
+ (srecode-dictionary-set-value dict "UTESTARGXFORM" nval1))
+
+ (let ((dicts (srecode-dictionary-lookup-name dict "UTLOOP")))
+ (dolist (D dicts)
+ ;; For each dictionary, lookup NAME, and transform into
+ ;; something in DICT instead.
+ (let ((sval (srecode-dictionary-lookup-name D "NAME")))
+ (srecode-dictionary-set-value dict (concat "FOO_" sval) sval)
+ )))
+ )
+
+;;; TEST POINTS
+;;
+(defvar srecode-utest-output-entries
+ (list
+ (srecode-utest-output
+ :point "test1" :name "test"
+ :output (concat ";; " (user-full-name) "\n"
+ ";; " (upcase (user-full-name))) )
+ (srecode-utest-output
+ :point "subs" :name "subs"
+ :output ";; Before Loop
+;; After Loop" )
+ (srecode-utest-output
+ :point "firstlast" :name "firstlast"
+ :output "
+;; << -- FIRST
+;; I'm First
+;; I'm Not Last
+;; -- >>
+
+;; << -- MIDDLE
+;; I'm Not First
+;; I'm Not Last
+;; -- >>
+
+;; << -- LAST
+;; I'm Not First
+;; I'm Last
+;; -- >>
+" )
+ (srecode-utest-output
+ :point "gapsomething" :name "gapsomething"
+ :output ";; First Line
+### ALL ALONE ON A LINE ###
+;;Second Line"
+ :pre-fill ";; First Line
+!;;Second Line")
+ (srecode-utest-output
+ :point "wrapsomething" :name "wrapsomething"
+ :output ";; Put this line in front:
+;; First Line
+;; Put this line at the end:"
+ :pre-fill "!;; First Line
+!")
+ (srecode-utest-output
+ :point "inlinetext" :name "inlinetext"
+ :output ";; A big long comment XX*In the middle*XX with cursor in middle"
+ :pre-fill ";; A big long comment XX!XX with cursor in middle")
+
+ (srecode-utest-output
+ :point "wrapinclude-basic" :name "wrapinclude-basic"
+ :output ";; An includable we could use.
+;; \n;; Text after a point inserter."
+ )
+ (srecode-utest-output
+ :point "wrapinclude-basic2" :name "wrapinclude-basic"
+ :output ";; An includable MOOSE we could use.
+;; \n;; Text after a point inserter."
+ :dict-entries '("COMMENT" "MOOSE")
+ )
+ (srecode-utest-output
+ :point "wrapinclude-around" :name "wrapinclude-around"
+ :output ";; An includable we could use.
+;; [VAR]Intermediate Comments
+;; Text after a point inserter."
+ )
+ (srecode-utest-output
+ :point "wrapinclude-around1" :name "wrapinclude-around"
+ :output ";; An includable PENGUIN we could use.
+;; [VAR]Intermediate Comments
+;; Text after a point inserter."
+ :dict-entries '("COMMENT" "PENGUIN")
+ )
+ (srecode-utest-output
+ :point "complex-subdict" :name "complex-subdict"
+ :output ";; I have a cow and a dog.")
+ (srecode-utest-output
+ :point "wrap-new-template" :name "wrap-new-template"
+ :output "template newtemplate
+\"A nice doc string goes here.\"
+----
+Random text in the new template
+----
+bind \"a\""
+ :dict-entries '( "NAME" "newtemplate" "KEY" "a" )
+ )
+ (srecode-utest-output
+ :point "column-data" :name "column-data"
+ :output "Table of Values:
+Left Justified | Right Justified
+FIRST | FIRST
+VERY VERY LONG STRIN | VERY VERY LONG STRIN
+MIDDLE | MIDDLE
+S | S
+LAST | LAST")
+ (srecode-utest-output
+ :point "custom-arg-handler" :name "custom-arg-handler"
+ :output "OUTSIDE SECTION: ARG HANDLER ONE
+INSIDE SECTION: ARG HANDLER ONE")
+ (srecode-utest-output
+ :point "custom-arg-w-arg none" :name "custom-arg-w-arg"
+ :output "Value of xformed UTWA: NO VALUE")
+ (srecode-utest-output
+ :point "custom-arg-w-arg upcase" :name "custom-arg-w-arg"
+ :dict-entries '( "UTWA" "uppercaseme" )
+ :output "Value of xformed UTWA: UPPERCASEME")
+ (srecode-utest-output
+ :point "custom-arg-w-subdict" :name "custom-arg-w-subdict"
+ :output "All items here: item1 item2 item3")
+
+ ;; Test cases for new "section ... end" dictionary syntax
+ (srecode-utest-output
+ :point "nested-dictionary-syntax-flat"
+ :name "nested-dictionary-syntax-flat"
+ :output "sub item1")
+ (srecode-utest-output
+ :point "nested-dictionary-syntax-nesting"
+ :name "nested-dictionary-syntax-nesting"
+ :output "item11-item11-item21-item31 item21-item11-item21-item31 item31-item311-item321 ")
+ (srecode-utest-output
+ :point "nested-dictionary-syntax-mixed"
+ :name "nested-dictionary-syntax-mixed"
+ :output "item1 item2"))
+ "Test point entries for the template output tests.")
+
+;;; Master Harness
+;;
+(defvar srecode-utest-testfile
+ (expand-file-name (concat (make-temp-name "srecode-utest-") ".srt") temporary-file-directory)
+ "File used to do testing.")
+
+(ert-deftest srecode-utest-template-output ()
+ "Test various template insertion options."
+ (save-excursion
+ (let ((testbuff (find-file-noselect srecode-utest-testfile)))
+
+ (set-buffer testbuff)
+
+ (srecode-load-tables-for-mode major-mode)
+ (srecode-load-tables-for-mode major-mode 'tests)
+
+ (should (srecode-table major-mode))
+
+ ;; Loop over the output testpoints.
+ (dolist (p srecode-utest-output-entries)
+ (should-not (srecode-utest-test p)))))
+
+ (when (file-exists-p srecode-utest-testfile)
+ (delete-file srecode-utest-testfile)))
+
+;;; Project test
+;;
+;; Test that "project" specification works ok.
+
+(ert-deftest srecode-utest-project ()
+ "Test that project filtering works."
+ (save-excursion
+ (let ((testbuff (find-file-noselect srecode-utest-testfile))
+ (temp nil))
+
+ (set-buffer testbuff)
+ (erase-buffer)
+
+ ;; Load the basics, and test that we can't find the application templates.
+ (srecode-load-tables-for-mode major-mode)
+
+ (should (srecode-table major-mode))
+
+ (setq temp (srecode-template-get-table (srecode-table)
+ "test-project"
+ "test"
+ 'tests
+ ))
+ (when temp
+ (should-not "App Template Loaded when not specified."))
+
+ ;; Load the application templates, and make sure we can find them.
+ (srecode-load-tables-for-mode major-mode 'tests)
+
+ (dolist (table (oref (srecode-table) tables))
+ (when (gethash "test" (oref table contexthash))
+ (oset table project default-directory)))
+
+ (setq temp (srecode-template-get-table (srecode-table)
+ "test-project"
+ "test"
+ 'tests
+ ))
+
+ (when (not temp)
+ (should-not "Failed to load app specific template when available."))
+
+ ;; Temporarily change the home of this file. This will make the
+ ;; project template go out of scope.
+ (let ((default-directory (expand-file-name "~/")))
+
+ (setq temp (srecode-template-get-table (srecode-table)
+ "test-project"
+ "test"
+ 'tests
+ ))
+
+ (when temp
+ (should-not "Project specific template available when in wrong directory."))
+
+ )))
+ (when (file-exists-p srecode-utest-testfile)
+ (delete-file srecode-utest-testfile)))
+
+
+(provide 'cedet/srecode-utest-template)
+;;; srecode-utest-template.el ends here
diff --git a/test/lisp/cedet/srecode/document-tests.el b/test/lisp/cedet/srecode/document-tests.el
new file mode 100644
index 00000000000..5341bb09366
--- /dev/null
+++ b/test/lisp/cedet/srecode/document-tests.el
@@ -0,0 +1,78 @@
+;;; document-tests.el --- Tests for srecode/document.el -*- lexical-binding:t -*-
+
+;; Copyright (C) 2008-2022 Free Software Foundation, Inc.
+
+;; Author: Eric M. Ludlam <zappo@gnu.org>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Extracted from srecode-document.el in the CEDET distribution.
+
+;; Converted to ert from test/manual/cedet/srecode-tests.el
+
+;;; Code:
+
+(require 'ert)
+(require 'srecode/document)
+
+;; FIXME: This test fails even before conversion to ert.
+(ert-deftest srecode-document-function-comment-extract-test ()
+ "Test old comment extraction.
+Dump out the extracted dictionary."
+ :tags '(:unstable)
+ (srecode-load-tables-for-mode major-mode)
+ (srecode-load-tables-for-mode major-mode 'document)
+
+ (should (srecode-table))
+ ;; (error "No template table found for mode %s" major-mode)
+
+ (let* ((temp (srecode-template-get-table (srecode-table)
+ "function-comment"
+ "declaration"
+ 'document))
+ (fcn-in (semantic-current-tag)))
+
+ (should temp)
+ ;; (error "No templates for function comments")
+
+ ;; Try to figure out the tag we want to use.
+ (should fcn-in)
+ (should (semantic-tag-of-class-p fcn-in 'function))
+ ;; (error "No tag of class 'function to insert comment for")
+
+ (let ((lextok (semantic-documentation-comment-preceding-tag fcn-in 'lex)))
+
+ (should lextok)
+ ;; (error "No comment to attempt an extraction")
+
+ (let ((s (semantic-lex-token-start lextok))
+ (e (semantic-lex-token-end lextok))
+ (extract nil))
+
+ (pulse-momentary-highlight-region s e)
+
+ ;; Extract text from the existing comment.
+ (setq extract (srecode-extract temp s e))
+
+ (with-output-to-temp-buffer "*SRECODE DUMP*"
+ (princ "EXTRACTED DICTIONARY FOR ")
+ (princ (semantic-tag-name fcn-in))
+ (princ "\n--------------------------------------------\n")
+ (srecode-dump extract))))))
+
+;;; document-tests.el ends here
diff --git a/test/manual/cedet/srecode-tests.el b/test/lisp/cedet/srecode/fields-tests.el
index 5d387a2d0c7..292ac4e3b5e 100644
--- a/test/manual/cedet/srecode-tests.el
+++ b/test/lisp/cedet/srecode/fields-tests.el
@@ -1,8 +1,8 @@
-;;; srecode-tests.el --- Some tests for CEDET's srecode
+;;; srecode/fields-tests.el --- Tests for srecode/fields.el -*- lexical-binding: t -*-
-;; Copyright (C) 2008-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2022 Free Software Foundation, Inc.
-;; Author: Eric M. Ludlam <eric@siege-engine.com>
+;; Author: Eric M. Ludlam <zappo@gnu.org>
;; This file is part of GNU Emacs.
@@ -21,13 +21,15 @@
;;; Commentary:
-;; Extracted from srecode-fields.el and srecode-document.el in the
-;; CEDET distribution.
+;; Extracted from srecode-fields.el in the CEDET distribution.
+
+;; Converted to ert from test/manual/cedet/srecode-tests.el
;;; Code:
;;; From srecode-fields:
+(require 'ert)
(require 'srecode/fields)
(defvar srecode-field-utest-text
@@ -36,15 +38,10 @@
It is filled with some text."
"Text for tests.")
-(defun srecode-field-utest ()
- "Test the srecode field manager."
- (interactive)
- (if (featurep 'xemacs)
- (message "There is no XEmacs support for SRecode Fields.")
- (srecode-field-utest-impl)))
-
-(defun srecode-field-utest-impl ()
+;; FIXME: This test fails even before conversion to ert.
+(ert-deftest srecode-field-utest-impl ()
"Implementation of the SRecode field utest."
+ :tags '(:unstable)
(save-excursion
(find-file "/tmp/srecode-field-test.txt")
@@ -60,21 +57,20 @@ It is filled with some text."
(end-of-line)
(forward-word -1)
- (setq f (srecode-field "Test"
- :name "TEST"
+ (setq f (srecode-field :name "TEST"
:start 6
:end 8))
(when (or (not (slot-boundp f 'overlay)) (not (oref f overlay)))
(error "Field test: Overlay info not created for field"))
- (when (and (overlay-p (oref f overlay))
+ (when (and (overlayp (oref f overlay))
(not (overlay-get (oref f overlay) 'srecode-init-only)))
(error "Field creation overlay is not tagged w/ init flag"))
(srecode-overlaid-activate f)
- (when (or (not (overlay-p (oref f overlay)))
+ (when (or (not (overlayp (oref f overlay)))
(overlay-get (oref f overlay) 'srecode-init-only))
(error "New field overlay not created during activation"))
@@ -102,19 +98,17 @@ It is filled with some text."
(reg nil)
(fields
(list
- (srecode-field "Test1" :name "TEST-1" :start 5 :end 10)
- (srecode-field "Test2" :name "TEST-2" :start 15 :end 20)
- (srecode-field "Test3" :name "TEST-3" :start 25 :end 30)
+ (srecode-field :name "TEST-1" :start 5 :end 10)
+ (srecode-field :name "TEST-2" :start 15 :end 20)
+ (srecode-field :name "TEST-3" :start 25 :end 30)
- (srecode-field "Test4" :name "TEST-4" :start 35 :end 35))
- ))
+ (srecode-field :name "TEST-4" :start 35 :end 35))))
(when (not (= (length srecode-field-archive) 4))
(error "Region Test: Found %d fields. Expected 4"
(length srecode-field-archive)))
- (setq reg (srecode-template-inserted-region "REG"
- :start 4
+ (setq reg (srecode-template-inserted-region :start 4
:end 40))
(srecode-overlaid-activate reg)
@@ -133,15 +127,15 @@ It is filled with some text."
;; Various sizes
(mapc (lambda (T)
- (if (string= (object-name-string T) "Test4")
+ (if (string= (eieio-object-name-string T) "Test4")
(progn
(when (not (srecode-empty-region-p T))
(error "Field %s is not empty"
- (object-name T)))
+ (eieio-object-name T)))
)
(when (not (= (srecode-region-size T) 5))
(error "Calculated size of %s was not 5"
- (object-name T)))))
+ (eieio-object-name T)))))
fields)
;; Make sure things stay up after a 'command'.
@@ -153,21 +147,21 @@ It is filled with some text."
(when (not (eq (srecode-overlaid-at-point 'srecode-field)
(nth 0 fields)))
(error "Region Test: Field %s not under point"
- (object-name (nth 0 fields))))
+ (eieio-object-name (nth 0 fields))))
(srecode-field-next)
(when (not (eq (srecode-overlaid-at-point 'srecode-field)
(nth 1 fields)))
(error "Region Test: Field %s not under point"
- (object-name (nth 1 fields))))
+ (eieio-object-name (nth 1 fields))))
(srecode-field-prev)
(when (not (eq (srecode-overlaid-at-point 'srecode-field)
(nth 0 fields)))
(error "Region Test: Field %s not under point"
- (object-name (nth 0 fields))))
+ (eieio-object-name (nth 0 fields))))
;; Move cursor out of the region and have everything cleaned up.
(goto-char 42)
@@ -178,7 +172,7 @@ It is filled with some text."
(mapc (lambda (T)
(when (slot-boundp T 'overlay)
(error "Overlay did not clear off of field %s"
- (object-name T))))
+ (eieio-object-name T))))
fields)
;; End of LET
@@ -186,11 +180,10 @@ It is filled with some text."
;; Test variable linkage.
(let* ((srecode-field-archive nil)
- (f1 (srecode-field "Test1" :name "TEST" :start 6 :end 8))
- (f2 (srecode-field "Test2" :name "TEST" :start 28 :end 30))
- (f3 (srecode-field "Test3" :name "NOTTEST" :start 35 :end 40))
- (reg (srecode-template-inserted-region "REG" :start 4 :end 40))
- )
+ (f1 (srecode-field :name "TEST" :start 6 :end 8))
+ (f2 (srecode-field :name "TEST" :start 28 :end 30))
+ (f3 (srecode-field :name "NOTTEST" :start 35 :end 40))
+ (reg (srecode-template-inserted-region :start 4 :end 40)))
(srecode-overlaid-activate reg)
(when (not (string= (srecode-overlaid-text f1)
@@ -235,62 +228,8 @@ It is filled with some text."
(error "Linkage Test: tail-insert string on dissimilar fields is now the same"))
;; Cleanup
- (srecode-delete reg)
- )
-
- (set-buffer-modified-p nil)
-
- (message " All field tests passed.")
- ))
-
-;;; From srecode-document:
-
-(require 'srecode/doc)
-
-(defun srecode-document-function-comment-extract-test ()
- "Test old comment extraction.
-Dump out the extracted dictionary."
- (interactive)
-
- (srecode-load-tables-for-mode major-mode)
- (srecode-load-tables-for-mode major-mode 'document)
-
- (if (not (srecode-table))
- (error "No template table found for mode %s" major-mode))
-
- (let* ((temp (srecode-template-get-table (srecode-table)
- "function-comment"
- "declaration"
- 'document))
- (fcn-in (semantic-current-tag)))
-
- (if (not temp)
- (error "No templates for function comments"))
-
- ;; Try to figure out the tag we want to use.
- (when (or (not fcn-in)
- (not (semantic-tag-of-class-p fcn-in 'function)))
- (error "No tag of class 'function to insert comment for"))
-
- (let ((lextok (semantic-documentation-comment-preceding-tag fcn-in 'lex))
- )
-
- (when (not lextok)
- (error "No comment to attempt an extraction"))
-
- (let ((s (semantic-lex-token-start lextok))
- (e (semantic-lex-token-end lextok))
- (extract nil))
-
- (pulse-momentary-highlight-region s e)
-
- ;; Extract text from the existing comment.
- (setq extract (srecode-extract temp s e))
+ (srecode-delete reg))
- (with-output-to-temp-buffer "*SRECODE DUMP*"
- (princ "EXTRACTED DICTIONARY FOR ")
- (princ (semantic-tag-name fcn-in))
- (princ "\n--------------------------------------------\n")
- (srecode-dump extract))))))
+ (set-buffer-modified-p nil)))
-;;; srecode-tests.el ends here
+;;; srecode/fields-tests.el ends here
diff --git a/test/lisp/char-fold-tests.el b/test/lisp/char-fold-tests.el
index 83d6fa79b1e..e7f5ff6fd2f 100644
--- a/test/lisp/char-fold-tests.el
+++ b/test/lisp/char-fold-tests.el
@@ -1,21 +1,23 @@
;;; char-fold-tests.el --- Tests for char-fold.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2013-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2022 Free Software Foundation, Inc.
;; Author: Artur Malabarba <bruce.connor.am@gmail.com>
-;; This program is free software; you can redistribute it and/or modify
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
-;; This program is distributed in the hope that it will be useful,
+;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
-;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Code:
@@ -24,7 +26,35 @@
(defun char-fold--random-word (n)
(mapconcat (lambda (_) (string (+ 9 (random 117))))
- (make-list n nil) ""))
+ (make-list n nil)))
+
+(defun char-fold--ascii-upcase (string)
+ "Like `upcase' but acts on ASCII characters only."
+ (replace-regexp-in-string "[a-z]+" 'upcase string))
+
+(defun char-fold--ascii-downcase (string)
+ "Like `downcase' but acts on ASCII characters only."
+ (replace-regexp-in-string "[a-z]+" 'downcase string))
+
+(defun char-fold--test-match-exactly (string &rest strings-to-match)
+ (let ((re (concat "\\`" (char-fold-to-regexp string) "\\'")))
+ (dolist (it strings-to-match)
+ (should (string-match re it)))
+ ;; Case folding
+ (let ((case-fold-search t))
+ (dolist (it strings-to-match)
+ (should (string-match (char-fold--ascii-upcase re) (downcase it)))
+ (should (string-match (char-fold--ascii-downcase re) (upcase it)))))))
+
+(defun char-fold--test-no-match-exactly (string &rest strings-to-match)
+ (let ((re (concat "\\`" (char-fold-to-regexp string) "\\'")))
+ (dolist (it strings-to-match)
+ (should-not (string-match re it)))
+ ;; Case folding
+ (let ((case-fold-search t))
+ (dolist (it strings-to-match)
+ (should-not (string-match (char-fold--ascii-upcase re) (downcase it)))
+ (should-not (string-match (char-fold--ascii-downcase re) (upcase it)))))))
(defun char-fold--test-search-with-contents (contents string)
(with-temp-buffer
@@ -35,6 +65,11 @@
(should (char-fold-search-forward string nil 'noerror))
(should (char-fold-search-backward string nil 'noerror))))
+(defun char-fold--permutation (strings)
+ (mapcar (lambda (string)
+ (cons string (remove string strings)))
+ strings))
+
(ert-deftest char-fold--test-consistency ()
(dotimes (n 30)
@@ -54,25 +89,7 @@
(concat w1 "\s\n\s\t\f\t\n\r\t" w2)
(concat w1 (make-string 10 ?\s) w2)))))
-(defun char-fold--ascii-upcase (string)
- "Like `upcase' but acts on ASCII characters only."
- (replace-regexp-in-string "[a-z]+" 'upcase string))
-
-(defun char-fold--ascii-downcase (string)
- "Like `downcase' but acts on ASCII characters only."
- (replace-regexp-in-string "[a-z]+" 'downcase string))
-
-(defun char-fold--test-match-exactly (string &rest strings-to-match)
- (let ((re (concat "\\`" (char-fold-to-regexp string) "\\'")))
- (dolist (it strings-to-match)
- (should (string-match re it)))
- ;; Case folding
- (let ((case-fold-search t))
- (dolist (it strings-to-match)
- (should (string-match (char-fold--ascii-upcase re) (downcase it)))
- (should (string-match (char-fold--ascii-downcase re) (upcase it)))))))
-
-(ert-deftest char-fold--test-some-defaults ()
+(ert-deftest char-fold--test-multi-defaults ()
(dolist (it '(("ffl" . "ffl") ("ffi" . "ffi")
("fi" . "fi") ("ff" . "ff")
("ä" . "ä")))
@@ -82,6 +99,14 @@
(set-char-table-extra-slot char-fold-table 0 multi)
(char-fold--test-match-exactly (car it) (cdr it)))))
+(ert-deftest char-fold--test-multi-lax ()
+ (dolist (it '(("f" . "fi") ("f" . "ff")))
+ (with-temp-buffer
+ (insert (cdr it))
+ (goto-char (point-min))
+ (should (search-forward-regexp
+ (char-fold-to-regexp (car it) 'lax) nil 'noerror)))))
+
(ert-deftest char-fold--test-fold-to-regexp ()
(let ((char-fold-table (make-char-table 'char-fold-table))
(multi (make-char-table 'char-fold-table)))
@@ -102,31 +127,99 @@
(char-fold--test-match-exactly "a1" "xx44" "99")
(char-fold--test-match-exactly "a12" "77" "xx442" "992")
;; Support for this case is disabled. See function definition or:
- ;; https://lists.gnu.org/archive/html/emacs-devel/2015-11/msg02562.html
+ ;; https://lists.gnu.org/r/emacs-devel/2015-11/msg02562.html
;; (char-fold--test-match-exactly "a12" "xxyy")
))
(ert-deftest char-fold--speed-test ()
(dolist (string (append '("tty-set-up-initial-frame-face"
"tty-set-up-initial-frame-face-frame-faceframe-faceframe-faceframe-face")
- (mapcar #'char-fold--random-word '(10 50 100
- 50 100))))
- (message "Testing %s" string)
+ (mapcar #'char-fold--random-word '(10 50 100 50 100))))
;; Make sure we didn't just fallback on the trivial search.
(should-not (string= (regexp-quote string)
(char-fold-to-regexp string)))
(with-temp-buffer
(save-excursion (insert string))
- (let ((time (time-to-seconds (current-time))))
+ (let ((time (time-to-seconds)))
;; Our initial implementation of case-folding in char-folding
;; created a lot of redundant paths in the regexp. Because of
;; that, if a really long string "almost" matches, the regexp
;; engine took a long time to realize that it doesn't match.
(should-not (char-fold-search-forward (concat string "c") nil 'noerror))
;; Ensure it took less than a second.
- (should (< (- (time-to-seconds (current-time))
- time)
- 1))))))
+ (should (< (- (time-to-seconds) time) 1))))))
+
+(ert-deftest char-fold--test-without-customization ()
+ (let* ((matches
+ '(
+ ("'" "’")
+ ("e" "ℯ" "ḗ" "ë" "ë")
+ ("ι"
+ "ί" ;; 1 level decomposition
+ "ί" ;; 2 level decomposition
+ "ΐ" ;; 3 level decomposition
+ )
+ ("ß" "ss")
+ ))
+ (no-matches
+ '(
+ ("и" "й")
+ )))
+ (dolist (strings matches)
+ (apply 'char-fold--test-match-exactly strings))
+ (dolist (strings no-matches)
+ (apply 'char-fold--test-no-match-exactly strings))))
+
+(ert-deftest char-fold--test-with-customization ()
+ :tags '(:expensive-test)
+ ;; FIXME: move some language-specific settings to defaults
+ (let ((char-fold-include
+ (append char-fold-include
+ '(
+ (?o "ø") ;; da no nb nn
+ (?l "ł") ;; pl
+ (?æ "ae")
+ (?→ "->")
+ (?⇒ "=>")
+ )))
+ (char-fold-exclude
+ (append char-fold-exclude
+ '(
+ (?a "å") ;; da no nb nn sv
+ (?a "ä") ;; et fi sv
+ (?o "ö") ;; et fi sv
+ (?n "ñ") ;; es
+ )))
+ (char-fold-symmetric t)
+ (matches
+ '(
+ ("e" "ℯ" "ḗ" "ë" "ë")
+ ("е" "ё" "ё")
+ ("ι" "ί" "ί" "ΐ")
+ ("ß" "ss")
+ ("o" "ø")
+ ("l" "ł")
+ ("æ" "ae")
+ ("→" "->")
+ ("⇒" "=>")
+ ))
+ (no-matches
+ '(
+ ("a" "å")
+ ("a" "ä")
+ ("o" "ö")
+ ("n" "ñ")
+ ("и" "й")
+ ))
+ ;; Don't override global value by char-fold-update-table below
+ char-fold-table)
+ (char-fold-update-table)
+ (dolist (strings matches)
+ (dolist (permutation (char-fold--permutation strings))
+ (apply 'char-fold--test-match-exactly permutation)))
+ (dolist (strings no-matches)
+ (dolist (permutation (char-fold--permutation strings))
+ (apply 'char-fold--test-no-match-exactly permutation)))))
(provide 'char-fold-tests)
;;; char-fold-tests.el ends here
diff --git a/test/lisp/color-tests.el b/test/lisp/color-tests.el
index bc942c3b598..e4e1eda26d3 100644
--- a/test/lisp/color-tests.el
+++ b/test/lisp/color-tests.el
@@ -1,6 +1,6 @@
;;; color-tests.el --- Tests for color.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2017 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2022 Free Software Foundation, Inc.
;; Author: Simen Heggestøyl <simenheg@gmail.com>
;; Keywords:
@@ -220,32 +220,32 @@
(ert-deftest color-tests-lighten-hsl ()
(should (equal (color-lighten-hsl 360 0.5 0.5 0) '(360 0.5 0.5)))
- (should (equal (color-lighten-hsl 360 0.5 0.5 -10) '(360 0.5 0.4)))
+ (should (equal (color-lighten-hsl 360 0.5 0.5 -10) '(360 0.5 0.45)))
(should (equal (color-lighten-hsl 360 0.5 0.5 -500) '(360 0.5 0.0)))
(should
(color-tests--approx-equal
- (color-lighten-hsl 120 0.5 0.8 5) '(120 0.5 0.85)))
+ (color-lighten-hsl 120 0.5 0.8 5) '(120 0.5 0.84)))
(should
(equal (color-lighten-hsl 120 0.5 0.8 500) '(120 0.5 1.0))))
(ert-deftest color-tests-lighten-name ()
- (should (equal (color-lighten-name "black" 100) "#ffffffffffff"))
+ (should (equal (color-lighten-name "black" 100) "#000000000000"))
(should (equal (color-lighten-name "white" 100) "#ffffffffffff"))
(should (equal (color-lighten-name "red" 0) "#ffff00000000"))
- (should (equal (color-lighten-name "red" 10) "#ffff33323332")))
+ (should (equal (color-lighten-name "red" 10) "#ffff19991999")))
(ert-deftest color-tests-darken-hsl ()
(should (equal (color-darken-hsl 360 0.5 0.5 0) '(360 0.5 0.5)))
- (should (equal (color-darken-hsl 360 0.5 0.5 -10) '(360 0.5 0.6)))
+ (should (equal (color-darken-hsl 360 0.5 0.5 -10) '(360 0.5 0.55)))
(should (equal (color-darken-hsl 360 0.5 0.5 -500) '(360 0.5 1.0)))
- (should (equal (color-darken-hsl 120 0.5 0.8 5) '(120 0.5 0.75)))
+ (should (equal (color-darken-hsl 120 0.5 0.8 5) '(120 0.5 0.76)))
(should (equal (color-darken-hsl 120 0.5 0.8 500) '(120 0.5 0.0))))
(ert-deftest color-tests-darken-name ()
(should (equal (color-darken-name "black" 100) "#000000000000"))
(should (equal (color-darken-name "white" 100) "#000000000000"))
(should (equal (color-darken-name "red" 0) "#ffff00000000"))
- (should (equal (color-darken-name "red" 10) "#cccc00000000")))
+ (should (equal (color-darken-name "red" 10) "#e66500000000")))
(provide 'color-tests)
;;; color-tests.el ends here
diff --git a/test/lisp/comint-tests.el b/test/lisp/comint-tests.el
index 06a39ebc393..8402c13daf3 100644
--- a/test/lisp/comint-tests.el
+++ b/test/lisp/comint-tests.el
@@ -1,6 +1,6 @@
-;;; comint-testsuite.el
+;;; comint-tests.el --- Tests for comint.el -*- lexical-binding:t -*-
-;; Copyright (C) 2010-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2022 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -29,16 +29,28 @@
(defvar comint-testsuite-password-strings
'("foo@example.net's password: " ; ssh
"Password for foo@example.org: " ; kinit
+ "Password for 'https://foo@example.org':" ; git push Bug#20910
"Please enter the password for foo@example.org: " ; kinit
"Kerberos password for devnull/root <at> GNU.ORG: " ; ksu
"Enter passphrase: " ; ssh-add
"Enter passphrase (empty for no passphrase): " ; ssh-keygen
"Enter same passphrase again: " ; ssh-keygen
+ "Enter your password: " ; python3 -m twine ... Bug#37636
"Passphrase for key root@GNU.ORG: " ; plink
"[sudo] password for user:" ; Ubuntu sudo
+ "[sudo] user 的密码:" ; localized
+ "doas (user@host) password:" ; OpenBSD doas
+ "PIN for user:" ; Bug#35523
"Password (again):"
"Enter password:"
- "Mot de Passe:" ; localized
+ "(user@host) Password: " ; openssh-8.6p1
+ "Current password:" ; "passwd" (to change password) in Debian.
+ "Enter encryption key: " ; ccrypt
+ "Enter decryption key: " ; ccrypt
+ "Enter encryption key: (repeat) " ; ccrypt
+ "Enter Auth Password:" ; OpenVPN (Bug#35724)
+ "Verify password: " ; zip -e zipfile.zip ... (Bug#47209)
+ "Mot de Passe :" ; localized (Bug#29729)
"Passwort:") ; localized
"List of strings that should match `comint-password-prompt-regexp'.")
@@ -47,8 +59,40 @@
(dolist (str comint-testsuite-password-strings)
(should (string-match comint-password-prompt-regexp str))))
-;; Local Variables:
-;; no-byte-compile: t
-;; End:
+(defun comint-tests/test-password-function (password-function)
+ "PASSWORD-FUNCTION can return nil or a string."
+ (when-let ((cat (executable-find "cat")))
+ (let ((comint-password-function password-function))
+ (cl-letf (((symbol-function 'read-passwd)
+ (lambda (&rest _args) "non-nil")))
+ (with-temp-buffer
+ (make-comint-in-buffer "test-comint-password" (current-buffer) cat)
+ (let ((proc (get-buffer-process (current-buffer))))
+ (set-process-query-on-exit-flag proc nil)
+ (set-process-query-on-exit-flag proc nil)
+ (comint-send-invisible "Password: ")
+ (accept-process-output proc 0.1)
+ (should (string-equal
+ (buffer-substring-no-properties (point-min) (point-max))
+ (concat (or (and password-function
+ (funcall password-function))
+ "non-nil")
+ "\n")))))))))
-;;; comint-testsuite.el ends here
+(ert-deftest comint-test-no-password-function ()
+ "Test that `comint-password-function' not being set does not
+alter normal password flow."
+ (comint-tests/test-password-function nil))
+
+(ert-deftest comint-test-password-function-with-value ()
+ "Test that `comint-password-function' alters normal password
+flow. Hook function returns alternative password."
+ (comint-tests/test-password-function
+ (lambda (&rest _args) "MaGiC-PaSsWoRd789")))
+
+(ert-deftest comint-test-password-function-with-nil ()
+ "Test that `comint-password-function' does not alter the normal
+password flow if it returns a nil value."
+ (comint-tests/test-password-function #'ignore))
+
+;;; comint-tests.el ends here
diff --git a/test/lisp/completion-tests.el b/test/lisp/completion-tests.el
new file mode 100644
index 00000000000..dee6f8d5dda
--- /dev/null
+++ b/test/lisp/completion-tests.el
@@ -0,0 +1,170 @@
+;;; completion-tests.el --- Tests for completion.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'completion)
+
+(ert-deftest completion-test-cmpl-string-case-type ()
+ (should (eq (cmpl-string-case-type "123ABCDEF456") :up))
+ (should (eq (cmpl-string-case-type "123abcdef456") :down))
+ (should (eq (cmpl-string-case-type "123aBcDeF456") :mixed))
+ (should (eq (cmpl-string-case-type "123456") :neither))
+ (should (eq (cmpl-string-case-type "Abcde123") :capitalized)))
+
+(ert-deftest completion-test-cmpl-merge-string-cases ()
+ (should (equal (cmpl-merge-string-cases "AbCdEf456" "abc") "AbCdEf456"))
+ (should (equal (cmpl-merge-string-cases "abcdef456" "ABC") "ABCDEF456"))
+ (should (equal (cmpl-merge-string-cases "ABCDEF456" "Abc") "Abcdef456"))
+ (should (equal (cmpl-merge-string-cases "ABCDEF456" "abc") "abcdef456")))
+
+(ert-deftest completion-test-add-find-delete-tail ()
+ (unwind-protect
+ (progn
+ ;; - Add and Find -
+ (should (equal (add-completion-to-head "banana") '("banana" 0 nil 0)))
+ (should (equal (find-exact-completion "banana") '("banana" 0 nil 0)))
+ (should (equal (find-exact-completion "bana") nil))
+ (should (equal (car (find-cmpl-prefix-entry "ban")) '(("banana" 0 nil 0))))
+ (should (equal (cdr (find-cmpl-prefix-entry "ban")) '(("banana" 0 nil 0))))
+
+ (should (equal (add-completion-to-head "banish") '("banish" 0 nil 0)))
+ (should (equal (find-exact-completion "banish") '("banish" 0 nil 0)))
+ (should (equal (car (find-cmpl-prefix-entry "ban")) '(("banish" 0 nil 0) ("banana" 0 nil 0))))
+ (should (equal (cdr (find-cmpl-prefix-entry "ban")) '(("banana" 0 nil 0))))
+
+ (should (equal (add-completion-to-head "banana") '("banana" 0 nil 0)))
+ (should (equal (car (find-cmpl-prefix-entry "ban")) '(("banana" 0 nil 0) ("banish" 0 nil 0))))
+ (should (equal (cdr (find-cmpl-prefix-entry "ban")) '(("banish" 0 nil 0))))
+
+ ;; - Deleting -
+ (should (equal (add-completion-to-head "banner") '("banner" 0 nil 0)))
+ (delete-completion "banner")
+ (should-not (find-exact-completion "banner"))
+ (should (equal (car (find-cmpl-prefix-entry "ban")) '(("banana" 0 nil 0) ("banish" 0 nil 0))))
+ (should (equal (cdr (find-cmpl-prefix-entry "ban")) '(("banish" 0 nil 0))))
+ (should (equal (add-completion-to-head "banner") '("banner" 0 nil 0)))
+ (delete-completion "banana")
+ (should (equal (car (find-cmpl-prefix-entry "ban")) '(("banner" 0 nil 0) ("banish" 0 nil 0))))
+ (should (equal (cdr (find-cmpl-prefix-entry "ban")) '(("banish" 0 nil 0))))
+ (delete-completion "banner")
+ (delete-completion "banish")
+ (should-not (find-cmpl-prefix-entry "ban"))
+ (should-error (delete-completion "banner"))
+
+ ;; - Tail -
+ (should (equal (add-completion-to-tail-if-new "banana") '("banana" 0 nil 0)))
+ (should (equal (car (find-cmpl-prefix-entry "ban")) '(("banana" 0 nil 0))))
+ (should (equal (cdr (find-cmpl-prefix-entry "ban")) '(("banana" 0 nil 0))))
+ (add-completion-to-tail-if-new "banish") '("banish" 0 nil 0)
+ (should (equal (car (find-cmpl-prefix-entry "ban")) '(("banana" 0 nil 0) ("banish" 0 nil 0))))
+ (should (equal (cdr (find-cmpl-prefix-entry "ban")) '(("banish" 0 nil 0)))))
+ (ignore-errors (kill-completion "banana"))
+ (ignore-errors (kill-completion "banner"))
+ (ignore-errors (kill-completion "banish"))))
+
+(ert-deftest completion-test-add-find-accept-delete ()
+ (unwind-protect
+ (progn
+ ;; - Add and Find -
+ (add-completion "banana" 5 10)
+ (should (equal (find-exact-completion "banana") '("banana" 5 10 0)))
+ (add-completion "banana" 6)
+ (should (equal (find-exact-completion "banana") '("banana" 6 10 0)))
+ (add-completion "banish")
+ (should (equal (car (find-cmpl-prefix-entry "ban")) '(("banish" 0 nil 0) ("banana" 6 10 0))))
+
+ ;; - Accepting -
+ (setq completion-to-accept "banana")
+ (accept-completion)
+ (should (equal (find-exact-completion "banana") '("banana" 7 10 0)))
+ (should (equal (car (find-cmpl-prefix-entry "ban")) '(("banana" 7 10 0) ("banish" 0 nil 0))))
+ (setq completion-to-accept "banish")
+ (add-completion "banner")
+ (should (equal (car (find-cmpl-prefix-entry "ban"))
+ '(("banner" 0 nil 0) ("banish" 1 nil 0) ("banana" 7 10 0))))
+
+ ;; - Deleting -
+ (kill-completion "banish")
+ (should (equal (car (find-cmpl-prefix-entry "ban")) '(("banner" 0 nil 0) ("banana" 7 10 0)))))
+ (ignore-errors (kill-completion "banish"))
+ (ignore-errors (kill-completion "banana"))
+ (ignore-errors (kill-completion "banner"))))
+
+(ert-deftest completion-test-search ()
+ (unwind-protect
+ (progn
+ ;; - Add and Find -
+ (add-completion "banana")
+ (completion-search-reset "ban")
+ (should (equal (car (completion-search-next 0)) "banana"))
+
+ ;; - Discrimination -
+ (add-completion "cumberland")
+ (add-completion "cumberbund")
+ ;; cumbering
+ (completion-search-reset "cumb")
+ (should (equal (car (completion-search-peek t)) "cumberbund"))
+ (should (equal (car (completion-search-next 0)) "cumberbund"))
+ (should (equal (car (completion-search-peek t)) "cumberland"))
+ (should (equal (car (completion-search-next 1)) "cumberland"))
+ (should-not (completion-search-peek nil))
+
+ ;; FIXME
+ ;; (should (equal (completion-search-next 2) "cumbering")) ; {cdabbrev}
+ ;;(completion-search-next 3) --> nil or "cumming" {depends on context}
+
+ (should (equal (car (completion-search-next 1)) "cumberland"))
+
+ ;; FIXME
+ ;; (should (equal (completion-search-peek t) "cumbering")) ; {cdabbrev}
+
+ ;; - Accepting -
+ (should (equal (car (completion-search-next 1)) "cumberland"))
+ (setq completion-to-accept "cumberland")
+ (completion-search-reset "foo")
+ (completion-search-reset "cum")
+ (should (equal (car (completion-search-next 0)) "cumberland"))
+
+ ;; - Deleting -
+ (kill-completion "cumberland")
+ (add-completion "cummings")
+ (completion-search-reset "cum")
+ (should (equal (car (completion-search-next 0)) "cummings"))
+ (should (equal (car (completion-search-next 1)) "cumberbund"))
+
+ ;; - Ignoring Capitalization -
+ (completion-search-reset "CuMb")
+ (should (equal (car (completion-search-next 0)) "cumberbund")))
+ (ignore-errors (kill-completion "banana"))
+ (ignore-errors (kill-completion "cumberland"))
+ (ignore-errors (kill-completion "cumberbund"))
+ (ignore-errors (kill-completion "cummings"))))
+
+(ert-deftest completion-test-lisp-def-regexp ()
+ (should (= (and (string-match *lisp-def-regexp* "\n(defun foo") (match-end 0)) 8))
+ (should (= (and (string-match *lisp-def-regexp* "\n(si:def foo") (match-end 0)) 9))
+ (should (= (and (string-match *lisp-def-regexp* "\n(def-bar foo")(match-end 0)) 10))
+ (should (= (and (string-match *lisp-def-regexp* "\n(defun (foo") (match-end 0)) 9)))
+
+(provide 'completion-tests)
+;;; completion-tests.el ends here
diff --git a/test/lisp/cus-edit-tests.el b/test/lisp/cus-edit-tests.el
new file mode 100644
index 00000000000..0ef5168109b
--- /dev/null
+++ b/test/lisp/cus-edit-tests.el
@@ -0,0 +1,89 @@
+;;; cus-edit-tests.el --- Tests for cus-edit.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'ert-x)
+(eval-when-compile (require 'cl-lib))
+(require 'cus-edit)
+
+(defmacro with-cus-edit-test (buffer &rest body)
+ (declare (indent 1))
+ `(save-window-excursion
+ (unwind-protect
+ (progn ,@body)
+ (when-let ((buf (get-buffer ,buffer)))
+ (kill-buffer buf)))))
+
+
+;;;; showing/hiding obsolete options
+
+(defgroup cus-edit-tests nil "Test."
+ :group 'test-group)
+
+(defcustom cus-edit-tests--obsolete-option-tag nil
+ "This should never be removed; it is obsolete for testing purposes."
+ :type 'boolean
+ :version "917.10") ; a super high version number
+(make-obsolete-variable 'cus-edit-tests--obsolete-option-tag nil "X.X-test")
+(defconst cus-edit-tests--obsolete-option-tag
+ (custom-unlispify-tag-name 'cus-edit-tests--obsolete-option-tag))
+
+(ert-deftest cus-edit-tests-customize-apropos/hide-obsolete ()
+ (with-cus-edit-test "*Customize Apropos*"
+ (customize-apropos "cus-edit-tests")
+ (should-not (search-forward cus-edit-tests--obsolete-option-tag nil t))))
+
+(ert-deftest cus-edit-tests-customize-changed/hide-obsolete ()
+ (with-cus-edit-test "*Customize Changed Options*"
+ (customize-changed "917.2") ;; Some future version.
+ (should-not (search-forward cus-edit-tests--obsolete-option-tag nil t))))
+
+(ert-deftest cus-edit-tests-customize-group/hide-obsolete ()
+ "Check that obsolete variables do not show up."
+ (with-cus-edit-test "*Customize Group: Cus Edit Tests*"
+ (customize-group 'cus-edit-tests)
+ (should-not (search-forward cus-edit-tests--obsolete-option-tag nil t))))
+
+(ert-deftest cus-edit-tests-customize-option/show-obsolete ()
+ (with-cus-edit-test "*Customize Option: Cus Edit Tests Obsolete Option Tag*"
+ (customize-option 'cus-edit-tests--obsolete-option-tag)
+ (goto-char (point-min))
+ (should (search-forward cus-edit-tests--obsolete-option-tag nil t))))
+
+(ert-deftest cus-edit-tests-customize-saved/show-obsolete ()
+ (with-cus-edit-test "*Customize Saved*"
+ (cl-letf (((get 'cus-edit-tests--obsolete-option-tag 'saved-value) '(t)))
+ (customize-saved)
+ (should (search-forward cus-edit-tests--obsolete-option-tag nil t)))))
+
+(defcustom cus-edit-test-foo1 0
+ ""
+ :type 'number)
+
+(ert-deftest test-setopt ()
+ (should (= (setopt cus-edit-test-foo1 1) 1))
+ (should (= cus-edit-test-foo1 1))
+ (should-error (setopt cus-edit-test-foo1 :foo)))
+
+(provide 'cus-edit-tests)
+;;; cus-edit-tests.el ends here
diff --git a/test/lisp/custom-resources/custom--test-theme.el b/test/lisp/custom-resources/custom--test-theme.el
new file mode 100644
index 00000000000..36424cdfcc3
--- /dev/null
+++ b/test/lisp/custom-resources/custom--test-theme.el
@@ -0,0 +1,13 @@
+;;; custom--test-theme.el --- A test theme. -*- lexical-binding:t -*-
+
+(deftheme custom--test
+ "A test theme.")
+
+(custom-theme-set-variables
+ 'custom--test
+ '(custom--test-user-option 'bar)
+ '(custom--test-variable 'bar)
+ '(custom--test-bug-21355-before 'before)
+ '(custom--test-bug-21355-after 'after))
+
+(provide-theme 'custom--test)
diff --git a/test/lisp/custom-tests.el b/test/lisp/custom-tests.el
new file mode 100644
index 00000000000..d1effaa72a8
--- /dev/null
+++ b/test/lisp/custom-tests.el
@@ -0,0 +1,328 @@
+;;; custom-tests.el --- tests for custom.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2018-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'ert-x)
+
+(require 'wid-edit)
+(require 'cus-edit)
+(require 'bytecomp)
+
+(ert-deftest custom-theme--load-path ()
+ "Test `custom-theme--load-path' behavior."
+ (ert-with-temp-directory temporary-file-directory
+ ;; Path is empty.
+ (let ((custom-theme-load-path ()))
+ (should (null (custom-theme--load-path))))
+
+ ;; Path comprises non-existent file.
+ (let* ((name (make-temp-name temporary-file-directory))
+ (custom-theme-load-path (list name)))
+ (should (not (file-exists-p name)))
+ (should (null (custom-theme--load-path))))
+
+ ;; Path comprises existing file.
+ (ert-with-temp-file file
+ (let* ((custom-theme-load-path (list file)))
+ (should (file-exists-p file))
+ (should (not (file-directory-p file)))
+ (should (null (custom-theme--load-path)))))
+
+ ;; Path comprises existing directory.
+ (ert-with-temp-directory dir
+ (let* ((custom-theme-load-path (list dir)))
+ (should (file-directory-p dir))
+ (should (equal (custom-theme--load-path) custom-theme-load-path))))
+
+ ;; Expand `custom-theme-directory' path element.
+ (let ((custom-theme-load-path '(custom-theme-directory)))
+ (let ((custom-theme-directory (make-temp-name temporary-file-directory)))
+ (should (not (file-exists-p custom-theme-directory)))
+ (should (null (custom-theme--load-path))))
+ (ert-with-temp-file custom-theme-directory
+ (should (file-exists-p custom-theme-directory))
+ (should (not (file-directory-p custom-theme-directory)))
+ (should (null (custom-theme--load-path))))
+ (ert-with-temp-directory custom-theme-directory
+ (should (file-directory-p custom-theme-directory))
+ (should (equal (custom-theme--load-path)
+ (list custom-theme-directory)))))
+
+ ;; Expand t path element.
+ (let ((custom-theme-load-path '(t)))
+ (let ((data-directory (make-temp-name temporary-file-directory)))
+ (should (not (file-exists-p data-directory)))
+ (should (null (custom-theme--load-path))))
+ (let ((data-directory temporary-file-directory)
+ (themedir (expand-file-name "themes" temporary-file-directory)))
+ (should (not (file-exists-p themedir)))
+ (should (null (custom-theme--load-path)))
+ (with-temp-file themedir)
+ (should (file-exists-p themedir))
+ (should (not (file-directory-p themedir)))
+ (should (null (custom-theme--load-path)))
+ (delete-file themedir)
+ (make-directory themedir)
+ (should (file-directory-p themedir))
+ (should (equal (custom-theme--load-path) (list themedir)))))))
+
+(ert-deftest custom-tests-require-theme ()
+ "Test `require-theme'."
+ (require 'warnings)
+ (ert-with-temp-directory temporary-file-directory
+ (let* ((default-directory temporary-file-directory)
+ (custom-theme-load-path (list default-directory))
+ (load-path ()))
+ ;; Generate some `.el' and `.elc' files.
+ (with-temp-file "custom-tests--a.el"
+ (insert "(provide 'custom-tests--a)"))
+ (make-empty-file "custom-tests--b.el")
+ (with-temp-file "custom-tests--b.elc"
+ (byte-compile-insert-header nil (current-buffer))
+ (insert "(provide 'custom-tests--b)"))
+ (make-empty-file "custom-tests--c.el")
+ (with-temp-file "custom-tests--d.elc"
+ (byte-compile-insert-header nil (current-buffer)))
+ ;; Load them.
+ (dolist (feature '(a b c d e))
+ (should-not (featurep (intern (format "custom-tests--%s" feature)))))
+ (should (eq (require-theme 'custom-tests--a) 'custom-tests--a))
+ (delete-file "custom-tests--a.el")
+ (dolist (feature '(custom-tests--a custom-tests--b))
+ (should (eq (require-theme feature) feature))
+ (should (featurep feature)))
+ (dolist (feature '(custom-tests--c custom-tests--d))
+ (dolist (noerror '(nil t))
+ (let ((err (should-error (require-theme feature noerror))))
+ (should (string-search "failed to provide feature" (cadr err))))))
+ (should-error (require-theme 'custom-tests--e) :type 'file-missing)
+ (should-not (require-theme 'custom-tests--e t))
+ (dolist (feature '(custom-tests--c custom-tests--d custom-tests--e))
+ (should-not (featurep feature))))))
+
+(defcustom custom--test-user-option 'foo
+ "User option for test."
+ :group 'emacs
+ :type 'symbol)
+
+(defvar custom--test-variable 'foo
+ "Variable for test.")
+
+;; This is demonstrating bug#34027.
+(ert-deftest custom--test-theme-variables ()
+ "Test variables setting with enabling / disabling a custom theme."
+ ;; We load custom-resources/custom--test-theme.el.
+ (let ((custom-theme-load-path `(,(ert-resource-directory))))
+ (load-theme 'custom--test 'no-confirm 'no-enable)
+ ;; The variables have still their initial values.
+ (should (equal custom--test-user-option 'foo))
+ (should (equal custom--test-variable 'foo))
+
+ (custom-set-variables
+ '(custom--test-user-option 'baz)
+ '(custom--test-variable 'baz))
+ ;; The initial values have been changed.
+ (should (equal custom--test-user-option 'baz))
+ (should (equal custom--test-variable 'baz))
+
+ ;; Enable and then disable.
+ (enable-theme 'custom--test)
+ (disable-theme 'custom--test)
+ ;; The variables should have the changed values, by reverting.
+ (should (equal custom--test-user-option 'baz))
+ (should (equal custom--test-variable 'baz))))
+
+;; This tests Bug#5358.
+(ert-deftest custom-test-show-comment-preserves-changes ()
+ "Test that adding a comment doesn't discard modifications in progress."
+ (customize-option 'custom--test-user-option)
+ (let* ((field (seq-find (lambda (widget)
+ (eq custom--test-user-option (widget-value widget)))
+ widget-field-list))
+ (parent (widget-get field :parent))
+ (origvalue (widget-value field)))
+ ;; Move to the end of the text of the widget, and modify it. This
+ ;; modification should be preserved after showing the comment field.
+ (goto-char (widget-field-text-end field))
+ (insert "bar")
+ (custom-comment-show parent)
+ ;; From now on, must use `widget-at' to get the value of the widget.
+ (should-not (eq origvalue (widget-value (widget-at))))
+ (should (eq (widget-get parent :custom-state) 'modified))
+ (should (eq (widget-value (widget-at))
+ (widget-apply field
+ :value-to-external
+ (concat
+ (widget-apply field :value-to-internal origvalue)
+ "bar"))))))
+
+(ert-deftest custom-test-enable-theme-keeps-settings ()
+ "Test that enabling a theme doesn't change its settings."
+ (let* ((custom-theme-load-path `(,(ert-resource-directory)))
+ settings)
+ (load-theme 'custom--test 'no-confirm 'no-enable)
+ (setq settings (get 'custom--test 'theme-settings))
+ (enable-theme 'custom--test)
+ (should (equal settings (get 'custom--test 'theme-settings)))))
+
+(defcustom custom--test-local-option 'initial
+ "Buffer-local user option for testing."
+ :group 'emacs
+ :type '(choice (const initial) (const changed))
+ :local t)
+
+(defcustom custom--test-permanent-option 'initial
+ "Permanently local user option for testing."
+ :group 'emacs
+ :type '(choice (const initial) (const changed))
+ :local 'permanent)
+
+(ert-deftest custom-test-local-option ()
+ "Test :local user options."
+ ;; Initial default values.
+ (should (eq custom--test-local-option 'initial))
+ (should (eq custom--test-permanent-option 'initial))
+ (should (eq (default-value 'custom--test-local-option) 'initial))
+ (should (eq (default-value 'custom--test-permanent-option) 'initial))
+ (let ((obuf (current-buffer)))
+ (with-temp-buffer
+ ;; Changed buffer-local values.
+ (setq custom--test-local-option 'changed)
+ (setq custom--test-permanent-option 'changed)
+ (should (eq custom--test-local-option 'changed))
+ (should (eq custom--test-permanent-option 'changed))
+ (should (eq (default-value 'custom--test-local-option) 'initial))
+ (should (eq (default-value 'custom--test-permanent-option) 'initial))
+ (with-current-buffer obuf
+ (should (eq custom--test-local-option 'initial))
+ (should (eq custom--test-permanent-option 'initial)))
+ ;; Permanent variable remains unchanged.
+ (kill-all-local-variables)
+ (should (eq custom--test-local-option 'initial))
+ (should (eq custom--test-permanent-option 'changed))
+ (should (eq (default-value 'custom--test-local-option) 'initial))
+ (should (eq (default-value 'custom--test-permanent-option) 'initial)))))
+
+;; The following three tests demonstrate Bug#21355.
+;; In this one, we set an user option for the current session and then
+;; we enable a theme that doesn't have a setting for it, ending up with
+;; a non-nil saved-value property. Since the `caar' of the theme-value
+;; property is user (i.e., the user theme setting is active), we might
+;; save the setting to the custom-file, even though it was meant for the
+;; current session only. So there should be a nil saved-value property
+;; for this test to pass.
+(ert-deftest custom-test-no-saved-value-after-enabling-theme ()
+ "Test that we don't record a saved-value property when we shouldn't."
+ (let ((custom-theme-load-path `(,(ert-resource-directory))))
+ (customize-option 'mark-ring-max)
+ (let* ((field (seq-find (lambda (widget)
+ (eq mark-ring-max (widget-value widget)))
+ widget-field-list))
+ (parent (widget-get field :parent)))
+ ;; Move to the editable widget, modify the value and save it.
+ (goto-char (widget-field-text-end field))
+ (insert "0")
+ (widget-apply parent :custom-set)
+ ;; Just setting for the current session should not store a saved-value
+ ;; property.
+ (should-not (get 'mark-ring-max 'saved-value))
+ ;; Now enable and disable the test theme.
+ (load-theme 'custom--test 'no-confirm)
+ (disable-theme 'custom--test)
+ ;; Since the user customized the option, this is OK.
+ (should (eq (caar (get 'mark-ring-max 'theme-value)) 'user))
+ ;; The saved-value property should still be nil.
+ (should-not (get 'mark-ring-max 'saved-value)))))
+
+;; In this second test, we load a theme that has a setting for the user option
+;; above. We must check that we don't end up with a non-nil saved-value
+;; property and a user setting active in the theme-value property, which
+;; means we might inadvertently save the session setting in the custom-file.
+(defcustom custom--test-bug-21355-before 'foo
+ "User option for `custom-test-no-saved-value-after-enabling-theme-2'."
+ :type 'symbol :group 'emacs)
+
+(ert-deftest custom-test-no-saved-value-after-enabling-theme-2 ()
+ "Test that we don't record a saved-value property when we shouldn't."
+ (let ((custom-theme-load-path `(,(ert-resource-directory))))
+ (customize-option 'custom--test-bug-21355-before)
+ (let* ((field (seq-find
+ (lambda (widget)
+ (eq custom--test-bug-21355-before (widget-value widget)))
+ widget-field-list))
+ (parent (widget-get field :parent)))
+ ;; Move to the editable widget, modify the value and save it.
+ (goto-char (widget-field-text-end field))
+ (insert "bar")
+ (widget-apply parent :custom-set)
+ ;; Just setting for the current session should not store a saved-value
+ ;; property.
+ (should-not (get 'custom--test-bug-21355-before 'saved-value))
+ ;; Now load our test theme, which has a setting for
+ ;; `custom--test-bug-21355-before'.
+ (load-theme 'custom--test 'no-confirm 'no-enable)
+ (enable-theme 'custom--test)
+ ;; Since the user customized the option, this is OK.
+ (should (eq (caar (get 'custom--test-bug-21355-before 'theme-value))
+ 'user))
+ ;; But the saved-value property has to be nil, since the user didn't mark
+ ;; this variable to save for future sessions.
+ (should-not (get 'custom--test-bug-21355-before 'saved-value)))))
+
+(defvar custom--test-bug-21355-after)
+
+;; In this test, we check that stashing a theme value for a not yet defined
+;; option works, but that later on if the user customizes the option for the
+;; current session, we might save the theme setting in the custom file.
+(ert-deftest custom-test-no-saved-value-after-customizing-option ()
+ "Test for a nil saved-value after setting an option for the current session."
+ (let ((custom-theme-load-path `(,(ert-resource-directory))))
+ ;; Check that we correctly stashed the value.
+ (load-theme 'custom--test 'no-confirm 'no-enable)
+ (enable-theme 'custom--test)
+ (should (and (not (boundp 'custom--test-bug-21355-after))
+ (eq (eval
+ (car (get 'custom--test-bug-21355-after 'saved-value)))
+ 'after)))
+ ;; Now Emacs finds the defcustom.
+ (defcustom custom--test-bug-21355-after 'initially "..."
+ :type 'symbol :group 'emacs)
+ ;; And we used the stashed value correctly.
+ (should (and (boundp 'custom--test-bug-21355-after)
+ (eq custom--test-bug-21355-after 'after)))
+ ;; Now customize it.
+ (customize-option 'custom--test-bug-21355-after)
+ (let* ((field (seq-find (lambda (widget)
+ (eq custom--test-bug-21355-after
+ (widget-value widget)))
+ widget-field-list))
+ (parent (widget-get field :parent)))
+ ;; Move to the editable widget, modify the value and save it.
+ (goto-char (widget-field-text-end field))
+ (insert "bar")
+ (widget-apply parent :custom-set)
+ ;; The user customized the variable, so this is OK.
+ (should (eq (caar (get 'custom--test-bug-21355-after 'theme-value))
+ 'user))
+ ;; But it was only for the current session, so this should not happen.
+ (should-not (get 'custom--test-bug-21355-after 'saved-value)))))
+
+;;; custom-tests.el ends here
diff --git a/test/lisp/dabbrev-tests.el b/test/lisp/dabbrev-tests.el
index ca1d00ab352..278a59c015c 100644
--- a/test/lisp/dabbrev-tests.el
+++ b/test/lisp/dabbrev-tests.el
@@ -1,6 +1,6 @@
-;;; dabbrev-tests.el --- Test suite for dabbrev.
+;;; dabbrev-tests.el --- Test suite for dabbrev. -*- lexical-binding:t -*-
-;; Copyright (C) 2016-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2022 Free Software Foundation, Inc.
;; Author: Alan Third <alan@idiocy.org>
;; Keywords: dabbrev
@@ -29,14 +29,43 @@
(ert-deftest dabbrev-expand-test ()
"Test for bug#1948.
-When DABBREV-ELIMINATE-NEWLINES is non-nil (the default),
-repeated calls to DABBREV-EXPAND can result in the source of
+When `dabbrev-eliminate-newlines' is non-nil (the default),
+repeated calls to `dabbrev-expand' can result in the source of
first expansion being replaced rather than the destination."
(with-temp-buffer
(insert "ab x\na\nab y")
(goto-char 8)
(save-window-excursion
(set-window-buffer nil (current-buffer))
- ;; M-/ SPC M-/ M-/
- (execute-kbd-macro "\257 \257\257"))
+ (execute-kbd-macro (kbd "M-/ SPC M-/ M-/")))
(should (string= (buffer-string) "ab x\nab y\nab y"))))
+
+(ert-deftest dabbrev-completion-test ()
+ "Test for bug#17899.
+dabbrev-completion should not look for expansions in other
+buffers unless a prefix argument is used."
+ (with-temp-buffer
+ (insert "axy")
+ (with-temp-buffer
+ (insert "abc\na")
+ (goto-char 6)
+ (save-window-excursion
+ (set-window-buffer nil (current-buffer))
+ (execute-kbd-macro (kbd "C-M-/")))
+ (should (string= (buffer-string) "abc\nabc")))))
+
+(ert-deftest dabbrev-completion-test-with-argument ()
+ "Test for bug#17899.
+dabbrev-completion should not complete because it has found
+multiple expansions."
+ (with-temp-buffer
+ (insert "axy")
+ (with-temp-buffer
+ (insert "abc\na")
+ (goto-char 6)
+ (save-window-excursion
+ (set-window-buffer nil (current-buffer))
+ (execute-kbd-macro (kbd "C-u C-u C-M-/")))
+ (should (string= (buffer-string) "abc\na")))))
+
+;;; dabbrev-tests.el ends here
diff --git a/test/lisp/delim-col-tests.el b/test/lisp/delim-col-tests.el
new file mode 100644
index 00000000000..97fa0f1e8f1
--- /dev/null
+++ b/test/lisp/delim-col-tests.el
@@ -0,0 +1,181 @@
+;;; delim-col-tests.el --- Tests for delim-col.el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2019-2022 Free Software Foundation, Inc.
+
+;; Author: Stefan Kangas <stefankangas@gmail.com>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'delim-col)
+
+(ert-deftest delim-col-tests-delimit-columns ()
+ (with-temp-buffer
+ (insert "a b c\n")
+ (delimit-columns-region (point-min) (point-max))
+ (should (equal (buffer-string) "a, b, c\n")))
+ (with-temp-buffer
+ (insert "a b c d\n"
+ "aaaa bb ccc ddddd\n"
+ "aaa bbb cccc dddd\n"
+ "aa bb ccccccc ddd\n")
+ (delimit-columns-region (point-min) (point-max))
+ (should (equal (buffer-string)
+ (concat "a, b, c, d \n"
+ "aaaa, bb, ccc, ddddd\n"
+ "aaa, bbb, cccc, dddd \n"
+ "aa, bb, ccccccc, ddd \n")))))
+
+(ert-deftest delim-col-tests-delimit-rectangle ()
+ (with-temp-buffer
+ (insert "a b c d\n"
+ "aaaa bb ccc ddddd\n"
+ "aaa bbb cccc dddd\n"
+ "aa bb ccccccc ddd\n")
+ (delimit-columns-rectangle 3 58) ; from first b to last c
+ (should (equal (buffer-string)
+ (concat "a b, c d\n"
+ "aaaa bb, ccc ddddd\n"
+ "aaa bbb, cccc dddd\n"
+ "aa bb, ccccccc ddd\n")))))
+
+(ert-deftest delim-col-tests-delimit-columns-str-separator ()
+ (let ((delimit-columns-str-separator ":"))
+ (with-temp-buffer
+ (insert "a b\n")
+ (delimit-columns-region (point-min) (point-max))
+ (should (equal (buffer-string) "a:b\n")))
+ (with-temp-buffer
+ (insert "a b c d\n"
+ "aa bb cc dd\n")
+ (delimit-columns-rectangle 3 16) ; from first b to last c
+ (should (equal (buffer-string)
+ (concat "a b: c d\n"
+ "aa bb:cc dd\n"))))))
+
+(ert-deftest delim-col-tests-delimit-columns-str-before-after ()
+ (let ((delimit-columns-str-before "[ ")
+ (delimit-columns-str-after " ]"))
+ (with-temp-buffer
+ (insert "a b c\n")
+ (delimit-columns-region (point-min) (point-max))
+ (should (equal (buffer-string) "[ a, b, c ]\n")))
+ (with-temp-buffer
+ (insert "a b c d\n"
+ "aaaa bb ccc ddddd\n"
+ "aaa bbb cccc dddd\n"
+ "aa bb ccccccc ddd\n")
+ (delimit-columns-region (point-min) (point-max))
+ (should (equal (buffer-string)
+ (concat "[ a, b, c, d ]\n"
+ "[ aaaa, bb, ccc, ddddd ]\n"
+ "[ aaa, bbb, cccc, dddd ]\n"
+ "[ aa, bb, ccccccc, ddd ]\n"))))
+ (with-temp-buffer
+ (insert "a b c d\n"
+ "aaaa bb ccc ddddd\n"
+ "aaa bbb cccc dddd\n"
+ "aa bb ccccccc ddd\n")
+ (delimit-columns-rectangle 3 58) ; from first b to last c
+ (should (equal (buffer-string)
+ (concat "a [ b, c ] d\n"
+ "aaaa [ bb, ccc ] ddddd\n"
+ "aaa [ bbb, cccc ] dddd\n"
+ "aa [ bb, ccccccc ] ddd\n"))))))
+
+(ert-deftest delim-col-tests-delimit-colummns-before-after ()
+ (let ((delimit-columns-before "<")
+ (delimit-columns-after ">"))
+ (with-temp-buffer
+ (insert "a b\n")
+ (delimit-columns-region (point-min) (point-max))
+ (should (equal (buffer-string) "<a>, <b>\n")))
+ (with-temp-buffer
+ (insert "a b c d\n"
+ "aa bb cc dd\n")
+ (delimit-columns-rectangle 3 17)
+ (should (equal (buffer-string)
+ (concat "a <b>, <c> d\n"
+ "aa <bb>, <cc> dd\n"))))))
+
+(ert-deftest delim-col-tests-delimit-columns-separator ()
+ (let ((delimit-columns-separator ","))
+ (with-temp-buffer
+ (insert "a,b,c\n")
+ (delimit-columns-region (point-min) (point-max))
+ (should (equal (buffer-string) "a, b, c\n")))))
+
+(ert-deftest delim-col-tests-delimit-columns-format/nil ()
+ (let ((delimit-columns-format nil))
+ (with-temp-buffer
+ (insert "a b\n"
+ "aa bb\n")
+ (delimit-columns-region (point-min) (point-max))
+ (should (equal (buffer-string)
+ (concat "a, b\n"
+ "aa, bb\n"))))
+ (with-temp-buffer
+ (insert "a b c d\n"
+ "aa bb cc dd\n")
+ (delimit-columns-rectangle 3 17) ; from first b to last c
+ (should (equal (buffer-string)
+ (concat "a b, c d\n"
+ "aa bb, cc dd\n"))))))
+
+(ert-deftest delim-col-tests-delimit-columns-format/separator ()
+ (let ((delimit-columns-format 'separator)
+ (delimit-columns-before "<")
+ (delimit-columns-after ">"))
+ (with-temp-buffer
+ (insert "a b\n"
+ "aa bb\n")
+ (delimit-columns-region (point-min) (point-max))
+ (should (equal (buffer-string)
+ (concat "<a> , <b> \n"
+ "<aa>, <bb>\n"))))
+ (with-temp-buffer
+ (insert "a b c d\n"
+ "aa bb cc dd\n")
+ (delimit-columns-rectangle 3 17) ; from first b to last c
+ (should (equal (buffer-string)
+ (concat "a <b> , <c> d\n"
+ "aa <bb>, <cc> dd\n"))))))
+
+(ert-deftest delim-col-tests-delimit-columns-format/padding ()
+ (let ((delimit-columns-format 'padding)
+ (delimit-columns-before "<")
+ (delimit-columns-after ">"))
+ (with-temp-buffer
+ (insert "a b\n"
+ "aa bb\n")
+ (delimit-columns-region (point-min) (point-max))
+ (should (equal (buffer-string)
+ (concat "<a >, <b >\n"
+ "<aa>, <bb>\n"))))
+ (with-temp-buffer
+ (insert "a b c d\n"
+ "aa bb cc dd\n")
+ (delimit-columns-rectangle 3 17) ; from first b to last c
+ (should (equal (buffer-string)
+ (concat "a <b >, <c > d\n"
+ "aa <bb>, <cc> dd\n"))))))
+
+(provide 'delim-col-tests)
+;;; delim-col-tests.el ends here
diff --git a/test/lisp/descr-text-tests.el b/test/lisp/descr-text-tests.el
index 538464aad7d..e5547d4f6eb 100644
--- a/test/lisp/descr-text-tests.el
+++ b/test/lisp/descr-text-tests.el
@@ -1,8 +1,8 @@
-;;; descr-text-test.el --- ERT tests for descr-text.el -*- lexical-binding: t -*-
+;;; descr-text-tests.el --- ERT tests for descr-text.el -*- lexical-binding: t -*-
-;; Copyright (C) 2014, 2016-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2014, 2016-2022 Free Software Foundation, Inc.
-;; Author: Michal Nazarewicz <mina86@mina86.com>
+;; Author: Michal Nazarewicz <mina86@mina86.com>
;; This file is part of GNU Emacs.
@@ -75,20 +75,20 @@
(goto-char (point-min))
(should (eq ?a (following-char))) ; make sure we are where we think we are
;; Function should return nil for an ASCII character.
- (should (not (describe-char-eldoc)))
+ (should (not (describe-char-eldoc 'ignore)))
(goto-char (1+ (point)))
(should (eq ?… (following-char)))
(let ((eldoc-echo-area-use-multiline-p t))
;; Function should return description of an Unicode character.
(should (equal "U+2026: Horizontal ellipsis (Po: Punctuation, Other)"
- (describe-char-eldoc))))
+ (describe-char-eldoc 'ignore))))
(goto-char (point-max))
;; At the end of the buffer, function should return nil and not blow up.
- (should (not (describe-char-eldoc)))))
+ (should (not (describe-char-eldoc 'ignore)))))
(provide 'descr-text-test)
-;;; descr-text-test.el ends here
+;;; descr-text-tests.el ends here
diff --git a/test/lisp/desktop-tests.el b/test/lisp/desktop-tests.el
new file mode 100644
index 00000000000..d52fe39ed96
--- /dev/null
+++ b/test/lisp/desktop-tests.el
@@ -0,0 +1,50 @@
+;;; desktop-tests.el --- Tests for desktop.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2020 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'desktop)
+
+(ert-deftest desktop-tests--emacs-pid-running-p ()
+ (should (desktop--emacs-pid-running-p (emacs-pid)))
+ (should-not (desktop--emacs-pid-running-p 1)))
+
+(ert-deftest desktop-tests--load-locked-desktop-p ()
+ (let ((desktop-load-locked-desktop t))
+ (should (desktop--load-locked-desktop-p (emacs-pid)))))
+
+(ert-deftest desktop-tests--load-locked-desktop-p-nil ()
+ (let ((desktop-load-locked-desktop nil))
+ (should-not (desktop--load-locked-desktop-p (emacs-pid)))))
+
+(ert-deftest desktop-tests--load-locked-desktop-p-ask ()
+ (let ((desktop-load-locked-desktop 'ask))
+ (cl-letf (((symbol-function 'y-or-n-p) (lambda (&rest _) t)))
+ (should (desktop--load-locked-desktop-p (emacs-pid))))
+ (cl-letf (((symbol-function 'y-or-n-p) (lambda (&rest _) nil)))
+ (should-not (desktop--load-locked-desktop-p (emacs-pid))))))
+
+(ert-deftest desktop-tests--load-locked-desktop-p-check ()
+ (let ((desktop-load-locked-desktop 'check-pid))
+ (desktop--load-locked-desktop-p (emacs-pid))))
+
+(provide 'desktop-tests)
diff --git a/test/lisp/dired-aux-tests.el b/test/lisp/dired-aux-tests.el
index d41feb1592f..e70898ab74e 100644
--- a/test/lisp/dired-aux-tests.el
+++ b/test/lisp/dired-aux-tests.el
@@ -1,6 +1,6 @@
;;; dired-aux-tests.el --- Test suite for dired-aux. -*- lexical-binding: t -*-
-;; Copyright (C) 2017 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2022 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -19,26 +19,153 @@
;;; Code:
(require 'ert)
+(require 'ert-x)
(require 'dired-aux)
-
+(eval-when-compile (require 'cl-lib))
(ert-deftest dired-test-bug27496 ()
"Test for https://debbugs.gnu.org/27496 ."
(skip-unless (executable-find shell-file-name))
- (let* ((foo (make-temp-file "foo"))
- (files (list foo)))
- (unwind-protect
- (cl-letf (((symbol-function 'y-or-n-p) 'error))
- (dired temporary-file-directory)
- (dired-goto-file foo)
- ;; `dired-do-shell-command' returns nil on success.
- (should-error (dired-do-shell-command "ls ? ./?" nil files))
- (should-error (dired-do-shell-command "ls ./? ?" nil files))
- (should-not (dired-do-shell-command "ls ? ?" nil files))
- (should-error (dired-do-shell-command "ls * ./*" nil files))
- (should-not (dired-do-shell-command "ls * *" nil files))
- (should-not (dired-do-shell-command "ls ? ./`?`" nil files)))
- (delete-file foo))))
+ (ert-with-temp-file foo
+ (let* ((files (list foo)))
+ (cl-letf (((symbol-function 'read-char-from-minibuffer) 'error))
+ (dired temporary-file-directory)
+ (dired-goto-file foo)
+ ;; `dired-do-shell-command' returns nil on success.
+ (should-error (dired-do-shell-command "ls ? ./?" nil files))
+ (should-error (dired-do-shell-command "ls ./? ?" nil files))
+ (should-not (dired-do-shell-command "ls ? ?" nil files))
+ (should-error (dired-do-shell-command "ls * ./*" nil files))
+ (should-not (dired-do-shell-command "ls * *" nil files))
+ (should-not (dired-do-shell-command "ls ? ./`?`" nil files))))))
+
+;; Auxiliary macro for `dired-test-bug28834': it binds
+;; `dired-create-destination-dirs' to CREATE-DIRS and execute BODY.
+;; If YES-OR-NO is non-nil, it binds `yes-or-no-p' to
+;; to avoid the prompt.
+(defmacro with-dired-bug28834-test (create-dirs yes-or-no &rest body)
+ (declare (debug (form symbolp body)))
+ (let ((foo (make-symbol "foo")))
+ `(ert-with-temp-directory ,foo
+ (ert-with-temp-file from
+ (let* ((dired-create-destination-dirs ,create-dirs))
+ (setq to-cp
+ (expand-file-name
+ "foo-cp" (file-name-as-directory (expand-file-name "bar" ,foo))))
+ (setq to-mv
+ (expand-file-name
+ "foo-mv" (file-name-as-directory (expand-file-name "qux" ,foo))))
+ (unwind-protect
+ (if ,yes-or-no
+ (cl-letf (((symbol-function 'yes-or-no-p)
+ (lambda (_prompt) (eq ,yes-or-no 'yes))))
+ ,@body)
+ ,@body)))))))
+
+(ert-deftest dired-test-bug28834 ()
+ "test for https://debbugs.gnu.org/28834 ."
+ (let (to-cp to-mv)
+ ;; `dired-create-destination-dirs' set to 'always.
+ (with-dired-bug28834-test
+ 'always nil
+ (dired-copy-file-recursive from to-cp nil)
+ (should (file-exists-p to-cp))
+ (dired-rename-file from to-mv nil)
+ (should (file-exists-p to-mv)))
+ ;; `dired-create-destination-dirs' set to nil.
+ (with-dired-bug28834-test
+ nil nil
+ (should-error (dired-copy-file-recursive from to-cp nil))
+ (should-error (dired-rename-file from to-mv nil)))
+ ;; `dired-create-destination-dirs' set to 'ask.
+ (with-dired-bug28834-test
+ 'ask 'yes ; Answer `yes'
+ (dired-copy-file-recursive from to-cp nil)
+ (should (file-exists-p to-cp))
+ (dired-rename-file from to-mv nil)
+ (should (file-exists-p to-mv)))
+ (with-dired-bug28834-test
+ 'ask 'no ; Answer `no'
+ (should-error (dired-copy-file-recursive from to-cp nil))
+ (should-error (dired-rename-file from to-mv nil)))))
+
+(ert-deftest dired-test-bug30624 ()
+ "test for https://debbugs.gnu.org/30624 ."
+ (cl-letf* ((target-dir (make-temp-file "target" 'dir))
+ ((symbol-function 'dired-mark-read-file-name)
+ (lambda (&rest _) target-dir))
+ (inhibit-message t))
+ ;; Delete target-dir: `dired-do-create-files' must recreate it.
+ (delete-directory target-dir)
+ (let ((file1 (make-temp-file "bug30624_file1"))
+ (file2 (make-temp-file "bug30624_file2"))
+ (dired-create-destination-dirs 'always)
+ (buf (dired temporary-file-directory)))
+ (unwind-protect
+ (progn
+ (dired-revert)
+ (dired-mark-files-regexp "bug30624_file")
+ (should (dired-do-create-files 'copy 'dired-copy-file "Copy" nil)))
+ (delete-directory target-dir 'recursive)
+ (mapc #'delete-file `(,file1 ,file2))
+ (kill-buffer buf)))))
+
+(defun dired-test--check-highlighting (command positions)
+ (let ((start 1))
+ (dolist (pos positions)
+ (should-not (text-property-not-all start (1- pos) 'face nil command))
+ (should (equal 'warning (get-text-property pos 'face command)))
+ (setq start (1+ pos)))
+ (should-not (text-property-not-all
+ start (length command) 'face nil command))))
+
+(ert-deftest dired-test-highlight-metachar ()
+ "Check that non-isolated meta-characters are highlighted."
+ (let* ((command "sed -r -e 's/oo?/a/' -e 's/oo?/a/' ? `?`")
+ (markers " ^ ^")
+ (result (dired--highlight-no-subst-chars
+ (dired--need-confirm-positions command "?")
+ command
+ t))
+ (lines (split-string result "\n")))
+ (should (= (length lines) 2))
+ (should (string-match (regexp-quote command) (nth 0 lines)))
+ (should (string-match (regexp-quote markers) (nth 1 lines)))
+ (dired-test--check-highlighting (nth 0 lines) '(15 29)))
+ ;; Note that `?` is considered isolated, but `*` is not.
+ (let* ((command "sed -e 's/o*/a/' -e 's/o`*` /a/'")
+ (markers " ^ ^")
+ (result (dired--highlight-no-subst-chars
+ (dired--need-confirm-positions command "*")
+ command
+ t))
+ (lines (split-string result "\n")))
+ (should (= (length lines) 2))
+ (should (string-match (regexp-quote command) (nth 0 lines)))
+ (should (string-match (regexp-quote markers) (nth 1 lines)))
+ (dired-test--check-highlighting (nth 0 lines) '(11 25)))
+ (let* ((command "sed 's/\\?/!/'")
+ (result (dired--highlight-no-subst-chars
+ (dired--need-confirm-positions command "?")
+ command
+ nil))
+ (lines (split-string result "\n")))
+ (should (= (length lines) 1))
+ (should (string-match (regexp-quote command) (nth 0 lines)))
+ (dired-test--check-highlighting (nth 0 lines) '(8))))
+
+(ert-deftest dired-guess-default ()
+ (let ((dired-guess-shell-alist-user nil)
+ (dired-guess-shell-alist-default
+ '(("\\.png\\'" "display")
+ ("\\.gif\\'" "display" "xloadimage")
+ ("\\.gif\\'" "feh")
+ ("\\.jpe?g\\'" "xloadimage"))))
+ (should (equal (dired-guess-default '("/tmp/foo.png")) "display"))
+ (should (equal (dired-guess-default '("/tmp/foo.gif"))
+ '("display" "xloadimage" "feh")))
+ (should (equal (dired-guess-default '("/tmp/foo.png" "/tmp/foo.txt"))
+ nil))))
(provide 'dired-aux-tests)
-;; dired-aux-tests.el ends here
+;;; dired-aux-tests.el ends here
diff --git a/test/lisp/dired-resources/insert-directory/test_dir/bar b/test/lisp/dired-resources/insert-directory/test_dir/bar
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/test/lisp/dired-resources/insert-directory/test_dir/bar
diff --git a/test/lisp/dired-resources/insert-directory/test_dir/foo b/test/lisp/dired-resources/insert-directory/test_dir/foo
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/test/lisp/dired-resources/insert-directory/test_dir/foo
diff --git a/test/lisp/dired-resources/insert-directory/test_dir_other/bar b/test/lisp/dired-resources/insert-directory/test_dir_other/bar
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/test/lisp/dired-resources/insert-directory/test_dir_other/bar
diff --git a/test/lisp/dired-resources/insert-directory/test_dir_other/foo b/test/lisp/dired-resources/insert-directory/test_dir_other/foo
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/test/lisp/dired-resources/insert-directory/test_dir_other/foo
diff --git a/test/lisp/dired-tests.el b/test/lisp/dired-tests.el
index 99006eca3e3..09becc7fe7a 100644
--- a/test/lisp/dired-tests.el
+++ b/test/lisp/dired-tests.el
@@ -1,6 +1,6 @@
;;; dired-tests.el --- Test suite. -*- lexical-binding: t -*-
-;; Copyright (C) 2015-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2022 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -19,17 +19,17 @@
;;; Code:
(require 'ert)
+(require 'ert-x)
(require 'dired)
-(require 'nadvice)
(ert-deftest dired-autoload ()
"Tests to see whether dired-x has been autoloaded"
(should
- (fboundp 'dired-jump))
+ (fboundp 'dired-do-relsymlink))
(should
(autoloadp
(symbol-function
- 'dired-jump))))
+ 'dired-do-relsymlink))))
(ert-deftest dired-test-bug22694 ()
"Test for https://debbugs.gnu.org/22694 ."
@@ -54,7 +54,7 @@
(when (buffer-live-p buf) (kill-buffer buf)))
(delete-directory dir 'recursive))))
-(defvar dired-dwim-target)
+(defvar dired-query)
(ert-deftest dired-test-bug25609 ()
"Test for https://debbugs.gnu.org/25609 ."
(let* ((from (make-temp-file "foo" 'dir))
@@ -142,116 +142,113 @@
(ert-deftest dired-test-bug27243-01 ()
"Test for https://debbugs.gnu.org/cgi/bugreport.cgi?bug=27243#5 ."
- (let* ((test-dir (file-name-as-directory (make-temp-file "test-dir-" t)))
- (save-pos (lambda ()
- (with-current-buffer (car (dired-buffers-for-dir test-dir))
- (dired-save-positions))))
- (dired-auto-revert-buffer t) buffers)
- ;; On MS-Windows, get rid of 8+3 short names in test-dir, if the
- ;; corresponding long file names exist, otherwise such names trip
- ;; dired-buffers-for-dir.
- (if (eq system-type 'windows-nt)
- (setq test-dir (file-truename test-dir)))
- (should-not (dired-buffers-for-dir test-dir))
- (with-current-buffer (find-file-noselect test-dir)
- (make-directory "test-subdir"))
- (message "Saved pos: %S" (funcall save-pos))
- ;; Point must be at end-of-buffer.
- (with-current-buffer (car (dired-buffers-for-dir test-dir))
- (should (eobp)))
- (push (dired test-dir) buffers)
- (message "Saved pos: %S" (funcall save-pos))
- ;; Previous dired call shouldn't create a new buffer: must visit the one
- ;; created by `find-file-noselect' above.
- (should (eq 1 (length (dired-buffers-for-dir test-dir))))
- (unwind-protect
- (let ((buf (current-buffer))
- (pt1 (point))
- (test-file (concat (file-name-as-directory "test-subdir")
- "test-file")))
- (message "Saved pos: %S" (funcall save-pos))
- (write-region "Test" nil test-file nil 'silent nil 'excl)
- (message "Saved pos: %S" (funcall save-pos))
- ;; Sanity check: point should now be on the subdirectory.
- (should (equal (dired-file-name-at-point)
- (concat test-dir (file-name-as-directory "test-subdir"))))
- (message "Saved pos: %S" (funcall save-pos))
- (push (dired-find-file) buffers)
- (let ((pt2 (point))) ; Point is on test-file.
- (pop-to-buffer-same-window buf)
- ;; Sanity check: point should now be back on the subdirectory.
- (should (eq (point) pt1))
+ (ert-with-temp-directory test-dir
+ (let* ((save-pos (lambda ()
+ (with-current-buffer (car (dired-buffers-for-dir test-dir))
+ (dired-save-positions))))
+ (dired-auto-revert-buffer t) buffers)
+ ;; On MS-Windows, get rid of 8+3 short names in test-dir, if the
+ ;; corresponding long file names exist, otherwise such names trip
+ ;; dired-buffers-for-dir.
+ (if (eq system-type 'windows-nt)
+ (setq test-dir (file-truename test-dir)))
+ (should-not (dired-buffers-for-dir test-dir))
+ (with-current-buffer (find-file-noselect test-dir)
+ (make-directory "test-subdir"))
+ (message "Saved pos: %S" (funcall save-pos))
+ ;; Point must be at end-of-buffer.
+ (with-current-buffer (car (dired-buffers-for-dir test-dir))
+ (should (eobp)))
+ (push (dired test-dir) buffers)
+ (message "Saved pos: %S" (funcall save-pos))
+ ;; Previous dired call shouldn't create a new buffer: must visit the one
+ ;; created by `find-file-noselect' above.
+ (should (eq 1 (length (dired-buffers-for-dir test-dir))))
+ (unwind-protect
+ (let ((buf (current-buffer))
+ (pt1 (point))
+ (test-file (concat (file-name-as-directory "test-subdir")
+ "test-file")))
+ (message "Saved pos: %S" (funcall save-pos))
+ (write-region "Test" nil test-file nil 'silent nil 'excl)
+ (message "Saved pos: %S" (funcall save-pos))
+ ;; Sanity check: point should now be on the subdirectory.
+ (should (equal (dired-file-name-at-point)
+ (concat test-dir (file-name-as-directory "test-subdir"))))
+ (message "Saved pos: %S" (funcall save-pos))
(push (dired-find-file) buffers)
- (should (eq (point) pt2))))
- (dolist (buf buffers)
- (when (buffer-live-p buf) (kill-buffer buf)))
- (delete-directory test-dir t))))
+ (let ((pt2 (point))) ; Point is on test-file.
+ (pop-to-buffer-same-window buf)
+ ;; Sanity check: point should now be back on the subdirectory.
+ (should (eq (point) pt1))
+ (push (dired-find-file) buffers)
+ (should (eq (point) pt2))))
+ (dolist (buf buffers)
+ (when (buffer-live-p buf) (kill-buffer buf)))))))
(ert-deftest dired-test-bug27243-02 ()
"Test for https://debbugs.gnu.org/cgi/bugreport.cgi?bug=27243#28 ."
- (let ((test-dir (make-temp-file "test-dir-" t))
- (dired-auto-revert-buffer t) buffers)
- ;; On MS-Windows, get rid of 8+3 short names in test-dir, if the
- ;; corresponding long file names exist, otherwise such names trip
- ;; string comparisons below.
- (if (eq system-type 'windows-nt)
- (setq test-dir (file-truename test-dir)))
- (with-current-buffer (find-file-noselect test-dir)
- (make-directory "test-subdir"))
- (push (dired test-dir) buffers)
- (unwind-protect
- (let ((buf (current-buffer))
- (pt1 (point))
- (test-file (concat (file-name-as-directory "test-subdir")
- "test-file")))
- (write-region "Test" nil test-file nil 'silent nil 'excl)
- ;; Sanity check: point should now be on the subdirectory.
- (should (equal (dired-file-name-at-point)
- (concat (file-name-as-directory test-dir)
- (file-name-as-directory "test-subdir"))))
- (push (dired-find-file) buffers)
- (let ((pt2 (point))) ; Point is on test-file.
+ (ert-with-temp-directory test-dir
+ (let ((dired-auto-revert-buffer t) buffers)
+ ;; On MS-Windows, get rid of 8+3 short names in test-dir, if the
+ ;; corresponding long file names exist, otherwise such names trip
+ ;; string comparisons below.
+ (if (eq system-type 'windows-nt)
+ (setq test-dir (file-truename test-dir)))
+ (with-current-buffer (find-file-noselect test-dir)
+ (make-directory "test-subdir"))
+ (push (dired test-dir) buffers)
+ (unwind-protect
+ (let ((buf (current-buffer))
+ (pt1 (point))
+ (test-file (concat (file-name-as-directory "test-subdir")
+ "test-file")))
+ (write-region "Test" nil test-file nil 'silent nil 'excl)
+ ;; Sanity check: point should now be on the subdirectory.
+ (should (equal (dired-file-name-at-point)
+ (concat (file-name-as-directory test-dir)
+ (file-name-as-directory "test-subdir"))))
+ (push (dired-find-file) buffers)
+ ;; Point is on test-file.
(switch-to-buffer buf)
;; Sanity check: point should now be back on the subdirectory.
(should (eq (point) pt1))
(push (dired test-dir) buffers)
- (should (eq (point) pt1))))
- (dolist (buf buffers)
- (when (buffer-live-p buf) (kill-buffer buf)))
- (delete-directory test-dir t))))
+ (should (eq (point) pt1)))
+ (dolist (buf buffers)
+ (when (buffer-live-p buf) (kill-buffer buf)))))))
(ert-deftest dired-test-bug27243-03 ()
"Test for https://debbugs.gnu.org/cgi/bugreport.cgi?bug=27243#61 ."
- (let ((test-dir (make-temp-file "test-dir-" t))
- (dired-auto-revert-buffer t)
- test-subdir1 test-subdir2 allbufs)
- (unwind-protect
- (progn
- (with-current-buffer (find-file-noselect test-dir)
- (push (current-buffer) allbufs)
- (make-directory "test-subdir1")
- (make-directory "test-subdir2")
- (let ((test-file1 "test-file1")
- (test-file2 "test-file2"))
- (with-current-buffer (find-file-noselect "test-subdir1")
- (push (current-buffer) allbufs)
- (write-region "Test1" nil test-file1 nil 'silent nil 'excl))
- (with-current-buffer (find-file-noselect "test-subdir2")
- (push (current-buffer) allbufs)
- (write-region "Test2" nil test-file2 nil 'silent nil 'excl))))
- ;; Call find-file with a wild card and test point in each file.
- (let ((buffers (find-file (concat (file-name-as-directory test-dir)
- "*")
- t)))
- (dolist (buf buffers)
- (let ((pt (with-current-buffer buf (point))))
- (switch-to-buffer (find-file-noselect test-dir))
- (find-file (buffer-name buf))
- (should (equal (point) pt))))
- (append buffers allbufs)))
- (dolist (buf allbufs)
- (when (buffer-live-p buf) (kill-buffer buf)))
- (delete-directory test-dir t))))
+ (ert-with-temp-directory test-dir
+ (let ((dired-auto-revert-buffer t)
+ allbufs)
+ (unwind-protect
+ (progn
+ (with-current-buffer (find-file-noselect test-dir)
+ (push (current-buffer) allbufs)
+ (make-directory "test-subdir1")
+ (make-directory "test-subdir2")
+ (let ((test-file1 "test-file1")
+ (test-file2 "test-file2"))
+ (with-current-buffer (find-file-noselect "test-subdir1")
+ (push (current-buffer) allbufs)
+ (write-region "Test1" nil test-file1 nil 'silent nil 'excl))
+ (with-current-buffer (find-file-noselect "test-subdir2")
+ (push (current-buffer) allbufs)
+ (write-region "Test2" nil test-file2 nil 'silent nil 'excl))))
+ ;; Call find-file with a wild card and test point in each file.
+ (let ((buffers (find-file (concat (file-name-as-directory test-dir)
+ "*")
+ t)))
+ (dolist (buf buffers)
+ (let ((pt (with-current-buffer buf (point))))
+ (switch-to-buffer (find-file-noselect test-dir))
+ (find-file (buffer-name buf))
+ (should (equal (point) pt))))
+ (append buffers allbufs)))
+ (dolist (buf allbufs)
+ (when (buffer-live-p buf) (kill-buffer buf)))))))
(ert-deftest dired-test-bug7131 ()
"Test for https://debbugs.gnu.org/7131 ."
@@ -275,28 +272,28 @@
;; ls-lisp-tests.el and em-ls-tests.el.
(skip-unless (and (not (featurep 'ls-lisp))
(not (featurep 'eshell))))
- (let* ((dir (make-temp-file "bug27631" 'dir))
- (dir1 (expand-file-name "dir1" dir))
- (dir2 (expand-file-name "dir2" dir))
- (default-directory dir)
- buf)
- (unwind-protect
- (progn
- (make-directory dir1)
- (make-directory dir2)
- (with-temp-file (expand-file-name "a.txt" dir1))
- (with-temp-file (expand-file-name "b.txt" dir2))
- (setq buf (dired (expand-file-name "dir*/*.txt" dir)))
- (dired-toggle-marks)
- (should (cdr (dired-get-marked-files))))
- (delete-directory dir 'recursive)
- (when (buffer-live-p buf) (kill-buffer buf)))))
+ (ert-with-temp-directory dir
+ (let* ((dir1 (expand-file-name "dir1" dir))
+ (dir2 (expand-file-name "dir2" dir))
+ (default-directory dir)
+ buf)
+ (unwind-protect
+ (progn
+ (make-directory dir1)
+ (make-directory dir2)
+ (with-temp-file (expand-file-name "a.txt" dir1))
+ (with-temp-file (expand-file-name "b.txt" dir2))
+ (setq buf (dired (expand-file-name "dir*/*.txt" dir)))
+ (dired-toggle-marks)
+ (should (cdr (dired-get-marked-files))))
+ (when (buffer-live-p buf) (kill-buffer buf))))))
(ert-deftest dired-test-bug27899 ()
"Test for https://debbugs.gnu.org/27899 ."
- (let* ((dir (expand-file-name "src" source-directory))
- (buf (dired (list dir "cygw32.c" "alloc.c" "w32xfns.c" "xdisp.c")))
- (orig dired-hide-details-mode))
+ :tags '(:unstable)
+ (dired (list (expand-file-name "src" source-directory)
+ "cygw32.c" "alloc.c" "w32xfns.c" "xdisp.c"))
+ (let ((orig dired-hide-details-mode))
(dired-goto-file (expand-file-name "cygw32.c"))
(forward-line 0)
(unwind-protect
@@ -310,73 +307,69 @@
(ert-deftest dired-test-bug27968 ()
"Test for https://debbugs.gnu.org/27968 ."
- (let* ((top-dir (make-temp-file "top-dir" t))
- (subdir (expand-file-name "subdir" top-dir))
- (header-len-fn (lambda ()
- (save-excursion
- (goto-char 1)
- (forward-line 1)
- (- (point-at-eol) (point)))))
- orig-len len diff pos line-nb)
- (make-directory subdir 'parents)
- (unwind-protect
- (with-current-buffer (dired-noselect subdir)
- (setq orig-len (funcall header-len-fn)
- pos (point)
- line-nb (line-number-at-pos))
- ;; Bug arises when the header line changes its length; this may
- ;; happen if the used space has changed: for instance, with the
- ;; creation of additional files.
- (make-directory "subdir" t)
- (dired-revert)
- ;; Change the header line.
- (save-excursion
- (goto-char 1)
- (forward-line 1)
- (let ((inhibit-read-only t)
- (new-header " test-bug27968"))
- (delete-region (point) (point-at-eol))
- (when (= orig-len (length new-header))
- ;; Wow lucky guy! I must buy lottery today.
- (setq new-header (concat new-header " :-)")))
- (insert new-header)))
- (setq len (funcall header-len-fn)
- diff (- len orig-len))
- (should-not (zerop diff)) ; Header length has changed.
- ;; If diff > 0, then the point moves back.
- ;; If diff < 0, then the point moves forward.
- ;; If diff = 0, then the point doesn't move.
- ;; Sometimes this point movement causes
- ;; line-nb != (line-number-at-pos pos), so that we get
- ;; an unexpected file at point if we store buffer points.
- ;; Note that the line number before/after revert
- ;; doesn't change.
- (should (= line-nb
- (line-number-at-pos)
- (line-number-at-pos (+ pos diff))))
- ;; After revert, the point must be in 'subdir' line.
- (should (equal "subdir" (dired-get-filename 'local t))))
- (delete-directory top-dir t))))
+ (ert-with-temp-directory top-dir
+ (let* ((subdir (expand-file-name "subdir" top-dir))
+ (header-len-fn (lambda ()
+ (save-excursion
+ (goto-char 1)
+ (forward-line 1)
+ (- (pos-eol) (point)))))
+ orig-len len diff pos line-nb)
+ (make-directory subdir 'parents)
+ (with-current-buffer (dired-noselect subdir)
+ (setq orig-len (funcall header-len-fn)
+ pos (point)
+ line-nb (line-number-at-pos))
+ ;; Bug arises when the header line changes its length; this may
+ ;; happen if the used space has changed: for instance, with the
+ ;; creation of additional files.
+ (make-directory "subdir" t)
+ (dired-revert)
+ ;; Change the header line.
+ (save-excursion
+ (goto-char 1)
+ (forward-line 1)
+ (let ((inhibit-read-only t)
+ (new-header " test-bug27968"))
+ (delete-region (point) (pos-eol))
+ (when (= orig-len (length new-header))
+ ;; Wow lucky guy! I must buy lottery today.
+ (setq new-header (concat new-header " :-)")))
+ (insert new-header)))
+ (setq len (funcall header-len-fn)
+ diff (- len orig-len))
+ (should-not (zerop diff)) ; Header length has changed.
+ ;; If diff > 0, then the point moves back.
+ ;; If diff < 0, then the point moves forward.
+ ;; If diff = 0, then the point doesn't move.
+ ;; Sometimes this point movement causes
+ ;; line-nb != (line-number-at-pos pos), so that we get
+ ;; an unexpected file at point if we store buffer points.
+ ;; Note that the line number before/after revert
+ ;; doesn't change.
+ (should (= line-nb
+ (line-number-at-pos)
+ (line-number-at-pos (+ pos diff))))
+ ;; After revert, the point must be in 'subdir' line.
+ (should (equal "subdir" (dired-get-filename 'local t)))))))
(defmacro dired-test-with-temp-dirs (just-empty-dirs &rest body)
"Helper macro for Bug#27940 test."
(declare (indent 1) (debug body))
- (let ((dir (make-symbol "dir"))
- (ignore-funcs (make-symbol "ignore-funcs")))
- `(let* ((,dir (make-temp-file "bug27940" t))
- (dired-deletion-confirmer (lambda (_) "yes")) ; Suppress prompts.
- (inhibit-message t)
- (default-directory ,dir))
- (dotimes (i 5) (make-directory (format "empty-dir-%d" i)))
- (unless ,just-empty-dirs
- (dotimes (i 5) (make-directory (format "non-empty-%d/foo" i) 'parents)))
- (make-directory "zeta-empty-dir")
- (unwind-protect
- (progn
- ,@body)
- (delete-directory ,dir t)
- (kill-buffer (current-buffer))))))
+ (let ((dir (make-symbol "dir")))
+ `(ert-with-temp-directory ,dir
+ (let* ((dired-deletion-confirmer (lambda (_) "yes")) ; Suppress prompts.
+ (inhibit-message t)
+ (default-directory ,dir))
+ (dotimes (i 5) (make-directory (format "empty-dir-%d" i)))
+ (unless ,just-empty-dirs
+ (dotimes (i 5) (make-directory (format "non-empty-%d/foo" i) 'parents)))
+ (make-directory "zeta-empty-dir")
+ (unwind-protect
+ (progn
+ ,@body)
+ (kill-buffer (current-buffer)))))))
(ert-deftest dired-test-bug27940 ()
"Test for https://debbugs.gnu.org/27940 ."
@@ -384,9 +377,9 @@
(dired-test-with-temp-dirs
'just-empty-dirs
(let (asked)
- (advice-add 'dired--yes-no-all-quit-help
+ (advice-add 'read-answer
:override
- (lambda (_) (setq asked t) "")
+ (lambda (_q _a) (setq asked t) "")
'((name . dired-test-bug27940-advice)))
(dired default-directory)
(dired-toggle-marks)
@@ -395,44 +388,44 @@
(progn
(should-not asked)
(should-not (dired-get-marked-files))) ; All dirs deleted.
- (advice-remove 'dired--yes-no-all-quit-help 'dired-test-bug27940-advice))))
+ (advice-remove 'read-answer 'dired-test-bug27940-advice))))
;; Answer yes
(dired-test-with-temp-dirs
nil
- (advice-add 'dired--yes-no-all-quit-help :override (lambda (_) "yes")
+ (advice-add 'read-answer :override (lambda (_q _a) "yes")
'((name . dired-test-bug27940-advice)))
(dired default-directory)
(dired-toggle-marks)
(dired-do-delete nil)
(unwind-protect
(should-not (dired-get-marked-files)) ; All dirs deleted.
- (advice-remove 'dired--yes-no-all-quit-help 'dired-test-bug27940-advice)))
+ (advice-remove 'read-answer 'dired-test-bug27940-advice)))
;; Answer no
(dired-test-with-temp-dirs
nil
- (advice-add 'dired--yes-no-all-quit-help :override (lambda (_) "no")
+ (advice-add 'read-answer :override (lambda (_q _a) "no")
'((name . dired-test-bug27940-advice)))
(dired default-directory)
(dired-toggle-marks)
(dired-do-delete nil)
(unwind-protect
(should (= 5 (length (dired-get-marked-files)))) ; Just the empty dirs deleted.
- (advice-remove 'dired--yes-no-all-quit-help 'dired-test-bug27940-advice)))
+ (advice-remove 'read-answer 'dired-test-bug27940-advice)))
;; Answer all
(dired-test-with-temp-dirs
nil
- (advice-add 'dired--yes-no-all-quit-help :override (lambda (_) "all")
+ (advice-add 'read-answer :override (lambda (_q _a) "all")
'((name . dired-test-bug27940-advice)))
(dired default-directory)
(dired-toggle-marks)
(dired-do-delete nil)
(unwind-protect
(should-not (dired-get-marked-files)) ; All dirs deleted.
- (advice-remove 'dired--yes-no-all-quit-help 'dired-test-bug27940-advice)))
+ (advice-remove 'read-answer 'dired-test-bug27940-advice)))
;; Answer quit
(dired-test-with-temp-dirs
nil
- (advice-add 'dired--yes-no-all-quit-help :override (lambda (_) "quit")
+ (advice-add 'read-answer :override (lambda (_q _a) "quit")
'((name . dired-test-bug27940-advice)))
(dired default-directory)
(dired-toggle-marks)
@@ -440,8 +433,170 @@
(dired-do-delete nil))
(unwind-protect
(should (= 6 (length (dired-get-marked-files)))) ; All empty dirs but zeta-empty-dir deleted.
- (advice-remove 'dired--yes-no-all-quit-help 'dired-test-bug27940-advice))))
+ (advice-remove 'read-answer 'dired-test-bug27940-advice))))
+
+(ert-deftest dired-test-directory-files ()
+ "Test for `directory-files'."
+ (let ((testdir (expand-file-name
+ "directory-files-test" (temporary-file-directory)))
+ (nod directory-files-no-dot-files-regexp))
+ (unwind-protect
+ (progn
+ (when (file-directory-p testdir)
+ (delete-directory testdir t))
+
+ (make-directory testdir)
+ (when (file-directory-p testdir)
+ ;; directory-empty-p: test non-existent dir
+ (should-not (directory-empty-p "some-imaginary-dir"))
+ (should (= 2 (length (directory-files testdir))))
+ ;; directory-empty-p: test empty dir
+ (should (directory-empty-p testdir))
+ (should-not (directory-files testdir nil nod t 1))
+ (dolist (file '(a b c d))
+ (make-empty-file (expand-file-name (symbol-name file) testdir)))
+ (should (= 6 (length (directory-files testdir))))
+ (should (equal "abcd" (mapconcat #'identity (directory-files
+ testdir nil nod))))
+ (should (= 2 (length (directory-files testdir nil "[bc]"))))
+ (should (= 3 (length (directory-files testdir nil nod nil 3))))
+ (dolist (file '(5 4 3 2 1))
+ (make-empty-file
+ (expand-file-name (number-to-string file) testdir)))
+ ;;(should (= 0 (length (directory-files testdir nil "[0-9]" t -1))))
+ (should (= 5 (length (directory-files testdir nil "[0-9]" t))))
+ (should (= 5 (length (directory-files testdir nil "[0-9]" t 50))))
+ (should-not (directory-empty-p testdir)))
+
+ (delete-directory testdir t)))))
+
+(ert-deftest dired-test-directory-files-and-attributes ()
+ "Test for `directory-files-and-attributes'."
+ (let ((testdir (expand-file-name
+ "directory-files-test" (temporary-file-directory)))
+ (nod directory-files-no-dot-files-regexp))
+
+ (unwind-protect
+ (progn
+ (when (file-directory-p testdir)
+ (delete-directory testdir t))
+
+ (make-directory testdir)
+ (when (file-directory-p testdir)
+ (should (= 2 (length (directory-files testdir))))
+ (should-not (directory-files-and-attributes testdir t nod t 1))
+ (dolist (file '(a b c d))
+ (make-directory (expand-file-name (symbol-name file) testdir)))
+ (should (= 6 (length (directory-files-and-attributes testdir))))
+ (dolist (dir (directory-files-and-attributes testdir t nod))
+ (should (file-directory-p (car dir)))
+ (should-not (file-regular-p (car dir))))
+ (should (= 2 (length
+ (directory-files-and-attributes testdir nil "[bc]"))))
+ (should (= 3 (length
+ (directory-files-and-attributes
+ testdir nil nod nil nil 3))))
+ (dolist (file '(5 4 3 2 1))
+ (make-empty-file
+ (expand-file-name (number-to-string file) testdir)))
+ ;; (should (= 0 (length (directory-files-and-attributes testdir nil
+ ;; "[0-9]" t
+ ;; nil -1))))
+ (should (= 5 (length
+ (directory-files-and-attributes
+ testdir nil "[0-9]" t))))
+ (should (= 5 (length
+ (directory-files-and-attributes
+ testdir nil "[0-9]" t nil 50))))))
+ (when (file-directory-p testdir)
+ (delete-directory testdir t)))))
+
+;; `dired-insert-directory' output tests.
+(let* ((data-dir "insert-directory")
+ (test-dir (file-name-as-directory
+ (ert-resource-file
+ (concat data-dir "/test_dir"))))
+ (test-dir-other (file-name-as-directory
+ (ert-resource-file
+ (concat data-dir "/test_dir_other"))))
+ (test-files `(,test-dir "foo" "bar")) ;expected files to be found
+ ;; Free space test data for `insert-directory'.
+ ;; Meaning: (path free-space-bytes-to-stub expected-free-space-string)
+ (free-data `((,test-dir 10 "available 10 B")
+ (,test-dir-other 100 "available 100 B")
+ (:default 999 "available 999 B"))))
+
+ (defun files-tests--look-up-free-data (path)
+ "Look up free space test data, with a default for unspecified paths."
+ (let ((path (file-name-as-directory path)))
+ (cdr (or (assoc path free-data)
+ (assoc :default free-data)))))
+
+ (defun files-tests--make-file-system-info-stub (&optional static-path)
+ "Return a stub for `file-system-info' using dynamic or static test data.
+If that data should be static, pass STATIC-PATH to choose which
+path's data to use."
+ (lambda (path)
+ (let* ((path (cond (static-path)
+ ;; file-system-info knows how to handle ".", so we
+ ;; do the same thing
+ ((equal "." path) default-directory)
+ (path)))
+ (return-size
+ ;; It is always defined but this silences the byte-compiler:
+ (when (fboundp 'files-tests--look-up-free-data)
+ (car (files-tests--look-up-free-data path)))))
+ (list return-size return-size return-size))))
+
+ (defun files-tests--insert-directory-output (dir &optional _verbose)
+ "Run `insert-directory' and return its output."
+ (with-current-buffer-window "files-tests--insert-directory" nil nil
+ (let ((dired-free-space 'separate))
+ (dired-insert-directory dir "-l" nil nil t))
+ (buffer-substring-no-properties (point-min) (point-max))))
+
+ (ert-deftest files-tests-insert-directory-shows-files ()
+ "Verify `insert-directory' reports the files in the directory."
+ ;; It is always defined but this silences the byte-compiler:
+ (when (fboundp 'files-tests--insert-directory-output)
+ (let* ((test-dir (car test-files))
+ (files (cdr test-files))
+ (output (files-tests--insert-directory-output test-dir)))
+ (dolist (file files)
+ (should (string-match-p file output))))))
+
+ (defun files-tests--insert-directory-shows-given-free (dir &optional
+ info-func)
+ "Run `insert-directory' and verify it reports the correct available space.
+Stub `file-system-info' to ensure the available space is consistent,
+either with the given stub function or a default one using test data."
+ ;; It is always defined but this silences the byte-compiler:
+ (when (and (fboundp 'files-tests--make-file-system-info-stub)
+ (fboundp 'files-tests--look-up-free-data)
+ (fboundp 'files-tests--insert-directory-output))
+ (cl-letf (((symbol-function 'file-system-info)
+ (or info-func
+ (files-tests--make-file-system-info-stub))))
+ (should (string-match-p (cadr
+ (files-tests--look-up-free-data dir))
+ (files-tests--insert-directory-output dir t))))))
+
+ (ert-deftest files-tests-insert-directory-shows-free ()
+ "Test that verbose `insert-directory' shows the correct available space."
+ ;; It is always defined but this silences the byte-compiler:
+ (when (and (fboundp 'files-tests--insert-directory-shows-given-free)
+ (fboundp 'files-tests--make-file-system-info-stub))
+ (files-tests--insert-directory-shows-given-free
+ test-dir
+ (files-tests--make-file-system-info-stub test-dir))))
+ (ert-deftest files-tests-bug-50630 ()
+ "Verify verbose `insert-directory' shows free space of the target directory.
+The current directory at call time should not affect the result (Bug#50630)."
+ ;; It is always defined but this silences the byte-compiler:
+ (when (fboundp 'files-tests--insert-directory-shows-given-free)
+ (let ((default-directory test-dir-other))
+ (files-tests--insert-directory-shows-given-free test-dir)))))
(provide 'dired-tests)
-;; dired-tests.el ends here
+;;; dired-tests.el ends here
diff --git a/test/lisp/dired-x-tests.el b/test/lisp/dired-x-tests.el
index a64cff1e272..7acaa3c1319 100644
--- a/test/lisp/dired-x-tests.el
+++ b/test/lisp/dired-x-tests.el
@@ -1,6 +1,6 @@
;;; dired-x-tests.el --- Test suite for dired-x. -*- lexical-binding: t -*-
-;; Copyright (C) 2017 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2022 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -19,6 +19,7 @@
;;; Code:
(require 'ert)
+(require 'ert-x)
(require 'dired-x)
@@ -31,23 +32,30 @@
(append (copy-sequence dirs)
(delete "c" (copy-sequence files)))
#'string<))
- (dir (make-temp-file "Bug25942" 'dir))
(extension "c"))
- (unwind-protect
- (progn
- (dolist (d dirs)
- (make-directory (expand-file-name d dir)))
- (dolist (f files)
- (write-region nil nil (expand-file-name f dir)))
- (dired dir)
- (dired-mark-extension extension)
- (should (equal '("bar.c" "foo.c")
- (sort (dired-get-marked-files 'local) #'string<)))
- (dired-unmark-all-marks)
- (dired-mark-suffix extension)
- (should (equal all-but-c
- (sort (dired-get-marked-files 'local) #'string<))))
- (delete-directory dir 'recursive))))
+ (ert-with-temp-directory dir
+ (dolist (d dirs)
+ (make-directory (expand-file-name d dir)))
+ (dolist (f files)
+ (write-region nil nil (expand-file-name f dir)))
+ (dired dir)
+ (dired-mark-extension extension)
+ (should (equal '("bar.c" "foo.c")
+ (sort (dired-get-marked-files 'local) #'string<)))
+ (dired-unmark-all-marks)
+ (dired-mark-suffix extension)
+ (should (equal all-but-c
+ (sort (dired-get-marked-files 'local) #'string<))))))
+
+(ert-deftest dired-x--string-to-number ()
+ (should (= (dired-x--string-to-number "2.4K") 2457.6))
+ (should (= (dired-x--string-to-number "2400") 2400))
+ (should (= (dired-x--string-to-number "123.4M") 129394278.4))
+ (should (= (dired-x--string-to-number "123.40000M") 129394278.4))
+ (should (= (dired-x--string-to-number "4.134") 4134))
+ (should (= (dired-x--string-to-number "4,134") 4134))
+ (should (= (dired-x--string-to-number "4 134") 4134))
+ (should (= (dired-x--string-to-number "41,52,134") 4152134)))
(provide 'dired-x-tests)
-;; dired-x-tests.el ends here
+;;; dired-x-tests.el ends here
diff --git a/test/lisp/dnd-tests.el b/test/lisp/dnd-tests.el
new file mode 100644
index 00000000000..67b660fc124
--- /dev/null
+++ b/test/lisp/dnd-tests.el
@@ -0,0 +1,441 @@
+;;; dnd-tests.el --- Tests for window system independent DND support -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Tests for stuff in dnd.el that doesn't require a window system.
+
+;; The drag API tests only check the behavior of the simplified drag
+;; APIs in dnd.el. Actual drags are not performed during the
+;; automated testing process (make check), but some of the tests can
+;; also be run under X.
+
+;;; Code:
+
+(require 'dnd)
+(require 'cl-lib)
+(require 'tramp)
+(require 'select)
+(require 'ert-x)
+
+(defvar dnd-tests-selection-table nil
+ "Alist of selection names to their values.")
+
+(defvar x-treat-local-requests-remotely)
+(defvar x-dnd-preserve-selection-data)
+
+;; Define some replacements for functions used by the drag-and-drop
+;; code on X when running under something else.
+(unless (eq window-system 'x)
+ ;; Substitute for x-begin-drag, which isn't present on all systems.
+ (defalias 'x-begin-drag
+ (lambda (_targets &optional action frame &rest _)
+ ;; Verify that frame is either nil or a valid frame.
+ (when (and frame (not (frame-live-p frame)))
+ (signal 'wrong-type-argument frame))
+ ;; Verify that the action is valid and pretend the drag succeeded
+ ;; (by returning the action).
+ (cl-ecase action
+ (XdndActionCopy action)
+ (XdndActionMove action)
+ (XdndActionLink action)
+ ;; These two are not technically valid, but x-begin-drag accepts
+ ;; them anyway.
+ (XdndActionPrivate action)
+ (XdndActionAsk 'XdndActionPrivate))))
+
+ ;; This doesn't work during tests.
+ (defalias 'gui-set-selection
+ (lambda (type data)
+ (or (gui--valid-simple-selection-p data)
+ (and (vectorp data)
+ (let ((valid t))
+ (dotimes (i (length data))
+ (or (gui--valid-simple-selection-p (aref data i))
+ (setq valid nil)))
+ valid))
+ (signal 'error (list "invalid selection" data)))
+ (setf (alist-get type dnd-tests-selection-table) data))))
+
+(declare-function x-get-selection-internal "xselect.c")
+
+(defun dnd-tests-verify-selection-data (type)
+ "Return the data of the drag-and-drop selection converted to TYPE."
+ (if (eq window-system 'x)
+ (let ((x-treat-local-requests-remotely t))
+ (x-get-selection-internal 'XdndSelection type))
+ (let* ((basic-value (cdr (assq 'XdndSelection
+ dnd-tests-selection-table)))
+ (local-value (if (stringp basic-value)
+ (or (get-text-property 0 type basic-value)
+ basic-value)
+ basic-value))
+ (converter-list (cdr (assq type selection-converter-alist)))
+ (converter (if (consp converter-list)
+ (cdr converter-list)
+ converter-list)))
+ (if (and local-value converter)
+ (funcall converter 'XdndSelection type local-value)
+ (error "No selection converter or local value: %s" type)))))
+
+(defun dnd-tests-remote-accessible-p ()
+ "Return if a test involving remote files can proceed."
+ (ignore-errors
+ (and
+ (file-remote-p ert-remote-temporary-file-directory)
+ (file-directory-p ert-remote-temporary-file-directory)
+ (file-writable-p ert-remote-temporary-file-directory))))
+
+(defun dnd-tests-make-temp-name ()
+ "Return a temporary remote file name for test.
+The temporary file is not created."
+ (expand-file-name (make-temp-name "dnd-test-remote")
+ ert-remote-temporary-file-directory))
+
+(defun dnd-tests-parse-tt-netfile (netfile)
+ "Parse NETFILE and return its components.
+NETFILE should be a canonicalized ToolTalk file name.
+Return a list of its hostname, real path, and local path."
+ (save-match-data
+ (when (string-match (concat "HOST=0-\\([[:digit:]]+\\),RPATH=\\([[:digit:]]+\\)-"
+ "\\([[:digit:]]+\\),LPATH=\\([[:digit:]]+\\)-"
+ "\\([[:digit:]]+\\)\\(:\\)")
+ netfile)
+ (let ((beg (match-end 6)))
+ (list (substring netfile beg
+ (+ beg 1
+ (string-to-number (match-string 1 netfile))))
+ (substring netfile
+ (+ beg
+ (string-to-number (match-string 2 netfile)))
+ (+ beg 1
+ (string-to-number (match-string 3 netfile))))
+ (substring netfile
+ (+ beg
+ (string-to-number (match-string 4 netfile)))
+ (+ beg 1
+ (string-to-number (match-string 5 netfile)))))))))
+
+(defun dnd-tests-extract-selection-data (selection expect-cons)
+ "Return the selection data in SELECTION.
+SELECTION can either be the value of `gui-get-selection', or the
+return value of a selection converter.
+
+If EXPECT-CONS, then expect SELECTION to be a cons (when not
+running under X).
+
+This function only tries to handle strings."
+ (when (and expect-cons (not (eq window-system 'x)))
+ (should (and (consp selection)
+ (stringp (cdr selection)))))
+ (if (stringp selection)
+ selection
+ (cdr selection)))
+
+(ert-deftest dnd-tests-begin-text-drag ()
+ ;; When running this test under X, please make sure to drop onto a
+ ;; program with reasonably correct behavior, such as dtpad, gedit,
+ ;; or Mozilla.
+ ;; ASCII Latin-1 UTF-8
+ (let ((test-text "hello, everyone! sæl öllsömul! всем привет")
+ (x-dnd-preserve-selection-data t))
+ ;; Verify that dragging works.
+ (should (eq (dnd-begin-text-drag test-text) 'copy))
+ (should (eq (dnd-begin-text-drag test-text nil 'move) 'move))
+ ;; Verify that the important data types are converted correctly.
+ (let ((string-data (dnd-tests-verify-selection-data 'STRING)))
+ ;; Check that the Latin-1 target is converted correctly.
+ (should (equal (dnd-tests-extract-selection-data string-data t)
+ (encode-coding-string test-text
+ 'iso-8859-1))))
+ ;; And that UTF8_STRING and the Xdnd UTF8 string are as well.
+ (let* ((string-data (dnd-tests-verify-selection-data
+ 'UTF8_STRING))
+ (string-data-1 (dnd-tests-verify-selection-data
+ 'text/plain\;charset=utf-8))
+ (extracted-1 (dnd-tests-extract-selection-data string-data-1 t))
+ (extracted (dnd-tests-extract-selection-data string-data t)))
+ (should (and (stringp extracted) (stringp extracted-1)))
+ (should (equal extracted extracted)))
+ ;; Now check text/plain.
+ (let ((string-data (dnd-tests-verify-selection-data
+ 'text/plain)))
+ (should (equal (dnd-tests-extract-selection-data string-data t)
+ (encode-coding-string test-text 'ascii))))))
+
+(ert-deftest dnd-tests-begin-file-drag ()
+ ;; These tests also involve handling remote file names.
+ (skip-unless (and (dnd-tests-remote-accessible-p)
+ ;; TODO: make these tests work under X.
+ (not (eq window-system 'x))))
+ (let ((normal-temp-file (expand-file-name (make-temp-name "dnd-test")
+ temporary-file-directory))
+ (normal-multibyte-file (expand-file-name
+ (make-temp-name "тест-на-перетаскивание")
+ temporary-file-directory))
+ (remote-temp-file (dnd-tests-make-temp-name))
+ (x-dnd-preserve-selection-data t))
+ ;; Touch those files if they don't exist.
+ (unless (file-exists-p normal-temp-file)
+ (write-region "" 0 normal-temp-file))
+ (unless (file-exists-p normal-multibyte-file)
+ (write-region "" 0 normal-multibyte-file))
+ (unless (file-exists-p remote-temp-file)
+ (write-region "" 0 remote-temp-file))
+ (unwind-protect
+ (progn
+ ;; Now test dragging a normal file.
+ (should (eq (dnd-begin-file-drag normal-temp-file) 'copy))
+ ;; Test that the selection data is correct.
+ (let ((uri-list-data (cdr (dnd-tests-verify-selection-data 'text/uri-list)))
+ (username-data (dnd-tests-verify-selection-data 'text/x-xdnd-username))
+ (file-name-data (cdr (dnd-tests-verify-selection-data 'FILE_NAME)))
+ (host-name-data (cdr (dnd-tests-verify-selection-data 'HOST_NAME)))
+ (netfile-data (cdr (dnd-tests-verify-selection-data '_DT_NETFILE))))
+ ;; Check if the URI list is formatted correctly.
+ (let* ((split-uri-list (split-string uri-list-data "[\0\r\n]" t))
+ (decoded (dnd-get-local-file-name (car split-uri-list))))
+ (should (equal decoded normal-temp-file)))
+ ;; Test that the username reported is correct.
+ (should (equal username-data (user-real-login-name)))
+ ;; Test that the file name data is correct.
+ (let* ((split-file-names (split-string file-name-data "\0"))
+ (file-name (car split-file-names)))
+ ;; Make sure there are no extra leading or trailing NULL bytes.
+ (should (and split-file-names (null (cdr split-file-names))))
+ ;; Make sure the file name is encoded correctly;
+ (should-not (multibyte-string-p file-name))
+ ;; Make sure decoding the file name results in the
+ ;; originals.
+ (should (equal (decode-coding-string file-name
+ (or file-name-coding-system
+ default-file-name-coding-system))
+ normal-temp-file))
+ ;; Also make sure the hostname is correct.
+ (should (equal host-name-data (system-name))))
+ ;; Check that the netfile hostname, rpath and lpath are correct.
+ (let ((parsed (dnd-tests-parse-tt-netfile netfile-data))
+ (filename (encode-coding-string normal-temp-file
+ (or file-name-coding-system
+ default-file-name-coding-system))))
+ (should (equal (nth 0 parsed) (system-name)))
+ (should (equal (nth 1 parsed) filename))
+ (should (equal (nth 2 parsed) filename))))
+ ;; And the remote file.
+ (should (eq (dnd-begin-file-drag remote-temp-file) 'copy))
+ ;; Test that the remote file was added to the list of files
+ ;; to remove later.
+ (should dnd-last-dragged-remote-file)
+ ;; Make sure the appropriate hook is added so the remote
+ ;; files are removed when Emacs exits.
+ (should (memq #'dnd-remove-last-dragged-remote-file
+ kill-emacs-hook))
+ ;; Test that the remote file was removed.
+ (should (progn
+ (dnd-begin-file-drag normal-temp-file)
+ (not dnd-last-dragged-remote-file)))
+ ;; Make sure the remote file removal hook was deleted.
+ (should-not (memq #'dnd-remove-last-dragged-remote-file
+ kill-emacs-hook))
+ ;; Test that links to remote files can't be created.
+ (should-error (dnd-begin-file-drag remote-temp-file nil 'link))
+ ;; Test dragging a file with a multibyte filename.
+ (should (eq (dnd-begin-file-drag normal-multibyte-file) 'copy))
+ ;; Test that the ToolTalk filename is encodes and decodes correctly.
+ (let* ((netfile-data (cdr (dnd-tests-verify-selection-data '_DT_NETFILE)))
+ (parsed (dnd-tests-parse-tt-netfile netfile-data))
+ (filename (encode-coding-string normal-multibyte-file
+ (or file-name-coding-system
+ default-file-name-coding-system))))
+ (should (equal (nth 0 parsed) (system-name)))
+ (should (equal (nth 1 parsed) filename))
+ (should (equal (nth 2 parsed) filename))))
+ (delete-file normal-temp-file)
+ (delete-file normal-multibyte-file)
+ (delete-file remote-temp-file))))
+
+(ert-deftest dnd-tests-begin-drag-files ()
+ (skip-unless (and (dnd-tests-remote-accessible-p)
+ ;; TODO: make these tests work under X.
+ (not (eq window-system 'x))))
+ (let ((normal-temp-file (expand-file-name (make-temp-name "dnd-test")
+ temporary-file-directory))
+ (normal-temp-file-1 (expand-file-name (make-temp-name "dnd-test")
+ temporary-file-directory))
+ (remote-temp-file (dnd-tests-make-temp-name))
+ (nonexistent-local-file
+ (expand-file-name (make-temp-name "dnd-test")
+ temporary-file-directory))
+ (nonexistent-remote-file (dnd-tests-make-temp-name))
+ (nonexistent-remote-file-1 (dnd-tests-make-temp-name))
+ (x-dnd-preserve-selection-data t))
+ ;; Touch those files if they don't exist.
+ (unless (file-exists-p normal-temp-file)
+ (write-region "" 0 normal-temp-file))
+ (unless (file-exists-p normal-temp-file-1)
+ (write-region "" 0 normal-temp-file))
+ (unless (file-exists-p remote-temp-file)
+ (write-region "" 0 remote-temp-file))
+ (ignore-errors
+ (delete-file nonexistent-local-file)
+ (delete-file nonexistent-remote-file)
+ (delete-file nonexistent-remote-file-1))
+ (unwind-protect
+ (progn
+ ;; Now test dragging a normal file and a remote file.
+ (should (eq (dnd-begin-drag-files (list normal-temp-file
+ remote-temp-file))
+ 'copy))
+ ;; Test that the remote file produced was added to the list
+ ;; of files to remove upon the next call.
+ (should dnd-last-dragged-remote-file)
+ ;; Make sure the appropriate hook is added so the remote
+ ;; files are removed when Emacs exits.
+ (should (memq #'dnd-remove-last-dragged-remote-file
+ kill-emacs-hook))
+ ;; Two local files at the same time.
+ (should (eq (dnd-begin-drag-files (list normal-temp-file
+ normal-temp-file-1))
+ 'copy))
+ ;; Test that the remote files were removed.
+ (should-not dnd-last-dragged-remote-file)
+ ;; And so was the hook.
+ (should-not (memq #'dnd-remove-last-dragged-remote-file
+ kill-emacs-hook))
+ ;; Test the selection data is correct.
+ (let ((uri-list-data (cdr (dnd-tests-verify-selection-data 'text/uri-list)))
+ (username-data (dnd-tests-verify-selection-data 'text/x-xdnd-username))
+ (file-name-data (cdr (dnd-tests-verify-selection-data 'FILE_NAME)))
+ (host-name-data (cdr (dnd-tests-verify-selection-data 'HOST_NAME))))
+ ;; Check if the URI list is formatted correctly.
+ (let* ((split-uri-list (split-string uri-list-data "[\0\r\n]" t))
+ (decoded (mapcar #'dnd-get-local-file-name split-uri-list)))
+ (should (equal (car decoded) normal-temp-file))
+ (should (equal (cadr decoded) normal-temp-file-1)))
+ ;; Test that the username reported is correct.
+ (should (equal username-data (user-real-login-name)))
+ ;; Test that the file name data is correct.
+ (let ((split-file-names (split-string file-name-data "\0")))
+ ;; Make sure there are no extra leading or trailing NULL bytes.
+ (should (equal (length split-file-names) 2))
+ ;; Make sure all file names are encoded correctly;
+ (dolist (name split-file-names)
+ (should-not (multibyte-string-p name)))
+ ;; Make sure decoding the file names result in the
+ ;; originals.
+ (should (equal (decode-coding-string (car split-file-names)
+ (or file-name-coding-system
+ default-file-name-coding-system))
+ normal-temp-file))
+ (should (equal (decode-coding-string (cadr split-file-names)
+ (or file-name-coding-system
+ default-file-name-coding-system))
+ normal-temp-file-1))
+ ;; Also make sure the hostname is correct.
+ (should (equal host-name-data (system-name)))))
+ ;; Multiple local files with some remote files that will
+ ;; fail, and some that won't.
+ (should (and (eq (dnd-begin-drag-files (list normal-temp-file
+ remote-temp-file
+ remote-temp-file
+ nonexistent-remote-file
+ normal-temp-file-1
+ nonexistent-remote-file-1))
+ 'copy)
+ ;; Make sure exactly two valid remote files
+ ;; were downloaded.
+ (eq (length dnd-last-dragged-remote-file) 2)))
+ ;; Make sure the appropriate hook is added so the remote
+ ;; files are removed when Emacs exits.
+ (should (memq #'dnd-remove-last-dragged-remote-file
+ kill-emacs-hook))
+ ;; Make sure links can't be created to remote files.
+ (should-error (dnd-begin-drag-files (list normal-temp-file
+ remote-temp-file
+ normal-temp-file-1)
+ nil 'link))
+ ;; And that they can to normal files.
+ (should (eq (dnd-begin-drag-files (list normal-temp-file
+ normal-temp-file-1)
+ nil 'link)
+ 'link))
+ ;; Make sure the remote file removal hook was deleted.
+ (should-not (memq #'dnd-remove-last-dragged-remote-file
+ kill-emacs-hook))
+ ;; Make sure you can't drag an empty list of files.
+ (should-error (dnd-begin-drag-files nil))
+ ;; And when all remote files are inaccessible.
+ (should-error (dnd-begin-drag-files (list nonexistent-remote-file
+ nonexistent-remote-file-1))))
+ (delete-file normal-temp-file)
+ (delete-file normal-temp-file-1)
+ (delete-file remote-temp-file))))
+
+(ert-deftest dnd-tests-get-local-file-uri ()
+ (should (equal (dnd-get-local-file-uri "file://localhost/path/to/foo")
+ "file:///path/to/foo"))
+ (should (equal (dnd-get-local-file-uri
+ (format "file://%s/path/to/" (system-name)))
+ "file:///path/to/"))
+ (should-not (dnd-get-local-file-uri "file://some-remote-host/path/to/foo"))
+ (should-not (dnd-get-local-file-uri "file:///path/to/foo")))
+
+(ert-deftest dnd-tests-open-remote-url ()
+ ;; Expensive test to make sure opening an FTP URL during
+ ;; drag-and-drop works.
+ :tags '(:expensive-test)
+ ;; Don't run if there is no ftp client.
+ (skip-unless (executable-find "ftp"))
+ ;; Don't run this test if the FTP server isn't reachable.
+ (skip-unless (and (fboundp 'network-lookup-address-info)
+ (network-lookup-address-info "ftp.gnu.org")))
+ ;; Make sure bug#56078 doesn't happen again.
+ (let ((url "ftp://anonymous@ftp.gnu.org/")
+ ;; This prints a bunch of annoying spaces to stdout.
+ (inhibit-message t))
+ (should (prog1 t (dnd-open-remote-url url 'private)))))
+
+(ert-deftest dnd-tests-direct-save ()
+ ;; This test just verifies that a direct save works; the window
+ ;; system specific test is in x-dnd-tests.el. When running this
+ ;; interactively, keep in mind that there are only two file managers
+ ;; which are known to implement XDS correctly: System G (see
+ ;; http://nps-systemg.sourceforge.net), and Emacs itself. GTK file
+ ;; managers such as Nautilus will not work, since they prefer the
+ ;; `text/uri-list' selection target to `XdndDirectSave0', contrary
+ ;; to the XDS specification.
+ (let ((window-system window-system)
+ (normal-temp-file (expand-file-name (make-temp-name "dnd-test")
+ temporary-file-directory)))
+ (unwind-protect
+ (progn
+ (unless (file-exists-p normal-temp-file)
+ (write-region "" 0 normal-temp-file))
+ (unless (eq window-system 'x)
+ ;; Use a window system that isn't X, since we only want to test
+ ;; the fallback code when run non-interactively.
+ (setq window-system 'haiku))
+ (should (eq (dnd-direct-save normal-temp-file
+ (make-temp-name "target-file-name"))
+ 'copy)))
+ (ignore-errors
+ (delete-file normal-temp-file)))))
+
+(provide 'dnd-tests)
+;;; dnd-tests.el ends here
diff --git a/test/lisp/dom-tests.el b/test/lisp/dom-tests.el
index f44fe3bdab6..cb96f12d19d 100644
--- a/test/lisp/dom-tests.el
+++ b/test/lisp/dom-tests.el
@@ -1,10 +1,12 @@
;;; dom-tests.el --- Tests for dom.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2016-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2022 Free Software Foundation, Inc.
;; Author: Simen Heggestøyl <simenheg@gmail.com>
;; Keywords:
+;; This file is part of GNU Emacs.
+
;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
@@ -84,6 +86,13 @@
(dom-set-attribute dom attr value)
(should (equal (dom-attr dom attr) value))))
+(ert-deftest dom-tests-remove-attribute ()
+ (let ((dom (copy-tree '(body ((foo . "bar") (zot . "foobar"))))))
+ (should (equal (dom-attr dom 'foo) "bar"))
+ (dom-remove-attribute dom 'foo)
+ (should (equal (dom-attr dom 'foo) nil))
+ (should (equal dom '(body ((zot . "foobar")))))))
+
(ert-deftest dom-tests-attr ()
(let ((dom (dom-tests--tree)))
(should-not (dom-attr dom 'id))
@@ -200,5 +209,13 @@ child results in an error."
(dom-pp node t)
(should (equal (buffer-string) "(\"foo\" nil)")))))
+(ert-deftest dom-test-search ()
+ (let ((dom '(a nil (b nil (c nil)))))
+ (should (equal (dom-search dom (lambda (d) (eq (dom-tag d) 'a)))
+ (list dom)))
+ (should (equal (dom-search dom (lambda (d) (memq (dom-tag d) '(b c))))
+ (list (car (dom-children dom))
+ (car (dom-children (car (dom-children dom)))))))))
+
(provide 'dom-tests)
;;; dom-tests.el ends here
diff --git a/test/lisp/edmacro-tests.el b/test/lisp/edmacro-tests.el
new file mode 100644
index 00000000000..e386342f6ee
--- /dev/null
+++ b/test/lisp/edmacro-tests.el
@@ -0,0 +1,48 @@
+;;; edmacro-tests.el --- Tests for edmacro.el -*- lexical-binding:t -*-
+
+;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'edmacro)
+
+(ert-deftest edmacro-test-edmacro-parse-keys ()
+ (should (equal (edmacro-parse-keys "") []))
+ (should (equal (edmacro-parse-keys "x") [?x]))
+ (should (equal (edmacro-parse-keys "C-a") [?\C-a]))
+
+ ;; comments
+ (should (equal (edmacro-parse-keys ";; foobar") []))
+ (should (equal (edmacro-parse-keys ";;;") []))
+ (should (equal (edmacro-parse-keys "; ; ;") [?\; ?\; ?\;]))
+ (should (equal (edmacro-parse-keys "REM foobar") []))
+ (should (equal (edmacro-parse-keys "x ;; foobar") [?x]))
+ (should (equal (edmacro-parse-keys "x REM foobar") [?x]))
+ (should (equal (edmacro-parse-keys "<<goto-line>>")
+ [?\M-x ?g ?o ?t ?o ?- ?l ?i ?n ?e ?\r]))
+
+ ;; repetitions
+ (should (equal (edmacro-parse-keys "3*x") [?x ?x ?x]))
+ (should (equal (edmacro-parse-keys "3*C-m") [?\C-m ?\C-m ?\C-m]))
+ (should (equal (edmacro-parse-keys "10*foo")
+ (apply #'vconcat (make-list 10 [?f ?o ?o])))))
+
+;;; edmacro-tests.el ends here
diff --git a/test/lisp/electric-tests.el b/test/lisp/electric-tests.el
index 7df2449b9eb..d34737e6090 100644
--- a/test/lisp/electric-tests.el
+++ b/test/lisp/electric-tests.el
@@ -1,22 +1,24 @@
-;;; electric-tests.el --- tests for electric.el
+;;; electric-tests.el --- tests for electric.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2013-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2022 Free Software Foundation, Inc.
;; Author: João Távora <joaotavora@gmail.com>
;; Keywords:
-;; This program is free software; you can redistribute it and/or modify
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
-;; This program is distributed in the hope that it will be useful,
+;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
-;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
@@ -33,7 +35,8 @@
(defun call-with-saved-electric-modes (fn)
(let ((saved-electric (if electric-pair-mode 1 -1))
(saved-layout (if electric-layout-mode 1 -1))
- (saved-indent (if electric-indent-mode 1 -1)))
+ (saved-indent (if electric-indent-mode 1 -1))
+ (blink-paren-function nil))
(electric-pair-mode -1)
(electric-layout-mode -1)
(electric-indent-mode -1)
@@ -45,28 +48,38 @@
(defmacro save-electric-modes (&rest body)
(declare (indent defun) (debug t))
- `(call-with-saved-electric-modes #'(lambda () ,@body)))
+ `(call-with-saved-electric-modes (lambda () ,@body)))
(defun electric-pair-test-for (fixture where char expected-string
- expected-point mode bindings fixture-fn)
+ expected-point mode bindings
+ fixture-fn &optional doc-string)
(with-temp-buffer
- (funcall mode)
- (insert fixture)
- (save-electric-modes
- (let ((last-command-event char)
- (transient-mark-mode 'lambda))
- (goto-char where)
- (funcall fixture-fn)
- (cl-progv
- (mapcar #'car bindings)
- (mapcar #'cdr bindings)
- (call-interactively (key-binding `[,last-command-event])))))
+ (dlet ((python-indent-guess-indent-offset-verbose nil))
+ (funcall mode)
+ (insert fixture)
+ (save-electric-modes
+ (let ((last-command-event char)
+ (transient-mark-mode 'lambda))
+ (goto-char where)
+ (funcall fixture-fn)
+ (cl-progv
+ (mapcar #'car bindings)
+ (mapcar #'cdr bindings)
+ (call-interactively (key-binding `[,last-command-event]))))))
+ (when
+ (and doc-string
+ (not
+ (and
+ (equal (buffer-substring-no-properties (point-min) (point-max))
+ expected-string)
+ (equal (point) expected-point))))
+ (message "\n%s\n" doc-string))
(should (equal (buffer-substring-no-properties (point-min) (point-max))
expected-string))
(should (equal (point)
expected-point))))
-(eval-when-compile
+(eval-and-compile
(defun electric-pair-define-test-form (name fixture
char
pos
@@ -84,46 +97,67 @@
(with-temp-buffer
(cl-progv
;; FIXME: avoid `eval'
- (mapcar #'car (eval bindings))
- (mapcar #'cdr (eval bindings))
- (funcall mode)
- (insert fixture)
- (goto-char (1+ pos))
- (insert char)
- (cond ((eq (aref skip-pair-string pos)
- ?p)
- (insert (cadr (electric-pair-syntax-info char)))
- (backward-char 1))
- ((eq (aref skip-pair-string pos)
- ?s)
- (delete-char -1)
- (forward-char 1)))
- (list
- (buffer-substring-no-properties (point-min) (point-max))
- (point))))
+ (mapcar #'car (eval bindings t))
+ (mapcar #'cdr (eval bindings t))
+ (dlet ((python-indent-guess-indent-offset-verbose nil))
+ (funcall mode)
+ (insert fixture)
+ (goto-char (1+ pos))
+ (insert char)
+ (cond ((eq (aref skip-pair-string pos)
+ ?p)
+ (insert (cadr (electric-pair-syntax-info char)))
+ (backward-char 1))
+ ((eq (aref skip-pair-string pos)
+ ?s)
+ (delete-char -1)
+ (forward-char 1)))
+ (list
+ (buffer-substring-no-properties (point-min) (point-max))
+ (point)))))
(list expected-string expected-point)))
(expected-string (car expected-string-and-point))
(expected-point (cadr expected-string-and-point))
(fixture (format "%s%s%s" prefix fixture suffix))
(expected-string (format "%s%s%s" prefix expected-string suffix))
(expected-point (+ (length prefix) expected-point))
- (pos (+ (length prefix) pos)))
+ (pos (+ (length prefix) pos))
+ (doc-string
+ (format "Electricity test in a `%s' buffer.\n
+Start with point at %d in a %d-char-long buffer
+like this one:
+
+ |%s| (buffer start and end are denoted by `|')
+%s
+%s
+Now press the key for: %c
+
+The buffer's contents should %s:
+
+ |%s|
+
+, and point should be at %d."
+ mode
+ (1+ pos)
+ (length fixture)
+ fixture
+ (if fixture-fn (format "\nNow call this:\n\n%s"
+ (pp-to-string fixture-fn))
+ "")
+ (if bindings (format "\nEnsure the following bindings:\n\n%s"
+ (pp-to-string bindings))
+ "")
+ char
+ (if (string= fixture expected-string) "stay" "become")
+ (string-replace "\n" "\\n" expected-string)
+ expected-point)))
`(ert-deftest ,(intern (format "electric-pair-%s-at-point-%s-in-%s%s"
name
(1+ pos)
mode
extra-desc))
()
- ,(format "With |%s|, try input %c at point %d. \
-Should %s |%s| and point at %d"
- fixture
- char
- (1+ pos)
- (if (string= fixture expected-string)
- "stay"
- "become")
- (replace-regexp-in-string "\n" "\\\\n" expected-string)
- expected-point)
+ ,doc-string
(electric-pair-test-for ,fixture
,(1+ pos)
,char
@@ -131,7 +165,8 @@ Should %s |%s| and point at %d"
,expected-point
',mode
,bindings
- ,fixture-fn)))))
+ ,fixture-fn
+ ,doc-string)))))
(cl-defmacro define-electric-pair-test
(name fixture
@@ -141,31 +176,36 @@ Should %s |%s| and point at %d"
expected-string
expected-point
bindings
- (modes '(quote (ruby-mode c++-mode)))
+ (modes '(quote (ruby-mode js-mode python-mode c-mode)))
(test-in-comments t)
(test-in-strings t)
(test-in-code t)
- (fixture-fn #'(lambda ()
- (electric-pair-mode 1))))
+ ;; The semantics of CL's defmacro "default values" is subtle:
+ ;; contrary to the actual arguments, these are evaluated (and
+ ;; are expected to return the "default form").
+ ;; `fixture-fn' contains a form whose evaluation returns a function.
+ (fixture-fn '#'electric-pair-mode))
`(progn
,@(cl-loop
- for mode in (eval modes) ;FIXME: avoid `eval'
+ for mode in (eval modes t) ;FIXME: avoid `eval'
append
(cl-loop
for (prefix suffix extra-desc) in
(append (if test-in-comments
`((,(with-temp-buffer
- (funcall mode)
- (insert "z")
- (comment-region (point-min) (point-max))
- (buffer-substring-no-properties (point-min)
- (1- (point-max))))
+ (dlet ((python-indent-guess-indent-offset-verbose
+ nil))
+ (funcall mode)
+ (insert "z")
+ (comment-region (point-min) (point-max))
+ (buffer-substring-no-properties (point-min)
+ (1- (point-max)))))
""
"-in-comments")))
(if test-in-strings
- `(("\"" "\"" "-in-strings")))
+ '(("\"" "\"" "-in-strings")))
(if test-in-code
- `(("" "" ""))))
+ '(("" "" ""))))
append
(cl-loop
for char across input
@@ -261,7 +301,7 @@ Should %s |%s| and point at %d"
;;; Quotes
;;;
(define-electric-pair-test pair-some-quotes-skip-others
- " \"\" " "-\"\"-----" :skip-pair-string "-ps------"
+ " \"\" " "-\"\"-\"---" :skip-pair-string "-ps-p----"
:test-in-strings nil
:bindings `((electric-pair-text-syntax-table
. ,prog-mode-syntax-table)))
@@ -324,7 +364,7 @@ baz\"\""
# \"
#
baz\"\""
- :fixture-fn #'(lambda () (goto-char (point-min)) (search-forward "bar")))
+ :fixture-fn (lambda () (goto-char (point-min)) (search-forward "bar")))
(define-electric-pair-test inhibit-in-mismatched-string-inside-c-comments
"foo\"\"/*
@@ -343,7 +383,7 @@ baz\"\""
\" \"
\"
*/baz\"\""
- :fixture-fn #'(lambda () (goto-char (point-min)) (search-forward "bar")))
+ :fixture-fn (lambda () (goto-char (point-min)) (search-forward "bar")))
;;; More quotes, but now don't bind `electric-pair-text-syntax-table'
@@ -375,13 +415,22 @@ baz\"\""
:bindings '((electric-pair-skip-whitespace . chomp))
:test-in-comments nil)
+(ert-deftest electric-pair-whitespace-chomping-2-at-point-4-in-c++-mode-in-strings nil
+ "Check if whitespace chomping works in `c++' unterminated strings."
+ (electric-pair-test-for
+ "\" ( \n \n ) \"" 4 41 "\" () \"" 5 'c++-mode
+ '((electric-pair-skip-whitespace . chomp))
+ (lambda () (electric-pair-mode 1))))
+
(define-electric-pair-test whitespace-chomping-dont-cross-comments
" ( \n\t\t\n ) " "--)------" :expected-string " () \n\t\t\n ) "
:expected-point 4
:bindings '((electric-pair-skip-whitespace . chomp))
:test-in-strings nil
:test-in-code nil
- :test-in-comments t)
+ :test-in-comments t
+ :fixture-fn (lambda () (when (eq major-mode 'c-mode)
+ (c-toggle-comment-style -1))))
(define-electric-pair-test whitespace-skipping-for-quotes-not-outside
" \" \"" "\"-----" :expected-string "\"\" \" \""
@@ -478,27 +527,28 @@ baz\"\""
(define-electric-pair-test js-mode-braces
"" "{" :expected-string "{}" :expected-point 2
:modes '(js-mode)
- :fixture-fn #'(lambda ()
- (electric-pair-mode 1)))
+ :fixture-fn (lambda ()
+ (electric-pair-mode 1)))
+
(define-electric-pair-test js-mode-braces-with-layout
"" "{" :expected-string "{\n\n}" :expected-point 3
:modes '(js-mode)
:test-in-comments nil
:test-in-strings nil
- :fixture-fn #'(lambda ()
- (electric-layout-mode 1)
- (electric-pair-mode 1)))
+ :fixture-fn (lambda ()
+ (electric-layout-mode 1)
+ (electric-pair-mode 1)))
(define-electric-pair-test js-mode-braces-with-layout-and-indent
"" "{" :expected-string "{\n \n}" :expected-point 7
:modes '(js-mode)
:test-in-comments nil
:test-in-strings nil
- :fixture-fn #'(lambda ()
- (electric-pair-mode 1)
- (electric-indent-mode 1)
- (electric-layout-mode 1)))
+ :fixture-fn (lambda ()
+ (electric-pair-mode 1)
+ (electric-indent-mode 1)
+ (electric-layout-mode 1)))
;;; Backspacing
@@ -513,6 +563,24 @@ baz\"\""
(should (equal "" (buffer-string))))))
+;;; Undoing
+(ert-deftest electric-pair-undo-unrelated-state ()
+ "Make sure `electric-pair-mode' does not confuse `undo' (bug#39680)."
+ (with-temp-buffer
+ (buffer-enable-undo)
+ (electric-pair-local-mode)
+ (let ((last-command-event ?\())
+ (ert-simulate-command '(self-insert-command 1)))
+ (undo-boundary)
+ (let ((last-command-event ?a))
+ (ert-simulate-command '(self-insert-command 1)))
+ (undo-boundary)
+ (ert-simulate-command '(undo))
+ (let ((last-command-event ?\())
+ (ert-simulate-command '(self-insert-command 1)))
+ (should (string= (buffer-string) "(())"))))
+
+
;;; Electric newlines between pairs
;;; TODO: better tests
(ert-deftest electric-pair-open-extra-newline ()
@@ -535,55 +603,55 @@ baz\"\""
;;;
(define-electric-pair-test autowrapping-1
"foo" "(" :expected-string "(foo)" :expected-point 2
- :fixture-fn #'(lambda ()
- (electric-pair-mode 1)
- (mark-sexp 1)))
+ :fixture-fn (lambda ()
+ (electric-pair-mode 1)
+ (mark-sexp 1)))
(define-electric-pair-test autowrapping-2
"foo" ")" :expected-string "(foo)" :expected-point 6
- :fixture-fn #'(lambda ()
- (electric-pair-mode 1)
- (mark-sexp 1)))
+ :fixture-fn (lambda ()
+ (electric-pair-mode 1)
+ (mark-sexp 1)))
(define-electric-pair-test autowrapping-3
"foo" ")" :expected-string "(foo)" :expected-point 6
- :fixture-fn #'(lambda ()
- (electric-pair-mode 1)
- (goto-char (point-max))
- (skip-chars-backward "\"")
- (mark-sexp -1)))
+ :fixture-fn (lambda ()
+ (electric-pair-mode 1)
+ (goto-char (point-max))
+ (skip-chars-backward "\"")
+ (mark-sexp -1)))
(define-electric-pair-test autowrapping-4
"foo" "(" :expected-string "(foo)" :expected-point 2
- :fixture-fn #'(lambda ()
- (electric-pair-mode 1)
- (goto-char (point-max))
- (skip-chars-backward "\"")
- (mark-sexp -1)))
+ :fixture-fn (lambda ()
+ (electric-pair-mode 1)
+ (goto-char (point-max))
+ (skip-chars-backward "\"")
+ (mark-sexp -1)))
(define-electric-pair-test autowrapping-5
"foo" "\"" :expected-string "\"foo\"" :expected-point 2
- :fixture-fn #'(lambda ()
- (electric-pair-mode 1)
- (mark-sexp 1)))
+ :fixture-fn (lambda ()
+ (electric-pair-mode 1)
+ (mark-sexp 1)))
(define-electric-pair-test autowrapping-6
"foo" "\"" :expected-string "\"foo\"" :expected-point 6
- :fixture-fn #'(lambda ()
- (electric-pair-mode 1)
- (goto-char (point-max))
- (skip-chars-backward "\"")
- (mark-sexp -1)))
+ :fixture-fn (lambda ()
+ (electric-pair-mode 1)
+ (goto-char (point-max))
+ (skip-chars-backward "\"")
+ (mark-sexp -1)))
(define-electric-pair-test autowrapping-7
"foo" "\"" :expected-string "``foo''" :expected-point 8
:modes '(tex-mode)
:test-in-comments nil
- :fixture-fn #'(lambda ()
- (electric-pair-mode 1)
- (goto-char (point-max))
- (skip-chars-backward "\"")
- (mark-sexp -1)))
+ :fixture-fn (lambda ()
+ (electric-pair-mode 1)
+ (goto-char (point-max))
+ (skip-chars-backward "\"")
+ (mark-sexp -1)))
;;; Electric quotes
@@ -735,6 +803,31 @@ baz\"\""
:bindings '((electric-quote-replace-double . t))
:test-in-comments nil :test-in-strings nil)
+(define-electric-pair-test electric-quote-replace-double-no-context-single
+ " " "-'" :expected-string " ’" :expected-point 3
+ :modes '(text-mode)
+ :fixture-fn #'electric-quote-local-mode
+ :bindings '((electric-quote-replace-double . t))
+ :test-in-comments nil :test-in-strings nil)
+
+(define-electric-pair-test electric-quote-replace-double-escaped-open
+ "foo \\" "-----\"" :expected-string "foo \\“"
+ :expected-point 7 :modes '(emacs-lisp-mode c-mode)
+ :fixture-fn #'electric-quote-local-mode
+ :bindings '((electric-quote-replace-double . t)
+ (electric-quote-comment . t)
+ (electric-quote-string . t))
+ :test-in-comments t :test-in-strings t :test-in-code nil)
+
+(define-electric-pair-test electric-quote-replace-double-escaped-close
+ "foo \\“foo\\" "----------\"" :expected-string "foo \\“foo\\”"
+ :expected-point 12 :modes '(emacs-lisp-mode c-mode)
+ :fixture-fn #'electric-quote-local-mode
+ :bindings '((electric-quote-replace-double . t)
+ (electric-quote-comment . t)
+ (electric-quote-string . t))
+ :test-in-comments t :test-in-strings t :test-in-code nil)
+
;; Simulate ‘markdown-mode’: it sets both ‘comment-start’ and
;; ‘comment-use-syntax’, but derives from ‘text-mode’.
(define-electric-pair-test electric-quote-markdown-in-text
@@ -761,5 +854,138 @@ baz\"\""
:bindings '((comment-start . "<!--") (comment-use-syntax . t))
:test-in-comments nil :test-in-strings nil)
+
+;;; tests for `electric-layout-mode'
+
+(define-derived-mode plainer-c-mode c-mode "pC"
+ "A plainer/saner C-mode with no internal electric machinery."
+ (c-toggle-electric-state -1)
+ (setq-local electric-indent-local-mode-hook nil)
+ (setq-local electric-indent-mode-hook nil)
+ (electric-indent-local-mode 1)
+ (dolist (key '(?\" ?\' ?\{ ?\} ?\( ?\) ?\[ ?\]))
+ (local-set-key (vector key) 'self-insert-command)))
+
+(defun electric-layout-for-c-style-du-jour (inserted)
+ "A function to use in `electric-layout-rules'."
+ (when (memq inserted '(?\{ ?\}))
+ (save-excursion
+ (backward-char 2) (c-point-syntax) (forward-char) ; silly, but needed
+ (c-brace-newlines (c-point-syntax)))))
+
+(ert-deftest electric-layout-plainer-c-mode-use-c-style ()
+ (ert-with-test-buffer ()
+ (plainer-c-mode)
+ (electric-layout-local-mode 1)
+ (electric-pair-local-mode 1)
+ (electric-indent-local-mode 1)
+ (setq-local electric-layout-rules
+ '(electric-layout-for-c-style-du-jour))
+ (insert "int main () ")
+ (let ((last-command-event ?\{))
+ (call-interactively (key-binding `[,last-command-event])))
+ (should (equal (buffer-string) "int main ()\n{\n \n}\n"))))
+
+(ert-deftest electric-layout-int-main-kernel-style ()
+ (ert-with-test-buffer ()
+ (plainer-c-mode)
+ (electric-layout-local-mode 1)
+ (electric-pair-local-mode 1)
+ (electric-indent-local-mode 1)
+ (setq-local electric-layout-rules
+ '((?\{ . (after))
+ (?\} . (before))))
+ (insert "int main () ")
+ (let ((last-command-event ?\{))
+ (call-interactively (key-binding `[,last-command-event])))
+ (should (equal (buffer-string) "int main () {\n \n}"))))
+
+(ert-deftest electric-layout-control-reindentation ()
+ "Same as `electric-layout-int-main-kernel-style', but checking
+Bug#35254."
+ (ert-with-test-buffer ()
+ (plainer-c-mode)
+ (electric-layout-local-mode 1)
+ (electric-pair-local-mode 1)
+ (electric-indent-local-mode 1)
+ (setq-local electric-layout-rules
+ '((?\{ . (after))
+ (?\} . (before))))
+ (insert "int main () ")
+ (let ((last-command-event ?\{))
+ (call-interactively (key-binding `[,last-command-event])))
+ (should (equal (buffer-string) "int main () {\n \n}"))
+ ;; insert an additional newline and check indentation and
+ ;; reindentation
+ (call-interactively 'newline)
+ (should (equal (buffer-string) "int main () {\n\n \n}"))))
+
+(ert-deftest electric-modes-int-main-allman-style ()
+ (ert-with-test-buffer ()
+ (plainer-c-mode)
+ (electric-layout-local-mode 1)
+ (electric-pair-local-mode 1)
+ (electric-indent-local-mode 1)
+ (setq-local electric-layout-rules
+ '((?\{ . (before after))
+ (?\} . (before))))
+ (insert "int main () ")
+ (let ((last-command-event ?\{))
+ (call-interactively (key-binding `[,last-command-event])))
+ (should (equal (buffer-string) "int main ()\n{\n \n}"))))
+
+(ert-deftest electric-pair-mode-newline-between-parens ()
+ (ert-with-test-buffer ()
+ (plainer-c-mode)
+ (electric-layout-local-mode -1) ;; ensure e-l-m mode is off
+ (electric-pair-local-mode 1)
+ (insert-before-markers "int main () {}")
+ (backward-char 1)
+ (let ((last-command-event ?\r))
+ (call-interactively (key-binding `[,last-command-event])))
+ (should (equal (buffer-string) "int main () {\n \n}"))))
+
+(ert-deftest electric-layout-mode-newline-between-parens-without-e-p-m ()
+ (ert-with-test-buffer ()
+ (plainer-c-mode)
+ (electric-layout-local-mode 1)
+ (electric-pair-local-mode -1) ;; ensure e-p-m mode is off
+ (electric-indent-local-mode 1)
+ (setq-local electric-layout-rules
+ '((?\n
+ .
+ (lambda ()
+ (when (eq (save-excursion
+ (skip-chars-backward "\t\s")
+ (char-before (1- (point))))
+ (matching-paren (char-after)))
+ '(after-stay))))))
+ (insert "int main () {}")
+ (backward-char 1)
+ (let ((last-command-event ?\r))
+ (call-interactively (key-binding `[,last-command-event])))
+ (should (equal (buffer-string) "int main () {\n \n}"))))
+
+(ert-deftest electric-layout-mode-newline-between-parens-without-e-p-m-2 ()
+ (ert-with-test-buffer ()
+ (plainer-c-mode)
+ (electric-layout-local-mode 1)
+ (electric-pair-local-mode -1) ;; ensure e-p-m mode is off
+ (electric-indent-local-mode 1)
+ (setq-local electric-layout-rules
+ '((lambda (char)
+ (when (and
+ (eq char ?\n)
+ (eq (save-excursion
+ (skip-chars-backward "\t\s")
+ (char-before (1- (point))))
+ (matching-paren (char-after))))
+ '(after-stay)))))
+ (insert "int main () {}")
+ (backward-char 1)
+ (let ((last-command-event ?\r))
+ (call-interactively (key-binding `[,last-command-event])))
+ (should (equal (buffer-string) "int main () {\n \n}"))))
+
(provide 'electric-tests)
;;; electric-tests.el ends here
diff --git a/test/lisp/elide-head-tests.el b/test/lisp/elide-head-tests.el
new file mode 100644
index 00000000000..6f351170f1d
--- /dev/null
+++ b/test/lisp/elide-head-tests.el
@@ -0,0 +1,227 @@
+;;; elide-head-tests.el --- Tests for elide-head.el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+;; Author: Simen Heggestøyl <simenheg@gmail.com>
+;; Keywords:
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;
+
+;;; Code:
+
+(require 'elide-head)
+(require 'ert)
+(require 'ert-x)
+
+(ert-deftest elide-head-tests-elide-head-mode ()
+ (let ((elide-head-headers-to-hide '(("START" . "END"))))
+ (with-temp-buffer
+ (insert "foo\nSTART\nHIDDEN\nEND\nbar")
+ (elide-head-mode 1)
+ (let ((o (car (overlays-at 14))))
+ (should (= (overlay-start o) 10))
+ (should (= (overlay-end o) 21))
+ (should (overlay-get o 'invisible))
+ (should (overlay-get o 'evaporate))))))
+
+(ert-deftest elide-head-tests-elide-head-mode/enable-disable ()
+ (let ((elide-head-headers-to-hide '(("START" . "END"))))
+ (with-temp-buffer
+ (insert "foo\nSTART\nHIDDEN\nEND\nbar")
+ (elide-head-mode 1)
+ (should (overlays-at 14))
+ (elide-head-mode -1)
+ (should-not (overlays-at 14)))))
+
+(ert-deftest elide-head-tests-elide-head-mode/normal-mode ()
+ (ert-with-temp-file fil
+ (with-temp-file fil
+ (insert "foo\nSTART\nHIDDEN\nEND\nbar"))
+ (let ((elide-head-headers-to-hide '(("START" . "END")))
+ (buf (find-file-noselect fil)))
+ (save-excursion
+ (unwind-protect
+ (progn
+ (set-buffer buf)
+ (elide-head-mode 1)
+ (should (= 1 (length (overlays-in (point-min) (point-max)))))
+ (normal-mode)
+ (should (= 0 (length (overlays-in (point-min) (point-max))))))
+ (when buf (kill-buffer buf)))))))
+
+(ert-deftest elide-head-tests-elide-head-mode/revert-buffer ()
+ (ert-with-temp-file fil
+ (with-temp-file fil
+ (insert "foo\nSTART\nHIDDEN\nEND\nbar"))
+ (let ((elide-head-headers-to-hide '(("START" . "END")))
+ (buf (find-file-noselect fil)))
+ (save-excursion
+ (unwind-protect
+ (progn
+ (set-buffer buf)
+ (elide-head-mode 1)
+ (should (= 1 (length (overlays-in (point-min) (point-max)))))
+ (revert-buffer nil t)
+ (elide-head-mode 1)
+ (should (= 1 (length (overlays-in (point-min) (point-max))))))
+ (when buf (kill-buffer buf)))))))
+
+
+(defmacro elide-head--add-test (name text search-str)
+ `(ert-deftest ,(intern (format "elide-head--test-headers-to-hide/%s" name)) ()
+ (with-temp-buffer
+ (insert ,text)
+ (elide-head-mode 1)
+ (goto-char (point-min))
+ (re-search-forward ,search-str)
+ (let ((o (car (overlays-at (match-beginning 0)))))
+ (should (overlayp o))
+ (should (overlay-get o 'invisible))
+ (should (overlay-get o 'evaporate))))))
+
+
+;;; GPLv3
+
+;; from Emacs
+(elide-head--add-test gpl3-1 "\
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+" "GNU Emacs is distributed in the hope that")
+
+;; from libtorrent
+(elide-head--add-test gpl3-2 "\
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+" "This library is distributed in the hope that")
+
+;; from notmuch
+(elide-head--add-test gpl3-3 "\
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see https://www.gnu.org/licenses/ .
+" "This program is distributed in the hope that")
+
+;; from fribok
+(elide-head--add-test gpl3-4 "\
+/***************************************************************************
+ * Copyright (C) 2007, 2009 by J. Random Hacker <jrh@example.org> *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program. If not, see <http://www.gnu.org/licenses/> *.
+ * *
+ ***************************************************************************/
+" "This program is distributed in the hope that")
+
+
+;;; GPLv2
+
+;; from jackmeter
+(elide-head--add-test gpl2-1 "\
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+" "This program is distributed in the hope that")
+
+
+;;; Obsolete
+
+(with-suppressed-warnings ((obsolete elide-head)
+ (obsolete elide-head-show))
+ (ert-deftest elide-head-tests-elide-head ()
+ (let ((elide-head-headers-to-hide '(("START" . "END"))))
+ (with-temp-buffer
+ (insert "foo\nSTART\nHIDDEN\nEND\nbar")
+ (elide-head)
+ (let ((o (car (overlays-at 14))))
+ (should (= (overlay-start o) 10))
+ (should (= (overlay-end o) 21))
+ (should (overlay-get o 'invisible))
+ (should (overlay-get o 'evaporate))))))
+
+ (ert-deftest elide-head-tests-elide-head-with-prefix-arg ()
+ (let ((elide-head-headers-to-hide '(("START" . "END"))))
+ (with-temp-buffer
+ (insert "foo\nSTART\nHIDDEN\nEND\nbar")
+ (elide-head)
+ (should (overlays-at 14))
+ (elide-head t)
+ (should-not (overlays-at 14)))))
+
+ (ert-deftest elide-head-tests-show ()
+ (let ((elide-head-headers-to-hide '(("START" . "END"))))
+ (with-temp-buffer
+ (insert "foo\nSTART\nHIDDEN\nEND\nbar")
+ (elide-head)
+ (should (overlays-at 14))
+ (elide-head-show)
+ (should-not (overlays-at 14))))))
+
+(provide 'elide-head-tests)
+;;; elide-head-tests.el ends here
diff --git a/test/lisp/emacs-lisp/backquote-tests.el b/test/lisp/emacs-lisp/backquote-tests.el
new file mode 100644
index 00000000000..2ba61726f09
--- /dev/null
+++ b/test/lisp/emacs-lisp/backquote-tests.el
@@ -0,0 +1,47 @@
+;;; backquote-tests.el --- Tests for backquote.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2019-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+
+(ert-deftest backquote-test-basic ()
+ (let ((lst '(ba bb bc))
+ (vec [ba bb bc]))
+ (should (equal 3 `,(eval '(+ x y) '((x . 1) (y . 2)))))
+ (should (equal vec `[,@lst]))
+ (should (equal `(a lst c) '(a lst c)))
+ (should (equal `(a ,lst c) '(a (ba bb bc) c)))
+ (should (equal `(a ,@lst c) '(a ba bb bc c)))
+ ;; Vectors work just like lists.
+ (should (equal `(a vec c) '(a vec c)))
+ (should (equal `(a ,vec c) '(a [ba bb bc] c)))
+ (should (equal `(a ,@vec c) '(a ba bb bc c)))))
+
+(ert-deftest backquote-test-nested ()
+ "Test nested backquotes."
+ (let ((lst '(ba bb bc))
+ (vec [ba bb bc]))
+ (should (equal `(a ,`(,@lst) c) `(a ,lst c)))
+ (should (equal `(a ,`[,@lst] c) `(a ,vec c)))
+ (should (equal `(a ,@`[,@lst] c) `(a ,@lst c)))))
+
+;;; backquote-tests.el ends here
diff --git a/test/lisp/emacs-lisp/backtrace-tests.el b/test/lisp/emacs-lisp/backtrace-tests.el
new file mode 100644
index 00000000000..b42de06776b
--- /dev/null
+++ b/test/lisp/emacs-lisp/backtrace-tests.el
@@ -0,0 +1,485 @@
+;;; backtrace-tests.el --- Tests for backtraces -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2018-2022 Free Software Foundation, Inc.
+
+;; Author: Gemini Lasswell
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'backtrace)
+(require 'ert)
+(require 'ert-x)
+(require 'seq)
+
+;; Delay evaluation of the backtrace-creating functions until
+;; load so that the backtraces are the same whether this file
+;; is compiled or not.
+
+(eval-and-compile
+ (defconst backtrace-tests--uncompiled-functions
+ '(progn
+ (defun backtrace-tests--make-backtrace (arg)
+ (backtrace-tests--setup-buffer))
+
+ (defun backtrace-tests--setup-buffer ()
+ "Set up the current buffer in backtrace mode."
+ (backtrace-mode)
+ (setq backtrace-frames (backtrace-get-frames))
+ (let ((this-index))
+ ;; Discard all past `backtrace-tests--make-backtrace'.
+ (dotimes (index (length backtrace-frames))
+ (when (eq (backtrace-frame-fun (nth index backtrace-frames))
+ 'backtrace-tests--make-backtrace)
+ (setq this-index index)))
+ (setq backtrace-frames (seq-subseq backtrace-frames 0 (1+ this-index))))
+ (backtrace-print))))
+
+ (eval backtrace-tests--uncompiled-functions t))
+
+(defun backtrace-tests--backtrace-lines ()
+ (if debugger-stack-frame-as-list
+ '(" (backtrace-get-frames)\n"
+ " (setq backtrace-frames (backtrace-get-frames))\n"
+ " (backtrace-tests--setup-buffer)\n"
+ " (backtrace-tests--make-backtrace %s)\n")
+ '(" backtrace-get-frames()\n"
+ " (setq backtrace-frames (backtrace-get-frames))\n"
+ " backtrace-tests--setup-buffer()\n"
+ " backtrace-tests--make-backtrace(%s)\n")))
+
+(defconst backtrace-tests--line-count (length (backtrace-tests--backtrace-lines)))
+
+(defun backtrace-tests--backtrace-lines-with-locals ()
+ (let ((lines (backtrace-tests--backtrace-lines))
+ (locals '(" [no locals]\n"
+ " [no locals]\n"
+ " [no locals]\n"
+ " arg = %s\n")))
+ (apply #'append (cl-mapcar #'list lines locals))))
+
+(defun backtrace-tests--result (value)
+ (format (apply #'concat (backtrace-tests--backtrace-lines))
+ (cl-prin1-to-string value)))
+
+(defun backtrace-tests--result-with-locals (value)
+ (let ((str (cl-prin1-to-string value)))
+ (format (apply #'concat (backtrace-tests--backtrace-lines-with-locals))
+ str str)))
+
+;; TODO check that debugger-batch-max-lines still works
+
+(defconst backtrace-tests--header "Test header\n")
+(defun backtrace-tests--insert-header ()
+ (insert backtrace-tests--header))
+
+;;; Tests
+
+(ert-deftest backtrace-tests--variables ()
+ "Backtrace buffers can show and hide local variables."
+ (ert-with-test-buffer (:name "variables")
+ (let ((results (concat backtrace-tests--header
+ (backtrace-tests--result 'value)))
+ (last-frame (format (nth (1- backtrace-tests--line-count)
+ (backtrace-tests--backtrace-lines)) 'value))
+ (last-frame-with-locals
+ (format (apply #'concat (nthcdr (* 2 (1- backtrace-tests--line-count))
+ (backtrace-tests--backtrace-lines-with-locals)))
+ 'value 'value)))
+ (backtrace-tests--make-backtrace 'value)
+ (setq backtrace-insert-header-function #'backtrace-tests--insert-header)
+ (backtrace-print)
+ (should (string= (backtrace-tests--get-substring (point-min) (point-max))
+ results))
+ ;; Go to the last frame.
+ (goto-char (point-max))
+ (forward-line -1)
+ ;; Turn on locals for that frame.
+ (backtrace-toggle-locals)
+ (should (string= (backtrace-tests--get-substring (point) (point-max))
+ last-frame-with-locals))
+ (should (string= (backtrace-tests--get-substring (point-min) (point-max))
+ (concat results
+ (format (car (last (backtrace-tests--backtrace-lines-with-locals)))
+ 'value))))
+ ;; Turn off locals for that frame.
+ (backtrace-toggle-locals)
+ (should (string= (backtrace-tests--get-substring (point) (point-max))
+ last-frame))
+ (should (string= (backtrace-tests--get-substring (point-min) (point-max))
+ results))
+ ;; Turn all locals on.
+ (backtrace-toggle-locals '(4))
+ (should (string= (backtrace-tests--get-substring (point) (point-max))
+ last-frame-with-locals))
+ (should (string= (backtrace-tests--get-substring (point-min) (point-max))
+ (concat backtrace-tests--header
+ (backtrace-tests--result-with-locals 'value))))
+ ;; Turn all locals off.
+ (backtrace-toggle-locals '(4))
+ (should (string= (backtrace-tests--get-substring
+ (point) (+ (point) (length last-frame)))
+ last-frame))
+ (should (string= (backtrace-tests--get-substring (point-min) (point-max))
+ results)))))
+
+(ert-deftest backtrace-tests--backward-frame ()
+ "`backtrace-backward-frame' moves backward to the start of a frame."
+ (ert-with-test-buffer (:name "backward")
+ (let ((results (concat backtrace-tests--header
+ (backtrace-tests--result nil))))
+ (backtrace-tests--make-backtrace nil)
+ (setq backtrace-insert-header-function #'backtrace-tests--insert-header)
+ (backtrace-print)
+ (should (string= (backtrace-tests--get-substring (point-min) (point-max))
+ results))
+
+ ;; Try to move backward from header.
+ (goto-char (+ (point-min) (/ (length backtrace-tests--header) 2)))
+ (let ((pos (point)))
+ (should-error (backtrace-backward-frame))
+ (should (= pos (point))))
+
+ ;; Try to move backward from start of first line.
+ (forward-line)
+ (let ((pos (point)))
+ (should-error (backtrace-backward-frame))
+ (should (= pos (point))))
+
+ ;; Move backward from middle of line.
+ (let ((start (point)))
+ (forward-char (/ (length (nth 0 (backtrace-tests--backtrace-lines))) 2))
+ (backtrace-backward-frame)
+ (should (= start (point))))
+
+ ;; Move backward from end of buffer.
+ (goto-char (point-max))
+ (backtrace-backward-frame)
+ (let* ((last (format (car (last (backtrace-tests--backtrace-lines))) nil))
+ (len (length last)))
+ (should (string= (buffer-substring-no-properties (point) (+ (point) len))
+ last)))
+
+ ;; Move backward from start of line.
+ (backtrace-backward-frame)
+ (let* ((line (car (last (backtrace-tests--backtrace-lines) 2)))
+ (len (length line)))
+ (should (string= (buffer-substring-no-properties (point) (+ (point) len))
+ line))))))
+
+(ert-deftest backtrace-tests--forward-frame ()
+ "`backtrace-forward-frame' moves forward to the start of a frame."
+ (ert-with-test-buffer (:name "forward")
+ (let* ((arg '(1 2 3))
+ (results (concat backtrace-tests--header
+ (backtrace-tests--result arg)))
+ (first-line (nth 0 (backtrace-tests--backtrace-lines))))
+ (backtrace-tests--make-backtrace arg)
+ (setq backtrace-insert-header-function #'backtrace-tests--insert-header)
+ (backtrace-print)
+ (should (string= (backtrace-tests--get-substring (point-min) (point-max))
+ results))
+ ;; Move forward from header.
+ (goto-char (+ (point-min) (/ (length backtrace-tests--header) 2)))
+ (backtrace-forward-frame)
+ (should (string= (backtrace-tests--get-substring
+ (point) (+ (point) (length first-line)))
+ first-line))
+
+ (let ((start (point))
+ (offset (/ (length first-line) 2))
+ (second-line (nth 1 (backtrace-tests--backtrace-lines))))
+ ;; Move forward from start of first frame.
+ (backtrace-forward-frame)
+ (should (string= (backtrace-tests--get-substring
+ (point) (+ (point) (length second-line)))
+ second-line))
+ ;; Move forward from middle of first frame.
+ (goto-char (+ start offset))
+ (backtrace-forward-frame)
+ (should (string= (backtrace-tests--get-substring
+ (point) (+ (point) (length second-line)))
+ second-line)))
+ ;; Try to move forward from middle of last frame.
+ (goto-char (- (point-max)
+ (/ 2 (length (car (last (backtrace-tests--backtrace-lines)))))))
+ (should-error (backtrace-forward-frame))
+ ;; Try to move forward from end of buffer.
+ (goto-char (point-max))
+ (should-error (backtrace-forward-frame)))))
+
+(ert-deftest backtrace-tests--single-and-multi-line ()
+ "Forms in backtrace frames can be on a single line or on multiple lines."
+ (ert-with-test-buffer (:name "single-multi-line")
+ (let* ((arg '(lambda (x) ; Quote this so it isn't made into a closure.
+ (let ((number (1+ x)))
+ (+ x number))))
+ (header-string "Test header: ")
+ (header (format "%s%s\n" header-string arg))
+ (insert-header-function (lambda ()
+ (insert header-string)
+ (insert (backtrace-print-to-string arg))
+ (insert "\n")))
+ (results (concat header (backtrace-tests--result arg)))
+ (last-line (format (nth (1- backtrace-tests--line-count)
+ (backtrace-tests--backtrace-lines))
+ arg))
+ (last-line-locals (format (nth (1- (* 2 backtrace-tests--line-count))
+ (backtrace-tests--backtrace-lines-with-locals))
+ arg)))
+
+ (backtrace-tests--make-backtrace arg)
+ (setq backtrace-insert-header-function insert-header-function)
+ (backtrace-print)
+ (should (string= (backtrace-tests--get-substring (point-min) (point-max))
+ results))
+ ;; Check pp and collapse for the form in the header.
+ (goto-char (point-min))
+ (backtrace-tests--verify-single-and-multi-line header)
+ ;; Check pp and collapse for the last frame.
+ (goto-char (point-max))
+ (backtrace-backward-frame)
+ (backtrace-tests--verify-single-and-multi-line last-line)
+ ;; Check pp and collapse for local variables in the last line.
+ (goto-char (point-max))
+ (backtrace-backward-frame)
+ (backtrace-toggle-locals)
+ (forward-line)
+ (backtrace-tests--verify-single-and-multi-line last-line-locals))))
+
+(defun backtrace-tests--verify-single-and-multi-line (line)
+ "Verify that `backtrace-single-line' and `backtrace-multi-line' work at point.
+Point should be at the beginning of a line, and LINE should be a
+string containing the text of the line at point. Assume that the
+line contains the strings \"lambda\" and \"number\"."
+ (let ((pos (point)))
+ (backtrace-multi-line)
+ ;; Verify point is still at the start of the line.
+ (should (= pos (point))))
+
+ ;; Verify the form now spans multiple lines.
+ (let ((pos (point)))
+ (search-forward "number")
+ (should-not (= pos (pos-bol))))
+ ;; Collapse the form.
+ (backtrace-single-line)
+ ;; Verify that the form is now back on one line,
+ ;; and that point is at the same place.
+ (should (string= (backtrace-tests--get-substring
+ (- (point) 6) (point)) "number"))
+ (should-not (= (point) (pos-bol)))
+ (should (string= (backtrace-tests--get-substring
+ (pos-bol) (1+ (pos-eol)))
+ line)))
+
+(ert-deftest backtrace-tests--print-circle ()
+ "Backtrace buffers can toggle `print-circle' syntax."
+ (ert-with-test-buffer (:name "print-circle")
+ (let* ((print-circle nil)
+ (arg (let ((val (make-list 5 'a))) (nconc val val) val))
+ (results (backtrace-tests--make-regexp
+ (backtrace-tests--result arg)))
+ (results-circle (regexp-quote (let ((print-circle t))
+ (backtrace-tests--result arg))))
+ (last-frame (backtrace-tests--make-regexp
+ (format (nth (1- backtrace-tests--line-count)
+ (backtrace-tests--backtrace-lines))
+ arg)))
+ (last-frame-circle (regexp-quote
+ (let ((print-circle t))
+ (format (nth (1- backtrace-tests--line-count)
+ (backtrace-tests--backtrace-lines))
+ arg)))))
+ (backtrace-tests--make-backtrace arg)
+ (backtrace-print)
+ (should (string-match-p results
+ (backtrace-tests--get-substring (point-min) (point-max))))
+ ;; Go to the last frame.
+ (goto-char (point-max))
+ (forward-line -1)
+ ;; Turn on print-circle for that frame.
+ (backtrace-toggle-print-circle)
+ (should (string-match-p last-frame-circle
+ (backtrace-tests--get-substring (point) (point-max))))
+ ;; Turn off print-circle for the frame.
+ (backtrace-toggle-print-circle)
+ (should (string-match-p last-frame
+ (backtrace-tests--get-substring (point) (point-max))))
+ (should (string-match-p results
+ (backtrace-tests--get-substring (point-min) (point-max))))
+ ;; Turn print-circle on for the buffer.
+ (backtrace-toggle-print-circle '(4))
+ (should (string-match-p last-frame-circle
+ (backtrace-tests--get-substring (point) (point-max))))
+ (should (string-match-p results-circle
+ (backtrace-tests--get-substring (point-min) (point-max))))
+ ;; Turn print-circle off.
+ (backtrace-toggle-print-circle '(4))
+ (should (string-match-p last-frame
+ (backtrace-tests--get-substring
+ (point) (+ (point) (length last-frame)))))
+ (should (string-match-p results
+ (backtrace-tests--get-substring (point-min) (point-max)))))))
+
+(ert-deftest backtrace-tests--print-gensym ()
+ "Backtrace buffers can toggle `print-gensym' syntax."
+ (ert-with-test-buffer (:name "print-gensym")
+ (let* ((print-gensym nil)
+ (arg (list (gensym "first") (gensym) (gensym "last")))
+ (results (backtrace-tests--make-regexp
+ (backtrace-tests--result arg)))
+ (results-gensym (regexp-quote (let ((print-gensym t))
+ (backtrace-tests--result arg))))
+ (last-frame (backtrace-tests--make-regexp
+ (format (nth (1- backtrace-tests--line-count)
+ (backtrace-tests--backtrace-lines))
+ arg)))
+ (last-frame-gensym (regexp-quote
+ (let ((print-gensym t))
+ (format (nth (1- backtrace-tests--line-count)
+ (backtrace-tests--backtrace-lines))
+ arg)))))
+ (backtrace-tests--make-backtrace arg)
+ (backtrace-print)
+ (should (string-match-p results
+ (backtrace-tests--get-substring (point-min) (point-max))))
+ ;; Go to the last frame.
+ (goto-char (point-max))
+ (forward-line -1)
+ ;; Turn on print-gensym for that frame.
+ (backtrace-toggle-print-gensym)
+ (should (string-match-p last-frame-gensym
+ (backtrace-tests--get-substring (point) (point-max))))
+ ;; Turn off print-gensym for the frame.
+ (backtrace-toggle-print-gensym)
+ (should (string-match-p last-frame
+ (backtrace-tests--get-substring (point) (point-max))))
+ (should (string-match-p results
+ (backtrace-tests--get-substring (point-min) (point-max))))
+ ;; Turn print-gensym on for the buffer.
+ (backtrace-toggle-print-gensym '(4))
+ (should (string-match-p last-frame-gensym
+ (backtrace-tests--get-substring (point) (point-max))))
+ (should (string-match-p results-gensym
+ (backtrace-tests--get-substring (point-min) (point-max))))
+ ;; Turn print-gensym off.
+ (backtrace-toggle-print-gensym '(4))
+ (should (string-match-p last-frame
+ (backtrace-tests--get-substring
+ (point) (+ (point) (length last-frame)))))
+ (should (string-match-p results
+ (backtrace-tests--get-substring (point-min) (point-max)))))))
+
+(defun backtrace-tests--make-regexp (str)
+ "Make regexp from STR for `backtrace-tests--print-circle'.
+Used for results of printing circular objects without
+`print-circle' on. Look for #n in string STR where n is any
+digit and replace with #[0-9]."
+ (let ((regexp (regexp-quote str)))
+ (with-temp-buffer
+ (insert regexp)
+ (goto-char (point-min))
+ (while (re-search-forward "#[0-9]" nil t)
+ (replace-match "#[0-9]")))
+ (buffer-string)))
+
+(ert-deftest backtrace-tests--expand-ellipsis ()
+ "Backtrace buffers ellipsify large forms as buttons which expand the ellipses."
+ ;; make a backtrace with an ellipsis
+ ;; expand the ellipsis
+ (ert-with-test-buffer (:name "variables")
+ (let* ((print-level nil)
+ (print-length nil)
+ (backtrace-line-length 300)
+ (arg (make-list 40 (make-string 10 ?a)))
+ (results (backtrace-tests--result arg)))
+ (backtrace-tests--make-backtrace arg)
+ (backtrace-print)
+
+ ;; There should be an ellipsis. Find and expand it.
+ (goto-char (point-min))
+ (search-forward "...")
+ (backward-char)
+ (push-button)
+
+ (should (string= (backtrace-tests--get-substring (point-min) (point-max))
+ results)))))
+
+(ert-deftest backtrace-tests--expand-ellipses ()
+ "Backtrace buffers ellipsify large forms and can expand the ellipses."
+ (ert-with-test-buffer (:name "variables")
+ (let* ((print-level nil)
+ (print-length nil)
+ (backtrace-line-length 300)
+ (arg (let ((outer (make-list 40 (make-string 10 ?a)))
+ (nested (make-list 40 (make-string 10 ?b))))
+ (setf (nth 39 nested) (make-list 40 (make-string 10 ?c)))
+ (setf (nth 39 outer) nested)
+ outer))
+ (results (backtrace-tests--result-with-locals arg)))
+
+ ;; Make a backtrace with local variables visible.
+ (backtrace-tests--make-backtrace arg)
+ (backtrace-print)
+ (backtrace-toggle-locals '(4))
+
+ ;; There should be two ellipses.
+ (goto-char (point-min))
+ (should (search-forward "..."))
+ (should (search-forward "..."))
+ (should-error (search-forward "..."))
+
+ ;; Expanding the last frame without argument should expand both
+ ;; ellipses, but the expansions will contain one ellipsis each.
+ (let ((buffer-len (- (point-max) (point-min))))
+ (goto-char (point-max))
+ (backtrace-backward-frame)
+ (backtrace-expand-ellipses)
+ (should (> (- (point-max) (point-min)) buffer-len))
+ (goto-char (point-min))
+ (should (search-forward "..."))
+ (should (search-forward "..."))
+ (should-error (search-forward "...")))
+
+ ;; Expanding with argument should remove all ellipses.
+ (goto-char (point-max))
+ (backtrace-backward-frame)
+ (backtrace-expand-ellipses '(4))
+ (goto-char (point-min))
+
+ (should-error (search-forward "..."))
+ (should (string= (backtrace-tests--get-substring (point-min) (point-max))
+ results)))))
+
+
+(ert-deftest backtrace-tests--to-string ()
+ "Backtraces can be produced as strings."
+ (let ((frames (ert-with-test-buffer (:name nil)
+ (backtrace-tests--make-backtrace "string")
+ backtrace-frames)))
+ (should (string= (backtrace-to-string frames)
+ (backtrace-tests--result "string")))))
+
+(defun backtrace-tests--get-substring (beg end)
+ "Return the visible text between BEG and END.
+Strip the string properties because it makes failed test results
+easier to read."
+ (substring-no-properties (filter-buffer-substring beg end)))
+
+(provide 'backtrace-tests)
+
+;;; backtrace-tests.el ends here
diff --git a/test/lisp/emacs-lisp/benchmark-tests.el b/test/lisp/emacs-lisp/benchmark-tests.el
index e1b67f1ed17..b3c4949acc7 100644
--- a/test/lisp/emacs-lisp/benchmark-tests.el
+++ b/test/lisp/emacs-lisp/benchmark-tests.el
@@ -1,6 +1,6 @@
;;; benchmark-tests.el --- Test suite for benchmark. -*- lexical-binding: t -*-
-;; Copyright (C) 2017 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2022 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -23,29 +23,37 @@
(require 'ert)
(ert-deftest benchmark-tests ()
- (let (str t-long t-short)
- (should (consp (benchmark-run nil (1+ 0))))
- (should (consp (benchmark-run 1 (1+ 0))))
+ (let (str t-long t-short m)
+ (should (consp (benchmark-run nil (setq m (1+ 0)))))
+ (should (consp (benchmark-run 1 (setq m (1+ 0)))))
(should (stringp (benchmark nil (1+ 0))))
(should (stringp (benchmark 1 (1+ 0))))
- (should (consp (benchmark-run-compiled nil (1+ 0))))
+ (should (consp (benchmark-run-compiled (1+ 0))))
(should (consp (benchmark-run-compiled 1 (1+ 0))))
;; First test is heavier, must need longer time.
- (should (> (car (benchmark-run nil
+ (let ((count1 0)
+ (count2 0)
+ (repeat 2))
+ (ignore (benchmark-run (setq count1 (1+ count1))))
+ (ignore (benchmark-run repeat (setq count2 (1+ count2))))
+ (should (> count2 count1)))
+ (should (> (car (benchmark-run
(let ((n 100000)) (while (> n 1) (setq n (1- n))))))
- (car (benchmark-run nil (1+ 0)))))
- (should (> (car (benchmark-run nil
+ (car (benchmark-run (setq m (1+ 0))))))
+ (should (> (car (benchmark-run
(let ((n 100000)) (while (> n 1) (setq n (1- n))))))
- (car (benchmark-run nil (1+ 0)))))
- (should (> (car (benchmark-run-compiled nil
+ (car (benchmark-run (setq m (1+ 0))))))
+ (should (> (car (benchmark-run-compiled
(let ((n 100000)) (while (> n 1) (setq n (1- n))))))
- (car (benchmark-run-compiled nil (1+ 0)))))
+ (car (benchmark-run-compiled (1+ 0)))))
(setq str (benchmark nil '(let ((n 100000)) (while (> n 1) (setq n (1- n))))))
(string-match "Elapsed time: \\([0-9.]+\\)" str)
(setq t-long (string-to-number (match-string 1 str)))
(setq str (benchmark nil '(1+ 0)))
(string-match "Elapsed time: \\([0-9.]+\\)" str)
(setq t-short (string-to-number (match-string 1 str)))
- (should (> t-long t-short))))
+ (should (> t-long t-short))
+ ;; Silence compiler.
+ m))
;;; benchmark-tests.el ends here.
diff --git a/test/lisp/emacs-lisp/bindat-tests.el b/test/lisp/emacs-lisp/bindat-tests.el
new file mode 100644
index 00000000000..0c03c51e2ef
--- /dev/null
+++ b/test/lisp/emacs-lisp/bindat-tests.el
@@ -0,0 +1,285 @@
+;;; bindat-tests.el --- tests for bindat.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2019-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'bindat)
+(require 'cl-lib)
+
+(bindat-defmacro ip () "An IPv4 address" '(vec 4 byte))
+
+(defconst header-bindat-spec
+ (bindat-type
+ (dest-ip ip)
+ (src-ip ip)
+ (dest-port uint 16)
+ (src-port uint 16)))
+
+(defconst data-bindat-spec
+ (bindat-type
+ (type u8)
+ (opcode u8)
+ (length uint 16 'le) ;; little endian order
+ (id strz 8)
+ (data vec length)
+ (_ align 4)))
+
+
+(defconst packet-bindat-spec
+ (bindat-type
+ (header type header-bindat-spec)
+ (items u8)
+ (_ fill 3)
+ (item repeat items
+ (_ type data-bindat-spec))))
+
+(defconst struct-bindat
+ '((header
+ (dest-ip . [192 168 1 100])
+ (src-ip . [192 168 1 101])
+ (dest-port . 284)
+ (src-port . 5408))
+ (items . 2)
+ (item ((type . 2)
+ (opcode . 3)
+ (length . 5)
+ (id . "ABCDEF")
+ (data . [1 2 3 4 5]))
+ ((type . 1)
+ (opcode . 4)
+ (length . 7)
+ (id . "BCDEFG")
+ (data . [6 7 8 9 10 11 12])))))
+
+(ert-deftest bindat-test-pack ()
+ (should (equal
+ (cl-map 'vector #'identity
+ (bindat-pack packet-bindat-spec struct-bindat))
+ [ 192 168 1 100 192 168 1 101 01 28 21 32 2 0 0 0
+ 2 3 5 0 ?A ?B ?C ?D ?E ?F 0 0 1 2 3 4 5 0 0 0
+ 1 4 7 0 ?B ?C ?D ?E ?F ?G 0 0 6 7 8 9 10 11 12 0 ])))
+
+(ert-deftest bindat-test-unpack ()
+ (should (equal
+ (bindat-unpack packet-bindat-spec
+ (bindat-pack packet-bindat-spec struct-bindat))
+ struct-bindat)))
+
+(ert-deftest bindat-test-pack/multibyte-string-fails ()
+ (should-error (bindat-pack nil nil "ö")))
+
+(ert-deftest bindat-test-unpack/multibyte-string-fails ()
+ (should-error (bindat-unpack nil "ö")))
+
+(ert-deftest bindat-test-format-vector ()
+ (should (equal (bindat-format-vector [1 2 3] "%d" "x" 2) "1x2"))
+ (should (equal (bindat-format-vector [1 2 3] "%d" "x") "1x2x3")))
+
+(ert-deftest bindat-test-vector-to-dec ()
+ (should (equal (bindat-vector-to-dec [1 2 3]) "1.2.3"))
+ (should (equal (bindat-vector-to-dec [2048 1024 512] ".") "2048.1024.512")))
+
+(ert-deftest bindat-test-vector-to-hex ()
+ (should (equal (bindat-vector-to-hex [1 2 3]) "01:02:03"))
+ (should (equal (bindat-vector-to-hex [2048 1024 512] ".") "800.400.200")))
+
+(ert-deftest bindat-test-ip-to-string ()
+ (should (equal (bindat-ip-to-string [192 168 0 1]) "192.168.0.1"))
+ (should (equal (bindat-ip-to-string "\300\250\0\1") "192.168.0.1")))
+
+(defconst bindat-test--int-websocket-type
+ (bindat-type
+ :pack-var value
+ (n1 u8
+ :pack-val (if (< value 126) value (if (< value 65536) 126 127)))
+ (n2 uint (pcase n1 (127 64) (126 16) (_ 0))
+ :pack-val value)
+ :unpack-val (if (< n1 126) n1 n2)))
+
+(ert-deftest bindat-test--pack-val ()
+ ;; This is intended to test the :(un)pack-val feature that offers
+ ;; control over the unpacked representation of the data.
+ (dolist (n '(0 42 125 126 127 128 150 255 5000 65535 65536 8769786876))
+ (should
+ (equal (bindat-unpack bindat-test--int-websocket-type
+ (bindat-pack bindat-test--int-websocket-type n))
+ n))))
+
+(ert-deftest bindat-test--sint ()
+ (dotimes (kind 32)
+ (let ((bitlen (* 8 (/ kind 2)))
+ (r (zerop (% kind 2))))
+ (dotimes (_ 100)
+ (let* ((n (random (ash 1 bitlen)))
+ (i (- n (ash 1 (1- bitlen))))
+ (stype (bindat-type sint bitlen r))
+ (utype (bindat-type if r (uintr bitlen) (uint bitlen))))
+ (should (equal (bindat-unpack
+ stype
+ (bindat-pack stype i))
+ i))
+ (when (>= i 0)
+ (should (equal (bindat-pack utype i)
+ (bindat-pack stype i)))
+ (should (equal (bindat-unpack utype (bindat-pack stype i))
+ i))))))))
+
+(defconst bindat-test--LEB128
+ (bindat-type
+ letrec ((loop
+ (struct :pack-var n
+ (head u8
+ :pack-val (+ (logand n 127) (if (> n 127) 128 0)))
+ (tail if (< head 128) (unit 0) loop
+ :pack-val (ash n -7))
+ :unpack-val (+ (logand head 127) (ash tail 7)))))
+ loop))
+
+(ert-deftest bindat-test--recursive ()
+ (dotimes (n 10)
+ (let ((max (ash 1 (* n 10))))
+ (dotimes (_ 10)
+ (let ((n (random max)))
+ (should (equal (bindat-unpack bindat-test--LEB128
+ (bindat-pack bindat-test--LEB128 n))
+ n)))))))
+
+(ert-deftest bindat-test--str-strz-prealloc ()
+ (dolist (tc `(((,(bindat-type str 1) "") . "xx")
+ ((,(bindat-type str 2) "") . "xx")
+ ((,(bindat-type str 2) "a") . "ax")
+ ((,(bindat-type str 2) "ab") . "ab")
+ ((,(bindat-type str 2) "abc") . "ab")
+ ((((x str 1)) ((x . ""))) . "xx")
+ ((((x str 2)) ((x . ""))) . "xx")
+ ((((x str 2)) ((x . "a"))) . "ax")
+ ((((x str 2)) ((x . "ab"))) . "ab")
+ ((((x str 2)) ((x . "abc"))) . "ab")
+ ((,(bindat-type strz 1) "") . "\0x")
+ ((,(bindat-type strz 2) "") . "\0x")
+ ((,(bindat-type strz 2) "a") . "a\0")
+ ((,(bindat-type strz 2) "ab") . "ab")
+ ((,(bindat-type strz 2) "abc") . "ab")
+ ((((x strz 1)) ((x . ""))) . "\0x")
+ ((((x strz 2)) ((x . ""))) . "\0x")
+ ((((x strz 2)) ((x . "a"))) . "a\0")
+ ((((x strz 2)) ((x . "ab"))) . "ab")
+ ((((x strz 2)) ((x . "abc"))) . "ab")
+ ((,(bindat-type strz) "") . "\0x")
+ ((,(bindat-type strz) "a") . "a\0")))
+ (let ((prealloc (make-string 2 ?x)))
+ (apply #'bindat-pack (append (car tc) (list prealloc)))
+ (should (equal prealloc (cdr tc))))))
+
+(ert-deftest bindat-test--str-strz-multibyte ()
+ (dolist (spec (list (bindat-type str 2)
+ (bindat-type strz 2)
+ (bindat-type strz)))
+ (should (equal (bindat-pack spec (string-to-multibyte "x")) "x\0"))
+ (should (equal (bindat-pack spec (string-to-multibyte "\xff")) "\xff\0"))
+ (should-error (bindat-pack spec "💩"))
+ (should-error (bindat-pack spec "\N{U+ff}")))
+ (dolist (spec (list '((x str 2)) '((x strz 2))))
+ (should (equal (bindat-pack spec `((x . ,(string-to-multibyte "x"))))
+ "x\0"))
+ (should (equal (bindat-pack spec `((x . ,(string-to-multibyte "\xff"))))
+ "\xff\0"))
+ (should-error (bindat-pack spec '((x . "💩"))))
+ (should-error (bindat-pack spec '((x . "\N{U+ff}"))))))
+
+(let ((spec (bindat-type strz 2)))
+ (ert-deftest bindat-test--strz-fixedlen-len ()
+ (should (equal (bindat-length spec "") 2))
+ (should (equal (bindat-length spec "a") 2)))
+
+ (ert-deftest bindat-test--strz-fixedlen-len-overflow ()
+ (should (equal (bindat-length spec "ab") 2))
+ (should (equal (bindat-length spec "abc") 2)))
+
+ (ert-deftest bindat-test--strz-fixedlen-pack ()
+ (should (equal (bindat-pack spec "") "\0\0"))
+ (should (equal (bindat-pack spec "a") "a\0")))
+
+ (ert-deftest bindat-test--strz-fixedlen-pack-overflow ()
+ ;; This is not the only valid semantic, but it's the one we've
+ ;; offered historically.
+ (should (equal (bindat-pack spec "ab") "ab"))
+ (should (equal (bindat-pack spec "abc") "ab")))
+
+ (ert-deftest bindat-test--strz-fixedlen-unpack ()
+ (should (equal (bindat-unpack spec "\0\0") ""))
+ (should (equal (bindat-unpack spec "\0X") ""))
+ (should (equal (bindat-unpack spec "a\0") "a"))
+ ;; Same comment as for b-t-s-f-pack-overflow.
+ (should (equal (bindat-unpack spec "ab") "ab"))
+ ;; Missing null terminator.
+ (should-error (bindat-unpack spec ""))
+ (should-error (bindat-unpack spec "a"))))
+
+(let ((spec (bindat-type strz)))
+ (ert-deftest bindat-test--strz-varlen-len ()
+ (should (equal (bindat-length spec "") 1))
+ (should (equal (bindat-length spec "abc") 4)))
+
+ (ert-deftest bindat-test--strz-varlen-pack ()
+ (should (equal (bindat-pack spec "") "\0"))
+ (should (equal (bindat-pack spec "abc") "abc\0"))
+ ;; Null bytes in the input string break unpacking.
+ (should-error (bindat-pack spec "\0"))
+ (should-error (bindat-pack spec "\0x"))
+ (should-error (bindat-pack spec "x\0"))
+ (should-error (bindat-pack spec "x\0y")))
+
+ (ert-deftest bindat-test--strz-varlen-unpack ()
+ (should (equal (bindat-unpack spec "\0") ""))
+ (should (equal (bindat-unpack spec "abc\0") "abc"))
+ ;; Missing null terminator.
+ (should-error (bindat-unpack spec ""))
+ (should-error (bindat-unpack spec "a"))))
+
+(let ((spec '((x strz 2))))
+ (ert-deftest bindat-test--strz-legacy-fixedlen-len ()
+ (should (equal (bindat-length spec '((x . ""))) 2))
+ (should (equal (bindat-length spec '((x . "a"))) 2)))
+
+ (ert-deftest bindat-test--strz-legacy-fixedlen-len-overflow ()
+ (should (equal (bindat-length spec '((x . "ab"))) 2))
+ (should (equal (bindat-length spec '((x . "abc"))) 2)))
+
+ (ert-deftest bindat-test--strz-legacy-fixedlen-pack ()
+ (should (equal (bindat-pack spec '((x . ""))) "\0\0"))
+ (should (equal (bindat-pack spec '((x . "a"))) "a\0")))
+
+ (ert-deftest bindat-test--strz-legacy-fixedlen-pack-overflow ()
+ ;; Same comment as for b-t-s-f-pack-overflow.
+ (should (equal (bindat-pack spec '((x . "ab"))) "ab"))
+ (should (equal (bindat-pack spec '((x . "abc"))) "ab")))
+
+ (ert-deftest bindat-test--strz-legacy-fixedlen-unpack ()
+ (should (equal (bindat-unpack spec "\0\0") '((x . ""))))
+ (should (equal (bindat-unpack spec "\0X") '((x . ""))))
+ (should (equal (bindat-unpack spec "a\0") '((x . "a"))))
+ ;; Same comment as for b-t-s-f-pack-overflow.
+ (should (equal (bindat-unpack spec "ab") '((x . "ab"))))
+ ;; Missing null terminator.
+ (should-error (bindat-unpack spec ""))
+ (should-error (bindat-unpack spec "a"))))
+
+;;; bindat-tests.el ends here
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/bc-test-alpha.el b/test/lisp/emacs-lisp/bytecomp-resources/bc-test-alpha.el
new file mode 100644
index 00000000000..6997d91b26a
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/bc-test-alpha.el
@@ -0,0 +1,9 @@
+;;; -*- lexical-binding: t -*-
+
+(require 'bc-test-beta)
+
+(defun bc-test-alpha-f (x)
+ (let ((y nil))
+ (list y (bc-test-beta-f x))))
+
+(provide 'bc-test-alpha)
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/bc-test-beta.el b/test/lisp/emacs-lisp/bytecomp-resources/bc-test-beta.el
new file mode 100644
index 00000000000..9205a13d7d5
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/bc-test-beta.el
@@ -0,0 +1,6 @@
+;;; -*- lexical-binding: t -*-
+
+(defsubst bc-test-beta-f (y)
+ y)
+
+(provide 'bc-test-beta)
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/error-lexical-var-with-add-hook.el b/test/lisp/emacs-lisp/bytecomp-resources/error-lexical-var-with-add-hook.el
new file mode 100644
index 00000000000..5f390898e6a
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/error-lexical-var-with-add-hook.el
@@ -0,0 +1,4 @@
+;;; -*- lexical-binding: t; -*-
+(let ((foo nil))
+ (add-hook 'foo #'next-line)
+ foo)
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/error-lexical-var-with-remove-hook.el b/test/lisp/emacs-lisp/bytecomp-resources/error-lexical-var-with-remove-hook.el
new file mode 100644
index 00000000000..eaa625eba1c
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/error-lexical-var-with-remove-hook.el
@@ -0,0 +1,4 @@
+;;; -*- lexical-binding: t; -*-
+(let ((foo nil))
+ (remove-hook 'foo #'next-line)
+ foo)
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/error-lexical-var-with-run-hook-with-args-until-failure.el b/test/lisp/emacs-lisp/bytecomp-resources/error-lexical-var-with-run-hook-with-args-until-failure.el
new file mode 100644
index 00000000000..7a116ad464b
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/error-lexical-var-with-run-hook-with-args-until-failure.el
@@ -0,0 +1,3 @@
+;;; -*- lexical-binding: t; -*-
+(let ((foo nil))
+ (run-hook-with-args-until-failure 'foo))
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/error-lexical-var-with-run-hook-with-args-until-success.el b/test/lisp/emacs-lisp/bytecomp-resources/error-lexical-var-with-run-hook-with-args-until-success.el
new file mode 100644
index 00000000000..96d10a343df
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/error-lexical-var-with-run-hook-with-args-until-success.el
@@ -0,0 +1,3 @@
+;;; -*- lexical-binding: t; -*-
+(let ((foo nil))
+ (run-hook-with-args-until-success 'foo #'next-line))
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/error-lexical-var-with-run-hook-with-args.el b/test/lisp/emacs-lisp/bytecomp-resources/error-lexical-var-with-run-hook-with-args.el
new file mode 100644
index 00000000000..bb9101bd070
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/error-lexical-var-with-run-hook-with-args.el
@@ -0,0 +1,3 @@
+;;; -*- lexical-binding: t; -*-
+(let ((foo nil))
+ (run-hook-with-args 'foo))
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/error-lexical-var-with-symbol-value.el b/test/lisp/emacs-lisp/bytecomp-resources/error-lexical-var-with-symbol-value.el
new file mode 100644
index 00000000000..5f390898e6a
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/error-lexical-var-with-symbol-value.el
@@ -0,0 +1,4 @@
+;;; -*- lexical-binding: t; -*-
+(let ((foo nil))
+ (add-hook 'foo #'next-line)
+ foo)
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/foo-inlinable.el b/test/lisp/emacs-lisp/bytecomp-resources/foo-inlinable.el
new file mode 100644
index 00000000000..47481574ea8
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/foo-inlinable.el
@@ -0,0 +1,6 @@
+;; -*- lexical-binding: t; -*-
+
+(defsubst foo-inlineable (foo-var)
+ (+ foo-var 2))
+
+(provide 'foo-inlinable)
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/fun-attr-warn.el b/test/lisp/emacs-lisp/bytecomp-resources/fun-attr-warn.el
new file mode 100644
index 00000000000..be907b32f47
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/fun-attr-warn.el
@@ -0,0 +1,266 @@
+;;; -*- lexical-binding: t -*-
+
+;; Correct
+
+(defun faw-str-decl-code (x)
+ "something"
+ (declare (pure t))
+ (print x))
+
+(defun faw-doc-decl-code (x)
+ (:documentation "something")
+ (declare (pure t))
+ (print x))
+
+(defun faw-str-int-code (x)
+ "something"
+ (interactive "P")
+ (print x))
+
+(defun faw-doc-int-code (x)
+ (:documentation "something")
+ (interactive "P")
+ (print x))
+
+(defun faw-decl-int-code (x)
+ (declare (pure t))
+ (interactive "P")
+ (print x))
+
+(defun faw-str-decl-int-code (x)
+ "something"
+ (declare (pure t))
+ (interactive "P")
+ (print x))
+
+(defun faw-doc-decl-int-code (x)
+ (:documentation "something")
+ (declare (pure t))
+ (interactive "P")
+ (print x))
+
+
+;; Correct (last string is return value)
+
+(defun faw-str ()
+ "something")
+
+(defun faw-decl-str ()
+ (declare (pure t))
+ "something")
+
+(defun faw-decl-int-str ()
+ (declare (pure t))
+ (interactive)
+ "something")
+
+(defun faw-str-str ()
+ "something"
+ "something else")
+
+(defun faw-doc-str ()
+ (:documentation "something")
+ "something else")
+
+
+;; Incorrect (bad order)
+
+(defun faw-int-decl-code (x)
+ (interactive "P")
+ (declare (pure t))
+ (print x))
+
+(defun faw-int-str-code (x)
+ (interactive "P")
+ "something"
+ (print x))
+
+(defun faw-int-doc-code (x)
+ (interactive "P")
+ (:documentation "something")
+ (print x))
+
+(defun faw-decl-str-code (x)
+ (declare (pure t))
+ "something"
+ (print x))
+
+(defun faw-decl-doc-code (x)
+ (declare (pure t))
+ (:documentation "something")
+ (print x))
+
+(defun faw-str-int-decl-code (x)
+ "something"
+ (interactive "P")
+ (declare (pure t))
+ (print x))
+
+(defun faw-doc-int-decl-code (x)
+ (:documentation "something")
+ (interactive "P")
+ (declare (pure t))
+ (print x))
+
+(defun faw-int-str-decl-code (x)
+ (interactive "P")
+ "something"
+ (declare (pure t))
+ (print x))
+
+(defun faw-int-doc-decl-code (x)
+ (interactive "P")
+ (:documentation "something")
+ (declare (pure t))
+ (print x))
+
+(defun faw-int-decl-str-code (x)
+ (interactive "P")
+ (declare (pure t))
+ "something"
+ (print x))
+
+(defun faw-int-decl-doc-code (x)
+ (interactive "P")
+ (declare (pure t))
+ (:documentation "something")
+ (print x))
+
+(defun faw-decl-int-str-code (x)
+ (declare (pure t))
+ (interactive "P")
+ "something"
+ (print x))
+
+(defun faw-decl-int-doc-code (x)
+ (declare (pure t))
+ (interactive "P")
+ (:documentation "something")
+ (print x))
+
+(defun faw-decl-str-int-code (x)
+ (declare (pure t))
+ "something"
+ (interactive "P")
+ (print x))
+
+(defun faw-decl-doc-int-code (x)
+ (declare (pure t))
+ (:documentation "something")
+ (interactive "P")
+ (print x))
+
+
+;; Incorrect (duplication)
+
+(defun faw-str-str-decl-int-code (x)
+ "something"
+ "something else"
+ (declare (pure t))
+ (interactive "P")
+ (print x))
+
+(defun faw-str-doc-decl-int-code (x)
+ "something"
+ (:documentation "something else")
+ (declare (pure t))
+ (interactive "P")
+ (print x))
+
+(defun faw-doc-str-decl-int-code (x)
+ (:documentation "something")
+ "something else"
+ (declare (pure t))
+ (interactive "P")
+ (print x))
+
+(defun faw-doc-doc-decl-int-code (x)
+ (:documentation "something")
+ (:documentation "something else")
+ (declare (pure t))
+ (interactive "P")
+ (print x))
+
+(defun faw-str-decl-str-int-code (x)
+ "something"
+ (declare (pure t))
+ "something else"
+ (interactive "P")
+ (print x))
+
+(defun faw-doc-decl-str-int-code (x)
+ (:documentation "something")
+ (declare (pure t))
+ "something else"
+ (interactive "P")
+ (print x))
+
+(defun faw-str-decl-doc-int-code (x)
+ "something"
+ (declare (pure t))
+ (:documentation "something else")
+ (interactive "P")
+ (print x))
+
+(defun faw-doc-decl-doc-int-code (x)
+ (:documentation "something")
+ (declare (pure t))
+ (:documentation "something else")
+ (interactive "P")
+ (print x))
+
+(defun faw-str-decl-decl-int-code (x)
+ "something"
+ (declare (pure t))
+ (declare (indent 1))
+ (interactive "P")
+ (print x))
+
+(defun faw-doc-decl-decl-int-code (x)
+ (:documentation "something")
+ (declare (pure t))
+ (declare (indent 1))
+ (interactive "P")
+ (print x))
+
+(defun faw-str-decl-int-decl-code (x)
+ "something"
+ (declare (pure t))
+ (interactive "P")
+ (declare (indent 1))
+ (print x))
+
+(defun faw-doc-decl-int-decl-code (x)
+ (:documentation "something")
+ (declare (pure t))
+ (interactive "P")
+ (declare (indent 1))
+ (print x))
+
+(defun faw-str-decl-int-int-code (x)
+ "something"
+ (declare (pure t))
+ (interactive "P")
+ (interactive "p")
+ (print x))
+
+(defun faw-doc-decl-int-int-code (x)
+ (:documentation "something")
+ (declare (pure t))
+ (interactive "P")
+ (interactive "p")
+ (print x))
+
+(defun faw-str-int-decl-int-code (x)
+ "something"
+ (interactive "P")
+ (declare (pure t))
+ (interactive "p")
+ (print x))
+
+(defun faw-doc-int-decl-int-code (x)
+ (:documentation "something")
+ (interactive "P")
+ (declare (pure t))
+ (interactive "p")
+ (print x))
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/no-byte-compile.el b/test/lisp/emacs-lisp/bytecomp-resources/no-byte-compile.el
new file mode 100644
index 00000000000..00ad1947507
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/no-byte-compile.el
@@ -0,0 +1 @@
+;; -*- no-byte-compile: t; -*-
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/nowarn-inline-after-defvar.el b/test/lisp/emacs-lisp/bytecomp-resources/nowarn-inline-after-defvar.el
new file mode 100644
index 00000000000..5582b2ab0ea
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/nowarn-inline-after-defvar.el
@@ -0,0 +1,17 @@
+;; -*- lexical-binding: t; -*-
+
+;; In this test, we try and make sure that inlined functions's code isn't
+;; mistakenly re-interpreted in the caller's context: we import an
+;; inlinable function from another file where `foo-var' is a normal
+;; lexical variable, and then call(inline) it in a function where
+;; `foo-var' is a dynamically-scoped variable.
+
+(require 'foo-inlinable
+ (expand-file-name "foo-inlinable.el"
+ (file-name-directory
+ (or byte-compile-current-file load-file-name))))
+
+(defvar foo-var)
+
+(defun foo-fun ()
+ (+ (foo-inlineable 5) 1))
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-autoload-not-on-top-level.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-autoload-not-on-top-level.el
new file mode 100644
index 00000000000..f193130c6ca
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-autoload-not-on-top-level.el
@@ -0,0 +1,3 @@
+;;; -*- lexical-binding: t -*-
+(defun foo ()
+ (autoload 'bar "baz" nil nil 'macro))
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-callargs-defsubst.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-callargs-defsubst.el
new file mode 100644
index 00000000000..3a29128cf3a
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-callargs-defsubst.el
@@ -0,0 +1,5 @@
+;;; -*- lexical-binding: t -*-
+(defsubst warn-callargs-defsubst-f1 (_x)
+ nil)
+(defun warn-callargs-defsubst-f2 ()
+ (warn-callargs-defsubst-f1 1 2))
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-callargs.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-callargs.el
new file mode 100644
index 00000000000..687add380b9
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-callargs.el
@@ -0,0 +1,5 @@
+;;; -*- lexical-binding: t -*-
+(defun foo (_x)
+ nil)
+(defun bar ()
+ (foo 1 2))
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-defcustom-nogroup.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-defcustom-nogroup.el
new file mode 100644
index 00000000000..a67d4f041f3
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-defcustom-nogroup.el
@@ -0,0 +1,3 @@
+;;; -*- lexical-binding: t -*-
+(defcustom foo nil
+ :type 'boolean)
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-defcustom-notype.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-defcustom-notype.el
new file mode 100644
index 00000000000..c15ab9b192a
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-defcustom-notype.el
@@ -0,0 +1,3 @@
+;;; -*- lexical-binding: t -*-
+(defcustom foo nil
+ :group 'emacs)
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-defvar-lacks-prefix.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-defvar-lacks-prefix.el
new file mode 100644
index 00000000000..9f3cbb98900
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-defvar-lacks-prefix.el
@@ -0,0 +1,2 @@
+;;; -*- lexical-binding: t -*-
+(defvar foo nil)
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-format.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-format.el
new file mode 100644
index 00000000000..a1902bc03b0
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-format.el
@@ -0,0 +1,2 @@
+;;; -*- lexical-binding: t -*-
+(message "%s" 1 2)
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-free-setq.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-free-setq.el
new file mode 100644
index 00000000000..6e187129c9b
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-free-setq.el
@@ -0,0 +1,2 @@
+;;; -*- lexical-binding: t -*-
+(setq foo 'bar)
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-free-variable-reference.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-free-variable-reference.el
new file mode 100644
index 00000000000..50a95272874
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-free-variable-reference.el
@@ -0,0 +1,4 @@
+;;; -*- lexical-binding: t -*-
+(defvar xxx-test)
+(defun foo ()
+ (setq xxx-test bar))
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-interactive-only.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-interactive-only.el
new file mode 100644
index 00000000000..9e0c99bd30b
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-interactive-only.el
@@ -0,0 +1,3 @@
+;;; -*- lexical-binding: t -*-
+(defun foo ()
+ (next-line))
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-lambda-malformed-interactive-spec.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-lambda-malformed-interactive-spec.el
new file mode 100644
index 00000000000..6bd902705ed
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-lambda-malformed-interactive-spec.el
@@ -0,0 +1,4 @@
+;;; -*- lexical-binding: t -*-
+(defun foo ()
+ (interactive "foo" "bar")
+ nil)
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-make-variable-buffer-local.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-make-variable-buffer-local.el
new file mode 100644
index 00000000000..aa1e6c0463b
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-make-variable-buffer-local.el
@@ -0,0 +1,4 @@
+;;; -*- lexical-binding: t -*-
+(defvar foobar)
+(defun foo ()
+ (make-variable-buffer-local 'foobar))
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-obsolete-defun.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-obsolete-defun.el
new file mode 100644
index 00000000000..2a7af617ac9
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-obsolete-defun.el
@@ -0,0 +1,8 @@
+;;; -*- lexical-binding: t -*-
+
+(defun foo-obsolete ()
+ (declare (obsolete nil "99.99"))
+ nil)
+
+(defun foo ()
+ (foo-obsolete))
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-obsolete-hook.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-obsolete-hook.el
new file mode 100644
index 00000000000..078e6e4a3a9
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-obsolete-hook.el
@@ -0,0 +1,3 @@
+;;; -*- lexical-binding: t -*-
+(defun foo ()
+ (add-hook 'bytecomp--tests-obsolete-var #'next-line))
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-obsolete-variable-bound.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-obsolete-variable-bound.el
new file mode 100644
index 00000000000..e65a541e6e3
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-obsolete-variable-bound.el
@@ -0,0 +1,7 @@
+;;; -*- lexical-binding: t -*-
+
+(make-obsolete-variable 'bytecomp--tests-obsolete-var-2 nil "99.99")
+
+(defun foo ()
+ (let ((bytecomp--tests-obsolete-var-2 2))
+ bytecomp--tests-obsolete-var-2))
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-obsolete-variable-same-file.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-obsolete-variable-same-file.el
new file mode 100644
index 00000000000..31deb6155ba
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-obsolete-variable-same-file.el
@@ -0,0 +1,13 @@
+;;; -*- lexical-binding: t -*-
+
+(defvar foo-obsolete nil)
+(make-obsolete-variable 'foo-obsolete nil "99.99")
+
+;; From bytecomp.el:
+;; If foo.el declares `toto' as obsolete, it is likely that foo.el will
+;; actually use `toto' in order for this obsolete variable to still work
+;; correctly, so paradoxically, while byte-compiling foo.el, the presence
+;; of a make-obsolete-variable call for `toto' is an indication that `toto'
+;; should not trigger obsolete-warnings in foo.el.
+(defun foo ()
+ foo-obsolete)
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-obsolete-variable.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-obsolete-variable.el
new file mode 100644
index 00000000000..9a517cc6767
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-obsolete-variable.el
@@ -0,0 +1,4 @@
+;;; -*- lexical-binding: t -*-
+
+(defun foo ()
+ bytecomp--tests-obsolete-var)
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-redefine-defun-as-macro.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-redefine-defun-as-macro.el
new file mode 100644
index 00000000000..6bd239b6598
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-redefine-defun-as-macro.el
@@ -0,0 +1,3 @@
+;;; -*- lexical-binding: t -*-
+(defun foo () nil)
+(defmacro foo () t)
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-redefine-defun.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-redefine-defun.el
new file mode 100644
index 00000000000..53e4c0ac8de
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-redefine-defun.el
@@ -0,0 +1,3 @@
+;;; -*- lexical-binding: t -*-
+(defun foo () nil)
+(defun foo () t)
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-redefine-macro-as-defun.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-redefine-macro-as-defun.el
new file mode 100644
index 00000000000..f71ae445615
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-redefine-macro-as-defun.el
@@ -0,0 +1,3 @@
+;;; -*- lexical-binding: t -*-
+(defmacro foo () t)
+(defun foo () nil)
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-save-excursion.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-save-excursion.el
new file mode 100644
index 00000000000..38185457192
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-save-excursion.el
@@ -0,0 +1,5 @@
+;;; -*- lexical-binding: t -*-
+(defun foo ()
+ (save-excursion
+ (set-buffer (current-buffer))
+ nil))
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-variable-let-bind-constant.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-variable-let-bind-constant.el
new file mode 100644
index 00000000000..cc1fb572577
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-variable-let-bind-constant.el
@@ -0,0 +1,3 @@
+;;; -*- lexical-binding: t -*-
+(defun foo ()
+ (let ((t 1)) t))
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-variable-let-bind-nonvariable.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-variable-let-bind-nonvariable.el
new file mode 100644
index 00000000000..dde2dcee6e7
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-variable-let-bind-nonvariable.el
@@ -0,0 +1,3 @@
+;;; -*- lexical-binding: t -*-
+(defun foo ()
+ (let (('t 1)) t))
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-variable-set-constant.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-variable-set-constant.el
new file mode 100644
index 00000000000..2fc0680cfab
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-variable-set-constant.el
@@ -0,0 +1,3 @@
+;;; -*- lexical-binding: t -*-
+(defun foo ()
+ (setq t nil))
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-variable-setq-nonvariable.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-variable-setq-nonvariable.el
new file mode 100644
index 00000000000..5a56913cd9b
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-variable-setq-nonvariable.el
@@ -0,0 +1,3 @@
+;;; -*- lexical-binding: t -*-
+(defun foo ()
+ (setq (a) nil))
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-variable-setq-odd.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-variable-setq-odd.el
new file mode 100644
index 00000000000..9ce80de08cd
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-variable-setq-odd.el
@@ -0,0 +1,3 @@
+;;; -*- lexical-binding: t -*-
+(defun foo (a b)
+ (setq a 1 b))
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-autoload.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-autoload.el
new file mode 100644
index 00000000000..96deb1bbb0a
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-autoload.el
@@ -0,0 +1,3 @@
+;;; -*- lexical-binding: t -*-
+(autoload 'foox "foo"
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-custom-declare-variable.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-custom-declare-variable.el
new file mode 100644
index 00000000000..2a4700bfda5
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-custom-declare-variable.el
@@ -0,0 +1,4 @@
+;;; -*- lexical-binding: t -*-
+(custom-declare-variable
+ 'foo t
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-defalias.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-defalias.el
new file mode 100644
index 00000000000..a4235d22bd3
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-defalias.el
@@ -0,0 +1,3 @@
+;;; -*- lexical-binding: t -*-
+(defalias 'foo #'ignore
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-defconst.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-defconst.el
new file mode 100644
index 00000000000..946f01989a0
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-defconst.el
@@ -0,0 +1,3 @@
+;;; -*- lexical-binding: t -*-
+(defconst foo-bar nil
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-define-abbrev-table.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-define-abbrev-table.el
new file mode 100644
index 00000000000..3da9ccd48c6
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-define-abbrev-table.el
@@ -0,0 +1,3 @@
+;;; -*- lexical-binding: t -*-
+(define-abbrev-table 'foo ()
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-define-obsolete-function-alias.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-define-obsolete-function-alias.el
new file mode 100644
index 00000000000..fea841b12ec
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-define-obsolete-function-alias.el
@@ -0,0 +1,3 @@
+;;; -*- lexical-binding: t -*-
+(define-obsolete-function-alias 'foo #'ignore "99.1"
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-define-obsolete-variable-alias.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-define-obsolete-variable-alias.el
new file mode 100644
index 00000000000..2d5f201cb65
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-define-obsolete-variable-alias.el
@@ -0,0 +1,3 @@
+;;; -*- lexical-binding: t -*-
+(define-obsolete-variable-alias 'foo 'ignore "99.1"
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-defun.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-defun.el
new file mode 100644
index 00000000000..94b0e80c979
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-defun.el
@@ -0,0 +1,3 @@
+;;; -*- lexical-binding: t -*-
+(defun foo ()
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-defvar.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-defvar.el
new file mode 100644
index 00000000000..99aacd09cbd
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-defvar.el
@@ -0,0 +1,6 @@
+;;; -*- lexical-binding: t -*-
+(defvar foo-bar nil
+ "multiline
+foo
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+bar")
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-defvaralias.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-defvaralias.el
new file mode 100644
index 00000000000..52fdc17f5bf
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-defvaralias.el
@@ -0,0 +1,3 @@
+;;; -*- lexical-binding: t -*-
+(defvaralias 'foo-bar #'ignore
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-ignore-fill-column.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-ignore-fill-column.el
new file mode 100644
index 00000000000..1ff554f3704
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-ignore-fill-column.el
@@ -0,0 +1,7 @@
+;;; -*- lexical-binding: t -*-
+(defvar foo-bar nil
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
+
+;; Local Variables:
+;; fill-column: 100
+;; End:
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-ignore-function-signature.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-ignore-function-signature.el
new file mode 100644
index 00000000000..e83f516e58c
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-ignore-function-signature.el
@@ -0,0 +1,4 @@
+;;; -*- lexical-binding: t -*-
+(defun foo-bar ()
+ "This should not warn:
+(fn COMMAND &rest ARGS &key (MARGIN (rx bol (+ \" \"))) (ARGUMENT (rx \"-\" (+ (any \"-\" alnum)) (32 \"=\"))) (METAVAR (rx (32 \" \") (or (+ (any alnum \"_-\")) (seq \"[\" (+? nonl) \"]\") (seq \"<\" (+? nonl) \">\") (seq \"{\" (+? nonl) \"}\")))) (SEPARATOR (rx \", \" symbol-start)) (DESCRIPTION (rx (* nonl) (* \"\\=\\n\" (>= 9 \" \") (* nonl)))) NARROW-START NARROW-END)")
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-ignore-override.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-ignore-override.el
new file mode 100644
index 00000000000..0bcf7b1d63b
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-ignore-override.el
@@ -0,0 +1,8 @@
+;;; -*- lexical-binding: t -*-
+(defvar foo-bar nil
+ "123456789012345")
+
+;; Local Variables:
+;; byte-compile-docstring-max-column: 10
+;; fill-column: 20
+;; End:
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-ignore-substitutions.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-ignore-substitutions.el
new file mode 100644
index 00000000000..37cfe463bfe
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-ignore-substitutions.el
@@ -0,0 +1,17 @@
+;;; -*- lexical-binding: t -*-
+(defalias 'foo #'ignore
+ "None of this should be considered too wide.
+
+; this should be treated as 60 characters - no warning
+\\[quit-window]\\[quit-window]\\[quit-window]\\[quit-window]\\[quit-window]\\[quit-window]\\[quit-window]\\[quit-window]\\[quit-window]\\[quit-window]\\[quit-window]\\[quit-window]\\[quit-window]\\[quit-window]\\[quit-window]\\[quit-window]\\[quit-window]\\[quit-window]
+
+; 64 * 'x' does not warn
+\\`x'\\`x'\\`x'\\`x'\\`x'\\`x'\\`x'\\`x'\\`x'\\`x'\\`x'\\`x'\\`x'\\`x'\\`x'\\`x'\\`x'\\`x'\\`x'\\`x'\\`x'\\`x'\\`x'\\`x'\\`x'\\`x'\\`x'\\`x'\\`x'\\`x'\\`x'\\`x'\\`x'\\`x'\\`x'\\`x'\\`x'\\`x'\\`x'\\`x'\\`x'\\`x'\\`x'\\`x'\\`x'\\`x'\\`x'\\`x'\\`x'\\`x'\\`x'\\`x'\\`x'\\`x'\\`x'\\`x'\\`x'\\`x'\\`x'\\`x'\\`x'\\`x'\\`x'\\`x'
+
+; keymaps are just ignored
+\\<foo-bar-map>\\<foo-bar-map>\\<foo-bar-map>\\<foo-bar-map>\\<foo-bar-map>\\<foo-bar-map>\\<foo-bar-map>\\<foo-bar-map>\\<foo-bar-map>\\<foo-bar-map>\\<foo-bar-map>\\<foo-bar-map>\\<foo-bar-map>\\<foo-bar-map>\\<foo-bar-map>\\<foo-bar-map>\\<foo-bar-map>\\<foo-bar-map>\\<foo-bar-map>\\<foo-bar-map>\\<foo-bar-map>\\<foo-bar-map>\\<foo-bar-map>\\<foo-bar-map>\\<foo-bar-map>\\<foo-bar-map>\\<foo-bar-map>\\<foo-bar-map>\\<foo-bar-map>
+
+\\{foo-bar-map}\\{foo-bar-map}\\{foo-bar-map}\\{foo-bar-map}\\{foo-bar-map}\\{foo-bar-map}\\{foo-bar-map}\\{foo-bar-map}\\{foo-bar-map}\\{foo-bar-map}\\{foo-bar-map}\\{foo-bar-map}\\{foo-bar-map}\\{foo-bar-map}\\{foo-bar-map}\\{foo-bar-map}\\{foo-bar-map}\\{foo-bar-map}\\{foo-bar-map}\\{foo-bar-map}\\{foo-bar-map}\\{foo-bar-map}\\{foo-bar-map}\\{foo-bar-map}\\{foo-bar-map}\\{foo-bar-map}\\{foo-bar-map}\\{foo-bar-map}\\{foo-bar-map}\\{foo-bar-map}\\{foo-bar-map}\\{foo-bar-map}\\{foo-bar-map}\\{foo-bar-map}\\{foo-bar-map}\\{foo-bar-map}
+
+bar baz foo bar baz foo bar baz foo bar baz foo bar baz foo bar
+")
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-ignore.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-ignore.el
new file mode 100644
index 00000000000..c80ddd180d9
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-ignore.el
@@ -0,0 +1,7 @@
+;;; -*- lexical-binding: t -*-
+(defvar foo-bar nil
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
+
+;; Local Variables:
+;; byte-compile-docstring-max-column: 100
+;; End:
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-multiline-first.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-multiline-first.el
new file mode 100644
index 00000000000..2563dbbb3b9
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-multiline-first.el
@@ -0,0 +1,5 @@
+;;; -*- lexical-binding: t -*-
+(defvar foo-bar nil
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+This is a multiline docstring where the first line is long.
+foobar")
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-multiline.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-multiline.el
new file mode 100644
index 00000000000..9ae7bc9b9f0
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-multiline.el
@@ -0,0 +1,6 @@
+;;; -*- lexical-binding: t -*-
+(defvar foo-bar nil
+ "This is a multiline docstring.
+But it's not the first line that is long.
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+foobar")
diff --git a/test/lisp/emacs-lisp/bytecomp-tests.el b/test/lisp/emacs-lisp/bytecomp-tests.el
index 30d2a4753cf..e7c308213e4 100644
--- a/test/lisp/emacs-lisp/bytecomp-tests.el
+++ b/test/lisp/emacs-lisp/bytecomp-tests.el
@@ -1,6 +1,6 @@
-;;; bytecomp-tests.el
+;;; bytecomp-tests.el --- Tests for bytecomp.el -*- lexical-binding:t -*-
-;; Copyright (C) 2008-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2022 Free Software Foundation, Inc.
;; Author: Shigeru Fukaya <shigeru.fukaya@gmail.com>
;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
@@ -26,10 +26,42 @@
;;; Commentary:
(require 'ert)
+(require 'ert-x)
(require 'cl-lib)
+(require 'subr-x)
+(require 'bytecomp)
;;; Code:
-(defconst byte-opt-testsuite-arith-data
+(defvar bytecomp-test-var nil)
+
+(defun bytecomp-test-get-var ()
+ bytecomp-test-var)
+
+(defun bytecomp-test-identity (x)
+ "Identity, but hidden from some optimizations."
+ x)
+
+(defmacro bytecomp-test-loop (outer1 outer2 inner1 inner2)
+ "Exercise constant propagation inside `while' loops.
+OUTER1, OUTER2, INNER1 and INNER2 are forms placed in the outer and
+inner loops respectively."
+ `(let ((x 1) (i 3) (res nil))
+ (while (> i 0)
+ (let ((y 2) (j 2))
+ (setq res (cons (list 'outer x y) res))
+ (while (> j 0)
+ (setq res (cons (list 'inner x y) res))
+ ,inner1
+ ,inner2
+ (setq j (1- j)))
+ ,outer1
+ ,outer2)
+ (setq i (1- i)))
+ res))
+
+(defvar bytecomp-tests--xx nil)
+
+(defconst bytecomp-tests--test-cases
'(
;; some functional tests
(let ((a most-positive-fixnum) (b 1) (c 1.0)) (+ a b c))
@@ -38,14 +70,18 @@
(let ((a 3) (b 2) (c 1.0)) (/ a b c))
(let ((a (+ 1 (expt 2 -64))) (b (expt 2 -65))) (+ a -1 b))
(let ((a (+ 1 (expt 2 -64))) (b (expt 2 -65))) (- a 1 (- b)))
- ;; This fails. Should it be a bug?
- ;; (let ((a (expt 2 -1074)) (b 0.125)) (* a 8 b))
+ (let ((a (expt 2 -1074)) (b 0.125)) (* a 8 b))
(let ((a 1.0)) (* a 0))
(let ((a 1.0)) (* a 2.0 0))
(let ((a 1.0)) (/ 0 a))
(let ((a 1.0)) (/ 3 a 2))
(let ((a most-positive-fixnum) (b 2.0)) (* a 2 b))
(let ((a 3) (b 2)) (/ a b 1.0))
+ (let ((a -0.0)) (+ a))
+ (let ((a -0.0)) (- a))
+ (let ((a -0.0)) (* a))
+ (let ((a -0.0)) (min a))
+ (let ((a -0.0)) (max a))
(/ 3 -1)
(+ 4 3 2 1)
(+ 4 3 2.0 1)
@@ -244,6 +280,9 @@
(let ((a 3) (b 2) (c 1.0)) (/ a b c 0))
(let ((a 3) (b 2) (c 1.0)) (/ a b c 1))
(let ((a 3) (b 2) (c 1.0)) (/ a b c -1))
+
+ (let ((a t)) (logand 0 a))
+
;; Test switch bytecode
(let ((a 3)) (cond ((eq a 1) 'one) ((eq a 2) 'two) ((eq a 3) 'three) (t t)))
(let ((a 'three)) (cond ((eq a 'one) 1) ((eq a 2) 'two) ((eq a 'three) 3)
@@ -286,90 +325,449 @@
(t)))
(let ((a))
(cond ((eq a 'foo) 'incorrect)
- ('correct))))
- "List of expression for test.
-Each element will be executed by interpreter and with
-bytecompiled code, and their results compared.")
+ ('correct)))
+ ;; Bug#31734
+ (let ((variable 0))
+ (cond
+ ((eq variable 'default)
+ (message "equal"))
+ (t
+ (message "not equal"))))
+ ;; Bug#35770
+ (let ((x 'a)) (cond ((eq x 'a) 'correct)
+ ((eq x 'b) 'incorrect)
+ ((eq x 'a) 'incorrect)
+ ((eq x 'c) 'incorrect)))
+ (let ((x #x10000000000000000))
+ (cond ((eql x #x10000000000000000) 'correct)
+ ((eql x #x10000000000000001) 'incorrect)
+ ((eql x #x10000000000000000) 'incorrect)
+ ((eql x #x10000000000000002) 'incorrect)))
+ (let ((x "a")) (cond ((equal x "a") 'correct)
+ ((equal x "b") 'incorrect)
+ ((equal x "a") 'incorrect)
+ ((equal x "c") 'incorrect)))
+ ;; Multi-value clauses
+ (mapcar (lambda (x) (cond ((eq x 'a) 11)
+ ((memq x '(b a c d)) 22)
+ ((eq x 'c) 33)
+ ((eq x 'e) 44)
+ ((memq x '(d f g)) 55)
+ (t 99)))
+ '(a b c d e f g h))
+ (mapcar (lambda (x) (cond ((eql x 1) 11)
+ ((memq x '(a b c)) 22)
+ ((memql x '(2 1 4 1e-3)) 33)
+ ((eq x 'd) 44)
+ ((eql x #x10000000000000000))))
+ '(1 2 4 1e-3 a b c d 1.0 #x10000000000000000))
+ (mapcar (lambda (x) (cond ((eq x 'a) 11)
+ ((memq x '(b d)) 22)
+ ((equal x '(a . b)) 33)
+ ((member x '(b c 1.5 2.5 "X" (d))) 44)
+ ((eql x 3.14) 55)
+ ((memql x '(9 0.5 1.5 q)) 66)
+ (t 99)))
+ '(a b c d (d) (a . b) "X" 0.5 1.5 3.14 9 9.0))
+ ;; Multi-switch cond form
+ (mapcar (lambda (p) (let ((x (car p)) (y (cadr p)))
+ (cond ((consp x) 11)
+ ((eq x 'a) 22)
+ ((memql x '(b 7 a -3)) 33)
+ ((equal y "a") 44)
+ ((memq y '(c d e)) 55)
+ ((booleanp x) 66)
+ ((eq x 'q) 77)
+ ((memq x '(r s)) 88)
+ ((eq x 't) 99)
+ (t 999))))
+ '((a c) (b c) (7 c) (-3 c) (nil nil) (t c) (q c) (r c) (s c)
+ (t c) (x "a") (x "c") (x c) (x d) (x e)))
-(defun bytecomp-check-1 (pat)
- "Return non-nil if PAT is the same whether directly evalled or compiled."
- (let ((warning-minimum-log-level :emergency)
- (byte-compile-warnings nil)
- (v0 (condition-case nil
- (eval pat)
- (error nil)))
- (v1 (condition-case nil
- (funcall (byte-compile (list 'lambda nil pat)))
- (error nil))))
- (equal v0 v1)))
-
-(put 'bytecomp-check-1 'ert-explainer 'bytecomp-explain-1)
-
-(defun bytecomp-explain-1 (pat)
- (let ((v0 (condition-case nil
- (eval pat)
- (error nil)))
- (v1 (condition-case nil
- (funcall (byte-compile (list 'lambda nil pat)))
- (error nil))))
- (format "Expression `%s' gives `%s' if directly evalled, `%s' if compiled."
- pat v0 v1)))
-
-(ert-deftest bytecomp-tests ()
- "Test the Emacs byte compiler."
- (dolist (pat byte-opt-testsuite-arith-data)
- (should (bytecomp-check-1 pat))))
-
-(defun test-byte-opt-arithmetic (&optional arg)
- "Unit test for byte-opt arithmetic operations.
-Subtests signal errors if something goes wrong."
- (interactive "P")
- (switch-to-buffer (generate-new-buffer "*Font Pase Test*"))
+ (mapcar (lambda (x) (ignore-errors (cond ((member '(a . b) x) 1)
+ ((equal x '(c)) 2))))
+ '(((a . b)) a b (c) (d)))
+ (mapcar (lambda (x) (ignore-errors (cond ((memq '(a . b) x) 1)
+ ((equal x '(c)) 2))))
+ '(((a . b)) a b (c) (d)))
+ (mapcar (lambda (x) (ignore-errors (cond ((member '(a b) x) 1)
+ ((equal x '(c)) 2))))
+ '(((a b)) a b (c) (d)))
+ (mapcar (lambda (x) (ignore-errors (cond ((memq '(a b) x) 1)
+ ((equal x '(c)) 2))))
+ '(((a b)) a b (c) (d)))
+
+ (assoc 'b '((a 1) (b 2) (c 3)))
+ (assoc "b" '(("a" 1) ("b" 2) ("c" 3)))
+ (let ((x '((a 1) (b 2) (c 3)))) (assoc 'c x))
+ (assoc 'a '((a 1) (b 2) (c 3)) (lambda (u v) (not (equal u v))))
+
+ ;; Constprop test cases
+ (let ((a 'alpha) (b (concat "be" "ta")) (c nil) (d t) (e :gamma)
+ (f '(delta epsilon)))
+ (list a b c d e f))
+
+ (let ((x 1) (y (+ 3 4)))
+ (list
+ (let (q (y x) (z y))
+ (if q x (list x y z)))))
+
+ (let* ((x 3) (y (* x 2)) (x (1+ y)))
+ x)
+
+ (let ((x 1) (bytecomp-test-var 2) (y 3))
+ (list x bytecomp-test-var (bytecomp-test-get-var) y))
+
+ (progn
+ (defvar d)
+ (let ((x 'a) (y 'b)) (list x y)))
+
+ (let ((x 2))
+ (list x (setq x 13) (setq x (* x 2)) x))
+
+ (let ((x 'a) (y 'b))
+ (setq y x
+ x (cons 'c y)
+ y x)
+ (list x y))
+
+ (let ((x 3))
+ (let ((y x) z)
+ (setq x 5)
+ (setq y (+ y 8))
+ (setq z (if (bytecomp-test-identity t)
+ (progn
+ (setq x (+ x 1))
+ (list x y))
+ (setq x (+ x 2))
+ (list x y)))
+ (list x y z)))
+
+ (let ((i 1) (s 0) (x 13))
+ (while (< i 5)
+ (setq s (+ s i))
+ (setq i (1+ i)))
+ (list s x i))
+
+ (let ((x 2))
+ (list (or (bytecomp-test-identity 'a) (setq x 3)) x))
+
+ (mapcar (lambda (b)
+ (let ((a nil))
+ (+ 0
+ (progn
+ (setq a b)
+ (setq b 1)
+ a))))
+ '(10))
+
+ (let* ((x 1)
+ (y (condition-case x
+ (/ 1 0)
+ (arith-error x))))
+ (list x y))
+
+ (funcall
+ (condition-case x
+ (/ 1 0)
+ (arith-error (prog1 (lambda (y) (+ y x))
+ (setq x 10))))
+ 4)
+
+ ;; Loop constprop: set the inner and outer variables in the inner
+ ;; and outer loops, all combinations.
+ (bytecomp-test-loop nil nil nil nil )
+ (bytecomp-test-loop nil nil nil (setq x 6))
+ (bytecomp-test-loop nil nil (setq x 5) nil )
+ (bytecomp-test-loop nil nil (setq x 5) (setq x 6))
+ (bytecomp-test-loop nil (setq x 4) nil nil )
+ (bytecomp-test-loop nil (setq x 4) nil (setq x 6))
+ (bytecomp-test-loop nil (setq x 4) (setq x 5) nil )
+ (bytecomp-test-loop nil (setq x 4) (setq x 5) (setq x 6))
+ (bytecomp-test-loop (setq x 3) nil nil nil )
+ (bytecomp-test-loop (setq x 3) nil nil (setq x 6))
+ (bytecomp-test-loop (setq x 3) nil (setq x 5) nil )
+ (bytecomp-test-loop (setq x 3) nil (setq x 5) (setq x 6))
+ (bytecomp-test-loop (setq x 3) (setq x 4) nil nil )
+ (bytecomp-test-loop (setq x 3) (setq x 4) nil (setq x 6))
+ (bytecomp-test-loop (setq x 3) (setq x 4) (setq x 5) nil )
+ (bytecomp-test-loop (setq x 3) (setq x 4) (setq x 5) (setq x 6))
+
+ ;; No error, no success handler.
+ (condition-case x
+ (list 42)
+ (error (cons 'bad x)))
+ ;; Error, no success handler.
+ (condition-case x
+ (/ 1 0)
+ (error (cons 'bad x)))
+ ;; No error, success handler.
+ (condition-case x
+ (list 42)
+ (error (cons 'bad x))
+ (:success (cons 'good x)))
+ ;; Error, success handler.
+ (condition-case x
+ (/ 1 0)
+ (error (cons 'bad x))
+ (:success (cons 'good x)))
+ ;; Verify that the success code is not subject to the error handlers.
+ (condition-case x
+ (list 42)
+ (error (cons 'bad x))
+ (:success (/ (car x) 0)))
+ ;; Check variable scoping on success.
+ (let ((x 2))
+ (condition-case x
+ (list x)
+ (error (list 'bad x))
+ (:success (list 'good x))))
+ ;; Check variable scoping on failure.
+ (let ((x 2))
+ (condition-case x
+ (/ 1 0)
+ (error (list 'bad x))
+ (:success (list 'good x))))
+ ;; Check capture of mutated result variable.
+ (funcall
+ (condition-case x
+ 3
+ (:success (prog1 (lambda (y) (+ y x))
+ (setq x 10))))
+ 4)
+ ;; Check for-effect context, on error.
+ (let ((f (lambda (x)
+ (condition-case nil
+ (/ 1 0)
+ (error 'bad)
+ (:success 'good))
+ (1+ x))))
+ (funcall f 3))
+ ;; Check for-effect context, on success.
+ (let ((f (lambda (x)
+ (condition-case nil
+ nil
+ (error 'bad)
+ (:success 'good))
+ (1+ x))))
+ (funcall f 3))
+
+ ;; Check `not' in cond switch (bug#49746).
+ (mapcar (lambda (x) (cond ((equal x "a") 1)
+ ((member x '("b" "c")) 2)
+ ((not x) 3)))
+ '("a" "b" "c" "d" nil))
+
+ ;; `let' and `let*' optimizations with body being constant or variable
+ (let* (a
+ (b (progn (setq a (cons 1 a)) 2))
+ (c (1+ b))
+ (d (list a c)))
+ d)
+ (let ((a nil))
+ (let ((b (progn (setq a (cons 1 a)) 2))
+ (c (progn (setq a (cons 3 a))))
+ (d (list a)))
+ d))
+ (let* ((_a 1)
+ (_b 2))
+ 'z)
+ (let ((_a 1)
+ (_b 2))
+ 'z)
+ (let (x y)
+ y)
+ (let* (x y)
+ y)
+ (let (x y)
+ 'a)
+ (let* (x y)
+ 'a)
+
+ ;; Check empty-list optimizations.
+ (mapcar (lambda (x) (member x nil)) '("a" 2 nil))
+ (mapcar (lambda (x) (memql x nil)) '(a 2 nil))
+ (mapcar (lambda (x) (memq x nil)) '(a nil))
+ (let ((n 0))
+ (list (mapcar (lambda (x) (member (setq n (1+ n)) nil)) '(a "nil"))
+ n))
+ (mapcar (lambda (x) (assoc x nil)) '("a" nil))
+ (mapcar (lambda (x) (assq x nil)) '(a nil))
+ (mapcar (lambda (x) (rassoc x nil)) '("a" nil))
+ (mapcar (lambda (x) (rassq x nil)) '(a nil))
+ (let ((n 0))
+ (list (mapcar (lambda (x) (assoc (setq n (1+ n)) nil)) '(a "nil"))
+ n))
+
+ ;; Exercise variable-aliasing optimizations.
+ (let ((a (list 1)))
+ (let ((b a))
+ (let ((a (list 2)))
+ (list a b))))
+
+ (let ((a (list 1)))
+ (let ((a (list 2))
+ (b a))
+ (list a b)))
+
+ (let* ((a (list 1))
+ (b a)
+ (a (list 2)))
+ (condition-case a
+ (list a b)
+ (error (list 'error a b))))
+
+ (let* ((a (list 1))
+ (b a)
+ (a (list 2)))
+ (condition-case a
+ (/ 0)
+ (error (list 'error a b))))
+
+ (let* ((a (list 1))
+ (b a)
+ (a (list 2))
+ (f (list (lambda (x) (list x a)))))
+ (funcall (car f) 3))
+
+ (let* ((a (list 1))
+ (b a)
+ (f (list (lambda (x) (setq a x)))))
+ (funcall (car f) 3)
+ (list a b))
+
+ (let* ((a (list 1))
+ (b a)
+ (a (list 2))
+ (f (list (lambda (x) (setq a x)))))
+ (funcall (car f) 3)
+ (list a b))
+
+ (cond)
+ (mapcar (lambda (x) (cond ((= x 0)))) '(0 1))
+
+ ;; These expressions give different results in lexbind and dynbind modes,
+ ;; but in each the compiler and interpreter should agree!
+ ;; (They look much the same but come in pairs exercising both the
+ ;; `let' and `let*' paths.)
+ (let ((f (lambda (x)
+ (lambda ()
+ (let ((g (lambda () x)))
+ (let ((x 'a))
+ (list x (funcall g))))))))
+ (funcall (funcall f 'b)))
+ (let ((f (lambda (x)
+ (lambda ()
+ (let ((g (lambda () x)))
+ (let* ((x 'a))
+ (list x (funcall g))))))))
+ (funcall (funcall f 'b)))
+ (let ((f (lambda (x)
+ (lambda ()
+ (let ((g (lambda () x)))
+ (setq x (list x x))
+ (let ((x 'a))
+ (list x (funcall g))))))))
+ (funcall (funcall f 'b)))
+ (let ((f (lambda (x)
+ (lambda ()
+ (let ((g (lambda () x)))
+ (setq x (list x x))
+ (let* ((x 'a))
+ (list x (funcall g))))))))
+ (funcall (funcall f 'b)))
+ (let ((f (lambda (x)
+ (let ((g (lambda () x))
+ (h (lambda () (setq x (list x x)))))
+ (let ((x 'a))
+ (list x (funcall g) (funcall h)))))))
+ (funcall (funcall f 'b)))
+ (let ((f (lambda (x)
+ (let ((g (lambda () x))
+ (h (lambda () (setq x (list x x)))))
+ (let* ((x 'a))
+ (list x (funcall g) (funcall h)))))))
+ (funcall (funcall f 'b)))
+
+ ;; Test constant-propagation of access to captured variables.
+ (let* ((x 2)
+ (f (lambda ()
+ (let ((y x)) (list y 3 y)))))
+ (funcall f))
+
+ ;; Test rewriting of `set' to `setq' (only done on dynamic variables).
+ (let ((xx 1)) (set 'xx 2) xx)
+ (let ((bytecomp-tests--xx 1))
+ (set 'bytecomp-tests--xx 2)
+ bytecomp-tests--xx)
+ (let ((aaa 1)) (set (make-local-variable 'aaa) 2) aaa)
+ (let ((bytecomp-tests--xx 1))
+ (set (make-local-variable 'bytecomp-tests--xx) 2)
+ bytecomp-tests--xx)
+ )
+ "List of expressions for cross-testing interpreted and compiled code.")
+
+(defconst bytecomp-tests--test-cases-lexbind-only
+ `(
+ ;; This would infloop (and exhaust stack) with dynamic binding.
+ (let ((f #'car))
+ (let ((f (lambda (x) (cons (funcall f x) (cdr x)))))
+ (funcall f '(1 . 2))))
+ )
+ "List of expressions for cross-testing interpreted and compiled code.
+These are only tested with lexical binding.")
+
+(defun bytecomp-tests--eval-interpreted (form)
+ "Evaluate FORM using the Lisp interpreter, returning errors as a
+special value."
+ (condition-case err
+ (eval form lexical-binding)
+ (error (list 'bytecomp-check-error (car err)))))
+
+(defun bytecomp-tests--eval-compiled (form)
+ "Evaluate FORM using the Lisp byte-code compiler, returning errors as a
+special value."
(let ((warning-minimum-log-level :emergency)
- (byte-compile-warnings nil)
- (pass-face '((t :foreground "green")))
- (fail-face '((t :foreground "red")))
- (print-escape-nonascii t)
- (print-escape-newlines t)
- (print-quoted t)
- v0 v1)
- (dolist (pat byte-opt-testsuite-arith-data)
- (condition-case nil
- (setq v0 (eval pat))
- (error (setq v0 nil)))
- (condition-case nil
- (setq v1 (funcall (byte-compile (list 'lambda nil pat))))
- (error (setq v1 nil)))
- (insert (format "%s" pat))
- (indent-to-column 65)
- (if (equal v0 v1)
- (insert (propertize "OK" 'face pass-face))
- (insert (propertize "FAIL\n" 'face fail-face))
- (indent-to-column 55)
- (insert (propertize (format "[%s] vs [%s]" v0 v1)
- 'face fail-face)))
- (insert "\n"))))
+ (byte-compile-warnings nil))
+ (condition-case err
+ (funcall (byte-compile (list 'lambda nil form)))
+ (error (list 'bytecomp-check-error (car err))))))
+
+(ert-deftest bytecomp-tests-lexbind ()
+ "Check that various expressions behave the same when interpreted and
+byte-compiled. Run with lexical binding."
+ (let ((lexical-binding t))
+ (dolist (form (append bytecomp-tests--test-cases-lexbind-only
+ bytecomp-tests--test-cases))
+ (ert-info ((prin1-to-string form) :prefix "form: ")
+ (should (equal (bytecomp-tests--eval-interpreted form)
+ (bytecomp-tests--eval-compiled form)))))))
+
+(ert-deftest bytecomp-tests-dynbind ()
+ "Check that various expressions behave the same when interpreted and
+byte-compiled. Run with dynamic binding."
+ (let ((lexical-binding nil))
+ (dolist (form bytecomp-tests--test-cases)
+ (ert-info ((prin1-to-string form) :prefix "form: ")
+ (should (equal (bytecomp-tests--eval-interpreted form)
+ (bytecomp-tests--eval-compiled form)))))))
(defun test-byte-comp-compile-and-load (compile &rest forms)
- (let ((elfile nil)
- (elcfile nil))
- (unwind-protect
- (progn
- (setf elfile (make-temp-file "test-bytecomp" nil ".el"))
- (when compile
- (setf elcfile (make-temp-file "test-bytecomp" nil ".elc")))
- (with-temp-buffer
- (dolist (form forms)
- (print form (current-buffer)))
- (write-region (point-min) (point-max) elfile nil 'silent))
- (if compile
- (let ((byte-compile-dest-file-function
- (lambda (e) elcfile)))
- (byte-compile-file elfile t))
- (load elfile nil 'nomessage)))
- (when elfile (delete-file elfile))
- (when elcfile (delete-file elcfile)))))
-(put 'test-byte-comp-compile-and-load 'lisp-indent-function 1)
+ (declare (indent 1))
+ (ert-with-temp-file elfile
+ :suffix ".el"
+ (ert-with-temp-file elcfile
+ :suffix ".elc"
+ (with-temp-buffer
+ (insert ";;; -*- lexical-binding: t -*-\n")
+ (dolist (form forms)
+ (print form (current-buffer)))
+ (write-region (point-min) (point-max) elfile nil 'silent))
+ (if compile
+ (let ((byte-compile-dest-file-function
+ (lambda (e) elcfile)))
+ (byte-compile-file elfile)))
+ (load elfile nil 'nomessage))))
(ert-deftest test-byte-comp-macro-expansion ()
(test-byte-comp-compile-and-load t
@@ -405,9 +803,13 @@ Subtests signal errors if something goes wrong."
(defun def () (m))))
(should (equal (funcall 'def) 4)))
+
+;;;; Warnings.
+
(ert-deftest bytecomp-tests--warnings ()
(with-current-buffer (get-buffer-create "*Compile-Log*")
(let ((inhibit-read-only t)) (erase-buffer)))
+ (mapc #'fmakunbound '(my-test0 my--test11 my--test12 my--test2))
(test-byte-comp-compile-and-load t
'(progn
(defun my-test0 ()
@@ -431,6 +833,219 @@ Subtests signal errors if something goes wrong."
;; Should not warn that mt--test2 is not known to be defined.
(should-not (re-search-forward "my--test2" nil t))))
+(defmacro bytecomp--with-warning-test (re-warning &rest form)
+ (declare (indent 1))
+ `(with-current-buffer (get-buffer-create "*Compile-Log*")
+ (let ((inhibit-read-only t)) (erase-buffer))
+ (byte-compile ,@form)
+ (ert-info ((prin1-to-string (buffer-string)) :prefix "buffer: ")
+ (should (re-search-forward ,(string-replace " " "[ \n]+" re-warning))))))
+
+(ert-deftest bytecomp-warn-wrong-args ()
+ (bytecomp--with-warning-test "remq.*3.*2"
+ '(remq 1 2 3)))
+
+(ert-deftest bytecomp-warn-wrong-args-subr ()
+ (bytecomp--with-warning-test "safe-length.*3.*1"
+ '(safe-length 1 2 3)))
+
+(ert-deftest bytecomp-warn-variable-lacks-prefix ()
+ (bytecomp--with-warning-test "foo.*lacks a prefix"
+ '(defvar foo nil)))
+
+(defvar bytecomp-tests--docstring (make-string 100 ?x))
+
+(ert-deftest bytecomp-warn-wide-docstring/defconst ()
+ (bytecomp--with-warning-test "defconst.*foo.*wider than.*characters"
+ `(defconst foo t ,bytecomp-tests--docstring)))
+
+(ert-deftest bytecomp-warn-wide-docstring/defvar ()
+ (bytecomp--with-warning-test "defvar.*foo.*wider than.*characters"
+ `(defvar foo t ,bytecomp-tests--docstring)))
+
+(defmacro bytecomp--define-warning-file-test (file re-warning &optional reverse)
+ `(ert-deftest ,(intern (format "bytecomp/%s" file)) ()
+ (with-current-buffer (get-buffer-create "*Compile-Log*")
+ (let ((inhibit-read-only t)) (erase-buffer))
+ (byte-compile-file ,(ert-resource-file file))
+ (ert-info ((buffer-string) :prefix "buffer: ")
+ (,(if reverse 'should-not 'should)
+ (re-search-forward ,re-warning nil t))))))
+
+(bytecomp--define-warning-file-test "error-lexical-var-with-add-hook.el"
+ "add-hook.*lexical var")
+
+(bytecomp--define-warning-file-test "error-lexical-var-with-remove-hook.el"
+ "remove-hook.*lexical var")
+
+(bytecomp--define-warning-file-test "error-lexical-var-with-run-hook-with-args-until-failure.el"
+ "args-until-failure.*lexical var")
+
+(bytecomp--define-warning-file-test "error-lexical-var-with-run-hook-with-args-until-success.el"
+ "args-until-success.*lexical var")
+
+(bytecomp--define-warning-file-test "error-lexical-var-with-run-hook-with-args.el"
+ "args.*lexical var")
+
+(bytecomp--define-warning-file-test "error-lexical-var-with-symbol-value.el"
+ "symbol-value.*lexical var")
+
+(bytecomp--define-warning-file-test "warn-autoload-not-on-top-level.el"
+ "compiler ignores.*autoload.*")
+
+(bytecomp--define-warning-file-test "warn-callargs.el"
+ "with 2 arguments, but accepts only 1")
+
+(bytecomp--define-warning-file-test "warn-callargs-defsubst.el"
+ "with 2 arguments, but accepts only 1")
+
+(bytecomp--define-warning-file-test "warn-defcustom-nogroup.el"
+ "fails to specify containing group")
+
+(bytecomp--define-warning-file-test "warn-defcustom-notype.el"
+ "fails to specify type")
+
+(bytecomp--define-warning-file-test "warn-defvar-lacks-prefix.el"
+ "var.*foo.*lacks a prefix")
+
+(bytecomp--define-warning-file-test "warn-format.el"
+ "called with 2 args to fill 1 format field")
+
+(bytecomp--define-warning-file-test "warn-free-setq.el"
+ "free.*foo")
+
+(bytecomp--define-warning-file-test "warn-free-variable-reference.el"
+ "free variable .bar")
+
+(bytecomp--define-warning-file-test "warn-make-variable-buffer-local.el"
+ "make-variable-buffer-local. not called at toplevel")
+
+(bytecomp--define-warning-file-test "warn-interactive-only.el"
+ "next-line.*interactive use only.*forward-line")
+
+(bytecomp--define-warning-file-test "warn-lambda-malformed-interactive-spec.el"
+ "malformed .interactive. specification")
+
+(bytecomp--define-warning-file-test "warn-obsolete-defun.el"
+ "foo-obsolete. is an obsolete function (as of 99.99)")
+
+(defvar bytecomp--tests-obsolete-var nil)
+(make-obsolete-variable 'bytecomp--tests-obsolete-var nil "99.99")
+
+(bytecomp--define-warning-file-test "warn-obsolete-hook.el"
+ "bytecomp--tests-obsolete-var. is an obsolete variable (as of 99.99)")
+
+(bytecomp--define-warning-file-test "warn-obsolete-variable-same-file.el"
+ "foo-obs.*obsolete.*99.99" t)
+
+(bytecomp--define-warning-file-test "warn-obsolete-variable.el"
+ "bytecomp--tests-obsolete-var. is an obsolete variable (as of 99.99)")
+
+(bytecomp--define-warning-file-test "warn-obsolete-variable-bound.el"
+ "bytecomp--tests-obs.*obsolete.*99.99" t)
+
+(bytecomp--define-warning-file-test "warn-redefine-defun-as-macro.el"
+ "as both function and macro")
+
+(bytecomp--define-warning-file-test "warn-redefine-macro-as-defun.el"
+ "as both function and macro")
+
+(bytecomp--define-warning-file-test "warn-redefine-defun.el"
+ "defined multiple")
+
+(bytecomp--define-warning-file-test "warn-save-excursion.el"
+ "with-current.*rather than save-excursion")
+
+(bytecomp--define-warning-file-test "warn-variable-let-bind-constant.el"
+ "let-bind constant")
+
+(bytecomp--define-warning-file-test "warn-variable-let-bind-nonvariable.el"
+ "let-bind nonvariable")
+
+(bytecomp--define-warning-file-test "warn-variable-set-constant.el"
+ "attempt to set constant")
+
+(bytecomp--define-warning-file-test "warn-variable-setq-nonvariable.el"
+ "attempt to set non-variable")
+
+(bytecomp--define-warning-file-test "warn-variable-setq-odd.el"
+ "odd number of arguments")
+
+(bytecomp--define-warning-file-test
+ "warn-wide-docstring-autoload.el"
+ "autoload .foox. docstring wider than .* characters")
+
+(bytecomp--define-warning-file-test
+ "warn-wide-docstring-custom-declare-variable.el"
+ "custom-declare-variable .foo. docstring wider than .* characters")
+
+(bytecomp--define-warning-file-test
+ "warn-wide-docstring-defalias.el"
+ "defalias .foo. docstring wider than .* characters")
+
+(bytecomp--define-warning-file-test
+ "warn-wide-docstring-defconst.el"
+ "defconst .foo-bar. docstring wider than .* characters")
+
+(bytecomp--define-warning-file-test
+ "warn-wide-docstring-define-abbrev-table.el"
+ "define-abbrev-table .foo. docstring wider than .* characters")
+
+(bytecomp--define-warning-file-test
+ "warn-wide-docstring-define-obsolete-function-alias.el"
+ "defalias .foo. docstring wider than .* characters")
+
+(bytecomp--define-warning-file-test
+ "warn-wide-docstring-define-obsolete-variable-alias.el"
+ "defvaralias .foo. docstring wider than .* characters")
+
+(bytecomp--define-warning-file-test
+ "warn-wide-docstring-defun.el"
+ "Warning: docstring wider than .* characters")
+
+(bytecomp--define-warning-file-test
+ "warn-wide-docstring-defvar.el"
+ "defvar .foo-bar. docstring wider than .* characters")
+
+(bytecomp--define-warning-file-test
+ "warn-wide-docstring-defvaralias.el"
+ "defvaralias .foo-bar. docstring wider than .* characters")
+
+(bytecomp--define-warning-file-test
+ "warn-wide-docstring-ignore-fill-column.el"
+ "defvar .foo-bar. docstring wider than .* characters" 'reverse)
+
+(bytecomp--define-warning-file-test
+ "warn-wide-docstring-ignore-function-signature.el"
+ "defvar .foo-bar. docstring wider than .* characters" 'reverse)
+
+(bytecomp--define-warning-file-test
+ "warn-wide-docstring-ignore-override.el"
+ "defvar .foo-bar. docstring wider than .* characters" 'reverse)
+
+(bytecomp--define-warning-file-test
+ "warn-wide-docstring-ignore-substitutions.el"
+ "defvar .foo-bar. docstring wider than .* characters" 'reverse)
+
+(bytecomp--define-warning-file-test
+ "warn-wide-docstring-ignore.el"
+ "defvar .foo-bar. docstring wider than .* characters" 'reverse)
+
+(bytecomp--define-warning-file-test
+ "warn-wide-docstring-multiline-first.el"
+ "defvar .foo-bar. docstring wider than .* characters")
+
+(bytecomp--define-warning-file-test
+ "warn-wide-docstring-multiline.el"
+ "defvar .foo-bar. docstring wider than .* characters")
+
+(bytecomp--define-warning-file-test
+ "nowarn-inline-after-defvar.el"
+ "Lexical argument shadows" 'reverse)
+
+
+;;;; Macro expansion.
+
(ert-deftest test-eager-load-macro-expansion ()
(test-byte-comp-compile-and-load nil
'(progn (defmacro abc (arg) 1) (defun def () (abc 2))))
@@ -465,54 +1080,12 @@ Subtests signal errors if something goes wrong."
(defun def () (m))))
(should (equal (funcall 'def) 4)))
-(defconst bytecomp-lexbind-tests
- `(
- (let ((f #'car))
- (let ((f (lambda (x) (cons (funcall f x) (cdr x)))))
- (funcall f '(1 . 2))))
- )
- "List of expression for test.
-Each element will be executed by interpreter and with
-bytecompiled code, and their results compared.")
-
-(defun bytecomp-lexbind-check-1 (pat)
- "Return non-nil if PAT is the same whether directly evalled or compiled."
- (let ((warning-minimum-log-level :emergency)
- (byte-compile-warnings nil)
- (v0 (condition-case nil
- (eval pat t)
- (error nil)))
- (v1 (condition-case nil
- (funcall (let ((lexical-binding t))
- (byte-compile `(lambda nil ,pat))))
- (error nil))))
- (equal v0 v1)))
-
-(put 'bytecomp-lexbind-check-1 'ert-explainer 'bytecomp-lexbind-explain-1)
-
-(defun bytecomp-lexbind-explain-1 (pat)
- (let ((v0 (condition-case nil
- (eval pat t)
- (error nil)))
- (v1 (condition-case nil
- (funcall (let ((lexical-binding t))
- (byte-compile (list 'lambda nil pat))))
- (error nil))))
- (format "Expression `%s' gives `%s' if directly evalled, `%s' if compiled."
- pat v0 v1)))
-
-(ert-deftest bytecomp-lexbind-tests ()
- "Test the Emacs byte compiler lexbind handling."
- (dolist (pat bytecomp-lexbind-tests)
- (should (bytecomp-lexbind-check-1 pat))))
-
(defmacro bytecomp-tests--with-temp-file (file-name-var &rest body)
(declare (indent 1))
(cl-check-type file-name-var symbol)
- `(let ((,file-name-var (make-temp-file "emacs")))
+ `(ert-with-temp-file ,file-name-var
(unwind-protect
(progn ,@body)
- (delete-file ,file-name-var)
(let ((elc (concat ,file-name-var ".elc")))
(if (file-exists-p elc) (delete-file elc))))))
@@ -520,37 +1093,28 @@ bytecompiled code, and their results compared.")
"Check that byte compiling warns about unescaped character
literals (Bug#20852)."
(should (boundp 'lread--unescaped-character-literals))
- (bytecomp-tests--with-temp-file source
- (write-region "(list ?) ?( ?; ?\" ?[ ?])" nil source)
- (bytecomp-tests--with-temp-file destination
- (let* ((byte-compile-dest-file-function (lambda (_) destination))
- (byte-compile-error-on-warn t)
- (byte-compile-debug t)
- (err (should-error (byte-compile-file source))))
- (should (equal (cdr err)
- (list (concat "unescaped character literals "
- "`?\"', `?(', `?)', `?;', `?[', `?]' "
- "detected!"))))))))
-
-(ert-deftest bytecomp-tests--old-style-backquotes ()
- "Check that byte compiling warns about old-style backquotes."
- (should (boundp 'lread--old-style-backquotes))
- (bytecomp-tests--with-temp-file source
- (write-region "(` (a b))" nil source)
- (bytecomp-tests--with-temp-file destination
- (let* ((byte-compile-dest-file-function (lambda (_) destination))
- (byte-compile-error-on-warn t)
- (byte-compile-debug t)
- (err (should-error (byte-compile-file source))))
- (should (equal (cdr err)
- (list "!! The file uses old-style backquotes !!
-This functionality has been obsolete for more than 10 years already
-and will be removed soon. See (elisp)Backquote in the manual.")))))))
-
+ (let ((byte-compile-error-on-warn t)
+ (byte-compile-debug t))
+ (bytecomp-tests--with-temp-file source
+ (write-region "(list ?) ?( ?; ?\" ?[ ?])" nil source)
+ (bytecomp-tests--with-temp-file destination
+ (let* ((byte-compile-dest-file-function (lambda (_) destination))
+ (err (should-error (byte-compile-file source))))
+ (should (equal (cdr err)
+ `(,(concat "unescaped character literals "
+ "`?\"', `?(', `?)', `?;', `?[', `?]' "
+ "detected, "
+ "`?\\\"', `?\\(', `?\\)', `?\\;', `?\\[', "
+ "`?\\]' expected!")))))))
+ ;; But don't warn in subsequent compilations (Bug#36068).
+ (bytecomp-tests--with-temp-file source
+ (write-region "(list 1 2 3)" nil source)
+ (bytecomp-tests--with-temp-file destination
+ (let ((byte-compile-dest-file-function (lambda (_) destination)))
+ (should (byte-compile-file source)))))))
(ert-deftest bytecomp-tests-function-put ()
"Check `function-put' operates during compilation."
- (should (boundp 'lread--old-style-backquotes))
(bytecomp-tests--with-temp-file source
(dolist (form '((function-put 'bytecomp-tests--foo 'foo 1)
(function-put 'bytecomp-tests--foo 'bar 2)
@@ -561,12 +1125,547 @@ and will be removed soon. See (elisp)Backquote in the manual.")))))))
(setq bytecomp-tests--foobar (bytecomp-tests--foobar))))
(print form (current-buffer)))
(write-region (point-min) (point-max) source nil 'silent)
- (byte-compile-file source t)
+ (byte-compile-file source)
+ (load source)
(should (equal bytecomp-tests--foobar (cons 1 2)))))
+(ert-deftest bytecomp-tests--test-no-warnings-with-advice ()
+ (defun f ())
+ (define-advice f (:around (oldfun &rest args) test)
+ (apply oldfun args))
+ (with-current-buffer (get-buffer-create "*Compile-Log*")
+ (let ((inhibit-read-only t)) (erase-buffer)))
+ (test-byte-comp-compile-and-load t '(defun f ()))
+ (with-current-buffer (get-buffer-create "*Compile-Log*")
+ (goto-char (point-min))
+ (should-not (search-forward "Warning" nil t))))
+
+(ert-deftest bytecomp-test-featurep-warnings ()
+ (let ((byte-compile-log-buffer (generate-new-buffer " *Compile-Log*")))
+ (unwind-protect
+ (progn
+ (with-temp-buffer
+ (insert "\
+\(defun foo ()
+ (an-undefined-function))
+
+\(defun foo1 ()
+ (if (featurep 'xemacs)
+ (some-undefined-function-if)))
+
+\(defun foo2 ()
+ (and (featurep 'xemacs)
+ (some-undefined-function-and)))
+
+\(defun foo3 ()
+ (if (not (featurep 'emacs))
+ (some-undefined-function-not)))
+
+\(defun foo4 ()
+ (or (featurep 'emacs)
+ (some-undefined-function-or)))
+")
+ (byte-compile-from-buffer (current-buffer)))
+ (with-current-buffer byte-compile-log-buffer
+ (should (search-forward "an-undefined-function" nil t))
+ (should-not (search-forward "some-undefined-function" nil t))))
+ (if (buffer-live-p byte-compile-log-buffer)
+ (kill-buffer byte-compile-log-buffer)))))
+
+(ert-deftest bytecomp-test--switch-duplicates ()
+ "Check that duplicates in switches are eliminated correctly (bug#35770)."
+ :expected-result (if byte-compile-cond-use-jump-table :passed :failed)
+ (dolist (params
+ '(((lambda (x)
+ (cond ((eq x 'a) 111)
+ ((eq x 'b) 222)
+ ((eq x 'a) 333)
+ ((eq x 'c) 444)))
+ (a b c)
+ string<)
+ ((lambda (x)
+ (cond ((eql x #x10000000000000000) 111)
+ ((eql x #x10000000000000001) 222)
+ ((eql x #x10000000000000000) 333)
+ ((eql x #x10000000000000002) 444)))
+ (#x10000000000000000 #x10000000000000001 #x10000000000000002)
+ <)
+ ((lambda (x)
+ (cond ((equal x "a") 111)
+ ((equal x "b") 222)
+ ((equal x "a") 333)
+ ((equal x "c") 444)))
+ ("a" "b" "c")
+ string<)))
+ (let* ((lisp (nth 0 params))
+ (keys (nth 1 params))
+ (lessp (nth 2 params))
+ (bc (byte-compile lisp))
+ (lap (byte-decompile-bytecode (aref bc 1) (aref bc 2)))
+ ;; Assume the first constant is the switch table.
+ (table (cadr (assq 'byte-constant lap))))
+ (should (hash-table-p table))
+ (should (equal (sort (hash-table-keys table) lessp) keys))
+ (should (member '(byte-constant 111) lap))
+ (should (member '(byte-constant 222) lap))
+ (should-not (member '(byte-constant 333) lap))
+ (should (member '(byte-constant 444) lap)))))
+
+(defun test-suppression (form suppress match)
+ (let ((lexical-binding t)
+ (byte-compile-log-buffer (generate-new-buffer " *Compile-Log*")))
+ ;; Check that we get a warning without suppression.
+ (with-current-buffer byte-compile-log-buffer
+ (setq-local fill-column 9999)
+ (setq-local warning-fill-column fill-column)
+ (let ((inhibit-read-only t))
+ (erase-buffer)))
+ (test-byte-comp-compile-and-load t form)
+ (with-current-buffer byte-compile-log-buffer
+ (unless match
+ (error "%s" (buffer-string)))
+ (goto-char (point-min))
+ (should (string-match match (buffer-string))))
+ ;; And that it's gone now.
+ (with-current-buffer byte-compile-log-buffer
+ (let ((inhibit-read-only t))
+ (erase-buffer)))
+ (test-byte-comp-compile-and-load t
+ `(with-suppressed-warnings ,suppress
+ ,form))
+ (with-current-buffer byte-compile-log-buffer
+ (goto-char (point-min))
+ (should-not (string-match match (buffer-string))))
+ ;; Also check that byte compiled forms are identical.
+ (should (equal (byte-compile form)
+ (byte-compile
+ `(with-suppressed-warnings ,suppress ,form))))))
+
+(ert-deftest bytecomp-test--with-suppressed-warnings ()
+ (test-suppression
+ '(defvar prefixless)
+ '((lexical prefixless))
+ "global/dynamic var .prefixless. lacks")
+
+ ;; FIXME: These messages cannot be suppressed reliably right now,
+ ;; but attempting mutate `nil' or `5' is a rather daft thing to do
+ ;; in the first place. Preventing mutation of constants such as
+ ;; `most-positive-fixnum' makes more sense but the compiler doesn't
+ ;; warn about that at all right now (it's caught at runtime, and we
+ ;; allow writing the same value).
+ ;;
+ ;; (test-suppression
+ ;; '(defun foo()
+ ;; (let ((nil t))
+ ;; (message-mail)))
+ ;; '((constants nil))
+ ;; "Warning: attempt to let-bind constant .nil.")
+
+ (test-suppression
+ '(progn
+ (defun obsolete ()
+ (declare (obsolete foo "22.1")))
+ (defun zot ()
+ (obsolete)))
+ '((obsolete obsolete))
+ "Warning: .obsolete. is an obsolete function")
+
+ (test-suppression
+ '(progn
+ (defun wrong-params (foo &optional unused)
+ (ignore unused)
+ foo)
+ (defun zot ()
+ (wrong-params 1 2 3)))
+ '((callargs wrong-params))
+ "Warning: .wrong-params. called with")
+
+ (test-byte-comp-compile-and-load nil
+ (defvar obsolete-variable nil)
+ (make-obsolete-variable 'obsolete-variable nil "24.1"))
+ (test-suppression
+ '(defun zot ()
+ obsolete-variable)
+ '((obsolete obsolete-variable))
+ "obsolete")
+
+ (test-suppression
+ '(defun zot ()
+ (next-line))
+ '((interactive-only next-line))
+ "interactive use only")
+
+ (test-suppression
+ '(defun zot ()
+ (mapcar #'list '(1 2 3))
+ nil)
+ '((mapcar mapcar))
+ "Warning: .mapcar. called for effect")
+
+ (test-suppression
+ '(defun zot ()
+ free-variable)
+ '((free-vars free-variable))
+ "Warning: reference to free variable")
+
+ (test-suppression
+ '(defun zot ()
+ (save-excursion
+ (set-buffer (get-buffer-create "foo"))
+ nil))
+ '((suspicious set-buffer))
+ "Warning: Use .with-current-buffer. rather than"))
+
+(ert-deftest bytecomp-tests--not-writable-directory ()
+ "Test that byte compilation works if the output directory isn't
+writable (Bug#44631)."
+ (ert-with-temp-directory directory
+ (let* ((input-file (expand-file-name "test.el" directory))
+ (output-file (expand-file-name "test.elc" directory))
+ (byte-compile-dest-file-function
+ (lambda (_) output-file))
+ (byte-compile-error-on-warn t))
+ (unwind-protect
+ (progn
+ (write-region "" nil input-file nil nil nil 'excl)
+ (write-region "" nil output-file nil nil nil 'excl)
+ (set-file-modes input-file #o400)
+ (set-file-modes output-file #o200)
+ (set-file-modes directory #o500)
+ (should (byte-compile-file input-file))
+ (should (file-regular-p output-file))
+ (should (cl-plusp (file-attribute-size
+ (file-attributes output-file)))))
+ ;; Allow the directory to be deleted.
+ (set-file-modes directory #o777)))))
+
+(ert-deftest bytecomp-tests--dest-mountpoint ()
+ "Test that byte compilation works if the destination file is a
+mountpoint (Bug#44631)."
+ (let ((bwrap (executable-find "bwrap"))
+ (emacs (expand-file-name invocation-name invocation-directory)))
+ (skip-unless bwrap)
+ (skip-unless (file-executable-p bwrap))
+ (skip-unless (not (file-remote-p bwrap)))
+ (skip-unless (file-executable-p emacs))
+ (skip-unless (not (file-remote-p emacs)))
+ (ert-with-temp-directory directory
+ (let* ((input-file (expand-file-name "test.el" directory))
+ (output-file (expand-file-name "test.elc" directory))
+ (unquoted-file (file-name-unquote output-file))
+ (byte-compile-dest-file-function
+ (lambda (_) output-file))
+ (byte-compile-error-on-warn t))
+ (should-not (file-remote-p input-file))
+ (should-not (file-remote-p output-file))
+ (write-region "" nil input-file nil nil nil 'excl)
+ (write-region "" nil output-file nil nil nil 'excl)
+ (unwind-protect
+ (progn
+ (set-file-modes input-file #o400)
+ (set-file-modes output-file #o200)
+ (set-file-modes directory #o500)
+ (with-temp-buffer
+ (let ((status (call-process
+ bwrap nil t nil
+ "--ro-bind" "/" "/"
+ "--bind" unquoted-file unquoted-file
+ emacs "--quick" "--batch" "--load=bytecomp"
+ (format "--eval=%S"
+ `(setq byte-compile-dest-file-function
+ (lambda (_) ,output-file)
+ byte-compile-error-on-warn t))
+ "--funcall=batch-byte-compile" input-file)))
+ (unless (eql status 0)
+ (ert-fail `((status . ,status)
+ (output . ,(buffer-string)))))))
+ (should (file-regular-p output-file))
+ (should (cl-plusp (file-attribute-size
+ (file-attributes output-file)))))
+ ;; Allow the directory to be deleted.
+ (set-file-modes directory #o777))))))
+
+(ert-deftest bytecomp-tests--target-file-no-directory ()
+ "Check that Bug#45287 is fixed."
+ (ert-with-temp-directory directory
+ (let* ((default-directory directory)
+ (byte-compile-dest-file-function (lambda (_) "test.elc"))
+ (byte-compile-error-on-warn t))
+ (write-region "" nil "test.el" nil nil nil 'excl)
+ (should (byte-compile-file "test.el"))
+ (should (file-regular-p "test.elc"))
+ (should (cl-plusp (file-attribute-size
+ (file-attributes "test.elc")))))))
+
+(defun bytecomp-tests--get-vars ()
+ (list (ignore-errors (symbol-value 'bytecomp-tests--var1))
+ (ignore-errors (symbol-value 'bytecomp-tests--var2))))
+
+(ert-deftest bytecomp-local-defvar ()
+ "Check that local `defvar' declarations work correctly, both
+interpreted and compiled."
+ (let ((lexical-binding t))
+ (let ((fun '(lambda ()
+ (defvar bytecomp-tests--var1)
+ (let ((bytecomp-tests--var1 'a) ; dynamic
+ (bytecomp-tests--var2 'b)) ; still lexical
+ (ignore bytecomp-tests--var2) ; avoid warning
+ (bytecomp-tests--get-vars)))))
+ (should (listp fun)) ; Guard against overzealous refactoring!
+ (should (equal (funcall (eval fun t)) '(a nil)))
+ (should (equal (funcall (byte-compile fun)) '(a nil)))
+ )
+
+ ;; `progn' does not constitute a lexical scope for `defvar' (bug#46387).
+ (let ((fun '(lambda ()
+ (progn
+ (defvar bytecomp-tests--var1)
+ (defvar bytecomp-tests--var2))
+ (let ((bytecomp-tests--var1 'c)
+ (bytecomp-tests--var2 'd))
+ (bytecomp-tests--get-vars)))))
+ (should (listp fun))
+ (should (equal (funcall (eval fun t)) '(c d)))
+ (should (equal (funcall (byte-compile fun)) '(c d))))))
+
+(ert-deftest bytecomp-reify-function ()
+ "Check that closures that modify their bound variables are
+compiled correctly."
+ (cl-letf ((lexical-binding t)
+ ((symbol-function 'counter) nil))
+ (let ((x 0))
+ (defun counter () (cl-incf x))
+ (should (equal (counter) 1))
+ (should (equal (counter) 2))
+ ;; byte compiling should not cause counter to always return the
+ ;; same value (bug#46834)
+ (byte-compile 'counter)
+ (should (equal (counter) 3))
+ (should (equal (counter) 4)))
+ (let ((x 0))
+ (let ((x 1))
+ (defun counter () x)
+ (should (equal (counter) 1))
+ ;; byte compiling should not cause the outer binding to shadow
+ ;; the inner one (bug#46834)
+ (byte-compile 'counter)
+ (should (equal (counter) 1))))))
+
+(ert-deftest bytecomp-string-vs-docstring ()
+ ;; Don't confuse a string return value for a docstring.
+ (let ((lexical-binding t))
+ (should (equal (funcall (byte-compile '(lambda (x) "foo")) 'dummy) "foo"))))
+
+(ert-deftest bytecomp-condition-case-success ()
+ ;; No error, no success handler.
+ (should (equal (condition-case x
+ (list 42)
+ (error (cons 'bad x)))
+ '(42)))
+ ;; Error, no success handler.
+ (should (equal (condition-case x
+ (/ 1 0)
+ (error (cons 'bad x)))
+ '(bad arith-error)))
+ ;; No error, success handler.
+ (should (equal (condition-case x
+ (list 42)
+ (error (cons 'bad x))
+ (:success (cons 'good x)))
+ '(good 42)))
+ ;; Error, success handler.
+ (should (equal (condition-case x
+ (/ 1 0)
+ (error (cons 'bad x))
+ (:success (cons 'good x)))
+ '(bad arith-error)))
+ ;; Verify that the success code is not subject to the error handlers.
+ (should-error (condition-case x
+ (list 42)
+ (error (cons 'bad x))
+ (:success (/ (car x) 0)))
+ :type 'arith-error)
+ ;; Check variable scoping.
+ (let ((x 2))
+ (should (equal (condition-case x
+ (list x)
+ (error (list 'bad x))
+ (:success (list 'good x)))
+ '(good (2))))
+ (should (equal (condition-case x
+ (/ 1 0)
+ (error (list 'bad x))
+ (:success (list 'good x)))
+ '(bad (arith-error)))))
+ ;; Check capture of mutated result variable.
+ (should (equal (funcall
+ (condition-case x
+ 3
+ (:success (prog1 (lambda (y) (+ y x))
+ (setq x 10))))
+ 4)
+ 14))
+ ;; Check for-effect context, on error.
+ (should (equal (let ((f (lambda (x)
+ (condition-case nil
+ (/ 1 0)
+ (error 'bad)
+ (:success 'good))
+ (1+ x))))
+ (funcall f 3))
+ 4))
+ ;; Check for-effect context, on success.
+ (should (equal (let ((f (lambda (x)
+ (condition-case nil
+ nil
+ (error 'bad)
+ (:success 'good))
+ (1+ x))))
+ (funcall f 3))
+ 4)))
+
+(declare-function bc-test-alpha-f (ert-resource-file "bc-test-alpha.el"))
+
+(ert-deftest bytecomp-defsubst ()
+ ;; Check that lexical variables don't leak into inlined code. See
+ ;; https://lists.gnu.org/archive/html/emacs-devel/2021-05/msg01227.html
+
+ ;; First, remove any trace of the functions and package defined:
+ (fmakunbound 'bc-test-alpha-f)
+ (fmakunbound 'bc-test-beta-f)
+ (setq features (delq 'bc-test-beta features))
+ ;; Byte-compile one file that uses a function from another file that isn't
+ ;; compiled.
+ (let ((file (ert-resource-file "bc-test-alpha.el"))
+ (load-path (cons (ert-resource-directory) load-path)))
+ (byte-compile-file file)
+ (load-file (concat file "c"))
+ (should (equal (bc-test-alpha-f 'a) '(nil a)))))
+
+(ert-deftest bytecomp-tests-byte-compile--wide-docstring-p/func-arg-list ()
+ (should-not (byte-compile--wide-docstring-p "\
+\(dbus-register-property BUS SERVICE PATH INTERFACE PROPERTY ACCESS \
+[TYPE] VALUE &optional EMITS-SIGNAL DONT-REGISTER-SERVICE)" fill-column))
+ (should-not (byte-compile--wide-docstring-p "\
+(fn CMD FLAGS FIS &key (BUF (cvs-temp-buffer)) DONT-CHANGE-DISC CVSARGS \
+POSTPROC)" fill-column))
+ ;; Bug#49007
+ (should-not (byte-compile--wide-docstring-p "\
+(fn (THIS rudel-protocol-backend) TRANSPORT \
+INFO INFO-CALLBACK &optional PROGRESS-CALLBACK)" fill-column))
+ (should-not (byte-compile--wide-docstring-p "\
+\(fn NAME () [DOCSTRING] [:expected-result RESULT-TYPE] \
+[:tags \\='(TAG...)] BODY...)" fill-column))
+ (should-not (byte-compile--wide-docstring-p "\
+(make-soap-xs-element &key NAME NAMESPACE-TAG ID TYPE^ OPTIONAL? MULTIPLE? \
+REFERENCE SUBSTITUTION-GROUP ALTERNATIVES IS-GROUP)" fill-column))
+ (should-not (byte-compile--wide-docstring-p "\
+(fn NAME FIXTURE INPUT &key SKIP-PAIR-STRING EXPECTED-STRING \
+EXPECTED-POINT BINDINGS (MODES \\='\\='(ruby-mode js-mode python-mode)) \
+(TEST-IN-COMMENTS t) (TEST-IN-STRINGS t) (TEST-IN-CODE t) \
+(FIXTURE-FN \\='#\\='electric-pair-mode))" fill-column)))
+
+(defun test-bytecomp-defgroup-choice ()
+ (should-not (byte-compile--suspicious-defcustom-choice 'integer))
+ (should-not (byte-compile--suspicious-defcustom-choice
+ '(choice (const :tag "foo" bar))))
+ (should (byte-compile--suspicious-defcustom-choice
+ '(choice (const :tag "foo" 'bar)))))
+
+(ert-deftest bytecomp-function-attributes ()
+ ;; Check that `byte-compile' keeps the declarations, interactive spec and
+ ;; doc string of the function (bug#55830).
+ (let ((fname 'bytecomp-test-fun))
+ (fset fname nil)
+ (put fname 'pure nil)
+ (put fname 'lisp-indent-function nil)
+ (eval `(defun ,fname (x)
+ "tata"
+ (declare (pure t) (indent 1))
+ (interactive "P")
+ (list 'toto x))
+ t)
+ (let ((bc (byte-compile fname)))
+ (should (byte-code-function-p bc))
+ (should (equal (funcall bc 'titi) '(toto titi)))
+ (should (equal (aref bc 5) "P"))
+ (should (equal (get fname 'pure) t))
+ (should (equal (get fname 'lisp-indent-function) 1))
+ (should (equal (aref bc 4) "tata\n\n(fn X)")))))
+
+(ert-deftest bytecomp-fun-attr-warn ()
+ ;; Check that warnings are emitted when doc strings, `declare' and
+ ;; `interactive' forms don't come in the proper order, or more than once.
+ (let* ((filename "fun-attr-warn.el")
+ (el (ert-resource-file filename))
+ (elc (concat el "c"))
+ (text-quoting-style 'grave))
+ (with-current-buffer (get-buffer-create "*Compile-Log*")
+ (let ((inhibit-read-only t))
+ (erase-buffer))
+ (byte-compile-file el)
+ (let ((expected
+ '("70:4: Warning: `declare' after `interactive'"
+ "74:4: Warning: Doc string after `interactive'"
+ "79:4: Warning: Doc string after `interactive'"
+ "84:4: Warning: Doc string after `declare'"
+ "89:4: Warning: Doc string after `declare'"
+ "96:4: Warning: `declare' after `interactive'"
+ "102:4: Warning: `declare' after `interactive'"
+ "108:4: Warning: `declare' after `interactive'"
+ "106:4: Warning: Doc string after `interactive'"
+ "114:4: Warning: `declare' after `interactive'"
+ "112:4: Warning: Doc string after `interactive'"
+ "118:4: Warning: Doc string after `interactive'"
+ "119:4: Warning: `declare' after `interactive'"
+ "124:4: Warning: Doc string after `interactive'"
+ "125:4: Warning: `declare' after `interactive'"
+ "130:4: Warning: Doc string after `declare'"
+ "136:4: Warning: Doc string after `declare'"
+ "142:4: Warning: Doc string after `declare'"
+ "148:4: Warning: Doc string after `declare'"
+ "159:4: Warning: More than one doc string"
+ "165:4: Warning: More than one doc string"
+ "171:4: Warning: More than one doc string"
+ "178:4: Warning: More than one doc string"
+ "186:4: Warning: More than one doc string"
+ "192:4: Warning: More than one doc string"
+ "200:4: Warning: More than one doc string"
+ "206:4: Warning: More than one doc string"
+ "215:4: Warning: More than one `declare' form"
+ "222:4: Warning: More than one `declare' form"
+ "230:4: Warning: More than one `declare' form"
+ "237:4: Warning: More than one `declare' form"
+ "244:4: Warning: More than one `interactive' form"
+ "251:4: Warning: More than one `interactive' form"
+ "258:4: Warning: More than one `interactive' form"
+ "257:4: Warning: `declare' after `interactive'"
+ "265:4: Warning: More than one `interactive' form"
+ "264:4: Warning: `declare' after `interactive'")))
+ (goto-char (point-min))
+ (let ((actual nil))
+ (while (re-search-forward
+ (rx bol (* (not ":")) ":"
+ (group (+ digit) ":" (+ digit) ": Warning: "
+ (or "More than one " (+ nonl) " form"
+ (: (+ nonl) " after " (+ nonl))))
+ eol)
+ nil t)
+ (push (match-string 1) actual))
+ (setq actual (nreverse actual))
+ (should (equal actual expected)))))))
+
+(ert-deftest byte-compile-file/no-byte-compile ()
+ (let* ((src-file (ert-resource-file "no-byte-compile.el"))
+ (dest-file (make-temp-file "bytecomp-tests-" nil ".elc"))
+ (byte-compile-dest-file-function (lambda (_) dest-file)))
+ (should (eq (byte-compile-file src-file) 'no-byte-compile))
+ (should-not (file-exists-p dest-file))))
+
+
;; Local Variables:
;; no-byte-compile: t
;; End:
(provide 'bytecomp-tests)
-;; bytecomp-tests.el ends here.
+;;; bytecomp-tests.el ends here
diff --git a/test/lisp/emacs-lisp/cconv-tests.el b/test/lisp/emacs-lisp/cconv-tests.el
new file mode 100644
index 00000000000..37470f863f3
--- /dev/null
+++ b/test/lisp/emacs-lisp/cconv-tests.el
@@ -0,0 +1,361 @@
+;;; cconv-tests.el --- Tests for cconv.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2018-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'cl-lib)
+(require 'generator)
+(require 'bytecomp)
+
+(ert-deftest cconv-tests-lambda-:documentation ()
+ "Docstring for lambda can be specified with :documentation."
+ (let ((fun (lambda ()
+ (:documentation (concat "lambda" " documentation"))
+ 'lambda-result)))
+ (should (string= (documentation fun) "lambda documentation"))
+ (should (eq (funcall fun) 'lambda-result))))
+
+(ert-deftest cconv-tests-pcase-lambda-:documentation ()
+ "Docstring for pcase-lambda can be specified with :documentation."
+ (let ((fun (pcase-lambda (`(,a ,b))
+ (:documentation (concat "pcase-lambda" " documentation"))
+ (list b a))))
+ (should (string= (documentation fun) "pcase-lambda documentation"))
+ (should (equal '(2 1) (funcall fun '(1 2))))))
+
+(defun cconv-tests-defun ()
+ (:documentation (concat "defun" " documentation"))
+ 'defun-result)
+(ert-deftest cconv-tests-defun-:documentation ()
+ "Docstring for defun can be specified with :documentation."
+ (should (string= (documentation 'cconv-tests-defun)
+ "defun documentation"))
+ (should (eq (cconv-tests-defun) 'defun-result)))
+
+(cl-defun cconv-tests-cl-defun ()
+ (:documentation (concat "cl-defun" " documentation"))
+ 'cl-defun-result)
+(ert-deftest cconv-tests-cl-defun-:documentation ()
+ "Docstring for cl-defun can be specified with :documentation."
+ (should (string= (documentation 'cconv-tests-cl-defun)
+ "cl-defun documentation"))
+ (should (eq (cconv-tests-cl-defun) 'cl-defun-result)))
+
+;; FIXME: The byte-complier croaks on this. See Bug#28557.
+;; (defmacro cconv-tests-defmacro ()
+;; (:documentation (concat "defmacro" " documentation"))
+;; '(quote defmacro-result))
+;; (ert-deftest cconv-tests-defmacro-:documentation ()
+;; "Docstring for defmacro can be specified with :documentation."
+;; (should (string= (documentation 'cconv-tests-defmacro)
+;; "defmacro documentation"))
+;; (should (eq (cconv-tests-defmacro) 'defmacro-result)))
+
+;; FIXME: The byte-complier croaks on this. See Bug#28557.
+;; (cl-defmacro cconv-tests-cl-defmacro ()
+;; (:documentation (concat "cl-defmacro" " documentation"))
+;; '(quote cl-defmacro-result))
+;; (ert-deftest cconv-tests-cl-defmacro-:documentation ()
+;; "Docstring for cl-defmacro can be specified with :documentation."
+;; (should (string= (documentation 'cconv-tests-cl-defmacro)
+;; "cl-defmacro documentation"))
+;; (should (eq (cconv-tests-cl-defmacro) 'cl-defmacro-result)))
+
+(cl-iter-defun cconv-tests-cl-iter-defun ()
+ (:documentation (concat "cl-iter-defun" " documentation"))
+ (iter-yield 'cl-iter-defun-result))
+(ert-deftest cconv-tests-cl-iter-defun-:documentation ()
+ "Docstring for cl-iter-defun can be specified with :documentation."
+ (should (string= (documentation 'cconv-tests-cl-iter-defun)
+ "cl-iter-defun documentation"))
+ (should (eq (iter-next (cconv-tests-cl-iter-defun))
+ 'cl-iter-defun-result)))
+
+(iter-defun cconv-tests-iter-defun ()
+ (:documentation (concat "iter-defun" " documentation"))
+ (iter-yield 'iter-defun-result))
+(ert-deftest cconv-tests-iter-defun-:documentation ()
+ "Docstring for iter-defun can be specified with :documentation."
+ (should (string= (documentation 'cconv-tests-iter-defun)
+ "iter-defun documentation"))
+ (should (eq (iter-next (cconv-tests-iter-defun)) 'iter-defun-result)))
+
+(ert-deftest cconv-tests-iter-lambda-:documentation ()
+ "Docstring for iter-lambda can be specified with :documentation."
+ (let ((iter-fun
+ (iter-lambda ()
+ (:documentation (concat "iter-lambda" " documentation"))
+ (iter-yield 'iter-lambda-result))))
+ (should (string= (documentation iter-fun) "iter-lambda documentation"))
+ (should (eq (iter-next (funcall iter-fun)) 'iter-lambda-result))))
+
+(ert-deftest cconv-tests-cl-function-:documentation ()
+ "Docstring for cl-function can be specified with :documentation."
+ (let ((fun (cl-function (lambda (&key arg)
+ (:documentation (concat "cl-function"
+ " documentation"))
+ (list arg 'cl-function-result)))))
+ (should (string-match "\\`cl-function documentation$" (documentation fun)))
+ (should (equal (funcall fun :arg t) '(t cl-function-result)))))
+
+(ert-deftest cconv-tests-function-:documentation ()
+ "Docstring for lambda inside function can be specified with :documentation."
+ (let ((fun #'(lambda (arg)
+ (:documentation (concat "function" " documentation"))
+ (list arg 'function-result))))
+ (should (string= (documentation fun) "function documentation"))
+ (should (equal (funcall fun t) '(t function-result)))))
+
+(fmakunbound 'cconv-tests-cl-defgeneric)
+(setplist 'cconv-tests-cl-defgeneric nil)
+(cl-defgeneric cconv-tests-cl-defgeneric (n)
+ (:documentation (concat "cl-defgeneric" " documentation")))
+(cl-defmethod cconv-tests-cl-defgeneric ((n integer))
+ (:documentation (concat "cl-defmethod" " documentation"))
+ (+ 1 n))
+(ert-deftest cconv-tests-cl-defgeneric-:documentation ()
+ "Docstring for cl-defgeneric can be specified with :documentation."
+ (let ((descr (describe-function 'cconv-tests-cl-defgeneric)))
+ (set-text-properties 0 (length descr) nil descr)
+ (should (string-match-p "cl-defgeneric documentation" descr))
+ (should (string-match-p "cl-defmethod documentation" descr)))
+ (should (= 11 (cconv-tests-cl-defgeneric 10))))
+
+(fmakunbound 'cconv-tests-cl-defgeneric-literal)
+(setplist 'cconv-tests-cl-defgeneric-literal nil)
+(cl-defgeneric cconv-tests-cl-defgeneric-literal (n)
+ (:documentation "cl-defgeneric-literal documentation"))
+(cl-defmethod cconv-tests-cl-defgeneric-literal ((n integer))
+ (:documentation "cl-defmethod-literal documentation")
+ (+ 1 n))
+(ert-deftest cconv-tests-cl-defgeneric-literal-:documentation ()
+ "Docstring for cl-defgeneric can be specified with :documentation."
+ (let ((descr (describe-function 'cconv-tests-cl-defgeneric-literal)))
+ (set-text-properties 0 (length descr) nil descr)
+ (should (string-match-p "cl-defgeneric-literal documentation" descr))
+ (should (string-match-p "cl-defmethod-literal documentation" descr)))
+ (should (= 11 (cconv-tests-cl-defgeneric-literal 10))))
+
+(defsubst cconv-tests-defsubst ()
+ (:documentation (concat "defsubst" " documentation"))
+ 'defsubst-result)
+(ert-deftest cconv-tests-defsubst-:documentation ()
+ "Docstring for defsubst can be specified with :documentation."
+ (should (string= (documentation 'cconv-tests-defsubst)
+ "defsubst documentation"))
+ (should (eq (cconv-tests-defsubst) 'defsubst-result)))
+
+(cl-defsubst cconv-tests-cl-defsubst ()
+ (:documentation (concat "cl-defsubst" " documentation"))
+ 'cl-defsubst-result)
+(ert-deftest cconv-tests-cl-defsubst-:documentation ()
+ "Docstring for cl-defsubst can be specified with :documentation."
+ (should (string= (documentation 'cconv-tests-cl-defsubst)
+ "cl-defsubst documentation"))
+ (should (eq (cconv-tests-cl-defsubst) 'cl-defsubst-result)))
+
+(ert-deftest cconv-convert-lambda-lifted ()
+ ;; Verify that lambda-lifting is actually performed at all.
+ (should (equal (cconv-closure-convert
+ '#'(lambda (x) (let ((f #'(lambda () (+ x 1))))
+ (funcall f))))
+ '#'(lambda (x) (let ((f #'(lambda (x) (+ x 1))))
+ (funcall f x)))))
+
+ ;; Bug#30872.
+ (should
+ (equal (funcall
+ (byte-compile
+ '#'(lambda (handle-fun arg)
+ (let* ((subfun
+ #'(lambda (params)
+ (ignore handle-fun)
+ (funcall #'(lambda () (setq params 42)))
+ params)))
+ (funcall subfun arg))))
+ nil 99)
+ 42)))
+
+(defun cconv-tests--intern-all (x)
+ "Intern all symbols in X."
+ (cond ((symbolp x) (intern (symbol-name x)))
+ ((consp x) (cons (cconv-tests--intern-all (car x))
+ (cconv-tests--intern-all (cdr x))))
+ ;; Assume we don't need to deal with vectors etc.
+ (t x)))
+
+(ert-deftest cconv-closure-convert-remap-var ()
+ ;; Verify that we correctly remap shadowed lambda-lifted variables.
+
+ ;; We intern all symbols for ease of comparison; this works because
+ ;; the `cconv-closure-convert' result should contain no pair of
+ ;; distinct symbols having the same name.
+
+ ;; Sanity check: captured variable, no lambda-lifting or shadowing:
+ (should (equal (cconv-tests--intern-all
+ (cconv-closure-convert
+ '#'(lambda (x)
+ #'(lambda () x))))
+ '#'(lambda (x)
+ (internal-make-closure
+ nil (x) nil
+ (internal-get-closed-var 0)))))
+
+ ;; Basic case:
+ (should (equal (cconv-tests--intern-all
+ (cconv-closure-convert
+ '#'(lambda (x)
+ (let ((f #'(lambda () x)))
+ (let ((x 'b))
+ (list x (funcall f)))))))
+ '#'(lambda (x)
+ (let ((f #'(lambda (x) x)))
+ (let ((x 'b)
+ (closed-x x))
+ (list x (funcall f closed-x)))))))
+ (should (equal (cconv-tests--intern-all
+ (cconv-closure-convert
+ '#'(lambda (x)
+ (let ((f #'(lambda () x)))
+ (let* ((x 'b))
+ (list x (funcall f)))))))
+ '#'(lambda (x)
+ (let ((f #'(lambda (x) x)))
+ (let* ((closed-x x)
+ (x 'b))
+ (list x (funcall f closed-x)))))))
+
+ ;; With the lambda-lifted shadowed variable also being captured:
+ (should (equal
+ (cconv-tests--intern-all
+ (cconv-closure-convert
+ '#'(lambda (x)
+ #'(lambda ()
+ (let ((f #'(lambda () x)))
+ (let ((x 'a))
+ (list x (funcall f))))))))
+ '#'(lambda (x)
+ (internal-make-closure
+ nil (x) nil
+ (let ((f #'(lambda (x) x)))
+ (let ((x 'a)
+ (closed-x (internal-get-closed-var 0)))
+ (list x (funcall f closed-x))))))))
+ (should (equal
+ (cconv-tests--intern-all
+ (cconv-closure-convert
+ '#'(lambda (x)
+ #'(lambda ()
+ (let ((f #'(lambda () x)))
+ (let* ((x 'a))
+ (list x (funcall f))))))))
+ '#'(lambda (x)
+ (internal-make-closure
+ nil (x) nil
+ (let ((f #'(lambda (x) x)))
+ (let* ((closed-x (internal-get-closed-var 0))
+ (x 'a))
+ (list x (funcall f closed-x))))))))
+ ;; With lambda-lifted shadowed variable also being mutably captured:
+ (should (equal
+ (cconv-tests--intern-all
+ (cconv-closure-convert
+ '#'(lambda (x)
+ #'(lambda ()
+ (let ((f #'(lambda () x)))
+ (setq x x)
+ (let ((x 'a))
+ (list x (funcall f))))))))
+ '#'(lambda (x)
+ (let ((x (list x)))
+ (internal-make-closure
+ nil (x) nil
+ (let ((f #'(lambda (x) (car-safe x))))
+ (setcar (internal-get-closed-var 0)
+ (car-safe (internal-get-closed-var 0)))
+ (let ((x 'a)
+ (closed-x (internal-get-closed-var 0)))
+ (list x (funcall f closed-x)))))))))
+ (should (equal
+ (cconv-tests--intern-all
+ (cconv-closure-convert
+ '#'(lambda (x)
+ #'(lambda ()
+ (let ((f #'(lambda () x)))
+ (setq x x)
+ (let* ((x 'a))
+ (list x (funcall f))))))))
+ '#'(lambda (x)
+ (let ((x (list x)))
+ (internal-make-closure
+ nil (x) nil
+ (let ((f #'(lambda (x) (car-safe x))))
+ (setcar (internal-get-closed-var 0)
+ (car-safe (internal-get-closed-var 0)))
+ (let* ((closed-x (internal-get-closed-var 0))
+ (x 'a))
+ (list x (funcall f closed-x)))))))))
+ ;; Lambda-lifted variable that isn't actually captured where it is shadowed:
+ (should (equal
+ (cconv-tests--intern-all
+ (cconv-closure-convert
+ '#'(lambda (x)
+ (let ((g #'(lambda () x))
+ (h #'(lambda () (setq x x))))
+ (let ((x 'b))
+ (list x (funcall g) (funcall h)))))))
+ '#'(lambda (x)
+ (let ((x (list x)))
+ (let ((g #'(lambda (x) (car-safe x)))
+ (h #'(lambda (x) (setcar x (car-safe x)))))
+ (let ((x 'b)
+ (closed-x x))
+ (list x (funcall g closed-x) (funcall h closed-x))))))))
+ (should (equal
+ (cconv-tests--intern-all
+ (cconv-closure-convert
+ '#'(lambda (x)
+ (let ((g #'(lambda () x))
+ (h #'(lambda () (setq x x))))
+ (let* ((x 'b))
+ (list x (funcall g) (funcall h)))))))
+ '#'(lambda (x)
+ (let ((x (list x)))
+ (let ((g #'(lambda (x) (car-safe x)))
+ (h #'(lambda (x) (setcar x (car-safe x)))))
+ (let* ((closed-x x)
+ (x 'b))
+ (list x (funcall g closed-x) (funcall h closed-x))))))))
+ )
+
+(ert-deftest cconv-tests-interactive-closure-bug51695 ()
+ (let ((f (let ((d 51695))
+ (lambda (data)
+ (interactive (progn (setq d (1+ d)) (list d)))
+ (list (called-interactively-p 'any) data)))))
+ (should (equal (list (call-interactively f)
+ (funcall f 51695)
+ (call-interactively f))
+ '((t 51696) (nil 51695) (t 51697))))))
+
+(provide 'cconv-tests)
+;;; cconv-tests.el ends here
diff --git a/test/lisp/emacs-lisp/check-declare-tests.el b/test/lisp/emacs-lisp/check-declare-tests.el
new file mode 100644
index 00000000000..59dfc10163d
--- /dev/null
+++ b/test/lisp/emacs-lisp/check-declare-tests.el
@@ -0,0 +1,108 @@
+;;; check-declare-tests.el --- Tests for check-declare.el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+;; Author: Simen Heggestøyl <simenheg@gmail.com>
+;; Keywords:
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;
+
+;;; Code:
+
+(require 'check-declare)
+(require 'ert)
+(require 'ert-x)
+(eval-when-compile (require 'subr-x))
+
+(ert-deftest check-declare-tests-locate ()
+ (should (file-exists-p (check-declare-locate "check-declare" "")))
+ (should
+ (string-prefix-p "ext:" (check-declare-locate "ext:foo" ""))))
+
+(ert-deftest check-declare-tests-scan ()
+ (ert-with-temp-file file
+ (with-temp-file file
+ (insert
+ (string-join
+ '(";; foo comment"
+ "(declare-function ring-insert \"ring\" (ring item))"
+ "(let ((foo 'code)) foo)")
+ "\n")))
+ (let ((res (check-declare-scan file)))
+ (should (= (length res) 1))
+ (pcase-let ((`((,fnfile ,fn ,arglist ,fileonly)) res))
+ (should (string-match-p "ring" fnfile))
+ (should (equal "ring-insert" fn))
+ (should (equal '(ring item) arglist))
+ (should-not fileonly)))))
+
+(ert-deftest check-declare-tests-verify ()
+ (ert-with-temp-file file
+ (with-temp-file file
+ (insert
+ (string-join
+ '(";; foo comment"
+ "(defun foo-fun ())"
+ "(defun ring-insert (ring item)"
+ "\"Insert onto ring RING the item ITEM.\""
+ "nil)")
+ "\n")))
+ (should-not
+ (check-declare-verify
+ file '(("foo.el" "ring-insert" (ring item)))))))
+
+(ert-deftest check-declare-tests-verify-mismatch ()
+ (ert-with-temp-file file
+ (with-temp-file file
+ (insert
+ (string-join
+ '(";; foo comment"
+ "(defun foo-fun ())"
+ "(defun ring-insert (ring)"
+ "\"Insert onto ring RING the item ITEM.\""
+ "nil)")
+ "\n")))
+ (should
+ (equal
+ (check-declare-verify
+ file '(("foo.el" "ring-insert" (ring item))))
+ '(("foo.el" "ring-insert" "arglist mismatch"))))))
+
+(ert-deftest check-declare-tests-sort ()
+ (should-not (check-declare-sort '()))
+ (should (equal (check-declare-sort '((a (1 a)) (b (2)) (d (1 d))))
+ '((2 (b)) (1 (a a) (d d))))))
+
+(ert-deftest check-declare-tests-warn ()
+ (with-temp-buffer
+ (let ((check-declare-warning-buffer (buffer-name)))
+ (check-declare-warn
+ "foo-file" "foo-fun" "bar-file" "it wasn't" 999)
+ (let ((res (buffer-string)))
+ ;; Don't care too much about the format of the output, but
+ ;; check that key information is present.
+ (should (string-search "foo-file" res))
+ (should (string-search "foo-fun" res))
+ (should (string-search "bar-file" res))
+ (should (string-search "it wasn't" res))
+ (should (string-search "999" res))))))
+
+(provide 'check-declare-tests)
+;;; check-declare-tests.el ends here
diff --git a/test/lisp/emacs-lisp/checkdoc-tests.el b/test/lisp/emacs-lisp/checkdoc-tests.el
index d832a862280..289476f0246 100644
--- a/test/lisp/emacs-lisp/checkdoc-tests.el
+++ b/test/lisp/emacs-lisp/checkdoc-tests.el
@@ -1,6 +1,6 @@
;;; checkdoc-tests.el --- unit tests for checkdoc.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2016-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2022 Free Software Foundation, Inc.
;; Author: Philipp Stephani <phst@google.com>
@@ -37,6 +37,78 @@
(insert "(defun foo())")
(should-error (checkdoc-defun) :type 'user-error)))
+(ert-deftest checkdoc-cl-defmethod-ok ()
+ "Checkdoc should be happy with a simple correct cl-defmethod."
+ (with-temp-buffer
+ (emacs-lisp-mode)
+ (insert "(cl-defmethod foo (a) \"Return A.\")")
+ (checkdoc-defun)))
+
+(ert-deftest checkdoc-cl-defmethod-with-types-ok ()
+ "Checkdoc should be happy with a cl-defmethod using types."
+ (with-temp-buffer
+ (emacs-lisp-mode)
+ ;; this method matches if A is the symbol `smthg' and if b is a list:
+ (insert "(cl-defmethod foo ((a (eql 'smthg)) (b list)) \"Return A+B.\")")
+ (checkdoc-defun)))
+
+(ert-deftest checkdoc-cl-defmethod-qualified-ok ()
+ "Checkdoc should be happy with a `cl-defmethod' using qualifiers."
+ (with-temp-buffer
+ (emacs-lisp-mode)
+ (insert "(cl-defmethod test :around ((a (eql 'smthg))) \"Return A.\")")
+ (checkdoc-defun)))
+
+(ert-deftest checkdoc-cl-defmethod-with-extra-qualifier-ok ()
+ "Checkdoc should be happy with a :extra qualified `cl-defmethod'."
+ (with-temp-buffer
+ (emacs-lisp-mode)
+ (insert "(cl-defmethod foo :extra \"foo\" ((a (eql 'smthg))) \"Return A.\")")
+ (checkdoc-defun))
+
+ (with-temp-buffer
+ (emacs-lisp-mode)
+ (insert
+ "(cl-defmethod foo :extra \"foo\" :after ((a (eql 'smthg))) \"Return A.\")")
+ (checkdoc-defun)))
+
+(ert-deftest checkdoc-cl-defmethod-with-extra-qualifier-and-nil-args-ok ()
+ "Checkdoc should be happy with a 0-arity :extra qualified `cl-defmethod'."
+ (with-temp-buffer
+ (emacs-lisp-mode)
+ (insert "(cl-defmethod foo :extra \"foo\" () \"Return A.\")")
+ (checkdoc-defun)))
+
+(ert-deftest checkdoc-cl-defun-with-key-ok ()
+ "Checkdoc should be happy with a cl-defun using &key."
+ (with-temp-buffer
+ (emacs-lisp-mode)
+ (insert "(cl-defun foo (&key a (b 27)) \"Return :A+:B.\")")
+ (checkdoc-defun)))
+
+(ert-deftest checkdoc-cl-defun-with-allow-other-keys-ok ()
+ "Checkdoc should be happy with a cl-defun using &allow-other-keys."
+ (with-temp-buffer
+ (emacs-lisp-mode)
+ (insert "(cl-defun foo (&key a &allow-other-keys) \"Return :A.\")")
+ (checkdoc-defun)))
+
+(ert-deftest checkdoc-cl-defun-with-default-optional-value-ok ()
+ "Checkdoc should be happy with a cl-defun using default values for optional args."
+ (with-temp-buffer
+ (emacs-lisp-mode)
+ ;; B is optional and equals 1+a if not provided. HAS-BS is non-nil
+ ;; if B was provided in the call:
+ (insert "(cl-defun foo (a &optional (b (1+ a) has-bs)) \"Return A + B.\")")
+ (checkdoc-defun)))
+
+(ert-deftest checkdoc-cl-defun-with-destructuring-ok ()
+ "Checkdoc should be happy with a cl-defun destructuring its arguments."
+ (with-temp-buffer
+ (emacs-lisp-mode)
+ (insert "(cl-defun foo ((a b &optional c) d) \"Return A+B+C+D.\")")
+ (checkdoc-defun)))
+
(ert-deftest checkdoc-tests--next-docstring ()
"Checks that the one-argument form of `defvar' works.
See the comments in Bug#24998."
@@ -50,4 +122,100 @@ See the comments in Bug#24998."
(should (looking-at-p "\"baz\")"))
(should-not (checkdoc-next-docstring))))
+(defun checkdoc-tests--abbrev-test (buffer-contents goto-string)
+ (with-temp-buffer
+ (emacs-lisp-mode)
+ (insert buffer-contents)
+ (goto-char (point-min))
+ (re-search-forward goto-string)
+ (checkdoc-in-abbreviation-p (point))))
+
+(ert-deftest checkdoc-tests-in-abbrevation-p/basic-case ()
+ (should (checkdoc-tests--abbrev-test "foo bar e.g. baz" "e.g"))
+ (should (checkdoc-tests--abbrev-test "behavior/errors etc. that" "etc"))
+ (should (checkdoc-tests--abbrev-test "foo vs. bar" "vs"))
+ (should (checkdoc-tests--abbrev-test "spy a.k.a. spy" "a.k.a")))
+
+(ert-deftest checkdoc-tests-in-abbrevation-p/with-parens ()
+ (should (checkdoc-tests--abbrev-test "foo bar (e.g. baz)" "e.g")))
+
+(ert-deftest checkdoc-tests-in-abbrevation-p/with-escaped-parens ()
+ (should (checkdoc-tests--abbrev-test "foo\n\\(e.g. baz)" "e.g")))
+
+(ert-deftest checkdoc-tests-in-abbrevation-p/single-char ()
+ (should (checkdoc-tests--abbrev-test "a. foo bar" "a")))
+
+(ert-deftest checkdoc-tests-in-abbrevation-p/with-em-dash ()
+ (should (checkdoc-tests--abbrev-test "foo bar baz---e.g." "e.g")))
+
+(ert-deftest checkdoc-tests-in-abbrevation-p/incorrect-abbreviation ()
+ (should-not (checkdoc-tests--abbrev-test "foo bar a.b.c." "a.b.c")))
+
+(defun checkdoc-test-error-format-is-good (msg &optional reverse literal)
+ (with-temp-buffer
+ (erase-buffer)
+ (emacs-lisp-mode)
+ (let ((standard-output (current-buffer)))
+ (if literal
+ (print (format "(error \"%s\")" msg))
+ (prin1 `(error ,msg))))
+ (goto-char (length "(error \""))
+ (if reverse
+ (should (checkdoc--error-bad-format-p))
+ (should-not (checkdoc--error-bad-format-p)))))
+
+(defun checkdoc-test-error-format-is-bad (msg &optional literal)
+ (checkdoc-test-error-format-is-good msg t literal))
+
+(ert-deftest checkdoc-tests-error-message-bad-format-p ()
+ (checkdoc-test-error-format-is-good "Foo")
+ (checkdoc-test-error-format-is-good "Foo: bar baz")
+ (checkdoc-test-error-format-is-good "some-symbol: Foo")
+ (checkdoc-test-error-format-is-good "`some-symbol' foo bar")
+ (checkdoc-test-error-format-is-good "%sfoo")
+ (checkdoc-test-error-format-is-good "avl-tree-enter:\\
+ Updated data does not match existing data" nil 'literal))
+
+(ert-deftest checkdoc-tests-error-message-bad-format-p/defined-symbols ()
+ (defvar checkdoc-tests--var-symbol nil)
+ (checkdoc-test-error-format-is-good "checkdoc-tests--var-symbol foo bar baz")
+ (defun checkdoc-tests--fun-symbol ())
+ (checkdoc-test-error-format-is-good "checkdoc-tests--fun-symbol foo bar baz"))
+
+(ert-deftest checkdoc-tests-error-message-bad-format-p/not-capitalized ()
+ (checkdoc-test-error-format-is-bad "foo")
+ (checkdoc-test-error-format-is-bad "some-symbol: foo")
+ (checkdoc-test-error-format-is-bad "avl-tree-enter:\
+ updated data does not match existing data"))
+
+(ert-deftest checkdoc-tests-fix-y-or-n-p ()
+ (with-temp-buffer
+ (emacs-lisp-mode)
+ (let ((standard-output (current-buffer))
+ (checkdoc-autofix-flag 'automatic))
+ (prin1 '(y-or-n-p "foo")) ; "foo"
+ (goto-char (length "(y-or-n-p "))
+ (checkdoc--fix-y-or-n-p)
+ (should (equal (buffer-string) "(y-or-n-p \"foo?\")")))))
+
+(ert-deftest checkdoc-tests-fix-y-or-n-p/no-change ()
+ (with-temp-buffer
+ (emacs-lisp-mode)
+ (let ((standard-output (current-buffer))
+ (checkdoc-autofix-flag 'automatic))
+ (prin1 '(y-or-n-p "foo?")) ; "foo?"
+ (goto-char (length "(y-or-n-p "))
+ (checkdoc--fix-y-or-n-p)
+ (should (equal (buffer-string) "(y-or-n-p \"foo?\")")))))
+
+(ert-deftest checkdoc-tests-fix-y-or-n-p/with-space ()
+ (with-temp-buffer
+ (emacs-lisp-mode)
+ (let ((standard-output (current-buffer))
+ (checkdoc-autofix-flag 'automatic))
+ (prin1 '(y-or-n-p "foo? ")) ; "foo? "
+ (goto-char (length "(y-or-n-p "))
+ (checkdoc--fix-y-or-n-p)
+ (should (equal (buffer-string) "(y-or-n-p \"foo? \")")))))
+
;;; checkdoc-tests.el ends here
diff --git a/test/lisp/emacs-lisp/cl-extra-tests.el b/test/lisp/emacs-lisp/cl-extra-tests.el
index c37caa1aab7..297e413d858 100644
--- a/test/lisp/emacs-lisp/cl-extra-tests.el
+++ b/test/lisp/emacs-lisp/cl-extra-tests.el
@@ -1,21 +1,21 @@
;;; cl-extra-tests.el --- tests for emacs-lisp/cl-extra.el -*- lexical-binding:t -*-
-;; Copyright (C) 2013-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2022 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
-;; This program is free software: you can redistribute it and/or
-;; modify it under the terms of the GNU General Public License as
-;; published by the Free Software Foundation, either version 3 of the
-;; License, or (at your option) any later version.
-;;
-;; This program is distributed in the hope that it will be useful, but
-;; WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-;; General Public License for more details.
-;;
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
;; You should have received a copy of the GNU General Public License
-;; along with this program. If not, see `https://www.gnu.org/licenses/'.
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Code:
@@ -77,7 +77,7 @@
(fn3 (lambda (x _y _z) (string-to-char (format "%S" x)))))
(should (equal lst (cl-map 'list fn1 lst)))
(should (equal (vconcat lst2) (cl-map 'vector fn2 lst lst2)))
- (should (equal (mapconcat (lambda (x) (format "%S" x)) lst "")
+ (should (equal (mapconcat (lambda (x) (format "%S" x)) lst)
(cl-map 'string fn3 lst lst2 lst3)))))
(ert-deftest cl-extra-test-maplist ()
@@ -94,4 +94,17 @@
(should (equal (list lst3 (cdr lst3) (cddr lst3))
(cl-maplist fn3 lst lst2 lst3)))))
+(ert-deftest cl-extra-test-cl-make-random-state ()
+ (let ((s (cl-make-random-state)))
+ ;; Test for Bug#33731.
+ (should-not (eq s (cl-make-random-state s)))))
+
+(ert-deftest cl-concatenate ()
+ (should (equal (cl-concatenate 'list '(1 2 3) '(4 5 6))
+ '(1 2 3 4 5 6)))
+ (should (equal (cl-concatenate 'vector [1 2 3] [4 5 6])
+ [1 2 3 4 5 6]))
+ (should (equal (cl-concatenate 'string "123" "456")
+ "123456")))
+
;;; cl-extra-tests.el ends here
diff --git a/test/lisp/emacs-lisp/cl-generic-tests.el b/test/lisp/emacs-lisp/cl-generic-tests.el
index 9b2b04bcca4..56b766769ea 100644
--- a/test/lisp/emacs-lisp/cl-generic-tests.el
+++ b/test/lisp/emacs-lisp/cl-generic-tests.el
@@ -1,6 +1,6 @@
;;; cl-generic-tests.el --- Tests for cl-generic.el functionality -*- lexical-binding: t; -*-
-;; Copyright (C) 2015-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2022 Free Software Foundation, Inc.
;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
@@ -23,8 +23,15 @@
;;; Code:
-(eval-when-compile (require 'ert)) ;Don't indirectly require cl-lib at run-time.
(require 'cl-generic)
+(require 'edebug)
+
+;; Don't indirectly require `cl-lib' at run-time.
+(require 'ert)
+(declare-function ert--should-signal-hook "ert")
+(declare-function ert--signal-should-execution "ert")
+(declare-function ert-fail "ert")
+(declare-function ert-set-test "ert")
(fmakunbound 'cl--generic-1)
(cl-defgeneric cl--generic-1 (x y))
@@ -49,7 +56,14 @@
(should (equal (cl--generic-1 'a nil) '(a)))
(should (equal (cl--generic-1 4 nil) '("quatre" 4)))
(should (equal (cl--generic-1 5 nil) '("cinq" 5)))
- (should (equal (cl--generic-1 6 nil) '("six" a))))
+ (should (equal (cl--generic-1 6 nil) '("six" a)))
+ (defvar cl--generic-fooval 41)
+ (cl-defmethod cl--generic-1 ((_x (eql (+ cl--generic-fooval 1))) _y)
+ "forty-two")
+ (cl-defmethod cl--generic-1 (_x (_y (eql 42)))
+ "FORTY-TWO")
+ (should (equal (cl--generic-1 42 nil) "forty-two"))
+ (should (equal (cl--generic-1 nil 42) "FORTY-TWO")))
(cl-defstruct cl-generic-struct-parent a b)
(cl-defstruct (cl-generic-struct-child1 (:include cl-generic-struct-parent)) c)
@@ -186,9 +200,14 @@
(fmakunbound 'cl--generic-1)
(cl-defgeneric cl--generic-1 (x y))
(cl-defmethod cl--generic-1 ((x t) y)
- (list x y (cl-next-method-p)))
+ (list x y
+ (with-suppressed-warnings ((obsolete cl-next-method-p))
+ (cl-next-method-p))))
(cl-defmethod cl--generic-1 ((_x (eql 4)) _y)
- (cl-list* "quatre" (cl-next-method-p) (cl-call-next-method)))
+ (cl-list* "quatre"
+ (with-suppressed-warnings ((obsolete cl-next-method-p))
+ (cl-next-method-p))
+ (cl-call-next-method)))
(should (equal (cl--generic-1 4 5) '("quatre" t 4 5 nil))))
(ert-deftest cl-generic-test-12-context ()
@@ -233,7 +252,7 @@
(let ((retval (cl--generic-method-files 'cl-generic-tests--generic)))
(should (equal (length retval) 2))
(mapc (lambda (x)
- (should (equal (car x) cl-generic-tests--this-file))
+ (should (equal (file-truename (car x)) cl-generic-tests--this-file))
(should (equal (cadr x) 'cl-generic-tests--generic)))
retval)
(should-not (equal (nth 0 retval) (nth 1 retval)))))
@@ -243,5 +262,40 @@
(should-not (cl--generic-method-files 'cl-generic-tests--undefined-generic))
(should-not (cl--generic-method-files 'cl-generic-tests--generic-without-methods)))
+(ert-deftest cl-defgeneric/edebug/method ()
+ "Check that `:method' forms in `cl-defgeneric' create unique
+Edebug symbols (Bug#42672)."
+ (with-temp-buffer
+ (dolist (form '((cl-defgeneric cl-defgeneric/edebug/method/1 (_)
+ (:method ((_ number)) 1)
+ (:method ((_ string)) 2)
+ (:method :around ((_ number)) 3))
+ (cl-defgeneric cl-defgeneric/edebug/method/2 (_)
+ (:method ((_ number)) 3))))
+ (print form (current-buffer)))
+ (let* ((edebug-all-defs t)
+ (edebug-initial-mode 'Go-nonstop)
+ (instrumented-names ())
+ (edebug-new-definition-function
+ (lambda (name)
+ (when (memq name instrumented-names)
+ (error "Duplicate definition of `%s'" name))
+ (push name instrumented-names)
+ (edebug-new-definition name))))
+ (eval-buffer)
+ (should (equal
+ (reverse instrumented-names)
+ ;; The generic function definitions come after the
+ ;; method definitions because their body ends later.
+ ;; FIXME: We'd rather have names such as
+ ;; `cl-defgeneric/edebug/method/1 ((_ number))', but
+ ;; that requires further changes to Edebug.
+ (list (intern "cl-defgeneric/edebug/method/1 (number)")
+ (intern "cl-defgeneric/edebug/method/1 (string)")
+ (intern "cl-defgeneric/edebug/method/1 :around (number)")
+ 'cl-defgeneric/edebug/method/1
+ (intern "cl-defgeneric/edebug/method/2 (number)")
+ 'cl-defgeneric/edebug/method/2))))))
+
(provide 'cl-generic-tests)
;;; cl-generic-tests.el ends here
diff --git a/test/lisp/emacs-lisp/cl-lib-tests.el b/test/lisp/emacs-lisp/cl-lib-tests.el
index 13c9af9bd6d..b19494af746 100644
--- a/test/lisp/emacs-lisp/cl-lib-tests.el
+++ b/test/lisp/emacs-lisp/cl-lib-tests.el
@@ -1,21 +1,21 @@
;;; cl-lib-tests.el --- tests for emacs-lisp/cl-lib.el -*- lexical-binding:t -*-
-;; Copyright (C) 2013-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2022 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
-;; This program is free software: you can redistribute it and/or
-;; modify it under the terms of the GNU General Public License as
-;; published by the Free Software Foundation, either version 3 of the
-;; License, or (at your option) any later version.
-;;
-;; This program is distributed in the hope that it will be useful, but
-;; WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-;; General Public License for more details.
-;;
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
;; You should have received a copy of the GNU General Public License
-;; along with this program. If not, see `https://www.gnu.org/licenses/'.
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
@@ -201,6 +201,10 @@
:b :a :a 42)
'(42 :a))))
+(ert-deftest cl-lib-empty-keyargs ()
+ (should-error (funcall (cl-function (lambda (&key) 1))
+ :b 1)))
+
(cl-defstruct (mystruct
(:constructor cl-lib--con-1 (&aux (abc 1)))
(:constructor cl-lib--con-2 (&optional def) "Constructor docstring."))
@@ -216,7 +220,7 @@
(should-error (cl-struct-slot-offset 'mystruct 'marypoppins))
(should (pcase (cl-struct-slot-info 'mystruct)
(`((cl-tag-slot) (abc 5 :readonly t)
- (def . ,(or `nil `(nil))))
+ (def . ,(or 'nil '(nil))))
t)))))
(ert-deftest cl-lib-struct-constructors ()
(should (string-match "\\`Constructor docstring."
@@ -238,6 +242,22 @@
(should (= (cl-the integer (cl-incf side-effect)) 1))
(should (= side-effect 1))))
+(ert-deftest cl-lib-test-incf ()
+ (let ((var 0))
+ (should (= (cl-incf var) 1))
+ (should (= var 1)))
+ (let ((alist))
+ (should (= (cl-incf (alist-get 'a alist 0)) 1))
+ (should (= (alist-get 'a alist 0) 1))))
+
+(ert-deftest cl-lib-test-decf ()
+ (let ((var 1))
+ (should (= (cl-decf var) 0))
+ (should (= var 0)))
+ (let ((alist))
+ (should (= (cl-decf (alist-get 'a alist 0)) -1))
+ (should (= (alist-get 'a alist 0) -1))))
+
(ert-deftest cl-lib-test-plusp ()
(should-not (cl-plusp -1.0e+INF))
(should-not (cl-plusp -1.5e2))
@@ -333,13 +353,6 @@
(should (= 5 (cl-fifth '(1 2 3 4 5 6))))
(should-error (cl-fifth "12345") :type 'wrong-type-argument))
-(ert-deftest cl-lib-test-fifth ()
- (should (null (cl-fifth '())))
- (should (null (cl-fifth '(1 2 3 4))))
- (should (= 5 (cl-fifth '(1 2 3 4 5))))
- (should (= 5 (cl-fifth '(1 2 3 4 5 6))))
- (should-error (cl-fifth "12345") :type 'wrong-type-argument))
-
(ert-deftest cl-lib-test-sixth ()
(should (null (cl-sixth '())))
(should (null (cl-sixth '(1 2 3 4 5))))
@@ -397,22 +410,6 @@
(should-error (cl-nth-value -1 (cl-values 2 3)) :type 'args-out-of-range)
(should (string= (cl-nth-value 0 "only lists") "only lists")))
-(ert-deftest cl-test-caaar ()
- (should (null (cl-caaar '())))
- (should (null (cl-caaar '(() (2)))))
- (should (null (cl-caaar '((() (2)) (a b)))))
- (should-error (cl-caaar '(1 2)) :type 'wrong-type-argument)
- (should-error (cl-caaar '((1 2))) :type 'wrong-type-argument)
- (should (= 1 (cl-caaar '(((1 2) (3 4))))))
- (should (null (cl-caaar '((() (3 4)))))))
-
-(ert-deftest cl-test-caadr ()
- (should (null (cl-caadr '())))
- (should (null (cl-caadr '(1))))
- (should-error (cl-caadr '(1 2)) :type 'wrong-type-argument)
- (should (= 2 (cl-caadr '(1 (2 3)))))
- (should (equal '((2) (3)) (cl-caadr '((1) (((2) (3))) (4))))))
-
(ert-deftest cl-test-ldiff ()
(let ((l '(1 2 3)))
(should (null (cl-ldiff '() '())))
@@ -512,15 +509,18 @@
(ert-deftest cl-lib-symbol-macrolet-2 ()
(should (equal (cl-lib-symbol-macrolet-4+5) (+ 4 5))))
-(defun cl-lib-tests--dummy-function ()
- ;; Dummy function to see if the file is compiled.
- t)
+
+(ert-deftest cl-lib-symbol-macrolet-hide ()
+ ;; bug#26325, bug#26073
+ (should (equal (let ((y 5))
+ (cl-symbol-macrolet ((x y))
+ (list x
+ (let ((x 6)) (list x y))
+ (cl-letf ((x 6)) (list x y))
+ (apply (lambda (x) (+ x 1)) (list 8)))))
+ '(5 (6 5) (6 6) 9))))
(ert-deftest cl-lib-defstruct-record ()
- ;; This test fails when compiled, see Bug#24402/27718.
- :expected-result (if (byte-code-function-p
- (symbol-function 'cl-lib-tests--dummy-function))
- :failed :passed)
(cl-defstruct foo x)
(let ((x (make-foo :x 42)))
(should (recordp x))
@@ -535,6 +535,7 @@
(should (eq (type-of x) 'vector))
(cl-old-struct-compat-mode 1)
+ (defvar cl-struct-foo)
(let ((cl-struct-foo (cl--struct-get-class 'foo)))
(setf (symbol-function 'cl-struct-foo) :quick-object-witness-check)
(should (eq (type-of x) 'foo))
@@ -550,4 +551,9 @@
(should cl-old-struct-compat-mode)
(cl-old-struct-compat-mode (if saved 1 -1))))
+(ert-deftest cl-constantly ()
+ (should (equal (mapcar (cl-constantly 3) '(a b c d))
+ '(3 3 3 3))))
+
+
;;; cl-lib-tests.el ends here
diff --git a/test/lisp/emacs-lisp/cl-macs-tests.el b/test/lisp/emacs-lisp/cl-macs-tests.el
index 575f170af6c..f742637ee35 100644
--- a/test/lisp/emacs-lisp/cl-macs-tests.el
+++ b/test/lisp/emacs-lisp/cl-macs-tests.el
@@ -1,21 +1,21 @@
;;; cl-macs-tests.el --- tests for emacs-lisp/cl-macs.el -*- lexical-binding:t -*-
-;; Copyright (C) 2017 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2022 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
-;; This program is free software: you can redistribute it and/or
-;; modify it under the terms of the GNU General Public License as
-;; published by the Free Software Foundation, either version 3 of the
-;; License, or (at your option) any later version.
-;;
-;; This program is distributed in the hope that it will be useful, but
-;; WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-;; General Public License for more details.
-;;
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
;; You should have received a copy of the GNU General Public License
-;; along with this program. If not, see `https://www.gnu.org/licenses/'.
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
@@ -23,14 +23,17 @@
(require 'cl-lib)
(require 'cl-macs)
+(require 'edebug)
(require 'ert)
+(require 'ert-x)
+(require 'pcase)
;;;; cl-loop tests -- many adapted from Steele's CLtL2
;;; ANSI 6.1.1.7 Destructuring
(ert-deftest cl-macs-loop-and-assignment ()
- ;; Bug#6583
+ "Bug#6583"
:expected-result :failed
(should (equal (cl-loop for numlist in '((1 2 4.0) (5 6 8.3) (8 9 10.4))
for a = (cl-first numlist)
@@ -39,6 +42,15 @@
collect (list c b a))
'((4.0 2 1) (8.3 6 5) (10.4 9 8)))))
+(ert-deftest cl-macs-loop-and-arrays ()
+ "Bug#40727"
+ (should (equal (cl-loop for y = (- (or x 0)) and x across [1 2]
+ collect (cons x y))
+ '((1 . 0) (2 . -1))))
+ (should (equal (cl-loop for x across [1 2] and y = (- (or x 0))
+ collect (cons x y))
+ '((1 . 0) (2 . -1)))))
+
(ert-deftest cl-macs-loop-destructure ()
(should (equal (cl-loop for (a b c) in '((1 2 4.0) (5 6 8.3) (8 9 10.4))
collect (list c b a))
@@ -61,7 +73,6 @@
;;; 6.1.2.1.1 The for-as-arithmetic subclause
(ert-deftest cl-macs-loop-for-as-arith ()
"Test various for-as-arithmetic subclauses."
- :expected-result :failed
(should (equal (cl-loop for i to 10 by 3 collect i)
'(0 3 6 9)))
(should (equal (cl-loop for i upto 3 collect i)
@@ -74,9 +85,9 @@
'(10 8 6)))
(should (equal (cl-loop for i from 10 downto 1 by 3 collect i)
'(10 7 4 1)))
- (should (equal (cl-loop for i above 0 by 2 downfrom 10 collect i)
+ (should (equal (cl-loop for i downfrom 10 above 0 by 2 collect i)
'(10 8 6 4 2)))
- (should (equal (cl-loop for i downto 10 from 15 collect i)
+ (should (equal (cl-loop for i from 15 downto 10 collect i)
'(15 14 13 12 11 10))))
(ert-deftest cl-macs-loop-for-as-arith-order-side-effects ()
@@ -417,7 +428,9 @@ collection clause."
'(2 3 4 5 6))))
(ert-deftest cl-macs-loop-across-ref ()
- (should (equal (cl-loop with my-vec = ["one" "two" "three"]
+ (should (equal (cl-loop with my-vec = (vector (cl-copy-seq "one")
+ (cl-copy-seq "two")
+ (cl-copy-seq "three"))
for x across-ref my-vec
do (setf (aref x 0) (upcase (aref x 0)))
finally return my-vec)
@@ -497,4 +510,297 @@ collection clause."
vconcat (vector (1+ x)))
[2 3 4 5 6])))
+(ert-deftest cl-macs-loop-for-as-equals-and ()
+ "Test for https://debbugs.gnu.org/29799 ."
+ (let ((arr (make-vector 3 0)))
+ (should (equal '((0 0) (1 1) (2 2))
+ (cl-loop for k below 3 for x = k and z = (elt arr k)
+ collect (list k x))))))
+
+
+(ert-deftest cl-defstruct/builtin-type ()
+ (should-error
+ (macroexpand '(cl-defstruct hash-table))
+ :type 'wrong-type-argument)
+ (should-error
+ (macroexpand '(cl-defstruct (hash-table (:predicate hash-table-p))))
+ :type 'wrong-type-argument))
+
+(ert-deftest cl-macs-test--symbol-macrolet ()
+ ;; A `setq' shouldn't be converted to a `setf' just because it occurs within
+ ;; a symbol-macrolet!
+ (should-error
+ ;; Use `eval' so the error is signaled when running the test rather than
+ ;; when macroexpanding it.
+ (eval '(let ((l (list 1))) (cl-symbol-macrolet ((x 1)) (setq (car l) 0))) t))
+ ;; Make sure `gv-synthetic-place' isn't macro-expanded before `setf' gets to
+ ;; see its `gv-expander'.
+ (should (equal (let ((l '(0)))
+ (let ((cl (car l)))
+ (cl-symbol-macrolet
+ ((p (gv-synthetic-place cl (lambda (v) `(setcar l ,v)))))
+ (cl-incf p)))
+ l)
+ '(1)))
+ ;; Make sure `gv-synthetic-place' isn't macro-expanded before
+ ;; `cl-letf' gets to see its `gv-expander'.
+ (should (equal
+ (condition-case err
+ (let ((x 1))
+ (list x
+ (cl-letf (((gv-synthetic-place (+ 1 2)
+ (lambda (v) `(setq x ,v)))
+ 7))
+ x)
+ x))
+ (error err))
+ '(1 7 3)))
+ (should (equal
+ (let ((x (list 42)))
+ (cl-symbol-macrolet ((m (car x)))
+ (list m
+ (cl-letf ((m 5)) m)
+ m)))
+ '(42 5 42))))
+
+(ert-deftest cl-macs-loop-conditional-step-clauses ()
+ "These tests failed under the initial fixes in #bug#29799."
+ (should (cl-loop for i from 1 upto 100 and j = 1 then (1+ j)
+ if (not (= i j))
+ return nil
+ end
+ until (> j 10)
+ finally return t))
+
+ (should (equal (let* ((size 7)
+ (arr (make-vector size 0)))
+ (cl-loop for k below size
+ for x = (* 2 k) and y = (1+ (elt arr k))
+ collect (list k x y)))
+ '((0 0 1) (1 2 1) (2 4 1) (3 6 1) (4 8 1) (5 10 1) (6 12 1))))
+
+ (should (equal (cl-loop for x below 3
+ for y below 2 and z = 1
+ collect x)
+ '(0 1)))
+
+ (should (equal (cl-loop for x below 3
+ and y below 2
+ collect x)
+ '(0 1)))
+
+ ;; this is actually disallowed in clisp, but is semantically consistent
+ (should (equal (cl-loop with result
+ for x below 3
+ for y = (progn (push x result) x) and z = 1
+ append (list x y) into result1
+ finally return (append result result1))
+ '(2 1 0 0 0 1 1 2 2)))
+
+ (should (equal (cl-loop with result
+ for x below 3
+ for _y = (progn (push x result))
+ finally return result)
+ '(2 1 0)))
+
+ ;; this unintuitive result is replicated by clisp
+ (should (equal (cl-loop with result
+ for x below 3
+ and y = (progn (push x result))
+ finally return result)
+ '(2 1 0 0)))
+
+ ;; this unintuitive result is replicated by clisp
+ (should (equal (cl-loop with result
+ for x below 3
+ and y = (progn (push x result)) then (progn (push (1+ x) result))
+ finally return result)
+ '(3 2 1 0)))
+
+ (should (cl-loop with result
+ for x below 3
+ for y = (progn (push x result) x) then (progn (push (1+ x) result) (1+ x))
+ and z = 1
+ collect y into result1
+ finally return (equal (nreverse result) result1))))
+
+(ert-deftest cl-macs-aux-edebug ()
+ "Check that Bug#40431 is fixed."
+ (with-temp-buffer
+ (prin1 '(cl-defun cl-macs-aux-edebug-test-fun (&aux ((a . b) '(1 . 2)))
+ (list a b))
+ (current-buffer))
+ ;; Just make sure the function can be instrumented.
+ (edebug-defun)))
+
+;;; cl-labels
+
+(ert-deftest cl-macs--labels ()
+ ;; Simple recursive function.
+ (cl-labels ((len (xs) (if xs (1+ (len (cdr xs))) 0)))
+ (should (equal (len (make-list 42 t)) 42)))
+
+ (let ((list-42 (make-list 42 t))
+ (list-42k (make-list 42000 t)))
+
+ (cl-labels
+ ;; Simple tail-recursive function.
+ ((len (xs n) (if xs (len (cdr xs) (1+ n)) n))
+ ;; Slightly obfuscated version to exercise tail calls from
+ ;; `let', `progn', `and' and `or'.
+ (len2 (xs n) (or (and (not xs) n)
+ (let (n1)
+ (and xs
+ (progn (setq n1 (1+ n))
+ (len2 (cdr xs) n1))))))
+ ;; Tail calls in error and success handlers.
+ (len3 (xs n)
+ (if xs
+ (condition-case k
+ (/ 1 (logand n 1))
+ (arith-error (len3 (cdr xs) (1+ n)))
+ (:success (len3 (cdr xs) (+ n k))))
+ n))
+
+ ;; Tail calls in `cond'.
+ (len4 (xs n)
+ (cond (xs (cond (nil 'nevertrue)
+ ((len4 (cdr xs) (1+ n)))))
+ (t n))))
+ (should (equal (len nil 0) 0))
+ (should (equal (len2 nil 0) 0))
+ (should (equal (len3 nil 0) 0))
+ (should (equal (len4 nil 0) 0))
+ (should (equal (len list-42 0) 42))
+ (should (equal (len2 list-42 0) 42))
+ (should (equal (len3 list-42 0) 42))
+ (should (equal (len4 list-42 0) 42))
+ ;; Should not bump into stack depth limits.
+ (should (equal (len list-42k 0) 42000))
+ (should (equal (len2 list-42k 0) 42000))
+ (should (equal (len3 list-42k 0) 42000))
+ (should (equal (len4 list-42k 0) 42000))))
+
+ ;; Check that non-recursive functions are handled more efficiently.
+ (should (pcase (macroexpand '(cl-labels ((f (x) (+ x 1))) (f 5)))
+ (`(let* ,_ (funcall ,_ 5)) t)))
+
+ ;; Case of "tail-recursive lambdas".
+ (should (pcase (macroexpand
+ '(cl-labels ((len (xs n) (if xs (len (cdr xs) (1+ n)) n)))
+ #'len))
+ (`(function (lambda (,_ ,_) . ,_)) t)))
+
+ ;; Verify that there is no tail position inside dynamic variable bindings.
+ (defvar dyn-var)
+ (let ((dyn-var 'a))
+ (cl-labels ((f (x) (if x
+ dyn-var
+ (let ((dyn-var 'b))
+ (f dyn-var)))))
+ (should (equal (f nil) 'b))))
+
+ ;; Control: same as above but with lexical binding.
+ (let ((lex-var 'a))
+ (cl-labels ((f (x) (if x
+ lex-var
+ (let ((lex-var 'b))
+ (f lex-var)))))
+ (should (equal (f nil) 'a)))))
+
+(ert-deftest cl-macs--progv ()
+ (defvar cl-macs--test)
+ (defvar cl-macs--test1)
+ (defvar cl-macs--test2)
+ (should (= (cl-progv '(cl-macs--test cl-macs--test) '(1 2) cl-macs--test) 2))
+ (should (equal (cl-progv '(cl-macs--test1 cl-macs--test2) '(1 2)
+ (list cl-macs--test1 cl-macs--test2))
+ '(1 2))))
+
+(ert-deftest cl-define-compiler-macro/edebug ()
+ "Check that we can instrument compiler macros."
+ (with-temp-buffer
+ (dolist (form '((defun cl-define-compiler-macro/edebug (a b) nil)
+ (cl-define-compiler-macro
+ cl-define-compiler-macro/edebug
+ (&whole w a b)
+ w)))
+ (print form (current-buffer)))
+ (let ((edebug-all-defs t)
+ (edebug-initial-mode 'Go-nonstop))
+ ;; Just make sure the forms can be instrumented.
+ (eval-buffer))))
+
+(ert-deftest cl-defstruct/edebug ()
+ "Check that we can instrument `cl-defstruct' forms."
+ (with-temp-buffer
+ (dolist (form '((cl-defstruct cl-defstruct/edebug/1)
+ (cl-defstruct (cl-defstruct/edebug/2
+ :noinline))
+ (cl-defstruct (cl-defstruct/edebug/3
+ (:noinline t)))
+ (cl-defstruct (cl-defstruct/edebug/4
+ :named))
+ (cl-defstruct (cl-defstruct/edebug/5
+ (:named t)))))
+ (print form (current-buffer)))
+ (let ((edebug-all-defs t)
+ (edebug-initial-mode 'Go-nonstop))
+ ;; Just make sure the forms can be instrumented.
+ (eval-buffer))))
+
+(ert-deftest cl-case-error ()
+ "Test that `cl-case' and `cl-ecase' signal an error if a t or
+`otherwise' key is misplaced."
+ (let ((text-quoting-style 'grave))
+ (dolist (form '((cl-case val (t 1) (123 2))
+ (cl-ecase val (t 1) (123 2))
+ (cl-ecase val (123 2) (t 1))))
+ (ert-info ((prin1-to-string form) :prefix "Form: ")
+ (let ((error (should-error (macroexpand form))))
+ (should (equal (cdr error)
+ '("Misplaced t or `otherwise' clause"))))))))
+
+(ert-deftest cl-case-warning ()
+ "Test that `cl-case' and `cl-ecase' warn about suspicious
+constructs."
+ (let ((text-quoting-style 'grave))
+ (pcase-dolist (`(,case . ,message)
+ `((nil . "Case nil will never match")
+ ('nil . ,(concat "Case 'nil will match `quote'. "
+ "If that's intended, write "
+ "(nil quote) instead. "
+ "Otherwise, don't quote `nil'."))
+ ('t . ,(concat "Case 't will match `quote'. "
+ "If that's intended, write "
+ "(t quote) instead. "
+ "Otherwise, don't quote `t'."))
+ ('foo . ,(concat "Case 'foo will match `quote'. "
+ "If that's intended, write "
+ "(foo quote) instead. "
+ "Otherwise, don't quote `foo'."))
+ (#'foo . ,(concat "Case #'foo will match "
+ "`function'. If that's "
+ "intended, write (foo function) "
+ "instead. Otherwise, don't "
+ "quote `foo'."))))
+ (dolist (macro '(cl-case cl-ecase))
+ (let ((form `(,macro val (,case 1))))
+ (ert-info ((prin1-to-string form) :prefix "Form: ")
+ (ert-with-message-capture messages
+ (macroexpand form)
+ (should (equal messages
+ (concat "Warning: " message "\n"))))))))))
+
+(ert-deftest cl-case-no-warning ()
+ "Test that `cl-case' and `cl-ecase' don't warn in some valid cases.
+See Bug#57915."
+ (dolist (case '(quote (quote) function (function)))
+ (dolist (macro '(cl-case cl-ecase))
+ (let ((form `(,macro val (,case 1))))
+ (ert-info ((prin1-to-string form) :prefix "Form: ")
+ (ert-with-message-capture messages
+ (macroexpand form)
+ (should (string-empty-p messages))))))))
+
;;; cl-macs-tests.el ends here
diff --git a/test/lisp/emacs-lisp/cl-preloaded-tests.el b/test/lisp/emacs-lisp/cl-preloaded-tests.el
new file mode 100644
index 00000000000..43cd7b6bff1
--- /dev/null
+++ b/test/lisp/emacs-lisp/cl-preloaded-tests.el
@@ -0,0 +1,33 @@
+;;; cl-preloaded-tests.el --- unit tests for cl-preloaded.el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2017-2022 Free Software Foundation, Inc.
+;; Author: Philipp Stephani <phst@google.com>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Unit tests for lisp/emacs-lisp/cl-preloaded.el.
+
+;;; Code:
+
+(ert-deftest cl-struct-define/builtin-type ()
+ (should-error
+ (cl-struct-define 'hash-table nil nil 'record nil nil
+ 'cl-preloaded-tests-tag 'cl-preloaded-tests nil)
+ :type 'wrong-type-argument))
+
+;;; cl-preloaded-tests.el ends here
diff --git a/test/lisp/emacs-lisp/cl-print-tests.el b/test/lisp/emacs-lisp/cl-print-tests.el
index a5dd5abf46b..57fe52a948e 100644
--- a/test/lisp/emacs-lisp/cl-print-tests.el
+++ b/test/lisp/emacs-lisp/cl-print-tests.el
@@ -1,6 +1,6 @@
;;; cl-print-tests.el --- Test suite for the cl-print facility. -*- lexical-binding:t -*-
-;; Copyright (C) 2017 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2022 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -19,40 +19,146 @@
;;; Commentary:
+;; See test/src/print-tests.el for tests which apply to both
+;; cl-print.el and src/print.c.
+
;;; Code:
(require 'ert)
-(cl-defstruct cl-print--test a b)
+(cl-defstruct (cl-print-tests-struct
+ (:constructor cl-print-tests-con))
+ a b c d e)
-(ert-deftest cl-print-tests-1 ()
- "Test cl-print code."
- (let ((x (make-cl-print--test :a 1 :b 2)))
- (let ((print-circle nil))
- (should (equal (cl-prin1-to-string `((x . ,x) (y . ,x)))
- "((x . #s(cl-print--test :a 1 :b 2)) (y . #s(cl-print--test :a 1 :b 2)))")))
- (let ((print-circle t))
- (should (equal (cl-prin1-to-string `((x . ,x) (y . ,x)))
- "((x . #1=#s(cl-print--test :a 1 :b 2)) (y . #1#))")))
- (should (string-match "\\`#f(compiled-function (x) \"[^\"]+\" [^\)]*)\\'"
- (cl-prin1-to-string (symbol-function #'caar))))))
-
-(ert-deftest cl-print-tests-2 ()
- (let ((x (record 'foo 1 2 3)))
- (should (equal
- x
- (car (read-from-string (with-output-to-string (prin1 x))))))
- (let ((print-circle t))
- (should (string-match
- "\\`(#1=#s(foo 1 2 3) #1#)\\'"
- (cl-prin1-to-string (list x x)))))))
+(ert-deftest cl-print-tests-ellipsis-cons ()
+ "Ellipsis expansion works in conses."
+ (let ((print-length 4)
+ (print-level 3))
+ (cl-print-tests-check-ellipsis-expansion
+ '(0 1 2 3 4 5) "(0 1 2 3 ...)" "4 5")
+ (cl-print-tests-check-ellipsis-expansion
+ '(0 1 2 3 4 5 6 7 8 9) "(0 1 2 3 ...)" "4 5 6 7 ...")
+ (cl-print-tests-check-ellipsis-expansion
+ '(a (b (c (d (e))))) "(a (b (c ...)))" "(d (e))")
+ (cl-print-tests-check-ellipsis-expansion
+ (let ((x (make-list 6 'b)))
+ (setf (nthcdr 6 x) 'c)
+ x)
+ "(b b b b ...)" "b b . c")))
-(ert-deftest cl-print-circle ()
- (let ((x '(#1=(a . #1#) #1#)))
+(ert-deftest cl-print-tests-ellipsis-vector ()
+ "Ellipsis expansion works in vectors."
+ (let ((print-length 4)
+ (print-level 3))
+ (cl-print-tests-check-ellipsis-expansion
+ [0 1 2 3 4 5] "[0 1 2 3 ...]" "4 5")
+ (cl-print-tests-check-ellipsis-expansion
+ [0 1 2 3 4 5 6 7 8 9] "[0 1 2 3 ...]" "4 5 6 7 ...")
+ (cl-print-tests-check-ellipsis-expansion
+ [a [b [c [d [e]]]]] "[a [b [c ...]]]" "[d [e]]")))
+
+(ert-deftest cl-print-tests-ellipsis-string ()
+ "Ellipsis expansion works in strings."
+ (let ((print-length 4)
+ (print-level 3))
+ (cl-print-tests-check-ellipsis-expansion
+ "abcdefg" "\"abcd...\"" "efg")
+ (cl-print-tests-check-ellipsis-expansion
+ "abcdefghijk" "\"abcd...\"" "efgh...")
+ (cl-print-tests-check-ellipsis-expansion
+ '(1 (2 (3 #("abcde" 0 5 (test t)))))
+ "(1 (2 (3 ...)))" "#(\"abcd...\" 0 5 (test t))")
+ (cl-print-tests-check-ellipsis-expansion
+ #("abcd" 0 1 (bold t) 1 2 (invisible t) 3 4 (italic t))
+ "#(\"abcd\" 0 1 (bold t) ...)" "1 2 (invisible t) ...")))
+
+(ert-deftest cl-print-tests-ellipsis-struct ()
+ "Ellipsis expansion works in structures."
+ (let ((print-length 4)
+ (print-level 3)
+ (struct (cl-print-tests-con)))
+ (cl-print-tests-check-ellipsis-expansion
+ struct "#s(cl-print-tests-struct :a nil :b nil :c nil :d nil ...)" ":e nil")
+ (let ((print-length 2))
+ (cl-print-tests-check-ellipsis-expansion
+ struct "#s(cl-print-tests-struct :a nil :b nil ...)" ":c nil :d nil ..."))
+ (cl-print-tests-check-ellipsis-expansion
+ `(a (b (c ,struct)))
+ "(a (b (c ...)))"
+ "#s(cl-print-tests-struct :a nil :b nil :c nil :d nil ...)")))
+
+(ert-deftest cl-print-tests-ellipsis-circular ()
+ "Ellipsis expansion works with circular objects."
+ (let ((wide-obj (list 0 1 2 3 4))
+ (deep-obj `(0 (1 (2 (3 (4))))))
+ (print-length 4)
+ (print-level 3))
+ (setf (nth 4 wide-obj) wide-obj)
+ (setf (car (cadadr (cadadr deep-obj))) deep-obj)
(let ((print-circle nil))
- (should (string-match "\\`((a . #[0-9]) (a . #[0-9]))\\'"
- (cl-prin1-to-string x))))
+ (cl-print-tests-check-ellipsis-expansion-rx
+ wide-obj (regexp-quote "(0 1 2 3 ...)") "\\`#[0-9]\\'")
+ (cl-print-tests-check-ellipsis-expansion-rx
+ deep-obj (regexp-quote "(0 (1 (2 ...)))") "\\`(3 (#[0-9]))\\'"))
(let ((print-circle t))
- (should (equal "(#1=(a . #1#) #1#)" (cl-prin1-to-string x))))))
+ (cl-print-tests-check-ellipsis-expansion
+ wide-obj "#1=(0 1 2 3 ...)" "#1#")
+ (cl-print-tests-check-ellipsis-expansion
+ deep-obj "#1=(0 (1 (2 ...)))" "(3 (#1#))"))))
+
+(defun cl-print-tests-check-ellipsis-expansion (obj expected expanded)
+ (let* ((result (cl-prin1-to-string obj))
+ (pos (next-single-property-change 0 'cl-print-ellipsis result))
+ value)
+ (should pos)
+ (setq value (get-text-property pos 'cl-print-ellipsis result))
+ (should (equal expected result))
+ (should (equal expanded (with-output-to-string (cl-print-expand-ellipsis
+ value nil))))))
+
+(defun cl-print-tests-check-ellipsis-expansion-rx (obj expected expanded)
+ (let* ((result (cl-prin1-to-string obj))
+ (pos (next-single-property-change 0 'cl-print-ellipsis result))
+ (value (get-text-property pos 'cl-print-ellipsis result)))
+ (should (string-match expected result))
+ (should (string-match expanded (with-output-to-string
+ (cl-print-expand-ellipsis value nil))))))
+
+(ert-deftest cl-print-tests-print-to-string-with-limit ()
+ (let* ((thing10 (make-list 10 'a))
+ (thing100 (make-list 100 'a))
+ (thing10x10 (make-list 10 thing10))
+ (nested-thing (let ((val 'a))
+ (dotimes (_i 20)
+ (setq val (list val)))
+ val))
+ ;; Make a consistent environment for this test.
+ (print-circle nil)
+ (print-level nil)
+ (print-length nil))
+
+ ;; Print something that fits in the space given.
+ (should (string= (cl-prin1-to-string thing10)
+ (cl-print-to-string-with-limit #'cl-prin1 thing10 100)))
+
+ ;; Print something which needs to be abbreviated and which can be.
+ (should (< (length (cl-print-to-string-with-limit #'cl-prin1 thing100 100))
+ 100
+ (length (cl-prin1-to-string thing100))))
+
+ ;; Print something resistant to easy abbreviation.
+ (should (string= (cl-prin1-to-string thing10x10)
+ (cl-print-to-string-with-limit #'cl-prin1 thing10x10 100)))
+
+ ;; Print something which should be abbreviated even if the limit is large.
+ (should (< (length (cl-print-to-string-with-limit #'cl-prin1 nested-thing 1000))
+ (length (cl-prin1-to-string nested-thing))))
+
+ ;; Print with no limits.
+ (dolist (thing (list thing10 thing100 thing10x10 nested-thing))
+ (let ((rep (cl-prin1-to-string thing)))
+ (should (string= rep (cl-print-to-string-with-limit #'cl-prin1 thing 0)))
+ (should (string= rep (cl-print-to-string-with-limit #'cl-prin1 thing nil)))))))
+
;;; cl-print-tests.el ends here.
diff --git a/test/lisp/emacs-lisp/cl-seq-tests.el b/test/lisp/emacs-lisp/cl-seq-tests.el
index 8c0d55663ca..f42ae69873f 100644
--- a/test/lisp/emacs-lisp/cl-seq-tests.el
+++ b/test/lisp/emacs-lisp/cl-seq-tests.el
@@ -1,6 +1,6 @@
;;; cl-seq-tests.el --- Tests for cl-seq.el functionality -*- lexical-binding: t; -*-
-;; Copyright (C) 2015-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2022 Free Software Foundation, Inc.
;; Author: Nicolas Richard <youngfrog@members.fsf.org>
@@ -294,6 +294,7 @@ Body are forms defining the test."
(ert-deftest cl-seq-test-bug24264 ()
"Test for https://debbugs.gnu.org/24264 ."
+ :tags '(:expensive-test)
(let ((list (append (make-list 8000005 1) '(8)))
(list2 (make-list 8000005 2)))
(should (cl-position 8 list))
@@ -302,6 +303,14 @@ Body are forms defining the test."
(should (equal '(2 8) (last (cl-replace list list2) 2)))
(should (equal '(1 1) (last (cl-fill list 1) 2)))))
+(ert-deftest cl-seq-bignum-eql ()
+ (let ((x (+ most-positive-fixnum 1))
+ (y (+ most-positive-fixnum 1)))
+ (let ((l (list y)))
+ (should (eq (cl-member x l) l)))
+ (let ((a (list (cons y 1) (cons 2 y))))
+ (should (eq (cl-assoc x a) (car a)))
+ (should (eq (cl-rassoc x a) (cadr a))))))
(provide 'cl-seq-tests)
;;; cl-seq-tests.el ends here
diff --git a/test/lisp/emacs-lisp/comp-cstr-tests.el b/test/lisp/emacs-lisp/comp-cstr-tests.el
new file mode 100644
index 00000000000..ba7ab6331ef
--- /dev/null
+++ b/test/lisp/emacs-lisp/comp-cstr-tests.el
@@ -0,0 +1,233 @@
+;;; comp-cstr-tests.el --- unit tests for src/comp.c -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+;; Author: Andrea Corallo <akrl@sdf.org>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Unit tests for lisp/emacs-lisp/comp-cstr.el
+
+;;; Code:
+
+(require 'ert)
+(require 'cl-lib)
+(require 'comp-cstr)
+
+(cl-eval-when (compile eval load)
+
+ (defun comp-cstr-test-ts (type-spec)
+ "Create a constraint from TYPE-SPEC and convert it back to type specifier."
+ (let ((comp-ctxt (make-comp-cstr-ctxt)))
+ (comp-cstr-to-type-spec (comp-type-spec-to-cstr type-spec))))
+
+ (defun comp-cstr-typespec-test (number type-spec expected-type-spec)
+ `(ert-deftest ,(intern (concat "comp-cstr-test-" (int-to-string number))) ()
+ (should (equal (comp-cstr-test-ts ',type-spec)
+ ',expected-type-spec))))
+
+ (defconst comp-cstr-typespec-tests-alist
+ `(;; 1
+ (symbol . symbol)
+ ;; 2
+ ((or string array) . array)
+ ;; 3
+ ((or symbol number) . (or number symbol))
+ ;; 4
+ ((or cons atom) . (or atom cons)) ;; SBCL return T
+ ;; 5
+ ((or integer number) . number)
+ ;; 6
+ ((or (or integer symbol) number) . (or number symbol))
+ ;; 7
+ ((or (or integer symbol) (or number list)) . (or list number symbol))
+ ;; 8
+ ((or (or integer number) nil) . number)
+ ;; 9
+ ((member foo) . (member foo))
+ ;; 10
+ ((member foo bar) . (member bar foo))
+ ;; 11
+ ((or (member foo) (member bar)) . (member bar foo))
+ ;; 12
+ ((or (member foo) symbol) . symbol) ;; SBCL return (OR SYMBOL (MEMBER FOO))
+ ;; 13
+ ((or (member foo) number) . (or (member foo) number))
+ ;; 14
+ ((or (integer 1 3) number) . number)
+ ;; 15
+ (integer . integer)
+ ;; 16
+ ((integer 1 2) . (integer 1 2))
+ ;; 17
+ ((or (integer -1 0) (integer 3 4)) . (or (integer -1 0) (integer 3 4)))
+ ;; 18
+ ((or (integer -1 2) (integer 3 4)) . (integer -1 4))
+ ;; 19
+ ((or (integer -1 3) (integer 3 4)) . (integer -1 4))
+ ;; 20
+ ((or (integer -1 4) (integer 3 4)) . (integer -1 4))
+ ;; 21
+ ((or (integer -1 5) (integer 3 4)) . (integer -1 5))
+ ;; 22
+ ((or (integer -1 *) (integer 3 4)) . (integer -1 *))
+ ;; 23
+ ((or (integer -1 2) (integer * 4)) . (integer * 4))
+ ;; 24
+ ((and string array) . string)
+ ;; 25
+ ((and cons atom) . nil)
+ ;; 26
+ ((and (member foo) (member foo bar baz)) . (member foo))
+ ;; 27
+ ((and (member foo) (member bar)) . nil)
+ ;; 28
+ ((and (member foo) symbol) . (member foo))
+ ;; 29
+ ((and (member foo) string) . nil)
+ ;; 30
+ ((and (member foo) (integer 1 2)) . nil)
+ ;; 31
+ ((and (member 1 2) (member 3 2)) . (integer 2 2))
+ ;; 32
+ ((and number (integer 1 2)) . (integer 1 2))
+ ;; 33
+ ((and integer (integer 1 2)) . (integer 1 2))
+ ;; 34
+ ((and (integer -1 0) (integer 3 5)) . nil)
+ ;; 35
+ ((and (integer -1 2) (integer 3 5)) . nil)
+ ;; 36
+ ((and (integer -1 3) (integer 3 5)) . (integer 3 3))
+ ;; 37
+ ((and (integer -1 4) (integer 3 5)) . (integer 3 4))
+ ;; 38
+ ((and (integer -1 5) nil) . nil)
+ ;; 39
+ ((not symbol) . (not symbol))
+ ;; 40
+ ((or (member foo) (not (member foo bar))) . (not (member bar)))
+ ;; 41
+ ((or (member foo bar) (not (member foo))) . t)
+ ;; 42
+ ((or symbol (not sequence)) . (not sequence))
+ ;; 43
+ ((or symbol (not symbol)) . t)
+ ;; 44
+ ((or symbol (not sequence)) . (not sequence))
+ ;; 45 Conservative.
+ ((or vector (not sequence)) . t)
+ ;; 46
+ ((or (integer 1 10) (not (integer * 5))) . (not (integer * 0)))
+ ;; 47
+ ((or symbol (integer 1 10) (not (integer * 5))) . (not (integer * 0)))
+ ;; 48
+ ((or (not symbol) (integer 1 10) (not (integer * 5))) . (not (or symbol (integer * 0))))
+ ;; 49
+ ((or symbol (not (member foo))) . (not (member foo)))
+ ;; 50
+ ((or (not symbol) (not (member foo))) . (not symbol))
+ ;; 51 Conservative.
+ ((or (not (member foo)) string) . (not (member foo)))
+ ;; 52 Conservative.
+ ((or (member foo) (not string)) . (not string))
+ ;; 53
+ ((or (not (integer 1 2)) integer) . t)
+ ;; 54
+ ((or (not (integer 1 2)) (not integer)) . (not integer))
+ ;; 55
+ ((or (integer 1 2) (not integer)) . (not (or (integer * 0) (integer 3 *))))
+ ;; 56
+ ((or number (not (integer 1 2))) . t)
+ ;; 57
+ ((or atom (not (integer 1 2))) . t)
+ ;; 58
+ ((or atom (not (member foo))) . t)
+ ;; 59
+ ((and symbol (not cons)) . symbol)
+ ;; 60
+ ((and symbol (not symbol)) . nil)
+ ;; 61
+ ((and atom (not symbol)) . atom)
+ ;; 62
+ ((and atom (not string)) . (or array sequence atom))
+ ;; 63 Conservative
+ ((and symbol (not (member foo))) . symbol)
+ ;; 64 Conservative
+ ((and symbol (not (member 3))) . symbol)
+ ;; 65
+ ((and (not (member foo)) (integer 1 10)) . (integer 1 10))
+ ;; 66
+ ((and (member foo) (not (integer 1 10))) . (member foo))
+ ;; 67
+ ((and t (not (member foo))) . (not (member foo)))
+ ;; 68
+ ((and integer (not (integer 3 4))) . (or (integer * 2) (integer 5 *)))
+ ;; 69
+ ((and (integer 0 20) (not (integer 5 10))) . (or (integer 0 4) (integer 11 20)))
+ ;; 70
+ ((and (not (member a)) (not (member b))) . (not (member a b)))
+ ;; 71
+ ((and (not boolean) (not (member b))) . (not (or (member b) boolean)))
+ ;; 72
+ ((and t (integer 1 1)) . (integer 1 1))
+ ;; 73
+ ((not (integer -1 5)) . (not (integer -1 5)))
+ ;; 74
+ ((and boolean (or number marker)) . nil)
+ ;; 75
+ ((and atom (or number marker)) . (or marker number))
+ ;; 76
+ ((and symbol (or number marker)) . nil)
+ ;; 77
+ ((and (or symbol string) (or number marker)) . nil)
+ ;; 78
+ ((and t t) . t)
+ ;; 79
+ ((and (or marker number) (integer 0 0)) . (integer 0 0))
+ ;; 80
+ ((and t (not t)) . nil)
+ ;; 81
+ ((or (integer 1 1) (not (integer 1 1))) . t)
+ ;; 82
+ ((not t) . nil)
+ ;; 83
+ ((not nil) . t)
+ ;; 84
+ ((or (not string) t) . t)
+ ;; 85
+ ((or (not vector) sequence) . sequence)
+ ;; 86
+ ((or (not symbol) null) . t)
+ ;; 87
+ ((and (or null integer) (not (or null integer))) . nil)
+ ;; 88
+ ((and (or (member a b c)) (not (or (member a b)))) . (member c)))
+ "Alist type specifier -> expected type specifier."))
+
+(defmacro comp-cstr-synthesize-tests ()
+ "Generate all tests from `comp-cstr-typespec-tests-alist'."
+ `(progn
+ ,@(cl-loop
+ for i from 1
+ for (ts . exp-ts) in comp-cstr-typespec-tests-alist
+ append (list (comp-cstr-typespec-test i ts exp-ts)))))
+
+(comp-cstr-synthesize-tests)
+
+;;; comp-cstr-tests.el ends here
diff --git a/test/lisp/emacs-lisp/copyright-tests.el b/test/lisp/emacs-lisp/copyright-tests.el
new file mode 100644
index 00000000000..b00d697aa64
--- /dev/null
+++ b/test/lisp/emacs-lisp/copyright-tests.el
@@ -0,0 +1,96 @@
+;;; copyright-tests.el --- tests for copyright.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'cl-lib)
+(require 'copyright)
+
+(defmacro with-copyright-test (orig result)
+ `(cl-letf (((symbol-function 'format-time-string) (lambda (&rest _) "2019")))
+ (let ((copyright-query nil)
+ (copyright-current-year 2019))
+ (with-temp-buffer
+ (insert ,orig)
+ (copyright-update)
+ (should (equal (buffer-string) ,result))))))
+
+(defvar copyright-tests--data
+ '((";; Copyright (C) 2017 Free Software Foundation, Inc."
+ . ";; Copyright (C) 2017, 2019 Free Software Foundation, Inc.")
+ (";; Copyright (C) 2017-2018 Free Software Foundation, Inc."
+ . ";; Copyright (C) 2017-2019 Free Software Foundation, Inc.")
+ (";; Copyright (C) 2017–2018 Free Software Foundation, Inc."
+ . ";; Copyright (C) 2017–2019 Free Software Foundation, Inc.")
+ (";; Copyright (C) 2005-2006, 2015, 2017-2018 Free Software Foundation, Inc."
+ . ";; Copyright (C) 2005-2006, 2015, 2017-2019 Free Software Foundation, Inc.")
+ (";; Copyright (C) 2005–2006, 2015, 2017–2018 Free Software Foundation, Inc."
+ . ";; Copyright (C) 2005–2006, 2015, 2017–2019 Free Software Foundation, Inc.")
+ (";; copyright '18 FSF"
+ . ";; copyright '18, '19 FSF")))
+
+(ert-deftest test-copyright-update ()
+ (dolist (test copyright-tests--data)
+ (with-copyright-test (car test) (cdr test))))
+
+(ert-deftest test-end-chop ()
+ (should
+ (equal
+ (with-temp-buffer
+ (let ((copyright-query nil))
+ (insert (make-string (- copyright-limit 14) ?x) "\n"
+ "\nCopyright 2006, 2007, 2008 Foo Bar\n\n")
+ (copyright-update)
+ (buffer-substring (- (point-max) 42) (point-max))))
+ "Copyright 2006, 2007, 2008, 2022 Foo Bar\n\n")))
+
+(ert-deftest test-correct-notice ()
+ (should (equal
+ (with-temp-buffer
+ (dotimes (_ 2)
+ (insert "Copyright 2021 FSF\n"))
+ (let ((copyright-at-end-flag t)
+ (copyright-query nil))
+ (copyright-update))
+ (buffer-string))
+ "Copyright 2021 FSF\nCopyright 2021, 2022 FSF\n")))
+
+(defmacro with-copyright-fix-years-test (orig result)
+ `(let ((copyright-year-ranges t))
+ (with-temp-buffer
+ (insert ,orig)
+ (copyright-fix-years)
+ (should (equal (buffer-string) ,result)))))
+
+(defvar copyright-fix-years-tests--data
+ '((";; Copyright (C) 2008, 2010, 2012"
+ . ";; Copyright (C) 2008, 2010, 2012")
+ (";; Copyright (C) 2008, 2009, 2010, 2013, 2014, 2015, 2016, 2018"
+ . ";; Copyright (C) 2008-2010, 2013-2016, 2018")
+ (";; Copyright (C) 2008-2010, 2011, 2015, 2016, 2017"
+ . ";; Copyright (C) 2008-2010, 2011, 2015-2017")))
+
+(ert-deftest text-copyright-fix-years ()
+ "Test basics of \\[copyright-fix-years]."
+ (dolist (test copyright-fix-years-tests--data)
+ (with-copyright-fix-years-test (car test) (cdr test))))
+
+(provide 'copyright-tests)
+;;; copyright-tests.el ends here
diff --git a/test/lisp/emacs-lisp/derived-tests.el b/test/lisp/emacs-lisp/derived-tests.el
new file mode 100644
index 00000000000..547b16843d4
--- /dev/null
+++ b/test/lisp/emacs-lisp/derived-tests.el
@@ -0,0 +1,64 @@
+;;; derived-tests.el --- tests for derived.el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2017-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+
+(define-derived-mode derived-tests--parent-mode prog-mode "P"
+ :after-hook
+ (let ((f (let ((x "S")) (lambda () x))))
+ (insert (format "AFP=%s " (let ((x "D")) x (funcall f)))))
+ (insert "PB "))
+
+(define-derived-mode derived-tests--child-mode derived-tests--parent-mode "C"
+ :after-hook
+ (let ((f (let ((x "S")) (lambda () x))))
+ (insert (format "AFC=%s " (let ((x "D")) x (funcall f)))))
+ (insert "CB "))
+
+(ert-deftest derived-tests-after-hook-lexical ()
+ (with-temp-buffer
+ (let ((derived-tests--child-mode-hook
+ (lambda () (insert "MH "))))
+ (derived-tests--child-mode)
+ (should (equal (buffer-string) "PB CB MH AFP=S AFC=S ")))))
+
+(declare-function mode-a "derived-tests")
+(declare-function mode-b "derived-tests")
+(declare-function mode-c "derived-tests")
+(ert-deftest test-add-font-lock ()
+ (define-derived-mode mode-a fundamental-mode "mode-a"
+ (font-lock-add-keywords nil `(("a" 0 'font-lock-keyword-face))))
+ (define-derived-mode mode-b mode-a "mode-b"
+ (font-lock-add-keywords nil `(("b" 0 'font-lock-builtin-face))))
+ (define-derived-mode mode-c mode-b "mode-c"
+ (font-lock-add-keywords nil `(("c" 0 'font-lock-constant-face))))
+
+ (with-temp-buffer
+ (mode-c)
+ (should (equal font-lock-keywords
+ '(t (("c" 0 'font-lock-constant-face)
+ ("b" 0 'font-lock-builtin-face)
+ ("a" 0 'font-lock-keyword-face))
+ ("c" (0 'font-lock-constant-face))
+ ("b" (0 'font-lock-builtin-face))
+ ("a" (0 'font-lock-keyword-face)))))))
+
+;;; derived-tests.el ends here
diff --git a/test/lisp/emacs-lisp/easy-mmode-tests.el b/test/lisp/emacs-lisp/easy-mmode-tests.el
new file mode 100644
index 00000000000..f6d07196727
--- /dev/null
+++ b/test/lisp/emacs-lisp/easy-mmode-tests.el
@@ -0,0 +1,63 @@
+;;; easy-mmode-tests.el --- tests for easy-mmode.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'easy-mmode)
+(require 'message)
+
+(ert-deftest easy-mmode--globalized-predicate ()
+ (with-temp-buffer
+ (emacs-lisp-mode)
+ (should (eq (easy-mmode--globalized-predicate-p nil) nil))
+ (should (eq (easy-mmode--globalized-predicate-p t) t))
+ (should (eq (easy-mmode--globalized-predicate-p '(not text-mode)) t))
+ (should (eq (easy-mmode--globalized-predicate-p '(not text-mode)) t))
+ (should (eq (easy-mmode--globalized-predicate-p '((not text-mode))) nil))
+ (should (eq (easy-mmode--globalized-predicate-p '((not text-mode) t)) t))
+ (should (eq (easy-mmode--globalized-predicate-p
+ '(c-mode emacs-lisp-mode))
+ t))
+ (mail-mode)
+ (should (eq (easy-mmode--globalized-predicate-p
+ '(c-mode (not message-mode mail-mode) text-mode))
+ nil))
+ (text-mode)
+ (should (eq (easy-mmode--globalized-predicate-p
+ '(c-mode (not message-mode mail-mode) text-mode))
+ t))))
+
+(define-minor-mode easy-mmode-test-mode "A test.")
+
+(ert-deftest easy-mmode--minor-mode ()
+ (with-temp-buffer
+ (should (eq easy-mmode-test-mode nil))
+ (easy-mmode-test-mode nil)
+ (should (eq easy-mmode-test-mode t))
+ (easy-mmode-test-mode -33)
+ (should (eq easy-mmode-test-mode nil))
+ (easy-mmode-test-mode 33)
+ (should (eq easy-mmode-test-mode t))
+ (easy-mmode-test-mode 'toggle)
+ (should (eq easy-mmode-test-mode nil))
+ (easy-mmode-test-mode 'toggle)
+ (should (eq easy-mmode-test-mode t))))
+
+;;; easy-mmode-tests.el ends here
diff --git a/test/lisp/emacs-lisp/edebug-resources/edebug-test-code.el b/test/lisp/emacs-lisp/edebug-resources/edebug-test-code.el
index f52a2b1896c..42d06889ea7 100644
--- a/test/lisp/emacs-lisp/edebug-resources/edebug-test-code.el
+++ b/test/lisp/emacs-lisp/edebug-resources/edebug-test-code.el
@@ -1,23 +1,23 @@
-;;; edebug-test-code.el --- Sample code for the Edebug test suite
+;;; edebug-test-code.el --- Sample code for the Edebug test suite -*- lexical-binding:t -*-
-;; Copyright (C) 2017 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2022 Free Software Foundation, Inc.
;; Author: Gemini Lasswell
;; This file is part of GNU Emacs.
-;; This program is free software: you can redistribute it and/or
-;; modify it under the terms of the GNU General Public License as
-;; published by the Free Software Foundation, either version 3 of the
-;; License, or (at your option) any later version.
-;;
-;; This program is distributed in the hope that it will be useful, but
-;; WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-;; General Public License for more details.
-;;
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
;; You should have received a copy of the GNU General Public License
-;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
@@ -41,7 +41,7 @@
(defun edebug-test-code-range (num)
!start!(let ((index 0)
(result nil))
- (while (< index num)!test!
+ (while !lt!(< index num)!test!
(push index result)!loop!
(cl-incf index))!end-loop!
(nreverse result)))
@@ -62,12 +62,12 @@
(defun edebug-test-code-format-vector-node (node)
!start!(concat "["
- (apply 'concat (mapcar 'edebug-test-code-format-node node))!apply!
+ (apply #'concat (mapcar #'edebug-test-code-format-node node))!apply!
"]"))
(defun edebug-test-code-format-list-node (node)
!start!(concat "{"
- (apply 'concat (mapcar 'edebug-test-code-format-node node))!apply!
+ (apply #'concat (mapcar #'edebug-test-code-format-node node))!apply!
"}"))
(defun edebug-test-code-format-node (node)
@@ -126,5 +126,32 @@
!start!(with-current-buffer (get-buffer-create "*edebug-test-code-buffer*")
!body!(format "current-buffer: %s" (current-buffer))))
+(defun edebug-test-code-use-destructuring-bind ()
+ (let ((two 2) (three 3))
+ (cl-destructuring-bind (x . y) (cons two three) (+ x!x! y!y!))))
+
+(defun edebug-test-code-use-cl-macrolet (x)
+ (cl-macrolet ((wrap (func &rest args)
+ `(format "The result of applying %s to %s is %S"
+ ',func!func! ',args
+ ,(cons func args))))
+ (wrap + 1 x)))
+
+(defun edebug-test-code-cl-flet1 ()
+ (cl-flet
+ ;; This `&rest' sexp head should not collide with
+ ;; the Edebug spec elem of the same name.
+ ((f (&rest x) x)
+ (gate (x) (+ x 5)))
+ ;; This call to `gate' shouldn't collide with the Edebug spec elem
+ ;; of the same name.
+ (message "Hi %s" (gate 7))))
+
+(defun edebug-test-code-use-gv-expander (x)
+ (declare (gv-expander
+ (lambda (do)
+ (funcall do `(car ,x) (lambda (v) `(setcar ,x ,v))))))
+ (car x))
+
(provide 'edebug-test-code)
;;; edebug-test-code.el ends here
diff --git a/test/lisp/emacs-lisp/edebug-tests.el b/test/lisp/emacs-lisp/edebug-tests.el
index 02f4d1c5abe..dea6e9ed611 100644
--- a/test/lisp/emacs-lisp/edebug-tests.el
+++ b/test/lisp/emacs-lisp/edebug-tests.el
@@ -1,23 +1,23 @@
;;; edebug-tests.el --- Edebug test suite -*- lexical-binding:t -*-
-;; Copyright (C) 2017 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2022 Free Software Foundation, Inc.
;; Author: Gemini Lasswell
;; This file is part of GNU Emacs.
-;; This program is free software: you can redistribute it and/or
-;; modify it under the terms of the GNU General Public License as
-;; published by the Free Software Foundation, either version 3 of the
-;; License, or (at your option) any later version.
-;;
-;; This program is distributed in the hope that it will be useful, but
-;; WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-;; General Public License for more details.
-;;
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
;; You should have received a copy of the GNU General Public License
-;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
@@ -36,17 +36,6 @@
(require 'edebug)
(require 'kmacro)
-;; Use `eval-and-compile' because this is used by the macro
-;; `edebug-tests-deftest'.
-(eval-and-compile
- (defvar edebug-tests-sample-code-file
- (expand-file-name
- "edebug-resources/edebug-test-code.el"
- (file-name-directory (or (bound-and-true-p byte-compile-current-file)
- load-file-name
- buffer-file-name)))
- "Name of file containing code samples for Edebug tests."))
-
(defvar edebug-tests-temp-file nil
"Name of temp file containing sample code stripped of stop point symbols.")
(defvar edebug-tests-stop-points nil
@@ -64,22 +53,20 @@ Since `should' failures which happen inside `post-command-hook' will
be trapped by the command loop, this preserves them until we get
back to the top level.")
-(defvar edebug-tests-keymap
- (let ((map (make-sparse-keymap)))
- (define-key map "@" 'edebug-tests-call-instrumented-func)
- (define-key map "C-u" 'universal-argument)
- (define-key map "C-p" 'previous-line)
- (define-key map "C-n" 'next-line)
- (define-key map "C-b" 'backward-char)
- (define-key map "C-a" 'move-beginning-of-line)
- (define-key map "C-e" 'move-end-of-line)
- (define-key map "C-k" 'kill-line)
- (define-key map "M-x" 'execute-extended-command)
- (define-key map "C-M-x" 'eval-defun)
- (define-key map "C-x X b" 'edebug-set-breakpoint)
- (define-key map "C-x X w" 'edebug-where)
- map)
- "Keys used by the keyboard macros in Edebug's tests.")
+(defvar-keymap edebug-tests-keymap
+ :doc "Keys used by the keyboard macros in Edebug's tests."
+ "@" 'edebug-tests-call-instrumented-func
+ "C-u" 'universal-argument
+ "C-p" 'previous-line
+ "C-n" 'next-line
+ "C-b" 'backward-char
+ "C-a" 'move-beginning-of-line
+ "C-e" 'move-end-of-line
+ "C-k" 'kill-line
+ "M-x" 'execute-extended-command
+ "C-M-x" 'eval-defun
+ "C-x X b" 'edebug-set-breakpoint
+ "C-x X w" 'edebug-where)
;;; Macros for defining tests:
@@ -108,33 +95,37 @@ back to the top level.")
;; sit-on interferes with keyboard macros.
(edebug-sit-on-break nil)
- (edebug-continue-kbd-macro t))
+ (edebug-continue-kbd-macro t)
+
+ ;; don't print backtraces, otherwise error messages don't match
+ (backtrace-on-error-noninteractive nil))
,@body))
(defmacro edebug-tests-with-normal-env (&rest body)
"Set up the environment for an Edebug test BODY, run it, and clean up."
(declare (debug (body)))
`(edebug-tests-with-default-config
- (let ((edebug-tests-failure-in-post-command nil)
- (edebug-tests-temp-file (make-temp-file "edebug-tests-" nil ".el")))
- (edebug-tests-setup-code-file edebug-tests-temp-file)
- (ert-with-message-capture
- edebug-tests-messages
- (unwind-protect
- (with-current-buffer (find-file edebug-tests-temp-file)
- (read-only-mode)
- (setq lexical-binding t)
- (eval-buffer)
- ,@body
- (when edebug-tests-failure-in-post-command
- (signal (car edebug-tests-failure-in-post-command)
- (cdr edebug-tests-failure-in-post-command))))
- (unload-feature 'edebug-test-code)
- (with-current-buffer (find-file-noselect edebug-tests-temp-file)
- (set-buffer-modified-p nil))
- (ignore-errors (kill-buffer (find-file-noselect
- edebug-tests-temp-file)))
- (ignore-errors (delete-file edebug-tests-temp-file)))))))
+ (ert-with-temp-file edebug-tests-temp-file
+ :suffix ".el"
+ (let ((edebug-tests-failure-in-post-command nil)
+ (find-file-suppress-same-file-warnings t))
+ (edebug-tests-setup-code-file edebug-tests-temp-file)
+ (ert-with-message-capture
+ edebug-tests-messages
+ (unwind-protect
+ (with-current-buffer (find-file edebug-tests-temp-file)
+ (read-only-mode)
+ (setq lexical-binding t)
+ (eval-buffer)
+ ,@body
+ (when edebug-tests-failure-in-post-command
+ (signal (car edebug-tests-failure-in-post-command)
+ (cdr edebug-tests-failure-in-post-command))))
+ (unload-feature 'edebug-test-code)
+ (with-current-buffer (find-file-noselect edebug-tests-temp-file)
+ (set-buffer-modified-p nil))
+ (ignore-errors (kill-buffer (find-file-noselect
+ edebug-tests-temp-file)))))))))
;; The following macro and its support functions implement an extension
;; to keyboard macros to allow interleaving of keyboard macro
@@ -210,7 +201,7 @@ All other elements will be nil."
(defvar edebug-tests-thunks nil
"List containing thunks to run after each command in a keyboard macro.")
(defvar edebug-tests-kbd-macro-index nil
- "Index into `edebug-tests-run-unpacked-kbd-macro's current keyboard macro.")
+ "Index into `edebug-tests-run-kbd-macro's current keyboard macro.")
(defun edebug-tests-run-macro (kbdmac &rest thunks)
"Run a keyboard macro and execute a thunk after each command in it.
@@ -221,20 +212,21 @@ be the same as every keystroke) execute the thunk at the same
index."
(let* ((edebug-tests-thunks thunks)
(edebug-tests-kbd-macro-index 0)
+ (find-file-suppress-same-file-warnings t)
saved-local-map)
(with-current-buffer (find-file-noselect edebug-tests-temp-file)
(setq saved-local-map overriding-local-map)
(setq overriding-local-map edebug-tests-keymap)
- (add-hook 'post-command-hook 'edebug-tests-post-command))
+ (add-hook 'post-command-hook #'edebug-tests-post-command))
(advice-add 'exit-recursive-edit
- :around 'edebug-tests-preserve-keyboard-macro-state)
+ :around #'edebug-tests-preserve-keyboard-macro-state)
(unwind-protect
(kmacro-call-macro nil nil nil kbdmac)
(advice-remove 'exit-recursive-edit
- 'edebug-tests-preserve-keyboard-macro-state)
+ #'edebug-tests-preserve-keyboard-macro-state)
(with-current-buffer (find-file-noselect edebug-tests-temp-file)
(setq overriding-local-map saved-local-map)
- (remove-hook 'post-command-hook 'edebug-tests-post-command)))))
+ (remove-hook 'post-command-hook #'edebug-tests-post-command)))))
(defun edebug-tests-preserve-keyboard-macro-state (orig &rest args)
"Call ORIG with ARGS preserving the value of `executing-kbd-macro'.
@@ -344,7 +336,7 @@ evaluate to \"symbol\", \"symbol-1\", \"symbol-2\", etc."
Write the loadable code to a buffer for TMPFILE, and set
`edebug-tests-stop-points' to a map from defined symbols to stop
point names to positions in the file."
- (with-current-buffer (find-file-noselect edebug-tests-sample-code-file)
+ (with-current-buffer (find-file-noselect (ert-resource-file "edebug-test-code.el"))
(let ((marked-up-code (buffer-string)))
(with-temp-file tmpfile
(insert marked-up-code))))
@@ -432,9 +424,12 @@ test and possibly others should be updated."
(verify-keybinding "P" 'edebug-view-outside) ;; same as v
(verify-keybinding "W" 'edebug-toggle-save-windows)
(verify-keybinding "?" 'edebug-help)
- (verify-keybinding "d" 'edebug-backtrace)
+ (verify-keybinding "d" 'edebug-pop-to-backtrace)
(verify-keybinding "-" 'negative-argument)
- (verify-keybinding "=" 'edebug-temp-display-freq-count)))
+ (verify-keybinding "=" 'edebug-temp-display-freq-count)
+ (should (eq (lookup-key backtrace-mode-map "n") 'backtrace-forward-frame))
+ (should (eq (lookup-key edebug-backtrace-mode-map "s")
+ 'backtrace-goto-source))))
(ert-deftest edebug-tests-stop-point-at-start-of-first-instrumented-function ()
"Edebug stops at the beginning of an instrumented function."
@@ -727,7 +722,7 @@ test and possibly others should be updated."
(edebug-on-error nil)
error-message
(command-error-function (lambda (&rest args)
- (setq error-message (cl-cadar args)))))
+ (setq error-message (cadar args)))))
(edebug-tests-run-kbd-macro
"@" (edebug-tests-should-be-at "format-node" "start")
"SPC" (edebug-tests-should-be-at "format-node" "vectorp")
@@ -748,7 +743,7 @@ test and possibly others should be updated."
(edebug-on-error nil)
(error-message "")
(command-error-function (lambda (&rest args)
- (setq error-message (cl-cadar args)))))
+ (setq error-message (cadar args)))))
(edebug-tests-run-kbd-macro
"@ SPC SPC SPC SPC SPC"
(edebug-tests-should-be-at "try-flavors" "macro")
@@ -861,18 +856,22 @@ test and possibly others should be updated."
(ert-deftest edebug-tests-trivial-backquote ()
"Edebug can instrument a trivial backquote expression (Bug#23651)."
(edebug-tests-with-normal-env
- (read-only-mode -1)
- (delete-region (point-min) (point-max))
- (insert "`1")
- (read-only-mode)
- (edebug-eval-defun nil)
- (should (string-match-p (regexp-quote "1 (#o1, #x1, ?\\C-a)")
+ (let ((inhibit-read-only t))
+ (delete-region (point-min) (point-max))
+ (insert "`1"))
+ (with-suppressed-warnings ((obsolete edebug-eval-defun))
+ (edebug-eval-defun nil))
+ ;; `eval-defun' outputs its message to the echo area in a rather
+ ;; funny way, so the "1" and the " (#o1, #x1, ?\C-a)" end up placed
+ ;; there in separate pieces (via `print' rather than via `message').
+ (should (string-match-p (regexp-quote " (#o1, #x1, ?\\C-a)")
edebug-tests-messages))
(setq edebug-tests-messages "")
(setq edebug-initial-mode 'go)
;; In Bug#23651 Edebug would hang reading `1.
- (edebug-eval-defun t)))
+ (with-suppressed-warnings ((obsolete edebug-eval-defun))
+ (edebug-eval-defun t))))
(ert-deftest edebug-tests-trivial-comma ()
"Edebug can read a trivial comma expression (Bug#23651)."
@@ -881,7 +880,8 @@ test and possibly others should be updated."
(delete-region (point-min) (point-max))
(insert ",1")
(read-only-mode)
- (should-error (edebug-eval-defun t))))
+ (with-suppressed-warnings ((obsolete edebug-eval-defun))
+ (should-error (edebug-eval-defun t)))))
(ert-deftest edebug-tests-circular-read-syntax ()
"Edebug can instrument code using circular read object syntax (Bug#23660)."
@@ -899,5 +899,220 @@ test and possibly others should be updated."
"@g" (should (equal edebug-tests-@-result
'(#("abcd" 1 3 (face italic)) 511))))))
+(ert-deftest edebug-tests-dotted-forms ()
+ "Edebug can instrument code matching the tail of a dotted spec (Bug#6415)."
+ (edebug-tests-with-normal-env
+ (edebug-tests-setup-@ "use-destructuring-bind" nil t)
+ (edebug-tests-run-kbd-macro
+ "@ SPC SPC SPC SPC SPC SPC"
+ (edebug-tests-should-be-at "use-destructuring-bind" "x")
+ (edebug-tests-should-match-result-in-messages "2 (#o2, #x2, ?\\C-b)")
+ "SPC"
+ (edebug-tests-should-be-at "use-destructuring-bind" "y")
+ (edebug-tests-should-match-result-in-messages "3 (#o3, #x3, ?\\C-c)")
+ "g"
+ (should (equal edebug-tests-@-result 5)))))
+
+(ert-deftest edebug-tests-cl-macrolet ()
+ "Edebug can instrument `cl-macrolet' expressions. (Bug#29919)"
+ (edebug-tests-with-normal-env
+ (edebug-tests-locate-def "use-cl-macrolet")
+ (edebug-tests-run-kbd-macro
+ "C-u C-M-x SPC"
+ (edebug-tests-should-be-at "use-cl-macrolet" "func")
+ (edebug-tests-should-match-result-in-messages "+"))
+ (let ((edebug-initial-mode 'Go-nonstop))
+ (edebug-tests-setup-@ "use-cl-macrolet" '(10) t))
+ (edebug-tests-run-kbd-macro
+ "@ SPC g"
+ (should (equal edebug-tests-@-result "The result of applying + to (1 x) is 11"))
+ )))
+
+(ert-deftest edebug-tests-backtrace-goto-source ()
+ "Edebug can jump to instrumented source from its *Edebug-Backtrace* buffer."
+ (edebug-tests-with-normal-env
+ (edebug-tests-setup-@ "range" '(2) t)
+ (edebug-tests-run-kbd-macro
+ "@ SPC SPC"
+ (edebug-tests-should-be-at "range" "lt")
+ "dns" ; Pop to backtrace, next frame, goto source.
+ (edebug-tests-should-be-at "range" "start")
+ "g"
+ (should (equal edebug-tests-@-result '(0 1))))))
+
+(ert-deftest edebug-cl-defmethod-qualifier ()
+ "Check that secondary `cl-defmethod' forms don't stomp over
+primary ones (Bug#42671)."
+ (with-temp-buffer
+ (let* ((edebug-all-defs t)
+ (edebug-initial-mode 'Go-nonstop)
+ (defined-symbols ())
+ (edebug-new-definition-function
+ (lambda (def-name)
+ (push def-name defined-symbols)
+ (edebug-new-definition def-name))))
+ (dolist (form '((cl-defmethod edebug-cl-defmethod-qualifier ((_ number)))
+ (cl-defmethod edebug-cl-defmethod-qualifier
+ :around ((_ number)))))
+ (print form (current-buffer)))
+ (eval-buffer)
+ (should
+ (equal
+ defined-symbols
+ (list (intern "edebug-cl-defmethod-qualifier :around (number)")
+ (intern "edebug-cl-defmethod-qualifier (number)")))))))
+
+(ert-deftest edebug-tests--conflicting-internal-names ()
+ "Check conflicts between form's head symbols and Edebug spec elements."
+ (edebug-tests-with-normal-env
+ (edebug-tests-setup-@ "cl-flet1" '(10) t)))
+
+(ert-deftest edebug-tests-gv-expander ()
+ "Edebug can instrument `gv-expander' expressions."
+ (edebug-tests-with-normal-env
+ (edebug-tests-setup-@ "use-gv-expander" nil t)
+ (should (equal
+ (catch 'text
+ (run-at-time 0 nil
+ (lambda () (throw 'text (buffer-substring (point) (+ (point) 5)))))
+ (eval '(setf (edebug-test-code-use-gv-expander (cons 'a 'b)) 3) t))
+ "(func"))))
+
+(defun edebug-tests--read (form spec)
+ (with-temp-buffer
+ (print form (current-buffer))
+ (goto-char (point-min))
+ (cl-letf ((edebug-all-forms t)
+ ((get (car form) 'edebug-form-spec) spec))
+ (edebug--read nil (current-buffer)))))
+
+(ert-deftest edebug-tests--&rest-behavior ()
+ ;; `&rest' is documented to allow the last "repetition" to be aborted early.
+ (should (edebug-tests--read '(dummy x 1 y 2 z)
+ '(&rest symbolp integerp)))
+ ;; `&rest' should notice here that the "symbolp integerp" sequence
+ ;; is not respected.
+ (should-error (edebug-tests--read '(dummy x 1 2 y)
+ '(&rest symbolp integerp))))
+
+(ert-deftest edebug-tests-cl-flet ()
+ "Check that Edebug can instrument `cl-flet' forms without name
+clashes (Bug#41853)."
+ (with-temp-buffer
+ (dolist (form '((defun edebug-tests-cl-flet-1 ()
+ (cl-flet ((inner () 0)) (message "Hi"))
+ (cl-flet ((inner () 1)) (inner)))
+ (defun edebug-tests-cl-flet-2 ()
+ (cl-flet ((inner () 2)) (inner)))))
+ (print form (current-buffer)))
+ (let* ((edebug-all-defs t)
+ (edebug-initial-mode 'Go-nonstop)
+ (instrumented-names ())
+ (edebug-new-definition-function
+ (lambda (name)
+ (when (memq name instrumented-names)
+ (error "Duplicate definition of `%s'" name))
+ (push name instrumented-names)
+ (edebug-new-definition name)))
+ ;; Make generated symbols reproducible.
+ (gensym-counter 10000))
+ (eval-buffer)
+ ;; Use `format' so as to throw away differences due to
+ ;; interned/uninterned symbols.
+ (should (equal (format "%s" (reverse instrumented-names))
+ ;; The outer definitions come after the inner
+ ;; ones because their body ends later.
+ ;; FIXME: We'd rather have names such as
+ ;; `edebug-tests-cl-flet-1@inner@cl-flet@10000',
+ ;; but that requires further changes to Edebug.
+ (format "%s" '(inner@cl-flet@10000
+ inner@cl-flet@10001
+ edebug-tests-cl-flet-1
+ inner@cl-flet@10002
+ edebug-tests-cl-flet-2)))))))
+
+(defmacro edebug-tests--duplicate-symbol-backtrack (arg)
+ "Helper macro that exemplifies Bug#42701.
+ARG is either (FORM) or (FORM IGNORED)."
+ (declare (debug ([&or (form) (form sexp)])))
+ (car arg))
+
+(ert-deftest edebug-tests-duplicate-symbol-backtrack ()
+ "Check that Edebug doesn't create duplicate symbols when
+backtracking (Bug#42701)."
+ (with-temp-buffer
+ (print '(defun edebug-tests-duplicate-symbol-backtrack ()
+ (edebug-tests--duplicate-symbol-backtrack
+ ;; Passing (FORM IGNORED) forces backtracking.
+ ((lambda () 123) ignored)))
+ (current-buffer))
+ (let* ((edebug-all-defs t)
+ (edebug-initial-mode 'Go-nonstop)
+ (instrumented-names ())
+ (edebug-new-definition-function
+ (lambda (name)
+ (when (memq name instrumented-names)
+ (error "Duplicate definition of `%s'" name))
+ (push name instrumented-names)
+ (edebug-new-definition name)))
+ ;; Make generated symbols reproducible.
+ (gensym-counter 10000))
+ (eval-buffer)
+ ;; The anonymous symbols are uninterned. Use their names so we
+ ;; can perform the assertion. The names should still be unique.
+ (should (equal (mapcar #'symbol-name (reverse instrumented-names))
+ ;; The outer definition comes after the inner
+ ;; ones because its body ends later.
+ ;; FIXME: There are twice as many inner
+ ;; definitions as expected due to Bug#42701.
+ ;; Once that bug is fixed, remove the duplicates.
+ '("edebug-anon10000"
+ "edebug-anon10001"
+ "edebug-tests-duplicate-symbol-backtrack"))))))
+
+(defmacro edebug-tests--duplicate-&define (_arg)
+ "Helper macro for the ERT test `edebug-tests-duplicate-&define'.
+The Edebug specification is similar to the one used by `cl-flet'
+previously; see Bug#41988."
+ (declare (debug (&or (&define name function-form) (defun)))))
+
+(ert-deftest edebug-tests-duplicate-&define ()
+ "Check that Edebug doesn't backtrack out of `&define' forms.
+This avoids potential duplicate definitions (Bug#41988)."
+ (with-temp-buffer
+ (print '(defun edebug-tests-duplicate-&define ()
+ (edebug-tests--duplicate-&define
+ (edebug-tests-duplicate-&define-inner () nil)))
+ (current-buffer))
+ (let* ((edebug-all-defs t)
+ (edebug-initial-mode 'Go-nonstop)
+ (instrumented-names ())
+ (edebug-new-definition-function
+ (lambda (name)
+ (when (memq name instrumented-names)
+ (error "Duplicate definition of `%s'" name))
+ (push name instrumented-names)
+ (edebug-new-definition name))))
+ (should-error (eval-buffer) :type 'invalid-read-syntax))))
+
+(ert-deftest edebug-tests-inline ()
+ "Check that Edebug can instrument inline functions (Bug#53068)."
+ (with-temp-buffer
+ (print '(define-inline edebug-tests-inline (arg)
+ (inline-quote ,arg))
+ (current-buffer))
+ (let ((edebug-all-defs t)
+ (edebug-initial-mode 'Go-nonstop))
+ (eval-buffer))))
+
+(ert-deftest edebug-test-dot-reader ()
+ (with-temp-buffer
+ (insert "(defun x () `(t .,t))")
+ (goto-char (point-min))
+ (should (equal (save-excursion
+ (edebug-read-storing-offsets (current-buffer)))
+ (save-excursion
+ (read (current-buffer)))))))
+
(provide 'edebug-tests)
;;; edebug-tests.el ends here
diff --git a/test/lisp/emacs-lisp/eieio-tests/eieio-test-methodinvoke.el b/test/lisp/emacs-lisp/eieio-tests/eieio-test-methodinvoke.el
index 818b3e76a1e..af19c122b9f 100644
--- a/test/lisp/emacs-lisp/eieio-tests/eieio-test-methodinvoke.el
+++ b/test/lisp/emacs-lisp/eieio-tests/eieio-test-methodinvoke.el
@@ -1,6 +1,6 @@
-;;; eieio-testsinvoke.el -- eieio tests for method invocation
+;;; eieio-test-methodinvoke.el --- eieio tests for method invocation -*- lexical-binding:t -*-
-;; Copyright (C) 2005, 2008, 2010, 2013-2017 Free Software Foundation,
+;; Copyright (C) 2005, 2008, 2010, 2013-2022 Free Software Foundation,
;; Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
@@ -22,22 +22,22 @@
;;; Commentary:
;;
-;; Test method invocation order. From the common lisp reference
-;; manual:
+;; Test method invocation order. From the Common Lisp Reference
+;; Manual:
;;
;; QUOTE:
;; - All the :before methods are called, in most-specific-first
;; order. Their values are ignored. An error is signaled if
;; call-next-method is used in a :before method.
;;
-;; - The most specific primary method is called. Inside the body of a
+;; - The most specific primary method is called. Inside the body of a
;; primary method, call-next-method may be used to call the next
-;; most specific primary method. When that method returns, the
+;; most specific primary method. When that method returns, the
;; previous primary method can execute more code, perhaps based on
-;; the returned value or values. The generic function no-next-method
+;; the returned value or values. The generic function no-next-method
;; is invoked if call-next-method is used and there are no more
-;; applicable primary methods. The function next-method-p may be
-;; used to determine whether a next method exists. If
+;; applicable primary methods. The function next-method-p may be
+;; used to determine whether a next method exists. If
;; call-next-method is not used, only the most specific primary
;; method is called.
;;
@@ -46,13 +46,18 @@
;; call-next-method is used in a :after method.
;;
;;
-;; Also test behavior of `call-next-method'. From clos.org:
+;; Also test behavior of `call-next-method'. From clos.org:
;;
;; QUOTE:
;; When call-next-method is called with no arguments, it passes the
;; current method's original arguments to the next method.
+;;; Code:
+
(require 'eieio)
+;; FIXME: See Bug#52971.
+(with-no-warnings
+ (require 'eieio-compat))
(require 'ert)
(defvar eieio-test-method-order-list nil
@@ -83,37 +88,40 @@
(defclass eitest-B-base2 () ())
(defclass eitest-B (eitest-B-base1 eitest-B-base2) ())
-(defmethod eitest-F :BEFORE ((p eitest-B-base1))
- (eieio-test-method-store :BEFORE 'eitest-B-base1))
-
-(defmethod eitest-F :BEFORE ((p eitest-B-base2))
- (eieio-test-method-store :BEFORE 'eitest-B-base2))
+(with-suppressed-warnings ((obsolete defmethod)
+ (obsolete defgeneric)
+ (obsolete call-next-method)
+ (obsolete next-method-p))
+ (defmethod eitest-F :BEFORE ((_p eitest-B-base1))
+ (eieio-test-method-store :BEFORE 'eitest-B-base1))
-(defmethod eitest-F :BEFORE ((p eitest-B))
- (eieio-test-method-store :BEFORE 'eitest-B))
+ (defmethod eitest-F :BEFORE ((_p eitest-B-base2))
+ (eieio-test-method-store :BEFORE 'eitest-B-base2))
-(defmethod eitest-F ((p eitest-B))
- (eieio-test-method-store :PRIMARY 'eitest-B)
- (call-next-method))
+ (defmethod eitest-F :BEFORE ((_p eitest-B))
+ (eieio-test-method-store :BEFORE 'eitest-B))
-(defmethod eitest-F ((p eitest-B-base1))
- (eieio-test-method-store :PRIMARY 'eitest-B-base1)
- (call-next-method))
+ (defmethod eitest-F ((_p eitest-B))
+ (eieio-test-method-store :PRIMARY 'eitest-B)
+ (call-next-method))
-(defmethod eitest-F ((p eitest-B-base2))
- (eieio-test-method-store :PRIMARY 'eitest-B-base2)
- (when (next-method-p)
+ (defmethod eitest-F ((_p eitest-B-base1))
+ (eieio-test-method-store :PRIMARY 'eitest-B-base1)
(call-next-method))
- )
-(defmethod eitest-F :AFTER ((p eitest-B-base1))
- (eieio-test-method-store :AFTER 'eitest-B-base1))
+ (defmethod eitest-F ((_p eitest-B-base2))
+ (eieio-test-method-store :PRIMARY 'eitest-B-base2)
+ (when (next-method-p)
+ (call-next-method)))
+
+ (defmethod eitest-F :AFTER ((_p eitest-B-base1))
+ (eieio-test-method-store :AFTER 'eitest-B-base1))
-(defmethod eitest-F :AFTER ((p eitest-B-base2))
- (eieio-test-method-store :AFTER 'eitest-B-base2))
+ (defmethod eitest-F :AFTER ((_p eitest-B-base2))
+ (eieio-test-method-store :AFTER 'eitest-B-base2))
-(defmethod eitest-F :AFTER ((p eitest-B))
- (eieio-test-method-store :AFTER 'eitest-B))
+ (defmethod eitest-F :AFTER ((_p eitest-B))
+ (eieio-test-method-store :AFTER 'eitest-B)))
(ert-deftest eieio-test-method-order-list-3 ()
(let ((eieio-test-method-order-list nil)
@@ -136,9 +144,11 @@
;;; Test static invocation
;;
-(defmethod eitest-H :STATIC ((class eitest-A))
- "No need to do work in here."
- 'moose)
+(with-suppressed-warnings ((obsolete defmethod)
+ (obsolete defgeneric))
+ (defmethod eitest-H :STATIC ((_class eitest-A))
+ "No need to do work in here."
+ 'moose))
(ert-deftest eieio-test-method-order-list-4 ()
;; Both of these situations should succeed.
@@ -147,17 +157,19 @@
;;; Return value from :PRIMARY
;;
-(defmethod eitest-I :BEFORE ((a eitest-A))
- (eieio-test-method-store :BEFORE 'eitest-A)
- ":before")
+(with-suppressed-warnings ((obsolete defmethod)
+ (obsolete defgeneric))
+ (defmethod eitest-I :BEFORE ((_a eitest-A))
+ (eieio-test-method-store :BEFORE 'eitest-A)
+ ":before")
-(defmethod eitest-I :PRIMARY ((a eitest-A))
- (eieio-test-method-store :PRIMARY 'eitest-A)
- ":primary")
+ (defmethod eitest-I :PRIMARY ((_a eitest-A))
+ (eieio-test-method-store :PRIMARY 'eitest-A)
+ ":primary")
-(defmethod eitest-I :AFTER ((a eitest-A))
- (eieio-test-method-store :AFTER 'eitest-A)
- ":after")
+ (defmethod eitest-I :AFTER ((_a eitest-A))
+ (eieio-test-method-store :AFTER 'eitest-A)
+ ":after"))
(ert-deftest eieio-test-method-order-list-5 ()
(let ((eieio-test-method-order-list nil)
@@ -173,18 +185,20 @@
(defclass C-base2 () ())
(defclass C (C-base1 C-base2) ())
-;; Just use the obsolete name once, to make sure it also works.
-(defmethod constructor :STATIC ((p C-base1) &rest args)
- (eieio-test-method-store :STATIC 'C-base1)
- (if (next-method-p) (call-next-method))
- )
+(with-suppressed-warnings ((obsolete defmethod)
+ (obsolete defgeneric)
+ (obsolete next-method-p)
+ (obsolete call-next-method))
+ ;; Just use the obsolete name once, to make sure it also works.
+ (defmethod constructor :STATIC ((_p C-base1) &rest _args)
+ (eieio-test-method-store :STATIC 'C-base1)
+ (if (next-method-p) (call-next-method)))
-(defmethod make-instance :STATIC ((p C-base2) &rest args)
- (eieio-test-method-store :STATIC 'C-base2)
- (if (next-method-p) (call-next-method))
- )
+ (defmethod make-instance :STATIC ((_p C-base2) &rest _args)
+ (eieio-test-method-store :STATIC 'C-base2)
+ (if (next-method-p) (call-next-method))))
-(cl-defmethod make-instance ((p (subclass C)) &rest args)
+(cl-defmethod make-instance ((_p (subclass C)) &rest _args)
(eieio-test-method-store :STATIC 'C)
(cl-call-next-method)
)
@@ -192,7 +206,7 @@
(ert-deftest eieio-test-method-order-list-6 ()
;; FIXME repeated intermittent failures on hydra (bug#24503)
;; ((:STATIC C) (:STATIC C-base1) (:STATIC C-base2)) != ((:STATIC C))")
- (skip-unless (not (getenv "EMACS_HYDRA_CI")))
+ :tags '(:unstable)
(let ((eieio-test-method-order-list nil)
(ans '(
(:STATIC C)
@@ -213,29 +227,32 @@
(defclass D-base2 (D-base0) () :method-invocation-order :depth-first)
(defclass D (D-base1 D-base2) () :method-invocation-order :depth-first)
-(defmethod eitest-F ((p D))
- "D"
- (eieio-test-method-store :PRIMARY 'D)
- (call-next-method))
-
-(defmethod eitest-F ((p D-base0))
- "D-base0"
- (eieio-test-method-store :PRIMARY 'D-base0)
- ;; This should have no next
- ;; (when (next-method-p) (call-next-method))
- )
+(with-suppressed-warnings ((obsolete defmethod)
+ (obsolete defgeneric)
+ (obsolete call-next-method)
+ (obsolete next-method-p))
+ (defmethod eitest-F ((_p D))
+ "D"
+ (eieio-test-method-store :PRIMARY 'D)
+ (call-next-method))
-(defmethod eitest-F ((p D-base1))
- "D-base1"
- (eieio-test-method-store :PRIMARY 'D-base1)
- (call-next-method))
+ (defmethod eitest-F ((_p D-base0))
+ "D-base0"
+ (eieio-test-method-store :PRIMARY 'D-base0)
+ ;; This should have no next
+ ;; (when (next-method-p) (call-next-method))
+ )
-(defmethod eitest-F ((p D-base2))
- "D-base2"
- (eieio-test-method-store :PRIMARY 'D-base2)
- (when (next-method-p)
+ (defmethod eitest-F ((_p D-base1))
+ "D-base1"
+ (eieio-test-method-store :PRIMARY 'D-base1)
(call-next-method))
- )
+
+ (defmethod eitest-F ((_p D-base2))
+ "D-base2"
+ (eieio-test-method-store :PRIMARY 'D-base2)
+ (when (next-method-p)
+ (call-next-method))))
(ert-deftest eieio-test-method-order-list-7 ()
(let ((eieio-test-method-order-list nil)
@@ -256,25 +273,28 @@
(defclass E-base2 (E-base0) () :method-invocation-order :breadth-first)
(defclass E (E-base1 E-base2) () :method-invocation-order :breadth-first)
-(defmethod eitest-F ((p E))
- (eieio-test-method-store :PRIMARY 'E)
- (call-next-method))
-
-(defmethod eitest-F ((p E-base0))
- (eieio-test-method-store :PRIMARY 'E-base0)
- ;; This should have no next
- ;; (when (next-method-p) (call-next-method))
- )
+(with-suppressed-warnings ((obsolete defmethod)
+ (obsolete defgeneric)
+ (obsolete next-method-p)
+ (obsolete call-next-method))
+ (defmethod eitest-F ((_p E))
+ (eieio-test-method-store :PRIMARY 'E)
+ (call-next-method))
-(defmethod eitest-F ((p E-base1))
- (eieio-test-method-store :PRIMARY 'E-base1)
- (call-next-method))
+ (defmethod eitest-F ((_p E-base0))
+ (eieio-test-method-store :PRIMARY 'E-base0)
+ ;; This should have no next
+ ;; (when (next-method-p) (call-next-method))
+ )
-(defmethod eitest-F ((p E-base2))
- (eieio-test-method-store :PRIMARY 'E-base2)
- (when (next-method-p)
+ (defmethod eitest-F ((_p E-base1))
+ (eieio-test-method-store :PRIMARY 'E-base1)
(call-next-method))
- )
+
+ (defmethod eitest-F ((_p E-base2))
+ (eieio-test-method-store :PRIMARY 'E-base2)
+ (when (next-method-p)
+ (call-next-method))))
(ert-deftest eieio-test-method-order-list-8 ()
(let ((eieio-test-method-order-list nil)
@@ -293,24 +313,32 @@
(defclass eitest-Ja ()
())
-(defmethod initialize-instance :after ((this eitest-Ja) &rest slots)
- ;(message "+Ja")
- ;; FIXME: Using next-method-p in an after-method is invalid!
- (when (next-method-p)
- (call-next-method))
- ;(message "-Ja")
- )
+(with-suppressed-warnings ((obsolete defmethod)
+ (obsolete defgeneric)
+ (obsolete next-method-p)
+ (obsolete call-next-method))
+ (defmethod initialize-instance :after ((_this eitest-Ja) &rest _slots)
+ ;;(message "+Ja")
+ ;; FIXME: Using next-method-p in an after-method is invalid!
+ (when (next-method-p)
+ (call-next-method))
+ ;;(message "-Ja")
+ ))
(defclass eitest-Jb ()
())
-(defmethod initialize-instance :after ((this eitest-Jb) &rest slots)
- ;(message "+Jb")
- ;; FIXME: Using next-method-p in an after-method is invalid!
- (when (next-method-p)
- (call-next-method))
- ;(message "-Jb")
- )
+(with-suppressed-warnings ((obsolete defmethod)
+ (obsolete defgeneric)
+ (obsolete next-method-p)
+ (obsolete call-next-method))
+ (defmethod initialize-instance :after ((_this eitest-Jb) &rest _slots)
+ ;;(message "+Jb")
+ ;; FIXME: Using next-method-p in an after-method is invalid!
+ (when (next-method-p)
+ (call-next-method))
+ ;;(message "-Jb")
+ ))
(defclass eitest-Jc (eitest-Jb)
())
@@ -318,15 +346,19 @@
(defclass eitest-Jd (eitest-Jc eitest-Ja)
())
-(defmethod initialize-instance ((this eitest-Jd) &rest slots)
- ;(message "+Jd")
- (when (next-method-p)
- (call-next-method))
- ;(message "-Jd")
- )
+(with-suppressed-warnings ((obsolete defmethod)
+ (obsolete defgeneric)
+ (obsolete next-method-p)
+ (obsolete call-next-method))
+ (defmethod initialize-instance ((_this eitest-Jd) &rest _slots)
+ ;;(message "+Jd")
+ (when (next-method-p)
+ (call-next-method))
+ ;;(message "-Jd")
+ ))
(ert-deftest eieio-test-method-order-list-9 ()
- (should (eitest-Jd "test")))
+ (should (eitest-Jd)))
;;; call-next-method with replacement arguments across a simple class hierarchy.
;;
@@ -343,36 +375,40 @@
(defclass CNM-2 (CNM-1-1 CNM-1-2)
())
-(defmethod CNM-M ((this CNM-0) args)
- (push (cons 'CNM-0 (copy-sequence args))
- eieio-test-call-next-method-arguments)
- (when (next-method-p)
- (call-next-method
- this (cons 'CNM-0 args))))
-
-(defmethod CNM-M ((this CNM-1-1) args)
- (push (cons 'CNM-1-1 (copy-sequence args))
- eieio-test-call-next-method-arguments)
- (when (next-method-p)
- (call-next-method
- this (cons 'CNM-1-1 args))))
-
-(defmethod CNM-M ((this CNM-1-2) args)
- (push (cons 'CNM-1-2 (copy-sequence args))
- eieio-test-call-next-method-arguments)
- (when (next-method-p)
- (call-next-method)))
-
-(defmethod CNM-M ((this CNM-2) args)
- (push (cons 'CNM-2 (copy-sequence args))
- eieio-test-call-next-method-arguments)
- (when (next-method-p)
- (call-next-method
- this (cons 'CNM-2 args))))
+(with-suppressed-warnings ((obsolete defmethod)
+ (obsolete defgeneric)
+ (obsolete next-method-p)
+ (obsolete call-next-method))
+ (defmethod CNM-M ((this CNM-0) args)
+ (push (cons 'CNM-0 (copy-sequence args))
+ eieio-test-call-next-method-arguments)
+ (when (next-method-p)
+ (call-next-method
+ this (cons 'CNM-0 args))))
+
+ (defmethod CNM-M ((this CNM-1-1) args)
+ (push (cons 'CNM-1-1 (copy-sequence args))
+ eieio-test-call-next-method-arguments)
+ (when (next-method-p)
+ (call-next-method
+ this (cons 'CNM-1-1 args))))
+
+ (defmethod CNM-M ((_this CNM-1-2) args)
+ (push (cons 'CNM-1-2 (copy-sequence args))
+ eieio-test-call-next-method-arguments)
+ (when (next-method-p)
+ (call-next-method)))
+
+ (defmethod CNM-M ((this CNM-2) args)
+ (push (cons 'CNM-2 (copy-sequence args))
+ eieio-test-call-next-method-arguments)
+ (when (next-method-p)
+ (call-next-method
+ this (cons 'CNM-2 args)))))
(ert-deftest eieio-test-method-order-list-10 ()
(let ((eieio-test-call-next-method-arguments nil))
- (CNM-M (CNM-2 "") '(INIT))
+ (CNM-M (CNM-2) '(INIT))
(should (equal (eieio-test-arguments-for 'CNM-0)
'(CNM-1-1 CNM-2 INIT)))
(should (equal (eieio-test-arguments-for 'CNM-1-1)
@@ -403,3 +439,5 @@
(should (equal (eieio-test--1 (make-instance 'CNM-2) 5)
'("CNM-1-1" "CNM-1-2" "CNM-0" 7 5)))
(should (equal (eieio-test--1 'CNM-2 6) '("subclass CNM-1-2" CNM-2 6))))
+
+;;; eieio-test-methodinvoke.el ends here
diff --git a/test/lisp/emacs-lisp/eieio-tests/eieio-test-persist.el b/test/lisp/emacs-lisp/eieio-tests/eieio-test-persist.el
index 738711c9c84..e839e1262fa 100644
--- a/test/lisp/emacs-lisp/eieio-tests/eieio-test-persist.el
+++ b/test/lisp/emacs-lisp/eieio-tests/eieio-test-persist.el
@@ -1,8 +1,8 @@
-;;; eieio-persist.el --- Tests for eieio-persistent class
+;;; eieio-test-persist.el --- Tests for eieio-persistent class -*- lexical-binding:t -*-
-;; Copyright (C) 2011-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2022 Free Software Foundation, Inc.
-;; Author: Eric M. Ludlam <eric@siege-engine.com>
+;; Author: Eric M. Ludlam <zappo@gnu.org>
;; This file is part of GNU Emacs.
@@ -40,6 +40,17 @@ This is usually a symbol that starts with `:'."
(car tuple)
nil)))
+(defun hash-equal (hash1 hash2)
+ "Compare two hash tables to see whether they are equal."
+ (and (= (hash-table-count hash1)
+ (hash-table-count hash2))
+ (catch 'flag
+ (maphash (lambda (x y)
+ (or (equal (gethash x hash2) y)
+ (throw 'flag nil)))
+ hash1)
+ (throw 'flag t))))
+
(defun persist-test-save-and-compare (original)
"Compare the object ORIGINAL against the one read fromdisk."
@@ -49,8 +60,8 @@ This is usually a symbol that starts with `:'."
(class (eieio-object-class original))
(fromdisk (eieio-persistent-read file class))
(cv (cl--find-class class))
- (slots (eieio--class-slots cv))
- )
+ (slots (eieio--class-slots cv)))
+
(unless (object-of-class-p fromdisk class)
(error "Persistent class %S != original class %S"
(eieio-object-class fromdisk)
@@ -62,18 +73,24 @@ This is usually a symbol that starts with `:'."
(origvalue (eieio-oref original oneslot))
(fromdiskvalue (eieio-oref fromdisk oneslot))
(initarg-p (eieio--attribute-to-initarg
- (cl--find-class class) oneslot))
- )
+ (cl--find-class class) oneslot)))
(if initarg-p
- (unless (equal origvalue fromdiskvalue)
+ (unless
+ (cond ((and (hash-table-p origvalue) (hash-table-p fromdiskvalue))
+ (hash-equal origvalue fromdiskvalue))
+ (t (equal origvalue fromdiskvalue)))
(error "Slot %S Original Val %S != Persistent Val %S"
oneslot origvalue fromdiskvalue))
;; Else !initarg-p
- (unless (equal (cl--slot-descriptor-initform slot) fromdiskvalue)
+ (let ((origval (cl--slot-descriptor-initform slot))
+ (diskval fromdiskvalue))
+ (unless
+ (cond ((and (hash-table-p origval) (hash-table-p diskval))
+ (hash-equal origval diskval))
+ (t (equal origval diskval)))
(error "Slot %S Persistent Val %S != Default Value %S"
- oneslot fromdiskvalue (cl--slot-descriptor-initform slot))))
- ))))
+ oneslot diskval origvalue))))))))
;;; Simple Case
;;
@@ -82,7 +99,7 @@ This is usually a symbol that starts with `:'."
(defclass persist-simple (eieio-persistent)
((slot1 :initarg :slot1
:type symbol
- :initform moose)
+ :initform 'moose)
(slot2 :initarg :slot2
:initform "foo")
(slot3 :initform 2))
@@ -90,7 +107,7 @@ This is usually a symbol that starts with `:'."
(ert-deftest eieio-test-persist-simple-1 ()
(let ((persist-simple-1
- (persist-simple "simple 1" :slot1 'goose :slot2 "testing"
+ (persist-simple :slot1 'goose :slot2 "testing"
:file (concat default-directory "test-ps1.pt"))))
(should persist-simple-1)
@@ -124,7 +141,7 @@ Assume SLOTVALUE is a symbol of some sort."
(ert-deftest eieio-test-persist-printer ()
(let ((persist-:printer-1
- (persist-:printer "persist" :slot1 'goose :slot2 "testing"
+ (persist-:printer :slot1 'goose :slot2 "testing"
:file (concat default-directory "test-ps2.pt"))))
(should persist-:printer-1)
(persist-test-save-and-compare persist-:printer-1)
@@ -148,9 +165,9 @@ Assume SLOTVALUE is a symbol of some sort."
((slot1 :initarg :slot1
:initform 1)
(slot2 :initform 2))
- "Class for testing persistent saving of an object that isn't
-persistent. This class is instead used as a slot value in a
-persistent class.")
+ "Class for testing persistent saving of an object that isn't persistent.
+This class is instead used as a slot value in a persistent
+class.")
(defclass persistent-with-objs-slot (eieio-persistent)
((pnp :initarg :pnp
@@ -161,8 +178,7 @@ persistent class.")
(ert-deftest eieio-test-non-persistent-as-slot ()
(let ((persist-wos
(persistent-with-objs-slot
- "persist wos 1"
- :pnp (persist-not-persistent "pnp 1" :slot1 3)
+ :pnp (persist-not-persistent :slot1 3)
:file (concat default-directory "test-ps3.pt"))))
(persist-test-save-and-compare persist-wos)
@@ -188,8 +204,7 @@ persistent class.")
(ert-deftest eieio-test-non-persistent-as-slot-child ()
(let ((persist-woss
(persistent-with-objs-slot-subs
- "persist woss 1"
- :pnp (persist-not-persistent-subclass "pnps 1" :slot1 3)
+ :pnp (persist-not-persistent-subclass :slot1 3)
:file (concat default-directory "test-ps4.pt"))))
(persist-test-save-and-compare persist-woss)
@@ -205,13 +220,16 @@ persistent class.")
((slot1 :initarg :slot1
:type (or persistent-random-class null persist-not-persistent))
(slot2 :initarg :slot2
- :type (or persist-not-persistent persist-random-class null))))
+ :type (or persist-not-persistent persistent-random-class null))
+ (slot3 :initarg :slot3
+ :type persistent-random-class)))
(ert-deftest eieio-test-multiple-class-slot ()
(let ((persist
- (persistent-multiclass-slot "random string"
+ (persistent-multiclass-slot
:slot1 (persistent-random-class)
:slot2 (persist-not-persistent)
+ :slot3 (persistent-random-class)
:file (concat default-directory "test-ps5.pt"))))
(unwind-protect
(persist-test-save-and-compare persist)
@@ -229,13 +247,109 @@ persistent class.")
(ert-deftest eieio-test-slot-with-list-of-objects ()
(let ((persist-wols
(persistent-with-objs-list-slot
- "persist wols 1"
- :pnp (list (persist-not-persistent "pnp 1" :slot1 3)
- (persist-not-persistent "pnp 2" :slot1 4)
- (persist-not-persistent "pnp 3" :slot1 5))
+ :pnp (list (persist-not-persistent :slot1 3)
+ (persist-not-persistent :slot1 4)
+ (persist-not-persistent :slot1 5))
:file (concat default-directory "test-ps5.pt"))))
(persist-test-save-and-compare persist-wols)
(delete-file (oref persist-wols file))))
+;;; Tests targeted at popular libraries in the wild.
+
+;; Objects inside hash tables and vectors (pcache), see bug#29220.
+(defclass person ()
+ ((name :type string :initarg :name)))
+
+(defclass classy (eieio-persistent)
+ ((teacher
+ :type person
+ :initarg :teacher)
+ (students
+ :initarg :students :initform (make-hash-table :test 'equal))
+ (janitors
+ :type list
+ :initarg :janitors)
+ (random-vector
+ :type vector
+ :initarg :random-vector)))
+
+(defun eieio-test-persist-hash-and-vector ()
+ (let* ((jane (make-instance 'person :name "Jane"))
+ (bob (make-instance 'person :name "Bob"))
+ (hans (make-instance 'person :name "Hans"))
+ (dierdre (make-instance 'person :name "Dierdre"))
+ (class (make-instance 'classy
+ :teacher jane
+ :janitors (list [tuesday nil]
+ [friday nil])
+ :random-vector [nil]
+ :file (concat default-directory "classy-" emacs-version ".eieio"))))
+ (puthash "Bob" bob (slot-value class 'students))
+ (aset (slot-value class 'random-vector) 0
+ (make-instance 'persistent-random-class))
+ (unwind-protect
+ (persist-test-save-and-compare class)
+ (delete-file (oref class file)))
+ (aset (car (slot-value class 'janitors)) 1 hans)
+ (aset (nth 1 (slot-value class 'janitors)) 1 dierdre)
+ (unwind-protect
+ (persist-test-save-and-compare class)
+ (delete-file (oref class file)))))
+
+(ert-deftest eieio-persist-hash-and-vector-backward-compatibility ()
+ (let ((eieio-backward-compatibility t)) ; The default.
+ (eieio-test-persist-hash-and-vector)))
+
+(ert-deftest eieio-persist-hash-and-vector-no-backward-compatibility ()
+ :expected-result :failed ;; Bug#29220.
+ (let ((eieio-backward-compatibility nil))
+ (eieio-test-persist-hash-and-vector)))
+
+;; Extra quotation of lists inside other objects (Gnus registry), also
+;; bug#29220.
+
+(defclass eieio-container (eieio-persistent)
+ ((alist
+ :initarg :alist
+ :type list)
+ (vec
+ :initarg :vec
+ :type vector)
+ (htab
+ :initarg :htab
+ :type hash-table)))
+
+(defun eieio-test-persist-interior-lists ()
+ (let* ((thing (make-instance
+ 'eieio-container
+ :vec [nil]
+ :htab (make-hash-table :test #'equal)
+ :file (concat default-directory
+ "container-" emacs-version ".eieio")))
+ (john (make-instance 'person :name "John"))
+ (alexie (make-instance 'person :name "Alexie"))
+ (alst '(("first" (one two three))
+ ("second" (four five six)))))
+ (setf (slot-value thing 'alist) alst)
+ (puthash "alst" alst (slot-value thing 'htab))
+ (aset (slot-value thing 'vec) 0 alst)
+ (unwind-protect
+ (persist-test-save-and-compare thing)
+ (delete-file (slot-value thing 'file)))
+ (setf (nth 2 (cadar alst)) john
+ (nth 2 (cadadr alst)) alexie)
+ (unwind-protect
+ (persist-test-save-and-compare thing)
+ (delete-file (slot-value thing 'file)))))
+
+(ert-deftest eieio-test-persist-interior-lists-backward-compatibility ()
+ (let ((eieio-backward-compatibility t)) ; The default.
+ (eieio-test-persist-interior-lists)))
+
+(ert-deftest eieio-test-persist-interior-lists-no-backward-compatibility ()
+ :expected-result :failed ;; Bug#29220.
+ (let ((eieio-backward-compatibility nil))
+ (eieio-test-persist-interior-lists)))
+
;;; eieio-test-persist.el ends here
diff --git a/test/lisp/emacs-lisp/eieio-tests/eieio-tests.el b/test/lisp/emacs-lisp/eieio-tests/eieio-tests.el
index fbdb9896a40..9b27d4ab938 100644
--- a/test/lisp/emacs-lisp/eieio-tests/eieio-tests.el
+++ b/test/lisp/emacs-lisp/eieio-tests/eieio-tests.el
@@ -1,6 +1,6 @@
-;;; eieio-tests.el -- eieio tests routines
+;;; eieio-tests.el --- eieio test routines -*- lexical-binding: t -*-
-;; Copyright (C) 1999-2003, 2005-2010, 2012-2017 Free Software
+;; Copyright (C) 1999-2003, 2005-2010, 2012-2022 Free Software
;; Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
@@ -27,18 +27,26 @@
(require 'ert)
(require 'eieio)
(require 'eieio-base)
+;; FIXME: See Bug#52971.
+(with-no-warnings
+ (require 'eieio-compat))
(require 'eieio-opt)
(eval-when-compile (require 'cl-lib))
+;; Silence byte-compiler.
+(eval-when-compile
+ (dolist (slot '(:a :b ooga-booga :derived-value missing-slot))
+ (cl-pushnew slot eieio--known-slot-names)))
+
;;; Code:
;; Set up some test classes
(defclass class-a ()
((water :initarg :water
- :initform h20
+ :initform 'h20
:type symbol
:documentation "Detail about water.")
- (classslot :initform penguin
+ (classslot :initform 'penguin
:type symbol
:documentation "A class allocated slot."
:allocation :class)
@@ -48,53 +56,57 @@
:type (or null class-a)
:documentation "Test self referencing types.")
)
- "Class A")
+ "Class A.")
+
+;; Silence compiler warning about `water' not being a class-allocated slot.
+(defclass eieio-tests--dummy () ((water :allocation :class)))
(defclass class-b ()
((land :initform "Sc"
:type string
:documentation "Detail about land."))
- "Class B")
+ "Class B.")
(defclass class-ab (class-a class-b)
((amphibian :initform "frog"
:documentation "Detail about amphibian on land and water."))
"Class A and B combined.")
-(defclass class-c ()
- ((slot-1 :initarg :moose
- :initform moose
- :type symbol
- :allocation :instance
- :documentation "First slot testing slot arguments."
- :custom symbol
- :label "Wild Animal"
- :group borg
- :protection :public)
- (slot-2 :initarg :penguin
- :initform "penguin"
- :type string
- :allocation :instance
- :documentation "Second slot testing slot arguments."
- :custom string
- :label "Wild bird"
- :group vorlon
- :accessor get-slot-2
- :protection :private)
- (slot-3 :initarg :emu
- :initform emu
- :type symbol
- :allocation :class
- :documentation "Third slot test class allocated accessor"
- :custom symbol
- :label "Fuzz"
- :group tokra
- :accessor get-slot-3
- :protection :private)
- )
- (:custom-groups (foo))
- "A class for testing slot arguments."
- )
+(with-no-warnings ; FIXME: Make more specific.
+ (defclass class-c ()
+ ((slot-1 :initarg :moose
+ :initform 'moose
+ :type symbol
+ :allocation :instance
+ :documentation "First slot testing slot arguments."
+ :custom symbol
+ :label "Wild Animal"
+ :group borg
+ :protection :public)
+ (slot-2 :initarg :penguin
+ :initform "penguin"
+ :type string
+ :allocation :instance
+ :documentation "Second slot testing slot arguments."
+ :custom string
+ :label "Wild bird"
+ :group vorlon
+ :accessor get-slot-2
+ :protection :private)
+ (slot-3 :initarg :emu
+ :initform 'emu
+ :type symbol
+ :allocation :class
+ :documentation "Third slot test class allocated accessor"
+ :custom symbol
+ :label "Fuzz"
+ :group tokra
+ :accessor get-slot-3
+ :protection :private)
+ )
+ (:custom-groups (foo))
+ "A class for testing slot arguments."
+ ))
(defclass class-subc (class-c)
((slot-1 ;; :initform moose - don't override this
@@ -132,21 +144,25 @@
;; (error "invalid-slot-type thrown when eieio-error-unsupported-class-tags is nil")
;; )))
+;; Silence byte-compiler.
+(declare-function eitest-subordinate--eieio-childp nil)
+(declare-function class-alloc-initarg--eieio-childp nil)
(ert-deftest eieio-test-01-mix-alloc-initarg ()
;; Only run this test if the message framework thingy works.
- (when (and (message "foo") (string= "foo" (current-message)))
+ (skip-unless (and (message "foo") (string= "foo" (current-message))))
- ;; Defining this class should generate a warning(!) message that
- ;; you should not mix :initarg with class allocated slots.
+ ;; Defining this class should generate a warning(!) message that
+ ;; you should not mix :initarg with class allocated slots.
+ (with-no-warnings ; FIXME: Make more specific.
(defclass class-alloc-initarg ()
((throwwarning :initarg :throwwarning
- :allocation :class))
- "Throw a warning mixing allocation class and an initarg.")
+ :allocation :class))
+ "Throw a warning mixing allocation class and an initarg."))
- ;; Check that message is there
- (should (current-message))
- (should (string-match "Class allocated slots do not need :initarg"
- (current-message)))))
+ ;; Check that message is there
+ (should (current-message))
+ (should (string-match "Class allocated slots do not need :initarg"
+ (current-message))))
(defclass abstract-class ()
((some-slot :initarg :some-slot
@@ -160,30 +176,33 @@
;; error
(should-error (abstract-class)))
-(defgeneric generic1 () "First generic function")
+(with-suppressed-warnings ((obsolete defgeneric))
+ (defgeneric generic1 () "First generic function."))
(ert-deftest eieio-test-03-generics ()
- (defun anormalfunction () "A plain function for error testing." nil)
- (should-error
- (progn
- (defgeneric anormalfunction ()
- "Attempt to turn it into a generic.")))
-
- ;; Check that generic-p works
- (should (generic-p 'generic1))
-
- (defmethod generic1 ((c class-a))
- "Method on generic1."
- 'monkey)
-
- (defmethod generic1 (not-an-object)
- "Method generic1 that can take a non-object."
- not-an-object)
-
- (let ((ans-obj (generic1 (class-a)))
- (ans-num (generic1 666)))
- (should (eq ans-obj 'monkey))
- (should (eq ans-num 666))))
+ (with-suppressed-warnings ((obsolete defmethod)
+ (obsolete defgeneric))
+ (defun anormalfunction () "A plain function for error testing." nil)
+ (should-error
+ (progn
+ (defgeneric anormalfunction ()
+ "Attempt to turn it into a generic.")))
+
+ ;; Check that generic-p works
+ (should (generic-p 'generic1))
+
+ (defmethod generic1 ((_c class-a))
+ "Method on generic1."
+ 'monkey)
+
+ (defmethod generic1 (not-an-object)
+ "Method generic1 that can take a non-object."
+ not-an-object)
+
+ (let ((ans-obj (generic1 (class-a)))
+ (ans-num (generic1 666)))
+ (should (eq ans-obj 'monkey))
+ (should (eq ans-num 666)))))
(defclass static-method-class ()
((some-slot :initform nil
@@ -191,12 +210,17 @@
:documentation "A slot."))
:documentation "A class used for testing static methods.")
-(defmethod static-method-class-method :STATIC ((c static-method-class) value)
- "Test static methods.
+(with-suppressed-warnings ((obsolete defmethod)
+ (obsolete defgeneric))
+ (defmethod static-method-class-method :STATIC ((c static-method-class) value)
+ "Test static methods.
Argument C is the class bound to this static method."
- (if (eieio-object-p c) (setq c (eieio-object-class c)))
- (oset-default c some-slot value))
+ (if (eieio-object-p c) (setq c (eieio-object-class c)))
+ (oset-default c some-slot value)))
+;; Silence byte-compiler.
+(declare-function static-method-class-2 nil)
+(declare-function static-method-class-2--eieio-childp nil)
(ert-deftest eieio-test-04-static-method ()
;; Call static method on a class and see if it worked
(static-method-class-method 'static-method-class 'class)
@@ -209,11 +233,13 @@ Argument C is the class bound to this static method."
()
"A second class after the previous for static methods.")
- (defmethod static-method-class-method :STATIC ((c static-method-class-2) value)
- "Test static methods.
+ (with-suppressed-warnings ((obsolete defmethod)
+ (obsolete defgeneric))
+ (defmethod static-method-class-method :STATIC ((c static-method-class-2) value)
+ "Test static methods.
Argument C is the class bound to this static method."
- (if (eieio-object-p c) (setq c (eieio-object-class c)))
- (oset-default c some-slot (intern (concat "moose-" (symbol-name value)))))
+ (if (eieio-object-p c) (setq c (eieio-object-class c)))
+ (oset-default c some-slot (intern (concat "moose-" (symbol-name value))))))
(static-method-class-method 'static-method-class-2 'class)
(should (eq (oref-default 'static-method-class-2 some-slot) 'moose-class))
@@ -240,64 +266,71 @@ Argument C is the class bound to this static method."
(should (make-instance 'class-a :water 'cho))
(should (make-instance 'class-b)))
-(defmethod class-cn ((a class-a))
- "Try calling `call-next-method' when there isn't one.
+(with-suppressed-warnings ((obsolete defmethod)
+ (obsolete defgeneric))
+ (defmethod class-cn ((_a class-a))
+ "Try calling `call-next-method' when there isn't one.
Argument A is object of type symbol `class-a'."
- (call-next-method))
+ (with-suppressed-warnings ((obsolete call-next-method))
+ (call-next-method)))
-(defmethod no-next-method ((a class-a) &rest args)
- "Override signal throwing for variable `class-a'.
+ (defmethod no-next-method ((_a class-a) &rest _args)
+ "Override signal throwing for variable `class-a'.
Argument A is the object of class variable `class-a'."
- 'moose)
+ 'moose))
(ert-deftest eieio-test-08-call-next-method ()
;; Play with call-next-method
(should (eq (class-cn eitest-ab) 'moose)))
-(defmethod no-applicable-method ((b class-b) method &rest args)
- "No need.
+(with-suppressed-warnings ((obsolete defmethod)
+ (obsolete defgeneric))
+ (defmethod no-applicable-method ((_b class-b) _method &rest _args)
+ "No need.
Argument B is for booger.
METHOD is the method that was attempting to be called."
- 'moose)
+ 'moose))
(ert-deftest eieio-test-09-no-applicable-method ()
;; Non-existing methods.
(should (eq (class-cn eitest-b) 'moose)))
-(defmethod class-fun ((a class-a))
- "Fun with class A."
- 'moose)
+(with-suppressed-warnings ((obsolete defmethod)
+ (obsolete defgeneric))
+ (defmethod class-fun ((_a class-a))
+ "Fun with class A."
+ 'moose)
-(defmethod class-fun ((b class-b))
- "Fun with class B."
- (error "Class B fun should not be called")
- )
+ (defmethod class-fun ((_b class-b))
+ "Fun with class B."
+ (error "Class B fun should not be called"))
-(defmethod class-fun-foo ((b class-b))
- "Foo Fun with class B."
- 'moose)
+ (defmethod class-fun-foo ((_b class-b))
+ "Foo Fun with class B."
+ 'moose)
-(defmethod class-fun2 ((a class-a))
- "More fun with class A."
- 'moose)
+ (defmethod class-fun2 ((_a class-a))
+ "More fun with class A."
+ 'moose)
-(defmethod class-fun2 ((b class-b))
- "More fun with class B."
- (error "Class B fun2 should not be called")
- )
+ (defmethod class-fun2 ((_b class-b))
+ "More fun with class B."
+ (error "Class B fun2 should not be called"))
-(defmethod class-fun2 ((ab class-ab))
- "More fun with class AB."
- (call-next-method))
+ (defmethod class-fun2 ((_ab class-ab))
+ "More fun with class AB."
+ (with-suppressed-warnings ((obsolete call-next-method))
+ (call-next-method)))
-;; How about if B is the only slot?
-(defmethod class-fun3 ((b class-b))
- "Even More fun with class B."
- 'moose)
+ ;; How about if B is the only slot?
+ (defmethod class-fun3 ((_b class-b))
+ "Even More fun with class B."
+ 'moose)
-(defmethod class-fun3 ((ab class-ab))
- "Even More fun with class AB."
- (call-next-method))
+ (defmethod class-fun3 ((_ab class-ab))
+ "Even More fun with class AB."
+ (with-suppressed-warnings ((obsolete call-next-method))
+ (call-next-method))))
(ert-deftest eieio-test-10-multiple-inheritance ()
;; play with methods and mi
@@ -314,20 +347,22 @@ METHOD is the method that was attempting to be called."
(defvar class-fun-value-seq '())
-(defmethod class-fun-value :BEFORE ((a class-a))
- "Return `before', and push `before' in `class-fun-value-seq'."
- (push 'before class-fun-value-seq)
- 'before)
-
-(defmethod class-fun-value :PRIMARY ((a class-a))
- "Return `primary', and push `primary' in `class-fun-value-seq'."
- (push 'primary class-fun-value-seq)
- 'primary)
-
-(defmethod class-fun-value :AFTER ((a class-a))
- "Return `after', and push `after' in `class-fun-value-seq'."
- (push 'after class-fun-value-seq)
- 'after)
+(with-suppressed-warnings ((obsolete defmethod)
+ (obsolete defgeneric))
+ (defmethod class-fun-value :BEFORE ((_a class-a))
+ "Return `before', and push `before' in `class-fun-value-seq'."
+ (push 'before class-fun-value-seq)
+ 'before)
+
+ (defmethod class-fun-value :PRIMARY ((_a class-a))
+ "Return `primary', and push `primary' in `class-fun-value-seq'."
+ (push 'primary class-fun-value-seq)
+ 'primary)
+
+ (defmethod class-fun-value :AFTER ((_a class-a))
+ "Return `after', and push `after' in `class-fun-value-seq'."
+ (push 'after class-fun-value-seq)
+ 'after))
(ert-deftest eieio-test-12-generic-function-call ()
;; Test value of a generic function call
@@ -343,20 +378,23 @@ METHOD is the method that was attempting to be called."
;;
(ert-deftest eieio-test-13-init-methods ()
- (defmethod initialize-instance ((a class-a) &rest slots)
- "Initialize the slots of class-a."
- (call-next-method)
- (if (/= (oref a test-tag) 1)
- (error "shared-initialize test failed."))
- (oset a test-tag 2))
-
- (defmethod shared-initialize ((a class-a) &rest slots)
- "Shared initialize method for class-a."
- (call-next-method)
- (oset a test-tag 1))
-
- (let ((ca (class-a)))
- (should-not (/= (oref ca test-tag) 2))))
+ (with-suppressed-warnings ((obsolete defmethod)
+ (obsolete defgeneric)
+ (obsolete call-next-method))
+ (defmethod initialize-instance ((a class-a) &rest _slots)
+ "Initialize the slots of class-a."
+ (call-next-method)
+ (if (/= (oref a test-tag) 1)
+ (error "shared-initialize test failed."))
+ (oset a test-tag 2))
+
+ (defmethod shared-initialize ((a class-a) &rest _slots)
+ "Shared initialize method for class-a."
+ (call-next-method)
+ (oset a test-tag 1))
+
+ (let ((ca (class-a)))
+ (should (= (oref ca test-tag) 2)))))
;;; Perform slot testing
@@ -368,10 +406,11 @@ METHOD is the method that was attempting to be called."
(should (oref eitest-ab amphibian)))
(ert-deftest eieio-test-15-slot-missing ()
-
- (defmethod slot-missing ((ab class-ab) &rest foo)
- "If a slot in AB is unbound, return something cool. FOO."
- 'moose)
+ (with-suppressed-warnings ((obsolete defmethod)
+ (obsolete defgeneric))
+ (defmethod slot-missing ((_ab class-ab) &rest _foo)
+ "If a slot in AB is unbound, return something cool. FOO."
+ 'moose))
(should (eq (oref eitest-ab ooga-booga) 'moose))
(should-error (oref eitest-a ooga-booga) :type 'invalid-slot-name))
@@ -391,17 +430,20 @@ METHOD is the method that was attempting to be called."
(defclass virtual-slot-class ()
((base-value :initarg :base-value))
"Class has real slot :base-value and simulated slot :derived-value.")
-(defmethod slot-missing ((vsc virtual-slot-class)
- slot-name operation &optional new-value)
- "Simulate virtual slot derived-value."
- (cond
- ((or (eq slot-name :derived-value)
- (eq slot-name 'derived-value))
- (with-slots (base-value) vsc
- (if (eq operation 'oref)
- (+ base-value 1)
- (setq base-value (- new-value 1)))))
- (t (call-next-method))))
+(with-suppressed-warnings ((obsolete defmethod)
+ (obsolete defgeneric))
+ (defmethod slot-missing ((vsc virtual-slot-class)
+ slot-name operation &optional new-value)
+ "Simulate virtual slot derived-value."
+ (cond
+ ((or (eq slot-name :derived-value)
+ (eq slot-name 'derived-value))
+ (with-slots (base-value) vsc
+ (if (eq operation 'oref)
+ (+ base-value 1)
+ (setq base-value (- new-value 1)))))
+ (t (with-suppressed-warnings ((obsolete call-next-method))
+ (call-next-method))))))
(ert-deftest eieio-test-17-virtual-slot ()
(setq eitest-vsca (virtual-slot-class :base-value 1))
@@ -424,35 +466,37 @@ METHOD is the method that was attempting to be called."
(should (= (oref eitest-vscb :derived-value) 5)))
(ert-deftest eieio-test-18-slot-unbound ()
-
- (defmethod slot-unbound ((a class-a) &rest foo)
- "If a slot in A is unbound, ignore FOO."
- 'moose)
-
- (should (eq (oref eitest-a water) 'moose))
-
- ;; Check if oset of unbound works
- (oset eitest-a water 'moose)
- (should (eq (oref eitest-a water) 'moose))
-
- ;; oref/oref-default comparison
- (should-not (eq (oref eitest-a water) (oref-default eitest-a water)))
-
- ;; oset-default -> oref/oref-default comparison
- (oset-default (eieio-object-class eitest-a) water 'moose)
- (should (eq (oref eitest-a water) (oref-default eitest-a water)))
-
- ;; After setting 'water to 'moose, make sure a new object has
- ;; the right stuff.
- (oset-default (eieio-object-class eitest-a) water 'penguin)
- (should (eq (oref (class-a) water) 'penguin))
-
- ;; Revert the above
- (defmethod slot-unbound ((a class-a) &rest foo)
- "If a slot in A is unbound, ignore FOO."
- ;; Disable the old slot-unbound so we can run this test
- ;; more than once
- (call-next-method)))
+ (with-suppressed-warnings ((obsolete defmethod)
+ (obsolete defgeneric))
+ (defmethod slot-unbound ((_a class-a) &rest _foo)
+ "If a slot in A is unbound, ignore FOO."
+ 'moose)
+
+ (should (eq (oref eitest-a water) 'moose))
+
+ ;; Check if oset of unbound works
+ (oset eitest-a water 'moose)
+ (should (eq (oref eitest-a water) 'moose))
+
+ ;; oref/oref-default comparison
+ (should-not (eq (oref eitest-a water) (oref-default eitest-a water)))
+
+ ;; oset-default -> oref/oref-default comparison
+ (oset-default (eieio-object-class eitest-a) water 'moose)
+ (should (eq (oref eitest-a water) (oref-default eitest-a water)))
+
+ ;; After setting 'water to 'moose, make sure a new object has
+ ;; the right stuff.
+ (oset-default (eieio-object-class eitest-a) water 'penguin)
+ (should (eq (oref (class-a) water) 'penguin))
+
+ ;; Revert the above
+ (defmethod slot-unbound ((_a class-a) &rest _foo)
+ "If a slot in A is unbound, ignore FOO."
+ ;; Disable the old slot-unbound so we can run this test
+ ;; more than once
+ (with-suppressed-warnings ((obsolete call-next-method))
+ (call-next-method)))))
(ert-deftest eieio-test-19-slot-type-checking ()
;; Slot type checking
@@ -489,7 +533,7 @@ METHOD is the method that was attempting to be called."
(defclass inittest nil
((staticval :initform 1)
- (symval :initform eieio-test-permuting-value)
+ (symval :initform 'eieio-test-permuting-value)
(evalval :initform (symbol-value 'eieio-test-permuting-value))
(evalnow :initform (symbol-value 'eieio-test-permuting-value)
:allocation :class)
@@ -506,8 +550,10 @@ METHOD is the method that was attempting to be called."
(should (eq (oref eitest-pvinit evalval) 2))
(should (eq (oref eitest-pvinit evalnow) 1)))
+;; Silence byte-compiler.
(defvar eitest-tests nil)
-
+(declare-function eitest-superior nil)
+(declare-function eitest-superior--eieio-childp nil)
(ert-deftest eieio-test-22-init-forms-dont-match-runnable ()
;; Init forms with types that don't match the runnable.
(defclass eitest-subordinate nil
@@ -515,7 +561,7 @@ METHOD is the method that was attempting to be called."
"Test class that will be a calculated value.")
(defclass eitest-superior nil
- ((sub :initform (eitest-subordinate)
+ ((sub :initform (funcall #'eitest-subordinate)
:type eitest-subordinate))
"A class with an initform that creates a class.")
@@ -555,7 +601,10 @@ METHOD is the method that was attempting to be called."
(should-not (cl-typep listooa '(list-of class-b)))
(should-not (cl-typep listoob '(list-of class-a)))))
+;; Silence byte-compiler.
(defvar eitest-t1 nil)
+(declare-function eieio-tests-initform-not-evaluated-when-initarg-is-present nil)
+(declare-function eieio-tests-initform-not-evaluated-when-initarg-is-present--eieio-childp nil)
(ert-deftest eieio-test-25-slot-tests ()
(setq eitest-t1 (class-c))
;; Slot initialization
@@ -574,7 +623,21 @@ METHOD is the method that was attempting to be called."
(setf (get-slot-3 eitest-t1) 'setf-emu)
(should (eq (get-slot-3 eitest-t1) 'setf-emu))
;; Roll back
- (setf (get-slot-3 eitest-t1) 'emu))
+ (setf (get-slot-3 eitest-t1) 'emu)
+ (defvar eieio-tests-initform-was-evaluated)
+ (defclass eieio-tests-initform-not-evaluated-when-initarg-is-present ()
+ ((slot-with-initarg-and-initform
+ :initarg :slot-with-initarg-and-initform
+ :initform (setf eieio-tests-initform-was-evaluated t))))
+ (setq eieio-tests-initform-was-evaluated nil)
+ (make-instance
+ 'eieio-tests-initform-not-evaluated-when-initarg-is-present)
+ (should eieio-tests-initform-was-evaluated)
+ (setq eieio-tests-initform-was-evaluated nil)
+ (make-instance
+ 'eieio-tests-initform-not-evaluated-when-initarg-is-present
+ :slot-with-initarg-and-initform t)
+ (should-not eieio-tests-initform-was-evaluated))
(defvar eitest-t2 nil)
(ert-deftest eieio-test-26-default-inheritance ()
@@ -603,12 +666,14 @@ METHOD is the method that was attempting to be called."
()
"Protection testing baseclass.")
-(defmethod prot0-slot-2 ((s2 prot-0))
- "Try to access slot-2 from this class which doesn't have it.
+(with-suppressed-warnings ((obsolete defmethod)
+ (obsolete defgeneric))
+ (defmethod prot0-slot-2 ((s2 prot-0))
+ "Try to access slot-2 from this class which doesn't have it.
The object S2 passed in will be of class prot-1, which does have
the slot. This could be allowed, and currently is in EIEIO.
Needed by the eieio persistent base class."
- (oref s2 slot-2))
+ (oref s2 slot-2)))
(defclass prot-1 (prot-0)
((slot-1 :initarg :slot-1
@@ -626,26 +691,28 @@ Needed by the eieio persistent base class."
nil
"A class for testing the :protection option.")
-(defmethod prot1-slot-2 ((s2 prot-1))
- "Try to access slot-2 in S2."
- (oref s2 slot-2))
+(with-suppressed-warnings ((obsolete defmethod)
+ (obsolete defgeneric))
+ (defmethod prot1-slot-2 ((s2 prot-1))
+ "Try to access slot-2 in S2."
+ (oref s2 slot-2))
-(defmethod prot1-slot-2 ((s2 prot-2))
- "Try to access slot-2 in S2."
- (oref s2 slot-2))
+ (defmethod prot1-slot-2 ((s2 prot-2))
+ "Try to access slot-2 in S2."
+ (oref s2 slot-2))
-(defmethod prot1-slot-3-only ((s2 prot-1))
- "Try to access slot-3 in S2.
+ (defmethod prot1-slot-3-only ((s2 prot-1))
+ "Try to access slot-3 in S2.
Do not override for `prot-2'."
- (oref s2 slot-3))
+ (oref s2 slot-3))
-(defmethod prot1-slot-3 ((s2 prot-1))
- "Try to access slot-3 in S2."
- (oref s2 slot-3))
+ (defmethod prot1-slot-3 ((s2 prot-1))
+ "Try to access slot-3 in S2."
+ (oref s2 slot-3))
-(defmethod prot1-slot-3 ((s2 prot-2))
- "Try to access slot-3 in S2."
- (oref s2 slot-3))
+ (defmethod prot1-slot-3 ((s2 prot-2))
+ "Try to access slot-3 in S2."
+ (oref s2 slot-3)))
(defvar eitest-p1 nil)
(defvar eitest-p2 nil)
@@ -689,13 +756,24 @@ Do not override for `prot-2'."
(defvar eitest-II2 nil)
(defvar eitest-II3 nil)
(ert-deftest eieio-test-29-instance-inheritor ()
- (setq eitest-II1 (II "II Test."))
+ (setq eitest-II1 (II))
(oset eitest-II1 slot2 'cat)
(setq eitest-II2 (clone eitest-II1 "eitest-II2 Test."))
(oset eitest-II2 slot1 'moose)
(setq eitest-II3 (clone eitest-II2 "eitest-II3 Test."))
(oset eitest-II3 slot3 'penguin)
+ ;; Test that slots are non-initialized slots are unbounded
+ (oref eitest-II2 slot1)
+ (should (slot-boundp eitest-II2 'slot1))
+ (should-not (slot-boundp eitest-II2 'slot2))
+ (should-not (slot-boundp eitest-II2 'slot3))
+ (should-not (slot-boundp eitest-II3 'slot2))
+ (should-not (slot-boundp eitest-II3 'slot1))
+ (should-not (slot-boundp eitest-II3 'slot2))
+ (should (eieio-instance-inheritor-slot-boundp eitest-II3 'slot2))
+ (should (slot-boundp eitest-II3 'slot3))
+
;; Test level 1 inheritance
(should (eq (oref eitest-II3 slot1) 'moose))
;; Test level 2 inheritance
@@ -704,7 +782,7 @@ Do not override for `prot-2'."
(should (eq (oref eitest-II3 slot3) 'penguin)))
(defclass slotattr-base ()
- ((initform :initform init)
+ ((initform :initform 'init)
(type :type list)
(initarg :initarg :initarg)
(protection :protection :private)
@@ -719,7 +797,7 @@ Do not override for `prot-2'."
Subclasses to override slot attributes.")
(defclass slotattr-ok (slotattr-base)
- ((initform :initform no-init)
+ ((initform :initform 'no-init)
(initarg :initarg :initblarg)
(custom :custom string
:label "One String"
@@ -753,28 +831,29 @@ Subclasses to override slot attributes.")
(let ((obj (slotattr-ok)))
(should (eq (oref obj initform) 'no-init))))
-(defclass slotattr-class-base ()
- ((initform :allocation :class
- :initform init)
- (type :allocation :class
- :type list)
- (initarg :allocation :class
- :initarg :initarg)
- (protection :allocation :class
- :protection :private)
- (custom :allocation :class
- :custom (repeat string)
- :label "Custom Strings"
- :group moose)
- (docstring :allocation :class
- :documentation
- "Replace the doc-string for this property.")
- )
- "Baseclass we will attempt to subclass.
-Subclasses to override slot attributes.")
+(with-no-warnings ; FIXME: Make more specific.
+ (defclass slotattr-class-base ()
+ ((initform :allocation :class
+ :initform 'init)
+ (type :allocation :class
+ :type list)
+ (initarg :allocation :class
+ :initarg :initarg)
+ (protection :allocation :class
+ :protection :private)
+ (custom :allocation :class
+ :custom (repeat string)
+ :label "Custom Strings"
+ :group moose)
+ (docstring :allocation :class
+ :documentation
+ "Replace the doc-string for this property.")
+ )
+ "Baseclass we will attempt to subclass.
+Subclasses to override slot attributes."))
(defclass slotattr-class-ok (slotattr-class-base)
- ((initform :initform no-init)
+ ((initform :initform 'no-init)
(initarg :initarg :initblarg)
(custom :custom string
:label "One String"
@@ -836,11 +915,12 @@ Subclasses to override slot attributes.")
(should (setq eitest-CLONETEST2 (clone eitest-CLONETEST1))))
(defclass IT (eieio-instance-tracker)
- ((tracking-symbol :initform IT-list)
+ ((tracking-symbol :initform 'IT-list)
(slot1 :initform 'die))
"Instance Tracker test object.")
(ert-deftest eieio-test-33-instance-tracker ()
+ (defvar IT-list)
(let (IT-list IT1)
(should (setq IT1 (IT)))
;; The instance tracker must find this
@@ -862,8 +942,7 @@ Subclasses to override slot attributes.")
(should (oref obj1 a-slot))))
(defclass NAMED (eieio-named)
- ((some-slot :initform nil)
- )
+ ((some-slot :initform nil))
"A class inheriting from eieio-named.")
(ert-deftest eieio-test-35-named-object ()
@@ -876,12 +955,12 @@ Subclasses to override slot attributes.")
(defclass opt-test1 ()
()
- "Abstract base class"
+ "Abstract base class."
:abstract t)
(defclass opt-test2 (opt-test1)
()
- "Instantiable child")
+ "Instantiable child.")
(ert-deftest eieio-test-36-build-class-alist ()
(should (= (length (eieio-build-class-alist 'opt-test1 nil)) 2))
@@ -889,19 +968,83 @@ Subclasses to override slot attributes.")
(defclass eieio--testing () ())
-(defmethod constructor :static ((_x eieio--testing) newname &rest _args)
- (list newname 2))
+(with-suppressed-warnings ((obsolete defmethod)
+ (obsolete defgeneric))
+ (defmethod constructor :static ((_x eieio--testing) newname &rest _args)
+ (list newname 2)))
(ert-deftest eieio-test-37-obsolete-name-in-constructor ()
- ;; FIXME repeated intermittent failures on hydra (bug#24503)
- (skip-unless (not (getenv "EMACS_HYDRA_CI")))
- (should (equal (eieio--testing "toto") '("toto" 2))))
+ ;; FIXME repeated intermittent failures on hydra and elsewhere (bug#24503).
+ :tags '(:unstable)
+ ;; Disable byte-compiler "Warning: Obsolete name arg "toto" to
+ ;; constructor eieio--testing". This could be made more specific
+ ;; with changes to `with-suppressed-warnings', but it's not worth
+ ;; the hassle for just this one test.
+ (with-no-warnings
+ (should (equal (eieio--testing "toto") '("toto" 2)))))
(ert-deftest eieio-autoload ()
"Tests to see whether reftex-auc has been autoloaded"
(should
(fboundp 'eieio--defalias)))
+(ert-deftest eieio-test-38-clone-named-object ()
+ (let* ((A (NAMED :object-name "aa"))
+ (B (clone A :object-name "bb"))
+ (C (clone A "cc"))
+ (D (clone A))
+ (E (clone D)))
+ (should (string= "aa" (oref A object-name)))
+ (should (string= "bb" (oref B object-name)))
+ (should (string= "cc" (oref C object-name)))
+ (should (string= "aa-1" (oref D object-name)))
+ (should (string= "aa-2" (oref E object-name)))))
+
+(defclass TII (eieio-instance-inheritor)
+ ((a :initform 1 :initarg :a)
+ (b :initarg :b)
+ (c :initarg :c))
+ "Instance Inheritor test class.")
+
+(ert-deftest eieio-test-39-clone-instance-inheritor-with-args ()
+ (let* ((A (TII))
+ (B (clone A :b "bb"))
+ (C (clone B :a "aa")))
+
+ (should (string= "aa" (oref C :a)))
+ (should (string= "bb" (oref C :b)))
+
+ (should (slot-boundp A :a))
+ (should-not (slot-boundp A :b))
+ (should-not (slot-boundp A :c))
+
+ (should-not (slot-boundp B :a))
+ (should (slot-boundp B :b))
+ (should-not (slot-boundp A :c))
+
+ (should (slot-boundp C :a))
+ (should-not (slot-boundp C :b))
+ (should-not (slot-boundp C :c))
+
+ (should (eieio-instance-inheritor-slot-boundp C :a))
+ (should (eieio-instance-inheritor-slot-boundp C :b))
+ (should-not (eieio-instance-inheritor-slot-boundp C :c))))
+
+;;;; Interaction with defstruct
+
+(cl-defstruct eieio-test--struct a b (c nil :read-only t))
+
+(ert-deftest eieio-test-defstruct-slot-value ()
+ (let ((x (make-eieio-test--struct :a 'A :b 'B :c 'C)))
+ (should (eq (eieio-test--struct-a x)
+ (slot-value x 'a)))
+ (should (eq (eieio-test--struct-b x)
+ (slot-value x 'b)))
+ (should (eq (eieio-test--struct-c x)
+ (slot-value x 'c)))
+ (setf (slot-value x 'a) 1)
+ (should (eq (eieio-test--struct-a x) 1))
+ (should-error (setf (slot-value x 'c) 3) :type 'eieio-read-only)))
(provide 'eieio-tests)
diff --git a/test/lisp/emacs-lisp/ert-tests.el b/test/lisp/emacs-lisp/ert-tests.el
index b620a662846..84c28e11315 100644
--- a/test/lisp/emacs-lisp/ert-tests.el
+++ b/test/lisp/emacs-lisp/ert-tests.el
@@ -1,23 +1,23 @@
;;; ert-tests.el --- ERT's self-tests -*- lexical-binding: t -*-
-;; Copyright (C) 2007-2008, 2010-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2008, 2010-2022 Free Software Foundation, Inc.
;; Author: Christian Ohler <ohler@gnu.org>
;; This file is part of GNU Emacs.
-;; This program is free software: you can redistribute it and/or
-;; modify it under the terms of the GNU General Public License as
-;; published by the Free Software Foundation, either version 3 of the
-;; License, or (at your option) any later version.
-;;
-;; This program is distributed in the hope that it will be useful, but
-;; WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-;; General Public License for more details.
-;;
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
;; You should have received a copy of the GNU General Public License
-;; along with this program. If not, see `https://www.gnu.org/licenses/'.
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
@@ -39,10 +39,11 @@
(defun ert-self-test ()
"Run ERT's self-tests and make sure they actually ran."
(let ((window-configuration (current-window-configuration)))
- (let ((ert--test-body-was-run nil))
+ (let ((ert--test-body-was-run nil)
+ (ert--output-buffer-name " *ert self-tests*"))
;; The buffer name chosen here should not compete with the default
;; results buffer name for completion in `switch-to-buffer'.
- (let ((stats (ert-run-tests-interactively "^ert-" " *ert self-tests*")))
+ (let ((stats (ert-run-tests-interactively "^ert-")))
(cl-assert ert--test-body-was-run)
(if (zerop (ert-stats-completed-unexpected stats))
;; Hide results window only when everything went well.
@@ -188,7 +189,7 @@ failed or if there was a problem."
(ert-deftest ert-test-should-with-macrolet ()
(let ((test (make-ert-test :body (lambda ()
- (cl-macrolet ((foo () `(progn t nil)))
+ (cl-macrolet ((foo () '(progn t nil)))
(should (foo)))))))
(let ((result (let ((ert-debug-on-error nil))
(ert-run-test test))))
@@ -376,8 +377,11 @@ This macro is used to test if macroexpansion in `should' works."
(test (make-ert-test :body test-body))
(result (ert-run-test test)))
(should (ert-test-failed-p result))
- (should (eq (nth 1 (car (ert-test-failed-backtrace result)))
- 'signal))))
+ (should (memq (backtrace-frame-fun (car (ert-test-failed-backtrace result)))
+ ;;; This is `ert-fail' on nativecomp and `signal'
+ ;;; otherwise. It's not clear whether that's a bug
+ ;;; or not (bug#51308).
+ '(ert-fail signal)))))
(ert-deftest ert-test-messages ()
:tags '(:causes-redisplay)
@@ -490,54 +494,18 @@ This macro is used to test if macroexpansion in `should' works."
:name nil
:body nil
:tags '(a b))))
- (should (equal (ert-select-tests `(tag a) (list test)) (list test)))
- (should (equal (ert-select-tests `(tag b) (list test)) (list test)))
- (should (equal (ert-select-tests `(tag c) (list test)) '()))))
+ (should (equal (ert-select-tests '(tag a) (list test)) (list test)))
+ (should (equal (ert-select-tests '(tag b) (list test)) (list test)))
+ (should (equal (ert-select-tests '(tag c) (list test)) '()))))
+(ert-deftest ert-test-select-undefined ()
+ (let* ((symbol (make-symbol "ert-not-a-test"))
+ (data (should-error (ert-select-tests symbol t)
+ :type 'ert-test-unbound)))
+ (should (eq (cadr data) symbol))))
-;;; Tests for utility functions.
-(ert-deftest ert-test-proper-list-p ()
- (should (ert--proper-list-p '()))
- (should (ert--proper-list-p '(1)))
- (should (ert--proper-list-p '(1 2)))
- (should (ert--proper-list-p '(1 2 3)))
- (should (ert--proper-list-p '(1 2 3 4)))
- (should (not (ert--proper-list-p 'a)))
- (should (not (ert--proper-list-p '(1 . a))))
- (should (not (ert--proper-list-p '(1 2 . a))))
- (should (not (ert--proper-list-p '(1 2 3 . a))))
- (should (not (ert--proper-list-p '(1 2 3 4 . a))))
- (let ((a (list 1)))
- (setf (cdr (last a)) a)
- (should (not (ert--proper-list-p a))))
- (let ((a (list 1 2)))
- (setf (cdr (last a)) a)
- (should (not (ert--proper-list-p a))))
- (let ((a (list 1 2 3)))
- (setf (cdr (last a)) a)
- (should (not (ert--proper-list-p a))))
- (let ((a (list 1 2 3 4)))
- (setf (cdr (last a)) a)
- (should (not (ert--proper-list-p a))))
- (let ((a (list 1 2)))
- (setf (cdr (last a)) (cdr a))
- (should (not (ert--proper-list-p a))))
- (let ((a (list 1 2 3)))
- (setf (cdr (last a)) (cdr a))
- (should (not (ert--proper-list-p a))))
- (let ((a (list 1 2 3 4)))
- (setf (cdr (last a)) (cdr a))
- (should (not (ert--proper-list-p a))))
- (let ((a (list 1 2 3)))
- (setf (cdr (last a)) (cddr a))
- (should (not (ert--proper-list-p a))))
- (let ((a (list 1 2 3 4)))
- (setf (cdr (last a)) (cddr a))
- (should (not (ert--proper-list-p a))))
- (let ((a (list 1 2 3 4)))
- (setf (cdr (last a)) (cl-cdddr a))
- (should (not (ert--proper-list-p a)))))
+;;; Tests for utility functions.
(ert-deftest ert-test-parse-keys-and-body ()
(should (equal (ert--parse-keys-and-body '(foo)) '(nil (foo))))
(should (equal (ert--parse-keys-and-body '(:bar foo)) '((:bar foo) nil)))
@@ -561,17 +529,18 @@ This macro is used to test if macroexpansion in `should' works."
:body (lambda () (ert-skip
"skip message")))))
(let ((ert-debug-on-error nil))
- (let* ((buffer-name (generate-new-buffer-name " *ert-test-run-tests*"))
- (messages nil)
- (mock-message-fn
- (lambda (format-string &rest args)
- (push (apply #'format format-string args) messages))))
+ (cl-letf* ((buffer-name (generate-new-buffer-name
+ " *ert-test-run-tests*"))
+ (ert--output-buffer-name buffer-name)
+ (messages nil)
+ ((symbol-function 'message)
+ (lambda (format-string &rest args)
+ (push (apply #'format format-string args) messages))))
(save-window-excursion
(unwind-protect
(let ((case-fold-search nil))
(ert-run-tests-interactively
- `(member ,passing-test ,failing-test, skipped-test) buffer-name
- mock-message-fn)
+ `(member ,passing-test ,failing-test, skipped-test))
(should (equal messages `(,(concat
"Ran 3 tests, 1 results were "
"as expected, 1 unexpected, "
@@ -593,6 +562,69 @@ This macro is used to test if macroexpansion in `should' works."
(when (get-buffer buffer-name)
(kill-buffer buffer-name))))))))
+(ert-deftest ert-test-run-tests-batch ()
+ (let* ((complex-list '((:1 (:2 (:3 (:4 (:5 (:6 "abc"))))))))
+ (long-list (make-list 11 1))
+ (failing-test-1
+ (make-ert-test :name 'failing-test-1
+ :body (lambda () (should (equal complex-list 1)))))
+ (failing-test-2
+ (make-ert-test :name 'failing-test-2
+ :body (lambda () (should (equal long-list 1))))))
+ (let ((ert-debug-on-error nil)
+ messages)
+ (cl-letf* (((symbol-function 'message)
+ (lambda (format-string &rest args)
+ (push (apply #'format format-string args) messages))))
+ (save-window-excursion
+ (unwind-protect
+ (let ((case-fold-search nil)
+ (ert-batch-backtrace-right-margin nil)
+ (ert-batch-print-level 10)
+ (ert-batch-print-length 11))
+ (ert-run-tests-batch
+ `(member ,failing-test-1 ,failing-test-2))))))
+ (let ((long-text "(different-types[ \t\n]+(1 1 1 1 1 1 1 1 1 1 1)[ \t\n]+1)))[ \t\n]*$")
+ (complex-text "(different-types[ \t\n]+((:1[ \t\n]+(:2[ \t\n]+(:3[ \t\n]+(:4[ \t\n]+(:5[ \t\n]+(:6[ \t\n]+\"abc\")))))))[ \t\n]+1)))[ \t\n]*$")
+ found-long
+ found-complex)
+ (cl-loop for msg in (reverse messages)
+ do
+ (unless found-long
+ (setq found-long (string-match long-text msg)))
+ (unless found-complex
+ (setq found-complex (string-match complex-text msg))))
+ (should found-long)
+ (should found-complex)))))
+
+(ert-deftest ert-test-run-tests-batch-expensive ()
+ :tags (if (getenv "EMACS_EMBA_CI") '(:unstable))
+ (let* ((complex-list '((:1 (:2 (:3 (:4 (:5 (:6 "abc"))))))))
+ (failing-test-1
+ (make-ert-test :name 'failing-test-1
+ :body (lambda () (should (equal complex-list 1))))))
+ (let ((ert-debug-on-error nil)
+ messages)
+ (cl-letf* (((symbol-function 'message)
+ (lambda (format-string &rest args)
+ (push (apply #'format format-string args) messages))))
+ (save-window-excursion
+ (unwind-protect
+ (let ((case-fold-search nil)
+ (ert-batch-backtrace-right-margin nil)
+ (ert-batch-backtrace-line-length nil)
+ (ert-batch-print-level 6)
+ (ert-batch-print-length 11))
+ (ert-run-tests-batch
+ `(member ,failing-test-1))))))
+ (let ((frame "ert-fail(((should (equal complex-list 1)) :form (equal ((:1 (:2 (:3 (:4 (:5 (:6 \"abc\"))))))) 1) :value nil :explanation (different-types ((:1 (:2 (:3 (:4 (:5 (:6 \"abc\"))))))) 1)))")
+ found-frame)
+ (cl-loop for msg in (reverse messages)
+ do
+ (unless found-frame
+ (setq found-frame (cl-search frame msg :test 'equal))))
+ (should found-frame)))))
+
(ert-deftest ert-test-special-operator-p ()
(should (ert--special-operator-p 'if))
(should-not (ert--special-operator-p 'car))
@@ -669,6 +701,29 @@ This macro is used to test if macroexpansion in `should' works."
(should (equal (ert--explain-equal 'a sym)
`(different-symbols-with-the-same-name a ,sym)))))
+(ert-deftest ert-test-explain-equal-strings ()
+ (should (equal (ert--explain-equal "abc" "axc")
+ '(array-elt 1 (different-atoms
+ (?b "#x62" "?b")
+ (?x "#x78" "?x")))))
+ (should (equal (ert--explain-equal "abc" "abxc")
+ '(arrays-of-different-length
+ 3 4 "abc" "abxc" first-mismatch-at 2)))
+ (should (equal (ert--explain-equal "xyA" "xyÅ")
+ '(array-elt 2 (different-atoms
+ (?A "#x41" "?A")
+ (?Å "#xc5" "?Å")))))
+ (should (equal (ert--explain-equal "m\xff" "m\u00ff")
+ `(array-elt
+ 1 (different-atoms
+ (#x3fffff "#x3fffff" ,(string-to-multibyte "?\xff"))
+ (#xff "#xff" "?ÿ")))))
+ (should (equal (ert--explain-equal (string-to-multibyte "m\xff") "m\u00ff")
+ `(array-elt
+ 1 (different-atoms
+ (#x3fffff "#x3fffff" ,(string-to-multibyte "?\xff"))
+ (#xff "#xff" "?ÿ"))))))
+
(ert-deftest ert-test-explain-equal-improper-list ()
(should (equal (ert--explain-equal '(a . b) '(a . c))
'(cdr (different-atoms b c)))))
@@ -714,49 +769,40 @@ This macro is used to test if macroexpansion in `should' works."
(should (equal (ert--abbreviate-string "bar" 0 t) "")))
(ert-deftest ert-test-explain-equal-string-properties ()
- (should
- (equal (ert--explain-equal-including-properties #("foo" 0 1 (a b))
- "foo")
- '(char 0 "f"
- (different-properties-for-key a (different-atoms b nil))
- context-before ""
- context-after "oo")))
- (should (equal (ert--explain-equal-including-properties
+ (should-not (ert--explain-equal-including-properties-rec "foo" "foo"))
+ (should-not (ert--explain-equal-including-properties-rec
+ #("foo" 0 3 (a b))
+ (propertize "foo" 'a 'b)))
+ (should-not (ert--explain-equal-including-properties-rec
+ #("foo" 0 3 (a b c d))
+ (propertize "foo" 'a 'b 'c 'd)))
+ (should-not (ert--explain-equal-including-properties-rec
+ #("foo" 0 3 (a (t)))
+ (propertize "foo" 'a (list t))))
+
+ (should (equal (ert--explain-equal-including-properties-rec
+ #("foo" 0 3 (a b c e))
+ (propertize "foo" 'a 'b 'c 'd))
+ '(char 0 "f" (different-properties-for-key c (different-atoms e d))
+ context-before ""
+ context-after "oo")))
+ (should (equal (ert--explain-equal-including-properties-rec
+ #("foo" 0 1 (a b))
+ "foo")
+ '(char 0 "f"
+ (different-properties-for-key a (different-atoms b nil))
+ context-before ""
+ context-after "oo")))
+ (should (equal (ert--explain-equal-including-properties-rec
#("foo" 1 3 (a b))
#("goo" 0 1 (c d)))
'(array-elt 0 (different-atoms (?f "#x66" "?f")
(?g "#x67" "?g")))))
- (should
- (equal (ert--explain-equal-including-properties
- #("foo" 0 1 (a b c d) 1 3 (a b))
- #("foo" 0 1 (c d a b) 1 2 (a foo)))
- '(char 1 "o" (different-properties-for-key a (different-atoms b foo))
- context-before "f" context-after "o"))))
-
-(ert-deftest ert-test-equal-including-properties ()
- (should (equal-including-properties "foo" "foo"))
- (should (ert-equal-including-properties "foo" "foo"))
-
- (should (equal-including-properties #("foo" 0 3 (a b))
- (propertize "foo" 'a 'b)))
- (should (ert-equal-including-properties #("foo" 0 3 (a b))
- (propertize "foo" 'a 'b)))
-
- (should (equal-including-properties #("foo" 0 3 (a b c d))
- (propertize "foo" 'a 'b 'c 'd)))
- (should (ert-equal-including-properties #("foo" 0 3 (a b c d))
- (propertize "foo" 'a 'b 'c 'd)))
-
- (should-not (equal-including-properties #("foo" 0 3 (a b c e))
- (propertize "foo" 'a 'b 'c 'd)))
- (should-not (ert-equal-including-properties #("foo" 0 3 (a b c e))
- (propertize "foo" 'a 'b 'c 'd)))
-
- ;; This is bug 6581.
- (should-not (equal-including-properties #("foo" 0 3 (a (t)))
- (propertize "foo" 'a (list t))))
- (should (ert-equal-including-properties #("foo" 0 3 (a (t)))
- (propertize "foo" 'a (list t)))))
+ (should (equal (ert--explain-equal-including-properties-rec
+ #("foo" 0 1 (a b c d) 1 3 (a b))
+ #("foo" 0 1 (c d a b) 1 2 (a foo)))
+ '(char 1 "o" (different-properties-for-key a (different-atoms b foo))
+ context-before "f" context-after "o"))))
(ert-deftest ert-test-stats-set-test-and-result ()
(let* ((test-1 (make-ert-test :name 'test-1
@@ -820,6 +866,28 @@ This macro is used to test if macroexpansion in `should' works."
(should (eql 0 (ert-stats-completed-unexpected stats)))
(should (eql 1 (ert-stats-skipped stats)))))
+(ert-deftest ert-test-with-demoted-errors ()
+ "Check that ERT correctly handles `with-demoted-errors'."
+ :expected-result :failed ;; FIXME! Bug#11218
+ (should-not (with-demoted-errors "FOO: %S" (error "Foo"))))
+
+(ert-deftest ert-test-fail-inside-should ()
+ "Check that `ert-fail' inside `should' works correctly."
+ (let ((result (ert-run-test
+ (make-ert-test
+ :name 'test-1
+ :body (lambda () (should (integerp (ert-fail "Boo"))))))))
+ (should (ert-test-failed-p result))
+ (should (equal (ert-test-failed-condition result)
+ '(ert-test-failed "Boo")))))
+
+(ert-deftest ert-test-deftest-lexical-binding-t ()
+ "Check that `lexical-binding' in `ert-deftest' has the file value."
+ (should (equal lexical-binding t)))
+
+(ert-deftest ert-test-get-explainer ()
+ (should (eq (ert--get-explainer 'string-equal) 'ert--explain-string-equal))
+ (should (eq (ert--get-explainer 'string=) 'ert--explain-string-equal)))
(provide 'ert-tests)
diff --git a/test/lisp/emacs-lisp/ert-x-tests.el b/test/lisp/emacs-lisp/ert-x-tests.el
index 0cc89ac9977..63e7cd7608f 100644
--- a/test/lisp/emacs-lisp/ert-x-tests.el
+++ b/test/lisp/emacs-lisp/ert-x-tests.el
@@ -1,24 +1,24 @@
-;;; ert-x-tests.el --- Tests for ert-x.el
+;;; ert-x-tests.el --- Tests for ert-x.el -*- lexical-binding:t -*-
-;; Copyright (C) 2008, 2010-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2008, 2010-2022 Free Software Foundation, Inc.
;; Author: Phil Hagelberg
;; Christian Ohler <ohler@gnu.org>
;; This file is part of GNU Emacs.
-;; This program is free software: you can redistribute it and/or
-;; modify it under the terms of the GNU General Public License as
-;; published by the Free Software Foundation, either version 3 of the
-;; License, or (at your option) any later version.
-;;
-;; This program is distributed in the hope that it will be useful, but
-;; WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-;; General Public License for more details.
-;;
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
;; You should have received a copy of the GNU General Public License
-;; along with this program. If not, see `https://www.gnu.org/licenses/'.
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
@@ -82,6 +82,21 @@
(should-not (buffer-live-p buffer-1))
(should (buffer-live-p buffer-2))))))
+(ert-deftest ert-test-with-test-buffer-selected/selected ()
+ (ert-with-test-buffer-selected ()
+ (should (eq (window-buffer) (current-buffer)))))
+
+(ert-deftest ert-test-with-test-buffer-selected/modification-hooks ()
+ (ert-with-test-buffer-selected ()
+ (should (null inhibit-modification-hooks))))
+
+(ert-deftest ert-test-with-test-buffer-selected/return-value ()
+ (should (equal (ert-with-test-buffer-selected () "foo") "foo")))
+
+(ert-deftest ert-test-with-test-buffer-selected/buffer-name ()
+ (should (equal (ert-with-test-buffer (:name "foo") (buffer-name))
+ (ert-with-test-buffer-selected (:name "foo")
+ (buffer-name)))))
(ert-deftest ert-filter-string ()
(should (equal (ert-filter-string "foo bar baz" "quux")
@@ -90,10 +105,10 @@
"foo baz")))
(ert-deftest ert-propertized-string ()
- (should (ert-equal-including-properties
+ (should (equal-including-properties
(ert-propertized-string "a" '(a b) "b" '(c t) "cd")
#("abcd" 1 2 (a b) 2 4 (c t))))
- (should (ert-equal-including-properties
+ (should (equal-including-properties
(ert-propertized-string "foo " '(face italic) "bar" " baz" nil
" quux")
#("foo bar baz quux" 4 11 (face italic)))))
@@ -103,23 +118,27 @@
(ert-deftest ert-test-run-tests-interactively-2 ()
:tags '(:causes-redisplay)
- (let* ((passing-test (make-ert-test :name 'passing-test
- :body (lambda () (ert-pass))))
- (failing-test (make-ert-test :name 'failing-test
- :body (lambda ()
- (ert-info ((propertize "foo\nbar"
- 'a 'b))
- (ert-fail
- "failure message")))))
- (skipped-test (make-ert-test :name 'skipped-test
- :body (lambda () (ert-skip
- "skip message"))))
- (ert-debug-on-error nil)
- (buffer-name (generate-new-buffer-name "*ert-test-run-tests*"))
- (messages nil)
- (mock-message-fn
- (lambda (format-string &rest args)
- (push (apply #'format format-string args) messages))))
+ (cl-letf* ((passing-test (make-ert-test
+ :name 'passing-test
+ :body (lambda () (ert-pass))))
+ (failing-test (make-ert-test
+ :name 'failing-test
+ :body (lambda ()
+ (ert-info ((propertize "foo\nbar"
+ 'a 'b))
+ (ert-fail
+ "failure message")))))
+ (skipped-test (make-ert-test
+ :name 'skipped-test
+ :body (lambda () (ert-skip
+ "skip message"))))
+ (ert-debug-on-error nil)
+ (messages nil)
+ (buffer-name (generate-new-buffer-name "*ert-test-run-tests*"))
+ ((symbol-function 'message)
+ (lambda (format-string &rest args)
+ (push (apply #'format format-string args) messages)))
+ (ert--output-buffer-name buffer-name))
(cl-flet ((expected-string (with-font-lock-p)
(ert-propertized-string
"Selector: (member <passing-test> <failing-test> "
@@ -152,21 +171,19 @@
"failing-test"
nil "\n Info: " '(a b) "foo\n"
nil " " '(a b) "bar"
- nil "\n (ert-test-failed \"failure message\")\n\n\n"
- )))
+ nil "\n (ert-test-failed \"failure message\")\n\n\n")))
(save-window-excursion
(unwind-protect
(let ((case-fold-search nil))
(ert-run-tests-interactively
- `(member ,passing-test ,failing-test ,skipped-test) buffer-name
- mock-message-fn)
+ `(member ,passing-test ,failing-test ,skipped-test))
(should (equal messages `(,(concat
"Ran 3 tests, 1 results were "
"as expected, 1 unexpected, "
"1 skipped"))))
(with-current-buffer buffer-name
(font-lock-mode 0)
- (should (ert-equal-including-properties
+ (should (equal-including-properties
(ert-filter-string (buffer-string)
'("Started at:\\(.*\\)$" 1)
'("Finished at:\\(.*\\)$" 1))
@@ -175,7 +192,7 @@
;; pretend we are.
(let ((noninteractive nil))
(font-lock-mode 1))
- (should (ert-equal-including-properties
+ (should (equal-including-properties
(ert-filter-string (buffer-string)
'("Started at:\\(.*\\)$" 1)
'("Finished at:\\(.*\\)$" 1))
@@ -187,18 +204,15 @@
"Tests `ert-describe-test'."
(save-window-excursion
(ert-with-buffer-renamed ("*Help*")
- (if (< emacs-major-version 24)
- (should (equal (should-error (ert-describe-test 'ert-describe-test))
- '(error "Requires Emacs 24")))
- (ert-describe-test 'ert-test-describe-test)
- (with-current-buffer "*Help*"
- (let ((case-fold-search nil))
- (should (string-match (concat
- "\\`ert-test-describe-test is a test"
- " defined in"
- " ['`‘]ert-x-tests.elc?['’]\\.\n\n"
- "Tests ['`‘]ert-describe-test['’]\\.\n\\'")
- (buffer-string)))))))))
+ (ert-describe-test 'ert-test-describe-test)
+ (with-current-buffer "*Help*"
+ (let ((case-fold-search nil))
+ (should (string-match (concat
+ "\\`ert-test-describe-test is a test"
+ " defined in"
+ " ['`‘]ert-x-tests.elc?['’]\\.\n\n"
+ "Tests ['`‘]ert-describe-test['’]\\.\n\\'")
+ (buffer-string))))))))
(ert-deftest ert-test-message-log-truncation ()
:tags '(:causes-redisplay)
@@ -274,6 +288,62 @@ desired effect."
(cl-loop for x in '(0 1 2 3 4 t) do
(should (equal (c x) (lisp x))))))
+(ert-deftest ert-x-tests--with-temp-file-generate-suffix ()
+ (should (equal (ert--with-temp-file-generate-suffix "foo.el") "-foo"))
+ (should (equal (ert--with-temp-file-generate-suffix "foo-test.el") "-foo"))
+ (should (equal (ert--with-temp-file-generate-suffix "foo-tests.el") "-foo"))
+ (should (equal (ert--with-temp-file-generate-suffix "foo-bar-baz.el")
+ "-foo-bar-baz"))
+ (should (equal (ert--with-temp-file-generate-suffix "/foo/bar/baz.el")
+ "-baz")))
+
+(ert-deftest ert-x-tests-with-temp-file ()
+ (let (saved)
+ (ert-with-temp-file fil
+ (setq saved fil)
+ (should (file-exists-p fil))
+ (should (file-regular-p fil)))
+ (should-not (file-exists-p saved))))
+
+(ert-deftest ert-x-tests-with-temp-file/handle-error ()
+ (let (saved)
+ (ignore-errors
+ (ert-with-temp-file fil
+ (setq saved fil)
+ (error "foo")))
+ (should-not (file-exists-p saved))))
+
+(ert-deftest ert-x-tests-with-temp-file/prefix-and-suffix-kwarg ()
+ (ert-with-temp-file fil
+ :prefix "foo"
+ :suffix "bar"
+ (should (string-match "foo.*bar" fil))))
+
+(ert-deftest ert-x-tests-with-temp-file/text-kwarg ()
+ (ert-with-temp-file fil
+ :text "foobar3"
+ (let ((buf (find-file-noselect fil)))
+ (unwind-protect
+ (with-current-buffer buf
+ (should (equal (buffer-string) "foobar3")))
+ (kill-buffer buf)))))
+
+(ert-deftest ert-x-tests-with-temp-file/unknown-kwarg-signals-error ()
+ (should-error
+ (ert-with-temp-file fil :foo "foo" nil)))
+
+(ert-deftest ert-x-tests-with-temp-directory ()
+ (let (saved)
+ (ert-with-temp-directory dir
+ (setq saved dir)
+ (should (file-exists-p dir))
+ (should (file-directory-p dir))
+ (should (equal dir (file-name-as-directory dir))))
+ (should-not (file-exists-p saved))))
+
+(ert-deftest ert-x-tests-with-temp-directory/text-signals-error ()
+ (should-error
+ (ert-with-temp-directory dir :text "foo" nil)))
(provide 'ert-x-tests)
diff --git a/test/lisp/emacs-lisp/faceup-resources/faceup-test-mode.el b/test/lisp/emacs-lisp/faceup-resources/faceup-test-mode.el
new file mode 100644
index 00000000000..9b9c863aa0b
--- /dev/null
+++ b/test/lisp/emacs-lisp/faceup-resources/faceup-test-mode.el
@@ -0,0 +1,76 @@
+;;; faceup-test-mode.el --- Dummy major mode for testing `faceup'. -*- lexical-binding:t -*-
+
+;; Copyright (C) 2014-2022 Free Software Foundation, Inc.
+
+;; Author: Anders Lindgren
+;; Keywords: languages, faces
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Dummy major-mode for testing `faceup', a regression test system for
+;; font-lock keywords (syntax highlighting rules for Emacs).
+;;
+;; This mode use `syntax-propertize' to set the `syntax-table'
+;; property on "<" and ">" in "<TEXT>" to make them act like
+;; parentheses.
+;;
+;; This mode also sets the `help-echo' property on the text WARNING,
+;; the effect is that Emacs displays a tooltip when you move your
+;; mouse on to the text.
+
+;;; Code:
+
+(defvar faceup-test-mode-syntax-table
+ (make-syntax-table)
+ "Syntax table for `faceup-test-mode'.")
+
+(defvar faceup-test-font-lock-keywords
+ '(("\\_<WARNING\\_>"
+ (0 (progn
+ (add-text-properties (match-beginning 0)
+ (match-end 0)
+ '(help-echo "Balloon tip: Fly smoothly!"))
+ font-lock-warning-face))))
+ "Highlight rules for `faceup-test-mode'.")
+
+(defun faceup-test-syntax-propertize (start end)
+ (goto-char start)
+ (funcall
+ (syntax-propertize-rules
+ ("\\(<\\)\\([^<>\n]*\\)\\(>\\)"
+ (1 "() ")
+ (3 ")( ")))
+ start end))
+
+(defmacro faceup-test-define-prog-mode (mode name &rest args)
+ "Define a major mode for a programming language.
+If `prog-mode' is defined, inherit from it."
+ (declare (indent defun))
+ `(define-derived-mode
+ ,mode ,(and (fboundp 'prog-mode) 'prog-mode)
+ ,name ,@args))
+
+(faceup-test-define-prog-mode faceup-test-mode "faceup-test"
+ "Dummy major mode for testing `faceup', a test system for font-lock."
+ (setq-local syntax-propertize-function
+ #'faceup-test-syntax-propertize)
+ (setq font-lock-defaults '(faceup-test-font-lock-keywords nil)))
+
+(provide 'faceup-test-mode)
+
+;;; faceup-test-mode.el ends here
diff --git a/test/lisp/emacs-lisp/faceup-resources/faceup-test-this-file-directory.el b/test/lisp/emacs-lisp/faceup-resources/faceup-test-this-file-directory.el
new file mode 100644
index 00000000000..137b43a5dfd
--- /dev/null
+++ b/test/lisp/emacs-lisp/faceup-resources/faceup-test-this-file-directory.el
@@ -0,0 +1,32 @@
+;;; faceup-test-this-file-directory.el --- Support file for faceup tests -*- lexical-binding:t -*-
+
+;; Copyright (C) 2014-2022 Free Software Foundation, Inc.
+
+;; Author: Anders Lindgren
+;; Keywords: languages, faces
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Support file for `faceup-test-basics.el'. This file is used to test
+;; `faceup-this-file-directory' in various contexts.
+
+;;; Code:
+
+(defvar faceup-test-this-file-directory (faceup-this-file-directory))
+
+;;; faceup-test-this-file-directory.el ends here
diff --git a/test/lisp/emacs-lisp/faceup-resources/files/test1.txt b/test/lisp/emacs-lisp/faceup-resources/files/test1.txt
new file mode 100644
index 00000000000..d971f364c2d
--- /dev/null
+++ b/test/lisp/emacs-lisp/faceup-resources/files/test1.txt
@@ -0,0 +1,15 @@
+This is a test of `faceup', a regression test system for font-lock
+keywords. It should use major mode `faceup-test-mode'.
+
+WARNING: The first word on this line should use
+`font-lock-warning-face', and a tooltip should be displayed if the
+mouse pointer is moved over it.
+
+In this mode "<" and ">" are parentheses, but only when on the same
+line without any other "<" and ">" characters between them.
+<OK> <NOT <OK> >
+<
+NOT OK
+>
+
+test1.txt ends here.
diff --git a/test/lisp/emacs-lisp/faceup-resources/files/test1.txt.faceup b/test/lisp/emacs-lisp/faceup-resources/files/test1.txt.faceup
new file mode 100644
index 00000000000..ec9e82148fd
--- /dev/null
+++ b/test/lisp/emacs-lisp/faceup-resources/files/test1.txt.faceup
@@ -0,0 +1,15 @@
+This is a test of `faceup', a regression test system for font-lock
+keywords. It should use major mode `faceup-test-mode'.
+
+«(help-echo):"Balloon tip: Fly smoothly!":«w:WARNING»»: The first word on this line should use
+`font-lock-warning-face', and a tooltip should be displayed if the
+mouse pointer is moved over it.
+
+In this mode «s:"«(syntax-table):(4 . 41):<»"» and «s:"«(syntax-table):(5 . 40):>»"» are parentheses, but only when on the same
+line without any other «s:"«(syntax-table):(4 . 41):<»"» and «s:"«(syntax-table):(5 . 40):>»"» characters between them.
+«(syntax-table):(4 . 41):<»OK«(syntax-table):(5 . 40):>» <NOT «(syntax-table):(4 . 41):<»OK«(syntax-table):(5 . 40):>» >
+<
+NOT OK
+>
+
+test1.txt ends here.
diff --git a/test/lisp/emacs-lisp/faceup-tests/faceup-test-basics.el b/test/lisp/emacs-lisp/faceup-tests/faceup-test-basics.el
new file mode 100644
index 00000000000..b9fcb4e8863
--- /dev/null
+++ b/test/lisp/emacs-lisp/faceup-tests/faceup-test-basics.el
@@ -0,0 +1,269 @@
+;;; faceup-test-basics.el --- Tests for the `faceup' package. -*- lexical-binding:t -*-
+
+;; Copyright (C) 2014-2022 Free Software Foundation, Inc.
+
+;; Author: Anders Lindgren
+;; Keywords: languages, faces
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Basic tests for the `faceup' package.
+
+;;; Code:
+
+(eval-when-compile (require 'cl-lib))
+(require 'faceup)
+
+(ert-deftest faceup-functions ()
+ "Test primitive functions."
+ (should (equal (faceup-normalize-face-property '()) '()))
+ (should (equal (faceup-normalize-face-property 'a) '(a)))
+ (should (equal (faceup-normalize-face-property '(a)) '(a)))
+ (should (equal (faceup-normalize-face-property '(:x t)) '((:x t))))
+ (should (equal (faceup-normalize-face-property '(:x t a)) '((:x t))))
+ (should (equal (faceup-normalize-face-property '(:x t a b)) '((:x t))))
+ (should (equal (faceup-normalize-face-property '(a :x t)) '(a (:x t))))
+ (should (equal (faceup-normalize-face-property '(a b :x t))
+ '(a b (:x t))))
+
+ (should (equal (faceup-normalize-face-property '(:x t :y nil))
+ '((:y nil) (:x t))))
+ (should (equal (faceup-normalize-face-property '(:x t :y nil a))
+ '((:y nil) (:x t))))
+ (should (equal (faceup-normalize-face-property '(:x t :y nil a b))
+ '((:y nil) (:x t))))
+ (should (equal (faceup-normalize-face-property '(a :x t :y nil))
+ '(a (:y nil) (:x t))))
+ (should (equal (faceup-normalize-face-property '(a b :x t :y nil))
+ '(a b (:y nil) (:x t)))))
+
+
+(ert-deftest faceup-markup-basics ()
+ (should (equal (faceup-markup-string "") ""))
+ (should (equal (faceup-markup-string "test") "test")))
+
+(ert-deftest faceup-markup-escaping ()
+ (should (equal (faceup-markup-string "«") "««"))
+ (should (equal (faceup-markup-string "«A«B«C«") "««A««B««C««"))
+ (should (equal (faceup-markup-string "»") "«»"))
+ (should (equal (faceup-markup-string "»A»B»C»") "«»A«»B«»C«»")))
+
+(ert-deftest faceup-markup-plain ()
+ ;; UU
+ ;; ABCDEF
+ (should (equal (faceup-markup-string
+ #("ABCDEF" 2 4 (face underline)))
+ "AB«U:CD»EF")))
+
+(ert-deftest faceup-markup-plain-full-text ()
+ ;; UUUUUU
+ ;; ABCDEF
+ (should (equal (faceup-markup-string
+ #("ABCDEF" 0 6 (face underline)))
+ "«U:ABCDEF»")))
+
+(ert-deftest faceup-markup-anonymous-face ()
+ ;; AA
+ ;; ABCDEF
+ (should (equal (faceup-markup-string
+ #("ABCDEF" 2 4 (face (:underline t))))
+ "AB«:(:underline t):CD»EF")))
+
+(ert-deftest faceup-markup-anonymous-face-2keys ()
+ ;; AA
+ ;; ABCDEF
+ (should (equal (faceup-markup-string
+ #("ABCDEF" 2 4 (face (:foo t :bar nil))))
+ "AB«:(:foo t):«:(:bar nil):CD»»EF"))
+ ;; Plist in list.
+ (should (equal (faceup-markup-string
+ #("ABCDEF" 2 4 (face ((:foo t :bar nil)))))
+ "AB«:(:foo t):«:(:bar nil):CD»»EF"))
+ ;; Two plists.
+ (should (equal (faceup-markup-string
+ #("ABCDEF" 2 4 (face ((:foo t) (:bar nil)))))
+ "AB«:(:bar nil):«:(:foo t):CD»»EF")))
+
+(ert-deftest faceup-markup-anonymous-nested ()
+ ;; AA
+ ;; IIII
+ ;; ABCDEF
+ (should (equal (faceup-markup-string
+ #("ABCDEF"
+ 1 2 (face ((:foo t)))
+ 2 4 (face ((:bar t) (:foo t)))
+ 4 5 (face ((:foo t)))))
+ "A«:(:foo t):B«:(:bar t):CD»E»F")))
+
+(ert-deftest faceup-markup-nested ()
+ ;; UU
+ ;; IIII
+ ;; ABCDEF
+ (should (equal (faceup-markup-string
+ #("ABCDEF"
+ 1 2 (face italic)
+ 2 4 (face (underline italic))
+ 4 5 (face italic)))
+ "A«I:B«U:CD»E»F")))
+
+(ert-deftest faceup-markup-overlapping ()
+ ;; UUU
+ ;; III
+ ;; ABCDEF
+ (should (equal (faceup-markup-string
+ #("ABCDEF"
+ 1 2 (face italic)
+ 2 4 (face (underline italic))
+ 4 5 (face underline)))
+ "A«I:B«U:CD»»«U:E»F"))
+ ;; III
+ ;; UUU
+ ;; ABCDEF
+ (should (equal (faceup-markup-string
+ #("ABCDEF"
+ 1 2 (face italic)
+ 2 4 (face (italic underline))
+ 4 5 (face underline)))
+ "A«I:B»«U:«I:CD»E»F")))
+
+(ert-deftest faceup-markup-multi-face ()
+ ;; More than one face at the same location.
+ ;;
+ ;; The property to the front takes precedence, it is rendered as the
+ ;; innermost parenthesis pair.
+ (should (equal (faceup-markup-string
+ #("ABCDEF" 2 4 (face (underline italic))))
+ "AB«I:«U:CD»»EF"))
+ (should (equal (faceup-markup-string
+ #("ABCDEF" 2 4 (face (italic underline))))
+ "AB«U:«I:CD»»EF"))
+ ;; Equal ranges, full text.
+ (should (equal (faceup-markup-string
+ #("ABCDEF" 0 6 (face (underline italic))))
+ "«I:«U:ABCDEF»»"))
+ ;; Ditto, with stray markup characters.
+ (should (equal (faceup-markup-string
+ #("AB«CD»EF" 0 8 (face (underline italic))))
+ "«I:«U:AB««CD«»EF»»")))
+
+(ert-deftest faceup-markup-multi-property ()
+ (let ((faceup-properties '(alpha beta gamma)))
+ ;; One property.
+ (should (equal (faceup-markup-string
+ #("ABCDEF" 2 4 (alpha (a l p h a))))
+ "AB«(alpha):(a l p h a):CD»EF"))
+
+ ;; Two properties, inner enclosed.
+ (should (equal (faceup-markup-string
+ (let ((s (copy-sequence "ABCDEFGHIJ")))
+ (set-text-properties 2 8 '(alpha (a l p h a)) s)
+ (font-lock-append-text-property 4 6 'beta '(b e t a) s)
+ s))
+ "AB«(alpha):(a l p h a):CD«(beta):(b e t a):EF»GH»IJ"))
+
+ ;; Two properties, same end
+ (should (equal (faceup-markup-string
+ (let ((s (copy-sequence "ABCDEFGH")))
+ (set-text-properties 2 6 '(alpha (a)) s)
+ (add-text-properties 4 6 '(beta (b)) s)
+ s))
+ "AB«(alpha):(a):CD«(beta):(b):EF»»GH"))
+
+ ;; Two properties, overlap.
+ (should (equal (faceup-markup-string
+ (let ((s (copy-sequence "ABCDEFGHIJ")))
+ (set-text-properties 2 6 '(alpha (a)) s)
+ (add-text-properties 4 8 '(beta (b)) s)
+ s))
+ "AB«(alpha):(a):CD«(beta):(b):EF»»«(beta):(b):GH»IJ"))))
+
+
+(ert-deftest faceup-clean ()
+ "Test the clean features of `faceup'."
+ (should (equal (faceup-clean-string "") ""))
+ (should (equal (faceup-clean-string "test") "test"))
+ (should (equal (faceup-clean-string "AB«U:CD»EF") "ABCDEF"))
+ (should (equal (faceup-clean-string "«U:ABCDEF»") "ABCDEF"))
+ (should (equal (faceup-clean-string "A«I:B«U:CD»E»F") "ABCDEF"))
+ (should (equal (faceup-clean-string "A«I:B«U:CD»»«U:E»F") "ABCDEF"))
+ (should (equal (faceup-clean-string "AB«I:«U:CD»»EF") "ABCDEF"))
+ (should (equal (faceup-clean-string "«I:«U:ABCDEF»»") "ABCDEF"))
+ (should (equal (faceup-clean-string "«(foo)I:ABC»DEF") "ABCDEF"))
+ (should (equal (faceup-clean-string "«:(:foo t):ABC»DEF") "ABCDEF"))
+ ;; Escaped markup characters.
+ (should (equal (faceup-clean-string "««") "«"))
+ (should (equal (faceup-clean-string "«»") "»"))
+ (should (equal (faceup-clean-string "A«I:B«U:CD»«»»«U:E»F") "ABCD»EF")))
+
+
+(ert-deftest faceup-render ()
+ "Test the render features of `faceup'."
+ (should (equal (faceup-render-string "") ""))
+ (should (equal (faceup-render-string "««") "«"))
+ (should (equal (faceup-render-string "«»") "»"))
+ (should (equal (faceup-render-string "A«I:B«U:CD»«»»«U:E»F") "ABCD»EF")))
+
+
+(defvar faceup-test-resources-directory
+ (concat (file-name-directory
+ (substring (faceup-this-file-directory) 0 -1))
+ "faceup-resources/")
+ "The `faceup-resources' directory.")
+
+
+(defvar faceup-test-this-file-directory nil
+ "The result of `faceup-this-file-directory' in various contexts.
+
+This is set by the file test support file
+`faceup-test-this-file-directory.el'.")
+
+
+(ert-deftest faceup-directory ()
+ "Test `faceup-this-file-directory'."
+ (let ((file (concat faceup-test-resources-directory
+ "faceup-test-this-file-directory.el"))
+ (load-file-name nil))
+ ;; Test normal load.
+ (makunbound 'faceup-test-this-file-directory)
+ (load file nil :nomessage)
+ (should (equal faceup-test-this-file-directory
+ faceup-test-resources-directory))
+ ;; Test `eval-buffer'.
+ (makunbound 'faceup-test-this-file-directory)
+ (save-excursion
+ (find-file file)
+ (eval-buffer))
+ (should (equal faceup-test-this-file-directory
+ faceup-test-resources-directory))
+ ;; Test `eval-defun'.
+ (makunbound 'faceup-test-this-file-directory)
+ (save-excursion
+ (find-file file)
+ (save-excursion
+ (goto-char (point-min))
+ (while (not (eobp))
+ ;; Note: In batch mode, this prints the result of the
+ ;; evaluation. Unfortunately, this is hard to fix.
+ (eval-defun nil)
+ (forward-sexp))))
+ (should (equal faceup-test-this-file-directory
+ faceup-test-resources-directory))))
+
+(provide 'faceup-test-basics)
+
+;;; faceup-test-basics.el ends here
diff --git a/test/lisp/emacs-lisp/faceup-tests/faceup-test-files.el b/test/lisp/emacs-lisp/faceup-tests/faceup-test-files.el
new file mode 100644
index 00000000000..f07b8d830b9
--- /dev/null
+++ b/test/lisp/emacs-lisp/faceup-tests/faceup-test-files.el
@@ -0,0 +1,63 @@
+;;; faceup-test-files.el --- Self test of `faceup' using dummy major mode. -*- lexical-binding:t -*-
+
+;; Copyright (C) 2014-2022 Free Software Foundation, Inc.
+
+;; Author: Anders Lindgren
+;; Keywords: languages, faces
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Self test of `faceup' with a major mode that sets both the
+;; `syntax-table' and the `echo-help' property.
+;;
+;; This file can also be seen as a blueprint of test cases for real
+;; major modes.
+
+;;; Code:
+
+(require 'faceup)
+
+;; Note: The byte compiler needs the value to load `faceup-test-mode',
+;; hence the `eval-and-compile'.
+(eval-and-compile
+ (defvar faceup-test-files-dir (faceup-this-file-directory)
+ "The directory of this file."))
+
+(require 'faceup-test-mode
+ (concat faceup-test-files-dir
+ "../faceup-resources/"
+ "faceup-test-mode.el"))
+
+(defun faceup-test-files-check-one (file)
+ "Test that FILE is fontified as the .faceup file describes.
+
+FILE is interpreted as relative to this source directory."
+ (let ((faceup-properties '(face syntax-table help-echo)))
+ (faceup-test-font-lock-file 'faceup-test-mode
+ (concat
+ faceup-test-files-dir
+ "../faceup-resources/"
+ file))))
+(faceup-defexplainer faceup-test-files-check-one)
+
+(ert-deftest faceup-files ()
+ (should (faceup-test-files-check-one "files/test1.txt")))
+
+(provide 'faceup-test-files)
+
+;;; faceup-test-files.el ends here
diff --git a/test/lisp/emacs-lisp/find-func-tests.el b/test/lisp/emacs-lisp/find-func-tests.el
new file mode 100644
index 00000000000..d18a9dc1a94
--- /dev/null
+++ b/test/lisp/emacs-lisp/find-func-tests.el
@@ -0,0 +1,125 @@
+;;; find-func-tests.el --- Unit tests for find-func.el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
+;; Keywords:
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;
+
+;;; Code:
+
+(require 'ert-x) ;For `ert-simulate-keys'.
+(require 'find-func)
+
+(ert-deftest find-func-tests--library-completion () ;bug#43393
+ ;; FIXME: How can we make this work in batch (see also
+ ;; `mule-cmds--test-universal-coding-system-argument')?
+ ;; (skip-unless (not noninteractive))
+ ;; Check that `partial-completion' works when completing library names.
+ (should (equal "org/org"
+ (ert-simulate-keys
+ (kbd "o / o r g TAB RET")
+ (read-library-name))))
+ ;; Check that absolute file names also work.
+ (should (equal (expand-file-name "nxml/" data-directory)
+ (ert-simulate-keys
+ (concat data-directory (kbd "n x / TAB RET"))
+ (read-library-name)))))
+
+(ert-deftest find-func-tests--locate-symbols ()
+ (should (cdr
+ (find-function-search-for-symbol
+ #'goto-line nil "simple")))
+ (should (cdr
+ (find-function-search-for-symbol
+ 'minibuffer-history 'defvar "simple")))
+ (should (cdr
+ (find-function-search-for-symbol
+ 'with-current-buffer nil "subr")))
+ (should (cdr
+ (find-function-search-for-symbol
+ 'font-lock-warning-face 'defface "font-lock")))
+ (should-not (cdr
+ (find-function-search-for-symbol
+ 'wrong-variable 'defvar "simple")))
+ (should-not (cdr
+ (find-function-search-for-symbol
+ 'wrong-function nil "simple")))
+ (should (cdr (find-function-noselect #'goto-line)))
+ (should (cdr (find-function-noselect #'goto-char)))
+ ;; Setting LISP-ONLY and passing a primitive should error.
+ (should-error (find-function-noselect #'goto-char t))
+ (should-error (find-function-noselect 'wrong-function)))
+
+(defun test-locate-helper (func &optional expected-result)
+ "Assert on the result of `find-function-library' for FUNC.
+EXPECTED-RESULT is an alist (FUNC . LIBRARY) with the
+expected function symbol and function library, respectively."
+ (cl-destructuring-bind (orig-function . library)
+ (find-function-library func)
+ (cl-destructuring-bind (expected-func . expected-library)
+ expected-result
+ (should (eq orig-function expected-func))
+ (should (and
+ (not (string-empty-p expected-library))
+ (string-match-p expected-library library))))))
+
+(ert-deftest find-func-tests--locate-library ()
+ (test-locate-helper #'goto-line '(goto-line . "simple"))
+ (test-locate-helper #'forward-char '(forward-char . "cmds.c"))
+ (should-error (test-locate-helper 'wrong-function)))
+
+(ert-deftest find-func-tests--locate-adviced-symbols ()
+ (defun my-message ()
+ (message "Hello!"))
+ (advice-add #'mark-sexp :around 'my-message)
+ (test-locate-helper #'mark-sexp '(mark-sexp . "lisp"))
+ (advice-remove #'mark-sexp 'my-message))
+
+(ert-deftest find-func-tests--find-library-verbose ()
+ (unwind-protect
+ (progn
+ (advice-add 'dired :before #'ignore)
+ ;; bug#41104
+ (should (equal (find-function-library #'dired) '(dired . "dired"))))
+ (advice-remove 'dired #'ignore))
+
+ (find-function-library #'join-line nil t)
+ (with-current-buffer "*Messages*"
+ (save-excursion
+ (goto-char (point-max))
+ (skip-chars-backward "\n")
+ (should (string-match-p
+ ".join-line. is an alias for .delete-indentation."
+ (buffer-substring (pos-bol) (point)))))))
+
+;; Avoid a byte-compilation warning that may confuse people reading
+;; the result of the following test.
+(declare-function compilation--message->loc nil "compile")
+
+(ert-deftest find-func-tests--locate-macro-generated-symbols () ;bug#45443
+ (should (cdr (find-function-search-for-symbol
+ #'compilation--message->loc nil "compile")))
+ (should (cdr (find-function-search-for-symbol
+ 'c-mode-hook 'defvar "cc-mode"))))
+
+(provide 'find-func-tests)
+;;; find-func-tests.el ends here
diff --git a/test/lisp/emacs-lisp/float-sup-tests.el b/test/lisp/emacs-lisp/float-sup-tests.el
new file mode 100644
index 00000000000..f4353d9e855
--- /dev/null
+++ b/test/lisp/emacs-lisp/float-sup-tests.el
@@ -0,0 +1,33 @@
+;;; float-sup-tests.el --- Tests for float-sup.el -*- lexical-binding:t -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+
+(ert-deftest float-sup-degrees-and-radians ()
+ (should (equal (degrees-to-radians 180.0) float-pi))
+ (should (equal (radians-to-degrees float-pi) 180.0))
+ (should (equal (radians-to-degrees (degrees-to-radians 360.0)) 360.0))
+ (should (equal (degrees-to-radians (radians-to-degrees float-pi)) float-pi)))
+
+(provide 'float-sup-tests)
+;;; float-sup-tests.el ends here
diff --git a/test/lisp/emacs-lisp/generator-tests.el b/test/lisp/emacs-lisp/generator-tests.el
index 4cc6c841dac..b7a21d49b2f 100644
--- a/test/lisp/emacs-lisp/generator-tests.el
+++ b/test/lisp/emacs-lisp/generator-tests.el
@@ -1,6 +1,6 @@
;;; generator-tests.el --- Testing generators -*- lexical-binding: t -*-
-;; Copyright (C) 2015-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2022 Free Software Foundation, Inc.
;; Author: Daniel Colascione <dancol@dancol.org>
;; Keywords:
@@ -22,10 +22,16 @@
;;; Commentary:
+;; Unit tests for generator.el.
+
+;;; Code:
+
(require 'generator)
(require 'ert)
(require 'cl-lib)
+;;; Code:
+
(defun generator-list-subrs ()
(cl-loop for x being the symbols
when (and (fboundp x)
@@ -38,8 +44,8 @@
`cps-testcase' defines an ERT testcase called NAME that evaluates
BODY twice: once using ordinary `eval' and once using
lambda-generators. The test ensures that the two forms produce
-identical output.
-"
+identical output."
+ (declare (indent 1))
`(progn
(ert-deftest ,name ()
(should
@@ -57,8 +63,6 @@ identical output.
(let ((cps-inhibit-atomic-optimization t))
(iter-lambda () (iter-yield (progn ,@body)))))))))))
-(put 'cps-testcase 'lisp-indent-function 1)
-
(defvar *cps-test-i* nil)
(defun cps-get-test-i ()
*cps-test-i*)
@@ -70,7 +74,7 @@ identical output.
(cps-testcase cps-prog1-b (prog1 1))
(cps-testcase cps-prog1-c (prog2 1 2 3))
(cps-testcase cps-quote (progn 'hello))
-(cps-testcase cps-function (progn #'hello))
+(cps-testcase cps-function (progn #'message))
(cps-testcase cps-and-fail (and 1 nil 2))
(cps-testcase cps-and-succeed (and 1 2 3))
@@ -81,9 +85,9 @@ identical output.
(cps-testcase cps-or-empty (or))
(cps-testcase cps-let* (let* ((i 10)) i))
-(cps-testcase cps-let*-shadow-empty (let* ((i 10)) (let (i) i)))
+(cps-testcase cps-let*-shadow-empty (let* ((i 10)) i (let ((i nil)) i)))
(cps-testcase cps-let (let ((i 10)) i))
-(cps-testcase cps-let-shadow-empty (let ((i 10)) (let (i) i)))
+(cps-testcase cps-let-shadow-empty (let ((i 10)) i (let ((i nil)) i)))
(cps-testcase cps-let-novars (let nil 42))
(cps-testcase cps-let*-novars (let* nil 42))
@@ -91,7 +95,7 @@ identical output.
(let ((a 5) (b 6)) (let ((a b) (b a)) (list a b))))
(cps-testcase cps-let*-parallel
- (let* ((a 5) (b 6)) (let* ((a b) (b a)) (list a b))))
+ (let* ((a 5) (b 6)) a (let* ((a b) (b a)) (list a b))))
(cps-testcase cps-while-dynamic
(setq *cps-test-i* 0)
@@ -215,7 +219,7 @@ identical output.
(should (eql (iter-next it -1) 42))
(should (eql (iter-next it -1) -1))))
-(ert-deftest cps-loop ()
+(ert-deftest cps-loop-2 ()
(should
(equal (cl-loop for x iter-by (mygenerator 42)
collect x)
@@ -267,7 +271,7 @@ identical output.
(unwind-protect
(progn
(iter-yield 1)
- (error "test")
+ (error "Test")
(iter-yield 2))
(cl-incf nr-unwound))))))
(should (equal (iter-next iter) 1))
@@ -282,3 +286,35 @@ identical output.
(ert-deftest cps-test-declarations-preserved ()
(should (equal (documentation 'generator-with-docstring) "Documentation!"))
(should (equal (get 'generator-with-docstring 'lisp-indent-function) 5)))
+
+(ert-deftest cps-iter-lambda-with-dynamic-binding ()
+ "`iter-lambda' with dynamic binding produces correct result (bug#25965)."
+ (should (= 1
+ (iter-next
+ (funcall (iter-lambda ()
+ (let* ((fill-column 10) ;;any special variable will do
+ (i 0)
+ (j (setq i (1+ i))))
+ (iter-yield i))))))))
+
+(ert-deftest iter-lambda-variable-shadowing ()
+ "`iter-lambda' forms which have local variable shadowing (Bug#26073)."
+ (should (equal (iter-next
+ (funcall (iter-lambda ()
+ (let ((it 1))
+ (iter-yield (funcall
+ (lambda (it) (- it))
+ (1+ it)))))))
+ -2)))
+
+(defun generator-tests-edebug ()) ; silence byte-compiler
+(ert-deftest generator-tests-edebug ()
+ "Check that Bug#40434 is fixed."
+ (with-temp-buffer
+ (prin1 '(iter-defun generator-tests-edebug ()
+ (iter-yield 123))
+ (current-buffer))
+ (edebug-defun))
+ (should (eql (iter-next (generator-tests-edebug)) 123)))
+
+;;; generator-tests.el ends here
diff --git a/test/lisp/emacs-lisp/gv-tests.el b/test/lisp/emacs-lisp/gv-tests.el
index 93f70827133..0757e3c7aa5 100644
--- a/test/lisp/emacs-lisp/gv-tests.el
+++ b/test/lisp/emacs-lisp/gv-tests.el
@@ -1,6 +1,6 @@
;;; gv-tests.el --- tests for gv.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2017 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2022 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -19,23 +19,23 @@
;;; Code:
+(require 'edebug)
(require 'ert)
+(require 'ert-x)
(eval-when-compile (require 'cl-lib))
(cl-defmacro gv-tests--in-temp-dir ((elvar elcvar)
(&rest filebody)
&rest body)
(declare (indent 2))
- `(let ((default-directory (make-temp-file "gv-test" t)))
- (unwind-protect
- (let ((,elvar "gv-test-deffoo.el")
- (,elcvar "gv-test-deffoo.elc"))
- (with-temp-file ,elvar
- (insert ";; -*- lexical-binding: t; -*-\n")
- (dolist (form ',filebody)
- (pp form (current-buffer))))
- ,@body)
- (delete-directory default-directory t))))
+ `(ert-with-temp-directory default-directory
+ (let ((,elvar "gv-test-deffoo.el")
+ (,elcvar "gv-test-deffoo.elc"))
+ (with-temp-file ,elvar
+ (insert ";; -*- lexical-binding: t; -*-\n")
+ (dolist (form ',filebody)
+ (pp form (current-buffer))))
+ ,@body)))
(ert-deftest gv-define-expander-in-file ()
(gv-tests--in-temp-dir (el elc)
@@ -82,7 +82,10 @@
(with-temp-buffer
(call-process (concat invocation-directory invocation-name)
nil '(t t) nil
- "-Q" "-batch" "--eval" (prin1-to-string `(byte-compile-file ,el))
+ "-Q" "-batch"
+ "--eval" (prin1-to-string
+ `(let ((backtrace-on-error-noninteractive nil))
+ (byte-compile-file ,el)))
"-l" elc)
(should (equal (buffer-string)
"Symbol's function definition is void: \\(setf\\ gv-test-foo\\)\n")))))
@@ -132,10 +135,71 @@
"-Q" "-batch" "--eval" (prin1-to-string `(byte-compile-file ,el))
"-l" elc
"--eval"
- (prin1-to-string '(progn (setf (gv-test-foo gv-test-pair) 99)
- (message "%d" (car gv-test-pair)))))
- (should (equal (buffer-string)
- "Symbol's function definition is void: \\(setf\\ gv-test-foo\\)\n")))))
+ (prin1-to-string
+ '(let ((backtrace-on-error-noninteractive nil))
+ (setf (gv-test-foo gv-test-pair) 99)
+ (message "%d" (car gv-test-pair)))))
+ (should (string-match
+ "\\`Symbol.s function definition is void: \\\\(setf\\\\ gv-test-foo\\\\)\n\\'"
+ (buffer-string))))))
+
+(ert-deftest gv-setter-edebug ()
+ "Check that a setter can be defined and edebugged together with
+its getter (Bug#41853)."
+ (with-temp-buffer
+ (let ((edebug-all-defs t)
+ (edebug-initial-mode 'Go-nonstop))
+ (dolist (form '((defun gv-setter-edebug-help (b) b)
+ (defun gv-setter-edebug-get (a b)
+ (get a (gv-setter-edebug-help b)))
+ (gv-define-setter gv-setter-edebug-get (x a b)
+ `(setf (get ,a (gv-setter-edebug-help ,b)) ,x))
+ (push 123 (gv-setter-edebug-get 'gv-setter-edebug
+ 'gv-setter-edebug-prop))))
+ (print form (current-buffer)))
+ ;; Only check whether evaluation works in general.
+ (eval-buffer)))
+ (should (equal (get 'gv-setter-edebug 'gv-setter-edebug-prop) '(123))))
+
+(ert-deftest gv-plist-get ()
+ (require 'cl-lib)
+
+ ;; Simple setf usage for plist-get.
+ (should (equal (let ((target '(:a "a" :b "b" :c "c")))
+ (setf (plist-get target :b) "modify")
+ target)
+ '(:a "a" :b "modify" :c "c")))
+
+ ;; Other function (cl-rotatef) usage for plist-get.
+ (should (equal (let ((target '(:a "a" :b "b" :c "c")))
+ (cl-rotatef (plist-get target :b) (plist-get target :c))
+ target)
+ '(:a "a" :b "c" :c "b")))
+
+ ;; Add new key value pair at top of list if setf for missing key.
+ (should (equal (let ((target '(:a "a" :b "b" :c "c")))
+ (setf (plist-get target :d) "modify")
+ target)
+ '(:d "modify" :a "a" :b "b" :c "c")))
+
+ ;; Rotate with missing value.
+ ;; The value corresponding to the missing key is assumed to be nil.
+ (should (equal (let ((target '(:a "a" :b "b" :c "c")))
+ (cl-rotatef (plist-get target :b) (plist-get target :d))
+ target)
+ '(:d "b" :a "a" :b nil :c "c")))
+
+ ;; Simple setf usage for plist-get. (symbol plist)
+ (should (equal (let ((target '(a "a" b "b" c "c")))
+ (setf (plist-get target 'b) "modify")
+ target)
+ '(a "a" b "modify" c "c")))
+
+ ;; Other function (cl-rotatef) usage for plist-get. (symbol plist)
+ (should (equal (let ((target '(a "a" b "b" c "c")))
+ (cl-rotatef (plist-get target 'b) (plist-get target 'c))
+ target)
+ '(a "a" b "c" c "b"))))
;; `ert-deftest' messes up macroexpansion when the test file itself is
;; compiled (see Bug #24402).
diff --git a/test/lisp/emacs-lisp/hierarchy-tests.el b/test/lisp/emacs-lisp/hierarchy-tests.el
new file mode 100644
index 00000000000..41d3f2f3ccf
--- /dev/null
+++ b/test/lisp/emacs-lisp/hierarchy-tests.el
@@ -0,0 +1,556 @@
+;;; hierarchy-tests.el --- Tests for hierarchy.el -*- lexical-binding:t -*-
+
+;; Copyright (C) 2017-2019 Damien Cassou
+
+;; Author: Damien Cassou <damien@cassou.me>
+;; Maintainer: emacs-devel@gnu.org
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Tests for hierarchy.el
+
+;;; Code:
+
+(require 'ert)
+(require 'hierarchy)
+
+(defun hierarchy-animals ()
+ "Create a sorted animal hierarchy."
+ (let ((parentfn (lambda (item) (cl-case item
+ (dove 'bird)
+ (pigeon 'bird)
+ (bird 'animal)
+ (dolphin 'animal)
+ (cow 'animal))))
+ (hierarchy (hierarchy-new)))
+ (hierarchy-add-tree hierarchy 'dove parentfn)
+ (hierarchy-add-tree hierarchy 'pigeon parentfn)
+ (hierarchy-add-tree hierarchy 'dolphin parentfn)
+ (hierarchy-add-tree hierarchy 'cow parentfn)
+ (hierarchy-sort hierarchy)
+ hierarchy))
+
+(ert-deftest hierarchy-add-one-root ()
+ (let ((parentfn (lambda (_) nil))
+ (hierarchy (hierarchy-new)))
+ (hierarchy-add-tree hierarchy 'animal parentfn)
+ (should (equal (hierarchy-roots hierarchy) '(animal)))))
+
+(ert-deftest hierarchy-add-one-item-with-parent ()
+ (let ((parentfn (lambda (item)
+ (cl-case item
+ (bird 'animal))))
+ (hierarchy (hierarchy-new)))
+ (hierarchy-add-tree hierarchy 'bird parentfn)
+ (should (equal (hierarchy-roots hierarchy) '(animal)))
+ (should (equal (hierarchy-children hierarchy 'animal) '(bird)))))
+
+(ert-deftest hierarchy-add-one-item-with-parent-and-grand-parent ()
+ (let ((parentfn (lambda (item)
+ (cl-case item
+ (dove 'bird)
+ (bird 'animal))))
+ (hierarchy (hierarchy-new)))
+ (hierarchy-add-tree hierarchy 'dove parentfn)
+ (should (equal (hierarchy-roots hierarchy) '(animal)))
+ (should (equal (hierarchy-children hierarchy 'animal) '(bird)))
+ (should (equal (hierarchy-children hierarchy 'bird) '(dove)))))
+
+(ert-deftest hierarchy-add-same-root-twice ()
+ (let ((parentfn (lambda (_) nil))
+ (hierarchy (hierarchy-new)))
+ (hierarchy-add-tree hierarchy 'animal parentfn)
+ (hierarchy-add-tree hierarchy 'animal parentfn)
+ (should (equal (hierarchy-roots hierarchy) '(animal)))))
+
+(ert-deftest hierarchy-add-same-child-twice ()
+ (let ((parentfn (lambda (item)
+ (cl-case item
+ (bird 'animal))))
+ (hierarchy (hierarchy-new)))
+ (hierarchy-add-tree hierarchy 'bird parentfn)
+ (hierarchy-add-tree hierarchy 'bird parentfn)
+ (should (equal (hierarchy-roots hierarchy) '(animal)))
+ (should (equal (hierarchy-children hierarchy 'animal) '(bird)))))
+
+(ert-deftest hierarchy-add-item-and-its-parent ()
+ (let ((parentfn (lambda (item)
+ (cl-case item
+ (bird 'animal))))
+ (hierarchy (hierarchy-new)))
+ (hierarchy-add-tree hierarchy 'bird parentfn)
+ (hierarchy-add-tree hierarchy 'animal parentfn)
+ (should (equal (hierarchy-roots hierarchy) '(animal)))
+ (should (equal (hierarchy-children hierarchy 'animal) '(bird)))))
+
+(ert-deftest hierarchy-add-item-and-its-child ()
+ (let ((parentfn (lambda (item)
+ (cl-case item
+ (bird 'animal))))
+ (hierarchy (hierarchy-new)))
+ (hierarchy-add-tree hierarchy 'animal parentfn)
+ (hierarchy-add-tree hierarchy 'bird parentfn)
+ (should (equal (hierarchy-roots hierarchy) '(animal)))
+ (should (equal (hierarchy-children hierarchy 'animal) '(bird)))))
+
+(ert-deftest hierarchy-add-two-items-sharing-parent ()
+ (let ((parentfn (lambda (item)
+ (cl-case item
+ (dove 'bird)
+ (pigeon 'bird))))
+ (hierarchy (hierarchy-new)))
+ (hierarchy-add-tree hierarchy 'dove parentfn)
+ (hierarchy-add-tree hierarchy 'pigeon parentfn)
+ (should (equal (hierarchy-roots hierarchy) '(bird)))
+ (should (equal (hierarchy-children hierarchy 'bird) '(dove pigeon)))))
+
+(ert-deftest hierarchy-add-two-hierarchies ()
+ (let ((parentfn (lambda (item)
+ (cl-case item
+ (dove 'bird)
+ (circle 'shape))))
+ (hierarchy (hierarchy-new)))
+ (hierarchy-add-tree hierarchy 'dove parentfn)
+ (hierarchy-add-tree hierarchy 'circle parentfn)
+ (should (equal (hierarchy-roots hierarchy) '(bird shape)))
+ (should (equal (hierarchy-children hierarchy 'bird) '(dove)))
+ (should (equal (hierarchy-children hierarchy 'shape) '(circle)))))
+
+(ert-deftest hierarchy-add-with-childrenfn ()
+ (let ((childrenfn (lambda (item)
+ (cl-case item
+ (animal '(bird))
+ (bird '(dove pigeon)))))
+ (hierarchy (hierarchy-new)))
+ (hierarchy-add-tree hierarchy 'animal nil childrenfn)
+ (should (equal (hierarchy-roots hierarchy) '(animal)))
+ (should (equal (hierarchy-children hierarchy 'animal) '(bird)))
+ (should (equal (hierarchy-children hierarchy 'bird) '(dove pigeon)))))
+
+(ert-deftest hierarchy-add-with-parentfn-and-childrenfn ()
+ (let ((parentfn (lambda (item)
+ (cl-case item
+ (bird 'animal)
+ (animal 'life-form))))
+ (childrenfn (lambda (item)
+ (cl-case item
+ (bird '(dove pigeon))
+ (pigeon '(ashy-wood-pigeon)))))
+ (hierarchy (hierarchy-new)))
+ (hierarchy-add-tree hierarchy 'bird parentfn childrenfn)
+ (should (equal (hierarchy-roots hierarchy) '(life-form)))
+ (should (equal (hierarchy-children hierarchy 'life-form) '(animal)))
+ (should (equal (hierarchy-children hierarchy 'animal) '(bird)))
+ (should (equal (hierarchy-children hierarchy 'bird) '(dove pigeon)))
+ (should (equal (hierarchy-children hierarchy 'pigeon) '(ashy-wood-pigeon)))))
+
+(ert-deftest hierarchy-add-twice-with-parentfn-and-childrenfn ()
+ (let* ((parentfn (lambda (item)
+ (cl-case item
+ (dove 'bird)
+ (bird 'animal))))
+ (childrenfn (lambda (item)
+ (cl-case item
+ (animal '(bird))
+ (bird '(dove)))))
+ (hierarchy (hierarchy-new)))
+ (hierarchy-add-tree hierarchy 'bird parentfn childrenfn)
+ (should (equal (hierarchy-children hierarchy 'animal) '(bird)))
+ (should (equal (hierarchy-children hierarchy 'bird) '(dove)))))
+
+(ert-deftest hierarchy-add-trees ()
+ (let ((parentfn (lambda (item)
+ (cl-case item
+ (dove 'bird)
+ (pigeon 'bird)
+ (bird 'animal))))
+ (hierarchy (hierarchy-new)))
+ (hierarchy-add-trees hierarchy '(dove pigeon) parentfn)
+ (should (equal (hierarchy-roots hierarchy) '(animal)))
+ (should (equal (hierarchy-children hierarchy 'animal) '(bird)))
+ (should (equal (hierarchy-children hierarchy 'bird) '(dove pigeon)))))
+
+(ert-deftest hierarchy-from-list ()
+ (let ((hierarchy (hierarchy-from-list
+ '(animal (bird (dove)
+ (pigeon))
+ (cow)
+ (dolphin)))))
+ (hierarchy-sort hierarchy (lambda (item1 item2)
+ (string< (car item1)
+ (car item2))))
+ (should (equal (hierarchy-to-string hierarchy (lambda (item) (symbol-name (car item))))
+ "animal\n bird\n dove\n pigeon\n cow\n dolphin\n"))))
+
+(ert-deftest hierarchy-from-list-with-duplicates ()
+ (let ((hierarchy (hierarchy-from-list
+ '(a (b) (b))
+ t)))
+ (hierarchy-sort hierarchy (lambda (item1 item2)
+ ;; sort by ID
+ (< (car item1) (car item2))))
+ (should (equal (hierarchy-length hierarchy) 3))
+ (should (equal (hierarchy-to-string
+ hierarchy
+ (lambda (item)
+ (format "%s(%s)"
+ (cadr item)
+ (car item))))
+ "a(1)\n b(2)\n b(3)\n"))))
+
+(ert-deftest hierarchy-from-list-with-childrenfn ()
+ (let ((hierarchy (hierarchy-from-list
+ "abc"
+ nil
+ (lambda (item)
+ (when (string= item "abc")
+ (split-string item "" t))))))
+ (hierarchy-sort hierarchy (lambda (item1 item2) (string< item1 item2)))
+ (should (equal (hierarchy-length hierarchy) 4))
+ (should (equal (hierarchy-to-string hierarchy)
+ "abc\n a\n b\n c\n"))))
+
+(ert-deftest hierarchy-add-relation-check-error-when-different-parent ()
+ (let ((parentfn (lambda (item)
+ (cl-case item
+ (bird 'animal))))
+ (hierarchy (hierarchy-new)))
+ (hierarchy-add-tree hierarchy 'bird parentfn)
+ (should-error
+ (hierarchy--add-relation hierarchy 'bird 'cow #'identity))))
+
+(ert-deftest hierarchy-empty-p-return-non-nil-for-empty ()
+ (should (hierarchy-empty-p (hierarchy-new))))
+
+(ert-deftest hierarchy-empty-p-return-nil-for-non-empty ()
+ (should-not (hierarchy-empty-p (hierarchy-animals))))
+
+(ert-deftest hierarchy-length-of-empty-is-0 ()
+ (should (equal (hierarchy-length (hierarchy-new)) 0)))
+
+(ert-deftest hierarchy-length-of-non-empty-counts-items ()
+ (let ((parentfn (lambda (item)
+ (cl-case item
+ (bird 'animal)
+ (dove 'bird)
+ (pigeon 'bird))))
+ (hierarchy (hierarchy-new)))
+ (hierarchy-add-tree hierarchy 'dove parentfn)
+ (hierarchy-add-tree hierarchy 'pigeon parentfn)
+ (should (equal (hierarchy-length hierarchy) 4))))
+
+(ert-deftest hierarchy-has-root ()
+ (let ((parentfn (lambda (item)
+ (cl-case item
+ (bird 'animal)
+ (dove 'bird)
+ (pigeon 'bird))))
+ (hierarchy (hierarchy-new)))
+ (should-not (hierarchy-has-root hierarchy 'animal))
+ (should-not (hierarchy-has-root hierarchy 'bird))
+ (hierarchy-add-tree hierarchy 'dove parentfn)
+ (hierarchy-add-tree hierarchy 'pigeon parentfn)
+ (should (hierarchy-has-root hierarchy 'animal))
+ (should-not (hierarchy-has-root hierarchy 'bird))))
+
+(ert-deftest hierarchy-leafs ()
+ (let ((animals (hierarchy-animals)))
+ (should (equal (hierarchy-leafs animals)
+ '(dove pigeon dolphin cow)))))
+
+(ert-deftest hierarchy-leafs-includes-lonely-roots ()
+ (let ((parentfn (lambda (_) nil))
+ (hierarchy (hierarchy-new)))
+ (hierarchy-add-tree hierarchy 'foo parentfn)
+ (should (equal (hierarchy-leafs hierarchy)
+ '(foo)))))
+
+(ert-deftest hierarchy-leafs-of-node ()
+ (let ((animals (hierarchy-animals)))
+ (should (equal (hierarchy-leafs animals 'cow) '()))
+ (should (equal (hierarchy-leafs animals 'animal) '(dove pigeon dolphin cow)))
+ (should (equal (hierarchy-leafs animals 'bird) '(dove pigeon)))
+ (should (equal (hierarchy-leafs animals 'dove) '()))))
+
+(ert-deftest hierarchy-child-p ()
+ (let ((animals (hierarchy-animals)))
+ (should (hierarchy-child-p animals 'dove 'bird))
+ (should (hierarchy-child-p animals 'bird 'animal))
+ (should (hierarchy-child-p animals 'cow 'animal))
+ (should-not (hierarchy-child-p animals 'cow 'bird))
+ (should-not (hierarchy-child-p animals 'bird 'cow))
+ (should-not (hierarchy-child-p animals 'animal 'dove))
+ (should-not (hierarchy-child-p animals 'animal 'bird))))
+
+(ert-deftest hierarchy-descendant ()
+ (let ((animals (hierarchy-animals)))
+ (should (hierarchy-descendant-p animals 'dove 'animal))
+ (should (hierarchy-descendant-p animals 'dove 'bird))
+ (should (hierarchy-descendant-p animals 'bird 'animal))
+ (should (hierarchy-descendant-p animals 'cow 'animal))
+ (should-not (hierarchy-descendant-p animals 'cow 'bird))
+ (should-not (hierarchy-descendant-p animals 'bird 'cow))
+ (should-not (hierarchy-descendant-p animals 'animal 'dove))
+ (should-not (hierarchy-descendant-p animals 'animal 'bird))))
+
+(ert-deftest hierarchy-descendant-if-not-same ()
+ (let ((animals (hierarchy-animals)))
+ (should-not (hierarchy-descendant-p animals 'cow 'cow))
+ (should-not (hierarchy-descendant-p animals 'dove 'dove))
+ (should-not (hierarchy-descendant-p animals 'bird 'bird))
+ (should-not (hierarchy-descendant-p animals 'animal 'animal))))
+
+;; keywords supported: :test :key
+(ert-deftest hierarchy--set-equal ()
+ (should (hierarchy--set-equal '(1 2 3) '(1 2 3)))
+ (should (hierarchy--set-equal '(1 2 3) '(3 2 1)))
+ (should (hierarchy--set-equal '(3 2 1) '(1 2 3)))
+ (should-not (hierarchy--set-equal '(2 3) '(3 2 1)))
+ (should-not (hierarchy--set-equal '(1 2 3) '(2 3)))
+ (should-not (hierarchy--set-equal '("1" "2") '("2" "1") :test #'eq))
+ (should (hierarchy--set-equal '("1" "2") '("2" "1") :test #'equal))
+ (should-not (hierarchy--set-equal '(1 2) '(-1 -2)))
+ (should (hierarchy--set-equal '(1 2) '(-1 -2) :key #'abs))
+ (should-not (hierarchy--set-equal '(("1" 1) ("2" 1)) '(("1" 2) ("2" 2))))
+ (should-not (hierarchy--set-equal '(("1" 1) ("2" 1)) '(("1" 2) ("2" 2)) :key #'car))
+ (should-not (hierarchy--set-equal '(("1" 1) ("2" 1)) '(("1" 2) ("2" 2)) :test #'equal))
+ (should (hierarchy--set-equal '(("1" 1) ("2" 1)) '(("1" 2) ("2" 2)) :key #'car :test #'equal)))
+
+(ert-deftest hierarchy-equal-returns-true-for-same-hierarchy ()
+ (let ((animals (hierarchy-animals)))
+ (should (hierarchy-equal animals animals))
+ (should (hierarchy-equal (hierarchy-animals) animals))))
+
+(ert-deftest hierarchy-equal-returns-true-for-hierarchy-copies ()
+ (let ((animals (hierarchy-animals)))
+ (should (hierarchy-equal animals (hierarchy-copy animals)))))
+
+(ert-deftest hierarchy-map-item-on-leaf ()
+ (let* ((animals (hierarchy-animals))
+ (result (hierarchy-map-item (lambda (item indent) (cons item indent))
+ 'cow
+ animals)))
+ (should (equal result '((cow . 0))))))
+
+(ert-deftest hierarchy-map-item-on-leaf-with-indent ()
+ (let* ((animals (hierarchy-animals))
+ (result (hierarchy-map-item (lambda (item indent) (cons item indent))
+ 'cow
+ animals
+ 2)))
+ (should (equal result '((cow . 2))))))
+
+(ert-deftest hierarchy-map-item-on-parent ()
+ (let* ((animals (hierarchy-animals))
+ (result (hierarchy-map-item (lambda (item indent) (cons item indent))
+ 'bird
+ animals)))
+ (should (equal result '((bird . 0) (dove . 1) (pigeon . 1))))))
+
+(ert-deftest hierarchy-map-item-on-grand-parent ()
+ (let* ((animals (hierarchy-animals))
+ (result (hierarchy-map-item (lambda (item indent) (cons item indent))
+ 'animal
+ animals)))
+ (should (equal result '((animal . 0) (bird . 1) (dove . 2) (pigeon . 2)
+ (cow . 1) (dolphin . 1))))))
+
+(ert-deftest hierarchy-map-conses ()
+ (let* ((animals (hierarchy-animals))
+ (result (hierarchy-map (lambda (item indent)
+ (cons item indent))
+ animals)))
+ (should (equal result '((animal . 0)
+ (bird . 1)
+ (dove . 2)
+ (pigeon . 2)
+ (cow . 1)
+ (dolphin . 1))))))
+
+(ert-deftest hierarchy-map-tree ()
+ (let ((animals (hierarchy-animals)))
+ (should (equal (hierarchy-map-tree (lambda (item indent children)
+ (list item indent children))
+ animals)
+ '(animal
+ 0
+ ((bird 1 ((dove 2 nil) (pigeon 2 nil)))
+ (cow 1 nil)
+ (dolphin 1 nil)))))))
+
+(ert-deftest hierarchy-map-hierarchy-keeps-hierarchy ()
+ (let* ((animals (hierarchy-animals))
+ (result (hierarchy-map-hierarchy (lambda (item _) (identity item))
+ animals)))
+ (should (hierarchy-equal animals result))))
+
+(ert-deftest hierarchy-map-applies-function ()
+ (let* ((animals (hierarchy-animals))
+ (parentfn (lambda (item)
+ (cond
+ ((equal item "bird") "animal")
+ ((equal item "dove") "bird")
+ ((equal item "pigeon") "bird")
+ ((equal item "cow") "animal")
+ ((equal item "dolphin") "animal"))))
+ (expected (hierarchy-new)))
+ (hierarchy-add-tree expected "dove" parentfn)
+ (hierarchy-add-tree expected "pigeon" parentfn)
+ (hierarchy-add-tree expected "cow" parentfn)
+ (hierarchy-add-tree expected "dolphin" parentfn)
+ (should (hierarchy-equal
+ (hierarchy-map-hierarchy (lambda (item _) (symbol-name item)) animals)
+ expected))))
+
+(ert-deftest hierarchy-extract-tree ()
+ (let* ((animals (hierarchy-animals))
+ (birds (hierarchy-extract-tree animals 'bird)))
+ (hierarchy-sort birds)
+ (should (equal (hierarchy-roots birds) '(animal)))
+ (should (equal (hierarchy-children birds 'animal) '(bird)))
+ (should (equal (hierarchy-children birds 'bird) '(dove pigeon)))))
+
+(ert-deftest hierarchy-extract-tree-nil-if-not-in-hierarchy ()
+ (let* ((animals (hierarchy-animals)))
+ (should-not (hierarchy-extract-tree animals 'foobar))))
+
+(ert-deftest hierarchy-items-of-empty-hierarchy-is-empty ()
+ (should (seq-empty-p (hierarchy-items (hierarchy-new)))))
+
+(ert-deftest hierarchy-items-returns-sequence-of-same-length ()
+ (let* ((animals (hierarchy-animals))
+ (result (hierarchy-items animals)))
+ (should (= (seq-length result) (hierarchy-length animals)))))
+
+(ert-deftest hierarchy-items-return-all-elements-of-hierarchy ()
+ (let* ((animals (hierarchy-animals))
+ (result (hierarchy-items animals)))
+ (should (equal (seq-sort #'string< result) '(animal bird cow dolphin dove pigeon)))))
+
+(ert-deftest hierarchy-labelfn-indent-no-indent-if-0 ()
+ (let* ((labelfn-base (lambda (_item _indent) (insert "foo")))
+ (labelfn (hierarchy-labelfn-indent labelfn-base)))
+ (should (equal
+ (with-temp-buffer
+ (funcall labelfn "bar" 0)
+ (buffer-substring (point-min) (point-max)))
+ "foo"))))
+
+(ert-deftest hierarchy-labelfn-indent-three-times-if-3 ()
+ (let* ((labelfn-base (lambda (_item _indent) (insert "foo")))
+ (labelfn (hierarchy-labelfn-indent labelfn-base)))
+ (should (equal
+ (with-temp-buffer
+ (funcall labelfn "bar" 3)
+ (buffer-substring (point-min) (point-max)))
+ " foo"))))
+
+(ert-deftest hierarchy-labelfn-indent-default-indent-string ()
+ (let* ((labelfn-base (lambda (_item _indent) (insert "foo")))
+ (labelfn (hierarchy-labelfn-indent labelfn-base)))
+ (should (equal
+ (with-temp-buffer
+ (funcall labelfn "bar" 1)
+ (buffer-substring (point-min) (point-max)))
+ " foo"))))
+
+(ert-deftest hierarchy-labelfn-indent-custom-indent-string ()
+ (let* ((labelfn-base (lambda (_item _indent) (insert "foo")))
+ (labelfn (hierarchy-labelfn-indent labelfn-base "###"))
+ (content (with-temp-buffer
+ (funcall labelfn "bar" 1)
+ (buffer-substring (point-min) (point-max)))))
+ (should (equal content "###foo"))))
+
+(ert-deftest hierarchy-labelfn-button-propertize ()
+ (let* ((labelfn-base (lambda (_item _indent) (insert "foo")))
+ (actionfn #'identity)
+ (labelfn (hierarchy-labelfn-button labelfn-base actionfn))
+ (properties (with-temp-buffer
+ (funcall labelfn "bar" 1)
+ (text-properties-at 1))))
+ (should (equal (car properties) 'action))))
+
+(ert-deftest hierarchy-labelfn-button-execute-labelfn ()
+ (let* ((labelfn-base (lambda (_item _indent) (insert "foo")))
+ (actionfn #'identity)
+ (labelfn (hierarchy-labelfn-button labelfn-base actionfn))
+ (content (with-temp-buffer
+ (funcall labelfn "bar" 1)
+ (buffer-substring-no-properties (point-min) (point-max)))))
+ (should (equal content "foo"))))
+
+(ert-deftest hierarchy-labelfn-button-if-does-not-button-unless-condition ()
+ (let ((labelfn-base (lambda (_item _indent) (insert "foo")))
+ (spy-count 0)
+ (condition (lambda (_item _indent) nil)))
+ (cl-letf (((symbol-function 'hierarchy-labelfn-button) (lambda (_labelfn _actionfn) (lambda (_item _indent) (cl-incf spy-count)))))
+ (funcall (hierarchy-labelfn-button-if labelfn-base condition #'identity) nil nil)
+ (should (equal spy-count 0)))))
+
+(ert-deftest hierarchy-labelfn-button-if-does-button-when-condition ()
+ (let ((labelfn-base (lambda (_item _indent) (insert "foo")))
+ (spy-count 0)
+ (condition (lambda (_item _indent) t)))
+ (cl-letf (((symbol-function 'hierarchy-labelfn-button) (lambda (_labelfn _actionfn) (lambda (_item _indent) (cl-incf spy-count)))))
+ (funcall (hierarchy-labelfn-button-if labelfn-base condition #'identity) nil nil)
+ (should (equal spy-count 1)))))
+
+(ert-deftest hierarchy-labelfn-to-string ()
+ (let ((labelfn (lambda (item _indent) (insert item))))
+ (should (equal (hierarchy-labelfn-to-string labelfn "foo" 1) "foo"))))
+
+(ert-deftest hierarchy-print ()
+ (let* ((animals (hierarchy-animals))
+ (result (with-temp-buffer
+ (hierarchy-print animals)
+ (buffer-substring-no-properties (point-min) (point-max)))))
+ (should (equal result "animal\n bird\n dove\n pigeon\n cow\n dolphin\n"))))
+
+(ert-deftest hierarchy-to-string ()
+ (let* ((animals (hierarchy-animals))
+ (result (hierarchy-to-string animals)))
+ (should (equal result "animal\n bird\n dove\n pigeon\n cow\n dolphin\n"))))
+
+(ert-deftest hierarchy-tabulated-display ()
+ (let* ((animals (hierarchy-animals))
+ (labelfn (lambda (item _indent) (insert (symbol-name item))))
+ (contents (with-temp-buffer
+ (hierarchy-tabulated-display animals labelfn (current-buffer))
+ (buffer-substring-no-properties (point-min) (point-max)))))
+ (should (equal contents "animal\nbird\ndove\npigeon\ncow\ndolphin\n"))))
+
+(ert-deftest hierarchy-sort-non-root-nodes ()
+ (let* ((animals (hierarchy-animals)))
+ (should (equal (hierarchy-roots animals) '(animal)))
+ (should (equal (hierarchy-children animals 'animal) '(bird cow dolphin)))
+ (should (equal (hierarchy-children animals 'bird) '(dove pigeon)))))
+
+(ert-deftest hierarchy-sort-roots ()
+ (let* ((organisms (hierarchy-new))
+ (parentfn (lambda (item)
+ (cl-case item
+ (oak 'plant)
+ (bird 'animal)))))
+ (hierarchy-add-tree organisms 'oak parentfn)
+ (hierarchy-add-tree organisms 'bird parentfn)
+ (hierarchy-sort organisms)
+ (should (equal (hierarchy-roots organisms) '(animal plant)))))
+
+(provide 'hierarchy-tests)
+;;; hierarchy-tests.el ends here
diff --git a/test/lisp/emacs-lisp/icons-tests.el b/test/lisp/emacs-lisp/icons-tests.el
new file mode 100644
index 00000000000..e6e71a8e4fd
--- /dev/null
+++ b/test/lisp/emacs-lisp/icons-tests.el
@@ -0,0 +1,63 @@
+;;; icons-tests.el --- Tests for icons.el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;
+
+;;; Code:
+
+(require 'icons)
+(require 'ert)
+(require 'ert-x)
+(require 'cus-edit)
+
+(define-icon icon-test1 nil
+ '((symbol ">")
+ (text "great"))
+ "Test icon"
+ :version "29.1")
+
+(define-icon icon-test2 icon-test1
+ '((text "child"))
+ "Test icon"
+ :version "29.1")
+
+(deftheme test-icons-theme "")
+
+(ert-deftest test-icon-theme ()
+ (let ((icon-preference '(image emoji symbol text)))
+ (should (equal (icon-string 'icon-test1) ">")))
+ (let ((icon-preference '(text)))
+ (should (equal (icon-string 'icon-test1) "great")))
+ (custom-theme-set-icons
+ 'test-icons-theme
+ '(icon-test1 ((symbol "<") (text "less"))))
+ (let ((icon-preference '(image emoji symbol text)))
+ (should (equal (icon-string 'icon-test1) ">"))
+ (enable-theme 'test-icons-theme)
+ (should (equal (icon-string 'icon-test1) "<"))))
+
+(ert-deftest test-icon-inheretance ()
+ (let ((icon-preference '(image emoji symbol text)))
+ (should (equal (icon-string 'icon-test2) ">")))
+ (let ((icon-preference '(text)))
+ (should (equal (icon-string 'icon-test2) "child"))))
+
+;;; icons-tests.el ends here
diff --git a/test/lisp/emacs-lisp/let-alist-tests.el b/test/lisp/emacs-lisp/let-alist-tests.el
index edcfe8a5291..c4e4feaad30 100644
--- a/test/lisp/emacs-lisp/let-alist-tests.el
+++ b/test/lisp/emacs-lisp/let-alist-tests.el
@@ -1,6 +1,6 @@
;;; let-alist.el --- tests for file handling. -*- lexical-binding: t; -*-
-;; Copyright (C) 2012-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2022 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -82,7 +82,7 @@
(ert-deftest let-alist-list-to-sexp ()
"Check that multiple dots are handled correctly."
- (should (= 1 (eval (let-alist--list-to-sexp '(a b c d) ''((d (c (b (a . 1)))))))))
+ (should (= 1 (eval (let-alist--list-to-sexp '(a b c d) ''((d (c (b (a . 1)))))) t)))
(should (equal (let-alist--access-sexp '.foo.bar.baz 'var)
'(cdr (assq 'baz (cdr (assq 'bar (cdr (assq 'foo var))))))))
(should (equal (let-alist--access-sexp '..foo.bar.baz 'var) '.foo.bar.baz)))
@@ -95,4 +95,9 @@ See Bug#24641."
(should (equal (let-alist--deep-dot-search '(foo .bar (let-alist .qux .baz)))
'((.bar . bar) (.qux . qux))))) ; no .baz
-;;; let-alist.el ends here
+(ert-deftest let-alist--vectors ()
+ (should (equal (let-alist '((a . 1) (b . 2))
+ `[,(+ .a) ,(+ .a .b .b)])
+ [1 5])))
+
+;;; let-alist-tests.el ends here
diff --git a/test/lisp/emacs-lisp/lisp-mnt-tests.el b/test/lisp/emacs-lisp/lisp-mnt-tests.el
new file mode 100644
index 00000000000..200be7354a0
--- /dev/null
+++ b/test/lisp/emacs-lisp/lisp-mnt-tests.el
@@ -0,0 +1,44 @@
+;;; lisp-mnt-tests.el --- Tests for lisp-mnt -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;
+
+;;; Code:
+
+(require 'ert)
+(require 'lisp-mnt)
+
+(ert-deftest lm--tests-crack-address ()
+ (should (equal (lm-crack-address
+ "Bob Weiner <rsw@gnu.org>, Mats Lidell <matsl@gnu.org>")
+ '(("Bob Weiner" . "rsw@gnu.org")
+ ("Mats Lidell" . "matsl@gnu.org")))))
+
+(ert-deftest lm--tests-lm-website ()
+ (with-temp-buffer
+ (insert ";; URL: https://example.org/foo")
+ (should (string= (lm-website) "https://example.org/foo")))
+ (with-temp-buffer
+ (insert ";; X-URL: <https://example.org/foo>")
+ (should (string= (lm-website) "https://example.org/foo"))))
+
+(provide 'lisp-mnt-tests)
+;;; lisp-mnt-tests.el ends here
diff --git a/test/lisp/emacs-lisp/lisp-mode-tests.el b/test/lisp/emacs-lisp/lisp-mode-tests.el
index 6bc916f6c35..996ea201fb0 100644
--- a/test/lisp/emacs-lisp/lisp-mode-tests.el
+++ b/test/lisp/emacs-lisp/lisp-mode-tests.el
@@ -1,6 +1,8 @@
;;; lisp-mode-tests.el --- Test Lisp editing commands -*- lexical-binding: t; -*-
-;; Copyright (C) 2017 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
@@ -20,6 +22,10 @@
(require 'ert)
(require 'cl-lib)
(require 'lisp-mode)
+(require 'faceup)
+
+
+;;; Indentation
(defconst lisp-mode-tests--correctly-indented-sexp "\
\(a
@@ -113,6 +119,57 @@ noindent\" 3
;; we're indenting ends on the previous line.
(should (equal (buffer-string) original)))))
+(ert-deftest indent-sexp-go ()
+ "Make sure `indent-sexp' doesn't stop after #s."
+ ;; See https://debbugs.gnu.org/cgi/bugreport.cgi?bug=31984.
+ (with-temp-buffer
+ (emacs-lisp-mode)
+ (insert "#s(foo\nbar)\n")
+ (goto-char (point-min))
+ (indent-sexp)
+ (should (equal (buffer-string) "\
+#s(foo
+ bar)\n"))))
+
+(ert-deftest indent-sexp-cant-go ()
+ "`indent-sexp' shouldn't error before a sexp."
+ ;; See https://debbugs.gnu.org/cgi/bugreport.cgi?bug=31984#32.
+ (with-temp-buffer
+ (emacs-lisp-mode)
+ (insert "(())")
+ (goto-char (1+ (point-min)))
+ ;; Paredit calls `indent-sexp' from this position.
+ (indent-sexp)
+ (should (equal (buffer-string) "(())"))))
+
+(ert-deftest indent-sexp-stop-before-eol-comment ()
+ "`indent-sexp' shouldn't look for more sexps after an eol comment."
+ ;; See https://debbugs.gnu.org/35286.
+ (with-temp-buffer
+ (emacs-lisp-mode)
+ (let ((str "() ;;\n x"))
+ (insert str)
+ (goto-char (point-min))
+ (indent-sexp)
+ ;; The "x" is in the next sexp, so it shouldn't get indented.
+ (should (equal (buffer-string) str)))))
+
+(ert-deftest indent-sexp-stop-before-eol-non-lisp ()
+ "`indent-sexp' shouldn't be too aggressive in non-Lisp modes."
+ ;; See https://debbugs.gnu.org/35286#13.
+ (with-temp-buffer
+ (prolog-mode)
+ (let ((str "\
+x(H) -->
+ {y(H)}.
+a(A) -->
+ b(A)."))
+ (insert str)
+ (search-backward "{")
+ (indent-sexp)
+ ;; There's no line-spanning sexp, so nothing should be indented.
+ (should (equal (buffer-string) str)))))
+
(ert-deftest lisp-indent-region ()
"Test basics of `lisp-indent-region'."
(with-temp-buffer
@@ -224,6 +281,79 @@ Expected initialization file: `%s'\"
(comment-indent)
(should (equal (buffer-string) correct)))))
+(ert-deftest lisp-indent-with-read-only-field ()
+ "Test indentation on line with read-only field (Bug#32014)."
+ (with-temp-buffer
+ (insert (propertize "prompt> " 'field 'output 'read-only t
+ 'rear-nonsticky t 'front-sticky '(read-only)))
+ (insert " foo")
+ (lisp-indent-line)
+ (should (equal (buffer-string) "prompt> foo"))))
+
+(ert-deftest lisp-indent-unfinished-string ()
+ "Don't infloop on unfinished string (Bug#37045)."
+ (with-temp-buffer
+ (insert "\"\n")
+ (lisp-indent-region (point-min) (point-max))))
+
+(ert-deftest lisp-indent-defun ()
+ (with-temp-buffer
+ (lisp-mode)
+ (let ((orig "(defun x ()
+ (print (quote ( thingy great
+ stuff)))
+ (print (quote (thingy great
+ stuff))))"))
+ (insert orig)
+ (indent-region (point-min) (point-max))
+ (should (equal (buffer-string) orig)))))
+
+
+;;; Fontification
+
+(ert-deftest lisp-fontify-confusables ()
+ "Unescaped 'smart quotes' should be fontified in `font-lock-warning-face'."
+ (with-temp-buffer
+ (dolist (ch
+ '(#x2018 ;; LEFT SINGLE QUOTATION MARK
+ #x2019 ;; RIGHT SINGLE QUOTATION MARK
+ #x201B ;; SINGLE HIGH-REVERSED-9 QUOTATION MARK
+ #x201C ;; LEFT DOUBLE QUOTATION MARK
+ #x201D ;; RIGHT DOUBLE QUOTATION MARK
+ #x201F ;; DOUBLE HIGH-REVERSED-9 QUOTATION MARK
+ #x301E ;; DOUBLE PRIME QUOTATION MARK
+ #xFF02 ;; FULLWIDTH QUOTATION MARK
+ #xFF07 ;; FULLWIDTH APOSTROPHE
+ ))
+ (insert (format "«w:%c»foo \\%cfoo\n" ch ch)))
+ (let ((faceup (buffer-string)))
+ (faceup-clean-buffer)
+ (should (faceup-test-font-lock-buffer 'emacs-lisp-mode faceup)))))
+
+(ert-deftest test-lisp-current-defun-name ()
+ (require 'edebug)
+ (with-temp-buffer
+ (emacs-lisp-mode)
+ (insert "(defun foo ()\n'bar)\n")
+ (goto-char 5)
+ (should (equal (lisp-current-defun-name) "foo")))
+ (with-temp-buffer
+ (emacs-lisp-mode)
+ (insert "(define-flabbergast-test zot ()\n'bar)\n")
+ (goto-char 5)
+ (should (equal (lisp-current-defun-name) "zot")))
+ ;; These tests should probably work after bug#49592 has been fixed.
+ ;; (with-temp-buffer
+ ;; (emacs-lisp-mode)
+ ;; (insert "(progn\n ;; comment\n ;; about that\n (define-key ...)\n )")
+ ;; (goto-char 5)
+ ;; (should (equal (lisp-current-defun-name) "progn")))
+ ;; (with-temp-buffer
+ ;; (emacs-lisp-mode)
+ ;; (insert "(defblarg \"a\" 'b)")
+ ;; (goto-char 5)
+ ;; (should (equal (lisp-current-defun-name) "defblarg")))
+ )
(provide 'lisp-mode-tests)
;;; lisp-mode-tests.el ends here
diff --git a/test/lisp/emacs-lisp/lisp-tests.el b/test/lisp/emacs-lisp/lisp-tests.el
index ae1302bdce4..901447ecd27 100644
--- a/test/lisp/emacs-lisp/lisp-tests.el
+++ b/test/lisp/emacs-lisp/lisp-tests.el
@@ -1,6 +1,6 @@
;;; lisp-tests.el --- Test Lisp editing commands -*- lexical-binding: t; -*-
-;; Copyright (C) 2013-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2022 Free Software Foundation, Inc.
;; Author: Aaron S. Hawley <aaron.s.hawley@gmail.com>
;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
@@ -8,6 +8,8 @@
;; Author: Marcin Borkowski <mbork@mbork.pl>
;; Keywords: internal
+;; This file is part of GNU Emacs.
+
;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
@@ -136,8 +138,7 @@
(text-mode)
(insert "\"foo\"")
(goto-char (point-min))
- (delete-pair)
- (should (string-equal "fo\"" (buffer-string)))))
+ (should-error (delete-pair))))
(ert-deftest lisp-delete-pair-quotes-text-mode-syntax-table ()
"Test \\[delete-pair] with modified Text Mode syntax for #15014."
@@ -212,6 +213,7 @@
(should-error (forward-sexp)))) ;; FIXME: Shouldn't be an error.
;; Test some core Elisp rules.
+(defvar c-e-x)
(ert-deftest core-elisp-tests-1-defvar-in-let ()
"Test some core Elisp rules."
(with-temp-buffer
@@ -234,7 +236,7 @@
(should (or (not mark-active) (mark)))))
(ert-deftest core-elisp-tests-3-backquote ()
- (should (eq 3 (eval ``,,'(+ 1 2)))))
+ (should (eq 3 (eval ``,,'(+ 1 2) t))))
;; Test up-list and backward-up-list.
(defun lisp-run-up-list-test (fn data start instructions)
@@ -296,7 +298,7 @@
(lambda () (up-list 1 t t))
(or "(1 '2 ( 2' 1 '2 ) 2' 1)")
;; abcdefghijklmnopqrstuvwxy
- i k x scan-error)
+ i k x user-error)
(define-lisp-up-list-test backward-up-list-basic
(lambda () (backward-up-list))
@@ -323,7 +325,7 @@ start."
(declare (indent 1) (debug (def-form body)))
(let* ((var-pos nil)
(text (with-temp-buffer
- (insert (eval contents))
+ (insert (eval contents t))
(goto-char (point-min))
(while (re-search-forward elisp-test-point-position-regex nil t)
(push (list (intern (match-string-no-properties 1))
@@ -367,6 +369,61 @@ start."
"
"Test buffer for `mark-defun'."))
+;;; end-of-defun
+
+(ert-deftest end-of-defun-twice ()
+ "Test behavior of prefix arg for `end-of-defun' (Bug#24427).
+Calling `end-of-defun' twice should be the same as a prefix arg
+of two."
+ (setq last-command nil)
+ (cl-flet ((eod2 (lambda ()
+ (goto-char (point-min))
+ (end-of-defun)
+ (end-of-defun)
+ (let ((pt-eod2 (point)))
+ (goto-char (point-min))
+ (end-of-defun 2)
+ (should (= (point) pt-eod2))))))
+ (with-temp-buffer
+ (insert "\
+\(defun a ())
+
+\(defun b ())
+
+\(defun c ())")
+ (eod2))
+ (with-temp-buffer
+ (insert "\
+\(defun a ())
+\(defun b ())
+\(defun c ())")
+ (eod2)))
+ (elisp-tests-with-temp-buffer ";; Comment header
+
+\(defun func-1 (arg)
+ \"docstring\"
+ body)
+=!p1=
+;; Comment before a defun
+\(defun func-2 (arg)
+ \"docstring\"
+ body)
+
+\(defun func-3 (arg)
+ \"docstring\"
+ body)
+=!p2=(defun func-4 (arg)
+ \"docstring\"
+ body)
+
+;; end
+"
+ (goto-char p1)
+ (end-of-defun 2)
+ (should (= (point) p2))))
+
+;;; mark-defun
+
(ert-deftest mark-defun-no-arg-region-inactive ()
"Test `mark-defun' with no prefix argument and inactive
region."
@@ -589,5 +646,36 @@ region."
(should (= (point) before))
(should (= (mark) after))))
+(ert-deftest lisp-fill-paragraph-colon ()
+ "Keywords below Emacs Lisp docstrings should not be filled (Bug#24622).
+Keywords inside docstrings should be filled (Bug#7751)."
+ (elisp-tests-with-temp-buffer
+ "
+\(defcustom custom value
+ \"First\n
+Second\n
+=!inside=Third line\"
+ =!keywords=:type 'sexp
+ :version \"26.1\"
+ :group 'lisp-tests)"
+ (goto-char inside)
+ (fill-paragraph)
+ (goto-char keywords)
+ (beginning-of-line)
+ (should (looking-at " :type 'sexp\n :version \"26.1\"\n :")))
+ (elisp-tests-with-temp-buffer
+ "
+\(defun foo ()
+ \"Summary.
+=!inside=Testing keywords: :one :two :three\"
+ (body))" ; FIXME: Remove parens around body to test Bug#28937 once it's fixed
+ (goto-char inside)
+ (let ((emacs-lisp-docstring-fill-column 30))
+ (fill-paragraph))
+ (forward-line)
+ (should (looking-at ":three"))
+ (end-of-line)
+ (should-not (eq (preceding-char) ?\)))))
+
(provide 'lisp-tests)
;;; lisp-tests.el ends here
diff --git a/test/lisp/emacs-lisp/macroexp-resources/m1.el b/test/lisp/emacs-lisp/macroexp-resources/m1.el
new file mode 100644
index 00000000000..88c51e75261
--- /dev/null
+++ b/test/lisp/emacs-lisp/macroexp-resources/m1.el
@@ -0,0 +1,36 @@
+;;; m1.el --- Some sample code for macroexp-tests -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
+;; Keywords:
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(defconst macroexp--m1-tests-filename (macroexp-file-name))
+
+(eval-when-compile
+ (defconst macroexp--m1-tests-comp-filename (macroexp-file-name)))
+
+(defun macroexp--m1-tests-file-name ()
+ (macroexp--test-get-file-name))
+
+(provide 'm1)
+;;; m1.el ends here
diff --git a/test/lisp/emacs-lisp/macroexp-resources/m2.el b/test/lisp/emacs-lisp/macroexp-resources/m2.el
new file mode 100644
index 00000000000..cebe4cac125
--- /dev/null
+++ b/test/lisp/emacs-lisp/macroexp-resources/m2.el
@@ -0,0 +1,33 @@
+;;; m2.el --- More sample code for macroexp-tests -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
+;; Keywords:
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(defconst macroexp--m2-tests-filename (macroexp-file-name))
+
+(byte-compile-file (expand-file-name
+ "m1.el" (file-name-directory macroexp--m2-tests-filename)))
+
+(provide 'm2)
+;;; m2.el ends here
diff --git a/test/lisp/emacs-lisp/macroexp-resources/vk.el b/test/lisp/emacs-lisp/macroexp-resources/vk.el
new file mode 100644
index 00000000000..d9ca33671ef
--- /dev/null
+++ b/test/lisp/emacs-lisp/macroexp-resources/vk.el
@@ -0,0 +1,130 @@
+;;; vk.el --- test code for macroexp-tests -*- lexical-binding: t -*-
+
+;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'macroexp)
+
+(defmacro vk-variable-kind (var)
+ (if (macroexp--dynamic-variable-p var) ''dyn ''lex))
+
+(defvar vk-a 1)
+(defconst vk-b 2)
+(defvar vk-c)
+
+(defun vk-f1 (x)
+ (defvar vk-u1)
+ (let ((vk-a 10)
+ (vk-b 20)
+ (vk-c 30)
+ (vk-u1 40)
+ (y 50))
+ (ignore vk-a vk-b vk-c vk-u1 x y)
+ (list
+ (vk-variable-kind vk-a) ; dyn
+ (vk-variable-kind vk-b) ; dyn
+ (vk-variable-kind vk-c) ; dyn
+ (vk-variable-kind vk-u1) ; dyn
+ (vk-variable-kind x) ; lex
+ (vk-variable-kind y)))) ; lex
+
+(eval-and-compile
+ (defvar vk-u2)
+ (defun vk-f2 (x)
+ (defvar vk-v2)
+ (let ((vk-u2 11)
+ (vk-v2 12)
+ (y 13))
+ (ignore vk-u2 vk-v2 x y)
+ (list
+ (vk-variable-kind vk-u2) ; dyn
+ (vk-variable-kind vk-v2) ; dyn
+ (vk-variable-kind x) ; lex
+ (vk-variable-kind y))))) ; lex
+
+(eval-when-compile
+ (defvar vk-u3)
+ (defun vk-f3 (x)
+ (defvar vk-v3)
+ (let ((vk-a 23)
+ (vk-b 24)
+ (vk-u3 25)
+ (vk-v3 26)
+ (y 27))
+ (ignore vk-a vk-b vk-u3 vk-v3 x y)
+ (list
+ (vk-variable-kind vk-a) ; dyn
+ (vk-variable-kind vk-b) ; dyn
+ (vk-variable-kind vk-u3) ; dyn
+ (vk-variable-kind vk-v3) ; dyn
+ (vk-variable-kind x) ; lex
+ (vk-variable-kind y))))) ; lex
+
+(defconst vk-val3 (eval-when-compile (vk-f3 0)))
+
+(defconst vk-f4 '(lambda (x)
+ (defvar vk-v4)
+ (let ((vk-v4 31)
+ (y 32))
+ (ignore vk-v4 x y)
+ (list
+ (vk-variable-kind vk-a) ; dyn
+ (vk-variable-kind vk-b) ; dyn
+ (vk-variable-kind vk-v4) ; dyn
+ (vk-variable-kind x) ; dyn
+ (vk-variable-kind y))))) ; dyn
+
+(defconst vk-f5 '(closure (t) (x)
+ (defvar vk-v5)
+ (let ((vk-v5 41)
+ (y 42))
+ (ignore vk-v5 x y)
+ (list
+ (vk-variable-kind vk-a) ; dyn
+ (vk-variable-kind vk-b) ; dyn
+ (vk-variable-kind vk-v5) ; dyn
+ (vk-variable-kind x) ; lex
+ (vk-variable-kind y))))) ; lex
+
+(defun vk-f6 ()
+ (eval '(progn
+ (defvar vk-v6)
+ (let ((vk-v6 51)
+ (y 52))
+ (ignore vk-v6 y)
+ (list
+ (vk-variable-kind vk-a) ; dyn
+ (vk-variable-kind vk-b) ; dyn
+ (vk-variable-kind vk-v6) ; dyn
+ (vk-variable-kind vk-y)))))) ; dyn
+
+(defun vk-f7 ()
+ (eval '(progn
+ (defvar vk-v7)
+ (let ((vk-v7 51)
+ (y 52))
+ (ignore vk-v7 y)
+ (list
+ (vk-variable-kind vk-a) ; dyn
+ (vk-variable-kind vk-b) ; dyn
+ (vk-variable-kind vk-v7) ; dyn
+ (vk-variable-kind vk-y)))) ; lex
+ t))
+
+(provide 'vk)
diff --git a/test/lisp/emacs-lisp/macroexp-tests.el b/test/lisp/emacs-lisp/macroexp-tests.el
new file mode 100644
index 00000000000..4e6bd8b8fcd
--- /dev/null
+++ b/test/lisp/emacs-lisp/macroexp-tests.el
@@ -0,0 +1,127 @@
+;;; macroexp-tests.el --- Tests for macroexp.el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
+;; Keywords:
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'macroexp)
+(require 'ert-x)
+
+(ert-deftest macroexp--tests-fgrep ()
+ (should (equal (macroexp--fgrep '((x) (y)) '([x] z ((u))))
+ '((x))))
+ (should (equal (macroexp--fgrep '((x) (y)) '#2=([y] ((y #2#))))
+ '((y))))
+ (should (equal (macroexp--fgrep '((x) (y)) '#2=([r] ((a x)) a b c d . #2#))
+ '((x)))))
+
+(defconst macroexp--tests-filename (macroexp-file-name))
+
+(defmacro macroexp--test-get-file-name () (macroexp-file-name))
+
+(ert-deftest macroexp--tests-file-name ()
+ (should (string-match
+ "\\`macroexp-tests.elc?\\'"
+ (file-name-nondirectory macroexp--tests-filename)))
+ (let ((rsrc-dir (expand-file-name
+ "macroexp-resources"
+ (file-name-directory macroexp--tests-filename))))
+ (with-current-buffer
+ (find-file-noselect (expand-file-name "m1.el" rsrc-dir))
+ (defvar macroexp--m1-tests-filename)
+ (declare-function macroexp--m1-tests-file-name "m1" ())
+ ;; `macroexp-file-name' should work with `eval-buffer'.
+ (eval-buffer)
+ (should (equal "m1.el"
+ (file-name-nondirectory macroexp--m1-tests-filename)))
+ (should (equal "m1.el"
+ (file-name-nondirectory (macroexp--m1-tests-file-name))))
+ (search-forward "macroexp--m1-tests-filename")
+ (makunbound 'macroexp--m1-tests-filename)
+ ;; `macroexp-file-name' should also work with `eval-defun'.
+ (eval-defun nil)
+ (should (equal "m1.el"
+ (file-name-nondirectory macroexp--m1-tests-filename))))
+
+ ;; Test the case where we load a file which byte-compiles another.
+ (defvar macroexp--m1-tests-comp-filename)
+ (makunbound 'macroexp--m1-tests-comp-filename)
+ (load (expand-file-name "m2.el" rsrc-dir))
+ (should (equal "m1.el"
+ (file-name-nondirectory macroexp--m1-tests-comp-filename)))))
+
+(defun macroexp-tests--run-emacs (&rest args)
+ "Run Emacs in batch mode with ARGS, return output."
+ (let ((emacs (expand-file-name invocation-name invocation-directory)))
+ (with-temp-buffer
+ (let ((res (apply #'call-process emacs nil t nil
+ "-Q" "--batch" args))
+ (output (buffer-string)))
+ (unless (equal res 0)
+ (message "%s" output)
+ (error "Inferior Emacs exited with status %S" res))
+ output))))
+
+(defun macroexp-tests--eval-in-subprocess (file expr)
+ (let ((output (macroexp-tests--run-emacs
+ "-l" file (format "--eval=(print %S)" expr))))
+ (car (read-from-string output))))
+
+(defun macroexp-tests--byte-compile-in-subprocess (file)
+ "Byte-compile FILE using a subprocess to avoid contaminating the lisp state."
+ (let ((output (macroexp-tests--run-emacs "-f" "batch-byte-compile" file)))
+ (when output
+ (message "%s" output))))
+
+(ert-deftest macroexp--tests-dynamic-variable-p ()
+ "Test `macroexp--dynamic-variable-p'."
+ (let* ((vk-el (ert-resource-file "vk.el"))
+ (vk-elc (concat vk-el "c"))
+ (expr '(list (vk-f1 0)
+ (vk-f2 0)
+ vk-val3
+ (funcall vk-f4 0)
+ (funcall vk-f5 0)
+ (vk-f6)
+ (vk-f7))))
+ ;; We compile and run the test in separate processes for complete
+ ;; isolation between test cases.
+ (should (equal (macroexp-tests--eval-in-subprocess vk-el expr)
+ '((dyn dyn dyn dyn lex lex)
+ (dyn dyn lex lex)
+ (dyn dyn dyn dyn lex lex)
+ (dyn dyn dyn dyn dyn)
+ (dyn dyn dyn lex lex)
+ (dyn dyn dyn dyn)
+ (dyn dyn dyn lex))))
+ (macroexp-tests--byte-compile-in-subprocess vk-el)
+ (should (equal (macroexp-tests--eval-in-subprocess vk-elc expr)
+ '((dyn dyn dyn dyn lex lex)
+ (dyn dyn lex lex)
+ (dyn dyn dyn dyn lex lex)
+ (dyn dyn dyn dyn dyn)
+ (dyn dyn dyn lex lex)
+ (dyn dyn dyn dyn)
+ (dyn dyn dyn lex))))))
+
+;;; macroexp-tests.el ends here
diff --git a/test/lisp/emacs-lisp/map-tests.el b/test/lisp/emacs-lisp/map-tests.el
index 0a888d88b72..314a1c9e302 100644
--- a/test/lisp/emacs-lisp/map-tests.el
+++ b/test/lisp/emacs-lisp/map-tests.el
@@ -1,6 +1,6 @@
;;; map-tests.el --- Tests for map.el -*- lexical-binding:t -*-
-;; Copyright (C) 2015-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2022 Free Software Foundation, Inc.
;; Author: Nicolas Petton <nicolas@petton.fr>
;; Maintainer: emacs-devel@gnu.org
@@ -22,7 +22,7 @@
;;; Commentary:
-;; Tests for map.el
+;; Tests for map.el.
;;; Code:
@@ -30,101 +30,196 @@
(require 'map)
(defmacro with-maps-do (var &rest body)
- "Successively bind VAR to an alist, vector and hash-table.
+ "Successively bind VAR to an alist, plist, vector, and hash-table.
Each map is built from the following alist data:
-'((0 . 3) (1 . 4) (2 . 5)).
-Evaluate BODY for each created map.
-
-\(fn (var map) body)"
- (declare (indent 1) (debug t))
+ \\='((0 . 3) (1 . 4) (2 . 5)).
+Evaluate BODY for each created map."
+ (declare (indent 1) (debug (symbolp body)))
(let ((alist (make-symbol "alist"))
+ (plist (make-symbol "plist"))
(vec (make-symbol "vec"))
(ht (make-symbol "ht")))
`(let ((,alist (list (cons 0 3)
(cons 1 4)
(cons 2 5)))
+ (,plist (list 0 3 1 4 2 5))
(,vec (vector 3 4 5))
(,ht (make-hash-table)))
(puthash 0 3 ,ht)
(puthash 1 4 ,ht)
(puthash 2 5 ,ht)
- (dolist (,var (list ,alist ,vec ,ht))
+ (dolist (,var (list ,alist ,plist ,vec ,ht))
,@body))))
+(defmacro with-empty-maps-do (var &rest body)
+ "Like `with-maps-do', but with empty maps."
+ (declare (indent 1) (debug (symbolp body)))
+ `(dolist (,var (list (list) (vector) (make-hash-table)))
+ ,@body))
+
+(ert-deftest test-map-plist-p ()
+ "Test `map--plist-p'."
+ (with-empty-maps-do map
+ (should-not (map--plist-p map)))
+ (should-not (map--plist-p ""))
+ (should-not (map--plist-p '((()))))
+ (should (map--plist-p '(:a)))
+ (should (map--plist-p '(a)))
+ (should (map--plist-p '(nil)))
+ (should (map--plist-p '(""))))
+
(ert-deftest test-map-elt ()
(with-maps-do map
(should (= 3 (map-elt map 0)))
(should (= 4 (map-elt map 1)))
(should (= 5 (map-elt map 2)))
- (should (null (map-elt map -1)))
- (should (null (map-elt map 4)))))
+ (should-not (map-elt map -1))
+ (should-not (map-elt map 4))
+ (should-not (map-elt map 0.1))))
(ert-deftest test-map-elt-default ()
(with-maps-do map
- (should (= 5 (map-elt map 7 5)))))
+ (should (= 5 (map-elt map 7 5)))
+ (should (= 5 (map-elt map 0.1 5))))
+ (with-empty-maps-do map
+ (should (= 5 (map-elt map 0 5)))))
(ert-deftest test-map-elt-testfn ()
- (let ((map (list (cons "a" 1) (cons "b" 2)))
- ;; Make sure to use a non-eq "a", even when compiled.
- (noneq-key (string ?a)))
- (should-not (map-elt map noneq-key))
- (should (map-elt map noneq-key nil 'equal))))
+ (let* ((a (string ?a))
+ (map `((,a . 0) (,(string ?b) . 1))))
+ (should (= (map-elt map a) 0))
+ (should (= (map-elt map "a") 0))
+ (should (= (map-elt map (string ?a)) 0))
+ (should (= (map-elt map "b") 1))
+ (should (= (map-elt map (string ?b)) 1))))
(ert-deftest test-map-elt-with-nil-value ()
- (should (null (map-elt '((a . 1)
- (b))
- 'b
- '2))))
+ (should-not (map-elt '((a . 1) (b)) 'b 2)))
-(ert-deftest test-map-put ()
+(ert-deftest test-map-put! ()
(with-maps-do map
(setf (map-elt map 2) 'hello)
(should (eq (map-elt map 2) 'hello)))
(with-maps-do map
- (map-put map 2 'hello)
+ (with-suppressed-warnings ((obsolete map-put))
+ (map-put map 2 'hello))
(should (eq (map-elt map 2) 'hello)))
- (let ((ht (make-hash-table)))
- (setf (map-elt ht 2) 'a)
- (should (eq (map-elt ht 2)
- 'a)))
- (let ((alist '((0 . a) (1 . b) (2 . c))))
- (setf (map-elt alist 2) 'a)
- (should (eq (map-elt alist 2)
- 'a)))
- (let ((vec [3 4 5]))
- (should-error (setf (map-elt vec 3) 6))))
+ (with-maps-do map
+ (map-put! map 2 'hello)
+ (should (eq (map-elt map 2) 'hello))
+ (if (not (or (hash-table-p map)
+ (map--plist-p map)))
+ (should-error (map-put! map 5 'value)
+ ;; For vectors, it could arguably signal
+ ;; map-not-inplace as well, but it currently doesn't.
+ :type (if (listp map)
+ 'map-not-inplace
+ 'error))
+ (map-put! map 5 'value)
+ (should (eq (map-elt map 5) 'value)))))
+
+(ert-deftest test-map-put!-new-keys ()
+ "Test `map-put!' with new keys."
+ (with-maps-do map
+ (let ((size (map-length map)))
+ (if (arrayp map)
+ (progn
+ (should-error (setf (map-elt map 'k) 'v))
+ (should-error (setf (map-elt map size) 'v)))
+ (setf (map-elt map 'k) 'v)
+ (should (eq (map-elt map 'k) 'v))
+ (setf (map-elt map size) 'v)
+ (should (eq (map-elt map size) 'v))))))
+
+(ert-deftest test-map-put!-alist ()
+ "Test `map-put!' test function on alists."
+ (let ((key (string ?a))
+ (val 0)
+ map)
+ (should-error (map-put! map key val) :type 'map-not-inplace)
+ (setq map (list (cons key val)))
+ (map-put! map key (1- val))
+ (should (equal map '(("a" . -1))))
+ (map-put! map (string ?a) (1+ val))
+ (should (equal map '(("a" . 1))))
+ (should-error (map-put! map (string ?a) val #'eq) :type 'map-not-inplace)))
(ert-deftest test-map-put-alist-new-key ()
"Regression test for Bug#23105."
- (let ((alist '((0 . a))))
- (map-put alist 2 'b)
- (should (eq (map-elt alist 2)
- 'b))))
+ (let ((alist (list (cons 0 'a))))
+ (with-suppressed-warnings ((obsolete map-put))
+ (map-put alist 2 'b))
+ (should (eq (map-elt alist 2) 'b))))
(ert-deftest test-map-put-testfn-alist ()
(let ((alist (list (cons "a" 1) (cons "b" 2)))
;; Make sure to use a non-eq "a", even when compiled.
(noneq-key (string ?a)))
- (map-put alist noneq-key 3 'equal)
- (should-not (cddr alist))
- (map-put alist noneq-key 9)
- (should (cddr alist))))
+ (with-suppressed-warnings ((obsolete map-put))
+ (map-put alist noneq-key 3 #'equal)
+ (should-not (cddr alist))
+ (map-put alist noneq-key 9 #'eql)
+ (should (cddr alist)))))
(ert-deftest test-map-put-return-value ()
(let ((ht (make-hash-table)))
- (should (eq (map-put ht 'a 'hello) 'hello))))
+ (with-suppressed-warnings ((obsolete map-put))
+ (should (eq (map-put ht 'a 'hello) 'hello)))))
+
+(ert-deftest test-map-insert-empty ()
+ "Test `map-insert' on empty maps."
+ (with-empty-maps-do map
+ (if (arrayp map)
+ (should-error (map-insert map 0 6))
+ (let ((new (map-insert map 0 6)))
+ (should-not (eq map new))
+ (should-not (map-pairs map))
+ (should (= (map-elt new 0) 6))))))
+
+(ert-deftest test-map-insert ()
+ "Test `map-insert'."
+ (with-maps-do map
+ (let ((pairs (map-pairs map))
+ (size (map-length map))
+ (new (map-insert map 0 6)))
+ (should-not (eq map new))
+ (should (equal (map-pairs map) pairs))
+ (should (= (map-elt new 0) 6))
+ (if (arrayp map)
+ (should-error (map-insert map size 7))
+ (setq new (map-insert map size 7))
+ (should-not (eq map new))
+ (should (equal (map-pairs map) pairs))
+ (should (= (map-elt new size) 7))))))
(ert-deftest test-map-delete ()
(with-maps-do map
- (map-delete map 1)
- (should (null (map-elt map 1))))
+ (should (map-elt map 1))
+ (should (eq map (map-delete map 1)))
+ (should-not (map-elt map 1)))
(with-maps-do map
- (map-delete map -2)
- (should (null (map-elt map -2)))))
-
-(ert-deftest test-map-delete-return-value ()
- (let ((ht (make-hash-table)))
- (should (eq (map-delete ht 'a) ht))))
+ (should-not (map-elt map -2))
+ (should (eq map (map-delete map -2)))
+ (should-not (map-elt map -2)))
+ (with-maps-do map
+ ;; Check for OBOE.
+ (let ((key (map-length map)))
+ (should-not (map-elt map key))
+ (should (eq map (map-delete map key)))
+ (should-not (map-elt map key)))))
+
+(ert-deftest test-map-delete-empty ()
+ (with-empty-maps-do map
+ (should (eq map (map-delete map t)))))
+
+(ert-deftest test-map-delete-alist ()
+ "Test `map-delete' test function on alists."
+ (let* ((a (string ?a))
+ (map `((,a) (,(string ?b)))))
+ (setq map (map-delete map a))
+ (should (equal map '(("b"))))
+ (setq map (map-delete map (string ?b)))
+ (should-not map)))
(ert-deftest test-map-nested-elt ()
(let ((vec [a b [c d [e f]]]))
@@ -134,8 +229,9 @@ Evaluate BODY for each created map.
(d . 3)
(e . ((f . 4)
(g . 5))))))))
- (should (eq (map-nested-elt alist '(b e f))
- 4)))
+ (should (eq (map-nested-elt alist '(b e f)) 4)))
+ (let ((plist '(a 1 b (c 2 d 3 e (f 4 g 5)))))
+ (should (eq (map-nested-elt plist '(b e f)) 4)))
(let ((ht (make-hash-table)))
(setf (map-elt ht 'a) 1)
(setf (map-elt ht 'b) (make-hash-table))
@@ -145,218 +241,318 @@ Evaluate BODY for each created map.
(ert-deftest test-map-nested-elt-default ()
(let ((vec [a b [c d]]))
- (should (null (map-nested-elt vec '(2 3))))
- (should (null (map-nested-elt vec '(2 1 1))))
+ (should-not (map-nested-elt vec '(2 3)))
+ (should-not (map-nested-elt vec '(2 1 1)))
(should (= 4 (map-nested-elt vec '(2 1 1) 4)))))
(ert-deftest test-mapp ()
- (should (mapp nil))
- (should (mapp '((a . b) (c . d))))
- (should (mapp '(a b c d)))
- (should (mapp []))
- (should (mapp [1 2 3]))
- (should (mapp (make-hash-table)))
+ (with-empty-maps-do map
+ (should (mapp map)))
+ (with-maps-do map
+ (should (mapp map)))
+ (should (mapp ""))
(should (mapp "hello"))
- (should (not (mapp 1)))
- (should (not (mapp 'hello))))
+ (should-not (mapp 1))
+ (should-not (mapp 'hello)))
(ert-deftest test-map-keys ()
(with-maps-do map
(should (equal (map-keys map) '(0 1 2))))
- (should (null (map-keys nil)))
- (should (null (map-keys []))))
+ (with-empty-maps-do map
+ (should-not (map-keys map))))
(ert-deftest test-map-values ()
(with-maps-do map
- (should (equal (map-values map) '(3 4 5)))))
+ (should (equal (map-values map) '(3 4 5))))
+ (with-empty-maps-do map
+ (should-not (map-values map))))
(ert-deftest test-map-pairs ()
(with-maps-do map
- (should (equal (map-pairs map) '((0 . 3)
- (1 . 4)
- (2 . 5))))))
+ (should (equal (map-pairs map)
+ '((0 . 3)
+ (1 . 4)
+ (2 . 5)))))
+ (with-empty-maps-do map
+ (should-not (map-pairs map))))
(ert-deftest test-map-length ()
- (let ((ht (make-hash-table)))
- (puthash 'a 1 ht)
- (puthash 'b 2 ht)
- (puthash 'c 3 ht)
- (puthash 'd 4 ht)
- (should (= 0 (map-length nil)))
- (should (= 0 (map-length [])))
- (should (= 0 (map-length (make-hash-table))))
- (should (= 5 (map-length [0 1 2 3 4])))
- (should (= 2 (map-length '((a . 1) (b . 2)))))
- (should (= 4 (map-length ht)))))
+ (with-empty-maps-do map
+ (should (zerop (map-length map))))
+ (with-maps-do map
+ (should (= 3 (map-length map))))
+ (should (= 1 (map-length '(nil 1))))
+ (should (= 2 (map-length '(nil 1 t 2))))
+ (should (= 2 (map-length '((a . 1) (b . 2)))))
+ (should (= 5 (map-length [0 1 2 3 4])))
+ (should (= 4 (map-length #s(hash-table data (a 1 b 2 c 3 d 4))))))
(ert-deftest test-map-copy ()
(with-maps-do map
(let ((copy (map-copy map)))
- (should (equal (map-keys map) (map-keys copy)))
- (should (equal (map-values map) (map-values copy)))
- (should (not (eq map copy))))))
+ (should (equal (map-pairs map) (map-pairs copy)))
+ (should-not (eq map copy))
+ (map-put! map 0 0)
+ (should-not (equal (map-pairs map) (map-pairs copy)))))
+ (with-empty-maps-do map
+ (should-not (map-pairs (map-copy map)))))
+
+(ert-deftest test-map-copy-alist ()
+ "Test use of `copy-alist' for alists."
+ (let* ((cons (list 'a 1 2))
+ (alist (list cons))
+ (copy (map-copy alist)))
+ (setcar cons 'b)
+ (should (equal alist '((b 1 2))))
+ (should (equal copy '((a 1 2))))
+ (setcar (cdr cons) 0)
+ (should (equal alist '((b 0 2))))
+ (should (equal copy '((a 0 2))))
+ (setcdr cons 3)
+ (should (equal alist '((b . 3))))
+ (should (equal copy '((a 0 2))))))
(ert-deftest test-map-apply ()
- (with-maps-do map
- (should (equal (map-apply (lambda (k v) (cons (int-to-string k) v))
- map)
- '(("0" . 3) ("1" . 4) ("2" . 5)))))
- (let ((vec [a b c]))
- (should (equal (map-apply (lambda (k v) (cons (1+ k) v))
- vec)
- '((1 . a)
- (2 . b)
- (3 . c))))))
+ (let ((fn (lambda (k v) (cons (number-to-string k) v))))
+ (with-maps-do map
+ (should (equal (map-apply fn map)
+ '(("0" . 3) ("1" . 4) ("2" . 5)))))
+ (with-empty-maps-do map
+ (should-not (map-apply fn map)))))
(ert-deftest test-map-do ()
- (with-maps-do map
- (let ((result nil))
- (map-do (lambda (k v)
- (add-to-list 'result (list (int-to-string k) v)))
- map)
- (should (equal result '(("2" 5) ("1" 4) ("0" 3)))))))
+ (let* (res
+ (fn (lambda (k v)
+ (push (list (number-to-string k) v) res))))
+ (with-empty-maps-do map
+ (should-not (map-do fn map))
+ (should-not res))
+ (with-maps-do map
+ (setq res nil)
+ (should-not (map-do fn map))
+ (should (equal res '(("2" 5) ("1" 4) ("0" 3)))))))
(ert-deftest test-map-keys-apply ()
(with-maps-do map
- (should (equal (map-keys-apply (lambda (k) (int-to-string k))
- map)
- '("0" "1" "2"))))
- (let ((vec [a b c]))
- (should (equal (map-keys-apply (lambda (k) (1+ k))
- vec)
- '(1 2 3)))))
+ (should (equal (map-keys-apply #'1+ map) '(1 2 3))))
+ (with-empty-maps-do map
+ (let (ks)
+ (should-not (map-keys-apply (lambda (k) (push k ks)) map))
+ (should-not ks))))
(ert-deftest test-map-values-apply ()
(with-maps-do map
- (should (equal (map-values-apply (lambda (v) (1+ v))
- map)
- '(4 5 6))))
- (let ((vec [a b c]))
- (should (equal (map-values-apply (lambda (v) (symbol-name v))
- vec)
- '("a" "b" "c")))))
+ (should (equal (map-values-apply #'1+ map) '(4 5 6))))
+ (with-empty-maps-do map
+ (let (vs)
+ (should-not (map-values-apply (lambda (v) (push v vs)) map))
+ (should-not vs))))
(ert-deftest test-map-filter ()
(with-maps-do map
- (should (equal (map-keys (map-filter (lambda (_k v)
- (<= 4 v))
- map))
- '(1 2)))
- (should (null (map-filter (lambda (k _v)
- (eq 'd k))
- map))))
- (should (null (map-filter (lambda (_k v)
- (eq 3 v))
- [1 2 4 5])))
- (should (equal (map-filter (lambda (k _v)
- (eq 3 k))
- [1 2 4 5])
- '((3 . 5)))))
+ (should (equal (map-filter (lambda (_k v) (> v 3)) map)
+ '((1 . 4) (2 . 5))))
+ (should (equal (map-filter #'always map) (map-pairs map)))
+ (should-not (map-filter #'ignore map)))
+ (with-empty-maps-do map
+ (should-not (map-filter #'always map))
+ (should-not (map-filter #'ignore map))))
(ert-deftest test-map-remove ()
(with-maps-do map
- (should (equal (map-keys (map-remove (lambda (_k v)
- (>= v 4))
- map))
- '(0)))
- (should (equal (map-keys (map-remove (lambda (k _v)
- (eq 'd k))
- map))
- (map-keys map))))
- (should (equal (map-remove (lambda (_k v)
- (eq 3 v))
- [1 2 4 5])
- '((0 . 1)
- (1 . 2)
- (2 . 4)
- (3 . 5))))
- (should (null (map-remove (lambda (k _v)
- (>= k 0))
- [1 2 4 5]))))
+ (should (equal (map-remove (lambda (_k v) (> v 3)) map)
+ '((0 . 3))))
+ (should (equal (map-remove #'ignore map) (map-pairs map)))
+ (should-not (map-remove #'always map)))
+ (with-empty-maps-do map
+ (should-not (map-remove #'always map))
+ (should-not (map-remove #'ignore map))))
(ert-deftest test-map-empty-p ()
- (should (map-empty-p nil))
- (should (not (map-empty-p '((a . b) (c . d)))))
- (should (map-empty-p []))
- (should (not (map-empty-p [1 2 3])))
- (should (map-empty-p (make-hash-table)))
- (should (not (map-empty-p "hello")))
- (should (map-empty-p "")))
+ (with-empty-maps-do map
+ (should (map-empty-p map)))
+ (should (map-empty-p ""))
+ (should-not (map-empty-p '((a . b) (c . d))))
+ (should-not (map-empty-p [1 2 3]))
+ (should-not (map-empty-p "hello")))
(ert-deftest test-map-contains-key ()
- (should (map-contains-key '((a . 1) (b . 2)) 'a))
- (should (not (map-contains-key '((a . 1) (b . 2)) 'c)))
- (should (map-contains-key '(("a" . 1)) "a"))
- (should (not (map-contains-key '(("a" . 1)) "a" #'eq)))
- (should (map-contains-key [a b c] 2))
- (should (not (map-contains-key [a b c] 3))))
+ (with-empty-maps-do map
+ (should-not (map-contains-key map -1))
+ (should-not (map-contains-key map 0))
+ (should-not (map-contains-key map 1))
+ (should-not (map-contains-key map (map-length map))))
+ (with-maps-do map
+ (should-not (map-contains-key map -1))
+ (should (map-contains-key map 0))
+ (should (map-contains-key map 1))
+ (should-not (map-contains-key map (map-length map)))))
+
+(ert-deftest test-map-contains-key-testfn ()
+ "Test `map-contains-key' under different equalities."
+ (let ((key (string ?a))
+ (plist '("a" 1 a 2))
+ (alist '(("a" . 1) (a . 2))))
+ (should (map-contains-key alist 'a))
+ (should (map-contains-key plist 'a))
+ (should (map-contains-key alist 'a #'eq))
+ (should (map-contains-key plist 'a #'eq))
+ (should (map-contains-key alist key))
+ (should-not (map-contains-key plist key))
+ (should-not (map-contains-key alist key #'eq))
+ (should-not (map-contains-key plist key #'eq))))
(ert-deftest test-map-some ()
(with-maps-do map
- (should (map-some (lambda (k _v)
- (eq 1 k))
- map))
- (should-not (map-some (lambda (k _v)
- (eq 'd k))
- map)))
- (let ((vec [a b c]))
- (should (map-some (lambda (k _v)
- (> k 1))
- vec))
- (should-not (map-some (lambda (k _v)
- (> k 3))
- vec))))
+ (should (eq (map-some (lambda (k _v) (and (= k 1) 'found)) map)
+ 'found))
+ (should-not (map-some #'ignore map)))
+ (with-empty-maps-do map
+ (should-not (map-some #'always map))
+ (should-not (map-some #'ignore map))))
(ert-deftest test-map-every-p ()
(with-maps-do map
- (should (map-every-p (lambda (k _v)
- k)
- map))
- (should (not (map-every-p (lambda (_k _v)
- nil)
- map))))
- (let ((vec [a b c]))
- (should (map-every-p (lambda (k _v)
- (>= k 0))
- vec))
- (should (not (map-every-p (lambda (k _v)
- (> k 3))
- vec)))))
+ (should (map-every-p #'always map))
+ (should-not (map-every-p #'ignore map))
+ (should-not (map-every-p (lambda (k _v) (zerop k)) map)))
+ (with-empty-maps-do map
+ (should (map-every-p #'always map))
+ (should (map-every-p #'ignore map))
+ (should (map-every-p (lambda (k _v) (zerop k)) map))))
(ert-deftest test-map-into ()
- (let* ((alist '((a . 1) (b . 2)))
- (ht (map-into alist 'hash-table)))
+ (let* ((plist '(a 1 b 2))
+ (alist '((a . 1) (b . 2)))
+ (ht (map-into alist 'hash-table))
+ (ht2 (map-into alist '(hash-table :test equal))))
(should (hash-table-p ht))
- (should (equal (map-into (map-into alist 'hash-table) 'list)
- alist))
- (should (listp (map-into ht 'list)))
- (should (equal (map-keys (map-into (map-into ht 'list) 'hash-table))
- (map-keys ht)))
- (should (equal (map-values (map-into (map-into ht 'list) 'hash-table))
- (map-values ht)))
- (should (null (map-into nil 'list)))
- (should (map-empty-p (map-into nil 'hash-table)))
- (should-error (map-into [1 2 3] 'string))))
+ (should (equal (map-into ht 'list) alist))
+ (should (equal (map-pairs (map-into (map-into ht 'list) 'hash-table))
+ (map-pairs ht)))
+ (should (equal (map-into ht 'alist) (map-into ht2 'alist)))
+ (should (equal (map-into alist 'list) alist))
+ (should (equal (map-into alist 'alist) alist))
+ (should (equal (map-into alist 'plist) plist))
+ (should (equal (map-into plist 'alist) alist))
+ (should (equal (map-into plist 'plist) plist)))
+ (should-error (map-into [1 2 3] 'string) :type 'cl-no-applicable-method))
+
+(ert-deftest test-map-into-hash-test ()
+ "Test `map-into' with different hash-table test functions."
+ (should (eq (hash-table-test (map-into () 'hash-table)) #'equal))
+ (should (eq (hash-table-test (map-into () '(hash-table))) #'eql))
+ (should (eq (hash-table-test (map-into () '(hash-table :test eq))) #'eq))
+ (should (eq (hash-table-test (map-into () '(hash-table :test eql))) #'eql))
+ (should (eq (hash-table-test (map-into () '(hash-table :test equal)))
+ #'equal)))
+
+(ert-deftest test-map-into-empty ()
+ "Test `map-into' with empty maps."
+ (with-empty-maps-do map
+ (should-not (map-into map 'list))
+ (should-not (map-into map 'alist))
+ (should-not (map-into map 'plist))
+ (should (map-empty-p (map-into map 'hash-table)))))
(ert-deftest test-map-let ()
(map-let (foo bar baz) '((foo . 1) (bar . 2))
(should (= foo 1))
(should (= bar 2))
- (should (null baz)))
+ (should-not baz))
(map-let (('foo a)
('bar b)
('baz c))
'((foo . 1) (bar . 2))
(should (= a 1))
(should (= b 2))
- (should (null c))))
+ (should-not c)))
+
+(ert-deftest test-map-merge ()
+ "Test `map-merge'."
+ (should (equal (sort (map-merge 'list '(a 1) '((b . 2) (c . 3))
+ #s(hash-table data (c 4)))
+ (lambda (x y) (string< (car x) (car y))))
+ '((a . 1) (b . 2) (c . 4))))
+ (should (equal (map-merge 'list () '(:a 1)) '((:a . 1))))
+ (should (equal (map-merge 'alist () '(:a 1)) '((:a . 1))))
+ (should (equal (map-merge 'plist () '(:a 1)) '(:a 1))))
(ert-deftest test-map-merge-with ()
- (should (equal (map-merge-with 'list #'+
- '((1 . 2))
- '((1 . 3) (2 . 4))
- '((1 . 1) (2 . 5) (3 . 0)))
- '((3 . 0) (2 . 9) (1 . 6)))))
+ (should (equal (sort (map-merge-with 'list #'+
+ '((1 . 2))
+ '((1 . 3) (2 . 4))
+ '((1 . 1) (2 . 5) (3 . 0)))
+ #'car-less-than-car)
+ '((1 . 6) (2 . 9) (3 . 0))))
+ (should (equal (map-merge-with 'list #'+ () '(:a 1)) '((:a . 1))))
+ (should (equal (map-merge-with 'alist #'+ () '(:a 1)) '((:a . 1))))
+ (should (equal (map-merge-with 'plist #'+ () '(:a 1)) '(:a 1))))
+
+(ert-deftest test-map-merge-empty ()
+ "Test merging of empty maps."
+ (should-not (map-merge 'list))
+ (should-not (map-merge 'alist))
+ (should-not (map-merge 'plist))
+ (should-not (map-merge-with 'list #'+))
+ (should-not (map-merge-with 'alist #'+))
+ (should-not (map-merge-with 'plist #'+))
+ (should (map-empty-p (map-merge 'hash-table)))
+ (should (map-empty-p (map-merge-with 'hash-table #'+)))
+ (should-error (map-merge 'array) :type 'cl-no-applicable-method)
+ (should-error (map-merge-with 'array #'+) :type 'cl-no-applicable-method))
+
+(ert-deftest test-map-plist-pcase ()
+ (let ((plist '(:one 1 :two 2)))
+ (should (equal (pcase-let (((map :one (:two two)) plist))
+ (list one two))
+ '(1 2)))))
+
+(ert-deftest test-map-setf-alist-insert-key ()
+ (let ((alist))
+ (should (equal (setf (map-elt alist 'key) 'value)
+ 'value))
+ (should (equal alist '((key . value))))))
+
+(ert-deftest test-map-setf-alist-overwrite-key ()
+ (let ((alist '((key . value1))))
+ (should (equal (setf (map-elt alist 'key) 'value2)
+ 'value2))
+ (should (equal alist '((key . value2))))))
+
+(ert-deftest test-map-setf-plist-insert-key ()
+ (let ((plist '(key value)))
+ (should (equal (setf (map-elt plist 'key2) 'value2)
+ 'value2))
+ (should (equal plist '(key value key2 value2)))))
+
+(ert-deftest test-map-setf-plist-overwrite-key ()
+ (let ((plist '(key value)))
+ (should (equal (setf (map-elt plist 'key) 'value2)
+ 'value2))
+ (should (equal plist '(key value2)))))
+
+(ert-deftest test-hash-table-setf-insert-key ()
+ (let ((ht (make-hash-table)))
+ (should (equal (setf (map-elt ht 'key) 'value)
+ 'value))
+ (should (equal (map-elt ht 'key) 'value))))
+
+(ert-deftest test-hash-table-setf-overwrite-key ()
+ (let ((ht (make-hash-table)))
+ (puthash 'key 'value1 ht)
+ (should (equal (setf (map-elt ht 'key) 'value2)
+ 'value2))
+ (should (equal (map-elt ht 'key) 'value2))))
+
+(ert-deftest test-setf-map-with-function ()
+ (let ((num 0)
+ (map nil))
+ (setf (map-elt map 'foo)
+ (funcall (lambda ()
+ (cl-incf num))))
+ ;; Check that the function is only called once.
+ (should (= num 1))))
(provide 'map-tests)
;;; map-tests.el ends here
diff --git a/test/lisp/emacs-lisp/memory-report-tests.el b/test/lisp/emacs-lisp/memory-report-tests.el
new file mode 100644
index 00000000000..869144163b7
--- /dev/null
+++ b/test/lisp/emacs-lisp/memory-report-tests.el
@@ -0,0 +1,83 @@
+;;; memory-report-tests.el --- tests for memory-report.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'memory-report)
+
+(defun setup-memory-report-tests ()
+ ;; Set the sizes on things based on a 64-bit architecture. (We're
+ ;; hard-coding this to be able to write simple tests that'll work on
+ ;; all architectures.)
+ (memory-report--set-size
+ '((conses 16 499173 99889)
+ (symbols 48 22244 3)
+ (strings 32 92719 4559)
+ (string-bytes 1 40402011)
+ (vectors 16 31919)
+ (vector-slots 8 385148 149240)
+ (floats 8 434 4519)
+ (intervals 56 24499 997)
+ (buffers 984 33))))
+
+(ert-deftest memory-report-sizes ()
+ (setup-memory-report-tests)
+ (should (equal (memory-report-object-size (cons nil nil)) 16))
+ (should (equal (memory-report-object-size (cons 1 2)) 16))
+
+ (should (equal (memory-report-object-size (list 1 2)) 32))
+ (should (equal (memory-report-object-size (list 1)) 16))
+
+ (should (equal (memory-report-object-size (list 'foo)) 16))
+
+ (should (equal (memory-report-object-size (vector 1 2 3)) 64))
+ (should (equal (memory-report-object-size (vector 1 2 3 4)) 80))
+
+ (should (equal (memory-report-object-size "") 32))
+ (should (equal (memory-report-object-size "a") 33))
+ (should (equal (memory-report-object-size (propertize "a" 'face 'foo))
+ 81)))
+
+(ert-deftest memory-report-sizes-vectors ()
+ (should (= (memory-report--object-size
+ (make-hash-table :test #'eq)
+ ["long string that should be at least 40 bytes"])
+ 108))
+ (let ((string "long string that should be at least 40 bytes"))
+ (should (= (memory-report--object-size
+ (make-hash-table :test #'eq)
+ (vector string))
+ 108))
+ (should (= (memory-report--object-size
+ (make-hash-table :test #'eq)
+ (vector string string))
+ 124))))
+
+(ert-deftest memory-report-sizes-structs ()
+ (cl-defstruct memory-report-test-struct
+ (item0 nil)
+ (item1 nil))
+ (let ((s (make-memory-report-test-struct :item0 "hello" :item1 "world")))
+ (should (= (memory-report-object-size s)
+ 90))))
+
+(provide 'memory-report-tests)
+
+;;; memory-report-tests.el ends here
diff --git a/test/lisp/emacs-lisp/multisession-tests.el b/test/lisp/emacs-lisp/multisession-tests.el
new file mode 100644
index 00000000000..5807c27bd20
--- /dev/null
+++ b/test/lisp/emacs-lisp/multisession-tests.el
@@ -0,0 +1,207 @@
+;;; multisession-tests.el --- Tests for multisession.el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'multisession)
+(require 'ert)
+(require 'ert-x)
+(require 'cl-lib)
+
+(declare-function sqlite-close "sqlite.c")
+
+(ert-deftest multi-test-sqlite-simple ()
+ (skip-unless (sqlite-available-p))
+ (ert-with-temp-file dir
+ :directory t
+ (let ((user-init-file "/tmp/foo.el")
+ (multisession-storage 'sqlite)
+ (multisession-directory dir))
+ (unwind-protect
+ (progn
+ (define-multisession-variable multisession--foo 0
+ ""
+ :synchronized t)
+ (should (= (multisession-value multisession--foo) 0))
+ (cl-incf (multisession-value multisession--foo))
+ (should (= (multisession-value multisession--foo) 1))
+ (call-process
+ (concat invocation-directory invocation-name)
+ nil t nil
+ "-Q" "-batch"
+ "--eval" (prin1-to-string
+ `(progn
+ (require 'multisession)
+ (let ((multisession-directory ,dir)
+ (multisession-storage 'sqlite)
+ (user-init-file "/tmp/foo.el"))
+ (define-multisession-variable multisession--foo 0
+ ""
+ :synchronized t)
+ (cl-incf (multisession-value multisession--foo))))))
+ (should (= (multisession-value multisession--foo) 2)))
+ (sqlite-close multisession--db)
+ (setq multisession--db nil)))))
+
+(ert-deftest multi-test-sqlite-busy ()
+ (skip-unless (sqlite-available-p))
+ (ert-with-temp-file dir
+ :directory t
+ (let ((user-init-file "/tmp/foo.el")
+ (multisession-directory dir)
+ (multisession-storage 'sqlite)
+ proc)
+ (unwind-protect
+ (progn
+ (define-multisession-variable multisession--bar 0
+ ""
+ :synchronized t)
+ (should (= (multisession-value multisession--bar) 0))
+ (cl-incf (multisession-value multisession--bar))
+ (should (= (multisession-value multisession--bar) 1))
+ (setq proc
+ (start-process
+ "other-emacs"
+ nil
+ (concat invocation-directory invocation-name)
+ "-Q" "-batch"
+ "--eval" (prin1-to-string
+ `(progn
+ (require 'multisession)
+ (let ((multisession-directory ,dir)
+ (multisession-storage 'sqlite)
+ (user-init-file "/tmp/bar.el"))
+ (define-multisession-variable multisession--bar 0
+ "" :synchronized t)
+ (dotimes (i 100)
+ (cl-incf (multisession-value multisession--bar))))))))
+ (while (process-live-p proc)
+ (ignore-error 'sqlite-locked-error
+ (message "multisession--bar %s" (multisession-value multisession--bar))
+ ;;(cl-incf (multisession-value multisession--bar))
+ )
+ (sleep-for 0.1))
+ (message "multisession--bar ends up as %s" (multisession-value multisession--bar))
+ (should (< (multisession-value multisession--bar) 1003)))
+ (sqlite-close multisession--db)
+ (setq multisession--db nil)))))
+
+(ert-deftest multi-test-files-simple ()
+ (ert-with-temp-file dir
+ :directory t
+ (let ((user-init-file "/tmp/sfoo.el")
+ (multisession-storage 'files)
+ (multisession-directory dir))
+ (define-multisession-variable multisession--sfoo 0
+ ""
+ :synchronized t)
+ (should (= (multisession-value multisession--sfoo) 0))
+ (cl-incf (multisession-value multisession--sfoo))
+ (should (= (multisession-value multisession--sfoo) 1))
+ ;; On Windows and Haiku, we don't have sub-second resolution, so
+ ;; let some time pass to make the "later" logic work.
+ (when (memq system-type '(windows-nt haiku))
+ (sleep-for 0.6))
+ (call-process
+ (concat invocation-directory invocation-name)
+ nil t nil
+ "-Q" "-batch"
+ "--eval" (prin1-to-string
+ `(progn
+ (require 'multisession)
+ (let ((multisession-directory ,dir)
+ (multisession-storage 'files)
+ (user-init-file "/tmp/sfoo.el"))
+ (define-multisession-variable multisession--sfoo 0
+ ""
+ :synchronized t)
+ (cl-incf (multisession-value multisession--sfoo))))))
+ (should (= (multisession-value multisession--sfoo) 2)))))
+
+(ert-deftest multi-test-files-busy ()
+ (skip-unless (sqlite-available-p))
+ (ert-with-temp-file dir
+ :directory t
+ (let ((user-init-file "/tmp/foo.el")
+ (multisession-storage 'files)
+ (multisession-directory dir)
+ proc)
+ (define-multisession-variable multisession--sbar 0
+ ""
+ :synchronized t)
+ (should (= (multisession-value multisession--sbar) 0))
+ (cl-incf (multisession-value multisession--sbar))
+ (should (= (multisession-value multisession--sbar) 1))
+ (setq proc
+ (start-process
+ "other-emacs"
+ nil
+ (concat invocation-directory invocation-name)
+ "-Q" "-batch"
+ "--eval" (prin1-to-string
+ `(progn
+ (require 'multisession)
+ (let ((multisession-directory ,dir)
+ (multisession-storage 'files)
+ (user-init-file "/tmp/sbar.el"))
+ (define-multisession-variable multisession--sbar 0
+ "" :synchronized t)
+ (dotimes (i 100)
+ (cl-incf (multisession-value multisession--sbar))))))))
+ (while (process-live-p proc)
+ (message "multisession--sbar %s" (multisession-value multisession--sbar))
+ ;;(cl-incf (multisession-value multisession--sbar))
+ (sleep-for 0.1))
+ (message "multisession--sbar ends up as %s" (multisession-value multisession--sbar))
+ (should (< (multisession-value multisession--sbar) 200)))))
+
+(ert-deftest multi-test-files-some-values ()
+ (ert-with-temp-file dir
+ :directory t
+ (let ((user-init-file "/tmp/sfoo.el")
+ (multisession-storage 'files)
+ (multisession-directory dir))
+ (define-multisession-variable multisession--foo1 nil)
+ (should (eq (multisession-value multisession--foo1) nil))
+ (setf (multisession-value multisession--foo1) nil)
+ (should (eq (multisession-value multisession--foo1) nil))
+ (setf (multisession-value multisession--foo1) t)
+ (should (eq (multisession-value multisession--foo1) t))
+
+ (define-multisession-variable multisession--foo2 t)
+ (setf (multisession-value multisession--foo2) nil)
+ (should (eq (multisession-value multisession--foo2) nil))
+ (setf (multisession-value multisession--foo2) t)
+ (should (eq (multisession-value multisession--foo2) t))
+
+ (define-multisession-variable multisession--foo3 t)
+ (should-error (setf (multisession-value multisession--foo3) (make-marker)))
+
+ (let ((string (with-temp-buffer
+ (set-buffer-multibyte nil)
+ (insert 0 1 2)
+ (buffer-string))))
+ (should-not (multibyte-string-p string))
+ (define-multisession-variable multisession--foo4 nil)
+ (setf (multisession-value multisession--foo4) string)
+ (should (equal (multisession-value multisession--foo4) string))))))
+
+;;; multisession-tests.el ends here
diff --git a/test/lisp/emacs-lisp/nadvice-tests.el b/test/lisp/emacs-lisp/nadvice-tests.el
index 5cee61ee67d..a675986b90b 100644
--- a/test/lisp/emacs-lisp/nadvice-tests.el
+++ b/test/lisp/emacs-lisp/nadvice-tests.el
@@ -1,6 +1,6 @@
-;;; advice-tests.el --- Test suite for the new advice thingy.
+;;; nadvice-tests.el --- Test suite for the new advice thingy. -*- lexical-binding:t -*-
-;; Copyright (C) 2012-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2022 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -153,13 +153,13 @@ function being an around advice."
(ert-deftest advice-test-call-interactively ()
"Check interaction between advice on call-interactively and called-interactively-p."
- (defun sm-test7.4 () (interactive) (cons 1 (called-interactively-p)))
- (let ((old (symbol-function 'call-interactively)))
+ (let ((sm-test7.4 (lambda () (interactive) (cons 1 (called-interactively-p))))
+ (old (symbol-function 'call-interactively)))
(unwind-protect
(progn
(advice-add 'call-interactively :before #'ignore)
- (should (equal (sm-test7.4) '(1 . nil)))
- (should (equal (call-interactively 'sm-test7.4) '(1 . t))))
+ (should (equal (funcall sm-test7.4) '(1 . nil)))
+ (should (equal (call-interactively sm-test7.4) '(1 . t))))
(advice-remove 'call-interactively #'ignore)
(should (eq (symbol-function 'call-interactively) old)))))
@@ -204,8 +204,17 @@ function being an around advice."
(remove-function (var sm-test10) sm-advice)
(should (equal (funcall sm-test10 5) 15))))
+(ert-deftest advice-test-print ()
+ (let ((x (list 'cdr)))
+ (add-function :after (car x) 'car)
+ (should (equal (cl-prin1-to-string (car x))
+ "#f(advice car :after cdr)"))
+ (add-function :before (car x) 'first)
+ (should (equal (cl-prin1-to-string (car x))
+ "#f(advice first :before #f(advice car :after cdr))"))))
+
;; Local Variables:
;; no-byte-compile: t
;; End:
-;;; advice-tests.el ends here.
+;;; nadvice-tests.el ends here
diff --git a/test/lisp/emacs-lisp/oclosure-tests.el b/test/lisp/emacs-lisp/oclosure-tests.el
new file mode 100644
index 00000000000..00b008845c0
--- /dev/null
+++ b/test/lisp/emacs-lisp/oclosure-tests.el
@@ -0,0 +1,166 @@
+;;; oclosure-tests.e; --- Tests for Open Closures -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'oclosure)
+(require 'cl-lib)
+(require 'eieio)
+
+(oclosure-define (oclosure-test
+ (:copier oclosure-test-copy)
+ (:copier oclosure-test-copy1 (fst)))
+ "Simple OClosure."
+ fst snd (name :mutable t))
+
+(cl-defmethod oclosure-test-gen ((_x compiled-function)) "#<bytecode>")
+
+(cl-defmethod oclosure-test-gen ((_x cons)) "#<cons>")
+
+(cl-defmethod oclosure-test-gen ((_x oclosure))
+ (format "#<oclosure:%s>" (cl-call-next-method)))
+
+(cl-defmethod oclosure-test-gen ((_x oclosure-test))
+ (format "#<oclosure-test:%s>" (cl-call-next-method)))
+
+(ert-deftest oclosure-test ()
+ (let* ((i 42)
+ (ocl1 (oclosure-lambda (oclosure-test (fst 1) (snd 2) (name "hi"))
+ ()
+ (list fst snd i)))
+ (ocl2 (oclosure-lambda (oclosure-test (name (cl-incf i)) (fst (cl-incf i)))
+ ()
+ (list fst snd 152 i))))
+ (should (equal (list (oclosure-test--fst ocl1)
+ (oclosure-test--snd ocl1)
+ (oclosure-test--name ocl1))
+ '(1 2 "hi")))
+ (should (equal (list (oclosure-test--fst ocl2)
+ (oclosure-test--snd ocl2)
+ (oclosure-test--name ocl2))
+ '(44 nil 43)))
+ (should (equal (funcall ocl1) '(1 2 44)))
+ (should (equal (funcall ocl2) '(44 nil 152 44)))
+ (should (equal (funcall (oclosure-test-copy ocl1 :fst 7)) '(7 2 44)))
+ (should (equal (funcall (oclosure-test-copy1 ocl1 9)) '(9 2 44)))
+ (should (cl-typep ocl1 'oclosure-test))
+ (should (cl-typep ocl1 'oclosure))
+ (should (member (oclosure-test-gen ocl1)
+ '("#<oclosure-test:#<oclosure:#<cons>>>"
+ "#<oclosure-test:#<oclosure:#<bytecode>>>")))
+ (should (stringp (documentation #'oclosure-test--fst)))
+ ))
+
+(ert-deftest oclosure-test-limits ()
+ (defvar byte-compile-debug)
+ (should
+ (condition-case err
+ (let ((lexical-binding t)
+ (byte-compile-debug t))
+ (byte-compile '(lambda ()
+ (let ((inc-fst nil))
+ (oclosure-lambda (oclosure-test (fst 'foo)) ()
+ (setq inc-fst (lambda () (setq fst (1+ fst))))
+ fst))))
+ nil)
+ (error
+ (and (eq 'error (car err))
+ (string-match "fst.*mutated" (cadr err))))))
+ (should
+ (condition-case err
+ (progn (macroexpand-all '(oclosure-define oclosure--foo a a))
+ nil)
+ (error
+ (and (eq 'error (car err))
+ (string-match "Duplicate slot name: a$" (cadr err))))))
+ (should
+ (condition-case err
+ (progn (macroexpand-all
+ '(oclosure-define (oclosure--foo (:parent oclosure-test)) fst))
+ nil)
+ (error
+ (and (eq 'error (car err))
+ (string-match "Duplicate slot name: fst$" (cadr err))))))
+ (should
+ (condition-case err
+ (progn (macroexpand '(oclosure-lambda (oclosure-test (fst 1) (fst 2))
+ () fst))
+ nil)
+ (error
+ (and (eq 'error (car err))
+ (string-match "Duplicate slot: fst$" (cadr err)))))))
+
+(cl-defmethod oclosure-interactive-form ((ot oclosure-test))
+ (let ((snd (oclosure-test--snd ot)))
+ (if (stringp snd) (list 'interactive snd))))
+
+(ert-deftest oclosure-test-interactive-form ()
+ (should (equal (interactive-form
+ (oclosure-lambda (oclosure-test (fst 1) (snd 2)) () fst))
+ nil))
+ (should (equal (interactive-form
+ (oclosure-lambda (oclosure-test (fst 1) (snd 2)) ()
+ (interactive "r")
+ fst))
+ '(interactive "r")))
+ (should (equal (interactive-form
+ (oclosure-lambda (oclosure-test (fst 1) (snd "P")) () fst))
+ '(interactive "P")))
+ (should (not (commandp
+ (oclosure-lambda (oclosure-test (fst 1) (snd 2)) () fst))))
+ (should (commandp
+ (oclosure-lambda (oclosure-test (fst 1) (snd "P")) () fst))))
+
+(oclosure-define (oclosure-test-mut
+ (:parent oclosure-test)
+ (:copier oclosure-test-mut-copy))
+ "Simple OClosure with a mutable field."
+ (mut :mutable t))
+
+(ert-deftest oclosure-test-mutate ()
+ (let* ((f (oclosure-lambda (oclosure-test-mut (fst 0) (mut 3))
+ (x)
+ (+ x fst mut)))
+ (f2 (oclosure-test-mut-copy f :fst 50)))
+ (should (equal (oclosure-test-mut--mut f) 3))
+ (should (equal (funcall f 5) 8))
+ (should (equal (funcall f2 5) 58))
+ (cl-incf (oclosure-test-mut--mut f) 7)
+ (should (equal (oclosure-test-mut--mut f) 10))
+ (should (equal (funcall f 5) 15))
+ (should (equal (funcall f2 15) 68))))
+
+(ert-deftest oclosure-test-slot-value ()
+ (require 'eieio)
+ (let ((ocl (oclosure-lambda
+ (oclosure-test (fst 'fst1) (snd 'snd1) (name 'name1))
+ (x)
+ (list name fst snd x))))
+ (should (equal 'fst1 (slot-value ocl 'fst)))
+ (should (equal 'snd1 (slot-value ocl 'snd)))
+ (should (equal 'name1 (slot-value ocl 'name)))
+ (setf (slot-value ocl 'name) 'new-name)
+ (should (equal 'new-name (slot-value ocl 'name)))
+ (should (equal '(new-name fst1 snd1 arg) (funcall ocl 'arg)))
+ (should-error (setf (slot-value ocl 'fst) 'new-fst) :type 'setting-constant)
+ (should (equal 'fst1 (slot-value ocl 'fst)))
+ ))
+
+;;; oclosure-tests.el ends here.
diff --git a/test/lisp/emacs-lisp/package-resources/key.pub b/test/lisp/emacs-lisp/package-resources/key.pub
index a326d34e54f..99965723baf 100644
--- a/test/lisp/emacs-lisp/package-resources/key.pub
+++ b/test/lisp/emacs-lisp/package-resources/key.pub
@@ -1,18 +1,17 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
-Version: GnuPG v1.4.14 (GNU/Linux)
-mQENBFJNB8gBCACfbtpvYrM8V1HM0KFlIwatcEJugHqwOHpr/Z9mrCW0fxyQAW/d
-2L+3QVNsN9Tz/K9lLcBUgeR7rhVEzHNqhmhNj/HnikwGqXbIofhp+QbZmBKnAlCz
-d77kg8K9lozHtfTkm1gX/7DdPzQKmgi7WOzzi2395wGubeqJLvYaEcqVbI0Eob+E
-3CzRjNy/e/Tf3TJRW5etTcdZN6LVuIY7tNCHqlQZTwyycON/hfLTX6cLCnzDsqm/
-NxCuwn9aqP9aGRGfIu7Y+If3zTymvrXEPUN98OEID814bOKdx0uVTZRiSMbvuTGI
-8uMa/kpGX/78rqI61gbZV51RFoU7pT2tzwY/ABEBAAG0HkouIFIuIEhhY2tlciA8
-anJoQGV4YW1wbGUuY29tPokBOAQTAQIAIgUCUk0HyAIbAwYLCQgHAwIGFQgCCQoL
-BBYCAwECHgECF4AACgkQtpVAhgkYletuhQf+JAyHYhTZNxjq0UYlikuLX8EtYbXX
-PB+03J0B73SMzEai5XsiTU2ADxqxwr7pveVK1INf+IGLiiXBlQq+4DSOvQY4xLfp
-58jTOYRV1ECvlXK/JtvVOwufXREADaydf9l/MUxA5G2PPBWIuQknh3ysPSsx68OJ
-SzNHFwklLn0DKc4WloE/GLDpTzimnCg7QGzuUo3Iilpjdy8EvTdI5d3jx/mGJIwI
-goB+YZgyxSPM+GjDwh5DEwD7OexNqqa7RynnmU0epmlYyi9UufCHLwgiiEIzjpWi
-6+iF+CQ45ZAKncovByenIUv73J3ImOudrsskeAHBmahljv1he6uV9Egj2Q==
-=b5Kg
+mQGiBGFQyDcRBACmAI6cfY3fM02vb9JtC1BS19boKXbBsDoVrD9qRf8tDFROOpO3
+ZMlbuz+O9Vnljo6Y4WZGnyeWWAMqCditMOfr1cLbux77wSrmAVgZ9exwtGzkmUhM
+xcptzKuyod8NuhghXbJgVbfJZ6HlBkk4kiWv98iJQwUBZJfjBUfIv+acjwCg4M2i
+Ifu2A3UYl9VqF7qfcDOZudEEAI7V35yfsBDnr9ndKqdGYNw0alX9BEG3KwnAe0fF
+O1jDVW12Y/bwnyyrRTrz6o1G8dj7M4XVZQb5PpT9mpNzOSZ6yxqhg+foeJwn2JkD
+vyP+kMYU7SZ/tWuMOCdzN95Ki1rf+ti7pLnSMqKx+t3vOWwQbtnsbI6RCLLwETPA
+esghA/0X3Dw7cdiE5Xq4TRaPSGViCWP4ekL2KYKqmKv6M/4f2pgFNJY7C+2SIiiP
+T62zFlIjs5tF2Df34/M5mh4Vx6E8341r55+XO++kfFWJ5QjLiydRAY6ochG9IFgB
+xyBCkCNpiby9PpKyPodedBScdMxIAe4eJR7rG/j9gFC1MypBurQnSm9obm55IFJv
+Y2tldHMgPGpvaG5ueS5yb2NrZXRzQGdmeS5vcmc+iHgEExECADgWIQRIVz1DPzm4
+REDIXNtltQG5ACv6lwUCYVDINwIbAwULCQgHAgYVCgkICwIEFgIDAQIeAQIXgAAK
+CRBltQG5ACv6l4iZAKCqldroRYH7vUzVV0Uv1NcDVcpLngCgmEoLVxGLKSwDEXNq
+qjRDzDRpReg=
+=/l51
-----END PGP PUBLIC KEY BLOCK-----
diff --git a/test/lisp/emacs-lisp/package-resources/key.sec b/test/lisp/emacs-lisp/package-resources/key.sec
index d21e6ae9a45..5bbac1226ae 100644
--- a/test/lisp/emacs-lisp/package-resources/key.sec
+++ b/test/lisp/emacs-lisp/package-resources/key.sec
@@ -1,33 +1,17 @@
-----BEGIN PGP PRIVATE KEY BLOCK-----
-Version: GnuPG v1.4.14 (GNU/Linux)
-lQO+BFJNB8gBCACfbtpvYrM8V1HM0KFlIwatcEJugHqwOHpr/Z9mrCW0fxyQAW/d
-2L+3QVNsN9Tz/K9lLcBUgeR7rhVEzHNqhmhNj/HnikwGqXbIofhp+QbZmBKnAlCz
-d77kg8K9lozHtfTkm1gX/7DdPzQKmgi7WOzzi2395wGubeqJLvYaEcqVbI0Eob+E
-3CzRjNy/e/Tf3TJRW5etTcdZN6LVuIY7tNCHqlQZTwyycON/hfLTX6cLCnzDsqm/
-NxCuwn9aqP9aGRGfIu7Y+If3zTymvrXEPUN98OEID814bOKdx0uVTZRiSMbvuTGI
-8uMa/kpGX/78rqI61gbZV51RFoU7pT2tzwY/ABEBAAH+AwMCKCCpPNXkXuVgF7cz
-eByuvgIO7wImDYGOdJqsASSzV4q0u1acnGtlxg7WphKDF9RnC5+1ZZ1ZcrBcv2uJ
-xZm2jHdjqM3FmgQTN70GVzO1nKEur2wxlKotG4Q+8BtaRDwHdKpQFk+QW9aInH3C
-BkNWTK97iFwZaoUGxKuRJb35qjMe3SsDE7kdbtOqO+tOeppRVeOOZCn7F33ir/6i
-j2gmIME6LFDzvBi6YAyMBSh90Ak70HJINt0QfXlZf5MtX1NaxaEcnsRmwwcNqxh9
-JvcC9q4WrR92NhHCHI+lOsAe7hbwo/VkwRjSSx0HdKkx6kvdcNj/9LeX/jykzLvg
-kEqvAqT4Jmk57W2seqvpNcAO+eUVrJ5D1OR6khsUtikPp2pQH5MDXJDGcie+ZAFb
-w6BwoWBDBjooKtfuP0LKqrdtJG2JLe6yhBhWvfqHPBlUU1SsA7a5aTCLo8FiqgEI
-Kyy60zMx/2Mi48oN1a/mAoV1MTWLhOVUWJlIHM7nVLj1OaX0316LcLX/uTLTq40p
-apHKwERanzY7f8ROiv/Fa/J+9cCsfOLKfjFAjpBVUVoOb39HsyS/vvkGMY4kgaD6
-K6r9JPdsaoYvsLkxk5HyHF7Mk2uS1z1EIArD2/3lRiX6ag+IU1Nl3XDkgfZj06K3
-juS84dGF8CmN49uOEjzAJAQZH9jTs5OKzUuZhGJF+gt0L78vLOoKRr8bu1N1GPqU
-wnS908HWruXzjJl1CAhnuCa8FnDaU+tmEKjYpWuelx85kolpMW7LT5gOFZr84MIj
-Kq3Rt2hU6qQ7Cdy1ep531YKkmyh9Y4l/Tgir1OtnQQqtNuwHI497l7qAUnKZBBHZ
-guApjS9BoHsRXkw2mgDssZ+khOwj/xJm876nFSiQeCD0aIbU/4zJ9e2HUOJAZI1r
-d7QeSi4gUi4gSGFja2VyIDxqcmhAZXhhbXBsZS5jb20+iQE4BBMBAgAiBQJSTQfI
-AhsDBgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAKCRC2lUCGCRiV626FB/4kDIdi
-FNk3GOrRRiWKS4tfwS1htdc8H7TcnQHvdIzMRqLleyJNTYAPGrHCvum95UrUg1/4
-gYuKJcGVCr7gNI69BjjEt+nnyNM5hFXUQK+Vcr8m29U7C59dEQANrJ1/2X8xTEDk
-bY88FYi5CSeHfKw9KzHrw4lLM0cXCSUufQMpzhaWgT8YsOlPOKacKDtAbO5SjciK
-WmN3LwS9N0jl3ePH+YYkjAiCgH5hmDLFI8z4aMPCHkMTAPs57E2qprtHKeeZTR6m
-aVjKL1S58IcvCCKIQjOOlaLr6IX4JDjlkAqdyi8HJ6chS/vcnciY652uyyR4AcGZ
-qGWO/WF7q5X0SCPZ
-=5FZK
+lQG7BGFQyDcRBACmAI6cfY3fM02vb9JtC1BS19boKXbBsDoVrD9qRf8tDFROOpO3
+ZMlbuz+O9Vnljo6Y4WZGnyeWWAMqCditMOfr1cLbux77wSrmAVgZ9exwtGzkmUhM
+xcptzKuyod8NuhghXbJgVbfJZ6HlBkk4kiWv98iJQwUBZJfjBUfIv+acjwCg4M2i
+Ifu2A3UYl9VqF7qfcDOZudEEAI7V35yfsBDnr9ndKqdGYNw0alX9BEG3KwnAe0fF
+O1jDVW12Y/bwnyyrRTrz6o1G8dj7M4XVZQb5PpT9mpNzOSZ6yxqhg+foeJwn2JkD
+vyP+kMYU7SZ/tWuMOCdzN95Ki1rf+ti7pLnSMqKx+t3vOWwQbtnsbI6RCLLwETPA
+esghA/0X3Dw7cdiE5Xq4TRaPSGViCWP4ekL2KYKqmKv6M/4f2pgFNJY7C+2SIiiP
+T62zFlIjs5tF2Df34/M5mh4Vx6E8341r55+XO++kfFWJ5QjLiydRAY6ochG9IFgB
+xyBCkCNpiby9PpKyPodedBScdMxIAe4eJR7rG/j9gFC1MypBugAAn0mvGeJi+oSo
+5jXAeXBhRiTyI5WPCuK0J0pvaG5ueSBSb2NrZXRzIDxqb2hubnkucm9ja2V0c0Bn
+Znkub3JnPoh4BBMRAgA4FiEESFc9Qz85uERAyFzbZbUBuQAr+pcFAmFQyDcCGwMF
+CwkIBwIGFQoJCAsCBBYCAwECHgECF4AACgkQZbUBuQAr+peImQCgqpXa6EWB+71M
+1VdFL9TXA1XKS54AoJhKC1cRiyksAxFzaqo0Q8w0aUXo
+=cyQm
-----END PGP PRIVATE KEY BLOCK-----
diff --git a/test/lisp/emacs-lisp/package-resources/macro-builtin-package-1.0/macro-builtin-aux.el b/test/lisp/emacs-lisp/package-resources/macro-builtin-package-1.0/macro-builtin-aux.el
new file mode 100644
index 00000000000..724f88ec9ea
--- /dev/null
+++ b/test/lisp/emacs-lisp/package-resources/macro-builtin-package-1.0/macro-builtin-aux.el
@@ -0,0 +1,12 @@
+;;; macro-builtin-aux.el --- laksd -*- lexical-binding: t; -*-
+
+;; Author: Artur Malabarba <emacs@endlessparentheses.com>
+
+;;; Code:
+
+(defun macro-builtin-aux-1 ( &rest forms)
+ "Description"
+ `(progn ,@forms))
+
+(provide 'macro-builtin-aux)
+;;; macro-builtin-aux.el ends here
diff --git a/test/lisp/emacs-lisp/package-resources/macro-builtin-package-1.0/macro-builtin.el b/test/lisp/emacs-lisp/package-resources/macro-builtin-package-1.0/macro-builtin.el
new file mode 100644
index 00000000000..828968a0576
--- /dev/null
+++ b/test/lisp/emacs-lisp/package-resources/macro-builtin-package-1.0/macro-builtin.el
@@ -0,0 +1,21 @@
+;;; macro-builtin.el --- laksd -*- lexical-binding: t; -*-
+
+;; Author: Artur Malabarba <emacs@endlessparentheses.com>
+;; Keywords: tools
+;; Version: 1.0
+
+;;; Code:
+
+(require 'macro-builtin-aux)
+
+(defmacro macro-builtin-1 ( &rest forms)
+ "Description"
+ `(progn ,@forms))
+
+(defun macro-builtin-func ()
+ ""
+ (macro-builtin-1 'a 'b)
+ (macro-builtin-aux-1 'a 'b))
+
+(provide 'macro-builtin)
+;;; macro-builtin.el ends here
diff --git a/test/lisp/emacs-lisp/package-resources/macro-builtin-package-2.0/macro-builtin-aux.el b/test/lisp/emacs-lisp/package-resources/macro-builtin-package-2.0/macro-builtin-aux.el
new file mode 100644
index 00000000000..9f257d9d22c
--- /dev/null
+++ b/test/lisp/emacs-lisp/package-resources/macro-builtin-package-2.0/macro-builtin-aux.el
@@ -0,0 +1,16 @@
+;;; macro-builtin-aux.el --- laksd -*- lexical-binding: t; -*-
+
+;; Author: Artur Malabarba <emacs@endlessparentheses.com>
+
+;;; Code:
+
+(defmacro macro-builtin-aux-1 ( &rest forms)
+ "Description"
+ `(progn ,@forms))
+
+(defmacro macro-builtin-aux-3 ( &rest _)
+ "Description"
+ 90)
+
+(provide 'macro-builtin-aux)
+;;; macro-builtin-aux.el ends here
diff --git a/test/lisp/emacs-lisp/package-resources/macro-builtin-package-2.0/macro-builtin.el b/test/lisp/emacs-lisp/package-resources/macro-builtin-package-2.0/macro-builtin.el
new file mode 100644
index 00000000000..5d241c082d0
--- /dev/null
+++ b/test/lisp/emacs-lisp/package-resources/macro-builtin-package-2.0/macro-builtin.el
@@ -0,0 +1,30 @@
+;;; macro-builtin.el --- laksd -*- lexical-binding: t; -*-
+
+;; Author: Artur Malabarba <emacs@endlessparentheses.com>
+;; Keywords: tools
+;; Version: 2.0
+
+;;; Code:
+
+(require 'macro-builtin-aux)
+
+(defmacro macro-builtin-1 ( &rest forms)
+ "Description"
+ `(progn ,(cadr (car forms))))
+
+
+(defun macro-builtin-func ()
+ ""
+ (list (macro-builtin-1 '1 'b)
+ (macro-builtin-aux-1 'a 'b)))
+
+(defmacro macro-builtin-3 (&rest _)
+ "Description"
+ 10)
+
+(defun macro-builtin-10-and-90 ()
+ ""
+ (list (macro-builtin-3 haha) (macro-builtin-aux-3 hehe)))
+
+(provide 'macro-builtin)
+;;; macro-builtin.el ends here
diff --git a/test/lisp/emacs-lisp/package-resources/macro-problem-package-1.0/macro-aux.el b/test/lisp/emacs-lisp/package-resources/macro-problem-package-1.0/macro-aux.el
index f43232224af..ad20a3507a6 100644
--- a/test/lisp/emacs-lisp/package-resources/macro-problem-package-1.0/macro-aux.el
+++ b/test/lisp/emacs-lisp/package-resources/macro-problem-package-1.0/macro-aux.el
@@ -5,7 +5,7 @@
;;; Code:
(defun macro-aux-1 ( &rest forms)
- "Description"
+ "Description."
`(progn ,@forms))
(provide 'macro-aux)
diff --git a/test/lisp/emacs-lisp/package-resources/macro-problem-package-1.0/macro-problem.el b/test/lisp/emacs-lisp/package-resources/macro-problem-package-1.0/macro-problem.el
index 0533b1bd9c4..6e5e54e54fd 100644
--- a/test/lisp/emacs-lisp/package-resources/macro-problem-package-1.0/macro-problem.el
+++ b/test/lisp/emacs-lisp/package-resources/macro-problem-package-1.0/macro-problem.el
@@ -9,11 +9,11 @@
(require 'macro-aux)
(defmacro macro-problem-1 ( &rest forms)
- "Description"
+ "Description."
`(progn ,@forms))
(defun macro-problem-func ()
- ""
+ "Description."
(macro-problem-1 'a 'b)
(macro-aux-1 'a 'b))
diff --git a/test/lisp/emacs-lisp/package-resources/macro-problem-package-2.0/macro-aux.el b/test/lisp/emacs-lisp/package-resources/macro-problem-package-2.0/macro-aux.el
index 6a55a40e3b4..814d77183ab 100644
--- a/test/lisp/emacs-lisp/package-resources/macro-problem-package-2.0/macro-aux.el
+++ b/test/lisp/emacs-lisp/package-resources/macro-problem-package-2.0/macro-aux.el
@@ -5,11 +5,11 @@
;;; Code:
(defmacro macro-aux-1 ( &rest forms)
- "Description"
+ "Description."
`(progn ,@forms))
(defmacro macro-aux-3 ( &rest _)
- "Description"
+ "Description."
90)
(provide 'macro-aux)
diff --git a/test/lisp/emacs-lisp/package-resources/macro-problem-package-2.0/macro-problem.el b/test/lisp/emacs-lisp/package-resources/macro-problem-package-2.0/macro-problem.el
index cad4ed93f19..aef5eda7c6c 100644
--- a/test/lisp/emacs-lisp/package-resources/macro-problem-package-2.0/macro-problem.el
+++ b/test/lisp/emacs-lisp/package-resources/macro-problem-package-2.0/macro-problem.el
@@ -9,21 +9,21 @@
(require 'macro-aux)
(defmacro macro-problem-1 ( &rest forms)
- "Description"
+ "Description."
`(progn ,(cadr (car forms))))
(defun macro-problem-func ()
- ""
+ "Description."
(list (macro-problem-1 '1 'b)
(macro-aux-1 'a 'b)))
(defmacro macro-problem-3 (&rest _)
- "Description"
+ "Description."
10)
(defun macro-problem-10-and-90 ()
- ""
+ "Description."
(list (macro-problem-3 haha) (macro-aux-3 hehe)))
(provide 'macro-problem)
diff --git a/test/lisp/emacs-lisp/package-resources/newer-versions/new-pkg-1.0.el b/test/lisp/emacs-lisp/package-resources/newer-versions/new-pkg-1.0.el
index 7251622fa59..61c1b045990 100644
--- a/test/lisp/emacs-lisp/package-resources/newer-versions/new-pkg-1.0.el
+++ b/test/lisp/emacs-lisp/package-resources/newer-versions/new-pkg-1.0.el
@@ -1,4 +1,4 @@
-;;; new-pkg.el --- A package only seen after "updating" archive-contents
+;;; new-pkg.el --- A package only seen after "updating" archive-contents -*- lexical-binding:t -*-
;; Author: J. R. Hacker <jrh@example.com>
;; Version: 1.0
diff --git a/test/lisp/emacs-lisp/package-resources/newer-versions/simple-single-1.4.el b/test/lisp/emacs-lisp/package-resources/newer-versions/simple-single-1.4.el
index 7b1c00c06db..be6bedf8a1c 100644
--- a/test/lisp/emacs-lisp/package-resources/newer-versions/simple-single-1.4.el
+++ b/test/lisp/emacs-lisp/package-resources/newer-versions/simple-single-1.4.el
@@ -1,4 +1,4 @@
-;;; simple-single.el --- A single-file package with no dependencies
+;;; simple-single.el --- A single-file package with no dependencies -*- lexical-binding:t -*-
;; Author: J. R. Hacker <jrh@example.com>
;; Version: 1.4
@@ -7,14 +7,14 @@
;;; Commentary:
;; This package provides a minor mode to frobnicate and/or bifurcate
-;; any flanges you desire. To activate it, type "C-M-r M-3 butterfly"
+;; any flanges you desire. To activate it, type "C-M-r M-3 butterfly"
;; and all your dreams will come true.
;;
;; This is a new, updated version.
;;; Code:
-(defgroup simple-single nil "Simply a file"
+(defgroup simple-single nil "Simply a file."
:group 'lisp)
(defcustom simple-single-super-sunday nil
@@ -29,7 +29,7 @@ Default changed to nil."
;;;###autoload
(define-minor-mode simple-single-mode
- "It does good things to stuff")
+ "It does good things to stuff.")
(provide 'simple-single)
diff --git a/test/lisp/emacs-lisp/package-resources/signed/archive-contents.sig b/test/lisp/emacs-lisp/package-resources/signed/archive-contents.sig
index 658edd3f60e..b40620a0e89 100644
--- a/test/lisp/emacs-lisp/package-resources/signed/archive-contents.sig
+++ b/test/lisp/emacs-lisp/package-resources/signed/archive-contents.sig
Binary files differ
diff --git a/test/lisp/emacs-lisp/package-resources/signed/signed-bad-1.0.el b/test/lisp/emacs-lisp/package-resources/signed/signed-bad-1.0.el
index 3734823876e..781077251e9 100644
--- a/test/lisp/emacs-lisp/package-resources/signed/signed-bad-1.0.el
+++ b/test/lisp/emacs-lisp/package-resources/signed/signed-bad-1.0.el
@@ -1,4 +1,4 @@
-;;; signed-bad.el --- A single-file package with bad signature
+;;; signed-bad.el --- A single-file package with bad signature -*- lexical-binding: t -*-
;; Author: J. R. Hacker <jrh@example.com>
;; Version: 1.0
@@ -8,12 +8,12 @@
;;; Commentary:
;; This package provides a minor mode to frobnicate and/or bifurcate
-;; any flanges you desire. To activate it, type "C-M-r M-3 butterfly"
+;; any flanges you desire. To activate it, type "C-M-r M-3 butterfly"
;; and all your dreams will come true.
;;; Code:
-(defgroup signed-bad nil "Simply a file"
+(defgroup signed-bad nil "Simply a file."
:group 'lisp)
(defcustom signed-bad-super-sunday t
@@ -26,7 +26,7 @@
;;;###autoload
(define-minor-mode signed-bad-mode
- "It does good things to stuff")
+ "It does good things to stuff.")
(provide 'signed-bad)
diff --git a/test/lisp/emacs-lisp/package-resources/signed/signed-good-1.0.el b/test/lisp/emacs-lisp/package-resources/signed/signed-good-1.0.el
index 22718df2763..8a408c1f301 100644
--- a/test/lisp/emacs-lisp/package-resources/signed/signed-good-1.0.el
+++ b/test/lisp/emacs-lisp/package-resources/signed/signed-good-1.0.el
@@ -1,4 +1,4 @@
-;;; signed-good.el --- A single-file package with good signature
+;;; signed-good.el --- A single-file package with good signature -*- lexical-binding: t -*-
;; Author: J. R. Hacker <jrh@example.com>
;; Version: 1.0
@@ -8,12 +8,12 @@
;;; Commentary:
;; This package provides a minor mode to frobnicate and/or bifurcate
-;; any flanges you desire. To activate it, type "C-M-r M-3 butterfly"
+;; any flanges you desire. To activate it, type "C-M-r M-3 butterfly"
;; and all your dreams will come true.
;;; Code:
-(defgroup signed-good nil "Simply a file"
+(defgroup signed-good nil "Simply a file."
:group 'lisp)
(defcustom signed-good-super-sunday t
@@ -26,7 +26,7 @@
;;;###autoload
(define-minor-mode signed-good-mode
- "It does good things to stuff")
+ "It does good things to stuff.")
(provide 'signed-good)
diff --git a/test/lisp/emacs-lisp/package-resources/signed/signed-good-1.0.el.sig b/test/lisp/emacs-lisp/package-resources/signed/signed-good-1.0.el.sig
index 747918794ca..11092411601 100644
--- a/test/lisp/emacs-lisp/package-resources/signed/signed-good-1.0.el.sig
+++ b/test/lisp/emacs-lisp/package-resources/signed/signed-good-1.0.el.sig
Binary files differ
diff --git a/test/lisp/emacs-lisp/package-resources/signed/update-signatures.sh b/test/lisp/emacs-lisp/package-resources/signed/update-signatures.sh
new file mode 100755
index 00000000000..c3e82fd1737
--- /dev/null
+++ b/test/lisp/emacs-lisp/package-resources/signed/update-signatures.sh
@@ -0,0 +1,32 @@
+#! /bin/sh
+
+# Generate a new key and update the signatures for tests.
+
+# Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+# This file is part of GNU Emacs.
+
+# GNU Emacs is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# GNU Emacs is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+export GPG_AGENT=""
+KEYRING="./key.ring"
+TRUSTDB="./trust.db"
+GPG="gpg --no-default-keyring --trustdb-name $TRUSTDB --keyring $KEYRING --yes"
+
+rm $KEYRING
+$GPG --full-generate-key
+$GPG --export --armor > "../key.pub"
+$GPG --export-secret-keys -armor > "../key.sec"
+$GPG --detach-sign --sign "./archive-contents"
+$GPG --detach-sign --sign "./signed-good-1.0.el"
diff --git a/test/lisp/emacs-lisp/package-resources/simple-depend-1.0.el b/test/lisp/emacs-lisp/package-resources/simple-depend-1.0.el
index b58b658d024..f1ee8627610 100644
--- a/test/lisp/emacs-lisp/package-resources/simple-depend-1.0.el
+++ b/test/lisp/emacs-lisp/package-resources/simple-depend-1.0.el
@@ -1,4 +1,4 @@
-;;; simple-depend.el --- A single-file package with a dependency.
+;;; simple-depend.el --- A single-file package with a dependency. -*- lexical-binding:t -*-
;; Author: J. R. Hacker <jrh@example.com>
;; Version: 1.0
@@ -12,6 +12,6 @@
;;; Code:
(defvar simple-depend "Value"
- "Some trivial code")
+ "Some trivial code.")
;;; simple-depend.el ends here
diff --git a/test/lisp/emacs-lisp/package-resources/simple-single-1.3.el b/test/lisp/emacs-lisp/package-resources/simple-single-1.3.el
index 6756a28080b..459801d78cf 100644
--- a/test/lisp/emacs-lisp/package-resources/simple-single-1.3.el
+++ b/test/lisp/emacs-lisp/package-resources/simple-single-1.3.el
@@ -1,4 +1,4 @@
-;;; simple-single.el --- A single-file package with no dependencies
+;;; simple-single.el --- A single-file package with no dependencies -*- lexical-binding:t -*-
;; Author: J. R. Hacker <jrh@example.com>
;; Version: 1.3
@@ -8,12 +8,12 @@
;;; Commentary:
;; This package provides a minor mode to frobnicate and/or bifurcate
-;; any flanges you desire. To activate it, type "C-M-r M-3 butterfly"
+;; any flanges you desire. To activate it, type "C-M-r M-3 butterfly"
;; and all your dreams will come true.
;;; Code:
-(defgroup simple-single nil "Simply a file"
+(defgroup simple-single nil "Simply a file."
:group 'lisp)
(defcustom simple-single-super-sunday t
@@ -26,7 +26,7 @@
;;;###autoload
(define-minor-mode simple-single-mode
- "It does good things to stuff")
+ "It does good things to stuff.")
(provide 'simple-single)
diff --git a/test/lisp/emacs-lisp/package-resources/simple-two-depend-1.1.el b/test/lisp/emacs-lisp/package-resources/simple-two-depend-1.1.el
index 9cfe5c0d4e2..8de6141d67a 100644
--- a/test/lisp/emacs-lisp/package-resources/simple-two-depend-1.1.el
+++ b/test/lisp/emacs-lisp/package-resources/simple-two-depend-1.1.el
@@ -1,4 +1,4 @@
-;;; simple-two-depend.el --- A single-file package with two dependencies.
+;;; simple-two-depend.el --- A single-file package with two dependencies. -*- lexical-binding:t -*-
;; Author: J. R. Hacker <jrh@example.com>
;; Version: 1.1
@@ -12,6 +12,6 @@
;;; Code:
(defvar simple-two-depend "Value"
- "Some trivial code")
+ "Some trivial code.")
;;; simple-two-depend.el ends here
diff --git a/test/lisp/emacs-lisp/package-resources/with-nil-entry/archive-contents b/test/lisp/emacs-lisp/package-resources/with-nil-entry/archive-contents
new file mode 100644
index 00000000000..03e6aa7f7c6
--- /dev/null
+++ b/test/lisp/emacs-lisp/package-resources/with-nil-entry/archive-contents
@@ -0,0 +1,8 @@
+(1
+ (foo .
+ [(1 0)
+ nil "foo package" single])
+ nil
+ (bar .
+ [(1 0)
+ nil "bar package" single]))
diff --git a/test/lisp/emacs-lisp/package-tests.el b/test/lisp/emacs-lisp/package-tests.el
index 33209d3d990..b903cd781ba 100644
--- a/test/lisp/emacs-lisp/package-tests.el
+++ b/test/lisp/emacs-lisp/package-tests.el
@@ -1,6 +1,6 @@
-;;; package-test.el --- Tests for the Emacs package system
+;;; package-tests.el --- Tests for the Emacs package system -*- lexical-binding:t -*-
-;; Copyright (C) 2013-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2022 Free Software Foundation, Inc.
;; Author: Daniel Hackney <dan@haxney.org>
;; Version: 1.0
@@ -28,12 +28,18 @@
;; Run this in a clean Emacs session using:
;;
-;; $ emacs -Q --batch -L . -l package-test.el -l ert -f ert-run-tests-batch-and-exit
+;; $ emacs -Q --batch -L . -l package-tests.el -l ert -f ert-run-tests-batch-and-exit
+;;
+;; From the top level directory of the Emacs development repository,
+;; you can use this instead:
+;;
+;; $ make -C test package-tests
;;; Code:
(require 'package)
(require 'ert)
+(require 'ert-x)
(require 'cl-lib)
(setq package-menu-async nil)
@@ -97,13 +103,9 @@
(multi-file (0 1))))
"`package-desc' used for testing dependencies.")
-(defvar package-test-data-dir (expand-file-name "package-resources" package-test-file-dir)
+(defvar package-test-data-dir (ert-resource-directory)
"Base directory of package test files.")
-(defvar package-test-fake-contents-file
- (expand-file-name "archive-contents" package-test-data-dir)
- "Path to a static copy of \"archive-contents\".")
-
(cl-defmacro with-package-test ((&optional &key file
basedir
install
@@ -112,52 +114,60 @@
upload-base)
&rest body)
"Set up temporary locations and variables for testing."
- (declare (indent 1))
- `(let* ((package-test-user-dir (make-temp-file "pkg-test-user-dir-" t))
- (process-environment (cons (format "HOME=%s" package-test-user-dir)
- process-environment))
- (package-user-dir package-test-user-dir)
- (package-gnupghome-dir (expand-file-name "gnupg" package-user-dir))
- (package-archives `(("gnu" . ,(or ,location package-test-data-dir))))
- (default-directory package-test-file-dir)
- abbreviated-home-dir
- package--initialized
- package-alist
- ,@(if update-news
- '(package-update-news-on-upload t)
- (list (cl-gensym)))
- ,@(if upload-base
- '((package-test-archive-upload-base (make-temp-file "pkg-archive-base-" t))
- (package-archive-upload-base package-test-archive-upload-base))
- (list (cl-gensym)))) ;; Dummy value so `let' doesn't try to bind nil
- (let ((buf (get-buffer "*Packages*")))
- (when (buffer-live-p buf)
- (kill-buffer buf)))
- (unwind-protect
- (progn
- ,(if basedir `(cd ,basedir))
- (unless (file-directory-p package-user-dir)
- (mkdir package-user-dir))
- (cl-letf (((symbol-function 'yes-or-no-p) (lambda (&rest r) t))
- ((symbol-function 'y-or-n-p) (lambda (&rest r) t)))
- ,@(when install
- `((package-initialize)
- (package-refresh-contents)
- (mapc 'package-install ,install)))
- (with-temp-buffer
- ,(if file
- `(insert-file-contents ,file))
- ,@body)))
-
- (when (file-directory-p package-test-user-dir)
- (delete-directory package-test-user-dir t))
-
- (when (and (boundp 'package-test-archive-upload-base)
- (file-directory-p package-test-archive-upload-base))
- (delete-directory package-test-archive-upload-base t)))))
+ (declare (indent 1) (debug (([&rest form]) body)))
+ `(ert-with-temp-directory package-test-user-dir
+ (let* ((process-environment (cons (format "HOME=%s" package-test-user-dir)
+ process-environment))
+ (package-user-dir package-test-user-dir)
+ (package-gnupghome-dir (expand-file-name "gnupg" package-user-dir))
+ (package-archives `(("gnu" . ,(or ,location package-test-data-dir))))
+ (default-directory package-test-file-dir)
+ abbreviated-home-dir
+ package--initialized
+ package-alist
+ ,@(if update-news
+ '(package-update-news-on-upload t)
+ (list (cl-gensym)))
+ ,@(if upload-base
+ '((package-test-archive-upload-base (make-temp-file "pkg-archive-base-" t))
+ (package-archive-upload-base package-test-archive-upload-base))
+ (list (cl-gensym)))) ;; Dummy value so `let' doesn't try to bind nil
+ (let ((buf (get-buffer "*Packages*")))
+ (when (buffer-live-p buf)
+ (kill-buffer buf)))
+ (unwind-protect
+ (progn
+ ,(if basedir `(cd ,basedir))
+ (unless (file-directory-p package-user-dir)
+ (mkdir package-user-dir))
+ (cl-letf (((symbol-function 'yes-or-no-p) (lambda (&rest _) t))
+ ((symbol-function 'y-or-n-p) (lambda (&rest _) t)))
+ ,@(when install
+ `((package-initialize)
+ (package-refresh-contents)
+ (mapc 'package-install ,install)))
+ (with-temp-buffer
+ ,(if file
+ `(insert-file-contents ,file))
+ ,@body)))
+
+ (when ,upload-base
+ (dolist (f '("archive-contents"
+ "simple-single-1.3.el"
+ "simple-single-1.4.el"
+ "simple-single-readme.txt"))
+ (ignore-errors
+ (delete-file
+ (expand-file-name f package-test-archive-upload-base))))
+ (delete-directory package-test-archive-upload-base))
+
+ (when (and (boundp 'package-test-archive-upload-base)
+ (file-directory-p package-test-archive-upload-base))
+ (delete-directory package-test-archive-upload-base t))))))
(defmacro with-fake-help-buffer (&rest body)
"Execute BODY in a temp buffer which is treated as the \"*Help*\" buffer."
+ (declare (debug body))
`(with-temp-buffer
(help-mode)
;; Trick `help-buffer' into using the temp buffer.
@@ -168,10 +178,9 @@
(replace-regexp-in-string "-pkg\\.el\\'" "" (package--description-file dir)))
(defun package-test-suffix-matches (base suffix-list)
- "Return file names matching BASE concatenated with each item in SUFFIX-LIST"
- (cl-mapcan
- '(lambda (item) (file-expand-wildcards (concat base item)))
- suffix-list))
+ "Return file names matching BASE concatenated with each item in SUFFIX-LIST."
+ (mapcan (lambda (item) (file-expand-wildcards (concat base item)))
+ suffix-list))
(defvar tar-parse-info)
(declare-function tar-header-name "tar-mode" (cl-x) t) ; defstruct
@@ -189,20 +198,41 @@ Must called from within a `tar-mode' buffer."
"Return the package version as a string."
(package-version-join (package-desc-version desc)))
+(defun package-test--compatible-p (pkg-desc pkg-sample &optional kind)
+ (and (cl-every (lambda (f)
+ (equal (funcall f pkg-desc)
+ (funcall f pkg-sample)))
+ (cons (if kind #'package-desc-kind #'ignore)
+ '(package-desc-name
+ package-desc-version
+ package-desc-summary
+ package-desc-reqs
+ package-desc-archive
+ package-desc-dir
+ package-desc-signed)))
+ ;; The `extras' field should contain at least the specified elements.
+ (let ((extras (package-desc-extras pkg-desc))
+ (extras-sample (package-desc-extras pkg-sample)))
+ (cl-every (lambda (sample-elem)
+ (member sample-elem extras))
+ extras-sample))))
+
(ert-deftest package-test-desc-from-buffer ()
"Parse an elisp buffer to get a `package-desc' object."
- (with-package-test (:basedir "package-resources" :file "simple-single-1.3.el")
- (should (equal (package-buffer-info) simple-single-desc)))
- (with-package-test (:basedir "package-resources" :file "simple-depend-1.0.el")
- (should (equal (package-buffer-info) simple-depend-desc)))
- (with-package-test (:basedir "package-resources"
+ (with-package-test (:basedir (ert-resource-directory) :file "simple-single-1.3.el")
+ (should (package-test--compatible-p
+ (package-buffer-info) simple-single-desc 'kind)))
+ (with-package-test (:basedir (ert-resource-directory) :file "simple-depend-1.0.el")
+ (should (package-test--compatible-p
+ (package-buffer-info) simple-depend-desc 'kind)))
+ (with-package-test (:basedir (ert-resource-directory)
:file "multi-file-0.2.3.tar")
(tar-mode)
(should (equal (package-tar-file-info) multi-file-desc))))
(ert-deftest package-test-install-single ()
"Install a single file without using an archive."
- (with-package-test (:basedir "package-resources" :file "simple-single-1.3.el")
+ (with-package-test (:basedir (ert-resource-directory) :file "simple-single-1.3.el")
(should (package-install-from-buffer))
(package-initialize)
(should (package-installed-p 'simple-single))
@@ -222,18 +252,83 @@ Must called from within a `tar-mode' buffer."
(with-temp-buffer
(insert-file-contents (expand-file-name "simple-single-pkg.el"
simple-pkg-dir))
- (should (string= (buffer-string)
- (concat ";;; -*- no-byte-compile: t -*-\n"
- "(define-package \"simple-single\" \"1.3\" "
- "\"A single-file package "
- "with no dependencies\" 'nil "
- ":authors '((\"J. R. Hacker\" . \"jrh@example.com\")) "
- ":maintainer '(\"J. R. Hacker\" . \"jrh@example.com\") "
- ":url \"http://doodles.au\""
- ")\n"))))
+ (goto-char (point-min))
+ (let ((sexp (read (current-buffer))))
+ (should (eq (car-safe sexp) 'define-package))
+ (should (package-test--compatible-p
+ (apply #'package-desc-from-define (cdr sexp))
+ simple-single-desc))))
(should (file-exists-p autoloads-file))
(should-not (get-file-buffer autoloads-file)))))
+(ert-deftest package-test-install-file ()
+ "Install files with `package-install-file'."
+ (with-package-test (:basedir (ert-resource-directory))
+ (package-initialize)
+ (let* ((pkg-el "simple-single-1.3.el")
+ (source-file (expand-file-name pkg-el (ert-resource-directory))))
+ (should-not (package-installed-p 'simple-single))
+ (package-install-file source-file)
+ (should (package-installed-p 'simple-single))
+ (package-delete (cadr (assq 'simple-single package-alist)))
+ (should-not (package-installed-p 'simple-single)))
+
+ (let* ((pkg-el "multi-file-0.2.3.tar")
+ (source-file (expand-file-name pkg-el (ert-resource-directory))))
+ (package-initialize)
+ (should-not (package-installed-p 'multie-file))
+ (package-install-file source-file)
+ (should (package-installed-p 'multi-file))
+ (package-delete (cadr (assq 'multi-file package-alist))))
+ ))
+
+(ert-deftest package-test-install-file-EOLs ()
+ "Install same file multiple time with `package-install-file'
+but with a different end of line convention (bug#48137)."
+ (with-package-test (:basedir (ert-resource-directory))
+ (package-initialize)
+ (let* ((pkg-el "simple-single-1.3.el")
+ (source-file (expand-file-name pkg-el (ert-resource-directory))))
+
+ (with-temp-buffer
+ (insert-file-contents source-file)
+
+ (let (hashes)
+ (dolist (coding '(unix dos mac) hashes)
+ (let* ((eol-file (expand-file-name pkg-el package-test-user-dir)))
+ ;; save package with this EOL convention.
+ (set-buffer-file-coding-system coding)
+ (write-region (point-min) (point-max) eol-file)
+
+ (should-not (package-installed-p 'simple-single))
+ (package-install-file eol-file)
+ (should (package-installed-p 'simple-single))
+
+ ;; check the package file has been installed unmodified.
+ (let ((eol-hash (with-temp-buffer
+ (insert-file-contents-literally eol-file)
+ (buffer-hash))))
+ ;; also perform an additional check that the package
+ ;; file created with this EOL convention is different
+ ;; than all the others created so far.
+ (should-not (member eol-hash hashes))
+ (setq hashes (cons eol-hash hashes))
+
+ (let* ((descr (cadr (assq 'simple-single package-alist)))
+ (pkg-dir (package-desc-dir descr))
+ (dest-file (expand-file-name "simple-single.el" pkg-dir ))
+ (dest-hash (with-temp-buffer
+ (insert-file-contents-literally dest-file)
+ (buffer-hash))))
+
+ (should (string= dest-hash eol-hash))))
+
+ (package-delete (cadr (assq 'simple-single package-alist)))
+ (should-not (package-installed-p 'simple-single))
+ (delete-file eol-file)
+ (should-not (file-exists-p eol-file))
+ )))))))
+
(ert-deftest package-test-install-dependency ()
"Install a package which includes a dependency."
(with-package-test ()
@@ -243,9 +338,16 @@ Must called from within a `tar-mode' buffer."
(should (package-installed-p 'simple-single))
(should (package-installed-p 'simple-depend))))
+(declare-function macro-problem-func "macro-problem" ())
+(declare-function macro-problem-10-and-90 "macro-problem" ())
+(declare-function macro-builtin-func "macro-builtin" ())
+(declare-function macro-builtin-10-and-90 "macro-builtin" ())
+
(ert-deftest package-test-macro-compilation ()
- "Install a package which includes a dependency."
- (with-package-test (:basedir "package-resources")
+ "\"Activation has to be done before compilation, so that if we're
+ upgrading and macros have changed we load the new definitions
+ before compiling.\" -- package.el"
+ (with-package-test (:basedir (ert-resource-directory))
(package-install-file (expand-file-name "macro-problem-package-1.0/"))
(require 'macro-problem)
;; `macro-problem-func' uses a macro from `macro-aux'.
@@ -257,6 +359,32 @@ Must called from within a `tar-mode' buffer."
;; `macro-problem-10-and-90' depends on an entirely new macro from `macro-aux'.
(should (equal (macro-problem-10-and-90) '(10 90)))))
+(ert-deftest package-test-macro-compilation-gz ()
+ "Built-in's can be superseded as well."
+ (with-package-test (:basedir (ert-resource-directory))
+ (let ((dir (expand-file-name "macro-builtin-package-1.0")))
+ (unwind-protect
+ (let ((load-path load-path))
+ (add-to-list 'load-path (directory-file-name dir))
+ (byte-recompile-directory dir 0 t)
+ (mapc (lambda (f) (call-process "gzip" nil nil nil f))
+ (directory-files-recursively dir "\\`[^\\.].*\\.el\\'"))
+ (require 'macro-builtin)
+ (should (member (expand-file-name "macro-builtin-aux.elc" dir)
+ (mapcar #'car load-history)))
+ ;; `macro-builtin-func' uses a macro from `macro-aux'.
+ (should (equal (macro-builtin-func) '(progn a b)))
+ (package-install-file (expand-file-name "macro-builtin-package-2.0/"))
+ ;; After upgrading, `macro-builtin-func' depends on a new version
+ ;; of the macro from `macro-builtin-aux'.
+ (should (equal (macro-builtin-func) '(1 b)))
+ ;; `macro-builtin-10-and-90' depends on an entirely new macro from `macro-aux'.
+ (should (equal (macro-builtin-10-and-90) '(10 90))))
+ (mapc #'delete-file
+ (directory-files-recursively dir "\\`[^\\.].*\\.elc\\'"))
+ (mapc (lambda (f) (call-process "gunzip" nil nil nil f))
+ (directory-files-recursively dir "\\`[^\\.].*\\.el\\.gz\\'"))))))
+
(ert-deftest package-test-install-two-dependencies ()
"Install a package which includes a dependency."
(with-package-test ()
@@ -284,8 +412,7 @@ Must called from within a `tar-mode' buffer."
(ert-deftest package-test-install-prioritized ()
"Install a lower version from a higher-prioritized archive."
(with-package-test ()
- (let* ((newer-version (expand-file-name "package-resources/newer-versions"
- package-test-file-dir))
+ (let* ((newer-version (ert-resource-file "newer-versions"))
(package-archives `(("older" . ,package-test-data-dir)
("newer" . ,newer-version)))
(package-archive-priorities '(("older" . 100))))
@@ -300,7 +427,7 @@ Must called from within a `tar-mode' buffer."
(ert-deftest package-test-install-multifile ()
"Check properties of the installed multi-file package."
- (with-package-test (:basedir "package-resources" :install '(multi-file))
+ (with-package-test (:basedir (ert-resource-directory) :install '(multi-file))
(let ((autoload-file
(expand-file-name "multi-file-autoloads.el"
(expand-file-name
@@ -325,35 +452,130 @@ Must called from within a `tar-mode' buffer."
(goto-char (point-min))
(should (re-search-forward re nil t)))))))
+
+;;; Package Menu tests
+
+(defmacro with-package-menu-test (&rest body)
+ "Set up Package Menu (\"*Packages*\") buffer for testing."
+ (declare (indent 0) (debug (([&rest form]) body)))
+ `(with-package-test ()
+ (let ((buf (package-list-packages)))
+ (unwind-protect
+ (progn ,@body)
+ (kill-buffer buf)))))
+
(ert-deftest package-test-update-listing ()
"Ensure installed package status is updated."
+ (with-package-menu-test
+ (search-forward-regexp "^ +simple-single")
+ (package-menu-mark-install)
+ (package-menu-execute)
+ (run-hooks 'post-command-hook)
+ (should (package-installed-p 'simple-single))
+ (switch-to-buffer "*Packages*")
+ (goto-char (point-min))
+ (should (re-search-forward "^\\s-+simple-single\\s-+1.3\\s-+installed" nil t))
+ (goto-char (point-min))
+ (should-not (re-search-forward "^\\s-+simple-single\\s-+1.3\\s-+\\(available\\|new\\)" nil t))))
+
+(ert-deftest package-test-list-filter-by-archive ()
+ "Ensure package list is filtered correctly by archive version."
+ (with-package-menu-test
+ ;; TODO: Add another package archive to test filtering, because
+ ;; the testing environment currently only has one.
+ (package-menu-filter-by-archive "gnu")
+ (goto-char (point-min))
+ (should (looking-at "^\\s-+multi-file"))
+ (should (= (count-lines (point-min) (point-max)) 4))
+ (should-error (package-menu-filter-by-archive "non-existent archive"))))
+
+(ert-deftest package-test-list-filter-by-keyword ()
+ "Ensure package list is filtered correctly by package keyword."
+ (with-package-menu-test
+ (package-menu-filter-by-keyword "frobnicate")
+ (goto-char (point-min))
+ (should (re-search-forward "^\\s-+simple-single" nil t))
+ (should (= (count-lines (point-min) (point-max)) 1))
+ (should-error (package-menu-filter-by-keyword "non-existent-keyword"))))
+
+(ert-deftest package-test-list-filter-by-name ()
+ "Ensure package list is filtered correctly by package name."
+ (with-package-menu-test ()
+ (package-menu-filter-by-name "ansi-color")
+ (goto-char (point-min))
+ (should (re-search-forward "^\\s-+ansi-color" nil t))
+ (should (= (count-lines (point-min) (point-max)) 1))))
+
+(ert-deftest package-test-list-filter-by-status ()
+ "Ensure package list is filtered correctly by package status."
+ (with-package-menu-test
+ (package-menu-filter-by-status "available")
+ (goto-char (point-min))
+ (should (re-search-forward "^\\s-+multi-file" nil t))
+ (should (= (count-lines (point-min) (point-max)) 4))
+ ;; No installed packages in default environment.
+ (should-error (package-menu-filter-by-status "installed"))))
+
+(ert-deftest package-test-list-filter-marked ()
+ "Ensure package list is filtered correctly by non-empty mark."
(with-package-test ()
- (let ((buf (package-list-packages)))
- (search-forward-regexp "^ +simple-single")
- (package-menu-mark-install)
- (package-menu-execute)
- (run-hooks 'post-command-hook)
- (should (package-installed-p 'simple-single))
- (switch-to-buffer "*Packages*")
- (goto-char (point-min))
- (should (re-search-forward "^\\s-+simple-single\\s-+1.3\\s-+installed" nil t))
- (goto-char (point-min))
- (should-not (re-search-forward "^\\s-+simple-single\\s-+1.3\\s-+\\(available\\|new\\)" nil t))
- (kill-buffer buf))))
+ (package-list-packages)
+ (revert-buffer)
+ (search-forward-regexp "^ +simple-single")
+ (package-menu-mark-install)
+ (package-menu-filter-marked)
+ (goto-char (point-min))
+ (should (re-search-forward "^I +simple-single" nil t))
+ (should (= (count-lines (point-min) (point-max)) 1))
+ (package-menu-mark-unmark)
+ ;; No marked packages in default environment.
+ (should-error (package-menu-filter-marked))))
+
+(ert-deftest package-test-list-filter-by-version ()
+ (with-package-menu-test
+ (should-error (package-menu-filter-by-version "1.1" 'unknown-symbol))) )
+
+(defun package-test-filter-by-version (version predicate name)
+ (with-package-menu-test
+ (package-menu-filter-by-version version predicate)
+ (goto-char (point-min))
+ ;; We just check that the given package is included in the
+ ;; listing. One could be more ambitious.
+ (should (re-search-forward name))))
+
+(ert-deftest package-test-list-filter-by-version-= ()
+ "Ensure package list is filtered correctly by package version (=)."
+ (package-test-filter-by-version "1.1" '= "^\\s-+simple-two-depend"))
+
+(ert-deftest package-test-list-filter-by-version-< ()
+ "Ensure package list is filtered correctly by package version (<)."
+ (package-test-filter-by-version "1.2" '< "^\\s-+simple-two-depend"))
+
+(ert-deftest package-test-list-filter-by-version-> ()
+ "Ensure package list is filtered correctly by package version (>)."
+ (package-test-filter-by-version "1.0" '> "^\\s-+simple-two-depend"))
+
+(ert-deftest package-test-list-clear-filter ()
+ "Ensure package list filter is cleared correctly."
+ (with-package-menu-test
+ (let ((num-packages (count-lines (point-min) (point-max))))
+ (package-menu-filter-by-name "ansi-color")
+ (should (= (count-lines (point-min) (point-max)) 1))
+ (package-menu-clear-filter)
+ (should (= (count-lines (point-min) (point-max)) num-packages)))))
(ert-deftest package-test-update-archives ()
"Test updating package archives."
(with-package-test ()
- (let ((buf (package-list-packages)))
- (package-menu-refresh)
+ (let ((_buf (package-list-packages)))
+ (revert-buffer)
(search-forward-regexp "^ +simple-single")
(package-menu-mark-install)
(package-menu-execute)
(should (package-installed-p 'simple-single))
- (let ((package-test-data-dir
- (expand-file-name "package-resources/newer-versions" package-test-file-dir)))
+ (let ((package-test-data-dir (ert-resource-file "newer-versions")))
(setq package-archives `(("gnu" . ,package-test-data-dir)))
- (package-menu-refresh)
+ (revert-buffer)
;; New version should be available and old version should be installed
(goto-char (point-min))
@@ -365,11 +587,12 @@ Must called from within a `tar-mode' buffer."
(package-menu-mark-upgrades)
(package-menu-execute)
- (package-menu-refresh)
+ (revert-buffer)
(should (package-installed-p 'simple-single '(1 4)))))))
(ert-deftest package-test-update-archives-async ()
"Test updating package archives asynchronously."
+ :tags '(:expensive-test)
(skip-unless (executable-find "python2"))
(let* ((package-menu-async t)
(default-directory package-test-data-dir)
@@ -389,7 +612,7 @@ Must called from within a `tar-mode' buffer."
(when (re-search-forward "Server started, \\(.*\\)\n" nil t)
(setq addr (match-string 1))))
addr)))
- (with-package-test (:basedir package-test-data-dir :location addr)
+ (with-package-test (:basedir (ert-resource-directory) :location addr)
(list-packages)
(should package--downloads-in-progress)
(should mode-line-process)
@@ -406,6 +629,30 @@ Must called from within a `tar-mode' buffer."
(search-forward-regexp "^ +simple-single" nil t))))
(if (process-live-p process) (kill-process process)))))
+(ert-deftest package-test-update-archives/ignore-nil-entry ()
+ "Ignore any packages that are nil. Test for Bug#28502."
+ (with-package-test ()
+ (let* ((with-nil-entry (ert-resource-file "with-nil-entry"))
+ (package-archives `(("with-nil-entry" . ,with-nil-entry))))
+ (package-initialize)
+ (package-refresh-contents)
+ (should (equal (length package-archive-contents) 2)))))
+
+(ert-deftest package-test-package-installed-p ()
+ "Test package-installed-p before and after package initialization."
+ (with-package-test ()
+ ;; Verify that `package-installed-p' evaluates true for a built-in
+ ;; package, in this case `project', before package initialization.
+ (should (not package--initialized))
+ (should (package-installed-p 'project nil))
+ (should (not (package-installed-p 'imaginary-package nil)))
+
+ ;; The results don't change after package initialization.
+ (package-initialize)
+ (should package--initialized)
+ (should (package-installed-p 'project nil))
+ (should (not (package-installed-p 'imaginary-package nil)))))
+
(ert-deftest package-test-describe-package ()
"Test displaying help for a package."
@@ -414,7 +661,7 @@ Must called from within a `tar-mode' buffer."
(with-fake-help-buffer
(describe-package '5x5)
(goto-char (point-min))
- (should (search-forward "5x5 is a built-in package." nil t))
+ (should (search-forward "5x5 is built-in." nil t))
;; Don't assume the descriptions are in any particular order.
(save-excursion (should (search-forward "Status: Built-in." nil t)))
(save-excursion (should (search-forward "Summary: simple little puzzle game" nil t)))
@@ -428,17 +675,30 @@ Must called from within a `tar-mode' buffer."
(with-fake-help-buffer
(describe-package 'simple-single)
(goto-char (point-min))
- (should (search-forward "simple-single is an installed package." nil t))
+ (should (search-forward "Package simple-single is installed." nil t))
(save-excursion (should (re-search-forward "Status: Installed in ['`‘]simple-single-1.3/['’] (unsigned)." nil t)))
(save-excursion (should (search-forward "Version: 1.3" nil t)))
(save-excursion (should (search-forward "Summary: A single-file package with no dependencies" nil t)))
- (save-excursion (should (search-forward "Homepage: http://doodles.au" nil t)))
+ (save-excursion (should (search-forward "Website: http://doodles.au" nil t)))
(save-excursion (should (re-search-forward "Keywords: \\[?frobnicate\\]?" nil t)))
- ;; No description, though. Because at this point we don't know
- ;; what archive the package originated from, and we don't have
- ;; its readme file saved.
+ (save-excursion (should (search-forward "This package provides a minor mode to frobnicate"
+ nil t)))
)))
+(ert-deftest package-test-describe-installed-multi-file-package ()
+ "Test displaying of the readme for installed multi-file package."
+
+ (with-package-test ()
+ (package-initialize)
+ (package-refresh-contents)
+ (package-install 'multi-file)
+ (with-fake-help-buffer
+ (describe-package 'multi-file)
+ (goto-char (point-min))
+ (should (search-forward "Website: http://puddles.li" nil t))
+ (should (search-forward "This is a bare-bones readme file for the multi-file"
+ nil t)))))
+
(ert-deftest package-test-describe-non-installed-package ()
"Test displaying of the readme for non-installed package."
@@ -448,7 +708,7 @@ Must called from within a `tar-mode' buffer."
(with-fake-help-buffer
(describe-package 'simple-single)
(goto-char (point-min))
- (should (search-forward "Homepage: http://doodles.au" nil t))
+ (should (search-forward "Website: http://doodles.au" nil t))
(should (search-forward "This package provides a minor mode to frobnicate"
nil t)))))
@@ -461,40 +721,50 @@ Must called from within a `tar-mode' buffer."
(with-fake-help-buffer
(describe-package 'multi-file)
(goto-char (point-min))
- (should (search-forward "Homepage: http://puddles.li" nil t))
+ (should (search-forward "Website: http://puddles.li" nil t))
(should (search-forward "This is a bare-bones readme file for the multi-file"
nil t)))))
+(defvar epg-config--program-alist) ; Silence byte-compiler.
(ert-deftest package-test-signed ()
"Test verifying package signature."
- (skip-unless (ignore-errors
- (let ((homedir (make-temp-file "package-test" t)))
- (unwind-protect
- (let ((process-environment
- (cons (format "HOME=%s" homedir)
- process-environment)))
- (epg-check-configuration (epg-configuration))
- (epg-find-configuration 'OpenPGP))
- (delete-directory homedir t)))))
+ (skip-unless (ert-with-temp-directory homedir
+ (let ((process-environment
+ (cons (concat "HOME=" homedir)
+ process-environment)))
+ (require 'epg-config)
+ (defvar epg-config--program-alist)
+ (epg-find-configuration
+ 'OpenPGP nil
+ ;; By default we require gpg2 2.1+ due to some
+ ;; practical problems with pinentry. But this
+ ;; test works fine with 2.0 as well.
+ (let ((prog-alist (copy-tree epg-config--program-alist)))
+ (setf (alist-get "gpg2"
+ (alist-get 'OpenPGP prog-alist)
+ nil nil #'equal)
+ "2.0")
+ prog-alist)))))
(let* ((keyring (expand-file-name "key.pub" package-test-data-dir))
- (package-test-data-dir
- (expand-file-name "package-resources/signed" package-test-file-dir)))
+ (package-test-data-dir (ert-resource-file "signed")))
(with-package-test ()
(package-initialize)
(package-import-keyring keyring)
(package-refresh-contents)
(let ((package-check-signature 'allow-unsigned))
- (should (package-install 'signed-good))
+ (should (progn (package-install 'signed-good) 'noerror))
(should-error (package-install 'signed-bad)))
+ (package-delete (car (alist-get 'signed-good package-alist)))
(let ((package-check-signature t))
- (should (package-install 'signed-good))
+ (should (progn (package-install 'signed-good) 'noerror))
(should-error (package-install 'signed-bad)))
+ (package-delete (car (alist-get 'signed-good package-alist)))
(let ((package-check-signature nil))
- (should (package-install 'signed-good))
- (should (package-install 'signed-bad)))
+ (should (progn (package-install 'signed-good) 'noerror))
+ (should (progn (package-install 'signed-bad) 'noerror)))
;; Check if the installed package status is updated.
- (let ((buf (package-list-packages)))
- (package-menu-refresh)
+ (let ((_buf (package-list-packages)))
+ (revert-buffer)
(should (re-search-forward
"^\\s-+signed-good\\s-+\\(\\S-+\\)\\s-+\\(\\S-+\\)\\s-"
nil t))
@@ -504,7 +774,7 @@ Must called from within a `tar-mode' buffer."
(with-fake-help-buffer
(describe-package 'signed-good)
(goto-char (point-min))
- (should (re-search-forward "signed-good is an? \\(\\S-+\\) package." nil t))
+ (should (re-search-forward "Package signed-good is \\(\\S-+\\)\\." nil t))
(should (string-equal (match-string-no-properties 1) "installed"))
(should (re-search-forward
"Status: Installed in ['`‘]signed-good-1.0/['’]."
@@ -537,7 +807,7 @@ Must called from within a `tar-mode' buffer."
(ert-deftest package-x-test-upload-buffer ()
"Test creating an \"archive-contents\" file"
- (with-package-test (:basedir "package-resources"
+ (with-package-test (:basedir (ert-resource-directory)
:file "simple-single-1.3.el"
:upload-base t)
(package-upload-buffer)
@@ -556,12 +826,21 @@ Must called from within a `tar-mode' buffer."
(setq archive-contents
(package-read-from-string
(buffer-substring (point-min) (point-max)))))
- (should (equal archive-contents
- (list 1 package-x-test--single-archive-entry-1-3))))))
+ (should (equal 1 (car archive-contents)))
+ (should (equal 2 (length archive-contents)))
+ (let ((pac (cadr archive-contents))
+ (pac-sample package-x-test--single-archive-entry-1-3))
+ (should (equal (pop pac) (pop pac-sample)))
+ (dotimes (i 4)
+ (should (equal (aref pac i) (aref pac-sample i))))
+ ;; The `extras' field should contain at least the specified elements.
+ (should (cl-every (lambda (sample-elem)
+ (member sample-elem (aref pac 4)))
+ (aref pac-sample 4)))))))
(ert-deftest package-x-test-upload-new-version ()
"Test uploading a new version of a package"
- (with-package-test (:basedir "package-resources"
+ (with-package-test (:basedir (ert-resource-directory)
:file "simple-single-1.3.el"
:upload-base t)
(package-upload-buffer)
@@ -577,8 +856,17 @@ Must called from within a `tar-mode' buffer."
(setq archive-contents
(package-read-from-string
(buffer-substring (point-min) (point-max)))))
- (should (equal archive-contents
- (list 1 package-x-test--single-archive-entry-1-4))))))
+ (should (equal 1 (car archive-contents)))
+ (should (equal 2 (length archive-contents)))
+ (let ((pac (cadr archive-contents))
+ (pac-sample package-x-test--single-archive-entry-1-4))
+ (should (equal (pop pac) (pop pac-sample)))
+ (dotimes (i 4)
+ (should (equal (aref pac i) (aref pac-sample i))))
+ ;; The `extras' field should contain at least the specified elements.
+ (should (cl-every (lambda (sample-elem)
+ (member sample-elem (aref pac 4)))
+ (aref pac-sample 4)))))))
(ert-deftest package-test-get-deps ()
"Test `package--get-deps' with complex structures."
@@ -589,25 +877,16 @@ Must called from within a `tar-mode' buffer."
multi-file-desc
new-pkg-desc
simple-depend-desc-1
- simple-depend-desc-2))))
- (should
- (equal (package--get-deps 'simple-depend)
- '(simple-single)))
- (should
- (equal (package--get-deps 'simple-depend 'indirect)
- nil))
- (should
- (equal (package--get-deps 'simple-depend 'direct)
- '(simple-single)))
- (should
- (equal (package--get-deps 'simple-depend-2)
- '(simple-depend-1 multi-file simple-depend simple-single)))
+ simple-depend-desc-2)))
+ (pkg-cmp #'string-lessp))
(should
- (equal (package--get-deps 'simple-depend-2 'indirect)
- '(simple-depend multi-file simple-single)))
+ (equal (sort (package--get-deps '(simple-depend)) pkg-cmp)
+ (sort (list 'simple-depend 'simple-single) pkg-cmp)))
(should
- (equal (package--get-deps 'simple-depend-2 'direct)
- '(simple-depend-1 multi-file)))))
+ (equal (sort (package--get-deps '(simple-depend-2)) pkg-cmp)
+ (sort (list 'simple-depend-2 'simple-depend-1 'multi-file
+ 'simple-depend 'simple-single)
+ pkg-cmp)))))
(ert-deftest package-test-sort-by-dependence ()
"Test `package--sort-by-dependence' with complex structures."
@@ -638,4 +917,4 @@ Must called from within a `tar-mode' buffer."
(provide 'package-test)
-;;; package-test.el ends here
+;;; package-tests.el ends here
diff --git a/test/lisp/emacs-lisp/pcase-tests.el b/test/lisp/emacs-lisp/pcase-tests.el
index 3bd14ed4b42..80607990808 100644
--- a/test/lisp/emacs-lisp/pcase-tests.el
+++ b/test/lisp/emacs-lisp/pcase-tests.el
@@ -1,6 +1,6 @@
-;;; pcase-tests.el --- Test suite for pcase macro.
+;;; pcase-tests.el --- Test suite for pcase macro. -*- lexical-binding:t -*-
-;; Copyright (C) 2012-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2022 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -32,6 +32,10 @@
(should (equal (pcase '(2 . 3) ;bug#18554
(`(,hd . ,(and (pred atom) tl)) (list hd tl))
((pred consp) nil))
+ '(2 3)))
+ (should (equal (pcase '(2 . 3)
+ (`(,hd . ,(and (pred (not consp)) tl)) (list hd tl))
+ ((pred consp) nil))
'(2 3))))
(pcase-defmacro pcase-tests-plus (pat n)
@@ -51,11 +55,15 @@
(ert-deftest pcase-tests-member ()
(should (pcase-tests-grep
- 'memq (macroexpand-all '(pcase x ((or 1 2 3) body)))))
+ 'memq (macroexpand-all '(pcase x ((or 'a 'b 'c) body)))))
+ (should (pcase-tests-grep
+ 'memql (macroexpand-all '(pcase x ((or 1 2 3 'a) body)))))
(should (pcase-tests-grep
- 'member (macroexpand-all '(pcase x ((or '"a" '2 '3) body)))))
+ 'member (macroexpand-all '(pcase x ((or "a" 2 3 'a) body)))))
(should-not (pcase-tests-grep
'memq (macroexpand-all '(pcase x ((or "a" 2 3) body)))))
+ (should-not (pcase-tests-grep
+ 'memql (macroexpand-all '(pcase x ((or "a" 2 3) body)))))
(let ((exp (macroexpand-all
'(pcase x
("a" body1)
@@ -67,8 +75,89 @@
(ert-deftest pcase-tests-vectors ()
(should (equal (pcase [1 2] (`[,x] 1) (`[,x ,y] (+ x y))) 3)))
-;; Local Variables:
-;; no-byte-compile: t
-;; End:
+(ert-deftest pcase-tests-bug14773 ()
+ (let ((f (lambda (x)
+ (pcase 'dummy
+ ((and (let var x) (guard var)) 'left)
+ ((and (let var (not x)) (guard var)) 'right)))))
+ (should (equal (funcall f t) 'left))
+ (should (equal (funcall f nil) 'right))))
+
+(ert-deftest pcase-tests-bug46786 ()
+ (let ((self 'outer))
+ (ignore self)
+ (should (equal (cl-macrolet ((show-self () `(list 'self self)))
+ (pcase-let ((`(,self ,_self2) '(inner "2")))
+ (show-self)))
+ '(self inner)))))
+
+(ert-deftest pcase-tests-or-vars ()
+ (let ((f (lambda (v)
+ (pcase v
+ ((or (and 'b1 (let x1 4) (let x2 5))
+ (and 'b2 (let y1 8) (let y2 9)))
+ (list x1 x2 y1 y2))))))
+ (should (equal (funcall f 'b1) '(4 5 nil nil)))
+ (should (equal (funcall f 'b2) '(nil nil 8 9)))))
+
+(ert-deftest pcase-tests-cl-type ()
+ (should (equal (pcase 1
+ ((cl-type integer) 'integer))
+ 'integer))
+ (should (equal (pcase 1
+ ((cl-type (integer 0 2)) 'integer-0<=n<=2))
+ 'integer-0<=n<=2))
+ (should-error
+ ;; Avoid error at compile time due to compiler macro.
+ (eval '(pcase 1
+ ((cl-type notatype) 'integer))
+ t)))
+
+(ert-deftest pcase-tests-setq ()
+ (should (equal (let (a b)
+ (pcase-setq `((,a) (,b)) '((1) (2)))
+ (list a b))
+ (list 1 2)))
+
+ (should (equal (list nil nil)
+ (let ((a 'unset)
+ (b 'unset))
+ (pcase-setq `(head ,a ,b) nil)
+ (list a b))))
+
+ (should (equal (let (a b)
+ (pcase-setq `[,a ,b] [1 2])
+ (list a b))
+ '(1 2)))
+
+ (should-error (let (a b)
+ (pcase-setq `[,a ,b] nil)
+ (list a b)))
+
+ (should (equal (let (a b)
+ (pcase-setq a 1 b 2)
+ (list a b))
+ '(1 2)))
+
+ (should (= (let (a)
+ (pcase-setq a 1 `(,a) '(2))
+ a)
+ 2))
+
+ (should (equal (let (array list-item array-copy)
+ (pcase-setq (or `(,list-item) array) [1 2 3]
+ array-copy array
+ ;; This re-sets `array' to nil.
+ (or `(,list-item) array) '(4))
+ (list array array-copy list-item))
+ '(nil [1 2 3] 4)))
+
+ (let ((a nil))
+ (should-error (pcase-setq a 1 b)
+ :type '(wrong-number-of-arguments))
+ (should (eq a nil)))
+
+ (should-error (pcase-setq a)
+ :type '(wrong-number-of-arguments)))
;;; pcase-tests.el ends here.
diff --git a/test/lisp/emacs-lisp/pp-resources/code-formats.erts b/test/lisp/emacs-lisp/pp-resources/code-formats.erts
new file mode 100644
index 00000000000..c3e3023cb19
--- /dev/null
+++ b/test/lisp/emacs-lisp/pp-resources/code-formats.erts
@@ -0,0 +1,142 @@
+Code:
+ (lambda ()
+ (emacs-lisp-mode)
+ (let ((code (read (current-buffer))))
+ (erase-buffer)
+ (pp-emacs-lisp-code code)
+ (untabify (point-min) (point-max))))
+
+Name: code-formats1
+
+=-=
+(defun foo (bar)
+ "Yes."
+ (let ((a 1)
+ (b 2))
+ (zot 1 2 (funcall bar 2))))
+=-=-=
+
+
+Name: code-formats2
+
+=-=
+(defun pp-emacs-lisp-code (sexp)
+ "Insert SEXP into the current buffer, formatted as Emacs Lisp code."
+ (require 'edebug)
+ (let ((start (point))
+ (standard-output (current-buffer)))
+ (pp--insert-lisp sexp)
+ (insert "\n")
+ (goto-char start)
+ (indent-sexp)))
+=-=-=
+
+
+Name: code-formats3
+
+=-=
+(defun foo (bar)
+ "Yes."
+ (let ((a 1)
+ (b 2))
+ (zot-zot-zot-zot-zot-zot 1 2 (funcall
+ bar-bar-bar-bar-bar-bar-bar-bar-bar-bar
+ 2))))
+=-=-=
+
+
+Name: code-formats4
+
+=-=
+(defun foo (bar)
+ "Yes."
+ (let ((a 1)
+ (b 2)
+ foo bar zotfoo bar zotfoo bar zotfoo bar zotfoo bar zotfoo bar zotfoo
+ bar zot)
+ (zot 1 2 (funcall bar 2))))
+=-=-=
+
+
+Name: code-formats5
+
+=-=
+(defgroup pp ()
+ "Pretty printer for Emacs Lisp."
+ :prefix "pp-"
+ :group 'lisp)
+=-=-=
+
+Name: code-formats6
+
+=-=
+(defcustom pp-escape-newlines t
+ "Value of `print-escape-newlines' used by pp-* functions."
+ :type 'boolean
+ :group 'pp)
+=-=-=
+
+Name: code-formats7
+
+=-=
+(defun pp (object &optional stream)
+ (princ (pp-to-string object) (or stream standard-output)))
+=-=-=
+
+
+Name: code-formats8
+
+=-=
+(defun pp-eval-expression (expression)
+ "Evaluate EXPRESSION and pretty-print its value.
+Also add the value to the front of the list in the variable `values'."
+ (interactive (list (read--expression "Eval: ")))
+ (message "Evaluating...")
+ (let ((result (eval expression lexical-binding)))
+ (values--store-value result)
+ (pp-display-expression result "*Pp Eval Output*")))
+=-=-=
+
+Name: code-formats9
+
+=-=
+(lambda ()
+ (interactive)
+ 1)
+=-=-=
+
+
+Name: code-formats10
+
+=-=
+(funcall foo (concat "zot" (if (length> site 0) site
+ "bar")
+ "+"
+ (string-replace " " "+" query)))
+=-=-=
+
+
+Name: code-formats11
+
+=-=
+(lambda ()
+ [(foo bar) (foo bar)])
+=-=-=
+
+Name: code-formats12
+
+=-=
+(global-set-key (kbd "s-x") #'kill-region)
+=-=-=
+
+Name: code-formats13
+
+=-=
+'("a")
+=-=-=
+
+Name: code-formats14
+
+=-=
+'("a" . "b")
+=-=-=
diff --git a/test/lisp/emacs-lisp/pp-tests.el b/test/lisp/emacs-lisp/pp-tests.el
index aed2d3770fb..01ac572c537 100644
--- a/test/lisp/emacs-lisp/pp-tests.el
+++ b/test/lisp/emacs-lisp/pp-tests.el
@@ -1,6 +1,6 @@
;;; pp-tests.el --- Test suite for pretty printer. -*- lexical-binding: t -*-
-;; Copyright (C) 2017 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2022 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -20,6 +20,7 @@
;;; Code:
(require 'pp)
+(require 'ert-x)
(ert-deftest pp-print-quote ()
(should (string= (pp-to-string 'quote) "quote"))
@@ -32,4 +33,7 @@
(should (string= (pp-to-string '(quotefoo)) "(quotefoo)\n"))
(should (string= (pp-to-string '(a b)) "(a b)\n")))
+(ert-deftest test-indentation ()
+ (ert-test-erts-file (ert-resource-file "code-formats.erts")))
+
;;; pp-tests.el ends here.
diff --git a/test/lisp/emacs-lisp/range-tests.el b/test/lisp/emacs-lisp/range-tests.el
new file mode 100644
index 00000000000..660110aa1fb
--- /dev/null
+++ b/test/lisp/emacs-lisp/range-tests.el
@@ -0,0 +1,65 @@
+;;; range-tests.el --- Tests for range.el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;
+
+;;; Code:
+
+(require 'range)
+(require 'ert)
+(require 'ert-x)
+
+(ert-deftest ranges ()
+ (should (equal (range-compress-list '(2 3 4 5 9 11 12 13))
+ '((2 . 5) 9 (11 . 13))))
+ (should (equal (range-uncompress '((2 . 5) 9 (11 . 13)))
+ '(2 3 4 5 9 11 12 13)))
+ (should (equal (range-normalize '(1 . 2))
+ '((1 . 2))))
+ (should (equal (range-difference '((1 . 10))
+ '((2 . 7)))
+ '(1 (8 . 10))))
+ (should (equal (range-intersection '((2 . 5) 9 (11 . 13))
+ '((5 . 12)))
+ '(5 9 (11 . 12))))
+ (should (equal (range-add-list '((2 . 5) 9 (11 . 13))
+ '(10 11 12 15 16 17))
+ '((2 . 5) (9 . 10) (11 . 13) (15 . 17))))
+ (should (equal (range-remove (copy-tree '((2 . 5) 9 (11 . 13)))
+ '((5 . 9)))
+ '((2 . 4) (11 . 13))))
+ (should (range-member-p 9 '((2 . 5) 9 (11 . 13))))
+ (should (range-member-p 12 '((2 . 5) 9 (11 . 13))))
+ (should (equal (range-list-intersection
+ '(4 5 6 7 8 9)
+ '((2 . 5) 9 (11 . 13)))
+ '(4 5 9)))
+ (should (equal (range-list-difference
+ '(4 5 6 7 8 9)
+ '((2 . 5) 9 (11 . 13)))
+ '(6 7 8)))
+ (should (equal (range-length '((2 . 5) 9 (11 . 13)))
+ 8))
+ (should (equal (range-concat '((2 . 5) 9 (11 . 13))
+ '(6 (12 . 15)))
+ '((2 . 6) 9 (11 . 15)))))
+
+;;; range-tests.el ends here
diff --git a/test/lisp/emacs-lisp/regexp-opt-tests.el b/test/lisp/emacs-lisp/regexp-opt-tests.el
index 4beb7bfa1ca..46ed7c29b28 100644
--- a/test/lisp/emacs-lisp/regexp-opt-tests.el
+++ b/test/lisp/emacs-lisp/regexp-opt-tests.el
@@ -1,6 +1,6 @@
-;;; regexp-tests.el --- Test suite for regular expression handling.
+;;; regexp-opt-tests.el --- Tests for regexp-opt.el -*- lexical-binding: t -*-
-;; Copyright (C) 2013-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2022 Free Software Foundation, Inc.
;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
;; Keywords: internal
@@ -25,9 +25,45 @@
(require 'regexp-opt)
-(ert-deftest regexp-test-regexp-opt ()
- "Test the `compilation-error-regexp-alist' regexps.
-The test data is in `compile-tests--test-regexps-data'."
- (should (string-match (regexp-opt-charset '(?^)) "a^b")))
+(defun regexp-opt-test--permutations (l)
+ "All permutations of L, assuming no duplicates."
+ (if (cdr l)
+ (mapcan (lambda (x)
+ (mapcar (lambda (p) (cons x p))
+ (regexp-opt-test--permutations (remove x l))))
+ l)
+ (list l)))
-;;; regexp-tests.el ends here.
+(ert-deftest regexp-opt-longest-match ()
+ "Check that the regexp always matches as much as possible."
+ (let ((s "abcd"))
+ (dolist (perm (regexp-opt-test--permutations '("a" "ab" "ac" "abc")))
+ (should (equal (and (string-match (regexp-opt perm) s)
+ (match-string 0 s))
+ "abc")))))
+
+(ert-deftest regexp-opt-charset ()
+ (should (equal (regexp-opt-charset '(?a ?b ?a)) "[ab]"))
+ (should (equal (regexp-opt-charset '(?D ?d ?B ?a ?b ?C ?7 ?a ?c ?A))
+ "[7A-Da-d]"))
+ (should (equal (regexp-opt-charset '(?a)) "a"))
+
+ (should (equal (regexp-opt-charset '(?^)) "\\^"))
+ (should (equal (regexp-opt-charset '(?-)) "-"))
+ (should (equal (regexp-opt-charset '(?\])) "]"))
+ (should (equal (regexp-opt-charset '(?^ ?\])) "[]^]"))
+ (should (equal (regexp-opt-charset '(?^ ?-)) "[-^]"))
+ (should (equal (regexp-opt-charset '(?- ?\])) "[]-]"))
+ (should (equal (regexp-opt-charset '(?- ?\] ?^)) "[]^-]"))
+
+ (should (equal (regexp-opt-charset '(?^ ?a)) "[a^]"))
+ (should (equal (regexp-opt-charset '(?- ?a)) "[a-]"))
+ (should (equal (regexp-opt-charset '(?\] ?a)) "[]a]"))
+ (should (equal (regexp-opt-charset '(?^ ?\] ?a)) "[]a^]"))
+ (should (equal (regexp-opt-charset '(?^ ?- ?a)) "[a^-]"))
+ (should (equal (regexp-opt-charset '(?- ?\] ?a)) "[]a-]"))
+ (should (equal (regexp-opt-charset '(?- ?\] ?^ ?a)) "[]a^-]"))
+
+ (should (equal (regexp-opt-charset '()) regexp-unmatchable)))
+
+;;; regexp-opt-tests.el ends here
diff --git a/test/lisp/emacs-lisp/ring-tests.el b/test/lisp/emacs-lisp/ring-tests.el
index 00bcf8401c4..6bbcd94f201 100644
--- a/test/lisp/emacs-lisp/ring-tests.el
+++ b/test/lisp/emacs-lisp/ring-tests.el
@@ -1,6 +1,6 @@
;;; ring-tests.el --- Tests for ring.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2016-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2022 Free Software Foundation, Inc.
;; Author: Simen Heggestøyl <simenheg@gmail.com>
;; Keywords:
@@ -162,7 +162,44 @@
(should (= (ring-size ring) 5))
(should (equal (ring-elements ring) '(3 2 1)))))
-(ert-deftest ring-tests-insert ()
+(ert-deftest ring-resize/grow ()
+ (let ((ring (make-ring 3)))
+ (ring-insert ring 1)
+ (ring-insert ring 2)
+ (ring-insert ring 3)
+ (ring-resize ring 5)
+ (should (= (ring-size ring) 5))
+ (should (equal (ring-elements ring) '(3 2 1)))))
+
+(ert-deftest ring-resize/grow-empty ()
+ (let ((ring (make-ring 3)))
+ (ring-resize ring 5)
+ (should (= (ring-size ring) 5))
+ (should (equal (ring-elements ring) '()))))
+
+(ert-deftest ring-resize/grow-wrapped-ring ()
+ (let ((ring (make-ring 3)))
+ (ring-insert ring 1)
+ (ring-insert ring 2)
+ (ring-insert ring 3)
+ (ring-insert ring 4)
+ (ring-insert ring 5)
+ (ring-resize ring 5)
+ (should (= (ring-size ring) 5))
+ (should (equal (ring-elements ring) '(5 4 3)))))
+
+(ert-deftest ring-resize/shrink ()
+ (let ((ring (make-ring 5)))
+ (ring-insert ring 1)
+ (ring-insert ring 2)
+ (ring-insert ring 3)
+ (ring-insert ring 4)
+ (ring-insert ring 5)
+ (ring-resize ring 3)
+ (should (= (ring-size ring) 3))
+ (should (equal (ring-elements ring) '(5 4 3)))))
+
+(ert-deftest ring-tests-insert-2 ()
(let ((ring (make-ring 2)))
(ring-insert+extend ring :a)
(ring-insert+extend ring :b)
diff --git a/test/lisp/emacs-lisp/rmc-tests.el b/test/lisp/emacs-lisp/rmc-tests.el
new file mode 100644
index 00000000000..385b0fe44a5
--- /dev/null
+++ b/test/lisp/emacs-lisp/rmc-tests.el
@@ -0,0 +1,91 @@
+;;; rmc-tests.el --- Test suite for rmc.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2017-2022 Free Software Foundation, Inc.
+
+;; Author: Tino Calancha <tino.calancha@gmail.com>
+;; Keywords:
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'rmc)
+(require 'cl-lib)
+(eval-when-compile (require 'cl-lib))
+
+(ert-deftest test-rmc--add-key-description ()
+ (cl-letf (((symbol-function 'display-supports-face-attributes-p) (lambda (_ _) t)))
+ (should (equal (rmc--add-key-description '(?y "yes"))
+ '(?y . "yes")))
+ (should (equal (rmc--add-key-description '(?n "foo"))
+ '(?n . "n foo")))
+ (should (equal (rmc--add-key-description '(?\s "foo bar"))
+ `(?\s . "SPC foo bar")))))
+
+(ert-deftest test-rmc--add-key-description/with-attributes ()
+ (cl-letf (((symbol-function 'display-supports-face-attributes-p) (lambda (_ _) t)))
+ (should (equal-including-properties
+ (rmc--add-key-description '(?y "yes"))
+ `(?y . ,(concat (propertize "y" 'face 'read-multiple-choice-face) "es"))))
+ (should (equal-including-properties
+ (rmc--add-key-description '(?n "foo"))
+ `(?n . ,(concat (propertize "n" 'face 'read-multiple-choice-face) " foo"))))
+ (should (equal-including-properties
+ (rmc--add-key-description '(?\s "foo bar"))
+ `(?\s . ,(concat (propertize "SPC" 'face 'read-multiple-choice-face) " foo bar"))))))
+
+(ert-deftest test-rmc--add-key-description/non-graphical-display ()
+ (cl-letf (((symbol-function 'display-supports-face-attributes-p) (lambda (_ _) nil)))
+ (should (equal-including-properties
+ (rmc--add-key-description '(?y "yes"))
+ '(?y . "[Y]es")))
+ (should (equal-including-properties
+ (rmc--add-key-description '(?n "foo"))
+ `(?n . ,(concat (propertize "n" 'face 'help-key-binding) " foo"))))))
+
+(ert-deftest test-read-multiple-choice ()
+ (dolist (char '(?y ?n))
+ (cl-letf* (((symbol-function #'read-event) (lambda () char))
+ (str (if (eq char ?y) "yes" "no")))
+ (should (equal (list char str)
+ (read-multiple-choice "Do it? " '((?y "yes") (?n "no"))))))))
+
+(ert-deftest test-read-multiple-choice-help ()
+ (let ((chars '(?o ?a))
+ help)
+ (cl-letf* (((symbol-function #'read-event)
+ (lambda ()
+ (message "chars %S" chars)
+ (when (= 1 (length chars))
+ (with-current-buffer "*Multiple Choice Help*"
+ (setq help (buffer-string))))
+ (pop chars))))
+ (read-multiple-choice
+ "Choose:"
+ '((?a "aaa")
+ (?b "bbb")
+ (?c "ccc" "a really long description of ccc")))
+ (should (equal help "Choose:
+
+a: [A]aa b: [B]bb c: [C]cc
+ a really long
+ description of ccc
+ \n")))))
+
+;;; rmc-tests.el ends here
diff --git a/test/lisp/emacs-lisp/rx-tests.el b/test/lisp/emacs-lisp/rx-tests.el
index d9ebb769613..125ddee8595 100644
--- a/test/lisp/emacs-lisp/rx-tests.el
+++ b/test/lisp/emacs-lisp/rx-tests.el
@@ -1,6 +1,6 @@
-;;; rx-tests.el --- test for rx.el functions -*- lexical-binding: t -*-
+;;; rx-tests.el --- tests for rx.el -*- lexical-binding: t -*-
-;; Copyright (C) 2016-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2022 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -17,23 +17,149 @@
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
-;;; Commentary:
+;;; Code:
(require 'ert)
(require 'rx)
-;;; Code:
+(ert-deftest rx-seq ()
+ (should (equal (rx "a.b" "*" "c")
+ "a\\.b\\*c"))
+ (should (equal (rx (seq "a" (: "b" (and "c" (sequence "d" nonl)
+ "e")
+ "f")
+ "g"))
+ "abcd.efg"))
+ (should (equal (rx "a$" "b")
+ "a\\$b"))
+ (should (equal (rx bol "a" "b" ?c eol)
+ "^abc$"))
+ (should (equal (rx "a" "" "b")
+ "ab"))
+ (should (equal (rx (seq))
+ ""))
+ (should (equal (rx "" (or "ab" nonl) "")
+ "ab\\|.")))
+
+(ert-deftest rx-or ()
+ (should (equal (rx (or "ab" (| "c" nonl) "de"))
+ "ab\\|c\\|.\\|de"))
+ (should (equal (rx (or "ab" "abc" ?a))
+ "\\(?:a\\(?:bc?\\)?\\)"))
+ (should (equal (rx (or "ab" (| (or "abcd" "abcde")) (or "a" "abc")))
+ "\\(?:a\\(?:b\\(?:c\\(?:de?\\)?\\)?\\)?\\)"))
+ (should (equal (rx (or "a" (eval (string ?a ?b))))
+ "\\(?:ab?\\)"))
+ (should (equal (rx (| nonl "a") (| "b" blank))
+ "\\(?:.\\|a\\)\\(?:b\\|[[:blank:]]\\)"))
+ (should (equal (rx (|))
+ "\\`a\\`")))
+
+(ert-deftest rx-def-in-or ()
+ (rx-let ((a b)
+ (b (or "abc" c))
+ (c ?a)
+ (d (any "a-z")))
+ (should (equal (rx (or a (| "ab" "abcde") "abcd"))
+ "\\(?:a\\(?:b\\(?:c\\(?:de?\\)?\\)?\\)?\\)"))
+ (should (equal (rx (or ?m (not d)))
+ "[^a-ln-z]"))))
(ert-deftest rx-char-any ()
- "Test character alternatives with `\]' and `-' (Bug#25123)."
- (should (string-match
+ "Test character alternatives with `]' and `-' (Bug#25123)."
+ (should (equal
+ ;; relint suppression: Range .<-]. overlaps previous .]-{
(rx string-start (1+ (char (?\] . ?\{) (?< . ?\]) (?- . ?:)))
string-end)
- (apply #'string (nconc (number-sequence ?\] ?\{)
- (number-sequence ?< ?\])
- (number-sequence ?- ?:))))))
+ "\\`[.-:<-{-]+\\'")))
+
+(ert-deftest rx-char-any-range-nl ()
+ "Test character alternatives with LF as a range endpoint."
+ (should (equal (rx (any "\n-\r"))
+ "[\n-\r]"))
+ (should (equal (rx (any "\a-\n"))
+ "[\a-\n]")))
+
+(ert-deftest rx-char-any-raw-byte ()
+ "Test raw bytes in character alternatives."
+
+ ;; The multibyteness of the rx return value sometimes depends on whether
+ ;; the test had been byte-compiled or not, so we add explicit conversions.
+
+ ;; Separate raw characters.
+ (should (equal (string-to-multibyte (rx (any "\326A\333B")))
+ (string-to-multibyte "[AB\326\333]")))
+ ;; Range of raw characters, unibyte.
+ (should (equal (string-to-multibyte (rx (any "\200-\377")))
+ (string-to-multibyte "[\200-\377]")))
+
+ ;; Range of raw characters, multibyte.
+ (should (equal (rx (any "Å\211\326-\377\177"))
+ "[\177Å\211\326-\377]"))
+ ;; Split range; \177-\377ÿ should not be optimized to \177-\377.
+ (should (equal (rx (any "\177-\377" ?ÿ))
+ "[\177ÿ\200-\377]")))
+
+(ert-deftest rx-any ()
+ (should (equal (rx (any ?A (?C . ?D) "F-H" "J-L" "M" "N-P" "Q" "RS"))
+ "[ACDF-HJ-S]"))
+ (should (equal (rx (in "a!f" ?c) (char "q-z" "0-3")
+ (not-char "a-e1-5") (not (in "A-M" ?q)))
+ "[!acf][0-3q-z][^1-5a-e][^A-Mq]"))
+ (should (equal (rx (any "^") (any "]") (any "-")
+ (not (any "^")) (not (any "]")) (not (any "-")))
+ "\\^]-[^^][^]][^-]"))
+ (should (equal (rx (any "]" "^") (any "]" "-") (any "-" "^")
+ (not (any "]" "^")) (not (any "]" "-"))
+ (not (any "-" "^")))
+ "[]^][]-][-^][^]^][^]-][^-^]"))
+ (should (equal (rx (any "]" "^" "-") (not (any "]" "^" "-")))
+ "[]^-][^]^-]"))
+ (should (equal (rx (any "-" ascii) (any "^" ascii) (any "]" ascii))
+ "[[:ascii:]-][[:ascii:]^][][:ascii:]]"))
+ (should (equal (rx (not (any "-" ascii)) (not (any "^" ascii))
+ (not (any "]" ascii)))
+ "[^[:ascii:]-][^[:ascii:]^][^][:ascii:]]"))
+ (should (equal (rx (any "-]" ascii) (any "^]" ascii) (any "-^" ascii))
+ "[][:ascii:]-][]^[:ascii:]][[:ascii:]^-]"))
+ (should (equal (rx (not (any "-]" ascii)) (not (any "^]" ascii))
+ (not (any "-^" ascii)))
+ "[^][:ascii:]-][^]^[:ascii:]][^[:ascii:]^-]"))
+ (should (equal (rx (any "-]^" ascii) (not (any "-]^" ascii)))
+ "[]^[:ascii:]-][^]^[:ascii:]-]"))
+ (should (equal (rx (any "^" lower upper) (not (any "^" lower upper)))
+ "[[:lower:]^[:upper:]][^[:lower:]^[:upper:]]"))
+ (should (equal (rx (any "-" lower upper) (not (any "-" lower upper)))
+ "[[:lower:][:upper:]-][^[:lower:][:upper:]-]"))
+ (should (equal (rx (any "]" lower upper) (not (any "]" lower upper)))
+ "[][:lower:][:upper:]][^][:lower:][:upper:]]"))
+ ;; relint suppression: Duplicated character .-.
+ ;; relint suppression: Single-character range .f-f
+ ;; relint suppression: Range .--/. overlaps previous .-
+ ;; relint suppression: Range .\*--. overlaps previous .--/
+ (should (equal (rx (any "-a" "c-" "f-f" "--/*--") (any "," "-" "A"))
+ "[*-/acf][,A-]"))
+ (should (equal (rx (any "]-a" ?-) (not (any "]-a" ?-)))
+ "[]-a-][^]-a-]"))
+ (should (equal (rx (any "--]") (not (any "--]"))
+ (any "-" "^-a") (not (any "-" "^-a")))
+ "[].-\\-][^].-\\-][-^-a][^-^-a]"))
+ (should (equal (rx (not (any "!a" "0-8" digit nonascii)))
+ "[^!0-8a[:digit:][:nonascii:]]"))
+ (should (equal (rx (any) (not (any)))
+ "\\`a\\`[^z-a]"))
+ (should (equal (rx (any "") (not (any "")))
+ "\\`a\\`[^z-a]"))
+ ;; relint suppression: Duplicated class .space.
+ (should (equal (rx (any space ?a digit space))
+ "[a[:space:][:digit:]]"))
+ (should (equal (rx (not "\n") (not ?\n) (not (any "\n")) (not-char ?\n)
+ (| (not (in "a\n")) (not (char ?\n (?b . ?b)))))
+ ".....")))
(ert-deftest rx-pcase ()
+ (should (equal (pcase "i18n" ((rx (let x (+ digit))) (list 'ok x)))
+ '(ok "18")))
(should (equal (pcase "a 1 2 3 1 1 b"
((rx (let u (+ digit)) space
(let v (+ digit)) space
@@ -41,7 +167,423 @@
(backref u) space
(backref 1))
(list u v)))
- '("1" "3"))))
+ '("1" "3")))
+ (should (equal (pcase "bz"
+ ((rx "a" (let x nonl)) (list 1 x))
+ (_ 'no))
+ 'no))
+ (should (equal (pcase "az"
+ ((rx "a" (let x nonl)) (list 1 x))
+ ((rx "b" (let x nonl)) (list 2 x))
+ (_ 'no))
+ '(1 "z")))
+ (should (equal (pcase "bz"
+ ((rx "a" (let x nonl)) (list 1 x))
+ ((rx "b" (let x nonl)) (list 2 x))
+ (_ 'no))
+ '(2 "z")))
+ (let ((k "blue"))
+ (should (equal (pcase "<blue>"
+ ((rx "<" (literal k) ">") 'ok))
+ 'ok)))
+ (should (equal (pcase "abc"
+ ((rx (? (let x alpha)) (?? (let y alnum)) ?c)
+ (list x y)))
+ '("a" "b")))
+ (should (equal (pcase 'not-a-string
+ ((rx nonl) 'wrong)
+ (_ 'correct))
+ 'correct))
+ (should (equal (pcase "PQR"
+ ((and (rx (let a nonl)) (rx ?z))
+ (list 'one a))
+ ((rx (let b ?Q))
+ (list 'two b)))
+ '(two "Q")))
+ (should (equal (pcase-let (((rx ?B (let z nonl)) "ABC"))
+ (list 'ok z))
+ '(ok "C")))
+ (should (equal (pcase-let* (((rx ?E (let z nonl)) "DEF"))
+ (list 'ok z))
+ '(ok "F"))))
+
+(ert-deftest rx-kleene ()
+ "Test greedy and non-greedy repetition operators."
+ (should (equal (rx (* "a") (+ "b") (\? "c") (?\s "d")
+ (*? "e") (+? "f") (\?? "g") (?? "h"))
+ "a*b+c?d?e*?f+?g??h??"))
+ (should (equal (rx (zero-or-more "a") (0+ "b")
+ (one-or-more "c") (1+ "d")
+ (zero-or-one "e") (optional "f") (opt "g"))
+ "a*b*c+d+e?f?g?"))
+ (should (equal (rx (minimal-match
+ (seq (* "a") (+ "b") (\? "c") (?\s "d")
+ (*? "e") (+? "f") (\?? "g") (?? "h"))))
+ "a*b+c?d?e*?f+?g??h??"))
+ (should (equal (rx (minimal-match
+ (seq (zero-or-more "a") (0+ "b")
+ (one-or-more "c") (1+ "d")
+ (zero-or-one "e") (optional "f") (opt "g"))))
+ "a*?b*?c+?d+?e??f??g??"))
+ (should (equal (rx (maximal-match
+ (seq (* "a") (+ "b") (\? "c") (?\s "d")
+ (*? "e") (+? "f") (\?? "g") (?? "h"))))
+ "a*b+c?d?e*?f+?g??h??"))
+ (should (equal (rx "a" (*) (+ (*)) (? (*) (+)) "b")
+ "ab")))
+
+(ert-deftest rx-repeat ()
+ (should (equal (rx (= 3 "a") (>= 51 "b")
+ (** 2 11 "c") (repeat 6 "d") (repeat 4 8 "e"))
+ "a\\{3\\}b\\{51,\\}c\\{2,11\\}d\\{6\\}e\\{4,8\\}"))
+ (should (equal (rx (= 0 "k") (>= 0 "l") (** 0 0 "m") (repeat 0 "n")
+ (repeat 0 0 "o"))
+ "k\\{0\\}l\\{0,\\}m\\{0\\}n\\{0\\}o\\{0\\}"))
+ (should (equal (rx (opt (0+ "a")))
+ "\\(?:a*\\)?"))
+ (should (equal (rx (opt (= 4 "a")))
+ "a\\{4\\}?"))
+ (should (equal (rx "a" (** 3 7) (= 4) (>= 3) (= 4 (>= 7) (= 2)) "b")
+ "ab")))
+
+(ert-deftest rx-atoms ()
+ (should (equal (rx anychar anything)
+ "[^z-a][^z-a]"))
+ (should (equal (rx unmatchable)
+ "\\`a\\`"))
+ (should (equal (rx line-start not-newline nonl any line-end)
+ "^...$"))
+ (should (equal (rx bol string-start string-end buffer-start buffer-end
+ bos eos bot eot eol)
+ "^\\`\\'\\`\\'\\`\\'\\`\\'$"))
+ (should (equal (rx point word-start word-end bow eow symbol-start symbol-end
+ word-boundary not-word-boundary not-wordchar)
+ "\\=\\<\\>\\<\\>\\_<\\_>\\b\\B\\W"))
+ (should (equal (rx digit numeric num control cntrl)
+ "[[:digit:]][[:digit:]][[:digit:]][[:cntrl:]][[:cntrl:]]"))
+ (should (equal (rx hex-digit hex xdigit blank)
+ "[[:xdigit:]][[:xdigit:]][[:xdigit:]][[:blank:]]"))
+ (should (equal (rx graph graphic print printing)
+ "[[:graph:]][[:graph:]][[:print:]][[:print:]]"))
+ (should (equal (rx alphanumeric alnum letter alphabetic alpha)
+ "[[:alnum:]][[:alnum:]][[:alpha:]][[:alpha:]][[:alpha:]]"))
+ (should (equal (rx ascii nonascii lower lower-case)
+ "[[:ascii:]][[:nonascii:]][[:lower:]][[:lower:]]"))
+ (should (equal (rx punctuation punct space whitespace white)
+ "[[:punct:]][[:punct:]][[:space:]][[:space:]][[:space:]]"))
+ (should (equal (rx upper upper-case word wordchar)
+ "[[:upper:]][[:upper:]][[:word:]][[:word:]]"))
+ (should (equal (rx unibyte multibyte)
+ "[[:unibyte:]][[:multibyte:]]")))
+
+(ert-deftest rx-syntax ()
+ (should (equal (rx (syntax whitespace) (syntax punctuation)
+ (syntax word) (syntax symbol)
+ (syntax open-parenthesis) (syntax close-parenthesis))
+ "\\s-\\s.\\sw\\s_\\s(\\s)"))
+ (should (equal (rx (syntax string-quote) (syntax paired-delimiter)
+ (syntax escape) (syntax character-quote)
+ (syntax comment-start) (syntax comment-end)
+ (syntax string-delimiter) (syntax comment-delimiter))
+ "\\s\"\\s$\\s\\\\s/\\s<\\s>\\s|\\s!")))
+
+(ert-deftest rx-category ()
+ (should (equal (rx (category space-for-indent) (category base)
+ (category consonant) (category base-vowel)
+ (category upper-diacritical-mark)
+ (category lower-diacritical-mark)
+ (category tone-mark) (category symbol)
+ (category digit)
+ (category vowel-modifying-diacritical-mark)
+ (category vowel-sign) (category semivowel-lower)
+ (category not-at-end-of-line)
+ (category not-at-beginning-of-line))
+ "\\c \\c.\\c0\\c1\\c2\\c3\\c4\\c5\\c6\\c7\\c8\\c9\\c<\\c>"))
+ (should (equal (rx (category alpha-numeric-two-byte)
+ (category chinese-two-byte) (category greek-two-byte)
+ (category japanese-hiragana-two-byte)
+ (category indian-two-byte)
+ (category japanese-katakana-two-byte)
+ (category strong-left-to-right)
+ (category korean-hangul-two-byte)
+ (category strong-right-to-left)
+ (category cyrillic-two-byte)
+ (category combining-diacritic))
+ "\\cA\\cC\\cG\\cH\\cI\\cK\\cL\\cN\\cR\\cY\\c^"))
+ (should (equal (rx (category ascii) (category arabic) (category chinese)
+ (category ethiopic) (category greek) (category korean)
+ (category indian) (category japanese)
+ (category japanese-katakana) (category latin)
+ (category lao) (category tibetan))
+ "\\ca\\cb\\cc\\ce\\cg\\ch\\ci\\cj\\ck\\cl\\co\\cq"))
+ (should (equal (rx (category japanese-roman) (category thai)
+ (category vietnamese) (category hebrew)
+ (category cyrillic) (category can-break))
+ "\\cr\\ct\\cv\\cw\\cy\\c|"))
+ (should (equal (rx (category ?g) (not (category ?~)))
+ "\\cg\\C~")))
+
+(ert-deftest rx-not ()
+ (should (equal (rx (not word-boundary))
+ "\\B"))
+ (should (equal (rx (not ascii) (not lower-case) (not wordchar))
+ "[^[:ascii:]][^[:lower:]][^[:word:]]"))
+ (should (equal (rx (not (syntax punctuation)) (not (syntax escape)))
+ "\\S.\\S\\"))
+ (should (equal (rx (not (category tone-mark)) (not (category lao)))
+ "\\C4\\Co"))
+ (should (equal (rx (not (not ascii)) (not (not (not (any "a-z")))))
+ "[[:ascii:]][^a-z]"))
+ (should (equal (rx (not ?a) (not "b") (not (not "c")) (not (not ?d)))
+ "[^a][^b]cd")))
+
+(ert-deftest rx-charset-or ()
+ (should (equal (rx (or))
+ "\\`a\\`"))
+ (should (equal (rx (or (any "ba")))
+ "[ab]"))
+ (should (equal (rx (| (any "a-f") (any "c-k" ?y) (any ?r "x-z")))
+ "[a-krx-z]"))
+ (should (equal (rx (or (not (any "a-m")) (not (any "f-p"))))
+ "[^f-m]"))
+ (should (equal (rx (| (any "e-m") (not (any "a-z"))))
+ "[^a-dn-z]"))
+ (should (equal (rx (or (not (any "g-r")) (not (any "t"))))
+ "[^z-a]"))
+ (should (equal (rx (not (or (not (any "g-r")) (not (any "t")))))
+ "\\`a\\`"))
+ (should (equal (rx (or (| (any "a-f") (any "u-z"))
+ (any "g-r")))
+ "[a-ru-z]"))
+ (should (equal (rx (or (intersection (any "c-z") (any "a-g"))
+ (not (any "a-k"))))
+ "[^abh-k]"))
+ (should (equal (rx (or ?f (any "b-e") "a") (not (or ?x "y" (any "s-w"))))
+ "[a-f][^s-y]"))
+ (should (equal (rx (not (or (in "abc") (char "bcd"))))
+ "[^a-d]"))
+ (should (equal (rx (or (not (in "abc")) (not (char "bcd"))))
+ "[^bc]"))
+ (should (equal (rx (or "x" (? "yz")))
+ "x\\|\\(?:yz\\)?")))
+
+(ert-deftest rx-def-in-charset-or ()
+ (rx-let ((a (any "badc"))
+ (b (| a (any "def")))
+ (c ?a)
+ (d "b"))
+ (should (equal (rx (or b (any "q")) (or c d))
+ "[a-fq][ab]")))
+ (rx-let ((diff-| (a b) (not (or (not a) b))))
+ (should (equal (rx (diff-| (any "a-z") (any "gr")))
+ "[a-fh-qs-z]"))))
+
+(ert-deftest rx-intersection ()
+ (should (equal (rx (intersection))
+ "[^z-a]"))
+ (should (equal (rx (intersection (any "ba")))
+ "[ab]"))
+ (should (equal (rx (intersection (any "a-j" "u-z") (any "c-k" ?y)
+ (any "a-i" "x-z")))
+ "[c-iy]"))
+ (should (equal (rx (intersection (not (any "a-m")) (not (any "f-p"))))
+ "[^a-p]"))
+ (should (equal (rx (intersection (any "a-z") (not (any "g-q"))))
+ "[a-fr-z]"))
+ (should (equal (rx (intersection (any "a-d") (any "e")))
+ "\\`a\\`"))
+ (should (equal (rx (not (intersection (any "a-d") (any "e"))))
+ "[^z-a]"))
+ (should (equal (rx (intersection (any "d-u")
+ (intersection (any "e-z") (any "a-m"))))
+ "[e-m]"))
+ (should (equal (rx (intersection (or (any "a-f") (any "f-t"))
+ (any "e-w")))
+ "[e-t]"))
+ (should (equal (rx (intersection ?m (any "a-z") "m"))
+ "m")))
+
+(ert-deftest rx-def-in-intersection ()
+ (rx-let ((a (any "a-g"))
+ (b (intersection a (any "d-j"))))
+ (should (equal (rx (intersection b (any "e-k")))
+ "[e-g]")))
+ (rx-let ((diff-& (a b) (intersection a (not b))))
+ (should (equal (rx (diff-& (any "a-z") (any "m-p")))
+ "[a-lq-z]"))))
+
+(ert-deftest rx-group ()
+ (should (equal (rx (group nonl) (submatch "x")
+ (group-n 3 "y") (submatch-n 13 "z") (backref 1))
+ "\\(.\\)\\(x\\)\\(?3:y\\)\\(?13:z\\)\\1"))
+ (should (equal (rx (group) (group-n 2))
+ "\\(\\)\\(?2:\\)")))
+
+(ert-deftest rx-regexp ()
+ (should (equal (rx (regexp "abc") (regex "[de]"))
+ "\\(?:abc\\)[de]"))
+ (should (equal (rx "a" (regexp "$"))
+ "a\\(?:$\\)"))
+ (let ((x "a*"))
+ (should (equal (rx (regexp x) "b")
+ "\\(?:a*\\)b"))
+ (should (equal (rx "" (regexp x) (eval ""))
+ "a*"))))
+
+(ert-deftest rx-eval ()
+ (should (equal (rx (eval (list 'syntax 'symbol)))
+ "\\s_"))
+ (should (equal (rx "a" (eval (concat)) "b")
+ "ab")))
+
+(ert-deftest rx-literal ()
+ (should (equal (rx (literal "$a"))
+ "\\$a"))
+ (should (equal (rx (literal (char-to-string 42)) nonl)
+ "\\*."))
+ (let ((x "a+b"))
+ (should (equal (rx (opt (literal (upcase x))))
+ "\\(?:A\\+B\\)?"))))
+
+(ert-deftest rx-to-string ()
+ (should (equal (rx-to-string '(or nonl "\nx"))
+ "\\(?:.\\|\nx\\)"))
+ (should (equal (rx-to-string '(or nonl "\nx") t)
+ ".\\|\nx")))
+
+(ert-deftest rx-let ()
+ (rx-let ((beta gamma)
+ (gamma delta)
+ (delta (+ digit))
+ (epsilon (or gamma nonl)))
+ (should (equal (rx bol delta epsilon)
+ "^[[:digit:]]+\\(?:[[:digit:]]+\\|.\\)")))
+ (rx-let ((p () point)
+ (separated (x sep) (seq x (* sep x)))
+ (comma-separated (x) (separated x ","))
+ (semi-separated (x) (separated x ";"))
+ (matrix (v) (semi-separated (comma-separated v))))
+ (should (equal (rx (p) (matrix (+ "a")) eos)
+ "\\=a+\\(?:,a+\\)*\\(?:;a+\\(?:,a+\\)*\\)*\\'")))
+ (rx-let ((b bol)
+ (z "B")
+ (three (x) (= 3 x)))
+ (rx-let ((two (x) (seq x x))
+ (z "A")
+ (e eol))
+ (should (equal (rx b (two (three z)) e)
+ "^A\\{3\\}A\\{3\\}$"))))
+ (rx-let ((f (a b &rest r) (seq "<" a ";" b ":" r ">")))
+ (should (equal (rx bol (f ?x ?y) ?! (f ?u ?v ?w) ?! (f ?k ?l ?m ?n) eol)
+ "^<x;y:>!<u;v:w>!<k;l:mn>$")))
+
+ ;; Rest parameters are expanded by splicing.
+ (rx-let ((f (&rest r) (or bol r eol)))
+ (should (equal (rx (f "ab" nonl))
+ "^\\|ab\\|.\\|$")))
+
+ ;; Substitution is done in number positions.
+ (rx-let ((stars (n) (= n ?*)))
+ (should (equal (rx (stars 4))
+ "\\*\\{4\\}")))
+
+ ;; Substitution is done inside dotted pairs.
+ (rx-let ((f (x y z) (any x (y . z))))
+ (should (equal (rx (f ?* ?a ?t))
+ "[*a-t]")))
+
+ ;; Substitution is done in the head position of forms.
+ (rx-let ((f (x) (x "a")))
+ (should (equal (rx (f +))
+ "a+"))))
+
+(ert-deftest rx-define ()
+ (rx-define rx--a (seq "x" (opt "y")))
+ (should (equal (rx bol rx--a eol)
+ "^xy?$"))
+ (rx-define rx--c (lb rb &rest stuff) (seq lb stuff rb))
+ (should (equal (rx bol (rx--c "<" ">" rx--a nonl) eol)
+ "^<xy?.>$"))
+ (rx-define rx--b (* rx--a))
+ (should (equal (rx rx--b)
+ "\\(?:xy?\\)*"))
+ (rx-define rx--a "z")
+ (should (equal (rx rx--b)
+ "z*")))
+
+(defun rx--test-rx-to-string-define ()
+ ;; `rx-define' won't expand to code inside `ert-deftest' since we use
+ ;; `eval-and-compile'. Put it into a defun as a workaround.
+ (rx-define rx--d "Q")
+ (rx-to-string '(seq bol rx--d) t))
+
+(ert-deftest rx-to-string-define ()
+ "Check that `rx-to-string' uses definitions made by `rx-define'."
+ (should (equal (rx--test-rx-to-string-define)
+ "^Q")))
+
+(ert-deftest rx-let-define ()
+ "Test interaction between `rx-let' and `rx-define'."
+ (rx-define rx--e "one")
+ (rx-define rx--f "eins")
+ (rx-let ((rx--e "two"))
+ (should (equal (rx rx--e nonl rx--f) "two.eins"))
+ (rx-define rx--e "three")
+ (should (equal (rx rx--e) "two"))
+ (rx-define rx--f "zwei")
+ (should (equal (rx rx--f) "zwei")))
+ (should (equal (rx rx--e nonl rx--f) "three.zwei")))
+
+(ert-deftest rx-let-eval ()
+ (rx-let-eval '((a (* digit))
+ (f (x &rest r) (seq x nonl r)))
+ (should (equal (rx-to-string '(seq a (f bow a ?b)) t)
+ "[[:digit:]]*\\<.[[:digit:]]*b"))))
+
+(ert-deftest rx-redefine-builtin ()
+ (should-error (rx-define sequence () "x"))
+ (should-error (rx-define sequence "x"))
+ (should-error (rx-define nonl () "x"))
+ (should-error (rx-define nonl "x"))
+ (should-error (rx-let ((punctuation () "x")) nil))
+ (should-error (rx-let ((punctuation "x")) nil))
+ (should-error (rx-let-eval '((not-char () "x")) nil))
+ (should-error (rx-let-eval '((not-char "x")) nil)))
+
+(ert-deftest rx-def-in-not ()
+ "Test definition expansion inside (not ...)."
+ (rx-let ((a alpha)
+ (b (not hex))
+ (c (not (category base)))
+ (d (x) (any ?a x ?z))
+ (e (x) (syntax x))
+ (f (not b)))
+ (should (equal (rx (not a) (not b) (not c) (not f))
+ "[^[:alpha:]][[:xdigit:]]\\c.[^[:xdigit:]]"))
+ (should (equal (rx (not (d ?m)) (not (e symbol)))
+ "[^amz]\\S_"))))
+
+(ert-deftest rx-constituents ()
+ (let ((rx-constituents
+ (append '((beta . gamma)
+ (gamma . "a*b")
+ (delta . ((lambda (form)
+ (regexp-quote (format "<%S>" form)))
+ 1 nil symbolp))
+ (epsilon . delta))
+ rx-constituents)))
+ (should (equal (rx-to-string '(seq (+ beta) nonl gamma) t)
+ "\\(?:a*b\\)+.\\(?:a*b\\)"))
+ (should (equal (rx-to-string '(seq (delta a b c) (* (epsilon d e))) t)
+ "\\(?:<(delta a b c)>\\)\\(?:<(epsilon d e)>\\)*"))))
+
+(ert-deftest rx-compat ()
+ "Test old symbol retained for compatibility (bug#37517)."
+ (should (equal
+ (with-no-warnings
+ (rx-submatch-n '(group-n 3 (+ nonl) eol)))
+ "\\(?3:.+$\\)")))
(provide 'rx-tests)
-;; rx-tests.el ends here.
+
+;;; rx-tests.el ends here
diff --git a/test/lisp/emacs-lisp/seq-tests.el b/test/lisp/emacs-lisp/seq-tests.el
index 5aa794a43b0..d95b35c45eb 100644
--- a/test/lisp/emacs-lisp/seq-tests.el
+++ b/test/lisp/emacs-lisp/seq-tests.el
@@ -1,6 +1,6 @@
-;;; seq-tests.el --- Tests for sequences.el
+;;; seq-tests.el --- Tests for seq.el -*- lexical-binding:t -*-
-;; Copyright (C) 2014-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2022 Free Software Foundation, Inc.
;; Author: Nicolas Petton <nicolas@petton.fr>
;; Maintainer: emacs-devel@gnu.org
@@ -29,6 +29,9 @@
(require 'ert)
(require 'seq)
+(eval-when-compile
+ (require 'cl-lib))
+
(defmacro with-test-sequences (spec &rest body)
"Successively bind VAR to a list, vector, and string built from SEQ.
Evaluate BODY for each created sequence.
@@ -108,16 +111,12 @@ Evaluate BODY for each created sequence.
'((a 0) (b 1) (c 2) (d 3)))))
(ert-deftest test-seq-do-indexed ()
- (let ((result nil))
- (seq-do-indexed (lambda (elt i)
- (add-to-list 'result (list elt i)))
- nil)
- (should (equal result nil)))
+ (let (result)
+ (seq-do-indexed (lambda (elt i) (push (list elt i) result)) ())
+ (should-not result))
(with-test-sequences (seq '(4 5 6))
- (let ((result nil))
- (seq-do-indexed (lambda (elt i)
- (add-to-list 'result (list elt i)))
- seq)
+ (let (result)
+ (seq-do-indexed (lambda (elt i) (push (list elt i) result)) seq)
(should (equal (seq-elt result 0) '(6 2)))
(should (equal (seq-elt result 1) '(5 1)))
(should (equal (seq-elt result 2) '(4 0))))))
@@ -126,7 +125,7 @@ Evaluate BODY for each created sequence.
(with-test-sequences (seq '(6 7 8 9 10))
(should (equal (seq-filter #'test-sequences-evenp seq) '(6 8 10)))
(should (equal (seq-filter #'test-sequences-oddp seq) '(7 9)))
- (should (equal (seq-filter (lambda (elt) nil) seq) '())))
+ (should (equal (seq-filter (lambda (_) nil) seq) '())))
(with-test-sequences (seq '())
(should (equal (seq-filter #'test-sequences-evenp seq) '()))))
@@ -134,15 +133,23 @@ Evaluate BODY for each created sequence.
(with-test-sequences (seq '(6 7 8 9 10))
(should (equal (seq-remove #'test-sequences-evenp seq) '(7 9)))
(should (equal (seq-remove #'test-sequences-oddp seq) '(6 8 10)))
- (should (same-contents-p (seq-remove (lambda (elt) nil) seq) seq)))
+ (should (same-contents-p (seq-remove (lambda (_) nil) seq) seq)))
(with-test-sequences (seq '())
(should (equal (seq-remove #'test-sequences-evenp seq) '()))))
+(ert-deftest test-seq-remove-at-position ()
+ (with-test-sequences (seq '(1 2 3 4))
+ (should (same-contents-p (seq-remove-at-position seq 2) '(1 2 4)))
+ (should (same-contents-p (seq-remove-at-position seq 0) '(2 3 4)))
+ (should (same-contents-p (seq-remove-at-position seq 3) '(1 2 3)))
+ (should (eq (type-of (seq-remove-at-position seq 2))
+ (type-of seq)))))
+
(ert-deftest test-seq-count ()
(with-test-sequences (seq '(6 7 8 9 10))
(should (equal (seq-count #'test-sequences-evenp seq) 3))
(should (equal (seq-count #'test-sequences-oddp seq) 2))
- (should (equal (seq-count (lambda (elt) nil) seq) 0)))
+ (should (equal (seq-count (lambda (_) nil) seq) 0)))
(with-test-sequences (seq '())
(should (equal (seq-count #'test-sequences-evenp seq) 0))))
@@ -174,20 +181,34 @@ Evaluate BODY for each created sequence.
(should (seq-find #'null '(1 2 3) 'sentinel)))
(ert-deftest test-seq-contains ()
- (with-test-sequences (seq '(3 4 5 6))
- (should (seq-contains seq 3))
- (should-not (seq-contains seq 7)))
- (with-test-sequences (seq '())
- (should-not (seq-contains seq 3))
- (should-not (seq-contains seq nil))))
+ (with-suppressed-warnings ((obsolete seq-contains))
+ (with-test-sequences (seq '(3 4 5 6))
+ (should (seq-contains seq 3))
+ (should-not (seq-contains seq 7)))
+ (with-test-sequences (seq '())
+ (should-not (seq-contains seq 3))
+ (should-not (seq-contains seq nil)))))
(ert-deftest test-seq-contains-should-return-the-elt ()
+ (with-suppressed-warnings ((obsolete seq-contains))
+ (with-test-sequences (seq '(3 4 5 6))
+ (should (= 5 (seq-contains seq 5))))))
+
+(ert-deftest test-seq-contains-p ()
(with-test-sequences (seq '(3 4 5 6))
- (should (= 5 (seq-contains seq 5)))))
+ (should (eq (seq-contains-p seq 3) t))
+ (should-not (seq-contains-p seq 7)))
+ (with-test-sequences (seq '())
+ (should-not (seq-contains-p seq 3))
+ (should-not (seq-contains-p seq nil))))
+
+(ert-deftest test-seq-contains-p-with-nil ()
+ (should (seq-contains-p [nil] nil))
+ (should (seq-contains-p '(nil) nil)))
(ert-deftest test-seq-every-p ()
(with-test-sequences (seq '(43 54 22 1))
- (should (seq-every-p (lambda (elt) t) seq))
+ (should (seq-every-p (lambda (_) t) seq))
(should-not (seq-every-p #'test-sequences-oddp seq))
(should-not (seq-every-p #'test-sequences-evenp seq)))
(with-test-sequences (seq '(42 54 22 2))
@@ -244,6 +265,19 @@ Evaluate BODY for each created sequence.
(with-test-sequences (seq '())
(should (equal (seq-uniq seq) '()))))
+(defun seq-tests--list-subseq-ref (list start &optional end)
+ "Reference implementation of `seq-subseq' for lists."
+ (let ((len (length list)))
+ (when (< start 0)
+ (setq start (+ start len)))
+ (unless end
+ (setq end len))
+ (when (< end 0)
+ (setq end (+ end len)))
+ (if (<= 0 start end len)
+ (take (- end start) (nthcdr start list))
+ (error "bad args"))))
+
(ert-deftest test-seq-subseq ()
(with-test-sequences (seq '(2 3 4 5))
(should (equal (seq-subseq seq 0 4) seq))
@@ -262,7 +296,21 @@ Evaluate BODY for each created sequence.
(should-error (seq-subseq [] -1))
(should-error (seq-subseq "" -1))
(should-not (seq-subseq '() 0))
- (should-error (seq-subseq '() 0 -1)))
+ (should-error (seq-subseq '() 0 -1))
+
+ (dolist (list '(() (a b c d)))
+ (ert-info ((prin1-to-string list) :prefix "list: ")
+ (let ((len (length list)))
+ (dolist (start (number-sequence (- -2 len) (+ 2 len)))
+ (ert-info ((prin1-to-string start) :prefix "start: ")
+ (dolist (end (cons nil (number-sequence (- -2 len) (+ 2 len))))
+ (ert-info ((prin1-to-string end) :prefix "end: ")
+ (condition-case res
+ (seq-tests--list-subseq-ref list start end)
+ (error
+ (should-error (seq-subseq list start end)))
+ (:success
+ (should (equal (seq-subseq list start end) res))))))))))))
(ert-deftest test-seq-concatenate ()
(with-test-sequences (seq '(2 4 6))
@@ -325,6 +373,33 @@ Evaluate BODY for each created sequence.
(should (same-contents-p list vector))
(should (vectorp vector))))
+(ert-deftest test-seq-union ()
+ (let ((v1 '(1 2 3))
+ (v2 '(3 5)))
+ (should (same-contents-p (seq-union v1 v2)
+ '(1 2 3 5))))
+
+ (let ((v1 '(1 2 3 4 5 6))
+ (v2 '(4 5 6 7 8 9)))
+ (should (same-contents-p (seq-union v1 v2)
+ '(1 2 3 4 5 6 7 8 9))))
+
+ (let ((v1 [1 2 3 4 5])
+ (v2 [4 5 6 "a"]))
+ (should (same-contents-p (seq-union v1 v2)
+ '(1 2 3 4 5 6 "a"))))
+
+ (let ((v1 '("a" "b" "c"))
+ (v2 '("f" "c" "e" "a")))
+ (should (same-contents-p (seq-union v1 v2)
+ '("a" "b" "c" "f" "e"))))
+
+ (let ((v1 '("a"))
+ (v2 '("a"))
+ (testfn #'eq))
+ (should (same-contents-p (seq-union v1 v2 testfn)
+ '("a" "a")))))
+
(ert-deftest test-seq-intersection ()
(let ((v1 [2 3 4 5])
(v2 [1 3 5 6 7]))
@@ -366,12 +441,36 @@ Evaluate BODY for each created sequence.
(let ((seq '(1 (2 (3 (4))))))
(seq-let (_ (_ (_ (a)))) seq
(should (= a 4))))
- (let (seq)
+ (let ((seq nil))
(seq-let (a b c) seq
(should (null a))
(should (null b))
(should (null c)))))
+(ert-deftest test-seq-setq ()
+ (with-test-sequences (seq '(1 2 3 4))
+ (let (a b c d e)
+ (seq-setq (a b c d e) seq)
+ (should (= a 1))
+ (should (= b 2))
+ (should (= c 3))
+ (should (= d 4))
+ (should (null e)))
+ (let (a b others)
+ (seq-setq (a b &rest others) seq)
+ (should (= a 1))
+ (should (= b 2))
+ (should (same-contents-p others (seq-drop seq 2)))))
+ (let ((a)
+ (seq '(1 (2 (3 (4))))))
+ (seq-setq (_ (_ (_ (a)))) seq)
+ (should (= a 4)))
+ (let ((seq nil) a b c)
+ (seq-setq (a b c) seq)
+ (should (null a))
+ (should (null b))
+ (should (null c))))
+
(ert-deftest test-seq-min-max ()
(with-test-sequences (seq '(4 5 3 2 0 4))
(should (= (seq-min seq) 0))
@@ -391,6 +490,13 @@ Evaluate BODY for each created sequence.
(should (= (seq-position seq 'a #'eq) 0))
(should (null (seq-position seq (make-symbol "a") #'eq)))))
+(ert-deftest test-seq-positions ()
+ (with-test-sequences (seq '(1 2 3 1 4))
+ (should (equal '(0 3) (seq-positions seq 1)))
+ (should (seq-empty-p (seq-positions seq 9))))
+ (with-test-sequences (seq '(11 5 7 12 9 15))
+ (should (equal '(0 3 5) (seq-positions seq 10 #'>=)))))
+
(ert-deftest test-seq-sort-by ()
(let ((seq ["x" "xx" "xxx"]))
(should (equal (seq-sort-by #'seq-length #'> seq)
@@ -398,12 +504,10 @@ Evaluate BODY for each created sequence.
(ert-deftest test-seq-random-elt-take-all ()
(let ((seq '(a b c d e))
- (elts '()))
- (should (= 0 (length elts)))
+ elts)
(dotimes (_ 1000)
(let ((random-elt (seq-random-elt seq)))
- (add-to-list 'elts
- random-elt)))
+ (cl-pushnew random-elt elts)))
(should (= 5 (length elts)))))
(ert-deftest test-seq-random-elt-signal-on-empty ()
@@ -424,5 +528,69 @@ Evaluate BODY for each created sequence.
(should (eq (seq-into vec 'vector) vec))
(should (eq (seq-into str 'string) str))))
+(ert-deftest test-seq-first ()
+ (let ((lst '(1 2 3))
+ (vec [1 2 3]))
+ (should (eq (seq-first lst) 1))
+ (should (eq (seq-first vec) 1))))
+
+(ert-deftest test-seq-rest ()
+ (let ((lst '(1 2 3))
+ (vec [1 2 3]))
+ (should (equal (seq-rest lst) '(2 3)))
+ (should (equal (seq-rest vec) [2 3]))))
+
+;; Regression tests for bug#34852
+(progn
+ (ert-deftest test-seq-intersection-with-nil ()
+ (should (equal (seq-intersection '(1 2 nil) '(1 nil)) '(1 nil))))
+
+ (ert-deftest test-seq-set-equal-p-with-nil ()
+ (should (seq-set-equal-p '("a" "b" nil)
+ '(nil "b" "a"))))
+
+ (ert-deftest test-difference-with-nil ()
+ (should (equal (seq-difference '(1 nil) '(2 nil))
+ '(1)))))
+
+(ert-deftest test-seq-split ()
+ (let ((seq [0 1 2 3 4 5 6 7 8 9 10]))
+ (should (equal seq (car (seq-split seq 20))))
+ (should (equal seq (car (seq-split seq 11))))
+ (should (equal (seq-split seq 10)
+ '([0 1 2 3 4 5 6 7 8 9] [10])))
+ (should (equal (seq-split seq 5)
+ '([0 1 2 3 4] [5 6 7 8 9] [10])))
+ (should (equal (seq-split seq 1)
+ '([0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10])))
+ (should-error (seq-split seq 0))
+ (should-error (seq-split seq -10)))
+ (let ((seq '(0 1 2 3 4 5 6 7 8 9)))
+ (should (equal (seq-split seq 5)
+ '((0 1 2 3 4) (5 6 7 8 9)))))
+ (let ((seq "0123456789"))
+ (should (equal (seq-split seq 2)
+ '("01" "23" "45" "67" "89")))
+ (should (equal (seq-split seq 3)
+ '("012" "345" "678" "9")))))
+
+(ert-deftest test-seq-uniq-list ()
+ (let ((list '(1 2 3)))
+ (should (equal (seq-uniq (append list list)) '(1 2 3))))
+ (let ((list '(1 2 3 2 1)))
+ (should (equal (seq-uniq list) '(1 2 3))))
+ (let ((list (list (substring "1")
+ (substring "2")
+ (substring "3")
+ (substring "2")
+ (substring "1"))))
+ (should (equal (seq-uniq list) '("1" "2" "3")))
+ (should (equal (seq-uniq list #'eq) '("1" "2" "3" "2" "1"))))
+ ;; Long lists have a different code path.
+ (let ((list (seq-map-indexed (lambda (_ i) i)
+ (make-list 10000 nil))))
+ (should (= (length list) 10000))
+ (should (= (length (seq-uniq (append list list))) 10000))))
+
(provide 'seq-tests)
;;; seq-tests.el ends here
diff --git a/test/lisp/emacs-lisp/shadow-resources/p1/foo.el b/test/lisp/emacs-lisp/shadow-resources/p1/foo.el
new file mode 100644
index 00000000000..ffe68f9356f
--- /dev/null
+++ b/test/lisp/emacs-lisp/shadow-resources/p1/foo.el
@@ -0,0 +1 @@
+;;; This file intentionally left blank. -*- lexical-binding:t -*-
diff --git a/test/lisp/emacs-lisp/shadow-resources/p2/FOO.el b/test/lisp/emacs-lisp/shadow-resources/p2/FOO.el
new file mode 100644
index 00000000000..ffe68f9356f
--- /dev/null
+++ b/test/lisp/emacs-lisp/shadow-resources/p2/FOO.el
@@ -0,0 +1 @@
+;;; This file intentionally left blank. -*- lexical-binding:t -*-
diff --git a/test/lisp/emacs-lisp/shadow-tests.el b/test/lisp/emacs-lisp/shadow-tests.el
new file mode 100644
index 00000000000..a91c4efd048
--- /dev/null
+++ b/test/lisp/emacs-lisp/shadow-tests.el
@@ -0,0 +1,42 @@
+;;; shadow-tests.el --- Test suite for shadow. -*- lexical-binding: t -*-
+
+;; Copyright (C) 2018-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'ert-x)
+(require 'shadow)
+(eval-when-compile (require 'cl-lib))
+
+(ert-deftest shadow-case-insensitive ()
+ "Test shadowing for case insensitive filenames."
+ ;; Override `file-name-case-insensitive-p' so we test the same thing
+ ;; regardless of what file system we're running on.
+ (cl-letf (((symbol-function 'file-name-case-insensitive-p) (lambda (_f) t)))
+ (should (equal (list (ert-resource-file "p1/foo")
+ (ert-resource-file "p2/FOO"))
+ (load-path-shadows-find
+ (list (ert-resource-file "p1/")
+ (ert-resource-file "p2/"))))))
+ (cl-letf (((symbol-function 'file-name-case-insensitive-p) (lambda (_f) nil)))
+ (should-not (load-path-shadows-find
+ (list (ert-resource-file "p1/")
+ (ert-resource-file "p2/"))))))
+
+;;; shadow-tests.el ends here.
diff --git a/test/lisp/emacs-lisp/shortdoc-tests.el b/test/lisp/emacs-lisp/shortdoc-tests.el
new file mode 100644
index 00000000000..8515b9fdfb9
--- /dev/null
+++ b/test/lisp/emacs-lisp/shortdoc-tests.el
@@ -0,0 +1,60 @@
+;;; shortdoc-tests.el --- tests for shortdoc.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'shortdoc)
+
+(defun shortdoc-tests--tree-contains (tree fun)
+ "Whether TREE contains a call to FUN."
+ (and (proper-list-p tree)
+ (or (eq (car tree) fun)
+ (cl-some (lambda (x) (shortdoc-tests--tree-contains x fun)) tree))))
+
+(ert-deftest shortdoc-examples ()
+ "Check that each example actually contains the corresponding form."
+ (dolist (group shortdoc--groups)
+ (dolist (item group)
+ (when (consp item)
+ (let ((fun (car item))
+ (props (cdr item)))
+ (while props
+ (when (memq (car props) '(:eval :no-eval :no-eval* :no-value))
+ (let* ((example (cadr props))
+ (expr (cond
+ ((consp example) example)
+ ((stringp example) (read example)))))
+ (should (shortdoc-tests--tree-contains expr fun))))
+ (setq props (cddr props))))))))
+
+(ert-deftest shortdoc-all-groups-work ()
+ "Test that all defined shortdoc groups display correctly."
+ (dolist (group (mapcar (lambda (x) (car x)) shortdoc--groups))
+ (let ((buf-name (format "*Shortdoc %s*" group)) buf)
+ (unwind-protect
+ (progn
+ (shortdoc-display-group group)
+ (should (setq buf (get-buffer buf-name))))
+ (when buf
+ (kill-buffer buf))))))
+
+(provide 'shortdoc-tests)
+
+;;; shortdoc-tests.el ends here
diff --git a/test/lisp/emacs-lisp/subr-x-tests.el b/test/lisp/emacs-lisp/subr-x-tests.el
index 0e8871d9a9c..7a3efe9db62 100644
--- a/test/lisp/emacs-lisp/subr-x-tests.el
+++ b/test/lisp/emacs-lisp/subr-x-tests.el
@@ -1,22 +1,24 @@
-;;; subr-x-tests.el --- Testing the extended lisp routines
+;;; subr-x-tests.el --- Testing the extended lisp routines -*- lexical-binding:t -*-
-;; Copyright (C) 2014-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2022 Free Software Foundation, Inc.
;; Author: Fabián E. Gallina <fgallina@gnu.org>
;; Keywords:
-;; This program is free software; you can redistribute it and/or modify
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
-;; This program is distributed in the hope that it will be useful,
+;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
-;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
@@ -148,34 +150,34 @@
"Test `if-let' with falsie bindings."
(should (equal
(if-let* ((a nil))
- (list a b c)
+ "yes"
"no")
"no"))
(should (equal
(if-let* ((a nil) (b 2) (c 3))
- (list a b c)
+ "yes"
"no")
"no"))
(should (equal
(if-let* ((a 1) (b nil) (c 3))
- (list a b c)
+ "yes"
"no")
"no"))
(should (equal
(if-let* ((a 1) (b 2) (c nil))
- (list a b c)
+ "yes"
"no")
"no"))
(should (equal
- (let (z)
+ (let ((z nil))
(if-let* (z (a 1) (b 2) (c 3))
- (list a b c)
+ "yes"
"no"))
"no"))
(should (equal
- (let (d)
+ (let ((d nil))
(if-let* ((a 1) (b 2) (c 3) d)
- (list a b c)
+ "yes"
"no"))
"no")))
@@ -189,7 +191,7 @@
(ert-deftest subr-x-test-if-let*-and-laziness-is-preserved ()
"Test `if-let' respects `and' laziness."
- (let (a-called b-called c-called)
+ (let ((a-called nil) (b-called nil) c-called)
(should (equal
(if-let* ((a nil)
(b (setq b-called t))
@@ -197,7 +199,7 @@
"yes"
(list a-called b-called c-called))
(list nil nil nil))))
- (let (a-called b-called c-called)
+ (let ((a-called nil) (b-called nil) c-called)
(should (equal
(if-let* ((a (setq a-called t))
(b nil)
@@ -205,12 +207,12 @@
"yes"
(list a-called b-called c-called))
(list t nil nil))))
- (let (a-called b-called c-called)
+ (let ((a-called nil) (b-called nil) c-called)
(should (equal
(if-let* ((a (setq a-called t))
- (b (setq b-called t))
- (c nil)
- (d (setq c-called t)))
+ (b (setq b-called t))
+ (c nil)
+ (d (setq c-called t)))
"yes"
(list a-called b-called c-called))
(list t t nil)))))
@@ -312,34 +314,28 @@
"Test `when-let' with falsie bindings."
(should (equal
(when-let* ((a nil))
- (list a b c)
"no")
nil))
(should (equal
(when-let* ((a nil) (b 2) (c 3))
- (list a b c)
"no")
nil))
(should (equal
(when-let* ((a 1) (b nil) (c 3))
- (list a b c)
"no")
nil))
(should (equal
(when-let* ((a 1) (b 2) (c nil))
- (list a b c)
"no")
nil))
(should (equal
- (let (z)
+ (let ((z nil))
(when-let* (z (a 1) (b 2) (c 3))
- (list a b c)
"no"))
nil))
(should (equal
- (let (d)
+ (let ((d nil))
(when-let* ((a 1) (b 2) (c 3) d)
- (list a b c)
"no"))
nil)))
@@ -352,7 +348,7 @@
(ert-deftest subr-x-test-when-let*-and-laziness-is-preserved ()
"Test `when-let' respects `and' laziness."
- (let (a-called b-called c-called)
+ (let ((a-called nil) (b-called nil) (c-called nil))
(should (equal
(progn
(when-let* ((a nil)
@@ -361,7 +357,7 @@
"yes")
(list a-called b-called c-called))
(list nil nil nil))))
- (let (a-called b-called c-called)
+ (let ((a-called nil) (b-called nil) (c-called nil))
(should (equal
(progn
(when-let* ((a (setq a-called t))
@@ -370,7 +366,7 @@
"yes")
(list a-called b-called c-called))
(list t nil nil))))
- (let (a-called b-called c-called)
+ (let ((a-called nil) (b-called nil) (c-called nil))
(should (equal
(progn
(when-let* ((a (setq a-called t))
@@ -403,7 +399,7 @@
(should-error (eval '(and-let* (nil (x 1))) lexical-binding)
:type 'setting-constant)
(should (equal nil (and-let* ((nil) (x 1)))))
- (should-error (eval (and-let* (2 (x 1))) lexical-binding)
+ (should-error (eval '(and-let* (2 (x 1))) lexical-binding)
:type 'wrong-type-argument)
(should (equal 1 (and-let* ((2) (x 1)))))
(should (equal 2 (and-let* ((x 1) (2)))))
@@ -459,18 +455,18 @@
"Test `thread-first' wraps single function names."
(should (equal (macroexpand
'(thread-first 5
- -))
+ -))
'(- 5)))
(should (equal (macroexpand
'(thread-first (+ 1 2)
- -))
+ -))
'(- (+ 1 2)))))
(ert-deftest subr-x-test-thread-first-expansion ()
"Test `thread-first' expands correctly."
(should (equal
(macroexpand '(thread-first
- 5
+ 5
(+ 20)
(/ 25)
-
@@ -481,13 +477,13 @@
"Test several `thread-first' examples."
(should (equal (thread-first (+ 40 2)) 42))
(should (equal (thread-first
- 5
+ 5
(+ 20)
(/ 25)
-
(+ 40)) 39))
(should (equal (thread-first
- "this-is-a-string"
+ "this-is-a-string"
(split-string "-")
(nbutlast 2)
(append (list "good")))
@@ -504,18 +500,18 @@
"Test `thread-last' wraps single function names."
(should (equal (macroexpand
'(thread-last 5
- -))
+ -))
'(- 5)))
(should (equal (macroexpand
'(thread-last (+ 1 2)
- -))
+ -))
'(- (+ 1 2)))))
(ert-deftest subr-x-test-thread-last-expansion ()
"Test `thread-last' expands correctly."
(should (equal
(macroexpand '(thread-last
- 5
+ 5
(+ 20)
(/ 25)
-
@@ -526,18 +522,254 @@
"Test several `thread-last' examples."
(should (equal (thread-last (+ 40 2)) 42))
(should (equal (thread-last
- 5
+ 5
(+ 20)
(/ 25)
-
(+ 40)) 39))
(should (equal (thread-last
- (list 1 -2 3 -4 5)
+ (list 1 -2 3 -4 5)
(mapcar #'abs)
(cl-reduce #'+)
(format "abs sum is: %s"))
"abs sum is: 15")))
+
+;; Substring tests
+
+(ert-deftest subr-x-test-string-trim-left ()
+ "Test `string-trim-left' behavior."
+ (should (equal (string-trim-left "") ""))
+ (should (equal (string-trim-left " \t\n\r") ""))
+ (should (equal (string-trim-left " \t\n\ra") "a"))
+ (should (equal (string-trim-left "a \t\n\r") "a \t\n\r"))
+ (should (equal (string-trim-left "" "") ""))
+ (should (equal (string-trim-left "a" "") "a"))
+ (should (equal (string-trim-left "aa" "a*") ""))
+ (should (equal (string-trim-left "ba" "a*") "ba"))
+ (should (equal (string-trim-left "aa" "a*?") "aa"))
+ (should (equal (string-trim-left "aa" "a+?") "a")))
+
+(ert-deftest subr-x-test-string-trim-right ()
+ "Test `string-trim-right' behavior."
+ (should (equal (string-trim-right "") ""))
+ (should (equal (string-trim-right " \t\n\r") ""))
+ (should (equal (string-trim-right " \t\n\ra") " \t\n\ra"))
+ (should (equal (string-trim-right "a \t\n\r") "a"))
+ (should (equal (string-trim-right "" "") ""))
+ (should (equal (string-trim-right "a" "") "a"))
+ (should (equal (string-trim-right "aa" "a*") ""))
+ (should (equal (string-trim-right "ab" "a*") "ab"))
+ (should (equal (string-trim-right "aa" "a*?") "")))
+
+(ert-deftest subr-x-test-string-remove-prefix ()
+ "Test `string-remove-prefix' behavior."
+ (should (equal (string-remove-prefix "" "") ""))
+ (should (equal (string-remove-prefix "" "a") "a"))
+ (should (equal (string-remove-prefix "a" "") ""))
+ (should (equal (string-remove-prefix "a" "b") "b"))
+ (should (equal (string-remove-prefix "a" "a") ""))
+ (should (equal (string-remove-prefix "a" "aa") "a"))
+ (should (equal (string-remove-prefix "a" "ab") "b")))
+
+(ert-deftest subr-x-test-string-remove-suffix ()
+ "Test `string-remove-suffix' behavior."
+ (should (equal (string-remove-suffix "" "") ""))
+ (should (equal (string-remove-suffix "" "a") "a"))
+ (should (equal (string-remove-suffix "a" "") ""))
+ (should (equal (string-remove-suffix "a" "b") "b"))
+ (should (equal (string-remove-suffix "a" "a") ""))
+ (should (equal (string-remove-suffix "a" "aa") "a"))
+ (should (equal (string-remove-suffix "a" "ba") "b")))
+
+(ert-deftest subr-clean-whitespace ()
+ (should (equal (string-clean-whitespace " foo ") "foo"))
+ (should (equal (string-clean-whitespace " foo \r\n\t  Bar") "foo Bar")))
+
+(ert-deftest subr-string-fill ()
+ (should (equal (string-fill "foo" 10) "foo"))
+ (should (equal (string-fill "foobar" 5) "foobar"))
+ (should (equal (string-fill "foo bar zot" 5) "foo\nbar\nzot"))
+ (should (equal (string-fill "foo bar zot" 7) "foo bar\nzot")))
+
+(ert-deftest subr-string-limit ()
+ (should (equal (string-limit "foo" 10) "foo"))
+ (should (equal (string-limit "foo" 2) "fo"))
+ (should (equal (string-limit "foo" 2 t) "oo"))
+ (should (equal (string-limit "abc" 10 t) "abc"))
+ (should (equal (string-limit "foo" 0) ""))
+ (should-error (string-limit "foo" -1)))
+
+(ert-deftest subr-string-limit-coding ()
+ (should (not (multibyte-string-p (string-limit "foó" 10 nil 'utf-8))))
+ (should (equal (string-limit "foó" 10 nil 'utf-8) "fo\303\263"))
+ (should (equal (string-limit "foó" 3 nil 'utf-8) "fo"))
+ (should (equal (string-limit "foó" 4 nil 'utf-8) "fo\303\263"))
+ (should (equal (string-limit "foóa" 4 nil 'utf-8) "fo\303\263"))
+ (should (equal (string-limit "foóá" 4 nil 'utf-8) "fo\303\263"))
+ (should (equal (string-limit "foóá" 2 nil 'utf-8-with-signature)
+ ""))
+ (should (equal (string-limit "foóá" 4 nil 'utf-8-with-signature)
+ "\357\273\277f"))
+ (should (equal (string-limit "foóa" 4 nil 'iso-8859-1) "fo\363a"))
+ (should (equal (string-limit "foóá" 4 nil 'iso-8859-1) "fo\363\341"))
+ (should (equal (string-limit "foóá" 3 nil 'utf-16) ""))
+ (should (equal (string-limit "foóá" 6 nil 'utf-16) "\376\377\000f\000o"))
+
+ (should (equal (string-limit "foó" 10 t 'utf-8) "fo\303\263"))
+ (should (equal (string-limit "foó" 3 t 'utf-8) "o\303\263"))
+ (should (equal (string-limit "foó" 4 t 'utf-8) "fo\303\263"))
+ (should (equal (string-limit "foóa" 4 t 'utf-8) "o\303\263a"))
+ (should (equal (string-limit "foóá" 4 t 'utf-8) "\303\263\303\241"))
+ (should (equal (string-limit "foóá" 2 t 'utf-8-with-signature)
+ ""))
+ (should (equal (string-limit "foóa" 4 t 'iso-8859-1) "fo\363a"))
+ (should (equal (string-limit "foóá" 4 t 'iso-8859-1) "fo\363\341"))
+ (should (equal (string-limit "foóá" 6 t 'utf-16) "\376\377\000\363\000\341")))
+
+(ert-deftest subr-string-limit-glyphs ()
+ (should (equal (encode-coding-string "Hello, 👼🏻🧑🏼‍🤝‍🧑🏻" 'utf-8)
+ "Hello, \360\237\221\274\360\237\217\273\360\237\247\221\360\237\217\274\342\200\215\360\237\244\235\342\200\215\360\237\247\221\360\237\217\273"))
+ (should (= (length (encode-coding-string "Hello, 👼🏻🧑🏼‍🤝‍🧑🏻" 'utf-8)) 41))
+ (should (equal (string-limit "Hello, 👼🏻🧑🏼‍🤝‍🧑🏻" 100 nil 'utf-8)
+ "Hello, \360\237\221\274\360\237\217\273\360\237\247\221\360\237\217\274\342\200\215\360\237\244\235\342\200\215\360\237\247\221\360\237\217\273"))
+ (should (equal (string-limit "Hello, 👼🏻🧑🏼‍🤝‍🧑🏻" 15 nil 'utf-8)
+ "Hello, \360\237\221\274\360\237\217\273"))
+ (should (equal (string-limit "Hello, 👼🏻🧑🏼‍🤝‍🧑🏻" 10 nil 'utf-8)
+ "Hello, ")))
+
+(ert-deftest subr-string-lines ()
+ (should (equal (string-lines "foo") '("foo")))
+ (should (equal (string-lines "foo \nbar") '("foo " "bar"))))
+
+(ert-deftest subr-string-pad ()
+ (should (equal (string-pad "foo" 5) "foo "))
+ (should (equal (string-pad "foo" 5 ?-) "foo--"))
+ (should (equal (string-pad "foo" 5 ?- t) "--foo"))
+ (should (equal (string-pad "foo" 2 ?-) "foo")))
+
+(ert-deftest subr-string-chop-newline ()
+ (should (equal (string-chop-newline "foo\n") "foo"))
+ (should (equal (string-chop-newline "foo\nbar\n") "foo\nbar"))
+ (should (equal (string-chop-newline "foo\nbar") "foo\nbar")))
+
+(ert-deftest subr-ensure-empty-lines ()
+ (should
+ (equal
+ (with-temp-buffer
+ (insert "foo")
+ (goto-char (point-min))
+ (ensure-empty-lines 2)
+ (buffer-string))
+ "\n\nfoo"))
+ (should
+ (equal
+ (with-temp-buffer
+ (insert "foo")
+ (ensure-empty-lines 2)
+ (buffer-string))
+ "foo\n\n\n"))
+ (should
+ (equal
+ (with-temp-buffer
+ (insert "foo\n")
+ (ensure-empty-lines 2)
+ (buffer-string))
+ "foo\n\n\n"))
+ (should
+ (equal
+ (with-temp-buffer
+ (insert "foo\n\n\n\n\n")
+ (ensure-empty-lines 2)
+ (buffer-string))
+ "foo\n\n\n"))
+ (should
+ (equal
+ (with-temp-buffer
+ (insert "foo\n\n\n")
+ (ensure-empty-lines 0)
+ (buffer-string))
+ "foo\n")))
+
+(ert-deftest subr-x-test-add-display-text-property ()
+ (with-temp-buffer
+ (insert "Foo bar zot gazonk")
+ (add-display-text-property 4 8 'height 2.0)
+ (add-display-text-property 2 12 'raise 0.5)
+ (should (equal (get-text-property 2 'display) '(raise 0.5)))
+ (should (equal (get-text-property 5 'display)
+ '((raise 0.5) (height 2.0))))
+ (should (equal (get-text-property 9 'display) '(raise 0.5))))
+ (with-temp-buffer
+ (insert "Foo bar zot gazonk")
+ (put-text-property 4 8 'display [(height 2.0)])
+ (add-display-text-property 2 12 'raise 0.5)
+ (should (equal (get-text-property 2 'display) '(raise 0.5)))
+ (should (equal (get-text-property 5 'display)
+ [(raise 0.5) (height 2.0)]))
+ (should (equal (get-text-property 9 'display) '(raise 0.5)))))
+
+(ert-deftest subr-x-named-let ()
+ (let ((funs ()))
+ (named-let loop
+ ((rest '(1 42 3))
+ (sum 0))
+ (when rest
+ ;; Here, we make sure that the variables are distinct in every
+ ;; iteration, since a naive tail-call optimization would tend to end up
+ ;; with a single `sum' variable being shared by all the closures.
+ (push (lambda () sum) funs)
+ ;; Here we add a dummy `sum' variable which shadows the `sum' iteration
+ ;; variable since a naive tail-call optimization could also trip here
+ ;; thinking it can `(setq sum ...)' to set the iteration
+ ;; variable's value.
+ (let ((sum sum))
+ (loop (cdr rest) (+ sum (car rest))))))
+ (should (equal (mapcar #'funcall funs) '(43 1 0)))))
+
+(ert-deftest test-with-buffer-unmodified-if-unchanged ()
+ (with-temp-buffer
+ (with-buffer-unmodified-if-unchanged
+ (insert "t"))
+ (should (buffer-modified-p)))
+
+ (with-temp-buffer
+ (with-buffer-unmodified-if-unchanged
+ (insert "t")
+ (delete-char -1))
+ (should-not (buffer-modified-p)))
+
+ ;; Shouldn't error.
+ (should
+ (with-temp-buffer
+ (with-buffer-unmodified-if-unchanged
+ (insert "t")
+ (delete-char -1)
+ (kill-buffer))))
+
+ (with-temp-buffer
+ (let ((outer (current-buffer)))
+ (with-temp-buffer
+ (let ((inner (current-buffer)))
+ (with-buffer-unmodified-if-unchanged
+ (insert "t")
+ (delete-char -1)
+ (set-buffer outer))
+ (with-current-buffer inner
+ (should-not (buffer-modified-p))))))))
+
+(ert-deftest subr-x--hash-table-keys-and-values ()
+ (let ((h (make-hash-table)))
+ (puthash 'a 1 h)
+ (puthash 'c 3 h)
+ (puthash 'b 2 h)
+ (should (equal (sort (hash-table-keys h) #'string<) '(a b c)))
+ (should (equal (sort (hash-table-values h) #'<) '(1 2 3)))))
+
+(ert-deftest test-string-truncate-left ()
+ (should (equal (string-truncate-left "band" 3) "...d"))
+ (should (equal (string-truncate-left "band" 2) "...d"))
+ (should (equal (string-truncate-left "longstring" 8) "...tring")))
(provide 'subr-x-tests)
;;; subr-x-tests.el ends here
diff --git a/test/lisp/emacs-lisp/syntax-tests.el b/test/lisp/emacs-lisp/syntax-tests.el
new file mode 100644
index 00000000000..f266db5c702
--- /dev/null
+++ b/test/lisp/emacs-lisp/syntax-tests.el
@@ -0,0 +1,63 @@
+;;; syntax-tests.el --- tests for syntax.el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'syntax)
+
+(ert-deftest syntax-propertize--shift-groups-and-backrefs ()
+ "Test shifting of numbered groups and back-references in regexps."
+ ;; A numbered group must be shifted.
+ (should
+ (string=
+ (syntax-propertize--shift-groups-and-backrefs
+ "\\(?2:[abc]+\\)foobar" 2)
+ "\\(?4:[abc]+\\)foobar"))
+ ;; A back-reference \1 on a normal sub-regexp context must be
+ ;; shifted.
+ (should
+ (string=
+ (syntax-propertize--shift-groups-and-backrefs "\\(a\\)\\1" 2)
+ "\\(a\\)\\3"))
+ ;; Shifting must not happen if the \1 appears in a character class,
+ ;; or in a \{\} repetition construct (although \1 isn't valid there
+ ;; anyway).
+ (let ((rx-with-class "\\(a\\)[\\1-2]")
+ (rx-with-rep "\\(a\\)\\{1,\\1\\}"))
+ (should
+ (string=
+ (syntax-propertize--shift-groups-and-backrefs rx-with-class 2)
+ rx-with-class))
+ (should
+ (string=
+ (syntax-propertize--shift-groups-and-backrefs rx-with-rep 2)
+ rx-with-rep)))
+ ;; Now numbered groups and back-references in combination.
+ (should
+ (string=
+ (syntax-propertize--shift-groups-and-backrefs
+ "\\(?2:[abc]+\\)foo\\(\\2\\)" 2)
+ "\\(?4:[abc]+\\)foo\\(\\4\\)"))
+ ;; Emacs supports only the back-references \1,...,\9, so when a
+ ;; shift would result in \10 or more, an error must be signalled.
+ (should-error
+ (syntax-propertize--shift-groups-and-backrefs "\\(a\\)\\3" 7)))
+
+;;; syntax-tests.el ends here.
diff --git a/test/lisp/emacs-lisp/tabulated-list-test.el b/test/lisp/emacs-lisp/tabulated-list-tests.el
index 30a4f8f61b4..3ce4a63f4f0 100644
--- a/test/lisp/emacs-lisp/tabulated-list-test.el
+++ b/test/lisp/emacs-lisp/tabulated-list-tests.el
@@ -1,6 +1,6 @@
-;;; tabulated-list-test.el --- Tests for emacs-lisp/tabulated-list.el -*- lexical-binding: t; -*-
+;;; tabulated-list-tests.el --- Tests for emacs-lisp/tabulated-list.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2015-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2022 Free Software Foundation, Inc.
;; Author: Artur Malabarba <bruce.connor.am@gmail.com>
@@ -55,28 +55,37 @@
(ert-deftest tabulated-list-print ()
(tabulated-list--test-with-buffer
;; Basic printing.
- (should (string= (buffer-substring-no-properties (point-min) (point-max))
- " zzzz-game zzzz-game 2113 installed play zzzz in Emacs
+ (should (string-equal
+ (buffer-substring-no-properties (point-min) (point-max))
+ "\
+ zzzz-game zzzz-game 2113 installed play zzzz in Emacs
4clojure 4clojure 1507 obsolete Open and evaluate 4clojure.com questions
abc-mode abc-mode 944 available Major mode for editing abc music files
- mode mode 1128 installed A simple mode for editing Actionscript 3 files\n"))
+ mode mode 1128 installed A simple mode for editing Actionscript 3 files
+"))
;; Preserve position.
(forward-line 3)
(let ((pos (thing-at-point 'line)))
(pop tabulated-list-entries)
(tabulated-list-print t)
(should (equal (thing-at-point 'line) pos))
- (should (string= (buffer-substring-no-properties (point-min) (point-max))
- " 4clojure 4clojure 1507 obsolete Open and evaluate 4clojure.com questions
+ (should (string-equal
+ (buffer-substring-no-properties (point-min) (point-max))
+ "\
+ 4clojure 4clojure 1507 obsolete Open and evaluate 4clojure.com questions
abc-mode abc-mode 944 available Major mode for editing abc music files
- mode mode 1128 installed A simple mode for editing Actionscript 3 files\n"))
+ mode mode 1128 installed A simple mode for editing Actionscript 3 files
+"))
;; Check the UPDATE argument
(pop tabulated-list-entries)
(setf (cdr (car tabulated-list-entries)) (list ["x" "x" "944" "available" " XX"]))
(tabulated-list-print t t)
- (should (string= (buffer-substring-no-properties (point-min) (point-max))
- " x x 944 available XX
- mode mode 1128 installed A simple mode for editing Actionscript 3 files\n"))
+ (should (string-equal
+ (buffer-substring-no-properties (point-min) (point-max))
+ "\
+ x x 944 available XX
+ mode mode 1128 installed A simple mode for editing Actionscript 3 files
+"))
(should (equal (thing-at-point 'line) pos)))))
(ert-deftest tabulated-list-sort ()
@@ -86,25 +95,32 @@
(skip-chars-forward "[:blank:]")
(tabulated-list-sort)
(let ((text (buffer-substring-no-properties (point-min) (point-max))))
- (should (string= text " 4clojure 4clojure 1507 obsolete Open and evaluate 4clojure.com questions
+ (should (string-equal
+ text
+ "\
+ 4clojure 4clojure 1507 obsolete Open and evaluate 4clojure.com questions
abc-mode abc-mode 944 available Major mode for editing abc music files
mode mode 1128 installed A simple mode for editing Actionscript 3 files
- zzzz-game zzzz-game 2113 installed play zzzz in Emacs\n"))
+ zzzz-game zzzz-game 2113 installed play zzzz in Emacs
+"))
(skip-chars-forward "^[:blank:]")
(skip-chars-forward "[:blank:]")
(should (equal (get-text-property (point) 'tabulated-list-column-name)
"name-2"))
(tabulated-list-sort)
- ;; Check a `t' as the sorting predicate.
+ ;; Check a t as the sorting predicate.
(should (string= text (buffer-substring-no-properties (point-min) (point-max))))
;; Invert.
(tabulated-list-sort 1)
- (should (string= (buffer-substring-no-properties (point-min) (point-max))
- " zzzz-game zzzz-game 2113 installed play zzzz in Emacs
+ (should (string-equal
+ (buffer-substring-no-properties (point-min) (point-max))
+ "\
+ zzzz-game zzzz-game 2113 installed play zzzz in Emacs
mode mode 1128 installed A simple mode for editing Actionscript 3 files
abc-mode abc-mode 944 available Major mode for editing abc music files
- 4clojure 4clojure 1507 obsolete Open and evaluate 4clojure.com questions\n"))
+ 4clojure 4clojure 1507 obsolete Open and evaluate 4clojure.com questions
+"))
;; Again
(tabulated-list-sort 1)
(should (string= text (buffer-substring-no-properties (point-min) (point-max)))))
@@ -114,5 +130,4 @@
(should-error (tabulated-list-sort) :type 'user-error)
(should-error (tabulated-list-sort 4) :type 'user-error)))
-(provide 'tabulated-list-test)
-;;; tabulated-list-test.el ends here
+;;; tabulated-list-tests.el ends here
diff --git a/test/lisp/emacs-lisp/testcover-resources/testcases.el b/test/lisp/emacs-lisp/testcover-resources/testcases.el
index edb539f4c27..46040be1a6c 100644
--- a/test/lisp/emacs-lisp/testcover-resources/testcases.el
+++ b/test/lisp/emacs-lisp/testcover-resources/testcases.el
@@ -1,23 +1,23 @@
;;;; testcases.el -- Test cases for testcover-tests.el
-;; Copyright (C) 2017 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2022 Free Software Foundation, Inc.
;; Author: Gemini Lasswell
;; This file is part of GNU Emacs.
-;; This program is free software: you can redistribute it and/or
-;; modify it under the terms of the GNU General Public License as
-;; published by the Free Software Foundation, either version 3 of the
-;; License, or (at your option) any later version.
-;;
-;; This program is distributed in the hope that it will be useful, but
-;; WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-;; General Public License for more details.
-;;
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
;; You should have received a copy of the GNU General Public License
-;; along with this program. If not, see `https://www.gnu.org/licenses/'.
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
@@ -53,7 +53,6 @@
;; ==== constants-bug-25316 ====
"Testcover doesn't splotch constants."
-:expected-result :failed
;; ====
(defconst testcover-testcase-const "apples")
(defun testcover-testcase-zero () 0)
@@ -76,15 +75,14 @@
;; ==== customize-defcustom-bug-25326 ====
"Testcover doesn't prevent testing of defcustom values."
-:expected-result :failed
;; ====
(defgroup testcover-testcase nil
- "Test case for testcover"
+ "Test case for testcover."
:group 'lisp
:prefix "testcover-testcase-"
:version "26.0")
(defcustom testcover-testcase-flag t
- "Test value used by testcover-tests.el"
+ "Test value used by testcover-tests.el."
:type 'boolean
:group 'testcover-testcase)
(defun testcover-testcase-get-flag ()
@@ -113,7 +111,7 @@
"Wrapping a form with noreturn prevents splotching."
;; ====
(defun testcover-testcase-cancel (spacecraft)
- (error "no destination for %s" spacecraft))
+ (error "No destination for %s" spacecraft))
(defun testcover-testcase-launch (spacecraft planet)
(if (null planet)
(noreturn (testcover-testcase-cancel spacecraft%%%))
@@ -135,7 +133,6 @@
;; ==== 1-value-symbol-bug-25316 ====
"Wrapping a form with 1value prevents splotching."
-:expected-result :failed
;; ====
(defun testcover-testcase-always-zero (num)
(- num%%% num%%%)%%%)
@@ -223,14 +220,13 @@
(defun testcover-testcase-cc (arg)
(condition-case nil
(if (null arg%%%)%%%
- (error "foo")
+ (error "Foo")
"0")!!!
(error nil)))
(should-not (testcover-testcase-cc nil))
;; ==== quotes-within-backquotes-bug-25316 ====
-"Forms to instrument are found within quotes within backquotes."
-:expected-result :failed
+"Forms to analyze are found within quotes within backquotes."
;; ====
(defun testcover-testcase-make-list ()
(list 'defun 'defvar))
@@ -296,7 +292,6 @@
;; ==== backquote-1value-bug-24509 ====
"Commas within backquotes are recognized as non-1value."
-:expected-result :failed
;; ====
(defmacro testcover-testcase-lambda (&rest body)
`(lambda () ,@body))
@@ -320,7 +315,6 @@
;; ==== pcase-bug-24688 ====
"Testcover copes with condition-case within backquoted list."
-:expected-result :failed
;; ====
(defun testcover-testcase-pcase (form)
(pcase form%%%
@@ -335,7 +329,6 @@
;; ==== defun-in-backquote-bug-11307-and-24743 ====
"Testcover handles defun forms within backquoted list."
-:expected-result :failed
;; ====
(defmacro testcover-testcase-defun (name &rest body)
(declare (debug (symbolp def-body)))
@@ -348,7 +341,6 @@
;; ==== closure-1value-bug ====
"Testcover does not mark closures as 1value."
-:expected-result :failed
;; ====
;; -*- lexical-binding:t -*-
(setq testcover-testcase-foo nil)
@@ -365,7 +357,6 @@
;; ==== by-value-vs-by-reference-bug-25351 ====
"An object created by a 1value expression may be modified by other code."
-:expected-result :failed
;; ====
(defun testcover-testcase-ab ()
(list 'a 'b))
@@ -386,7 +377,7 @@
(should-error (testcover-testcase-thing 3))
;; ==== dotted-backquote ====
-"Testcover correctly instruments dotted backquoted lists."
+"Testcover can analyze code inside dotted backquoted lists."
;; ====
(defun testcover-testcase-dotted-bq (flag extras)
(let* ((bq
@@ -396,9 +387,16 @@
(should (equal '(a b c) (testcover-testcase-dotted-bq nil '(d e))))
(should (equal '(a b c d e) (testcover-testcase-dotted-bq t '(d e))))
+;; ==== quoted-backquote ====
+"Testcover correctly handles the quoted backquote symbol."
+;; ====
+(defun testcover-testcase-special-symbols ()
+ (list '\` '\, '\,@))
+
+(should (equal '(\` \, \,@) (testcover-testcase-special-symbols)))
+
;; ==== backquoted-vector-bug-25316 ====
-"Testcover reinstruments within backquoted vectors."
-:expected-result :failed
+"Testcover can analyze code within backquoted vectors."
;; ====
(defun testcover-testcase-vec (a b c)
`[,a%%% ,(list b%%% c%%%)%%%]%%%)
@@ -413,14 +411,20 @@
(should (equal '([[4 5] 6]) (testcover-testcase-vec-in-list 4 5 6)))
(should (equal '([100]) (testcover-testcase-vec-arg 100)))
+;; ==== dotted-list-in-vector-bug-30909 ====
+"Testcover can analyze dotted pairs within vectors."
+;; ====
+(defun testcover-testcase-vectors-with-dotted-pairs ()
+ (equal [(1 . "x")] [(1 2 . "y")])%%%)
+(should-not (testcover-testcase-vectors-with-dotted-pairs))
+
;; ==== vector-in-macro-spec-bug-25316 ====
-"Testcover reinstruments within vectors."
-:expected-result :failed
+"Testcover can analyze code inside vectors."
;; ====
(defmacro testcover-testcase-nth-case (arg vec)
(declare (indent 1)
(debug (form (vector &rest form))))
- `(eval (aref ,vec%%% ,arg%%%))%%%)
+ `(eval (aref ,vec%%% ,arg%%%) t)%%%)
(defun testcover-testcase-use-nth-case (choice val)
(testcover-testcase-nth-case choice
@@ -435,7 +439,6 @@
;; ==== mapcar-is-not-compose ====
"Mapcar with 1value arguments is not 1value."
-:expected-result :failed
;; ====
(defvar testcover-testcase-num 0)
(defun testcover-testcase-add-num (n)
@@ -450,10 +453,10 @@
;; ==== function-with-edebug-spec-bug-25316 ====
"Functions can have edebug specs too.
-See c-make-font-lock-search-function for an example in the Emacs
-sources. The other issue is that it's ok to use quote in an
-edebug spec, so testcover needs to cope with that."
-:expected-result :failed
+See `c-make-font-lock-search-function' for an example in the
+Emacs sources. `c-make-font-lock-search-function''s Edebug spec
+also contains a quote. See comment in `testcover-analyze-coverage'
+regarding the odd-looking coverage result for the quoted form."
;; ====
(defun testcover-testcase-make-function (forms)
`(lambda (flag) (if flag 0 ,@forms%%%))%%%)
@@ -462,7 +465,7 @@ edebug spec, so testcover needs to cope with that."
(("quote" (&rest def-form))))
(defun testcover-testcase-thing ()
- (testcover-testcase-make-function '((+ 1 (+ 2 (+ 3 (+ 4 5))))))%%%)
+ (testcover-testcase-make-function '(!!!(+ 1 !!!(+ 2 !!!(+ 3 !!!(+ 4 5)%%%)%%%)%%%)%%%))%%%)
(defun testcover-testcase-use-thing ()
(funcall (testcover-testcase-thing)%%% nil)%%%)
@@ -470,7 +473,7 @@ edebug spec, so testcover needs to cope with that."
(should (equal (testcover-testcase-use-thing) 15))
;; ==== backquoted-dotted-alist ====
-"Testcover can instrument a dotted alist constructed with backquote."
+"Testcover can analyze a dotted alist constructed with backquote."
;; ====
(defun testcover-testcase-make-alist (expr entries)
`((0 . ,expr%%%) . ,entries%%%)%%%)
@@ -480,7 +483,6 @@ edebug spec, so testcover needs to cope with that."
;; ==== coverage-of-the-unknown-symbol-bug-25471 ====
"Testcover correctly records coverage of code which uses `unknown'"
-:expected-result :failed
;; ====
(defun testcover-testcase-how-do-i-know-you (name)
(let ((val 'unknown))
@@ -494,10 +496,18 @@ edebug spec, so testcover needs to cope with that."
"Testcover captures and ignores circular list errors."
;; ====
(defun testcover-testcase-cyc1 (a)
- (let ((ls (make-list 10 a%%%)))
- (nconc ls ls)
- ls))
+ (let ((ls (make-list 10 a%%%)%%%))
+ (nconc ls%%% ls%%%)
+ ls)) ; The lack of a mark here is due to an ignored circular list error.
(testcover-testcase-cyc1 1)
(testcover-testcase-cyc1 1)
-
-;; testcases.el ends here.
+(defun testcover-testcase-cyc2 (a b)
+ (let ((ls1 (make-list 10 a%%%)%%%)
+ (ls2 (make-list 10 b)))
+ (nconc ls2 ls2)
+ (nconc ls1%%% ls2)
+ ls1))
+(testcover-testcase-cyc2 1 2)
+(testcover-testcase-cyc2 1 4)
+
+;;; testcases.el ends here
diff --git a/test/lisp/emacs-lisp/testcover-tests.el b/test/lisp/emacs-lisp/testcover-tests.el
index 0f0ee9a5095..39cd3175c26 100644
--- a/test/lisp/emacs-lisp/testcover-tests.el
+++ b/test/lisp/emacs-lisp/testcover-tests.el
@@ -1,23 +1,23 @@
;;; testcover-tests.el --- Testcover test suite -*- lexical-binding:t -*-
-;; Copyright (C) 2017 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2022 Free Software Foundation, Inc.
;; Author: Gemini Lasswell
;; This file is part of GNU Emacs.
-;; This program is free software: you can redistribute it and/or
-;; modify it under the terms of the GNU General Public License as
-;; published by the Free Software Foundation, either version 3 of the
-;; License, or (at your option) any later version.
-;;
-;; This program is distributed in the hope that it will be useful, but
-;; WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-;; General Public License for more details.
-;;
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
;; You should have received a copy of the GNU General Public License
-;; along with this program. If not, see `https://www.gnu.org/licenses/'.
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
@@ -31,26 +31,10 @@
;;; Code:
(require 'ert)
+(require 'ert-x)
(require 'testcover)
(require 'skeleton)
-;; Use `eval-and-compile' around all these definitions because they're
-;; used by the macro `testcover-tests-define-tests'.
-
-(eval-and-compile
- (defvar testcover-tests-file-dir
- (expand-file-name
- "testcover-resources/"
- (file-name-directory (or (bound-and-true-p byte-compile-current-file)
- load-file-name
- buffer-file-name)))
- "Directory of the \"testcover-tests.el\" file."))
-
-(eval-and-compile
- (defvar testcover-tests-test-cases
- (expand-file-name "testcases.el" testcover-tests-file-dir)
- "File containing marked up code to instrument and check."))
-
;; Convert Testcover's overlays to plain text.
(eval-and-compile
@@ -61,33 +45,34 @@ testcases.el. This can be used to create test cases if Testcover
is working correctly on a code sample. OPTARGS are optional
arguments for `testcover-start'."
(interactive "r")
- (let ((tempfile (make-temp-file "testcover-tests-" nil ".el"))
- (code (buffer-substring beg end))
- (marked-up-code))
- (unwind-protect
- (progn
- (with-temp-file tempfile
- (insert code))
- (save-current-buffer
- (let ((buf (find-file-noselect tempfile)))
- (set-buffer buf)
- (apply 'testcover-start (cons tempfile optargs))
- (testcover-mark-all buf)
- (dolist (overlay (overlays-in (point-min) (point-max)))
- (let ((ov-face (overlay-get overlay 'face)))
- (goto-char (overlay-end overlay))
- (cond
- ((eq ov-face 'testcover-nohits) (insert "!!!"))
- ((eq ov-face 'testcover-1value) (insert "%%%"))
- (t nil))))
- (setq marked-up-code (buffer-string)))
- (set-buffer-modified-p nil)))
- (ignore-errors (kill-buffer (find-file-noselect tempfile)))
- (ignore-errors (delete-file tempfile)))
-
- ;; Now replace the original code with the marked up code.
- (delete-region beg end)
- (insert marked-up-code))))
+ (ert-with-temp-file tempfile
+ :suffix ".el"
+ (let ((find-file-suppress-same-file-warnings t)
+ (code (buffer-substring beg end))
+ (marked-up-code))
+ (unwind-protect
+ (progn
+ (with-temp-file tempfile
+ (insert code))
+ (save-current-buffer
+ (let ((buf (find-file-noselect tempfile)))
+ (set-buffer buf)
+ (apply 'testcover-start (cons tempfile optargs))
+ (testcover-mark-all buf)
+ (dolist (overlay (overlays-in (point-min) (point-max)))
+ (let ((ov-face (overlay-get overlay 'face)))
+ (goto-char (overlay-end overlay))
+ (cond
+ ((eq ov-face 'testcover-nohits) (insert "!!!"))
+ ((eq ov-face 'testcover-1value) (insert "%%%"))
+ (t nil))))
+ (setq marked-up-code (buffer-string)))
+ (set-buffer-modified-p nil)))
+ (ignore-errors (kill-buffer (find-file-noselect tempfile))))
+
+ ;; Now replace the original code with the marked up code.
+ (delete-region beg end)
+ (insert marked-up-code)))))
(eval-and-compile
(defun testcover-tests-unmarkup-region (beg end)
@@ -114,33 +99,32 @@ arguments for `testcover-start'."
(eval-and-compile
(defun testcover-tests-run-test-case (marked-up-code)
"Test the operation of Testcover on the string MARKED-UP-CODE."
- (let ((tempfile (make-temp-file "testcover-tests-" nil ".el")))
- (unwind-protect
- (progn
- (with-temp-file tempfile
- (insert marked-up-code))
- ;; Remove the marks and mark the code up again. The original
- ;; and recreated versions should match.
- (save-current-buffer
- (set-buffer (find-file-noselect tempfile))
- ;; Fail the test if the debugger tries to become active,
- ;; which will happen if Testcover's reinstrumentation
- ;; leaves an edebug-enter in the code. This will also
- ;; prevent debugging these tests using Edebug.
- (cl-letf (((symbol-function #'edebug-enter)
- (lambda (&rest _args)
- (ert-fail
- (concat "Debugger invoked during test run "
- "(possible edebug-enter not replaced)")))))
- (dolist (byte-compile '(t nil))
- (testcover-tests-unmarkup-region (point-min) (point-max))
- (unwind-protect
- (testcover-tests-markup-region (point-min) (point-max) byte-compile)
- (set-buffer-modified-p nil))
- (should (string= marked-up-code
- (buffer-string)))))))
- (ignore-errors (kill-buffer (find-file-noselect tempfile)))
- (ignore-errors (delete-file tempfile))))))
+ (ert-with-temp-file tempfile
+ :suffix ".el"
+ (let ((find-file-suppress-same-file-warnings t))
+ (unwind-protect
+ (progn
+ (with-temp-file tempfile
+ (insert marked-up-code))
+ ;; Remove the marks and mark the code up again. The original
+ ;; and recreated versions should match.
+ (save-current-buffer
+ (set-buffer (find-file-noselect tempfile))
+ ;; Fail the test if the debugger tries to become active,
+ ;; which can happen if Testcover fails to attach itself
+ ;; correctly. Note that this will prevent debugging
+ ;; these tests using Edebug.
+ (cl-letf (((symbol-function #'edebug-default-enter)
+ (lambda (&rest _args)
+ (ert-fail "Debugger invoked during test run"))))
+ (dolist (byte-compile '(t nil))
+ (testcover-tests-unmarkup-region (point-min) (point-max))
+ (unwind-protect
+ (testcover-tests-markup-region (point-min) (point-max) byte-compile)
+ (set-buffer-modified-p nil))
+ (should (string= marked-up-code
+ (buffer-string)))))))
+ (ignore-errors (kill-buffer (find-file-noselect tempfile))))))))
;; Convert test case file to ert-defmethod.
@@ -151,7 +135,7 @@ Construct and return a list of `ert-deftest' forms. See testcases.el
for documentation of the test definition format."
(let (results)
(with-temp-buffer
- (insert-file-contents testcover-tests-test-cases)
+ (insert-file-contents (ert-resource-file "testcases.el"))
(goto-char (point-min))
(while (re-search-forward
(concat "^;; ==== \\([^ ]+?\\) ====\n"
diff --git a/test/lisp/emacs-lisp/text-property-search-tests.el b/test/lisp/emacs-lisp/text-property-search-tests.el
new file mode 100644
index 00000000000..98fdd55e85f
--- /dev/null
+++ b/test/lisp/emacs-lisp/text-property-search-tests.el
@@ -0,0 +1,175 @@
+;;; text-property-search-tests.el --- Testing text-property-search -*- lexical-binding:t -*-
+
+;; Copyright (C) 2018-2022 Free Software Foundation, Inc.
+
+;; Author: Lars Ingebrigtsen <larsi@gnus.org>
+;; Keywords:
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;
+
+;;; Code:
+
+(require 'ert)
+(require 'text-property-search)
+(require 'cl-lib)
+
+(defun text-property-setup ()
+ (insert "This is "
+ (propertize "bold1" 'face 'bold)
+ " and this is "
+ (propertize "italic1" 'face 'italic)
+ (propertize "bold2" 'face 'bold)
+ (propertize "italic2" 'face 'italic)
+ " at the end")
+ (goto-char (point-min)))
+
+(defmacro with-test (form result &optional point)
+ `(with-temp-buffer
+ (text-property-setup)
+ (when ,point
+ (goto-char ,point))
+ (should
+ (equal
+ (cl-loop for match = ,form
+ while match
+ collect (buffer-substring (prop-match-beginning match)
+ (prop-match-end match)))
+ ,result))))
+
+(ert-deftest text-property-search-forward-bold-t ()
+ (with-test (text-property-search-forward 'face 'bold t)
+ '("bold1" "bold2")))
+
+(ert-deftest text-property-search-forward-bold-nil ()
+ (with-test (text-property-search-forward 'face 'bold nil)
+ '("This is " " and this is italic1" "italic2 at the end")))
+
+(ert-deftest text-property-search-forward-nil-t ()
+ (with-test (text-property-search-forward 'face nil t)
+ '("This is " " and this is " " at the end")))
+
+(ert-deftest text-property-search-forward-nil-nil ()
+ (with-test (text-property-search-forward 'face nil nil)
+ '("bold1" "italic1" "bold2" "italic2")))
+
+(ert-deftest text-property-search-forward-partial-bold-t ()
+ (with-test (text-property-search-forward 'face 'bold t)
+ '("old1" "bold2")
+ 10))
+
+(ert-deftest text-property-search-forward-partial-non-current-bold-t ()
+ (with-test (text-property-search-forward 'face 'bold t t)
+ '("bold2")
+ 10))
+
+
+(ert-deftest text-property-search-backward-bold-t ()
+ (with-test (text-property-search-backward 'face 'bold t)
+ '("bold2" "bold1")
+ (point-max)))
+
+(ert-deftest text-property-search-backward-bold-nil ()
+ (with-test (text-property-search-backward 'face 'bold nil)
+ '( "italic2 at the end" " and this is italic1" "This is ")
+ (point-max)))
+
+(ert-deftest text-property-search-backward-nil-t ()
+ (with-test (text-property-search-backward 'face nil t)
+ '(" at the end" " and this is " "This is ")
+ (point-max)))
+
+(ert-deftest text-property-search-backward-nil-nil ()
+ (with-test (text-property-search-backward 'face nil nil)
+ '("italic2" "bold2" "italic1" "bold1")
+ (point-max)))
+
+(ert-deftest text-property-search-backward-partial-bold-t ()
+ (with-test (text-property-search-backward 'face 'bold t)
+ '("b" "bold1")
+ 35))
+
+(ert-deftest text-property-search-backward-partial-non-current-bold-t ()
+ (with-test (text-property-search-backward 'face 'bold t t)
+ '("bold1")
+ 35))
+
+(defmacro with-match-test (form beginning end value &optional point)
+ `(with-temp-buffer
+ (text-property-setup)
+ (when ,point
+ (goto-char ,point))
+ (should (equal ,form
+ (make-prop-match :beginning ,beginning
+ :end ,end
+ :value ,value)))))
+
+(ert-deftest text-property-search-forward-prop-match-match-face-nil-nil ()
+ (with-match-test
+ (text-property-search-forward 'face nil nil)
+ 9 14 'bold))
+
+(ert-deftest text-property-search-forward-prop-match-match-face-bold-t ()
+ (with-match-test
+ (text-property-search-forward 'face 'bold t)
+ 9 14 'bold))
+
+(ert-deftest text-property-search-forward-prop-match-match-face-bold-nil ()
+ (with-match-test
+ (text-property-search-forward 'face 'bold nil)
+ 1 9 nil))
+
+(ert-deftest text-property-search-backward-prop-match-match-face-nil-nil ()
+ (with-match-test
+ (text-property-search-backward 'face nil nil)
+ 39 46 'italic
+ (point-max)))
+
+(ert-deftest text-property-search-backward-prop-match-match-face-italic-t ()
+ (with-match-test
+ (text-property-search-backward 'face 'italic t)
+ 39 46 'italic
+ (point-max)))
+
+(ert-deftest text-property-search-backward-prop-match-match-face-italic-nil ()
+ (with-match-test
+ (text-property-search-backward 'face 'italic nil)
+ 46 57 nil
+ (point-max)))
+
+
+;;;; Position after search.
+
+(ert-deftest text-property-search-forward/point-at-beginning ()
+ (with-temp-buffer
+ (insert (concat "1234" (propertize "567" 'x t) "890"))
+ (goto-char (point-min))
+ (text-property-search-forward 'x t)
+ (should (= (point) 5))))
+
+(ert-deftest text-property-search-backward/point-at-end ()
+ (with-temp-buffer
+ (insert (concat "1234" (propertize "567" 'x t) "890"))
+ (goto-char (point-max))
+ (text-property-search-backward 'x t)
+ (should (= (point) 8))))
+
+(provide 'text-property-search-tests)
+
+;;; text-property-search-tests.el ends here
diff --git a/test/lisp/emacs-lisp/thunk-tests.el b/test/lisp/emacs-lisp/thunk-tests.el
index 973a14b8180..f593737fd22 100644
--- a/test/lisp/emacs-lisp/thunk-tests.el
+++ b/test/lisp/emacs-lisp/thunk-tests.el
@@ -1,6 +1,6 @@
;;; thunk-tests.el --- Tests for thunk.el -*- lexical-binding: t -*-
-;; Copyright (C) 2015-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2022 Free Software Foundation, Inc.
;; Author: Nicolas Petton <nicolas@petton.fr>
;; Maintainer: emacs-devel@gnu.org
@@ -51,5 +51,55 @@
(thunk-force thunk)
(should (= x 1))))
+
+
+;; thunk-let tests
+
+(ert-deftest thunk-let-basic-test ()
+ "Test whether bindings are established."
+ (should (equal (thunk-let ((x 1) (y 2)) (+ x y)) 3)))
+
+(ert-deftest thunk-let*-basic-test ()
+ "Test whether bindings are established."
+ (should (equal (thunk-let* ((x 1) (y (+ 1 x))) (+ x y)) 3)))
+
+(ert-deftest thunk-let-bound-vars-cant-be-set-test ()
+ "Test whether setting a `thunk-let' bound variable fails."
+ (should-error
+ (eval '(thunk-let ((x 1)) (let ((y 7)) (setq x (+ x y)) (* 10 x))) t)))
+
+(ert-deftest thunk-let-laziness-test ()
+ "Test laziness of `thunk-let'."
+ (should
+ (equal (let ((x-evalled nil)
+ (y-evalled nil))
+ (thunk-let ((x (progn (setq x-evalled t) (+ 1 2)))
+ (y (progn (setq y-evalled t) (+ 3 4))))
+ (let ((evalled-y y))
+ (list x-evalled y-evalled evalled-y))))
+ (list nil t 7))))
+
+(ert-deftest thunk-let*-laziness-test ()
+ "Test laziness of `thunk-let*'."
+ (should
+ (equal (let ((x-evalled nil)
+ (y-evalled nil)
+ (z-evalled nil)
+ (a-evalled nil))
+ (thunk-let* ((x (progn (setq x-evalled t) (+ 1 1)))
+ (y (progn (setq y-evalled t) (+ x 1)))
+ (z (progn (setq z-evalled t) (+ y 1)))
+ (a (progn (setq a-evalled t) (+ z 1))))
+ (let ((evalled-z z))
+ (list x-evalled y-evalled z-evalled a-evalled evalled-z))))
+ (list t t t nil 4))))
+
+(ert-deftest thunk-let-bad-binding-test ()
+ "Test whether a bad binding causes an error when expanding."
+ (should-error (macroexpand '(thunk-let ((x 1 1)) x)))
+ (should-error (macroexpand '(thunk-let (27) x)))
+ (should-error (macroexpand '(thunk-let x x))))
+
+
(provide 'thunk-tests)
;;; thunk-tests.el ends here
diff --git a/test/lisp/emacs-lisp/timer-tests.el b/test/lisp/emacs-lisp/timer-tests.el
index 916625cac3a..4d974cfd9d7 100644
--- a/test/lisp/emacs-lisp/timer-tests.el
+++ b/test/lisp/emacs-lisp/timer-tests.el
@@ -1,6 +1,6 @@
;;; timer-tests.el --- tests for timers -*- lexical-binding:t -*-
-;; Copyright (C) 2013-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2022 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -36,7 +36,33 @@
(ert-deftest timer-tests-debug-timer-check ()
;; This function exists only if --enable-checking.
- (if (fboundp 'debug-timer-check)
- (should (debug-timer-check)) t))
+ (skip-unless (fboundp 'debug-timer-check))
+ (when (fboundp 'debug-timer-check) ; silence byte-compiler
+ (should (debug-timer-check))))
+
+(ert-deftest timer-test-multiple-of-time ()
+ (should (time-equal-p
+ (timer-next-integral-multiple-of-time '(0 0 0 1) (1+ (ash 1 53)))
+ (list (ash 1 (- 53 16)) 1))))
+
+(ert-deftest timer-next-integral-multiple-of-time-2 ()
+ "Test bug#33071."
+ (let* ((tc (current-time))
+ (delta-ticks 1000)
+ (hz 128000)
+ (tce (time-convert tc hz))
+ (tc+delta (time-add tce (cons delta-ticks hz)))
+ (tc+deltae (time-convert tc+delta hz))
+ (tc+delta-ticks (car tc+deltae))
+ (tc-nexte (cons (- tc+delta-ticks (% tc+delta-ticks delta-ticks)) hz))
+ (nt (timer-next-integral-multiple-of-time
+ tc (/ (float delta-ticks) hz)))
+ (nte (time-convert nt hz)))
+ (should (equal tc-nexte nte))))
+
+(ert-deftest timer-next-integral-multiple-of-time-3 ()
+ "Test bug#33071."
+ (let ((nt (timer-next-integral-multiple-of-time '(32770 . 65539) 0.5)))
+ (should (time-equal-p 1 nt))))
;;; timer-tests.el ends here
diff --git a/test/lisp/emacs-lisp/unsafep-tests.el b/test/lisp/emacs-lisp/unsafep-tests.el
new file mode 100644
index 00000000000..fdd82b4fc3d
--- /dev/null
+++ b/test/lisp/emacs-lisp/unsafep-tests.el
@@ -0,0 +1,154 @@
+;;; unsafep-tests.el --- tests for unsafep.el -*- lexical-binding: t; -*-
+
+;; Author: Jonathan Yavner <jyavner@member.fsf.org>
+
+;; Copyright (C) 2002-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'unsafep)
+
+(defvar safe-functions)
+
+;;; These forms are all considered safe
+(defconst unsafep-tests--safe
+ '(((lambda (x) (* x 2)) 14)
+ (apply 'cdr (mapcar (lambda (x) (car x)) y))
+ (cond ((= x 4) 5) (t 27))
+ (condition-case x (car y) (error (car x)))
+ (let (x) (dolist (y '(1 2 3) (1+ y)) (push y x)))
+ (let (x) (apply (lambda (x) (* x 2)) 14))
+ (let ((x '(2))) (push 1 x) (pop x) (add-to-list 'x 2))
+ (let ((x 1) (y 2)) (setq x (+ x y)))
+ (let ((x 1)) (let ((y (+ x 3))) (* x y)))
+ (let* nil (current-time))
+ (let* ((x 1) (y (+ x 3))) (* x y))
+ (mapcar (lambda (x &optional y &rest z) (setq y (+ x 2)) (* y 3)) '(1 2 3))
+ (mapconcat #'(lambda (var) (propertize var 'face 'bold)) '("1" "2") ", ")
+ (setq buffer-display-count 14 mark-active t)
+ ;;This is not safe if you insert it into a buffer!
+ (propertize "x" 'display '(height (progn (delete-file "x") 1))))
+ "List of forms that `unsafep' should decide are safe.")
+
+;;; These forms are considered unsafe
+(defconst unsafep-tests--unsafe
+ '(( (add-to-list x y)
+ . (unquoted x))
+ ( (add-to-list y x)
+ . (unquoted y))
+ ( (add-to-list 'y x)
+ . (global-variable y))
+ ( (not (delete-file "unsafep.el"))
+ . (function delete-file))
+ ( (cond (t (aset local-abbrev-table 0 0)))
+ . (function aset))
+ ( (cond (t (setq unsafep-vars "")))
+ . (risky-local-variable unsafep-vars))
+ ( (condition-case format-alist 1)
+ . (risky-local-variable format-alist))
+ ( (condition-case x 1 (error (setq format-alist "")))
+ . (risky-local-variable format-alist))
+ ( (dolist (x (sort globalvar 'car)) (princ x))
+ . (function sort))
+ ( (dotimes (x 14) (delete-file "x"))
+ . (function delete-file))
+ ( (let ((post-command-hook "/tmp/")) 1)
+ . (risky-local-variable post-command-hook))
+ ( (let ((x (delete-file "x"))) 2)
+ . (function delete-file))
+ ( (let (x) (add-to-list 'x (delete-file "x")))
+ . (function delete-file))
+ ( (let (x) (condition-case y (setq x 1 z 2)))
+ . (global-variable z))
+ ( (let (x) (condition-case z 1 (error (delete-file "x"))))
+ . (function delete-file))
+ ( (let (x) (mapc (lambda (x) (setcar x 1)) '((1 . 2) (3 . 4))))
+ . (function setcar))
+ ( (let (y) (push (delete-file "x") y))
+ . (function delete-file))
+ ( (let* ((x 1)) (setq y 14))
+ . (global-variable y))
+ ( (mapc 'car (list '(1 . 2) (cons 3 4) (kill-buffer "unsafep.el")))
+ . (function kill-buffer))
+ ( (mapcar x y)
+ . (unquoted x))
+ ( (mapcar (lambda (x) (rename-file x "x")) '("unsafep.el"))
+ . (function rename-file))
+ ( (mapconcat x1 x2 " ")
+ . (unquoted x1))
+ ( (pop format-alist)
+ . (risky-local-variable format-alist))
+ ( (push 1 format-alist)
+ . (risky-local-variable format-alist))
+ ( (setq buffer-display-count (delete-file "x"))
+ . (function delete-file))
+ ;;These are actually safe (they signal errors)
+ ( (apply '(x) '(1 2 3))
+ . (function (x)))
+ ( (let (((x))) 1)
+ . (variable (x)))
+ ( (let (1) 2)
+ . (variable 1))
+ ( (error "Asdf")
+ . #'error)
+ ( (signal 'error "asdf")
+ . #'signal)
+ ( (throw 'asdf)
+ . #'throw)
+ ( (catch 'asdf 17)
+ . #'catch)
+ ( (play-sound-file "asdf")
+ . #'play-sound-file)
+ ( (replace-regexp-in-string "a" "b")
+ . #'replace-regexp-in-string)
+ )
+ "A-list of (FORM . REASON)... that `unsafep' should decide are unsafe.")
+
+(ert-deftest test-unsafep/safe ()
+ "Check safe forms with safe-functions nil."
+ (let (safe-functions)
+ (dolist (x unsafep-tests--safe)
+ (should-not (unsafep x)))))
+
+(ert-deftest test-unsafep/message ()
+ "Check that message is considered unsafe."
+ (should (unsafep '(dolist (x y) (message "here: %s" x))))
+ (should (unsafep '(dotimes (x 14 (* x 2)) (message "here: %d" x)))))
+
+(ert-deftest test-unsafep/unsafe ()
+ "Check unsafe forms with safe-functions nil."
+ (let (safe-functions)
+ (dolist (x unsafep-tests--unsafe)
+ (should (equal (unsafep (car x)) (cdr x))))))
+
+(ert-deftest test-unsafep/safe-functions-t ()
+ "safe-functions=t should allow delete-file"
+ (let ((safe-functions t))
+ (should-not (unsafep '(delete-file "x")))
+ (should-not (unsafep-function 'delete-file))))
+
+(ert-deftest test-unsafep/safe-functions-setcar ()
+ "safe-functions=(setcar) should allow setcar but not setcdr"
+ (let ((safe-functions '(setcar)))
+ (should-not (unsafep '(setcar x 1)))
+ (should (unsafep '(setcdr x 1)))))
+
+(provide 'unsafep-tests)
+
+;;; unsafep-tests.el ends here
diff --git a/test/lisp/emacs-lisp/vtable-tests.el b/test/lisp/emacs-lisp/vtable-tests.el
new file mode 100644
index 00000000000..627d9f9c5df
--- /dev/null
+++ b/test/lisp/emacs-lisp/vtable-tests.el
@@ -0,0 +1,42 @@
+;;; vtable-tests.el --- Tests for vtable.el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;
+
+;;; Code:
+
+(require 'vtable)
+(require 'ert)
+(require 'ert-x)
+
+(ert-deftest test-vstable-compute-columns ()
+ (should
+ (equal (mapcar
+ (lambda (column)
+ (vtable-column-align column))
+ (vtable--compute-columns
+ (make-vtable :columns '("a" "b" "c")
+ :objects '(("foo" 1 2)
+ ("bar" 3 :zot))
+ :insert nil)))
+ '(left right left))))
+
+;;; vtable-tests.el ends here
diff --git a/test/lisp/emacs-lisp/warnings-tests.el b/test/lisp/emacs-lisp/warnings-tests.el
new file mode 100644
index 00000000000..3b12092505d
--- /dev/null
+++ b/test/lisp/emacs-lisp/warnings-tests.el
@@ -0,0 +1,60 @@
+;;; warnings-tests.el --- tests for warnings.el -*- lexical-binding: t; -*-
+
+;; Author: Stefan Kangas <stefankangas@gmail.com>
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'warnings)
+
+(ert-deftest test-warning-suppress-p ()
+ (should (warning-suppress-p 'foo '((foo))))
+ (should (warning-suppress-p '(foo bar) '((foo bar))))
+ (should (warning-suppress-p '(foo bar baz) '((foo bar))))
+ (should-not (warning-suppress-p '(foo bar baz) '((foo bax))))
+ (should-not (warning-suppress-p 'foobar nil)))
+
+(ert-deftest test-display-warning ()
+ (dolist (level '(:emergency :error :warning))
+ (with-temp-buffer
+ (display-warning '(foo) "Hello123" level (current-buffer))
+ (should (string-match "foo" (buffer-string)))
+ (should (string-match "Hello123" (buffer-string))))
+ (with-current-buffer "*Messages*"
+ (should (string-match "Hello123" (buffer-string))))))
+
+(ert-deftest test-display-warning/warning-minimum-level ()
+ ;; This test only works interactively:
+ :expected-result :failed
+ (let ((warning-minimum-level :emergency))
+ (with-temp-buffer
+ (display-warning '(foo) "baz" :warning (current-buffer)))
+ (with-current-buffer "*Messages*"
+ (should-not (string-match "baz" (buffer-string))))))
+
+(ert-deftest test-display-warning/warning-minimum-log-level ()
+ (let ((warning-minimum-log-level :error))
+ (with-temp-buffer
+ (display-warning '(foo) "hello" :warning (current-buffer))
+ (should-not (string-match "hello" (buffer-string))))))
+
+(provide 'warnings-tests)
+
+;;; warnings-tests.el ends here
diff --git a/test/lisp/emulation/viper-tests.el b/test/lisp/emulation/viper-tests.el
index 938d5ed6ec5..1d2bf46b199 100644
--- a/test/lisp/emulation/viper-tests.el
+++ b/test/lisp/emulation/viper-tests.el
@@ -1,6 +1,6 @@
-;;; viper-tests.el --- tests for viper.
+;;; viper-tests.el --- tests for viper. -*- lexical-binding:t -*-
-;; Copyright (C) 2016-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2022 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -21,7 +21,8 @@
;;; Code:
-
+(require 'ert)
+(require 'ert-x)
(require 'viper)
(defun viper-test-undo-kmacro (kmacro)
@@ -30,47 +31,42 @@
This function makes as many attempts as possible to clean up
after itself, although it will leave a buffer called
*viper-test-buffer* if it fails (this is deliberate!)."
- (let (
- ;; Viper just turns itself off during batch use.
- (noninteractive nil)
- ;; Switch off start up message or it will chew the key presses.
- (viper-inhibit-startup-message 't)
- ;; Select an expert-level for the same reason.
- (viper-expert-level 5)
- ;; viper loads this even with -q so make sure it's empty!
- (viper-custom-file-name (make-temp-file "viper-tests" nil ".elc"))
- (before-buffer (current-buffer)))
- (unwind-protect
- (progn
- ;; viper-mode is essentially global, so set it here.
- (viper-mode)
- ;; We must switch to buffer because we are using a keyboard macro
- ;; which appears to not go to the current-buffer but what ever is
- ;; currently taking keyboard events. We use a named buffer because
- ;; then we can see what it in it if it all goes wrong.
- (switch-to-buffer
- (get-buffer-create
- "*viper-test-buffer*"))
- (erase-buffer)
- ;; The new buffer fails to enter vi state so set it.
- (viper-change-state-to-vi)
- ;; Run the macro.
- (execute-kbd-macro kmacro)
- (let ((rtn
- (buffer-substring-no-properties
- (point-min)
- (point-max))))
- ;; Kill the buffer iff the macro succeeds.
- (kill-buffer)
- rtn))
- ;; Switch everything off and restore the buffer.
- (toggle-viper-mode)
- (delete-file viper-custom-file-name)
- (switch-to-buffer before-buffer))))
-
-(ert-deftest viper-test-go ()
- "Test that this file is running."
- (should t))
+ (ert-with-temp-file viper-custom-file-name
+ ;; viper loads this even with -q so make sure it's empty!
+ :prefix "emacs-viper-tests" :suffix ".elc"
+ (let (;; Viper just turns itself off during batch use.
+ (noninteractive nil)
+ ;; Switch off start up message or it will chew the key presses.
+ (viper-inhibit-startup-message 't)
+ ;; Select an expert-level for the same reason.
+ (viper-expert-level 5)
+ (before-buffer (current-buffer)))
+ (unwind-protect
+ (progn
+ ;; viper-mode is essentially global, so set it here.
+ (viper-mode)
+ ;; We must switch to buffer because we are using a keyboard macro
+ ;; which appears to not go to the current-buffer but what ever is
+ ;; currently taking keyboard events. We use a named buffer because
+ ;; then we can see what it in it if it all goes wrong.
+ (switch-to-buffer
+ (get-buffer-create
+ "*viper-test-buffer*"))
+ (erase-buffer)
+ ;; The new buffer fails to enter vi state so set it.
+ (viper-change-state-to-vi)
+ ;; Run the macro.
+ (execute-kbd-macro kmacro)
+ (let ((rtn
+ (buffer-substring-no-properties
+ (point-min)
+ (point-max))))
+ ;; Kill the buffer iff the macro succeeds.
+ (kill-buffer)
+ rtn))
+ ;; Switch everything off and restore the buffer.
+ (toggle-viper-mode)
+ (switch-to-buffer before-buffer)))))
(ert-deftest viper-test-fix ()
"Test that the viper kmacro fixture is working."
diff --git a/test/lisp/env-tests.el b/test/lisp/env-tests.el
new file mode 100644
index 00000000000..fd3d3cb2734
--- /dev/null
+++ b/test/lisp/env-tests.el
@@ -0,0 +1,40 @@
+;;; env-tests.el --- Tests for env.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'env)
+(require 'ert)
+
+(ert-deftest test-substitute-env-in-file-name ()
+ (should (equal (substitute-env-in-file-name "foo_${HOME}_bar")
+ (concat "foo_" (getenv "HOME") "_bar"))))
+
+(ert-deftest test-getenv-setenv ()
+ (should (equal (setenv "EMACS_ENV_EL_TEST_VAR" "foobar") "foobar"))
+ (should (equal (getenv "EMACS_ENV_EL_TEST_VAR") "foobar"))
+ (should-not (getenv "LIKELY_TO_BE_NON_EXISTENT_FOO_BAR_BAZ")))
+
+(ert-deftest test-with-environment-variables ()
+ (let ((A "TEST") (B "/foo/bar"))
+ (with-environment-variables ((A B))
+ (should (equal (getenv A) B)))))
+
+(provide 'env-tests)
+;;; env-tests.el ends here
diff --git a/test/lisp/epg-config-tests.el b/test/lisp/epg-config-tests.el
new file mode 100644
index 00000000000..ac065909c45
--- /dev/null
+++ b/test/lisp/epg-config-tests.el
@@ -0,0 +1,47 @@
+;;; epg-config-tests.el --- Test suite for epg.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'epg-config)
+
+(ert-deftest epg-config-test-epg-find-configuration ()
+ (skip-unless (executable-find "gpg2"))
+ (should (assq 'version (epg-find-configuration 'OpenPGP))))
+
+(ert-deftest epg-config-test-epg-find-configuration/unknown-protocol ()
+ (should-error (epg-find-configuration 'does-not-exist)))
+
+(ert-deftest epg-config-test-epg-check-configuration ()
+ (should (epg-check-configuration '((version . "1.0")) "0.9"))
+ (should (epg-check-configuration '((version . "1.0")) "1.0"))
+ (should-error (epg-check-configuration '((version . "1.0")) "1.1"))
+ (should-error (epg-check-configuration '((version . "1.0")) 'foo))
+ (should-error (epg-check-configuration '((version . "1.0")) "foo")))
+
+(ert-deftest epg-config-test-epg-required-version-p ()
+ (skip-unless (executable-find "gpg2"))
+ (should (epg-required-version-p 'OpenPGP "1.0")))
+
+(provide 'epg-config-tests)
+
+;;; epg-config-tests.el ends here
diff --git a/test/data/epg/dummy-pinentry b/test/lisp/epg-resources/dummy-pinentry
index 2228dfb0c6d..2228dfb0c6d 100755
--- a/test/data/epg/dummy-pinentry
+++ b/test/lisp/epg-resources/dummy-pinentry
diff --git a/test/data/epg/pubkey.asc b/test/lisp/epg-resources/pubkey.asc
index c0bf28f6200..c0bf28f6200 100644
--- a/test/data/epg/pubkey.asc
+++ b/test/lisp/epg-resources/pubkey.asc
diff --git a/test/data/epg/seckey.asc b/test/lisp/epg-resources/seckey.asc
index 4ac7ba4a502..4ac7ba4a502 100644
--- a/test/data/epg/seckey.asc
+++ b/test/lisp/epg-resources/seckey.asc
diff --git a/test/lisp/epg-tests.el b/test/lisp/epg-tests.el
index cdb5f366acd..65aaafd9f18 100644
--- a/test/lisp/epg-tests.el
+++ b/test/lisp/epg-tests.el
@@ -1,6 +1,6 @@
;;; epg-tests.el --- Test suite for epg.el -*- lexical-binding: t -*-
-;; Copyright (C) 2013-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2022 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -22,16 +22,33 @@
;;; Code:
(require 'ert)
+(require 'ert-x)
(require 'epg)
(defvar epg-tests-context nil)
-(defvar epg-tests-data-directory
- (expand-file-name "data/epg" (getenv "EMACS_TEST_DIRECTORY"))
- "Directory containing epg test data.")
-
-(defun epg-tests-find-usable-gpg-configuration (&optional _require-passphrase)
- (epg-find-configuration 'OpenPGP 'no-cache))
+(defconst epg-tests--config-program-alist
+ ;; The default `epg-config--program-alist' requires gpg2 2.1 or
+ ;; greater due to some practical problems with pinentry. But most
+ ;; tests here work fine with 2.0 as well.
+ (let ((prog-alist (copy-tree epg-config--program-alist)))
+ (setf (alist-get "gpg2"
+ (alist-get 'OpenPGP prog-alist)
+ nil nil #'equal)
+ "2.0")
+ prog-alist))
+
+(defun epg-tests-find-usable-gpg-configuration
+ (&optional require-passphrase require-public-key)
+ ;; Clear config cache because we may be using a different
+ ;; program-alist. We do want to update the cache, so that
+ ;; `epg-make-context' can use our result.
+ (setq epg--configurations nil)
+ (epg-find-configuration 'OpenPGP nil
+ ;; The symmetric operations fail on Hydra
+ ;; with gpg 2.0.
+ (if (or (not require-passphrase) require-public-key)
+ epg-tests--config-program-alist)))
(defun epg-tests-passphrase-callback (_c _k _d)
;; Need to create a copy here, since the string will be wiped out
@@ -41,52 +58,51 @@
(cl-defmacro with-epg-tests ((&optional &key require-passphrase
require-public-key
require-secret-key)
- &rest body)
+ &rest body)
"Set up temporary locations and variables for testing."
(declare (indent 1) (debug (sexp body)))
- `(let* ((epg-tests-home-directory (make-temp-file "epg-tests-homedir" t))
- (process-environment
- (append
- (list "GPG_AGENT_INFO"
- (format "GNUPGHOME=%s" epg-tests-home-directory))
- process-environment)))
- (unwind-protect
- (let ((context (epg-make-context 'OpenPGP)))
- (setf (epg-context-program context)
- (alist-get 'program
- (epg-tests-find-usable-gpg-configuration
- ,(if require-passphrase
- `'require-passphrase))))
- (setf (epg-context-home-directory context)
- epg-tests-home-directory)
- ,(if require-passphrase
- `(with-temp-file (expand-file-name
- "gpg-agent.conf" epg-tests-home-directory)
- (insert "pinentry-program "
- (expand-file-name "dummy-pinentry"
- epg-tests-data-directory)
- "\n")
- (epg-context-set-passphrase-callback
- context
- #'epg-tests-passphrase-callback)))
- ,(if require-public-key
- `(epg-import-keys-from-file
- context
- (expand-file-name "pubkey.asc" epg-tests-data-directory)))
- ,(if require-secret-key
- `(epg-import-keys-from-file
- context
- (expand-file-name "seckey.asc" epg-tests-data-directory)))
- (with-temp-buffer
- (make-local-variable 'epg-tests-context)
- (setq epg-tests-context context)
- ,@body))
- (when (file-directory-p epg-tests-home-directory)
- (delete-directory epg-tests-home-directory t)))))
+ `(ert-with-temp-directory epg-tests-home-directory
+ (let* ((process-environment
+ (append
+ (list "GPG_AGENT_INFO"
+ (format "GNUPGHOME=%s" epg-tests-home-directory))
+ process-environment)))
+ ;; GNUPGHOME is needed to find a usable gpg, so we can't
+ ;; check whether to skip any earlier (Bug#23561).
+ (let ((epg-config (or (epg-tests-find-usable-gpg-configuration
+ ,require-passphrase ,require-public-key)
+ (ert-skip "No usable gpg config")))
+ (context (epg-make-context 'OpenPGP)))
+ (setf (epg-context-program context)
+ (alist-get 'program epg-config))
+ (setf (epg-context-home-directory context)
+ epg-tests-home-directory)
+ ,(if require-passphrase
+ '(with-temp-file (expand-file-name
+ "gpg-agent.conf" epg-tests-home-directory)
+ (insert "pinentry-program "
+ (ert-resource-file "dummy-pinentry")
+ "\n")
+ (epg-context-set-passphrase-callback
+ context
+ #'epg-tests-passphrase-callback)))
+ ,(if require-public-key
+ '(epg-import-keys-from-file
+ context
+ (ert-resource-file "pubkey.asc")))
+ ,(if require-secret-key
+ '(epg-import-keys-from-file
+ context
+ (ert-resource-file "seckey.asc")))
+ (with-temp-buffer
+ (setq-local epg-tests-context context)
+ ,@body)))))
(ert-deftest epg-decrypt-1 ()
- (skip-unless (epg-tests-find-usable-gpg-configuration 'require-passphrase))
+ :expected-result (if (getenv "EMACS_HYDRA_CI") :failed :passed) ; fixme
(with-epg-tests (:require-passphrase t)
+ (with-temp-file (expand-file-name "gpg.conf" epg-tests-home-directory)
+ (insert "ignore-mdc-error"))
(should (equal "test"
(epg-decrypt-string epg-tests-context "\
-----BEGIN PGP MESSAGE-----
@@ -97,14 +113,13 @@ jA0EAwMCE19JBLTvvmhgyRrGGglRbnKkK9PJG8fDwO5ccjysrR7IcdNcnA==
-----END PGP MESSAGE-----")))))
(ert-deftest epg-roundtrip-1 ()
- (skip-unless (epg-tests-find-usable-gpg-configuration 'require-passphrase))
+ :expected-result (if (getenv "EMACS_HYDRA_CI") :failed :passed) ; fixme
(with-epg-tests (:require-passphrase t)
(let ((cipher (epg-encrypt-string epg-tests-context "symmetric" nil)))
(should (equal "symmetric"
(epg-decrypt-string epg-tests-context cipher))))))
(ert-deftest epg-roundtrip-2 ()
- (skip-unless (epg-tests-find-usable-gpg-configuration 'require-passphrase))
(with-epg-tests (:require-passphrase t
:require-public-key t
:require-secret-key t)
@@ -115,7 +130,6 @@ jA0EAwMCE19JBLTvvmhgyRrGGglRbnKkK9PJG8fDwO5ccjysrR7IcdNcnA==
(epg-decrypt-string epg-tests-context cipher))))))
(ert-deftest epg-sign-verify-1 ()
- (skip-unless (epg-tests-find-usable-gpg-configuration 'require-passphrase))
(with-epg-tests (:require-passphrase t
:require-public-key t
:require-secret-key t)
@@ -129,7 +143,6 @@ jA0EAwMCE19JBLTvvmhgyRrGGglRbnKkK9PJG8fDwO5ccjysrR7IcdNcnA==
(should (eq 'good (epg-signature-status (car verify-result)))))))
(ert-deftest epg-sign-verify-2 ()
- (skip-unless (epg-tests-find-usable-gpg-configuration 'require-passphrase))
(with-epg-tests (:require-passphrase t
:require-public-key t
:require-secret-key t)
@@ -145,7 +158,6 @@ jA0EAwMCE19JBLTvvmhgyRrGGglRbnKkK9PJG8fDwO5ccjysrR7IcdNcnA==
(should (eq 'good (epg-signature-status (car verify-result)))))))
(ert-deftest epg-sign-verify-3 ()
- (skip-unless (epg-tests-find-usable-gpg-configuration 'require-passphrase))
(with-epg-tests (:require-passphrase t
:require-public-key t
:require-secret-key t)
@@ -160,7 +172,6 @@ jA0EAwMCE19JBLTvvmhgyRrGGglRbnKkK9PJG8fDwO5ccjysrR7IcdNcnA==
(should (eq 'good (epg-signature-status (car verify-result)))))))
(ert-deftest epg-import-1 ()
- (skip-unless (epg-tests-find-usable-gpg-configuration 'require-passphrase))
(with-epg-tests (:require-passphrase nil)
(should (= 0 (length (epg-list-keys epg-tests-context))))
(should (= 0 (length (epg-list-keys epg-tests-context nil t)))))
diff --git a/test/lisp/erc/erc-dcc-tests.el b/test/lisp/erc/erc-dcc-tests.el
new file mode 100644
index 00000000000..a1dfbab9dc5
--- /dev/null
+++ b/test/lisp/erc/erc-dcc-tests.el
@@ -0,0 +1,167 @@
+;;; erc-dcc-tests.el --- Tests for erc-dcc -*- lexical-binding:t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+;;
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published
+;; by the Free Software Foundation, either version 3 of the License,
+;; or (at your option) any later version.
+;;
+;; GNU Emacs is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+(require 'ert)
+(require 'erc-dcc)
+
+(ert-deftest erc-dcc-ctcp-query-send-regexp ()
+ (let ((s "DCC SEND \"file name\" 2130706433 9899 1405135128"))
+ (should (string-match erc-dcc-ctcp-query-send-regexp s))
+ (should-not (match-string 2 s))
+ (should (string= "file name" (match-string 1 s)))
+ (should (string= "SEND" (match-string 6 s))))
+ (let ((s "DCC SEND \"file \\\" name\" 2130706433 9899 1405135128"))
+ (should (string-match erc-dcc-ctcp-query-send-regexp s))
+ (should-not (match-string 2 s))
+ (should (string= "SEND" (match-string 6 s)))
+ (should (string= "file \" name"
+ (erc-dcc-unquote-filename (match-string 1 s)))))
+ (let ((s "DCC SEND filename 2130706433 9899 1405135128"))
+ (should (string-match erc-dcc-ctcp-query-send-regexp s))
+ (should (string= "filename" (match-string 2 s)))
+ (should (string= "2130706433" (match-string 3 s)))
+ (should (string= "9899" (match-string 4 s)))
+ (should (string= "1405135128" (match-string 5 s))))
+ (let ((s "DCC TSEND filename 2130706433 9899 1405135128"))
+ (should (string-match erc-dcc-ctcp-query-send-regexp s))
+ (should (string= "TSEND" (match-string 6 s)))))
+
+;; This also indirectly tests base functionality for
+;; `erc-dcc-do-LIST-command'
+
+(defun erc-dcc-tests--dcc-handle-ctcp-send (turbo)
+ (let (erc-send-completed-hook
+ erc-insert-modify-hook
+ erc-kill-channel-hook erc-kill-server-hook erc-kill-buffer-hook)
+ (with-current-buffer (get-buffer-create "fake-server")
+ (erc-mode)
+ (setq erc-server-process
+ (start-process "fake" (current-buffer) "sleep" "10")
+ erc-input-marker (make-marker)
+ erc-insert-marker (make-marker)
+ erc-server-current-nick "dummy")
+ (set-process-query-on-exit-flag erc-server-process nil)
+ (should-not erc-dcc-list)
+ (erc-ctcp-query-DCC erc-server-process
+ "tester"
+ "~tester"
+ "fake.irc"
+ "dummy"
+ (concat "DCC " (if turbo "TSEND" "SEND")
+ " foo 2130706433 9899 1405135128"))
+ (should-not (cdr erc-dcc-list))
+ (should (equal (plist-put (car erc-dcc-list) :parent 'fake)
+ `(:nick "tester!~tester@fake.irc"
+ :type GET
+ :peer nil
+ :parent fake
+ :ip "127.0.0.1"
+ :port "9899"
+ :file "foo"
+ :size 1405135128
+ :turbo ,(and turbo t)
+ :secure nil)))
+ (goto-char (point-min))
+ (should (search-forward "file foo offered by tester" nil t))
+ (erc-dcc-do-LIST-command erc-server-process)
+ (should (search-forward-regexp (concat
+ "GET +no +1405135128 +foo"
+ (and turbo " +(T)") "$")
+ nil t))
+ (when noninteractive
+ (kill-buffer))))
+ ;; `erc-dcc-list' is global; must leave it empty
+ (should erc-dcc-list)
+ (setq erc-dcc-list nil))
+
+(ert-deftest erc-dcc-handle-ctcp-send--base ()
+ (erc-dcc-tests--dcc-handle-ctcp-send nil))
+
+(ert-deftest erc-dcc-handle-ctcp-send--turbo ()
+ (erc-dcc-tests--dcc-handle-ctcp-send t))
+
+(ert-deftest erc-dcc-do-GET-command ()
+ (with-temp-buffer
+ (let* ((proc (start-process "fake" (current-buffer) "sleep" "10"))
+ (elt (list :nick "tester!~tester@fake.irc"
+ :type 'GET
+ :peer nil
+ :parent proc
+ :ip "127.0.0.1"
+ :port "9899"
+ :file "foo.bin"
+ :size 1405135128))
+ (erc-dcc-list (list elt))
+ ;;
+ erc-accidental-paste-threshold-seconds
+ erc-insert-modify-hook erc-send-completed-hook
+ erc-kill-channel-hook erc-kill-server-hook erc-kill-buffer-hook
+ calls)
+ (erc-mode)
+ (setq erc-server-process proc
+ erc-input-marker (make-marker)
+ erc-insert-marker (make-marker)
+ erc-server-current-nick "dummy")
+ (set-process-query-on-exit-flag proc nil)
+ (cl-letf (((symbol-function 'read-file-name)
+ (lambda (&rest _) "foo.bin"))
+ ((symbol-function 'erc-dcc-get-file)
+ (lambda (&rest r) (push r calls))))
+ (goto-char (point-max))
+ (set-marker erc-insert-marker (point-max))
+ (erc-display-prompt)
+
+ (ert-info ("No turbo")
+ (should-not (plist-member elt :turbo))
+ (goto-char erc-input-marker)
+ (insert "/dcc GET tester foo.bin")
+ (erc-send-current-line)
+ (should-not (plist-member (car erc-dcc-list) :turbo))
+ (should (equal (pop calls) (list elt "foo.bin" proc))))
+
+ (ert-info ("Arg turbo in pos 2")
+ (should-not (plist-member elt :turbo))
+ (goto-char erc-input-marker)
+ (insert "/dcc GET -t tester foo.bin")
+ (erc-send-current-line)
+ (should (eq t (plist-get (car erc-dcc-list) :turbo)))
+ (should (equal (pop calls) (list elt "foo.bin" proc))))
+
+ (ert-info ("Arg turbo in pos 4")
+ (setq elt (plist-put elt :turbo nil)
+ erc-dcc-list (list elt))
+ (goto-char erc-input-marker)
+ (insert "/dcc GET tester -t foo.bin")
+ (erc-send-current-line)
+ (should (eq t (plist-get (car erc-dcc-list) :turbo)))
+ (should (equal (pop calls) (list elt "foo.bin" proc))))
+
+ (ert-info ("Arg turbo in pos 6")
+ (setq elt (plist-put elt :turbo nil)
+ erc-dcc-list (list elt))
+ (goto-char erc-input-marker)
+ (insert "/dcc GET tester foo.bin -t")
+ (erc-send-current-line)
+ (should (eq t (plist-get (car erc-dcc-list) :turbo)))
+ (should (equal (pop calls) (list elt "foo.bin" proc))))))))
+
+;;; erc-dcc-tests.el ends here
diff --git a/test/lisp/erc/erc-join-tests.el b/test/lisp/erc/erc-join-tests.el
new file mode 100644
index 00000000000..8210defbfbd
--- /dev/null
+++ b/test/lisp/erc/erc-join-tests.el
@@ -0,0 +1,361 @@
+;;; erc-join-tests.el --- Tests for erc-join. -*- lexical-binding:t -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+;;
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published
+;; by the Free Software Foundation, either version 3 of the License,
+;; or (at your option) any later version.
+;;
+;; GNU Emacs is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert-x)
+(require 'erc-join)
+(require 'erc-networks)
+
+(ert-deftest erc-autojoin-channels--connect ()
+ (should (eq erc-autojoin-timing 'connect))
+ (should (= erc-autojoin-delay 30))
+ (should-not erc--autojoin-timer)
+
+ (let (calls
+ common
+ erc-kill-channel-hook erc-kill-server-hook erc-kill-buffer-hook)
+
+ (cl-letf (((symbol-function 'erc-server-send)
+ (lambda (line) (push line calls))))
+
+ (setq common
+ (lambda ()
+ (ert-with-test-buffer (:name "foonet")
+ (erc-mode)
+ (setq erc-server-process
+ (start-process "true" (current-buffer) "true")
+ erc-network 'FooNet
+ erc-session-server "irc.gnu.chat"
+ erc-server-current-nick "tester"
+ erc-networks--id (erc-networks--id-create nil)
+ erc-server-announced-name "foo.gnu.chat")
+ (set-process-query-on-exit-flag erc-server-process nil)
+ (erc-autojoin-channels erc-server-announced-name
+ "tester")
+ (should-not erc--autojoin-timer))))
+
+ (ert-info ("Join immediately on connect; server")
+ (let ((erc-autojoin-channels-alist '(("\\.gnu\\.chat\\'" "#chan"))))
+ (funcall common))
+ (should (equal (pop calls) "JOIN #chan")))
+
+ (ert-info ("Join immediately on connect; network")
+ (let ((erc-autojoin-channels-alist '((FooNet "#chan"))))
+ (funcall common))
+ (should (equal (pop calls) "JOIN #chan")))
+
+ (ert-info ("Do nothing; server")
+ (let ((erc-autojoin-channels-alist '(("bar\\.gnu\\.chat" "#chan"))))
+ (funcall common))
+ (should-not calls))
+
+ (ert-info ("Do nothing; network")
+ (let ((erc-autojoin-channels-alist '((BarNet "#chan"))))
+ (funcall common))
+ (should-not calls)))))
+
+(ert-deftest erc-autojoin-channels--delay ()
+ (should (eq erc-autojoin-timing 'connect))
+ (should (= erc-autojoin-delay 30))
+ (should-not erc--autojoin-timer)
+
+ (let (calls
+ common
+ erc-kill-channel-hook erc-kill-server-hook erc-kill-buffer-hook
+ (erc-autojoin-timing 'ident)
+ (erc-autojoin-delay 0.05))
+
+ (cl-letf (((symbol-function 'erc-server-send)
+ (lambda (line) (push line calls)))
+ ((symbol-function 'erc-autojoin-after-ident)
+ (lambda (&rest _r) (error "I ran but shouldn't have"))))
+
+ (setq common
+ (lambda ()
+ (ert-with-test-buffer (:name "foonet")
+ (erc-mode)
+ (setq erc-server-process
+ (start-process "true" (current-buffer) "true")
+ erc-network 'FooNet
+ erc-session-server "irc.gnu.chat"
+ erc-server-current-nick "tester"
+ erc-networks--id (erc-networks--id-create nil)
+ erc-server-announced-name "foo.gnu.chat")
+ (set-process-query-on-exit-flag erc-server-process nil)
+ (should-not erc--autojoin-timer)
+ (erc-autojoin-channels erc-server-announced-name "tester")
+ (should erc--autojoin-timer)
+ (should-not calls)
+ (sleep-for 0.1))))
+
+ (ert-info ("Deferred on connect; server")
+ (let ((erc-autojoin-channels-alist '(("\\.gnu\\.chat\\'" "#chan"))))
+ (funcall common))
+ (should (equal (pop calls) "JOIN #chan")))
+
+ (ert-info ("Deferred on connect; network")
+ (let ((erc-autojoin-channels-alist '((FooNet "#chan"))))
+ (funcall common))
+ (should (equal (pop calls) "JOIN #chan")))
+
+ (ert-info ("Do nothing; server")
+ (let ((erc-autojoin-channels-alist '(("bar\\.gnu\\.chat" "#chan"))))
+ (funcall common))
+ (should-not calls)))))
+
+(ert-deftest erc-autojoin-channels--ident ()
+ (should (eq erc-autojoin-timing 'connect))
+ (should (= erc-autojoin-delay 30))
+ (should-not erc--autojoin-timer)
+
+ (let (calls
+ common
+ erc-kill-channel-hook erc-kill-server-hook erc-kill-buffer-hook
+ (erc-autojoin-timing 'ident))
+
+ (cl-letf (((symbol-function 'erc-server-send)
+ (lambda (line) (push line calls))))
+
+ (setq common
+ (lambda ()
+ (ert-with-test-buffer (:name "foonet")
+ (erc-mode)
+ (setq erc-server-process
+ (start-process "true" (current-buffer) "true")
+ erc-network 'FooNet
+ erc-server-current-nick "tester"
+ erc-networks--id (erc-networks--id-create nil)
+ erc-server-announced-name "foo.gnu.chat")
+ (set-process-query-on-exit-flag erc-server-process nil)
+ (erc-autojoin-after-ident 'FooNet "tester")
+ (should-not erc--autojoin-timer))))
+
+ (ert-info ("Join on NickServ hook; server")
+ (let ((erc-autojoin-channels-alist '(("\\.gnu\\.chat\\'" "#chan"))))
+ (funcall common))
+ (should (equal (pop calls) "JOIN #chan")))
+
+ (ert-info ("Join on NickServ hook; network")
+ (let ((erc-autojoin-channels-alist '((FooNet "#chan"))))
+ (funcall common))
+ (should (equal (pop calls) "JOIN #chan"))))))
+
+(defun erc-join-tests--autojoin-add--common (setup &optional fwd)
+ (let (calls
+ erc-autojoin-channels-alist
+ erc-kill-channel-hook erc-kill-server-hook erc-kill-buffer-hook)
+
+ (cl-letf (((symbol-function 'erc-handle-parsed-server-response)
+ (lambda (_p m) (push m calls))))
+
+ (ert-with-test-buffer (:name "foonet")
+ (erc-mode)
+ (setq erc-server-process
+ (start-process "true" (current-buffer) "true")
+ erc-server-current-nick "tester"
+ erc--isupport-params (make-hash-table)
+ erc-server-announced-name "foo.gnu.chat")
+ (puthash 'CHANTYPES '("&#") erc--isupport-params)
+ (funcall setup)
+ (set-process-query-on-exit-flag erc-server-process nil)
+ (should-not calls)
+
+ (ert-info ("Add #chan")
+ (erc-parse-server-response erc-server-process
+ (concat ":tester!~i@c.u JOIN #chan"
+ (and fwd " * :Tes Ter")))
+ (should calls)
+ (erc-autojoin-add erc-server-process (pop calls))
+ (should (equal erc-autojoin-channels-alist '((FooNet "#chan")))))
+
+ (ert-info ("More recently joined chans are prepended")
+ (erc-parse-server-response
+ erc-server-process ; with account username
+ (concat ":tester!~i@c.u JOIN #spam" (and fwd " tester :Tes Ter")))
+ (should calls)
+ (erc-autojoin-add erc-server-process (pop calls))
+ (should (equal erc-autojoin-channels-alist
+ '((FooNet "#spam" "#chan")))))
+
+ (ert-info ("Duplicates skipped")
+ (erc-parse-server-response erc-server-process
+ (concat ":tester!~i@c.u JOIN #chan"
+ (and fwd " * :Tes Ter")))
+ (should calls)
+ (erc-autojoin-add erc-server-process (pop calls))
+ (should (equal erc-autojoin-channels-alist
+ '((FooNet "#spam" "#chan")))))
+
+ (ert-info ("Server used for local channel")
+ (erc-parse-server-response erc-server-process
+ (concat ":tester!~i@c.u JOIN &local"
+ (and fwd " * :Tes Ter")))
+ (should calls)
+ (erc-autojoin-add erc-server-process (pop calls))
+ (should (equal erc-autojoin-channels-alist
+ '(("foo\\.gnu\\.chat" "&local")
+ (FooNet "#spam" "#chan")))))))))
+
+(ert-deftest erc-autojoin-add--network ()
+ (erc-join-tests--autojoin-add--common
+ (lambda () (setq erc-network 'FooNet
+ erc-networks--id (erc-networks--id-create nil)))))
+
+(ert-deftest erc-autojoin-add--network-extended-syntax ()
+ (erc-join-tests--autojoin-add--common
+ (lambda () (setq erc-network 'FooNet
+ erc-networks--id (erc-networks--id-create nil)))
+ 'forward-compatible))
+
+(ert-deftest erc-autojoin-add--network-id ()
+ (erc-join-tests--autojoin-add--common
+ (lambda () (setq erc-network 'invalid
+ erc-networks--id (erc-networks--id-create 'FooNet)))))
+
+(ert-deftest erc-autojoin-add--server ()
+ (let (calls
+ erc-autojoin-channels-alist
+ erc-kill-channel-hook erc-kill-server-hook erc-kill-buffer-hook)
+
+ (cl-letf (((symbol-function 'erc-handle-parsed-server-response)
+ (lambda (_p m) (push m calls))))
+
+ (ert-info ("Network unavailable, announced name used")
+ (setq erc-autojoin-channels-alist nil)
+ (ert-with-test-buffer (:name "foonet")
+ (erc-mode)
+ (setq erc-server-process
+ (start-process "true" (current-buffer) "true")
+ erc-server-current-nick "tester"
+ erc-server-announced-name "foo.gnu.chat"
+ erc-networks--id (make-erc-networks--id)) ; assume too early
+ (set-process-query-on-exit-flag erc-server-process nil)
+ (should-not calls)
+ (erc-parse-server-response erc-server-process
+ ":tester!~u@q6ddatxcq6txy.irc JOIN #chan")
+ (should calls)
+ (erc-autojoin-add erc-server-process (pop calls))
+ (should (equal erc-autojoin-channels-alist
+ '(("gnu.chat" "#chan")))))))))
+
+(defun erc-join-tests--autojoin-remove--common (setup)
+ (let (calls
+ erc-autojoin-channels-alist
+ erc-kill-channel-hook erc-kill-server-hook erc-kill-buffer-hook)
+
+ (cl-letf (((symbol-function 'erc-handle-parsed-server-response)
+ (lambda (_p m) (push m calls))))
+
+ (setq erc-autojoin-channels-alist ; mutated, so can't quote whole thing
+ (list '(FooNet "#spam" "##chan")
+ '(BarNet "#bar" "##bar")
+ '("foo\\.gnu\\.chat" "&local")))
+
+ (ert-with-test-buffer (:name "foonet")
+ (erc-mode)
+ (setq erc-server-process
+ (start-process "true" (current-buffer) "true")
+ erc-server-current-nick "tester"
+ erc--isupport-params (make-hash-table)
+ erc-server-announced-name "foo.gnu.chat")
+ (puthash 'CHANTYPES '("&#") erc--isupport-params)
+ (funcall setup)
+ (set-process-query-on-exit-flag erc-server-process nil)
+ (should-not calls)
+
+ (ert-info ("Remove #chan")
+ (erc-parse-server-response erc-server-process
+ ":tester!~i@c.u PART ##chan")
+ (should calls)
+ (erc-autojoin-remove erc-server-process (pop calls))
+ (should (equal erc-autojoin-channels-alist
+ '((FooNet "#spam")
+ (BarNet "#bar" "##bar")
+ ("foo\\.gnu\\.chat" "&local")))))
+
+ (ert-info ("Wrong network, nothing done")
+ (erc-parse-server-response erc-server-process
+ ":tester!~i@c.u PART #bar")
+ (should calls)
+ (erc-autojoin-remove erc-server-process (pop calls))
+ (should (equal erc-autojoin-channels-alist
+ '((FooNet "#spam")
+ (BarNet "#bar" "##bar")
+ ("foo\\.gnu\\.chat" "&local")))))
+
+ (ert-info ("Local channel keyed by server found")
+ (erc-parse-server-response erc-server-process
+ ":tester!~i@c.u PART &local")
+ (should calls)
+ (erc-autojoin-remove erc-server-process (pop calls))
+ (should (equal erc-autojoin-channels-alist
+ '((FooNet "#spam") (BarNet "#bar" "##bar")))))))))
+
+(ert-deftest erc-autojoin-remove--network ()
+ (erc-join-tests--autojoin-remove--common
+ (lambda () (setq erc-network 'FooNet
+ erc-networks--id (erc-networks--id-create nil)))))
+
+(ert-deftest erc-autojoin-remove--network-id ()
+ (erc-join-tests--autojoin-remove--common
+ (lambda () (setq erc-network 'fake-a-roo
+ erc-networks--id (erc-networks--id-create 'FooNet)))))
+
+(ert-deftest erc-autojoin-remove--server ()
+ (let (calls
+ erc-autojoin-channels-alist
+ erc-kill-channel-hook erc-kill-server-hook erc-kill-buffer-hook)
+
+ (cl-letf (((symbol-function 'erc-handle-parsed-server-response)
+ (lambda (_p m) (push m calls))))
+
+ (setq erc-autojoin-channels-alist (list '("gnu.chat" "#spam" "##chan")
+ '("fsf.chat" "#bar" "##bar")))
+
+ (ert-with-test-buffer (:name "foonet")
+ (erc-mode)
+ (setq erc-server-process
+ (start-process "true" (current-buffer) "true")
+ erc-server-current-nick "tester"
+ erc-server-announced-name "foo.gnu.chat"
+ ;; Assume special case w/o known network
+ erc-networks--id (make-erc-networks--id))
+ (set-process-query-on-exit-flag erc-server-process nil)
+ (should-not calls)
+
+ (ert-info ("Announced name matched, #chan removed")
+ (erc-parse-server-response erc-server-process
+ ":tester!~i@c.u PART ##chan")
+ (should calls)
+ (erc-autojoin-remove erc-server-process (pop calls))
+ (should (equal erc-autojoin-channels-alist
+ '(("gnu.chat" "#spam")
+ ("fsf.chat" "#bar" "##bar")))))
+
+ (ert-info ("Wrong announced name, nothing done")
+ (erc-parse-server-response erc-server-process
+ ":tester!~i@c.u PART #bar")
+ (should calls)
+ (erc-autojoin-remove erc-server-process (pop calls))
+ (should (equal erc-autojoin-channels-alist
+ '(("gnu.chat" "#spam")
+ ("fsf.chat" "#bar" "##bar")))))))))
+
+;;; erc-join-tests.el ends here
diff --git a/test/lisp/erc/erc-match-tests.el b/test/lisp/erc/erc-match-tests.el
new file mode 100644
index 00000000000..cd7598703b5
--- /dev/null
+++ b/test/lisp/erc/erc-match-tests.el
@@ -0,0 +1,193 @@
+;;; erc-match-tests.el --- Tests for erc-match. -*- lexical-binding:t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+;;; Code:
+
+(require 'ert-x)
+(require 'erc-match)
+
+
+(ert-deftest erc-add-entry-to-list ()
+ (let ((erc-pals '("z"))
+ (erc-match-quote-when-adding 'ask))
+
+ (ert-info ("Default (ask)")
+ (ert-simulate-keys "\t\ry\r"
+ (erc-add-entry-to-list 'erc-pals "?" '((".")) nil)
+ (should (equal (pop erc-pals) "\\.")))
+
+ (ert-info ("Inverted")
+ (ert-simulate-keys "\t\ry\r"
+ (erc-add-entry-to-list 'erc-pals "?" '((".")) nil)
+ (should (equal (pop erc-pals) "\\."))))
+
+ (ert-info ("Skipped")
+ (ert-simulate-keys "\t\r"
+ (erc-add-entry-to-list 'erc-pals "?" '(("x")) nil)
+ (should (equal (pop erc-pals) "x")))))
+
+ (ert-info ("Verbatim")
+ (setq erc-match-quote-when-adding nil)
+ (ert-simulate-keys "\t\r"
+ (erc-add-entry-to-list 'erc-pals "?" '((".")) nil)
+ (should (equal (pop erc-pals) ".")))
+
+ (ert-info ("Inverted")
+ (ert-simulate-keys "\t\r"
+ (erc-add-entry-to-list 'erc-pals "?" '((".")) t)
+ (should (equal (pop erc-pals) "\\.")))))
+
+ (ert-info ("Quoted")
+ (setq erc-match-quote-when-adding t)
+ (ert-simulate-keys "\t\r"
+ (erc-add-entry-to-list 'erc-pals "?" '((".")) nil)
+ (should (equal (pop erc-pals) "\\.")))
+
+ (ert-info ("Inverted")
+ (ert-simulate-keys "\t\r"
+ (erc-add-entry-to-list 'erc-pals "?" '((".")) t)
+ (should (equal (pop erc-pals) ".")))))
+
+ (should (equal erc-pals '("z")))))
+
+(ert-deftest erc-pals ()
+ (with-temp-buffer
+ (setq erc-server-process (start-process "true" (current-buffer) "true")
+ erc-server-users (make-hash-table :test #'equal))
+ (set-process-query-on-exit-flag erc-server-process nil)
+ (erc-add-server-user "FOO[m]" (make-erc-server-user :nickname "foo[m]"))
+ (erc-add-server-user "tester" (make-erc-server-user :nickname "tester"))
+
+ (let ((erc-match-quote-when-adding t)
+ erc-pals calls rvs)
+ (cl-letf (((symbol-function 'completing-read)
+ (lambda (&rest r) (push r calls) (pop rvs))))
+
+ (ert-info ("`erc-add-pal'")
+ (push "foo[m]" rvs)
+ (ert-simulate-command '(erc-add-pal))
+ (should (equal (cadr (pop calls)) '(("tester") ("foo[m]"))))
+ (should (equal erc-pals '("foo\\[m]"))))
+
+ (ert-info ("`erc-match-pal-p'")
+ (should (erc-match-pal-p "FOO[m]!~u@example.net" nil)))
+
+ (ert-info ("`erc-delete-pal'")
+ (push "foo\\[m]" rvs)
+ (ert-simulate-command '(erc-delete-pal))
+ (should (equal (cadr (pop calls)) '(("foo\\[m]"))))
+ (should-not erc-pals))
+
+ (ert-info ("`erc-add-pal' verbatim")
+ (push "foo[m]" rvs)
+ (ert-simulate-command '(erc-add-pal (4)))
+ (should (equal (cadr (pop calls)) '(("tester") ("foo[m]"))))
+ (should (equal erc-pals '("foo[m]"))))))))
+
+(ert-deftest erc-fools ()
+ (with-temp-buffer
+ (setq erc-server-process (start-process "true" (current-buffer) "true")
+ erc-server-users (make-hash-table :test #'equal))
+ (set-process-query-on-exit-flag erc-server-process nil)
+ (erc-add-server-user "FOO[m]" (make-erc-server-user :nickname "foo[m]"))
+ (erc-add-server-user "tester" (make-erc-server-user :nickname "tester"))
+
+ (let ((erc-match-quote-when-adding t)
+ erc-fools calls rvs)
+ (cl-letf (((symbol-function 'completing-read)
+ (lambda (&rest r) (push r calls) (pop rvs))))
+
+ (ert-info ("`erc-add-fool'")
+ (push "foo[m]" rvs)
+ (ert-simulate-command '(erc-add-fool))
+ (should (equal (cadr (pop calls)) '(("tester") ("foo[m]"))))
+ (should (equal erc-fools '("foo\\[m]"))))
+
+ (ert-info ("`erc-match-fool-p'")
+ (should (erc-match-fool-p "FOO[m]!~u@example.net" ""))
+ (should (erc-match-fool-p "tester!~u@example.net" "FOO[m]: die")))
+
+ (ert-info ("`erc-delete-fool'")
+ (push "foo\\[m]" rvs)
+ (ert-simulate-command '(erc-delete-fool))
+ (should (equal (cadr (pop calls)) '(("foo\\[m]"))))
+ (should-not erc-fools))
+
+ (ert-info ("`erc-add-fool' verbatim")
+ (push "foo[m]" rvs)
+ (ert-simulate-command '(erc-add-fool (4)))
+ (should (equal (cadr (pop calls)) '(("tester") ("foo[m]"))))
+ (should (equal erc-fools '("foo[m]"))))))))
+
+(ert-deftest erc-keywords ()
+ (let ((erc-match-quote-when-adding t)
+ erc-keywords calls rvs)
+ (cl-letf (((symbol-function 'completing-read)
+ (lambda (&rest r) (push r calls) (pop rvs))))
+
+ (ert-info ("`erc-add-keyword'")
+ (push "[cit. needed]" rvs)
+ (ert-simulate-command '(erc-add-keyword))
+ (should (equal (cadr (pop calls)) nil))
+ (should (equal erc-keywords '("\\[cit\\. needed]"))))
+
+ (ert-info ("`erc-match-keyword-p'")
+ (should (erc-match-keyword-p nil "is pretty [cit. needed]")))
+
+ (ert-info ("`erc-delete-keyword'")
+ (push "\\[cit\\. needed]" rvs)
+ (ert-simulate-command '(erc-delete-keyword))
+ (should (equal (cadr (pop calls)) '(("\\[cit\\. needed]"))))
+ (should-not erc-keywords))
+
+ (ert-info ("`erc-add-keyword' verbatim")
+ (push "[...]" rvs)
+ (ert-simulate-command '(erc-add-keyword (4)))
+ (should (equal (cadr (pop calls)) nil))
+ (should (equal erc-keywords '("[...]")))))))
+
+(ert-deftest erc-dangerous-hosts ()
+ (let ((erc-match-quote-when-adding t)
+ erc-dangerous-hosts calls rvs)
+ (cl-letf (((symbol-function 'completing-read)
+ (lambda (&rest r) (push r calls) (pop rvs))))
+
+ (ert-info ("`erc-add-dangerous-host'")
+ (push "example.net" rvs)
+ (ert-simulate-command '(erc-add-dangerous-host))
+ (should (equal (cadr (pop calls)) nil))
+ (should (equal erc-dangerous-hosts '("example\\.net"))))
+
+ (ert-info ("`erc-match-dangerous-host-p'")
+ (should (erc-match-dangerous-host-p "FOO[m]!~u@example.net" nil)))
+
+ (ert-info ("`erc-delete-dangerous-host'")
+ (push "example\\.net" rvs)
+ (ert-simulate-command '(erc-delete-dangerous-host))
+ (should (equal (cadr (pop calls)) '(("example\\.net"))))
+ (should-not erc-dangerous-hosts))
+
+ (ert-info ("`erc-add-dangerous-host' verbatim")
+ (push "example.net" rvs)
+ (ert-simulate-command '(erc-add-dangerous-host (4)))
+ (should (equal (cadr (pop calls)) nil))
+ (should (equal erc-dangerous-hosts '("example.net")))))))
+
+;;; erc-match-tests.el ends here
diff --git a/test/lisp/erc/erc-networks-tests.el b/test/lisp/erc/erc-networks-tests.el
new file mode 100644
index 00000000000..66a334b7091
--- /dev/null
+++ b/test/lisp/erc/erc-networks-tests.el
@@ -0,0 +1,1707 @@
+;;; erc-networks-tests.el --- Tests for erc-networks. -*- lexical-binding:t -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+;;
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published
+;; by the Free Software Foundation, either version 3 of the License,
+;; or (at your option) any later version.
+;;
+;; GNU Emacs is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert-x) ; cl-lib
+(require 'erc-networks)
+
+(defun erc-networks-tests--create-dead-proc (&optional buf)
+ (let ((p (start-process "true" (or buf (current-buffer)) "true")))
+ (while (process-live-p p) (sit-for 0.1))
+ p))
+
+(defun erc-networks-tests--create-live-proc (&optional buf)
+ (let ((proc (start-process "sleep" (or buf (current-buffer)) "sleep" "1")))
+ (set-process-query-on-exit-flag proc nil)
+ proc))
+
+;; When we drop 27, call `get-buffer-create with INHIBIT-BUFFER-HOOKS.
+(defun erc-networks-tests--clean-bufs ()
+ (let (erc-kill-channel-hook
+ erc-kill-server-hook
+ erc-kill-buffer-hook)
+ (dolist (buf (erc-buffer-list))
+ (kill-buffer buf))))
+
+(defun erc-networks-tests--bufnames (prefix)
+ (let* ((case-fold-search)
+ (pred (lambda (b) (string-prefix-p prefix (buffer-name b))))
+ (prefixed (seq-filter pred (buffer-list))))
+ (sort (mapcar #'buffer-name prefixed) #'string<)))
+
+(ert-deftest erc-networks--id ()
+ (cl-letf (((symbol-function 'float-time)
+ (lambda (&optional _) 0.0)))
+
+ ;; Fixed
+ (should (equal (erc-networks--id-fixed-create 'foo)
+ (make-erc-networks--id-fixed :ts (float-time)
+ :symbol 'foo)))
+
+ ;; Eliding
+ (let* ((erc-network 'FooNet)
+ (erc-server-current-nick "Joe")
+ (identity (erc-networks--id-create nil)))
+
+ (should (equal identity #s(erc-networks--id-qualifying
+ 0.0 FooNet [FooNet "joe"] 1)))
+ (should (equal (erc-networks--id-qualifying-grow-id identity)
+ 'FooNet/joe))
+ (should (equal identity #s(erc-networks--id-qualifying
+ 0.0 FooNet/joe [FooNet "joe"] 2)))
+ (should-not (erc-networks--id-qualifying-grow-id identity))
+ (should (equal identity #s(erc-networks--id-qualifying
+ 0.0 FooNet/joe [FooNet "joe"] 2))))
+
+ ;; Compat
+ (with-current-buffer (get-buffer-create "fake.chat")
+ (with-suppressed-warnings ((obsolete erc-rename-buffers))
+ (let (erc-rename-buffers)
+ (should (equal (erc-networks--id-create nil)
+ (make-erc-networks--id-fixed :ts (float-time)
+ :symbol 'fake.chat)))))
+ (kill-buffer))))
+
+(ert-deftest erc-networks--id-create ()
+ (cl-letf (((symbol-function 'float-time)
+ (lambda (&optional _) 0.0)))
+
+ (should (equal (erc-networks--id-create 'foo)
+ (make-erc-networks--id-fixed :ts (float-time)
+ :symbol 'foo)))
+ (should (equal (erc-networks--id-create "foo")
+ (make-erc-networks--id-fixed :ts (float-time)
+ :symbol 'foo)))
+ (should (equal (erc-networks--id-create [h i])
+ (make-erc-networks--id-fixed :ts (float-time)
+ :symbol (quote \[h\ \i\]))))
+
+ (with-current-buffer (get-buffer-create "foo")
+ (let ((expected (make-erc-networks--id-fixed :ts (float-time)
+ :symbol 'foo)))
+ (with-suppressed-warnings ((obsolete erc-rename-buffers))
+ (let (erc-rename-buffers)
+ (should (equal (erc-networks--id-create nil) expected))))
+ (with-suppressed-warnings ((obsolete erc-reuse-buffers))
+ (let (erc-reuse-buffers)
+ (should (equal (erc-networks--id-create nil) expected))
+ (should (equal (erc-networks--id-create 'bar) expected)))))
+ (kill-buffer))))
+
+(ert-deftest erc-networks--id-qualifying-prefix-length ()
+ (should-not (erc-networks--id-qualifying-prefix-length
+ (make-erc-networks--id-qualifying)
+ (make-erc-networks--id-qualifying)))
+
+ (should-not (erc-networks--id-qualifying-prefix-length
+ (make-erc-networks--id-qualifying :parts [1 2])
+ (make-erc-networks--id-qualifying :parts [2 3])))
+
+ (should (= 1 (erc-networks--id-qualifying-prefix-length
+ (make-erc-networks--id-qualifying :parts [1])
+ (make-erc-networks--id-qualifying :parts [1 2]))))
+
+ (should (= 1 (erc-networks--id-qualifying-prefix-length
+ (make-erc-networks--id-qualifying :parts [1 2])
+ (make-erc-networks--id-qualifying :parts [1 3]))))
+
+ (should (= 2 (erc-networks--id-qualifying-prefix-length
+ (make-erc-networks--id-qualifying :parts [1 2])
+ (make-erc-networks--id-qualifying :parts [1 2]))))
+
+ (should (= 1 (erc-networks--id-qualifying-prefix-length
+ (make-erc-networks--id-qualifying :parts ["1"])
+ (make-erc-networks--id-qualifying :parts ["1"])))))
+
+(ert-deftest erc-networks--id-sort-buffers ()
+ (let (oldest middle newest)
+
+ (with-temp-buffer
+ (setq erc-networks--id (erc-networks--id-fixed-create 'oldest)
+ oldest (current-buffer))
+
+ (with-temp-buffer
+ (setq erc-networks--id (erc-networks--id-fixed-create 'middle)
+ middle (current-buffer))
+
+ (with-temp-buffer
+ (setq erc-networks--id (erc-networks--id-fixed-create 'newest)
+ newest (current-buffer))
+
+ (should (equal (erc-networks--id-sort-buffers
+ (list oldest newest middle))
+ (list newest middle oldest))))))))
+
+(ert-deftest erc-networks-rename-surviving-target-buffer--channel ()
+ (should (memq #'erc-networks-rename-surviving-target-buffer
+ erc-kill-channel-hook))
+
+ (let ((chan-foonet-buffer (get-buffer-create "#chan@foonet")))
+
+ (with-current-buffer chan-foonet-buffer
+ (erc-mode)
+ (setq erc-networks--id (make-erc-networks--id-qualifying
+ :parts [foonet "bob"] :len 1)
+ erc--target (erc--target-from-string "#chan")))
+
+ (with-current-buffer (get-buffer-create "#chan@barnet")
+ (erc-mode)
+ (setq erc-networks--id (make-erc-networks--id-qualifying
+ :parts [barnet "bob"] :len 1)
+ erc--target (erc--target-from-string "#chan")))
+
+ (kill-buffer "#chan@barnet")
+ (should (equal (erc-networks-tests--bufnames "#chan") '("#chan")))
+ (should (eq chan-foonet-buffer (get-buffer "#chan"))))
+
+ (erc-networks-tests--clean-bufs))
+
+(ert-deftest erc-networks-rename-surviving-target-buffer--query ()
+ (should (memq #'erc-networks-rename-surviving-target-buffer
+ erc-kill-buffer-hook))
+
+ (let ((bob-foonet (get-buffer-create "bob@foonet")))
+
+ (with-current-buffer bob-foonet
+ (erc-mode)
+ (setq erc-networks--id (make-erc-networks--id-qualifying
+ :parts [foonet "bob"] :len 1)
+ erc--target (erc--target-from-string "bob")))
+
+ (with-current-buffer (get-buffer-create "bob@barnet")
+ (erc-mode)
+ (setq erc-networks--id (make-erc-networks--id-qualifying
+ :parts [barnet "bob"] :len 1)
+ erc--target (erc--target-from-string "bob")))
+
+ (kill-buffer "bob@barnet")
+ (should (equal (erc-networks-tests--bufnames "bob") '("bob")))
+ (should (eq bob-foonet (get-buffer "bob"))))
+
+ (erc-networks-tests--clean-bufs))
+
+(ert-deftest erc-networks-rename-surviving-target-buffer--multi ()
+
+ (ert-info ("Multiple leftover channels untouched")
+ (with-current-buffer (get-buffer-create "#chan@foonet")
+ (erc-mode)
+ (setq erc--target (erc--target-from-string "#chan")))
+ (with-current-buffer (get-buffer-create "#chan@barnet")
+ (erc-mode)
+ (setq erc--target (erc--target-from-string "#chan")))
+ (with-current-buffer (get-buffer-create "#chan@baznet")
+ (erc-mode)
+ (setq erc--target (erc--target-from-string "#chan")))
+ (kill-buffer "#chan@baznet")
+ (should (equal (erc-networks-tests--bufnames "#chan")
+ '("#chan@barnet" "#chan@foonet")))
+ (erc-networks-tests--clean-bufs))
+
+ (ert-info ("Multiple leftover queries untouched")
+ (with-current-buffer (get-buffer-create "bob@foonet")
+ (erc-mode)
+ (setq erc--target (erc--target-from-string "bob")))
+ (with-current-buffer (get-buffer-create "bob@barnet")
+ (erc-mode)
+ (setq erc--target (erc--target-from-string "bob")))
+ (with-current-buffer (get-buffer-create "bob@baznet")
+ (erc-mode)
+ (setq erc--target (erc--target-from-string "bob")))
+ (kill-buffer "bob@baznet")
+ (should (equal (erc-networks-tests--bufnames "bob")
+ '("bob@barnet" "bob@foonet")))
+ (erc-networks-tests--clean-bufs)))
+
+;; As of May 2022, this "shrink" stuff runs whenever an ERC buffer is
+;; killed because `erc-networks-shrink-ids-and-buffer-names' is a
+;; default member of all three erc-kill-* functions.
+
+;; Note: this overlaps a fair bit with the "hook" variants, i.e.,
+;; `erc-networks--shrink-ids-and-buffer-names--hook-outstanding-*' If
+;; this ever fails, just delete this and fix those. But please copy
+;; over and adapt the comments first.
+
+(ert-deftest erc-networks--shrink-ids-and-buffer-names--perform-outstanding ()
+ ;; While some buffer #a@barnet/dummy is being killed, its display ID
+ ;; is not collapsed because collisions still exist.
+ ;;
+ ;; Note that we don't have to set `erc-server-connected' because
+ ;; this function is intentionally connectivity agnostic.
+ (with-current-buffer (get-buffer-create "foonet/tester")
+ (erc-mode)
+ (setq erc-server-current-nick "tester" ; Always set (`erc-open')
+ ;; Set when transport connected
+ erc-server-process (erc-networks-tests--create-live-proc)
+ ;; Both set just before IRC (logically) connected (post MOTD)
+ erc-network 'foonet
+ erc-networks--id (make-erc-networks--id-qualifying
+ :symbol 'foonet/tester
+ :parts [foonet "tester"]
+ :len 2))) ; is/was a plain foonet collision
+
+ ;; Presumably, some server buffer named foonet/dummy was just
+ ;; killed, hence the length 2 display ID.
+
+ ;; A target buffer for chan #a exists for foonet/tester. The
+ ;; precise form of its name should not affect shrinking.
+ (with-current-buffer (get-buffer-create
+ (elt ["#a" "#a@foonet" "#a@foonet/tester"] (random 3)))
+ (erc-mode)
+ (setq erc-server-process (buffer-local-value 'erc-server-process
+ (get-buffer "foonet/tester"))
+ erc-network 'foonet
+ erc-server-current-nick "tester"
+ erc-networks--id (buffer-local-value 'erc-networks--id
+ (get-buffer "foonet/tester"))
+ erc--target (erc--target-from-string "#a")))
+
+ ;; Another network context exists (so we have buffers to iterate
+ ;; over), and it's also part of a collision group.
+ (with-current-buffer (get-buffer-create "barnet/tester")
+ (erc-mode)
+ (setq erc-network 'barnet
+ erc-server-current-nick "tester"
+ erc-networks--id (make-erc-networks--id-qualifying
+ :symbol 'barnet/tester
+ :parts [barnet "tester"]
+ :len 2)
+ erc-server-process (erc-networks-tests--create-live-proc)))
+
+ (with-current-buffer (get-buffer-create "barnet/dummy")
+ (erc-mode)
+ (setq erc-network 'barnet
+ erc-server-current-nick "dummy"
+ erc-networks--id (make-erc-networks--id-qualifying
+ :symbol 'barnet/dummy
+ :parts [barnet "dummy"]
+ :len 2)
+ erc-server-process (erc-networks-tests--create-live-proc)))
+
+ ;; The buffer being killed is not part of the foonet collision
+ ;; group, which contains one display ID eligible for shrinkage.
+ (with-current-buffer (get-buffer-create
+ (elt ["#a@barnet" "#a@barnet/tester"] (random 2)))
+ (erc-mode)
+ (setq erc-network 'barnet
+ erc-server-current-nick "tester"
+ erc-server-process (buffer-local-value 'erc-server-process
+ (get-buffer "barnet/tester"))
+ erc-networks--id (buffer-local-value 'erc-networks--id
+ (get-buffer "barnet/tester"))
+ erc--target (erc--target-from-string "#a")))
+
+ (with-temp-buffer ; doesn't matter what the current buffer is
+ (setq erc-networks--id (make-erc-networks--id-qualifying)) ; mock
+ (erc-networks--shrink-ids-and-buffer-names))
+
+ (should (equal (mapcar #'buffer-name (erc-buffer-list))
+ '("foonet" ; shrunk
+ "#a@foonet" ; shrunk
+ "barnet/tester"
+ "barnet/dummy"
+ "#a@barnet/tester")))
+
+ (erc-networks-tests--clean-bufs))
+
+;; This likewise overlaps with the "hook" variants below. If this
+;; should ever fail, just delete it and optionally fix those.
+
+(ert-deftest erc-networks--shrink-ids-and-buffer-names--perform-collapse ()
+ ;; This is similar to the "outstanding" variant above, but both
+ ;; groups are eligible for renaming, which is abnormal but possible
+ ;; when recovering from some mishap.
+ (with-current-buffer (get-buffer-create "foonet/tester")
+ (erc-mode)
+ (setq erc-network 'foonet
+ erc-server-current-nick "tester"
+ erc-networks--id (make-erc-networks--id-qualifying
+ :symbol 'foonet/tester
+ :parts [foonet "tester"]
+ :len 2)
+ erc-server-process (erc-networks-tests--create-live-proc)))
+
+ (with-current-buffer
+ (get-buffer-create (elt ["#a" "#a@foonet/tester"] (random 2)))
+ (erc-mode)
+ (setq erc-server-process (buffer-local-value 'erc-server-process
+ (get-buffer "foonet/tester"))
+ erc-network 'foonet
+ erc-server-current-nick "tester"
+ erc-networks--id (buffer-local-value 'erc-networks--id
+ (get-buffer "foonet/tester"))
+ erc--target (erc--target-from-string "#a")))
+
+ (with-current-buffer (get-buffer-create "barnet/tester")
+ (erc-mode)
+ (setq erc-network 'barnet
+ erc-server-current-nick "tester"
+ erc-networks--id (make-erc-networks--id-qualifying
+ :symbol 'barnet/tester
+ :parts [barnet "tester"]
+ :len 2)
+ erc-server-process (erc-networks-tests--create-live-proc)))
+
+ (with-current-buffer
+ (get-buffer-create (elt ["#b" "#b@foonet/tester"] (random 2)))
+ (erc-mode)
+ (setq erc-network 'barnet
+ erc-server-current-nick "tester"
+ erc-server-process (buffer-local-value 'erc-server-process
+ (get-buffer "barnet/tester"))
+ erc-networks--id (buffer-local-value 'erc-networks--id
+ (get-buffer "barnet/tester"))
+ erc--target (erc--target-from-string "#b")))
+
+ (with-temp-buffer
+ (setq erc-networks--id (make-erc-networks--id-qualifying))
+ (erc-networks--shrink-ids-and-buffer-names))
+
+ (should (equal (mapcar #'buffer-name (erc-buffer-list))
+ '("foonet" "#a" "barnet" "#b")))
+
+ (erc-networks-tests--clean-bufs))
+
+(defun erc-networks--shrink-ids-and-buffer-names--hook-outstanding-common ()
+
+ (with-current-buffer (get-buffer-create "foonet/tester")
+ (erc-mode)
+ (setq erc-network 'foonet
+ erc-server-current-nick "tester"
+ erc-networks--id (make-erc-networks--id-qualifying
+ :symbol 'foonet/tester
+ :parts [foonet "tester"]
+ :len 2)
+ erc-server-process (erc-networks-tests--create-live-proc)))
+
+ (with-current-buffer (get-buffer-create "#a@foonet/tester")
+ (erc-mode)
+ (setq erc-server-process (buffer-local-value 'erc-server-process
+ (get-buffer "foonet/tester"))
+ erc-network 'foonet
+ erc-server-current-nick "tester"
+ erc-networks--id (buffer-local-value 'erc-networks--id
+ (get-buffer "foonet/tester"))
+ erc--target (erc--target-from-string "#a")))
+
+ (with-current-buffer (get-buffer-create "barnet/tester")
+ (erc-mode)
+ (setq erc-network 'barnet
+ erc-server-current-nick "tester"
+ erc-networks--id (make-erc-networks--id-qualifying
+ :symbol 'barnet/tester
+ :parts [barnet "tester"]
+ :len 2)
+ erc-server-process (erc-networks-tests--create-live-proc)))
+
+ (with-current-buffer (get-buffer-create "barnet/dummy")
+ (erc-mode)
+ (setq erc-network 'barnet
+ erc-server-current-nick "dummy"
+ erc-networks--id (make-erc-networks--id-qualifying
+ :symbol 'barnet/dummy
+ :parts [barnet "dummy"]
+ :len 2)
+ erc-server-process (erc-networks-tests--create-live-proc)))
+
+ (with-current-buffer (get-buffer-create "#a@barnet/tester")
+ (erc-mode)
+ (setq erc-network 'barnet
+ erc-server-current-nick "tester"
+ erc-server-process (buffer-local-value 'erc-server-process
+ (get-buffer "barnet/tester"))
+ erc-networks--id (buffer-local-value 'erc-networks--id
+ (get-buffer "barnet/tester"))
+ erc--target (erc--target-from-string "#a"))))
+
+(ert-deftest erc-networks--shrink-ids-and-buffer-names--hook-outstanding-srv ()
+ (erc-networks--shrink-ids-and-buffer-names--hook-outstanding-common)
+ (with-current-buffer (get-buffer-create "foonet/dummy")
+ (erc-mode)
+ (setq erc-network 'foonet
+ erc-server-current-nick "dummy"
+ erc-networks--id (make-erc-networks--id-qualifying
+ :symbol 'foonet/dummy
+ :parts [foonet "dummy"]
+ :len 2)
+ erc-server-process (erc-networks-tests--create-live-proc))
+ (kill-buffer))
+
+ (should (equal (mapcar #'buffer-name (erc-buffer-list))
+ '("foonet"
+ "#a@foonet"
+ "barnet/tester"
+ "barnet/dummy"
+ "#a@barnet/tester")))
+ (erc-networks-tests--clean-bufs))
+
+(ert-deftest erc-networks--shrink-ids-and-buffer-names--hook-outstanding-tgt ()
+ (erc-networks--shrink-ids-and-buffer-names--hook-outstanding-common)
+ (with-current-buffer (get-buffer-create "#a@foonet/dummy")
+ (erc-mode)
+ (setq erc-network 'foonet
+ erc-server-current-nick "dummy"
+ erc-networks--id (make-erc-networks--id-qualifying
+ :symbol 'foonet/dummy
+ :parts [foonet "dummy"]
+ :len 2)
+ erc--target (erc--target-from-string "#a")
+ erc-server-process (with-temp-buffer
+ (erc-networks-tests--create-dead-proc))))
+
+ (with-current-buffer "#a@foonet/dummy" (kill-buffer))
+
+ ;; Identical to *-server variant above
+ (should (equal (mapcar #'buffer-name (erc-buffer-list))
+ '("foonet"
+ "#a@foonet"
+ "barnet/tester"
+ "barnet/dummy"
+ "#a@barnet/tester")))
+ (erc-networks-tests--clean-bufs))
+
+(ert-deftest erc-networks-rename-surviving-target-buffer--shrink ()
+ (erc-networks--shrink-ids-and-buffer-names--hook-outstanding-common)
+
+ ;; This buffer isn't "#a@foonet" (yet) because the shrink-ids hook
+ ;; hasn't run. However, when it's the rename hook runs, its network
+ ;; id *is* "foonet", not "foonet/tester".
+ (with-current-buffer "#a@foonet/tester" (kill-buffer))
+
+ (should (equal (mapcar #'buffer-name (erc-buffer-list))
+ '("foonet"
+ "barnet/tester"
+ "barnet/dummy"
+ "#a")))
+
+ (erc-networks-tests--clean-bufs))
+
+(ert-deftest erc-networks--shrink-ids-and-buffer-names--server ()
+
+ (with-current-buffer (get-buffer-create "foonet/tester")
+ (erc-mode)
+ (setq erc-network 'foonet
+ erc-server-current-nick "tester"
+ erc-networks--id (make-erc-networks--id-qualifying
+ :symbol 'foonet/tester
+ :parts [foonet "tester"]
+ :len 2)
+ erc-server-process (erc-networks-tests--create-live-proc)))
+
+ (with-current-buffer (get-buffer-create "foonet/dummy")
+ (erc-mode)
+ (setq erc-network 'foonet
+ erc-server-current-nick "dummy"
+ erc-networks--id (make-erc-networks--id-qualifying
+ :symbol 'foonet/dummy
+ :parts [foonet "dummy"]
+ :len 2)
+ erc-server-process (erc-networks-tests--create-dead-proc))
+ (kill-buffer))
+
+ (should (equal (mapcar #'buffer-name (erc-buffer-list)) '("foonet")))
+
+ (erc-networks-tests--clean-bufs))
+
+(defun erc-networks--shrink-ids-and-buffer-names--hook-collapse (check)
+
+ (with-current-buffer (get-buffer-create "foonet/tester")
+ (erc-mode)
+ (setq erc-network 'foonet
+ erc-server-current-nick "tester"
+ erc-networks--id (make-erc-networks--id-qualifying
+ :symbol 'foonet/tester
+ :parts [foonet "tester"]
+ :len 2)
+ erc-server-process (erc-networks-tests--create-live-proc)))
+
+ (with-current-buffer (get-buffer-create "#a@foonet/tester")
+ (erc-mode)
+ (setq erc-server-process (buffer-local-value 'erc-server-process
+ (get-buffer "foonet/tester"))
+ erc-network 'foonet
+ erc-server-current-nick "tester"
+ erc-networks--id (buffer-local-value 'erc-networks--id
+ (get-buffer "foonet/tester"))
+ erc--target (erc--target-from-string "#a")))
+
+ (with-current-buffer (get-buffer-create "barnet/tester")
+ (erc-mode)
+ (setq erc-network 'barnet
+ erc-server-current-nick "tester"
+ erc-networks--id (make-erc-networks--id-qualifying
+ :symbol 'barnet/tester
+ :parts [barnet "tester"]
+ :len 2)
+ erc-server-process (erc-networks-tests--create-live-proc)))
+
+ (with-current-buffer (get-buffer-create "#b@foonet/tester")
+ (erc-mode)
+ (setq erc-network 'barnet
+ erc-server-current-nick "tester"
+ erc-server-process (buffer-local-value 'erc-server-process
+ (get-buffer "barnet/tester"))
+ erc-networks--id (buffer-local-value 'erc-networks--id
+ (get-buffer "barnet/tester"))
+ erc--target (erc--target-from-string "#b")))
+
+ (funcall check)
+
+ (should (equal (mapcar #'buffer-name (erc-buffer-list))
+ '("foonet" "#a" "barnet" "#b")))
+
+ (erc-networks-tests--clean-bufs))
+
+(ert-deftest erc-networks--shrink-ids-and-buffer-names--hook-collapse-server ()
+ (erc-networks--shrink-ids-and-buffer-names--hook-collapse
+ (lambda ()
+ (with-current-buffer (get-buffer-create "foonet/dummy")
+ (erc-mode)
+ (setq erc-network 'foonet
+ erc-server-current-nick "dummy"
+ erc-networks--id (make-erc-networks--id-qualifying
+ :symbol 'foonet/dummy
+ :parts [foonet "dummy"]
+ :len 2)
+ erc-server-process (erc-networks-tests--create-live-proc))
+ (kill-buffer)))))
+
+(ert-deftest erc-networks--shrink-ids-and-buffer-names--hook-collapse-target ()
+ (erc-networks--shrink-ids-and-buffer-names--hook-collapse
+ (lambda ()
+ (with-current-buffer (get-buffer-create "#a@foonet/dummy")
+ (erc-mode)
+ (setq erc-network 'foonet
+ erc-server-current-nick "dummy"
+ erc-networks--id (make-erc-networks--id-qualifying
+ :symbol 'foonet/dummy
+ :parts [foonet "dummy"]
+ :len 2)
+ ;; `erc-kill-buffer-function' uses legacy target detection
+ ;; but falls back on buffer name, so no need for:
+ ;;
+ ;; erc-default-recipients '("#a")
+ ;;
+ erc--target (erc--target-from-string "#a")
+ erc-server-process (with-temp-buffer
+ (erc-networks-tests--create-dead-proc)))
+ (kill-buffer)))))
+
+;; FIXME this test is old and may describe impossible states:
+;; leftover identities being qual-equal but not eq (implies
+;; `erc-networks--reclaim-orphaned-target-buffers' is somehow broken).
+;;
+;; Otherwise, the point of this test is to show that server process
+;; identity does not impact the hunt for duplicates.
+
+(defun erc-tests--prep-erc-networks--reconcile-buffer-names--duplicates (start)
+
+ (with-current-buffer (get-buffer-create "foonet")
+ (erc-mode)
+ (setq erc-network 'foonet
+ erc-server-current-nick "tester"
+ erc-networks--id (erc-networks--id-create nil)
+ erc-server-process (funcall start)))
+
+ (with-current-buffer (get-buffer-create "#chan") ; prior session
+ (erc-mode)
+ (setq erc-server-process (buffer-local-value 'erc-server-process
+ (get-buffer "foonet"))
+ erc--target (erc--target-from-string "#chan")
+ erc-networks--id (erc-networks--id-create nil)))
+
+ (ert-info ("Conflicts not recognized as ERC buffers and not renamed")
+ (get-buffer-create "#chan@foonet")
+ (should (equal (erc-networks-tests--bufnames "#chan")
+ '("#chan" "#chan@foonet"))))
+
+ ;; These are dupes (not "collisions")
+
+ (with-current-buffer "#chan@foonet" ; same proc
+ (erc-mode)
+ (setq erc--target (erc--target-from-string "#chan")
+ erc-network 'foonet
+ erc-server-current-nick "tester"
+ erc-server-process (buffer-local-value 'erc-server-process
+ (get-buffer "foonet"))
+ erc-networks--id (erc-networks--id-create nil)))
+
+ (with-current-buffer (get-buffer-create "#chan@foonet<dead>")
+ (erc-mode)
+ (setq erc--target (erc--target-from-string "#chan")
+ erc-server-process (erc-networks-tests--create-dead-proc)
+ erc-network 'foonet
+ erc-server-current-nick "tester"
+ erc-networks--id (erc-networks--id-create nil)))
+
+ (with-current-buffer (get-buffer-create "#chan@foonet<live>")
+ (erc-mode)
+ (setq erc--target (erc--target-from-string "#chan")
+ erc-server-process (erc-networks-tests--create-live-proc)
+ erc-network 'foonet
+ erc-server-current-nick "tester"
+ erc-networks--id (erc-networks--id-create nil)))
+
+ (let ((created (list (get-buffer "#chan@foonet<live>")
+ (get-buffer "#chan@foonet<dead>")
+ (get-buffer "#chan@foonet"))))
+
+ (with-current-buffer "foonet"
+ (should (string= (erc-networks--reconcile-buffer-names
+ (erc--target-from-string "#chan") erc-networks--id)
+ "#chan")))
+
+ (ert-info ("All buffers considered dupes renamed")
+ (should (equal (erc-networks-tests--bufnames "#chan")
+ '("#chan" "#chan<2>" "#chan<3>" "#chan<4>"))))
+
+ (ert-info ("All buffers renamed from newest to oldest")
+ (should (equal created (list (get-buffer "#chan<2>")
+ (get-buffer "#chan<3>")
+ (get-buffer "#chan<4>"))))))
+
+ (erc-networks-tests--clean-bufs))
+
+(defun erc-tests--prep-erc-networks--reconcile-buffer-names--dupes-given (go)
+
+ ;; The connection's network is discovered before target buffers are
+ ;; created. This shows that the network doesn't matter when only
+ ;; "given" IDs are present.
+ (with-current-buffer (get-buffer-create "oofnet")
+ (erc-mode)
+ (setq erc-networks--id (erc-networks--id-create 'oofnet)
+ erc-network 'foonet
+ erc-server-current-nick "tester"
+ erc-server-process (funcall go)))
+
+ (with-current-buffer (get-buffer-create "#chan") ; prior session
+ (erc-mode)
+ (setq erc-networks--id (erc-networks--id-create 'oofnet)
+ erc-server-process (buffer-local-value 'erc-server-process
+ (get-buffer "oofnet"))
+ erc--target (erc--target-from-string "#chan")))
+
+ (with-current-buffer (get-buffer-create "#chan@oofnet") ;dupe/not collision
+ (erc-mode)
+ (setq erc-networks--id (erc-networks--id-create 'oofnet)
+ erc-server-process (buffer-local-value 'erc-server-process
+ (get-buffer "oofnet"))
+ erc--target (erc--target-from-string "#chan")))
+
+ (with-current-buffer "oofnet"
+ (should (string= (erc-networks--reconcile-buffer-names
+ (erc--target-from-string "#chan") erc-networks--id)
+ "#chan")))
+
+ (ert-info ("All buffers matching target and network renamed")
+ (should (equal (erc-networks-tests--bufnames "#chan")
+ '("#chan" "#chan<2>"))))
+
+ (erc-networks-tests--clean-bufs))
+
+(ert-deftest erc-networks--reconcile-buffer-names--duplicates ()
+ (ert-info ("Process live, no error")
+ (erc-tests--prep-erc-networks--reconcile-buffer-names--duplicates
+ #'erc-networks-tests--create-live-proc))
+
+ (ert-info ("Process live, no error, given ID")
+ (erc-tests--prep-erc-networks--reconcile-buffer-names--dupes-given
+ #'erc-networks-tests--create-live-proc))
+
+ (ert-info ("Process dead")
+ (erc-tests--prep-erc-networks--reconcile-buffer-names--duplicates
+ #'erc-networks-tests--create-dead-proc))
+
+ (ert-info ("Process dead, given ID")
+ (erc-tests--prep-erc-networks--reconcile-buffer-names--dupes-given
+ #'erc-networks-tests--create-dead-proc)))
+
+(defun erc-tests--prep-erc-networks--reconcile-buffer-names--no-srv-buf (check)
+ (let ((foonet-proc (with-temp-buffer
+ (erc-networks-tests--create-dead-proc))))
+ (with-current-buffer (get-buffer-create "barnet")
+ (erc-mode)
+ (setq erc-network 'barnet
+ erc-server-current-nick "tester"
+ erc-networks--id (erc-networks--id-create nil)
+ erc-server-process (erc-networks-tests--create-dead-proc)))
+
+ ;; Different proc and not "qual-equal" (different elts)
+ (with-current-buffer (get-buffer-create "#chan")
+ (erc-mode)
+ (setq erc-network 'foonet
+ erc-server-current-nick "tester"
+ erc-networks--id (erc-networks--id-create nil)
+ erc--target (erc--target-from-string "#chan")
+ erc-server-process foonet-proc))
+ (funcall check)
+ (erc-networks-tests--clean-bufs)))
+
+(ert-deftest erc-networks--reconcile-buffer-names--no-server-buf ()
+ (ert-info ("Existing #chan buffer respected")
+ (erc-tests--prep-erc-networks--reconcile-buffer-names--no-srv-buf
+ (lambda ()
+ (with-current-buffer "barnet"
+ (should (string= (erc-networks--reconcile-buffer-names
+ (erc--target-from-string "#chan") erc-networks--id)
+ "#chan@barnet")))
+ (ert-info ("Existing #chan buffer found and renamed")
+ (should (equal (erc-networks-tests--bufnames "#chan")
+ '("#chan@foonet")))))))
+
+ (ert-info ("Existing #chan buffer")
+ (erc-tests--prep-erc-networks--reconcile-buffer-names--no-srv-buf
+ (lambda ()
+ (with-current-buffer (get-buffer-create "foonet")
+ (erc-mode)
+ (setq erc-network 'foonet
+ erc-server-current-nick "tester"
+ erc-networks--id (erc-networks--id-create nil)
+ erc-server-process (erc-networks-tests--create-dead-proc))
+ (should (string= (erc-networks--reconcile-buffer-names
+ (erc--target-from-string "#chan") erc-networks--id)
+ "#chan")))
+ (ert-info ("Nothing renamed")
+ (should (equal (erc-networks-tests--bufnames "#chan") '("#chan")))))))
+
+ (ert-info ("Existing #chan@foonet and #chan@barnet buffers")
+ (erc-tests--prep-erc-networks--reconcile-buffer-names--no-srv-buf
+ (lambda ()
+ (with-current-buffer "#chan"
+ (rename-buffer "#chan@foonet"))
+ (should-not (get-buffer "#chan@barnet"))
+ (with-current-buffer (get-buffer-create "#chan@barnet")
+ (erc-mode)
+ (setq erc--target (erc--target-from-string "#chan")
+ erc-server-process (buffer-local-value 'erc-server-process
+ (get-buffer "barnet"))
+ erc-networks--id (erc-networks--id-create nil)))
+ (with-current-buffer (get-buffer-create "foonet")
+ (erc-mode)
+ (setq erc-network 'foonet
+ erc-server-current-nick "tester"
+ erc-server-process (erc-networks-tests--create-live-proc)
+ erc-networks--id (erc-networks--id-create nil))
+ (set-process-query-on-exit-flag erc-server-process nil)
+ (should (string= (erc-networks--reconcile-buffer-names
+ (erc--target-from-string "#chan") erc-networks--id)
+ "#chan@foonet")))
+ (ert-info ("Nothing renamed")
+ (should (equal (erc-networks-tests--bufnames "#chan")
+ '("#chan@barnet" "#chan@foonet"))))))))
+
+(defun erc-tests--prep-erc-networks--reconcile-buffer-names--no-srv-buf-given
+ (check)
+ (let ((oofnet-proc (with-temp-buffer
+ (erc-networks-tests--create-dead-proc))))
+
+ (with-current-buffer (get-buffer-create "rabnet")
+ (erc-mode)
+ ;; Again, given name preempts network lookup (unrealistic but
+ ;; highlights priorities)
+ (setq erc-networks--id (erc-networks--id-create 'rabnet)
+ erc-network 'barnet
+ erc-server-current-nick "tester"
+ erc-server-process (erc-networks-tests--create-dead-proc)))
+
+ ;; Identity is not "qual-equal" to above
+ (with-current-buffer (get-buffer-create "#chan")
+ (erc-mode)
+ (setq erc-networks--id (erc-networks--id-create 'oofnet)
+ erc-network 'foonet
+ erc--target (erc--target-from-string "#chan")
+ erc-server-process oofnet-proc))
+ (funcall check)
+ (erc-networks-tests--clean-bufs)))
+
+(ert-deftest erc-networks--reconcile-buffer-names--no-server-buf-given ()
+
+ (ert-info ("Existing #chan buffer respected")
+ (erc-tests--prep-erc-networks--reconcile-buffer-names--no-srv-buf-given
+ (lambda ()
+ (with-current-buffer "rabnet"
+ (should (string= (erc-networks--reconcile-buffer-names
+ (erc--target-from-string "#chan") erc-networks--id)
+ "#chan@rabnet")))
+
+ (ert-info ("Existing #chan buffer found and renamed")
+ (should (equal (erc-networks-tests--bufnames "#chan")
+ '("#chan@oofnet")))))))
+
+ (ert-info ("Existing #chan@oofnet and #chan@rabnet buffers")
+ (erc-tests--prep-erc-networks--reconcile-buffer-names--no-srv-buf-given
+ (lambda ()
+ ;; #chan has already been uniquified (but not grown)
+ (with-current-buffer "#chan" (rename-buffer "#chan@oofnet"))
+ (should-not (get-buffer "#chan@rabnet"))
+
+ (with-current-buffer (get-buffer-create "#chan@rabnet")
+ (erc-mode)
+ (setq erc--target (erc--target-from-string "#chan")
+ erc-server-process (buffer-local-value 'erc-server-process
+ (get-buffer "rabnet"))
+ erc-networks--id (buffer-local-value 'erc-networks--id
+ (get-buffer "rabnet"))))
+
+ (with-current-buffer (get-buffer-create "oofnet")
+ (erc-mode)
+ (setq erc-network 'oofnet
+ erc-server-current-nick "tester"
+ erc-server-process (erc-networks-tests--create-live-proc)
+ erc-networks--id (erc-networks--id-create 'oofnet)) ; given
+ (set-process-query-on-exit-flag erc-server-process nil)
+ (should (string= (erc-networks--reconcile-buffer-names
+ (erc--target-from-string "#chan") erc-networks--id)
+ "#chan@oofnet")))
+
+ (ert-info ("Nothing renamed")
+ (should (equal (erc-networks-tests--bufnames "#chan")
+ '("#chan@oofnet" "#chan@rabnet"))))))))
+
+;; This shows a corner case where a user explicitly assigns a "given"
+;; ID via `erc-tls' but later connects again without one. It would
+;; actually probably be better if the given identity were to win and
+;; the derived one got an <n>-suffix.
+;;
+;; If we just compared net identities, the two would match, but they
+;; don't here because one has a given name and the other a
+;; discovered/assembled one; so they are *not* qual-equal.
+(ert-deftest erc-networks--reconcile-buffer-names--no-srv-buf-given-mismatch ()
+ ;; Existing #chan buffer *not* respected
+ (erc-tests--prep-erc-networks--reconcile-buffer-names--no-srv-buf-given
+ (lambda ()
+ (with-current-buffer (get-buffer-create "oofnet")
+ (erc-mode)
+ (setq erc-network 'oofnet
+ erc-server-current-nick "tester"
+ erc-server-process (erc-networks-tests--create-dead-proc)
+ erc-networks--id (erc-networks--id-create nil)) ; derived
+ (should (string= (erc-networks--reconcile-buffer-names
+ (erc--target-from-string "#chan") erc-networks--id)
+ "#chan@oofnet")))
+
+ (ert-info ("Collision renamed but not grown (because it's a given)")
+ ;; Original chan uniquified and moved out of the way
+ (should (equal (erc-networks-tests--bufnames "#chan")
+ '("#chan@oofnet<2>")))))))
+
+(defun erc-tests--prep-erc-networks--reconcile-buffer-names--multi-net (check)
+
+ (with-current-buffer (get-buffer-create "foonet")
+ (erc-mode)
+ (setq erc-network 'foonet
+ erc-server-current-nick "tester"
+ erc-server-process (erc-networks-tests--create-dead-proc)
+ erc-networks--id (erc-networks--id-create nil))) ; derived
+
+ (with-current-buffer (get-buffer-create "barnet")
+ (erc-mode)
+ (setq erc-network 'barnet
+ erc-server-current-nick "tester"
+ erc-server-process (erc-networks-tests--create-dead-proc)
+ erc-networks--id (erc-networks--id-create nil))) ; derived
+
+ (with-current-buffer
+ (get-buffer-create (elt ["#chan" "#chan@foonet"] (random 2)))
+ (erc-mode)
+ (setq erc--target (erc--target-from-string "#chan"))
+ (cl-multiple-value-setq (erc-server-process erc-networks--id)
+ (with-current-buffer "foonet"
+ (list erc-server-process erc-networks--id))))
+
+ (with-current-buffer (get-buffer-create "#chan@barnet")
+ (erc-mode)
+ (setq erc--target (erc--target-from-string "#chan"))
+ (cl-multiple-value-setq (erc-server-process erc-networks--id)
+ (with-current-buffer "barnet"
+ (list erc-server-process erc-networks--id))))
+
+ (funcall check)
+ (erc-networks-tests--clean-bufs))
+
+(ert-deftest erc-networks--reconcile-buffer-names--multi-net ()
+ (ert-info ("Same network rename")
+ (erc-tests--prep-erc-networks--reconcile-buffer-names--multi-net
+ (lambda ()
+ (with-current-buffer "foonet"
+ (let ((result (erc-networks--reconcile-buffer-names
+ (erc--target-from-string "#chan") erc-networks--id)))
+ (should (string= result "#chan@foonet"))))
+
+ (should (equal (erc-networks-tests--bufnames "#chan")
+ '("#chan@barnet" "#chan@foonet"))))))
+
+ (ert-info ("Same network keep name")
+ (erc-tests--prep-erc-networks--reconcile-buffer-names--multi-net
+ (lambda ()
+ (with-current-buffer "barnet"
+ (let ((result (erc-networks--reconcile-buffer-names
+ (erc--target-from-string "#chan") erc-networks--id)))
+ (should (string= result "#chan@barnet"))))
+
+ (should (equal (erc-networks-tests--bufnames "#chan")
+ '("#chan@barnet" "#chan@foonet")))))))
+
+(defun erc-tests--prep-erc-networks--reconcile-buffer-names--multi-net-given
+ (check)
+
+ (with-current-buffer (get-buffer-create "oofnet")
+ (erc-mode)
+ (setq erc-network 'foonet
+ erc-server-current-nick "tester"
+ erc-networks--id (erc-networks--id-create 'oofnet) ; one given
+ erc-server-process (erc-networks-tests--create-dead-proc)))
+
+ (with-current-buffer (get-buffer-create "rabnet")
+ (erc-mode)
+ (setq erc-network 'barnet
+ erc-server-current-nick "tester"
+ erc-networks--id (erc-networks--id-create 'rabnet) ; another given
+ erc-server-process (erc-networks-tests--create-dead-proc)))
+
+ (with-current-buffer (get-buffer-create (elt ["chan" "#chan@oofnet"]
+ (random 2)))
+ (erc-mode)
+ (setq erc--target (erc--target-from-string "#chan"))
+ (cl-multiple-value-setq (erc-server-process erc-networks--id)
+ (with-current-buffer "oofnet"
+ (list erc-server-process erc-networks--id))))
+
+ (with-current-buffer (get-buffer-create "#chan@barnet")
+ (erc-mode)
+ (setq erc--target (erc--target-from-string "#chan"))
+ (cl-multiple-value-setq (erc-server-process erc-networks--id)
+ (with-current-buffer "rabnet"
+ (list erc-server-process erc-networks--id))))
+
+ (funcall check)
+ (erc-networks-tests--clean-bufs))
+
+(ert-deftest erc-networks--reconcile-buffer-names--multi-net-given ()
+ (ert-info ("Same network rename")
+ (erc-tests--prep-erc-networks--reconcile-buffer-names--multi-net-given
+ (lambda ()
+ (with-current-buffer "oofnet"
+ (let ((result (erc-networks--reconcile-buffer-names
+ (erc--target-from-string "#chan") erc-networks--id)))
+ (should (string= result "#chan@oofnet"))))
+
+ (should (equal (erc-networks-tests--bufnames "#chan")
+ '("#chan@oofnet" "#chan@rabnet"))))))
+
+ (ert-info ("Same network keep name")
+ (erc-tests--prep-erc-networks--reconcile-buffer-names--multi-net-given
+ (lambda ()
+ (with-current-buffer "rabnet"
+ (let ((result (erc-networks--reconcile-buffer-names
+ (erc--target-from-string "#chan") erc-networks--id)))
+ (should (string= result "#chan@rabnet"))))
+
+ (should (equal (erc-networks-tests--bufnames "#chan")
+ '("#chan@oofnet" "#chan@rabnet")))))))
+
+(defun erc-tests--prep-erc-networks--reconcile-buffer-names--multi-net-mixed
+ (check)
+
+ (with-current-buffer (get-buffer-create "foonet")
+ (erc-mode)
+ (setq erc-network 'foonet
+ erc-server-current-nick "tester"
+ erc-networks--id (erc-networks--id-create nil) ; one derived
+ erc-server-process (erc-networks-tests--create-dead-proc)))
+
+ (with-current-buffer (get-buffer-create "my-conn")
+ (erc-mode)
+ (setq erc-network 'barnet
+ erc-server-current-nick "tester"
+ erc-networks--id (erc-networks--id-create 'my-conn) ; one given
+ erc-server-process (erc-networks-tests--create-dead-proc)))
+
+ (with-current-buffer (get-buffer-create (elt ["#chan" "#chan@foonet"]
+ (random 2)))
+ (erc-mode)
+ (setq erc--target (erc--target-from-string "#chan"))
+ (cl-multiple-value-setq (erc-server-process erc-networks--id)
+ (with-current-buffer "foonet"
+ (list erc-server-process erc-networks--id))))
+
+ (with-current-buffer (get-buffer-create "#chan@my-conn")
+ (erc-mode)
+ (setq erc--target (erc--target-from-string "#chan"))
+ (cl-multiple-value-setq (erc-server-process erc-networks--id)
+ (with-current-buffer "my-conn"
+ (list erc-server-process erc-networks--id))))
+
+ (funcall check)
+ (erc-networks-tests--clean-bufs))
+
+(ert-deftest erc-networks--reconcile-buffer-names--multi-net-existing ()
+
+ (ert-info ("Buf name derived from network")
+ (erc-tests--prep-erc-networks--reconcile-buffer-names--multi-net-mixed
+ (lambda ()
+ (with-current-buffer "foonet"
+ (let ((result (erc-networks--reconcile-buffer-names
+ (erc--target-from-string "#chan") erc-networks--id)))
+ (should (string= result "#chan@foonet"))))
+
+ (should (equal (erc-networks-tests--bufnames "#chan")
+ '("#chan@foonet" "#chan@my-conn"))))))
+
+ (ert-info ("Buf name given")
+ (erc-tests--prep-erc-networks--reconcile-buffer-names--multi-net-mixed
+ (lambda ()
+ (with-current-buffer "my-conn"
+ (let ((result (erc-networks--reconcile-buffer-names
+ (erc--target-from-string "#chan") erc-networks--id)))
+ (should (string= result "#chan@my-conn"))))
+
+ (should (equal (erc-networks-tests--bufnames "#chan")
+ '("#chan@foonet" "#chan@my-conn")))))))
+
+(ert-deftest erc-networks--reconcile-buffer-names--multi-net-suffixed ()
+ ;; Two networks, same channel. One network has two connections.
+ ;; When the same channel is joined on the latter under a different
+ ;; nick, all buffer names involving that network are suffixed with
+ ;; the network identity.
+
+ (with-current-buffer (get-buffer-create "foonet/bob")
+ (erc-mode)
+ (setq erc-network 'foonet
+ erc-server-current-nick "bob"
+ erc-networks--id (make-erc-networks--id-qualifying
+ :symbol 'foonet/bob
+ :parts [foonet "bob"]
+ :len 2)
+ erc-server-process (erc-networks-tests--create-live-proc)))
+
+ (with-current-buffer (get-buffer-create
+ (elt ["#chan@foonet" "#chan@foonet/bob"] (random 2)))
+ (erc-mode)
+ (setq erc--target (erc--target-from-string "#chan")
+ erc-server-process (buffer-local-value 'erc-server-process
+ (get-buffer "foonet/bob"))
+ erc-networks--id (buffer-local-value 'erc-networks--id
+ (get-buffer "foonet/bob"))))
+
+ (with-current-buffer (get-buffer-create "barnet")
+ (erc-mode)
+ (setq erc-network 'barnet
+ erc-server-current-nick (elt ["alice" "bob"] (random 2))
+ erc-networks--id (erc-networks--id-create 'barnet)
+ erc-server-process (erc-networks-tests--create-live-proc)))
+
+ (with-current-buffer (get-buffer-create "#chan@barnet")
+ (erc-mode)
+ (setq erc--target (erc--target-from-string "#chan")
+ erc-server-process (buffer-local-value 'erc-server-process
+ (get-buffer "barnet"))
+ erc-networks--id (buffer-local-value 'erc-networks--id
+ (get-buffer "barnet"))))
+
+ (with-current-buffer (get-buffer-create "foonet/alice")
+ (erc-mode)
+ (setq erc-network 'foonet
+ erc-server-current-nick "alice"
+ erc-networks--id (make-erc-networks--id-qualifying
+ :symbol 'foonet/alice
+ :parts [foonet "alice"]
+ :len 2)
+ erc-server-process (erc-networks-tests--create-live-proc)))
+
+ (with-current-buffer "foonet/alice"
+ (let ((result (erc-networks--reconcile-buffer-names
+ (erc--target-from-string "#chan") erc-networks--id)))
+ (should (string= result "#chan@foonet/alice"))))
+
+ (should (equal (erc-networks-tests--bufnames "#chan")
+ '("#chan@barnet" "#chan@foonet/bob")))
+
+ (erc-networks-tests--clean-bufs))
+
+(ert-deftest erc-networks--reconcile-buffer-names--local ()
+ (with-current-buffer (get-buffer-create "DALnet")
+ (erc-mode)
+ (setq erc-network 'DALnet
+ erc-server-announced-name "elysium.ga.us.dal.net"
+ erc-server-process (erc-networks-tests--create-dead-proc)
+ erc--isupport-params (make-hash-table)
+ erc-networks--id (erc-networks--id-create nil))
+ (puthash 'CHANTYPES '("&#") erc--isupport-params))
+
+ (ert-info ("Local chan buffer from older, disconnected identity")
+ (with-current-buffer (get-buffer-create "&chan")
+ (erc-mode)
+ ;; Cheat here because localp is determined on identity init
+ (setq erc--target (with-current-buffer "DALnet"
+ (erc--target-from-string "&chan"))
+ erc-network 'DALnet
+ erc-server-announced-name "twisted.ma.us.dal.net"
+ erc-server-process (erc-networks-tests--create-dead-proc)
+ erc-networks--id (erc-networks--id-create nil))))
+
+ (ert-info ("Local channels renamed using network server names")
+ (with-current-buffer "DALnet"
+ (let ((result (erc-networks--reconcile-buffer-names
+ (erc--target-from-string "&chan") erc-networks--id)))
+ (should (string= result "&chan@elysium.ga.us.dal.net")))))
+
+ (should (get-buffer "&chan@twisted.ma.us.dal.net"))
+ (should-not (get-buffer "&chan"))
+ (erc-networks-tests--clean-bufs))
+
+(ert-deftest erc-networks--set-name ()
+ (with-current-buffer (get-buffer-create "localhost:6667")
+ (let (erc-server-announced-name
+ (erc--isupport-params (make-hash-table))
+ erc-network
+ calls)
+ (erc-mode)
+
+ (cl-letf (((symbol-function 'erc-display-line)
+ (lambda (&rest r) (push r calls))))
+
+ (ert-info ("Signals when `erc-server-announced-name' unset")
+ (should-error (erc-networks--set-name nil (make-erc-response)))
+ (should-not calls))
+
+ (ert-info ("Signals when table empty and NETWORK param unset")
+ (setq erc-server-announced-name "irc.fake.gnu.org")
+ (let ((err (should-error (erc-networks--set-name
+ nil (make-erc-response)))))
+ (should (string-match-p "failed" (cadr err)))
+ (should (eq (car err) 'error)))
+ (should (string-match-p (rx "*** Failed") (car (pop calls)))))))
+
+ (erc-networks-tests--clean-bufs)))
+
+(ert-deftest erc-networks--ensure-announced ()
+ (with-current-buffer (get-buffer-create "localhost:6667")
+ (should (local-variable-if-set-p 'erc-server-announced-name))
+ (let (erc-insert-modify-hook
+ (erc-server-process (erc-networks-tests--create-live-proc))
+ (parsed (make-erc-response
+ :unparsed ":irc.barnet.org 422 tester :MOTD File is missing"
+ :sender "irc.barnet.org"
+ :command "422"
+ :command-args '("tester" "MOTD File is missing")
+ :contents "MOTD File is missing")))
+
+ (erc-mode) ; boilerplate displayable start (needs `erc-server-process')
+ (insert "\n\n")
+ (setq erc-input-marker (make-marker) erc-insert-marker (make-marker))
+ (set-marker erc-insert-marker (point-max))
+ (erc-display-prompt) ; boilerplate displayable end
+
+ (erc-networks--ensure-announced erc-server-process parsed)
+ (goto-char (point-min))
+ (search-forward "Failed")
+ (should (string= erc-server-announced-name "irc.barnet.org")))
+ (when noninteractive (kill-buffer))))
+
+(ert-deftest erc-networks--rename-server-buffer--no-existing--orphan ()
+ (with-current-buffer (get-buffer-create "#chan")
+ (erc-mode)
+ (setq erc-network 'FooNet
+ erc-server-current-nick "tester"
+ erc--target (erc--target-from-string "#chan")
+ erc-networks--id (erc-networks--id-create nil)))
+
+ (with-current-buffer (get-buffer-create "irc.foonet.org")
+ (erc-mode)
+ (setq erc-network 'FooNet
+ erc-server-current-nick "tester"
+ erc-server-process (erc-networks-tests--create-live-proc)
+ erc-networks--id (erc-networks--id-create nil))
+ (should-not (erc-networks--rename-server-buffer erc-server-process))
+ (should (string= (buffer-name) "FooNet")))
+
+ (ert-info ("Channel buffer reassociated")
+ (erc-server-process-alive "#chan")
+ (with-current-buffer "#chan"
+ (should erc-server-connected)
+ (erc-with-server-buffer
+ (should (string= (buffer-name) "FooNet")))))
+
+ (erc-networks-tests--clean-bufs))
+
+(ert-deftest erc-networks--rename-server-buffer--existing--reuse ()
+ (let* ((old-buf (get-buffer-create "FooNet"))
+ (old-proc (erc-networks-tests--create-dead-proc old-buf)))
+
+ (with-current-buffer old-buf
+ (erc-mode)
+ (insert "*** Old buf")
+ (setq erc-network 'FooNet
+ erc-server-current-nick "tester"
+ erc-insert-marker (set-marker (make-marker) (point-max))
+ erc-server-process old-proc
+ erc-networks--id (erc-networks--id-create nil)))
+
+ (with-current-buffer (get-buffer-create "#chan")
+ (erc-mode)
+ (setq erc-network 'FooNet
+ erc-server-process old-proc
+ erc-networks--id (erc-networks--id-create nil)
+ erc--target (erc--target-from-string "#chan")))
+
+ (ert-info ("New buffer steals name, content")
+ (with-current-buffer (get-buffer-create "irc.foonet.org")
+ (erc-mode)
+ (setq erc-network 'FooNet
+ erc-server-current-nick "tester"
+ erc-server-process (erc-networks-tests--create-live-proc)
+ erc-networks--id (erc-networks--id-create nil))
+ (should-not (erc-networks--rename-server-buffer erc-server-process))
+ (should (string= (buffer-name) "FooNet"))
+ (goto-char (point-min))
+ (should (search-forward "Old buf"))))
+
+ (ert-info ("Channel buffer reassociated")
+ (erc-server-process-alive "#chan")
+ (with-current-buffer "#chan"
+ (should erc-server-connected)
+ (should-not (eq erc-server-process old-proc))
+ (erc-with-server-buffer
+ (should (string= (buffer-name) "FooNet")))))
+
+ (ert-info ("Original buffer killed off")
+ (should-not (buffer-live-p old-buf))))
+
+ (erc-networks-tests--clean-bufs))
+
+;; This is for compatibility with pre-28.1 behavior. Basically, we're
+;; trying to match the behavior bug for bug. All buffers were always
+;; suffixed and never reassociated. 28.1 introduced a regression that
+;; reversed the latter, but we've reverted that.
+
+(ert-deftest erc-networks--rename-server-buffer--existing--noreuse ()
+ (with-suppressed-warnings ((obsolete erc-reuse-buffers))
+ (should erc-reuse-buffers) ; default
+ (let* ((old-buf (get-buffer-create "irc.foonet.org:6697/irc.foonet.org"))
+ (old-proc (erc-networks-tests--create-dead-proc old-buf))
+ erc-reuse-buffers)
+ (with-current-buffer old-buf
+ (erc-mode)
+ (insert "*** Old buf")
+ (setq erc-network 'FooNet
+ erc-server-current-nick "tester"
+ erc-insert-marker (set-marker (make-marker) (point-max))
+ erc-server-process old-proc
+ erc-networks--id (erc-networks--id-create nil)))
+ (with-current-buffer (get-buffer-create "#chan")
+ (erc-mode)
+ (setq erc-network 'FooNet
+ erc-server-process old-proc
+ erc-networks--id (buffer-local-value 'erc-networks--id old-buf)
+ erc--target (erc--target-from-string "#chan"))
+ (rename-buffer (erc-networks--construct-target-buffer-name erc--target)))
+
+ (ert-info ("Server buffer uniquely renamed")
+ (with-current-buffer
+ (get-buffer-create "irc.foonet.org:6697/irc.foonet.org<2>")
+ (erc-mode)
+ (setq erc-network 'FooNet
+ erc-server-current-nick "tester"
+ erc-server-process (erc-networks-tests--create-live-proc)
+ erc-networks--id (erc-networks--id-create nil))
+ (should-not (erc-networks--rename-server-buffer erc-server-process))
+ (should (string= (buffer-name)
+ "irc.foonet.org:6697/irc.foonet.org<2>"))
+ (goto-char (point-min))
+ (should-not (search-forward "Old buf" nil t))))
+
+ (ert-info ("Channel buffer not reassociated")
+ (should-not
+ (erc-server-process-alive
+ (should (get-buffer "#chan/irc.foonet.org"))))
+ (with-current-buffer (get-buffer "#chan/irc.foonet.org")
+ (should-not erc-server-connected)
+ (should (eq erc-server-process old-proc))
+ (erc-with-server-buffer
+ (should (string= (buffer-name)
+ "irc.foonet.org:6697/irc.foonet.org")))))
+
+ (ert-info ("Old buffer still around")
+ (should (buffer-live-p old-buf)))))
+ (erc-networks-tests--clean-bufs))
+
+(ert-deftest erc-networks--rename-server-buffer--reconnecting ()
+ (let* ((old-buf (get-buffer-create "FooNet"))
+ (old-proc (erc-networks-tests--create-dead-proc old-buf)))
+
+ (with-current-buffer old-buf
+ (erc-mode)
+ (insert "*** Old buf")
+ (setq erc-network 'FooNet
+ erc-server-current-nick "tester"
+ erc-insert-marker (set-marker (make-marker) (point-max))
+ erc-server-process old-proc
+ erc-networks--id (erc-networks--id-create nil)))
+
+ (with-current-buffer (get-buffer-create "#chan")
+ (erc-mode)
+ (setq erc-network 'FooNet
+ erc-server-process old-proc
+ erc--target (erc--target-from-string "#chan")
+ erc-networks--id (erc-networks--id-create nil)))
+
+ (ert-info ("No new buffer")
+ (with-current-buffer old-buf
+ (setq erc-server-process (erc-networks-tests--create-live-proc))
+ (should-not (erc-networks--rename-server-buffer erc-server-process))
+ (should (string= (buffer-name) "FooNet"))
+ (goto-char (point-min))
+ (should (search-forward "Old buf"))))
+
+ (ert-info ("Channel buffer updated with live proc")
+ (erc-server-process-alive "#chan")
+ (with-current-buffer "#chan"
+ (should erc-server-connected)
+ (should-not (eq erc-server-process old-proc))
+ (erc-with-server-buffer
+ (should (string= (buffer-name) "FooNet"))))))
+
+ (erc-networks-tests--clean-bufs))
+
+(ert-deftest erc-networks--rename-server-buffer--id ()
+ (let* ((old-buf (get-buffer-create "MySession"))
+ (old-proc (erc-networks-tests--create-dead-proc old-buf)))
+
+ (with-current-buffer old-buf
+ (erc-mode)
+ (insert "*** Old buf")
+ (setq erc-network 'FooNet
+ erc-networks--id (erc-networks--id-create 'MySession)
+ erc-insert-marker (set-marker (make-marker) (point-max))
+ erc-server-process old-proc))
+
+ (with-current-buffer (get-buffer-create "#chan")
+ (erc-mode)
+ (setq erc-network 'FooNet
+ erc-networks--id (erc-networks--id-create 'MySession)
+ erc-server-process old-proc
+ erc--target (erc--target-from-string "#chan")))
+
+ (ert-info ("No new buffer")
+ (with-current-buffer old-buf
+ (setq erc-server-process (erc-networks-tests--create-live-proc))
+ (should-not (erc-networks--rename-server-buffer erc-server-process))
+ (should (string= (buffer-name) "MySession"))
+ (goto-char (point-min))
+ (should (search-forward "Old buf"))))
+
+ (ert-info ("Channel buffer updated with live proc")
+ (erc-server-process-alive "#chan")
+ (with-current-buffer "#chan"
+ (should erc-server-connected)
+ (should-not (eq erc-server-process old-proc))
+ (erc-with-server-buffer
+ (should (string= (buffer-name) "MySession"))))))
+
+ (erc-networks-tests--clean-bufs))
+
+(ert-deftest erc-networks--rename-server-buffer--existing--live ()
+ (let* (erc-kill-server-hook
+ erc-insert-modify-hook
+ (old-buf (get-buffer-create "FooNet"))
+ (old-proc (erc-networks-tests--create-live-proc old-buf))) ; live
+
+ (with-current-buffer old-buf
+ (erc-mode)
+ (insert "*** Old buf")
+ (setq erc-network 'FooNet
+ erc-server-current-nick "tester"
+ erc-insert-marker (set-marker (make-marker) (point-max))
+ erc-server-process old-proc
+ erc-networks--id (erc-networks--id-create nil))
+ (should (erc-server-process-alive)))
+
+ (with-current-buffer (get-buffer-create "#chan")
+ (erc-mode)
+ (setq erc-network 'FooNet
+ erc-server-process old-proc
+ erc-networks--id (erc-networks--id-create nil)
+ erc-server-connected t
+ erc--target (erc--target-from-string "#chan")))
+
+ (ert-info ("New buffer rejected, abandoned, not killed")
+ (with-current-buffer (get-buffer-create "irc.foonet.org")
+ (erc-mode)
+ (setq erc-network 'FooNet
+ erc-server-current-nick "tester"
+ erc-insert-marker (set-marker (make-marker) (point-max))
+ erc-server-process (erc-networks-tests--create-live-proc)
+ erc-networks--id (erc-networks--id-create nil))
+ (should-not (erc-networks--rename-server-buffer erc-server-process))
+ (should (eq erc-active-buffer old-buf))
+ (should-not (erc-server-process-alive))
+ (should (string= (buffer-name) "irc.foonet.org"))
+ (goto-char (point-min))
+ (search-forward "still connected")))
+
+ (ert-info ("Channel buffer updated with live proc")
+ (should (erc-server-process-alive "#chan"))
+ (with-current-buffer "#chan"
+ (should erc-server-connected)
+ (should (erc-server-buffer-live-p))
+ (should (eq erc-server-process old-proc))
+ (should (buffer-live-p (process-buffer erc-server-process)))
+ (with-current-buffer (process-buffer erc-server-process)
+ (should (eq (current-buffer) (get-buffer "FooNet")))
+ (should (eq (current-buffer) old-buf))))))
+
+ (should (get-buffer "FooNet"))
+ (should (get-buffer "irc.foonet.org"))
+
+ (erc-networks-tests--clean-bufs))
+
+(ert-deftest erc-networks--rename-server-buffer--local-match ()
+ (let* ((old-buf (get-buffer-create "FooNet"))
+ (old-proc (erc-networks-tests--create-dead-proc old-buf)))
+
+ (with-current-buffer old-buf
+ (erc-mode)
+ (insert "*** Old buf")
+ (setq erc-network 'FooNet
+ erc-server-current-nick "tester"
+ erc-server-announced-name "us-east.foonet.org"
+ erc-insert-marker (set-marker (make-marker) (point-max))
+ erc-server-process old-proc
+ erc--isupport-params (make-hash-table)
+ erc-networks--id (erc-networks--id-create nil))
+ (puthash 'CHANTYPES '("&#") erc--isupport-params))
+
+ (with-current-buffer (get-buffer-create "&chan")
+ (erc-mode)
+ (setq erc-network 'FooNet
+ erc-server-process old-proc
+ erc-server-announced-name "us-east.foonet.org"
+ erc--target (erc--target-from-string "&chan")
+ erc-networks--id (erc-networks--id-create nil)))
+
+ (ert-info ("New server buffer steals name, content")
+ (with-current-buffer (get-buffer-create "irc.foonet.org")
+ (erc-mode)
+ (setq erc-network 'FooNet
+ erc-server-current-nick "tester"
+ erc-server-announced-name "us-east.foonet.org"
+ erc-server-process (erc-networks-tests--create-live-proc)
+ erc--isupport-params (make-hash-table)
+ erc-networks--id (erc-networks--id-create nil))
+ (puthash 'CHANTYPES '("&#") erc--isupport-params)
+ (should-not (erc-networks--rename-server-buffer erc-server-process))
+ (should (string= (buffer-name) "FooNet"))
+ (goto-char (point-min))
+ (should (search-forward "Old buf"))))
+
+ (ert-info ("Channel buffer reassociated when &local server matches")
+ (should (erc-server-process-alive "&chan"))
+ (with-current-buffer "&chan"
+ (should erc-server-connected)
+ (should-not (eq erc-server-process old-proc))
+ (erc-with-server-buffer
+ (should (string= (buffer-name) "FooNet")))))
+
+ (ert-info ("Original buffer killed off")
+ (should-not (buffer-live-p old-buf)))
+
+ (erc-networks-tests--clean-bufs)))
+
+(ert-deftest erc-networks--rename-server-buffer--local-nomatch ()
+ (let* ((old-buf (get-buffer-create "FooNet"))
+ (old-proc (erc-networks-tests--create-dead-proc old-buf)))
+
+ (with-current-buffer old-buf
+ (erc-mode)
+ (insert "*** Old buf")
+ (setq erc-network 'FooNet
+ erc-server-current-nick "tester"
+ erc-server-announced-name "us-west.foonet.org"
+ erc-insert-marker (set-marker (make-marker) (point-max))
+ erc-server-process old-proc
+ erc--isupport-params (make-hash-table)
+ erc-networks--id (erc-networks--id-create nil))
+ (puthash 'CHANTYPES '("&#") erc--isupport-params))
+
+ (with-current-buffer (get-buffer-create "&chan")
+ (erc-mode)
+ (setq erc-network 'FooNet
+ erc-server-process old-proc
+ erc-server-announced-name "us-west.foonet.org" ; west
+ erc--target (erc--target-from-string "&chan")
+ erc-networks--id (erc-networks--id-create nil)))
+
+ (ert-info ("New server buffer steals name, content")
+ (with-current-buffer (get-buffer-create "irc.foonet.org")
+ (erc-mode)
+ (setq erc-network 'FooNet
+ erc-server-current-nick "tester"
+ erc-server-announced-name "us-east.foonet.org" ; east
+ erc-server-process (erc-networks-tests--create-live-proc)
+ erc--isupport-params (make-hash-table)
+ erc-networks--id (erc-networks--id-create nil))
+
+ (puthash 'CHANTYPES '("&#") erc--isupport-params)
+ (should-not (erc-networks--rename-server-buffer erc-server-process))
+ (should (string= (buffer-name) "FooNet"))
+ (goto-char (point-min))
+ (should (search-forward "Old buf"))))
+
+ (ert-info ("Channel buffer now orphaned even though network matches")
+ (should-not (erc-server-process-alive "&chan"))
+ (with-current-buffer "&chan"
+ (should-not erc-server-connected)
+ (should (eq erc-server-process old-proc))
+ (erc-with-server-buffer
+ (should (string= (buffer-name) "FooNet")))))
+
+ (ert-info ("Original buffer killed off")
+ (should-not (buffer-live-p old-buf)))
+
+ (erc-networks-tests--clean-bufs)))
+
+(ert-deftest erc-networks--update-server-identity--double-existing ()
+ (with-temp-buffer
+ (erc-mode)
+ (setq erc-networks--id (make-erc-networks--id-qualifying
+ :parts [foonet "bob"] :len 1))
+
+ (with-current-buffer (get-buffer-create "#chan@foonet/bob")
+ (erc-mode)
+ (setq erc-networks--id (make-erc-networks--id-qualifying
+ :parts [foonet "bob"] :len 2)))
+ (with-current-buffer (get-buffer-create "foonet/alice")
+ (erc-mode)
+ (setq erc-networks--id
+ (make-erc-networks--id-qualifying :parts [foonet "alice"] :len 2)))
+
+ (ert-info ("Adopt equivalent identity")
+ (should (eq (erc-networks--update-server-identity)
+ (buffer-local-value 'erc-networks--id
+ (get-buffer "#chan@foonet/bob")))))
+
+ (ert-info ("Ignore non-matches")
+ (should-not (erc-networks--update-server-identity))
+ (should (eq erc-networks--id
+ (buffer-local-value 'erc-networks--id
+ (get-buffer "#chan@foonet/bob"))))))
+
+ (erc-networks-tests--clean-bufs))
+
+(ert-deftest erc-networks--update-server-identity--double-new ()
+ (with-temp-buffer
+ (erc-mode)
+ (setq erc-networks--id (make-erc-networks--id-qualifying
+ :parts [foonet "bob"] :len 1))
+
+ (with-current-buffer (get-buffer-create "foonet/alice")
+ (erc-mode)
+ (setq erc-networks--id
+ (make-erc-networks--id-qualifying :parts [foonet "alice"] :len 2)))
+ (with-current-buffer (get-buffer-create "#chan@foonet/alice")
+ (erc-mode)
+ (setq erc-networks--id (buffer-local-value 'erc-networks--id
+ (get-buffer "foonet/alice"))))
+
+ (ert-info ("Evolve identity to prevent ambiguity")
+ (should-not (erc-networks--update-server-identity))
+ (should (= (erc-networks--id-qualifying-len erc-networks--id) 2))
+ (should (eq (erc-networks--id-symbol erc-networks--id) 'foonet/bob))))
+
+ (erc-networks-tests--clean-bufs))
+
+(ert-deftest erc-networks--update-server-identity--double-bounded ()
+ (with-temp-buffer
+ (erc-mode)
+ (setq erc-networks--id (make-erc-networks--id-qualifying
+ :parts [foonet "bob"] :len 1))
+
+ (with-current-buffer (get-buffer-create "foonet/alice/home")
+ (erc-mode)
+ (setq erc-networks--id (make-erc-networks--id-qualifying
+ :parts [foonet "alice" home] :len 3)))
+ (with-current-buffer (get-buffer-create "#chan@foonet/alice/home")
+ (erc-mode)
+ (setq erc-networks--id
+ (buffer-local-value 'erc-networks--id
+ (get-buffer "foonet/alice/home"))))
+
+ (ert-info ("Evolve identity to prevent ambiguity")
+ (should-not (erc-networks--update-server-identity))
+ (should (= (erc-networks--id-qualifying-len erc-networks--id) 2))
+ (should (eq (erc-networks--id-symbol erc-networks--id) 'foonet/bob))))
+
+ (erc-networks-tests--clean-bufs))
+
+(ert-deftest erc-networks--update-server-identity--double-even ()
+ (with-temp-buffer
+ (erc-mode)
+ (setq erc-networks--id
+ (make-erc-networks--id-qualifying :parts [foonet "bob"] :len 1))
+
+ (with-current-buffer (get-buffer-create "foonet")
+ (erc-mode)
+ (setq erc-networks--id
+ (make-erc-networks--id-qualifying :parts [foonet "alice"] :len 1)))
+ (with-current-buffer (get-buffer-create "#chan")
+ (erc-mode)
+ (setq erc--target (erc--target-from-string "#chan")
+ erc-networks--id (buffer-local-value 'erc-networks--id
+ (get-buffer "foonet"))))
+
+ (ert-info ("Evolve identity to prevent ambiguity")
+ (should-not (erc-networks--update-server-identity))
+ (should (= (erc-networks--id-qualifying-len erc-networks--id) 2))
+ (should (eq (erc-networks--id-symbol erc-networks--id) 'foonet/bob)))
+
+ (ert-info ("Collision renamed")
+ (with-current-buffer "foonet/alice"
+ (should (eq (erc-networks--id-symbol erc-networks--id) 'foonet/alice)))
+
+ (with-current-buffer "#chan@foonet/alice"
+ (should (eq (erc-networks--id-symbol erc-networks--id)
+ 'foonet/alice)))))
+
+ (erc-networks-tests--clean-bufs))
+
+(ert-deftest erc-networks--update-server-identity--triple-new ()
+ (with-temp-buffer
+ (erc-mode)
+ (setq erc-networks--id
+ (make-erc-networks--id-qualifying :parts [foonet "bob" home] :len 1))
+
+ (with-current-buffer (get-buffer-create "foonet/bob/office")
+ (erc-mode)
+ (setq erc-networks--id
+ (make-erc-networks--id-qualifying :parts [foonet "bob" office]
+ :len 3)))
+ (with-current-buffer (get-buffer-create "#chan@foonet/bob/office")
+ (erc-mode)
+ (setq erc-networks--id
+ (buffer-local-value 'erc-networks--id
+ (get-buffer "foonet/bob/office"))))
+
+ (ert-info ("Extend our identity's canonical ID so that it's unique")
+ (should-not (erc-networks--update-server-identity))
+ (should (= (erc-networks--id-qualifying-len erc-networks--id) 3))))
+
+ (erc-networks-tests--clean-bufs))
+
+;;; erc-networks-tests.el ends here
diff --git a/test/lisp/erc/erc-scenarios-auth-source.el b/test/lisp/erc/erc-scenarios-auth-source.el
new file mode 100644
index 00000000000..3d399a18154
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-auth-source.el
@@ -0,0 +1,178 @@
+;;; erc-scenarios-auth-source.el --- auth-source scenarios -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+;; Commentary:
+;;
+;; For practical reasons (mainly lack of imagination), this file
+;; contains tests for both server-password and NickServ contexts.
+
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-scenarios-common)))
+
+(eval-when-compile (require 'erc-join)
+ (require 'erc-services))
+
+(defun erc-scenarios-common--auth-source (id dialog &rest rest)
+ (push "machine GNU.chat port %d user \"#chan\" password spam" rest)
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "base/auth-source")
+ (dumb-server (erc-d-run "localhost" t dialog))
+ (port (process-contact dumb-server :service))
+ (ents `(,@(mapcar (lambda (fmt) (format fmt port)) rest)
+ "machine MyHost port irc password 123"))
+ (netrc-file (make-temp-file "auth-source-test" nil nil
+ (string-join ents "\n")))
+ (auth-sources (list netrc-file))
+ (auth-source-do-cache nil)
+ (erc-scenarios-common-extra-teardown (lambda ()
+ (delete-file netrc-file))))
+
+ (ert-info ("Connect")
+ (with-current-buffer (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :full-name "tester"
+ :id id)
+ (should (string= (buffer-name) (if id
+ (symbol-name id)
+ (format "127.0.0.1:%d" port))))
+ (erc-d-t-wait-for 5 (eq erc-network 'FooNet))))))
+
+(ert-deftest erc-scenarios-base-auth-source-server--dialed ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common--auth-source
+ nil 'foonet
+ "machine GNU.chat port %d user tester password fake"
+ "machine FooNet port %d user tester password fake"
+ "machine 127.0.0.1 port %d user tester password changeme"
+ "machine 127.0.0.1 port %d user imposter password fake"))
+
+(ert-deftest erc-scenarios-base-auth-source-server--netid ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common--auth-source
+ 'MySession 'foonet
+ "machine MySession port %d user tester password changeme"
+ "machine 127.0.0.1 port %d user tester password fake"
+ "machine FooNet port %d user tester password fake"))
+
+(ert-deftest erc-scenarios-base-auth-source-server--netid-custom ()
+ :tags '(:expensive-test)
+ (let ((erc-auth-source-server-function
+ (lambda (&rest _) (erc-auth-source-search :host "MyHost"))))
+ (erc-scenarios-common--auth-source
+ 'MySession 'foonet
+ "machine 127.0.0.1 port %d user tester password fake"
+ "machine MyHost port %d user tester password changeme"
+ "machine MySession port %d user tester password fake")))
+
+(ert-deftest erc-scenarios-base-auth-source-server--nopass ()
+ :tags '(:expensive-test)
+ (let (erc-auth-source-server-function)
+ (erc-scenarios-common--auth-source nil 'nopass)))
+
+(ert-deftest erc-scenarios-base-auth-source-server--nopass-netid ()
+ :tags '(:expensive-test)
+ (let (erc-auth-source-server-function)
+ (erc-scenarios-common--auth-source 'MySession 'nopass)))
+
+;; Identify via auth source with no initial password
+
+(defun erc-scenarios-common--services-auth-source (&rest rest)
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "services/auth-source")
+ (erc-server-flood-penalty 0.1)
+ (dumb-server (erc-d-run "localhost" t 'libera))
+ (port (process-contact dumb-server :service))
+ (ents `(,@(mapcar (lambda (fmt) (format fmt port)) rest)
+ "machine MyHost port irc password 123"))
+ (netrc-file (make-temp-file "auth-source-test" nil nil
+ (string-join ents "\n")))
+ (auth-sources (list netrc-file))
+ (auth-source-do-cache nil)
+ (erc-modules (cons 'services erc-modules))
+ (erc-use-auth-source-for-nickserv-password t) ; do consult for NickServ
+ (expect (erc-d-t-make-expecter))
+ (erc-scenarios-common-extra-teardown (lambda ()
+ (delete-file netrc-file))))
+
+ (cl-letf (((symbol-function 'read-passwd)
+ (lambda (&rest _) (error "Unexpected read-passwd call"))))
+ (ert-info ("Connect without password")
+ (with-current-buffer (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :full-name "tester")
+ (should (string= (buffer-name) (format "127.0.0.1:%d" port)))
+ (erc-d-t-wait-for 8 (eq erc-network 'Libera.Chat))
+ (funcall expect 3 "This nickname is registered.")
+ (funcall expect 3 "You are now identified")
+ (funcall expect 3 "Last login from")
+ (erc-cmd-QUIT ""))))
+
+ (erc-services-mode -1)
+
+ (should-not (memq 'services erc-modules))))
+
+;; These tests are about authenticating to nick services
+
+(ert-deftest erc-scenarios-services-auth-source--network ()
+ :tags '(:expensive-test)
+ ;; Skip consulting auth-source for the server password (PASS).
+ (let (erc-auth-source-server-function)
+ (erc-scenarios-common--services-auth-source
+ "machine 127.0.0.1 port %d user tester password spam"
+ "machine zirconium.libera.chat port %d user tester password fake"
+ "machine Libera.Chat port %d user tester password changeme")))
+
+(ert-deftest erc-scenarios-services-auth-source--network-connect-lookup ()
+ :tags '(:expensive-test)
+ ;; Do consult auth-source for the server password (and find nothing)
+ (erc-scenarios-common--services-auth-source
+ "machine zirconium.libera.chat port %d user tester password fake"
+ "machine Libera.Chat port %d user tester password changeme"))
+
+(ert-deftest erc-scenarios-services-auth-source--announced ()
+ :tags '(:expensive-test)
+ (let (erc-auth-source-server-function)
+ (erc-scenarios-common--services-auth-source
+ "machine 127.0.0.1 port %d user tester password spam"
+ "machine zirconium.libera.chat port %d user tester password changeme")))
+
+(ert-deftest erc-scenarios-services-auth-source--dialed ()
+ :tags '(:expensive-test)
+ ;; Support legacy host -> domain name
+ ;; (likely most common in real configs)
+ (let (erc-auth-source-server-function)
+ (erc-scenarios-common--services-auth-source
+ "machine 127.0.0.1 port %d user tester password changeme")))
+
+(ert-deftest erc-scenarios-services-auth-source--custom ()
+ :tags '(:expensive-test)
+ (let (erc-auth-source-server-function
+ (erc-auth-source-services-function
+ (lambda (&rest _) (erc-auth-source-search :host "MyAccount"))))
+ (erc-scenarios-common--services-auth-source
+ "machine zirconium.libera.chat port %d user tester password spam"
+ "machine MyAccount port %d user tester password changeme"
+ "machine 127.0.0.1 port %d user tester password fake")))
+
+;;; erc-scenarios-auth-source.el ends here
diff --git a/test/lisp/erc/erc-scenarios-base-association-nick.el b/test/lisp/erc/erc-scenarios-base-association-nick.el
new file mode 100644
index 00000000000..3e848be4df2
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-base-association-nick.el
@@ -0,0 +1,163 @@
+;;; erc-scenarios-base-association-nick.el --- base assoc scenarios -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-scenarios-common)))
+
+(eval-when-compile (require 'erc-join))
+
+;; You register a new nick, disconnect, and log back in, but your nick
+;; is not granted, so ERC obtains a backtick'd version. You open a
+;; query buffer for NickServ, and ERC names it using the net-ID (which
+;; includes the backtick'd nick) as a suffix. The original
+;; (disconnected) NickServ buffer gets renamed with *its* net-ID as
+;; well. You then identify to NickServ, and the dead session is no
+;; longer considered distinct.
+
+(ert-deftest erc-scenarios-base-association-nick-bumped ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "base/assoc/bumped")
+ (dumb-server (erc-d-run "localhost" t 'renicked 'again))
+ (port (process-contact dumb-server :service))
+ (expect (erc-d-t-make-expecter))
+ (erc-server-flood-penalty 0.5)
+ (erc-server-flood-margin 30))
+
+ (ert-info ("Connect to foonet with nick tester")
+ (with-current-buffer (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :full-name "tester")
+ (erc-scenarios-common-assert-initial-buf-name nil port)
+ (erc-d-t-wait-for 5 (eq erc-network 'foonet))))
+
+ (ert-info ("Create an account for tester and quit")
+ (with-current-buffer "foonet"
+ (funcall expect 3 "debug mode")
+
+ (erc-cmd-QUERY "NickServ")
+ (with-current-buffer "NickServ"
+ (erc-scenarios-common-say "REGISTER changeme")
+ (funcall expect 5 "Account created")
+ (funcall expect 1 "You're now logged in as tester"))
+
+ (with-current-buffer "foonet"
+ (erc-cmd-QUIT "")
+ (erc-d-t-wait-for 4 (not (erc-server-process-alive)))
+ (funcall expect 5 "ERC finished"))))
+
+ (with-current-buffer "foonet"
+ (erc-cmd-RECONNECT))
+
+ (erc-d-t-wait-for 10 "Nick request rejection prevents reassociation (good)"
+ (get-buffer "foonet/tester`"))
+
+ (ert-info ("Ask NickServ to change nick")
+ (with-current-buffer "foonet/tester`"
+ (funcall expect 3 "already in use")
+ (funcall expect 3 "debug mode")
+ (erc-cmd-QUERY "NickServ"))
+
+ (erc-d-t-wait-for 1 "Dead NickServ query buffer renamed, now qualified"
+ (get-buffer "NickServ@foonet/tester"))
+
+ (with-current-buffer "NickServ@foonet/tester`" ; new one
+ (erc-scenarios-common-say "IDENTIFY tester changeme")
+ (funcall expect 5 "You're now logged in as tester")
+ (ert-info ("Original buffer found, reused")
+ (erc-d-t-wait-for 2 (equal (buffer-name) "NickServ")))))
+
+ (ert-info ("Ours is the only NickServ buffer that remains")
+ (should-not (cdr (erc-scenarios-common-buflist "NickServ"))))
+
+ (ert-info ("Visible network ID truncated to one component")
+ (should (not (get-buffer "foonet/tester`")))
+ (should (not (get-buffer "foonet/tester")))
+ (should (get-buffer "foonet")))))
+
+;; A less common variant is when your bouncer switches to an alternate
+;; nick while you're disconnected, and upon reconnecting, you get
+;; a new nick.
+
+(ert-deftest erc-scenarios-base-association-nick-bumped-mandated-renick ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "base/assoc/bumped")
+ (dumb-server (erc-d-run "localhost" t 'foisted 'refoisted))
+ (port (process-contact dumb-server :service))
+ (expect (erc-d-t-make-expecter))
+ (erc-server-flood-penalty 0.5)
+ (erc-server-flood-margin 30))
+
+ (ert-info ("Connect to foonet with nick tester")
+ (with-current-buffer (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :full-name "tester")
+ (erc-scenarios-common-assert-initial-buf-name nil port)
+ (erc-d-t-wait-for 5 (eq erc-network 'foonet))))
+
+ (ert-info ("Greet bob and quit")
+ (with-current-buffer "foonet"
+ (funcall expect 3 "debug mode")
+
+ (erc-cmd-QUERY "bob")
+ (with-current-buffer "bob"
+ (erc-scenarios-common-say "hi")
+ (funcall expect 5 "hola")
+ (funcall expect 1 "how r u?"))
+
+ (with-current-buffer "foonet"
+ (erc-cmd-QUIT "")
+ (erc-d-t-wait-for 4 (not (erc-server-process-alive)))
+ (funcall expect 5 "ERC finished"))))
+
+ ;; Since we use reconnect, a new buffer won't be created
+ ;; TODO add variant with clean `erc' invocation
+ (with-current-buffer "foonet"
+ (erc-cmd-RECONNECT))
+
+ (ert-info ("Server-initiated renick")
+ (with-current-buffer (erc-d-t-wait-for 10 (get-buffer "foonet/dummy"))
+ (should-not (get-buffer "foonet/tester"))
+ (funcall expect 15 "debug mode"))
+
+ (erc-d-t-wait-for 1 "Old query renamed, now qualified"
+ (get-buffer "bob@foonet/tester"))
+
+ (with-current-buffer (erc-d-t-wait-for 5 (get-buffer "bob@foonet/dummy"))
+ (erc-cmd-NICK "tester")
+ (ert-info ("Buffers combined")
+ (erc-d-t-wait-for 2 (equal (buffer-name) "bob")))))
+
+ (with-current-buffer "foonet"
+ (funcall expect 5 "You're now logged in as tester"))
+
+ (ert-info ("Ours is the only bob buffer that remains")
+ (should-not (cdr (erc-scenarios-common-buflist "bob"))))
+
+ (ert-info ("Visible network ID truncated to one component")
+ (should (not (get-buffer "foonet/dummy")))
+ (should (get-buffer "foonet")))))
+
+;;; erc-scenarios-base-association-nick.el ends here
diff --git a/test/lisp/erc/erc-scenarios-base-association-samenet.el b/test/lisp/erc/erc-scenarios-base-association-samenet.el
new file mode 100644
index 00000000000..b7c7079df34
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-base-association-samenet.el
@@ -0,0 +1,144 @@
+;;; erc-scenarios-base-association-samenet.el --- assoc samenet scenarios -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-scenarios-common)))
+
+(declare-function erc-network-name "erc-networks")
+(declare-function erc-network "erc-networks")
+(defvar erc-autojoin-channels-alist)
+(defvar erc-network)
+
+;; One network, two simultaneous connections, no IDs.
+;; Reassociates on reconnect with and without server buffer.
+
+(defun erc-scenarios-common--base-association-samenet (after)
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "base/assoc/samenet")
+ (dumb-server (erc-d-run "localhost" t 'tester 'chester 'tester2))
+ (port (process-contact dumb-server :service))
+ (expect (erc-d-t-make-expecter))
+ (erc-server-flood-penalty 0.5)
+ (erc-server-flood-margin 30))
+
+ (ert-info ("Connect to foonet with nick tester")
+ (with-current-buffer (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :password "changeme"
+ :full-name "tester")
+ (erc-scenarios-common-assert-initial-buf-name nil port)
+ (erc-d-t-wait-for 5 (eq erc-network 'foonet))))
+
+ (ert-info ("Connect to foonet with nick chester")
+ (with-current-buffer (erc :server "127.0.0.1"
+ :port port
+ :nick "chester"
+ :password "changeme"
+ :full-name "chester")
+ (erc-scenarios-common-assert-initial-buf-name nil port)))
+
+ (erc-d-t-wait-for 3 "Dialed Buflist is Empty"
+ (not (erc-scenarios-common-buflist "127.0.0.1")))
+
+ (with-current-buffer "foonet/tester"
+ (funcall expect 3 "debug mode")
+ (erc-cmd-JOIN "#chan"))
+
+ (erc-d-t-wait-for 10 (get-buffer "#chan@foonet/tester"))
+ (with-current-buffer "foonet/chester" (funcall expect 3 "debug mode"))
+ (erc-d-t-wait-for 10 (get-buffer "#chan@foonet/chester"))
+
+ (ert-info ("Nick tester sees other nick chester in channel")
+ (with-current-buffer "#chan@foonet/tester"
+ (funcall expect 5 "chester")
+ (funcall expect 5 "find the forester")
+ (erc-cmd-QUIT "")))
+
+ (ert-info ("Nick chester sees other nick tester in same channel")
+ (with-current-buffer "#chan@foonet/chester"
+ (funcall expect 5 "tester")
+ (funcall expect 5 "find the forester")))
+
+ (funcall after expect)))
+
+(ert-deftest erc-scenarios-base-association-samenet--reconnect-one ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common--base-association-samenet
+ (lambda (expect)
+
+ (ert-info ("Connection tester reconnects")
+ (with-current-buffer "foonet/tester"
+ (erc-d-t-wait-for 10 (not (erc-server-process-alive)))
+ (funcall expect 10 "*** ERC finished")
+ (erc-cmd-RECONNECT)
+ (funcall expect 5 "debug mode")))
+
+ (ert-info ("Reassociated to same channel")
+ (with-current-buffer "#chan@foonet/tester"
+ (funcall expect 5 "chester")
+ (funcall expect 5 "welcome again")
+ (erc-cmd-QUIT "")))
+
+ (with-current-buffer "#chan@foonet/chester"
+ (funcall expect 5 "tester")
+ (funcall expect 5 "welcome again")
+ (funcall expect 5 "welcome again")
+ (erc-cmd-QUIT "")))))
+
+(ert-deftest erc-scenarios-base-association-samenet--new-buffer ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common--base-association-samenet
+ (lambda (expect)
+
+ (ert-info ("Tester kills buffer and connects from scratch")
+
+ (let (port)
+ (with-current-buffer "foonet/tester"
+ (erc-d-t-wait-for 10 (not (erc-server-process-alive)))
+ (funcall expect 10 "*** ERC finished")
+ (setq port erc-session-port)
+ (kill-buffer))
+
+ (with-current-buffer (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :password "changeme"
+ :full-name "tester")
+
+ (erc-d-t-wait-for 5 (eq erc-network 'foonet)))))
+
+ (with-current-buffer "foonet/tester" (funcall expect 3 "debug mode"))
+
+ (ert-info ("Reassociated to same channel")
+ (with-current-buffer "#chan@foonet/tester"
+ (funcall expect 5 "chester")
+ (funcall expect 5 "welcome again")
+ (erc-cmd-QUIT "")))
+
+ (with-current-buffer "#chan@foonet/chester"
+ (funcall expect 5 "tester")
+ (funcall expect 5 "welcome again")
+ (funcall expect 5 "welcome again")
+ (erc-cmd-QUIT "")))))
+
+;;; erc-scenarios-base-association-samenet.el ends here
diff --git a/test/lisp/erc/erc-scenarios-base-association.el b/test/lisp/erc/erc-scenarios-base-association.el
new file mode 100644
index 00000000000..83e5101e3ad
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-base-association.el
@@ -0,0 +1,192 @@
+;;; erc-scenarios-base-association.el --- base assoc scenarios -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-scenarios-common)))
+
+(declare-function erc-network-name "erc-networks")
+(declare-function erc-network "erc-networks")
+(defvar erc-autojoin-channels-alist)
+(defvar erc-network)
+
+;; Two networks, same channel name, no confusion (no bouncer). Some
+;; of this draws from bug#47522 "foil-in-server-buf". It shows that
+;; disambiguation-related changes added for bug#48598 are not specific
+;; to bouncers.
+
+(defun erc-scenarios-common--base-association-multi-net (second-join)
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "base/assoc/multi-net")
+ (erc-server-flood-penalty 0.1)
+ (dumb-server-foonet-buffer (get-buffer-create "*server-foonet*"))
+ (dumb-server-barnet-buffer (get-buffer-create "*server-barnet*"))
+ (dumb-server-foonet (erc-d-run "localhost" t "server-foonet" 'foonet))
+ (dumb-server-barnet (erc-d-run "localhost" t "server-barnet" 'barnet))
+ (expect (erc-d-t-make-expecter)))
+
+ (ert-info ("Connect to foonet, join #chan")
+ (with-current-buffer
+ (erc :server "127.0.0.1"
+ :port (process-contact dumb-server-foonet :service)
+ :nick "tester"
+ :password "changeme"
+ :full-name "tester")
+ (funcall expect 3 "debug mode")
+ (erc-cmd-JOIN "#chan")))
+
+ (erc-d-t-wait-for 2 (get-buffer "#chan"))
+
+ (ert-info ("Connect to barnet, join #chan")
+ (with-current-buffer
+ (erc :server "127.0.0.1"
+ :port (process-contact dumb-server-barnet :service)
+ :nick "tester"
+ :password "changeme"
+ :full-name "tester")
+ (funcall expect 5 "debug mode")))
+
+ (funcall second-join)
+
+ (erc-d-t-wait-for 3 (get-buffer "#chan@barnet"))
+
+ (erc-d-t-wait-for 2 "Buf #chan now #chan@foonet"
+ (and (get-buffer "#chan@foonet") (not (get-buffer "#chan"))))
+
+ (ert-info ("All #chan@foonet output consumed")
+ (with-current-buffer "#chan@foonet"
+ (funcall expect 3 "bob")
+ (funcall expect 3 "was created on")
+ (funcall expect 3 "prosperous")))
+
+ (ert-info ("All #chan@barnet output consumed")
+ (with-current-buffer "#chan@barnet"
+ (funcall expect 3 "mike")
+ (funcall expect 3 "was created on")
+ (funcall expect 20 "ingenuous")))))
+
+(ert-deftest erc-scenarios-base-association-multi-net--baseline ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common--base-association-multi-net
+ (lambda () (with-current-buffer "barnet" (erc-cmd-JOIN "#chan")))))
+
+;; The /join command only targets the current buffer's process. This
+;; recasts scenario bug#48598 "ambiguous-join" (which was based on
+;; bug#47522) to show that issuing superfluous /join commands
+;; (apparently fairly common) is benign.
+
+(ert-deftest erc-scenarios-base-association-multi-net--ambiguous-join ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common--base-association-multi-net
+ (lambda ()
+ (ert-info ("Nonsensical JOIN attempts silently dropped.")
+ (with-current-buffer "foonet" (erc-cmd-JOIN "#chan"))
+ (sit-for 0.1)
+ (with-current-buffer "#chan" (erc-cmd-JOIN "#chan"))
+ (sit-for 0.1)
+ (erc-d-t-wait-for 2 (get-buffer "#chan"))
+ (erc-d-t-wait-for 1 "Only one #chan buffer exists"
+ (should (equal (erc-scenarios-common-buflist "#chan")
+ (list (get-buffer "#chan")))))
+ (with-current-buffer "*server-barnet*"
+ (erc-d-t-absent-for 0.1 "JOIN"))
+ (with-current-buffer "barnet" (erc-cmd-JOIN "#chan"))))))
+
+;; Playback for same channel on two networks routed correctly.
+;; Originally from Bug#48598: 28.0.50; buffer-naming collisions
+;; involving bouncers in ERC.
+
+(ert-deftest erc-scenarios-base-association-bouncer-history ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "base/assoc/bouncer-history")
+ (erc-d-t-cleanup-sleep-secs 1)
+ (dumb-server (erc-d-run "localhost" t 'foonet 'barnet))
+ (port (process-contact dumb-server :service))
+ (erc-server-flood-penalty 0.5)
+ (expect (erc-d-t-make-expecter))
+ erc-autojoin-channels-alist
+ erc-server-buffer-foo erc-server-process-foo
+ erc-server-buffer-bar erc-server-process-bar)
+
+ (ert-info ("Connect to foonet")
+ (with-current-buffer
+ (setq erc-server-buffer-foo (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :password "foonet:changeme"
+ :full-name "tester"))
+ (setq erc-server-process-foo erc-server-process)
+ (should (string= (buffer-name) (format "127.0.0.1:%d" port)))
+ (funcall expect 5 "foonet")))
+
+ (erc-d-t-wait-for 5 (get-buffer "#chan"))
+
+ (ert-info ("Connect to barnet")
+ (with-current-buffer
+ (setq erc-server-buffer-bar (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :password "barnet:changeme"
+ :full-name "tester"))
+ (setq erc-server-process-bar erc-server-process)
+ (erc-d-t-wait-for 5 "Temporary name assigned"
+ (string= (buffer-name) (format "127.0.0.1:%d" port)))
+ (funcall expect 5 "barnet")))
+
+ (ert-info ("Server buffers are unique")
+ (should-not (eq erc-server-buffer-foo erc-server-buffer-bar)))
+
+ (ert-info ("Networks correctly determined and adopted as buffer names")
+ (with-current-buffer erc-server-buffer-foo
+ (erc-d-t-wait-for 3 "network name foonet becomes buffer name"
+ (and (eq (erc-network) 'foonet) (string= (buffer-name) "foonet"))))
+ (with-current-buffer erc-server-buffer-bar
+ (erc-d-t-wait-for 3 "network name barnet becomes buffer name"
+ (and (eq (erc-network) 'barnet) (string= (buffer-name) "barnet")))))
+
+ (erc-d-t-wait-for 5 (get-buffer "#chan@barnet"))
+
+ (ert-info ("Two channel buffers created, original #chan renamed")
+ (should (= 4 (length (erc-buffer-list))))
+ (should (equal (list (get-buffer "#chan@barnet")
+ (get-buffer "#chan@foonet"))
+ (erc-scenarios-common-buflist "#chan"))))
+
+ (ert-info ("#chan@foonet is exclusive, no cross-contamination")
+ (with-current-buffer "#chan@foonet"
+ (erc-d-t-search-for 1 "<bob>")
+ (erc-d-t-absent-for 0.1 "<joe>")
+ (should (eq erc-server-process erc-server-process-foo))))
+
+ (ert-info ("#chan@barnet is exclusive, no cross-contamination")
+ (with-current-buffer "#chan@barnet"
+ (erc-d-t-search-for 1 "<joe>")
+ (erc-d-t-absent-for 0.1 "<bob>")
+ (should (eq erc-server-process erc-server-process-bar))))
+
+ (ert-info ("All output sent")
+ (with-current-buffer "#chan@foonet"
+ (erc-d-t-search-for 10 "please your lordship"))
+ (with-current-buffer "#chan@barnet"
+ (erc-d-t-search-for 10 "I'll bid adieu")))))
+
+;;; erc-scenarios-base-association.el ends here
diff --git a/test/lisp/erc/erc-scenarios-base-compat-rename-bouncer.el b/test/lisp/erc/erc-scenarios-base-compat-rename-bouncer.el
new file mode 100644
index 00000000000..474739d01be
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-base-compat-rename-bouncer.el
@@ -0,0 +1,171 @@
+;;; erc-scenarios-compat-rename-bouncer.el --- compat-rename scenarios -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-scenarios-common)))
+
+(eval-when-compile (require 'erc-join))
+
+;; Ensure deprecated option still respected when old default value
+;; explicitly set ("respected" in the sense of having names reflect
+;; dialed TCP endpoints with possible uniquifiers but without any of
+;; the old issues, pre-bug#48598).
+
+(defun erc-scenarios-common--base-compat-no-rename-bouncer (dialogs auto more)
+ (erc-scenarios-common-with-cleanup
+ ;; These actually *are* (assigned-)network-id related because
+ ;; our kludge assigns one after the fact.
+ ((erc-scenarios-common-dialog "base/netid/bouncer")
+ (erc-d-t-cleanup-sleep-secs 1)
+ (erc-server-flood-penalty 0.1)
+ (dumb-server (apply #'erc-d-run "localhost" t dialogs))
+ (port (process-contact dumb-server :service))
+ (chan-buf-foo (format "#chan@127.0.0.1:%d" port))
+ (chan-buf-bar (format "#chan@127.0.0.1:%d<2>" port))
+ (expect (erc-d-t-make-expecter))
+ (erc-server-auto-reconnect auto)
+ erc-server-buffer-foo erc-server-process-foo
+ erc-server-buffer-bar erc-server-process-bar)
+
+ (ert-info ("Connect to foonet")
+ (with-current-buffer
+ (setq erc-server-buffer-foo (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :password "foonet:changeme"
+ :full-name "tester"
+ :id nil))
+ (setq erc-server-process-foo erc-server-process)
+ (erc-d-t-wait-for 3 (eq (erc-network) 'foonet))
+ (erc-d-t-wait-for 3 "Final buffer name determined"
+ (string= (buffer-name) (format "127.0.0.1:%d" port)))
+ (funcall expect 5 "foonet")))
+
+ (ert-info ("Join #chan@foonet")
+ (with-current-buffer erc-server-buffer-foo (erc-cmd-JOIN "#chan"))
+ (with-current-buffer (erc-d-t-wait-for 5 (get-buffer "#chan"))
+ (funcall expect 5 "<alice>")))
+
+ (ert-info ("Connect to barnet")
+ (with-current-buffer
+ (setq erc-server-buffer-bar (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :password "barnet:changeme"
+ :full-name "tester"
+ :id nil))
+ (setq erc-server-process-bar erc-server-process)
+ (erc-d-t-wait-for 3 (eq (erc-network) 'barnet))
+ (erc-d-t-wait-for 3 "Final buffer name determined"
+ (string= (buffer-name) (format "127.0.0.1:%d<2>" port)))
+ (funcall expect 5 "barnet")))
+
+ (ert-info ("Server buffers are unique, no names based on IPs")
+ (should-not (eq erc-server-buffer-foo erc-server-buffer-bar))
+ (should (equal (erc-scenarios-common-buflist "127.0.0.1")
+ (list (get-buffer (format "127.0.0.1:%d<2>" port))
+ (get-buffer (format "127.0.0.1:%d" port))))))
+
+ (ert-info ("Join #chan@barnet")
+ (with-current-buffer erc-server-buffer-bar (erc-cmd-JOIN "#chan")))
+
+ (erc-d-t-wait-for 5 "Exactly 2 #chan-prefixed buffers exist"
+ (equal (list (get-buffer chan-buf-bar)
+ (get-buffer chan-buf-foo))
+ (erc-scenarios-common-buflist "#chan")))
+
+ (ert-info ("#chan@127.0.0.1:$port is exclusive to foonet")
+ (with-current-buffer chan-buf-foo
+ (erc-d-t-search-for 1 "<bob>")
+ (erc-d-t-absent-for 0.1 "<joe>")
+ (should (eq erc-server-process erc-server-process-foo))
+ (erc-d-t-search-for 10 "ape is dead")
+ (erc-d-t-wait-for 5 (not (erc-server-process-alive)))))
+
+ (ert-info ("#chan@127.0.0.1:$port<2> is exclusive to barnet")
+ (with-current-buffer chan-buf-bar
+ (erc-d-t-search-for 1 "<joe>")
+ (erc-d-t-absent-for 0.1 "<bob>")
+ (should (eq erc-server-process erc-server-process-bar))
+ (erc-d-t-search-for 10 "keeps you from dishonour")
+ (erc-d-t-wait-for 5 (not (erc-server-process-alive)))))
+
+ (when more (funcall more))))
+
+(ert-deftest erc-scenarios-base-compat-no-rename-bouncer--basic ()
+ :tags '(:expensive-test)
+ (with-suppressed-warnings ((obsolete erc-rename-buffers))
+ (let (erc-rename-buffers)
+ (erc-scenarios-common--base-compat-no-rename-bouncer
+ '(foonet barnet) nil nil))))
+
+(ert-deftest erc-scenarios-base-compat-no-rename-bouncer--reconnect ()
+ :tags '(:expensive-test)
+ (let ((erc-d-tmpl-vars '((token . (group (| "barnet" "foonet")))))
+ (erc-d-match-handlers
+ (list :pass #'erc-scenarios-common--clash-rename-pass-handler))
+ (dialogs '(foonet-drop barnet-drop stub-again stub-again
+ foonet-again barnet-again))
+ (after
+ (lambda ()
+ (pcase-let* ((`(,barnet ,foonet)
+ (erc-scenarios-common-buflist "127.0.0.1"))
+ (port (process-contact (with-current-buffer foonet
+ erc-server-process)
+ :service)))
+
+ (ert-info ("Sanity check: barnet retains uniquifying suffix")
+ (should (string-suffix-p "<2>" (buffer-name barnet))))
+
+ ;; Simulate disconnection and `erc-server-auto-reconnect'
+ (ert-info ("Reconnect to foonet and barnet back-to-back")
+ (with-current-buffer foonet
+ (erc-d-t-wait-for 5 (erc-server-process-alive)))
+ (with-current-buffer barnet
+ (erc-d-t-wait-for 5 (erc-server-process-alive))))
+
+ (ert-info ("#chan@127.0.0.1:<port> is exclusive to foonet")
+ (with-current-buffer (format "#chan@127.0.0.1:%d" port)
+ (erc-d-t-search-for 1 "<alice>")
+ (erc-d-t-absent-for 0.1 "<joe>")
+ (erc-d-t-search-for 10 "please your lordship")))
+
+ (ert-info ("#chan@barnet is exclusive to barnet")
+ (with-current-buffer (format "#chan@127.0.0.1:%d<2>" port)
+ (erc-d-t-search-for 1 "<joe>")
+ (erc-d-t-absent-for 0.1 "<bob>")
+ (erc-d-t-search-for 1 "much in private")))
+
+ ;; Ordering deterministic here even though not so for reconnect
+ (should (equal (list barnet foonet)
+ (erc-scenarios-common-buflist "127.0.0.1")))
+ (should (equal (list
+ (get-buffer (format "#chan@127.0.0.1:%d<2>" port))
+ (get-buffer (format "#chan@127.0.0.1:%d" port)))
+ (erc-scenarios-common-buflist "#chan")))))))
+
+ (with-suppressed-warnings ((obsolete erc-rename-buffers))
+ (let (erc-rename-buffers)
+ (erc-scenarios-common--base-compat-no-rename-bouncer dialogs
+ 'auto after)))))
+
+;;; erc-scenarios-compat-rename-bouncer.el ends here
diff --git a/test/lisp/erc/erc-scenarios-base-misc-regressions.el b/test/lisp/erc/erc-scenarios-base-misc-regressions.el
new file mode 100644
index 00000000000..8f5700df14b
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-base-misc-regressions.el
@@ -0,0 +1,126 @@
+;;; erc-scenarios-base-misc-regressions.el --- misc regressions scenarios -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-scenarios-common)))
+
+(eval-when-compile (require 'erc-join))
+
+(defun erc-scenarios--rebuffed-gapless-pass-handler (dialog exchange)
+ (when (eq (erc-d-dialog-name dialog) 'pass-stub)
+ (let* ((match (erc-d-exchange-match exchange 1))
+ (sym (if (string= match "foonet") 'foonet 'barnet)))
+ (should (member match (list "foonet" "barnet")))
+ (erc-d-load-replacement-dialog dialog sym 1))))
+
+(ert-deftest erc-scenarios-base-gapless-connect ()
+ "Back-to-back entry-point invocations happen successfully.
+Originally from scenario rebuffed/gapless as explained in Bug#48598:
+28.0.50; buffer-naming collisions involving bouncers in ERC."
+ :tags '(:expensive-test)
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "base/gapless-connect")
+ (erc-server-flood-penalty 0.1)
+ (erc-server-flood-penalty erc-server-flood-penalty)
+ (erc-d-tmpl-vars '((token . (group (| "barnet" "foonet")))))
+ (erc-d-match-handlers
+ (list :pass #'erc-scenarios--rebuffed-gapless-pass-handler))
+ (dumb-server (erc-d-run "localhost" t
+ 'pass-stub 'pass-stub 'barnet 'foonet))
+ (port (process-contact dumb-server :service))
+ (expect (erc-d-t-make-expecter))
+ erc-autojoin-channels-alist
+ erc-server-buffer-foo
+ erc-server-buffer-bar)
+
+ (ert-info ("Connect twice to same endpoint without pausing")
+ (setq erc-server-buffer-foo (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :password "foonet:changeme"
+ :full-name "tester")
+ erc-server-buffer-bar (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :password "barnet:changeme"
+ :full-name "tester")))
+
+ (ert-info ("Returned server buffers are unique")
+ (should-not (eq erc-server-buffer-foo erc-server-buffer-bar)))
+
+ (ert-info ("Both connections still alive")
+ (should (get-process (format "erc-127.0.0.1-%d" port)))
+ (should (get-process (format "erc-127.0.0.1-%d<1>" port))))
+
+ (with-current-buffer erc-server-buffer-bar
+ (funcall expect 2 "marked as being away"))
+
+ (with-current-buffer (erc-d-t-wait-for 20 (get-buffer "#bar"))
+ (funcall expect 10 "was created on")
+ (funcall expect 2 "his second fit"))
+
+ (with-current-buffer (erc-d-t-wait-for 20 (get-buffer "#foo"))
+ (funcall expect 10 "was created on")
+ (funcall expect 2 "no use of him"))))
+
+;; This defends against a regression in `erc-server-PRIVMSG' caused by
+;; the removal of `erc-auto-query'. When an active channel buffer is
+;; killed off and PRIVMSGs arrive targeting it, the buffer should be
+;; recreated. See elsewhere for NOTICE logic, which is more complex.
+
+(ert-deftest erc-scenarios-base-channel-buffer-revival ()
+ :tags '(:expensive-test)
+
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "base/channel-buffer-revival")
+ (dumb-server (erc-d-run "localhost" t 'foonet))
+ (port (process-contact dumb-server :service))
+ erc-autojoin-channels-alist
+ erc-server-buffer-foo)
+
+ (ert-info ("Connect to foonet")
+ (setq erc-server-buffer-foo (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :password "changeme"
+ :full-name "tester"))
+ (with-current-buffer erc-server-buffer-foo
+ (should (string= (buffer-name) (format "127.0.0.1:%d" port)))))
+
+ (ert-info ("Server buffer is unique and temp name is absent")
+ (erc-d-t-wait-for 1 (get-buffer "FooNet"))
+ (should-not (erc-scenarios-common-buflist "127.0.0.1"))
+ (with-current-buffer erc-server-buffer-foo
+ (erc-cmd-JOIN "#chan")))
+
+ (ert-info ("Channel buffer #chan alive and well")
+ (with-current-buffer (erc-d-t-wait-for 8 (get-buffer "#chan"))
+ (erc-d-t-search-for 10 "Our queen and all her elves")
+ (kill-buffer)))
+
+ (should-not (get-buffer "#chan"))
+
+ (ert-info ("Channel buffer #chan revived")
+ (with-current-buffer (erc-d-t-wait-for 5 (get-buffer "#chan"))
+ (erc-d-t-search-for 10 "and be prosperous")))))
+
+;;; erc-scenarios-base-misc-regressions.el ends here
diff --git a/test/lisp/erc/erc-scenarios-base-netid-bouncer-id.el b/test/lisp/erc/erc-scenarios-base-netid-bouncer-id.el
new file mode 100644
index 00000000000..6c6568cad68
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-base-netid-bouncer-id.el
@@ -0,0 +1,34 @@
+;;; erc-scenarios-base-netid-bouncer-id.el --- net-id bouncer ID scenarios -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-scenarios-common)))
+
+(ert-deftest erc-scenarios-base-netid-bouncer--id-foo ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common--base-network-id-bouncer '(:foo-id t) 'foonet 'barnet))
+
+(ert-deftest erc-scenarios-base-netid-bouncer--id-bar ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common--base-network-id-bouncer '(:bar-id t) 'foonet 'barnet))
+
+;;; erc-scenarios-base-netid-bouncer-id.el ends here
diff --git a/test/lisp/erc/erc-scenarios-base-netid-bouncer-recon-base.el b/test/lisp/erc/erc-scenarios-base-netid-bouncer-recon-base.el
new file mode 100644
index 00000000000..f48e1ef3940
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-base-netid-bouncer-recon-base.el
@@ -0,0 +1,30 @@
+;;; erc-scenarios-base-netid-bouncer-recon-base.el --- net-id base scenarios -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-scenarios-common)))
+
+(ert-deftest erc-scenarios-base-netid-bouncer--recon-base ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common--base-network-id-bouncer--reconnect nil nil))
+
+;;; erc-scenarios-base-netid-bouncer-recon-base.el ends here
diff --git a/test/lisp/erc/erc-scenarios-base-netid-bouncer-recon-both.el b/test/lisp/erc/erc-scenarios-base-netid-bouncer-recon-both.el
new file mode 100644
index 00000000000..2f58c3269e3
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-base-netid-bouncer-recon-both.el
@@ -0,0 +1,32 @@
+;;; erc-scenarios-base-netid-bouncer-recon-both.el --- net-id both scenarios -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-scenarios-common)))
+
+(require 'erc-scenarios-common)
+
+(ert-deftest erc-scenarios-base-netid-bouncer--recon-both ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common--base-network-id-bouncer--reconnect 'foo-id 'bar-id))
+
+;;; erc-scenarios-base-netid-bouncer-recon-both.el ends here
diff --git a/test/lisp/erc/erc-scenarios-base-netid-bouncer-recon-id.el b/test/lisp/erc/erc-scenarios-base-netid-bouncer-recon-id.el
new file mode 100644
index 00000000000..72510809ab4
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-base-netid-bouncer-recon-id.el
@@ -0,0 +1,35 @@
+;;; erc-scenarios-base-netid-bouncer-recon-id.el --- recon ID scenarios -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-scenarios-common)))
+
+(ert-deftest erc-scenarios-base-netid-bouncer--reconnect-id-foo ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common--base-network-id-bouncer--reconnect 'foo-id nil))
+
+(ert-deftest erc-scenarios-base-netid-bouncer--reconnect-id-bar ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common--base-network-id-bouncer--reconnect nil 'bar-id))
+
+
+;;; erc-scenarios-base-netid-bouncer-recon-id.el ends here
diff --git a/test/lisp/erc/erc-scenarios-base-netid-bouncer.el b/test/lisp/erc/erc-scenarios-base-netid-bouncer.el
new file mode 100644
index 00000000000..d171e1f9f91
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-base-netid-bouncer.el
@@ -0,0 +1,35 @@
+;;; erc-scenarios-base-netid-bouncer.el --- net-id bouncer scenarios -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-scenarios-common)))
+
+(ert-deftest erc-scenarios-base-netid-bouncer--base ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common--base-network-id-bouncer () 'foonet 'barnet))
+
+(ert-deftest erc-scenarios-base-netid-bouncer--both ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common--base-network-id-bouncer '(:foo-id t :bar-id t)
+ 'foonet 'barnet))
+
+;;; erc-scenarios-base-netid-bouncer.el ends here
diff --git a/test/lisp/erc/erc-scenarios-base-netid-samenet.el b/test/lisp/erc/erc-scenarios-base-netid-samenet.el
new file mode 100644
index 00000000000..248144d6f9b
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-base-netid-samenet.el
@@ -0,0 +1,147 @@
+;;; erc-scenarios-base-network-id-samenet.el --- netid-id samenet scenarios -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-scenarios-common)))
+
+(eval-when-compile (require 'erc-join))
+
+(cl-defun erc-scenarios-common--base-network-id-same-network
+ ((&key nick id server chan
+ &aux (nick-a nick) (id-a id) (serv-buf-a server) (chan-buf-a chan))
+ (&key nick id server chan
+ &aux (nick-b nick) (id-b id) (serv-buf-b server) (chan-buf-b chan)))
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "base/netid/samenet")
+ (dumb-server (erc-d-run "localhost" t 'tester 'chester))
+ (port (process-contact dumb-server :service))
+ (expect (erc-d-t-make-expecter))
+ (erc-server-flood-penalty 0.1)
+ (erc-server-flood-margin 30)
+ erc-serv-buf-a erc-serv-buf-b)
+
+ (ert-info ("Connect to foonet with nick tester")
+ (with-current-buffer
+ (setq erc-serv-buf-a (erc :server "127.0.0.1"
+ :port port
+ :nick nick-a
+ :password "changeme"
+ :full-name nick-a
+ :id id-a))
+ (erc-scenarios-common-assert-initial-buf-name id-a port)
+ (erc-d-t-wait-for 5 (eq erc-network 'foonet))))
+
+ (ert-info ("Connect to foonet with nick chester")
+ (with-current-buffer
+ (setq erc-serv-buf-b (erc :server "127.0.0.1"
+ :port port
+ :nick nick-b
+ :password "changeme"
+ :full-name nick-b
+ :id id-b))
+ (erc-scenarios-common-assert-initial-buf-name id-b port)))
+
+ (erc-d-t-wait-for 3 (not (erc-scenarios-common-buflist "127.0.0.1")))
+
+ (with-current-buffer erc-serv-buf-a
+ (should (string= (buffer-name) serv-buf-a))
+ (funcall expect 8 "debug mode")
+ (erc-cmd-JOIN "#chan"))
+
+ (with-current-buffer erc-serv-buf-b
+ (should (string= (buffer-name) serv-buf-b))
+ (funcall expect 8 "debug mode")
+ (erc-cmd-JOIN "#chan"))
+
+ (erc-d-t-wait-for 10 (get-buffer chan-buf-a))
+ (erc-d-t-wait-for 10 (get-buffer chan-buf-b))
+
+ (ert-info ("Greets other nick in same channel")
+ (with-current-buffer chan-buf-a
+ (funcall expect 5 "chester")
+ (funcall expect 5 "find the forester")
+ (erc-cmd-MSG "#chan chester: hi")))
+
+ (ert-info ("Sees other nick in same channel")
+ (with-current-buffer chan-buf-b
+ (funcall expect 5 "tester")
+ (funcall expect 10 "<tester> chester: hi")
+ (funcall expect 5 "This was lofty")
+ (erc-cmd-MSG "#chan hi tester")))
+
+ (with-current-buffer chan-buf-a
+ (funcall expect 5 "To employ you towards")
+ (erc-cmd-QUIT ""))
+
+ (with-current-buffer chan-buf-b
+ (funcall expect 5 "To employ you towards")
+ (erc-cmd-QUIT ""))))
+
+(ert-deftest erc-scenarios-base-network-id-same-network--two-ids ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common--base-network-id-same-network
+ (list :nick "tester"
+ :id 'tester/foonet
+ :server "tester/foonet"
+ :chan "#chan@tester/foonet")
+ (list :nick "chester"
+ :id 'chester/foonet
+ :server "chester/foonet"
+ :chan "#chan@chester/foonet")))
+
+(ert-deftest erc-scenarios-base-network-id-same-network--one-id-tester ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common--base-network-id-same-network
+ (list :nick "tester"
+ :id 'tester/foonet
+ :server "tester/foonet"
+ :chan "#chan@tester/foonet")
+ (list :nick "chester"
+ :id nil
+ :server "foonet"
+ :chan "#chan@foonet")))
+
+(ert-deftest erc-scenarios-base-network-id-same-network--one-id-chester ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common--base-network-id-same-network
+ (list :nick "tester"
+ :id nil
+ :server "foonet"
+ :chan "#chan@foonet")
+ (list :nick "chester"
+ :id 'chester/foonet
+ :server "chester/foonet"
+ :chan "#chan@chester/foonet")))
+
+(ert-deftest erc-scenarios-base-network-id-same-network--no-ids ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common--base-network-id-same-network
+ (list :nick "tester"
+ :id nil
+ :server "foonet/tester"
+ :chan "#chan@foonet/tester") ; <- note net before nick
+ (list :nick "chester"
+ :id nil
+ :server "foonet/chester"
+ :chan "#chan@foonet/chester")))
+
+;;; erc-scenarios-base-network-id-samenet.el ends here
diff --git a/test/lisp/erc/erc-scenarios-base-reconnect.el b/test/lisp/erc/erc-scenarios-base-reconnect.el
new file mode 100644
index 00000000000..49298dc5942
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-base-reconnect.el
@@ -0,0 +1,227 @@
+;;; erc-scenarios-base-reconnect.el --- Base-reconnect scenarios -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-scenarios-common)))
+
+(eval-when-compile (require 'erc-join))
+
+;; This ensures we only reconnect `erc-server-reconnect-attempts'
+;; (rather than infinitely many) times, which can easily happen when
+;; tweaking code related to process sentinels in erc-backend.el.
+
+(ert-deftest erc-scenarios-base-reconnect-timer ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "base/reconnect")
+ (dumb-server (erc-d-run "localhost" t 'timer 'timer 'timer-last))
+ (port (process-contact dumb-server :service))
+ (expect (erc-d-t-make-expecter))
+ (erc-server-auto-reconnect t)
+ erc-autojoin-channels-alist
+ erc-server-buffer)
+
+ (ert-info ("Connect to foonet")
+ (setq erc-server-buffer (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :password "changeme"
+ :full-name "tester"))
+ (with-current-buffer erc-server-buffer
+ (should (string= (buffer-name) (format "127.0.0.1:%d" port)))))
+
+ (ert-info ("Server tries to connect thrice (including initial attempt)")
+ (with-current-buffer erc-server-buffer
+ (dotimes (n 3)
+ (ert-info ((format "Attempt %d" n))
+ (funcall expect 3 "Opening connection")
+ (funcall expect 2 "Password incorrect")
+ (funcall expect 2 "Connection failed!")
+ (funcall expect 2 "Re-establishing connection")))
+ (ert-info ("Prev attempt was final")
+ (erc-d-t-absent-for 1 "Opening connection" (point)))))
+
+ (ert-info ("Server buffer is unique and temp name is absent")
+ (should (equal (list (get-buffer (format "127.0.0.1:%d" port)))
+ (erc-scenarios-common-buflist "127.0.0.1"))))))
+
+(defun erc-scenarios-common--base-reconnect-options (test)
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "base/reconnect")
+ (dumb-server (erc-d-run "localhost" t 'options 'options-again))
+ (port (process-contact dumb-server :service))
+ (expect (erc-d-t-make-expecter))
+ (erc-server-flood-penalty 0.1)
+ (erc-server-auto-reconnect t)
+ erc-autojoin-channels-alist
+ erc-server-buffer)
+
+ (should (memq 'autojoin erc-modules))
+
+ (ert-info ("Connect to foonet")
+ (setq erc-server-buffer (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :password "changeme"
+ :full-name "tester"))
+ (with-current-buffer erc-server-buffer
+ (should (string= (buffer-name) (format "127.0.0.1:%d" port)))
+ (funcall expect 10 "debug mode")))
+
+ (ert-info ("Wait for some output in channels")
+ (with-current-buffer (erc-d-t-wait-for 10 (get-buffer "#chan"))
+ (funcall expect 10 "welcome")))
+
+ (ert-info ("Server buffer shows connection failed")
+ (with-current-buffer erc-server-buffer
+ (funcall expect 10 "Connection failed! Re-establishing")))
+
+ (should (equal erc-autojoin-channels-alist '((FooNet "#chan"))))
+
+ (funcall test)
+
+ ;; A manual /JOIN command tells ERC we're done auto-reconnecting
+ (with-current-buffer "FooNet" (erc-cmd-JOIN "#spam"))
+
+ (erc-d-t-ensure-for 1 "Newly joined chan ignores `erc-reconnect-display'"
+ (not (eq (window-buffer) (get-buffer "#spam"))))
+
+ (ert-info ("Wait for auto reconnect")
+ (with-current-buffer erc-server-buffer
+ (funcall expect 10 "still in debug mode")))
+
+ (ert-info ("Wait for activity to recommence in channels")
+ (with-current-buffer (erc-d-t-wait-for 10 (get-buffer "#chan"))
+ (funcall expect 10 "forest of Arden"))
+ (with-current-buffer (erc-d-t-wait-for 10 (get-buffer "#spam"))
+ (funcall expect 10 "her elves come here anon")))))
+
+(ert-deftest erc-scenarios-base-reconnect-options--buffer ()
+ :tags '(:expensive-test)
+ (should (eq erc-join-buffer 'bury))
+ (should-not erc-reconnect-display)
+
+ ;; FooNet (the server buffer) is not switched to because it's
+ ;; already current (but not shown) when `erc-open' is called. See
+ ;; related conditional guard towards the end of that function.
+
+ (let ((erc-reconnect-display 'buffer))
+ (erc-scenarios-common--base-reconnect-options
+ (lambda ()
+ (pop-to-buffer-same-window "*Messages*")
+
+ (erc-d-t-ensure-for 1 "Server buffer not shown"
+ (not (eq (window-buffer) (get-buffer "FooNet"))))
+
+ (erc-d-t-wait-for 5 "Channel #chan shown when autojoined"
+ (eq (window-buffer) (get-buffer "#chan")))))))
+
+(ert-deftest erc-scenarios-base-reconnect-options--default ()
+ :tags '(:expensive-test)
+ (should (eq erc-join-buffer 'bury))
+ (should-not erc-reconnect-display)
+
+ (erc-scenarios-common--base-reconnect-options
+
+ (lambda ()
+ (pop-to-buffer-same-window "*Messages*")
+
+ (erc-d-t-ensure-for 1 "Server buffer not shown"
+ (not (eq (window-buffer) (get-buffer "FooNet"))))
+
+ (erc-d-t-ensure-for 3 "Channel #chan not shown"
+ (not (eq (window-buffer) (get-buffer "#chan"))))
+
+ (eq (window-buffer) (messages-buffer)))))
+
+;; Upon reconnecting, playback for channel and target buffers is
+;; routed correctly. Autojoin is irrelevant here, but for the
+;; skeptical, see `erc-scenarios-common--join-network-id', which
+;; overlaps with this and includes spurious JOINs ignored by the
+;; server.
+
+(ert-deftest erc-scenarios-base-association-reconnect-playback ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "base/assoc/reconplay")
+ (erc-server-flood-penalty 0.1)
+ (erc-server-flood-margin 30)
+ (dumb-server (erc-d-run "localhost" t 'foonet 'again))
+ (port (process-contact dumb-server :service))
+ (expect (erc-d-t-make-expecter))
+ erc-autojoin-channels-alist
+ erc-server-buffer-foo)
+
+ (ert-info ("Connect to foonet")
+ (setq erc-server-buffer-foo (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :password "changeme"
+ :full-name "tester"))
+ (with-current-buffer erc-server-buffer-foo
+ (should (string= (buffer-name) (format "127.0.0.1:%d" port)))))
+
+ (ert-info ("Setup")
+
+ (ert-info ("Server buffer is unique and temp name is absent")
+ (erc-d-t-wait-for 3 (get-buffer "foonet"))
+ (should-not (erc-scenarios-common-buflist "127.0.0.1")))
+
+ (ert-info ("Channel buffer #chan playback received")
+ (with-current-buffer (erc-d-t-wait-for 8 (get-buffer "#chan"))
+ (funcall expect 10 "But purgatory")))
+
+ (ert-info ("Ask for help from services or bouncer bot")
+ (with-current-buffer erc-server-buffer-foo
+ (erc-cmd-MSG "*status help")))
+
+ (ert-info ("Help received")
+ (with-current-buffer (erc-d-t-wait-for 5 (get-buffer "*status"))
+ (funcall expect 10 "Rehash")))
+
+ (ert-info ("#chan convo done")
+ (with-current-buffer "#chan"
+ (funcall expect 10 "most egregious indignity"))))
+
+ ;; KLUDGE (see note above test)
+ (should erc-autojoin-channels-alist)
+ (setq erc-autojoin-channels-alist nil)
+
+ (with-current-buffer erc-server-buffer-foo
+ (erc-cmd-QUIT "")
+ (erc-d-t-wait-for 4 (not (erc-server-process-alive)))
+ (erc-cmd-RECONNECT))
+
+ (ert-info ("Channel buffer found and associated")
+ (with-current-buffer "#chan"
+ (funcall expect 10 "Wilt thou rest damned")))
+
+ (ert-info ("Help buffer found and associated")
+ (with-current-buffer "*status"
+ (erc-scenarios-common-say "help")
+ (funcall expect 10 "Restart ZNC")))
+
+ (ert-info ("#chan convo done")
+ (with-current-buffer "#chan"
+ (funcall expect 10 "here comes the lady")))))
+
+;;; erc-scenarios-base-reconnect.el ends here
diff --git a/test/lisp/erc/erc-scenarios-base-renick.el b/test/lisp/erc/erc-scenarios-base-renick.el
new file mode 100644
index 00000000000..bf27f61b3fc
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-base-renick.el
@@ -0,0 +1,305 @@
+;;; erc-scenarios-base-renick.el --- Re-nicking scenarios -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-scenarios-common)))
+
+(eval-when-compile (require 'erc-join))
+
+;; The server changes your nick just after registration.
+
+(ert-deftest erc-scenarios-base-renick-self-auto ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "base/renick/self")
+ (erc-server-flood-penalty 0.1)
+ (dumb-server (erc-d-run "localhost" t 'auto))
+ (port (process-contact dumb-server :service))
+ erc-autojoin-channels-alist
+ erc-server-buffer-foo)
+
+ (ert-info ("Connect to foonet")
+ (setq erc-server-buffer-foo (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :password "foonet:changeme"
+ :full-name "tester"))
+ (with-current-buffer erc-server-buffer-foo
+ (should (string= (buffer-name) (format "127.0.0.1:%d" port)))))
+
+ (with-current-buffer (erc-d-t-wait-for 3 (get-buffer "foonet"))
+ (erc-d-t-search-for 10 "Your new nickname is dummy"))
+
+ (ert-info ("Joined by bouncer to #foo, own nick present")
+ (with-current-buffer (erc-d-t-wait-for 1 (get-buffer "#foo"))
+ (erc-d-t-search-for 10 "dummy")
+ (erc-d-t-search-for 10 "On Thursday")))))
+
+;; You change your nickname manually in a server buffer; a message is
+;; printed in channel buffers.
+
+(ert-deftest erc-scenarios-base-renick-self-manual ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "base/renick/self")
+ (erc-server-flood-penalty 0.1)
+ (dumb-server (erc-d-run "localhost" t 'manual))
+ (port (process-contact dumb-server :service))
+ (expect (erc-d-t-make-expecter))
+ erc-autojoin-channels-alist
+ erc-server-buffer-foo)
+
+ (ert-info ("Connect to foonet")
+ (setq erc-server-buffer-foo (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :password "foonet:changeme"
+ :full-name "tester"))
+ (with-current-buffer erc-server-buffer-foo
+ (should (string= (buffer-name) (format "127.0.0.1:%d" port)))))
+
+ (erc-d-t-wait-for 3 (get-buffer "foonet"))
+
+ (ert-info ("Joined by bouncer to #foo, own nick present")
+ (with-current-buffer (erc-d-t-wait-for 1 (get-buffer "#foo"))
+ (funcall expect 5 "tester")
+ (funcall expect 5 "On Thursday")
+ (erc-with-server-buffer (erc-cmd-NICK "dummy"))
+ (funcall expect 5 "Your new nickname is dummy")
+ (funcall expect 5 "<bob> dummy: Hi")
+ ;; Regression in which changing a nick would trigger #foo@foonet
+ (erc-d-t-ensure-for 0.4 (equal (buffer-name) "#foo"))))))
+
+;; You connect to the same network with two different nicks. You
+;; manually change the first nick at some point, and buffer names are
+;; updated correctly.
+
+(ert-deftest erc-scenarios-base-renick-self-qualified ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "base/renick/self")
+ (dumb-server (erc-d-run "localhost" t 'qual-tester 'qual-chester))
+ (port (process-contact dumb-server :service))
+ (expect (erc-d-t-make-expecter))
+ (erc-server-flood-penalty 0.1)
+ (erc-server-flood-margin 30)
+ erc-serv-buf-a erc-serv-buf-b)
+
+ (ert-info ("Connect to foonet with nick tester")
+ (with-current-buffer
+ (setq erc-serv-buf-a (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :password "changeme"
+ :full-name "tester"))
+ (erc-d-t-wait-for 5 (eq erc-network 'foonet))))
+
+ (ert-info ("Connect to foonet with nick chester")
+ (with-current-buffer
+ (setq erc-serv-buf-b (erc :server "127.0.0.1"
+ :port port
+ :nick "chester"
+ :password "changeme"
+ :full-name "chester"))))
+
+ (erc-d-t-wait-for 3 "Dialed Buflist is Empty"
+ (not (erc-scenarios-common-buflist "127.0.0.1")))
+
+ (with-current-buffer "foonet/tester"
+ (funcall expect 3 "debug mode")
+ (erc-cmd-JOIN "#chan"))
+
+ (with-current-buffer "foonet/chester"
+ (funcall expect 3 "debug mode")
+ (erc-cmd-JOIN "#chan"))
+
+ (erc-d-t-wait-for 10 (get-buffer "#chan@foonet/tester"))
+ (erc-d-t-wait-for 10 (get-buffer "#chan@foonet/chester"))
+
+ (ert-info ("Greets other nick in same channel")
+ (with-current-buffer "#chan@foonet/tester"
+ (funcall expect 5 "<bob> chester, welcome!")
+ (erc-cmd-NICK "dummy")
+ (funcall expect 5 "Your new nickname is dummy")
+ (funcall expect 5 "find the forester")
+ (erc-d-t-wait-for 5 (string= (buffer-name) "#chan@foonet/dummy"))))
+
+ (ert-info ("Renick propagated throughout all buffers of process")
+ (should-not (get-buffer "#chan@foonet/tester"))
+ (should-not (get-buffer "foonet/tester"))
+ (should (get-buffer "foonet/dummy")))))
+
+;; When a channel user changes their nick, any query buffers for them
+;; are updated.
+
+(ert-deftest erc-scenarios-base-renick-queries-solo ()
+ :tags '(:expensive-test)
+
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "base/renick/queries")
+ (erc-server-flood-penalty 0.1)
+ (erc-server-flood-margin 20)
+ (dumb-server (erc-d-run "localhost" t 'solo))
+ (port (process-contact dumb-server :service))
+ erc-autojoin-channels-alist
+ erc-server-buffer-foo)
+
+ (ert-info ("Connect to foonet")
+ (setq erc-server-buffer-foo (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :password "foonet:changeme"
+ :full-name "tester"))
+ (with-current-buffer erc-server-buffer-foo
+ (should (string= (buffer-name) (format "127.0.0.1:%d" port)))))
+
+ (erc-d-t-wait-for 1 (get-buffer "foonet"))
+
+ (ert-info ("Joined by bouncer to #foo, pal persent")
+ (with-current-buffer (erc-d-t-wait-for 1 (get-buffer "#foo"))
+ (erc-d-t-search-for 1 "On Thursday")
+ (erc-scenarios-common-say "hi")))
+
+ (erc-d-t-wait-for 10 "Query buffer appears with message from pal"
+ (get-buffer "Lal"))
+
+ (ert-info ("Chat with pal, who changes name")
+ (with-current-buffer "Lal"
+ (erc-d-t-search-for 3 "hello")
+ (erc-scenarios-common-say "hi")
+ (erc-d-t-search-for 10 "is now known as Linguo")
+ (should-not (search-forward "is now known as Linguo" nil t))))
+
+ (erc-d-t-wait-for 1 (get-buffer "Linguo"))
+ (should-not (get-buffer "Lal"))
+
+ (with-current-buffer "Linguo" (erc-scenarios-common-say "howdy Linguo"))
+
+ (with-current-buffer "#foo"
+ (erc-d-t-search-for 10 "is now known as Linguo")
+ (should-not (search-forward "is now known as Linguo" nil t))
+ (erc-cmd-PART ""))
+
+ (with-current-buffer "Linguo"
+ (erc-d-t-search-for 10 "get along"))))
+
+;; You share a channel and a query buffer with a user on two different
+;; networks (through a proxy). The user changes their nick on both
+;; networks at the same time. Query buffers are updated accordingly.
+
+(ert-deftest erc-scenarios-base-renick-queries-bouncer ()
+ :tags '(:expensive-test)
+
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "base/renick/queries")
+ (erc-server-flood-penalty 0.1)
+ (erc-server-flood-margin 30)
+ (dumb-server (erc-d-run "localhost" t 'bouncer-foonet 'bouncer-barnet))
+ (port (process-contact dumb-server :service))
+ (expect (erc-d-t-make-expecter))
+ erc-accidental-paste-threshold-seconds
+ erc-autojoin-channels-alist
+ erc-server-buffer-foo
+ erc-server-buffer-bar)
+
+ (ert-info ("Connect to foonet")
+ (setq erc-server-buffer-foo (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :password "foonet:changeme"
+ :full-name "tester"))
+ (with-current-buffer erc-server-buffer-foo
+ (should (string= (buffer-name) (format "127.0.0.1:%d" port)))))
+
+ (erc-d-t-wait-for 5 (get-buffer "foonet"))
+
+ (ert-info ("Connect to barnet")
+ (setq erc-server-buffer-bar (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :password "barnet:changeme"
+ :full-name "tester"))
+ (with-current-buffer erc-server-buffer-bar
+ (should (string= (buffer-name) (format "127.0.0.1:%d" port)))))
+
+ (erc-d-t-wait-for 5 (get-buffer "barnet"))
+ (should-not (erc-scenarios-common-buflist "127.0.0.1"))
+
+ (ert-info ("Joined by bouncer to #chan@foonet, pal persent")
+ (with-current-buffer (erc-d-t-wait-for 10 (get-buffer "#chan@foonet"))
+ (funcall expect 1 "rando")
+ (funcall expect 1 "simply misused")))
+
+ (ert-info ("Joined by bouncer to #chan@barnet, pal persent")
+ (with-current-buffer (erc-d-t-wait-for 10 (get-buffer "#chan@barnet"))
+ (funcall expect 1 "rando")
+ (funcall expect 2 "come, sir, I am")))
+
+ (ert-info ("Query buffer exists for rando@foonet")
+ (with-current-buffer (erc-d-t-wait-for 10 (get-buffer "rando@foonet"))
+ (funcall expect 1 "guess not")
+ (erc-scenarios-common-say "I here")))
+
+ (ert-info ("Query buffer exists for rando@barnet")
+ (with-current-buffer (erc-d-t-wait-for 10 (get-buffer "rando@barnet"))
+ (funcall expect 2 "rentacop")
+ (erc-scenarios-common-say "Linda said you were gonna kill me.")))
+
+ (ert-info ("Sync convo for rando@foonet")
+ (with-current-buffer "rando@foonet"
+ (funcall expect 1 "u are dumb")
+ (erc-scenarios-common-say "not so")))
+
+ (ert-info ("Sync convo for rando@barnet")
+ (with-current-buffer "rando@barnet"
+ (funcall expect 3 "I never saw her before")
+ (erc-scenarios-common-say "You aren't with Wage?")))
+
+ (erc-d-t-wait-for 3 (get-buffer "frenemy@foonet"))
+ (erc-d-t-wait-for 3 (get-buffer "frenemy@barnet"))
+ (should-not (get-buffer "rando@foonet"))
+ (should-not (get-buffer "rando@barnet"))
+
+ (with-current-buffer "frenemy@foonet"
+ (funcall expect 1 "now known as")
+ (funcall expect 1 "doubly so"))
+
+ (with-current-buffer "frenemy@barnet"
+ (funcall expect 1 "now known as")
+ (funcall expect 1 "reality picture"))
+
+ (when noninteractive
+ (with-current-buffer "frenemy@barnet" (kill-buffer))
+ (erc-d-t-wait-for 2 (get-buffer "frenemy"))
+ (should-not (get-buffer "frenemy@foonet")))
+
+ (with-current-buffer "#chan@foonet"
+ (funcall expect 10 "is now known as frenemy")
+ (should-not (search-forward "now known as frenemy" nil t)) ; regression
+ (funcall expect 10 "words are razors"))
+
+ (with-current-buffer "#chan@barnet"
+ (funcall expect 10 "is now known as frenemy")
+ (should-not (search-forward "now known as frenemy" nil t))
+ (erc-d-t-search-for 25 "I have lost"))))
+
+;;; erc-scenarios-base-renick.el ends here
diff --git a/test/lisp/erc/erc-scenarios-base-reuse-buffers.el b/test/lisp/erc/erc-scenarios-base-reuse-buffers.el
new file mode 100644
index 00000000000..8e7e939d046
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-base-reuse-buffers.el
@@ -0,0 +1,233 @@
+;;; erc-scenarios-base-reuse-buffers.el --- base-reuse-buffers scenarios -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-scenarios-common)))
+
+(eval-when-compile (require 'erc-join))
+
+(defun erc-scenarios-common--base-reuse-buffers-server-buffers (&optional more)
+ "Show that `erc-reuse-buffers' doesn't affect server buffers.
+Overlaps some with `clash-of-chans/uniquify'. Adapted from
+rebuffed/reuseless, described in Bug#48598: 28.0.50; buffer-naming
+collisions involving bouncers in ERC. Run EXTRA."
+ (erc-scenarios-common-with-cleanup
+ ((dumb-server (erc-d-run "localhost" t 'foonet 'barnet))
+ (port (process-contact dumb-server :service))
+ erc-autojoin-channels-alist)
+
+ (ert-info ("Connect to foonet")
+ (with-current-buffer (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :password "foonet:changeme"
+ :full-name "tester")
+ (should (string= (buffer-name)
+ (format "127.0.0.1:%d/127.0.0.1" port)))
+ (erc-d-t-search-for 12 "marked as being away")))
+
+ (ert-info ("Connect to barnet")
+ (with-current-buffer (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :password "barnet:changeme"
+ :full-name "tester")
+ (should (string= (buffer-name)
+ (format "127.0.0.1:%d/127.0.0.1<2>" port)))
+ (erc-d-t-search-for 45 "marked as being away")))
+
+ (erc-d-t-wait-for 2 (get-buffer (format "127.0.0.1:%d/127.0.0.1" port)))
+ (erc-d-t-wait-for 2 (get-buffer (format "127.0.0.1:%d/127.0.0.1<2>" port)))
+
+ (ert-info ("Server buffers are unique, no IP-based names")
+ (should (cdr (erc-scenarios-common-buflist "127.0.0.1"))))
+ (when more (funcall more port))))
+
+;; XXX maybe remove: already covered many times over by other scenarios
+(ert-deftest erc-scenarios-base-reuse-buffers-server-buffers--enabled ()
+ :tags '(:expensive-test)
+ (with-suppressed-warnings ((obsolete erc-reuse-buffers))
+ (should erc-reuse-buffers))
+ (let ((erc-scenarios-common-dialog "base/reuse-buffers/server"))
+ (erc-scenarios-common-with-cleanup
+ ((dumb-server (erc-d-run "localhost" t 'foonet 'barnet))
+ (port (process-contact dumb-server :service))
+ erc-autojoin-channels-alist)
+
+ (ert-info ("Connect to foonet")
+ (with-current-buffer (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :password "foonet:changeme"
+ :full-name "tester")
+ (should (string= (buffer-name) (format "127.0.0.1:%d" port)))
+ (erc-d-t-search-for 12 "marked as being away")))
+
+ (ert-info ("Connect to barnet")
+ (with-current-buffer (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :password "barnet:changeme"
+ :full-name "tester")
+ (should (string= (buffer-name) (format "127.0.0.1:%d" port)))
+ (erc-d-t-search-for 45 "marked as being away")))
+
+ (erc-d-t-wait-for 2 (get-buffer "foonet"))
+ (erc-d-t-wait-for 2 (get-buffer "barnet"))
+
+ (ert-info ("Server buffers are unique, no IP-based names")
+ (should-not (eq (get-buffer "foonet") (get-buffer "barnet")))
+ (should-not (erc-scenarios-common-buflist "127.0.0.1"))))))
+
+;; FIXME no sense in running this twice (JOIN variant includes this)
+(ert-deftest erc-scenarios-base-reuse-buffers-server-buffers--disabled ()
+ :tags '(:expensive-test)
+ (with-suppressed-warnings ((obsolete erc-reuse-buffers))
+ (should erc-reuse-buffers)
+ (let ((erc-scenarios-common-dialog "base/reuse-buffers/server")
+ erc-reuse-buffers)
+ (erc-scenarios-common--base-reuse-buffers-server-buffers nil))))
+
+;; This also asserts that `erc-cmd-JOIN' is no longer susceptible to a
+;; regression introduced in 28.1 (ERC 5.4) that caused phantom target
+;; buffers of the form target/server to be created via
+;; `switch-to-buffer' ("phantom" because they would go unused"). This
+;; would happen (in place of a JOIN being sent out) when a previously
+;; used (parted) target buffer existed and `erc-reuse-buffers' was
+;; nil.
+;;
+;; Note: All the `erc-get-channel-user' calls have to do with the fact
+;; that `erc-default-target' relies on the ambiguously defined
+;; `erc-default-recipients' (meaning it's overloaded in the sense of
+;; being used both for retrieving a target name and checking if a
+;; channel has been PARTed). While not ideal, `erc-get-channel-user'
+;; can (also) be used to detect the latter.
+
+(defun erc-scenarios-common--base-reuse-buffers-channel-buffers (port)
+ "The option `erc-reuse-buffers' is still respected when nil.
+Adapted from scenario clash-of-chans/uniquify described in Bug#48598:
+28.0.50; buffer-naming collisions involving bouncers in ERC."
+ (let* ((expect (erc-d-t-make-expecter))
+ (server-buffer-foo
+ (get-buffer (format "127.0.0.1:%d/127.0.0.1" port)))
+ (server-buffer-bar
+ (get-buffer (format "127.0.0.1:%d/127.0.0.1<2>" port)))
+ (server-process-foo
+ (buffer-local-value 'erc-server-process server-buffer-foo))
+ (server-process-bar
+ (buffer-local-value 'erc-server-process server-buffer-bar)))
+
+ (ert-info ("Unique #chan buffers exist")
+ (erc-d-t-wait-for 3 (get-buffer "#chan/127.0.0.1<2>"))
+ (erc-d-t-wait-for 3 (get-buffer "#chan/127.0.0.1")))
+
+ (ert-info ("#chan@foonet is exclusive and not contaminated")
+ (with-current-buffer "#chan/127.0.0.1"
+ (funcall expect 1 "<bob>")
+ (erc-d-t-absent-for 0.1 "<joe>")
+ (funcall expect 1 "strength to climb")
+ (should (eq erc-server-process server-process-foo))))
+
+ (ert-info ("#chan@barnet is exclusive and not contaminated")
+ (with-current-buffer "#chan/127.0.0.1<2>"
+ (funcall expect 1 "<joe>")
+ (erc-d-t-absent-for 0.1 "<bob>")
+ (funcall expect 1 "the loudest noise")
+ (should (eq erc-server-process server-process-bar))))
+
+ (ert-info ("Part #chan@foonet")
+ (with-current-buffer "#chan/127.0.0.1"
+ (erc-d-t-search-for 1 "shake my sword")
+ (erc-cmd-PART "#chan")
+ (funcall expect 3 "You have left channel #chan")
+ (erc-cmd-JOIN "#chan")))
+
+ (ert-info ("Part #chan@barnet")
+ (with-current-buffer "#chan/127.0.0.1<2>"
+ (funcall expect 10 "Arm it in rags")
+ (should (erc-get-channel-user (erc-current-nick)))
+ (erc-cmd-PART "#chan")
+ (funcall expect 3 "You have left channel #chan")
+ (should-not (erc-get-channel-user (erc-current-nick)))
+ (erc-cmd-JOIN "#chan")))
+
+ (erc-d-t-wait-for 3 "New unique target buffer for #chan@foonet created"
+ (get-buffer "#chan/127.0.0.1<3>"))
+
+ (ert-info ("Activity continues in new, <n>-suffixed #chan@foonet buffer")
+ (with-current-buffer "#chan/127.0.0.1"
+ (should-not (erc-get-channel-user (erc-current-nick))))
+ (with-current-buffer "#chan/127.0.0.1<3>"
+ (should (erc-get-channel-user (erc-current-nick)))
+ (funcall expect 2 "You have joined channel #chan")
+ (funcall expect 2 "#chan was created on")
+ (funcall expect 2 "<alice>")
+ (should (eq erc-server-process server-process-foo))
+ (erc-d-t-absent-for 0.2 "<joe>")))
+
+ (sit-for 3)
+ (erc-d-t-wait-for 5 "New unique target buffer for #chan@barnet created"
+ (get-buffer "#chan/127.0.0.1<4>"))
+
+ (ert-info ("Activity continues in new, <n>-suffixed #chan@barnet buffer")
+ (with-current-buffer "#chan/127.0.0.1<2>"
+ (should-not (erc-get-channel-user (erc-current-nick))))
+ (with-current-buffer "#chan/127.0.0.1<4>"
+ (funcall expect 2 "You have joined channel #chan")
+ (funcall expect 1 "Users on #chan: @mike joe tester")
+ (funcall expect 2 "<mike>")
+ (should (eq erc-server-process server-process-bar))
+ (erc-d-t-absent-for 0.2 "<bob>")))
+
+ (ert-info ("Two new chans created for a total of four")
+ (let* ((bufs (erc-scenarios-common-buflist "#chan"))
+ (names (sort (mapcar #'buffer-name bufs) #'string<)))
+ (should
+ (equal names (mapcar (lambda (f) (concat "#chan/127.0.0.1" f))
+ '("" "<2>" "<3>" "<4>"))))))
+
+ (ert-info ("All output sent")
+ (with-current-buffer "#chan/127.0.0.1<3>"
+ (funcall expect 10 "most lively"))
+ (with-current-buffer "#chan/127.0.0.1<4>"
+ (funcall expect 10 "soul black")))
+
+ ;; TODO ensure the exact <N>'s aren't reassigned during killing as
+ ;; they are when the option is on.
+ (ert-info ("Buffers are exempt from shortening")
+ (kill-buffer "#chan/127.0.0.1<4>")
+ (kill-buffer "#chan/127.0.0.1<3>")
+ (kill-buffer "#chan/127.0.0.1<2>")
+ (should-not (get-buffer "#chan"))
+ (should (get-buffer "#chan/127.0.0.1")))))
+
+(ert-deftest erc-scenarios-base-reuse-buffers-channel-buffers--disabled ()
+ :tags '(:expensive-test)
+ (with-suppressed-warnings ((obsolete erc-reuse-buffers))
+ (should erc-reuse-buffers)
+ (let ((erc-scenarios-common-dialog "base/reuse-buffers/channel")
+ (erc-server-flood-penalty 0.1)
+ erc-reuse-buffers)
+ (erc-scenarios-common--base-reuse-buffers-server-buffers
+ #'erc-scenarios-common--base-reuse-buffers-channel-buffers))))
+
+;;; erc-scenarios-base-reuse-buffers.el ends here
diff --git a/test/lisp/erc/erc-scenarios-base-unstable.el b/test/lisp/erc/erc-scenarios-base-unstable.el
new file mode 100644
index 00000000000..2313a15842c
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-base-unstable.el
@@ -0,0 +1,134 @@
+;;; erc-scenarios-base-unstable.el --- base unstable scenarios -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-scenarios-common)))
+
+(eval-when-compile (require 'erc-join))
+
+;; Not unstable, but stashed here for now
+
+(ert-deftest erc-scenarios-aux-unix-socket ()
+ :tags '(:expensive-test)
+ (skip-unless (featurep 'make-network-process '(:family local)))
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "base/renick/self")
+ (erc-server-flood-penalty 0.1)
+ (sock (expand-file-name "erc-d.sock" temporary-file-directory))
+ (erc-scenarios-common-extra-teardown (lambda () (delete-file sock)))
+ (erc-server-connect-function
+ (lambda (n b _ p &rest r)
+ (apply #'make-network-process
+ `(:name ,n :buffer ,b :service ,p :family local ,@r))))
+ (dumb-server (erc-d-run nil sock 'auto))
+ erc-autojoin-channels-alist
+ erc-server-buffer-foo)
+
+ (ert-info ("Connect to foonet")
+ (setq erc-server-buffer-foo (erc :server "fake"
+ :port sock
+ :nick "tester"
+ :password "foonet:changeme"
+ :full-name "tester"))
+ (with-current-buffer erc-server-buffer-foo
+ (should (string= (buffer-name) (format "fake:%s" sock)))))
+
+ (with-current-buffer (erc-d-t-wait-for 3 (get-buffer "foonet"))
+ (erc-d-t-search-for 10 "Your new nickname is dummy"))
+
+ (ert-info ("Joined by bouncer to #foo, own nick present")
+ (with-current-buffer (erc-d-t-wait-for 3 (get-buffer "#foo"))
+ (erc-d-t-search-for 10 "dummy")
+ (erc-d-t-search-for 10 "On Thursday")))))
+
+;; See `erc-networks--rename-server-buffer'. A perceived loss in
+;; network connectivity turns out to be a false alarm, but the bouncer
+;; has already accepted the second connection
+
+(defun erc-scenarios--base-aborted-reconnect ()
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "base/reconnect")
+ (erc-d-t-cleanup-sleep-secs 1)
+ (dumb-server (erc-d-run "localhost" t 'aborted 'aborted-dupe))
+ (port (process-contact dumb-server :service))
+ erc-autojoin-channels-alist
+ erc-server-buffer-foo)
+
+ (ert-info ("Connect to foonet")
+ (setq erc-server-buffer-foo (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :password "changeme"
+ :full-name "tester"))
+ (with-current-buffer erc-server-buffer-foo
+ (should (string= (buffer-name) (format "127.0.0.1:%d" port)))))
+
+ (ert-info ("Server buffer is unique and temp name is absent")
+ (erc-d-t-wait-for 10 (get-buffer "FooNet"))
+ (should-not (erc-scenarios-common-buflist "127.0.0.1"))
+ (with-current-buffer erc-server-buffer-foo
+ (erc-cmd-JOIN "#chan")))
+
+ (ert-info ("Channel buffer #chan alive and well")
+ (with-current-buffer (erc-d-t-wait-for 4 (get-buffer "#chan"))
+ (erc-d-t-search-for 10 "welcome")))
+
+ (ert-info ("Connect to foonet again")
+ (setq erc-server-buffer-foo (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :password "changeme"
+ :full-name "tester"))
+ (let ((inhibit-message noninteractive))
+ (with-current-buffer erc-server-buffer-foo
+ (should (string= (buffer-name) (format "127.0.0.1:%d" port)))
+ (erc-d-t-wait-for 5 (not (erc-server-process-alive)))
+ (erc-d-t-search-for 10 "FooNet still connected"))))
+
+ (ert-info ("Server buffer is unique and temp name is absent")
+ (should (equal (list (get-buffer "FooNet"))
+ (erc-scenarios-common-buflist "FooNet")))
+ (should (equal (list (get-buffer (format "127.0.0.1:%d" port)))
+ (erc-scenarios-common-buflist "127.0.0.1"))))
+
+ (ert-info ("Channel buffer #chan still going")
+ (with-current-buffer "#chan"
+ (erc-d-t-search-for 10 "and be prosperous")))))
+
+(ert-deftest erc-scenarios-base-aborted-reconnect ()
+ :tags '(:unstable)
+ (let ((tries 3)
+ (timeout 1)
+ failed)
+ (while (condition-case _err
+ (progn
+ (erc-scenarios--base-aborted-reconnect)
+ nil)
+ (ert-test-failed
+ (message "Test %S failed; %s attempt(s) remaining."
+ (ert-test-name (ert-running-test))
+ tries)
+ (sleep-for (cl-incf timeout))
+ (not (setq failed (zerop (cl-decf tries)))))))
+ (should-not failed)))
+
+;;; erc-scenarios-base-unstable.el ends here
diff --git a/test/lisp/erc/erc-scenarios-base-upstream-recon-soju.el b/test/lisp/erc/erc-scenarios-base-upstream-recon-soju.el
new file mode 100644
index 00000000000..5a5b363f31d
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-base-upstream-recon-soju.el
@@ -0,0 +1,43 @@
+;;; erc-scenarios-upstream-recon-soju.el --- Upstream soju -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+;; Commentary:
+;;
+;; These concern the loss and recovery of a proxy's IRC-side connection.
+
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-scenarios-common)))
+
+(ert-deftest erc-scenarios-upstream-recon--soju ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common--upstream-reconnect
+ (lambda ()
+ (with-current-buffer "foonet"
+ (erc-d-t-search-for 1 "disconnected from foonet")
+ (erc-d-t-search-for 1 "connected from foonet"))
+ (with-current-buffer "barnet"
+ (erc-d-t-search-for 1 "disconnected from barnet")
+ (erc-d-t-search-for 1 "connected from barnet")))
+ 'soju-foonet
+ 'soju-barnet))
+
+;;; erc-scenarios-upstream-recon-soju.el ends here
diff --git a/test/lisp/erc/erc-scenarios-base-upstream-recon-znc.el b/test/lisp/erc/erc-scenarios-base-upstream-recon-znc.el
new file mode 100644
index 00000000000..6e9a2172459
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-base-upstream-recon-znc.el
@@ -0,0 +1,43 @@
+;;; erc-scenarios-upstream-recon-znc.el --- Upstream znc -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+;; Commentary:
+;;
+;; These concern the loss and recovery of a proxy's IRC-side connection.
+
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-scenarios-common)))
+
+(ert-deftest erc-scenarios-upstream-recon--znc ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common--upstream-reconnect
+ (lambda ()
+ (with-current-buffer "*status@foonet"
+ (erc-d-t-search-for 1 "Disconnected from IRC")
+ (erc-d-t-search-for 1 "Connected!"))
+ (with-current-buffer "*status@barnet"
+ (erc-d-t-search-for 1 "Disconnected from IRC")
+ (erc-d-t-search-for 1 "Connected!")))
+ 'znc-foonet
+ 'znc-barnet))
+
+;;; erc-scenarios-upstream-recon-znc.el ends here
diff --git a/test/lisp/erc/erc-scenarios-internal.el b/test/lisp/erc/erc-scenarios-internal.el
new file mode 100644
index 00000000000..e4e1edb97e3
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-internal.el
@@ -0,0 +1,27 @@
+;;; erc-scenarios-internal.el --- Proxy file for erc-d tests -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (expand-file-name "erc-d" (ert-resource-directory))
+ load-path)))
+ (load "erc-d-tests" nil 'silent)))
+
+;;; erc-scenarios-internal.el ends here
diff --git a/test/lisp/erc/erc-scenarios-join-auth-source.el b/test/lisp/erc/erc-scenarios-join-auth-source.el
new file mode 100644
index 00000000000..94336db07c5
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-join-auth-source.el
@@ -0,0 +1,67 @@
+;;; erc-scenarios-join-auth-source.el --- join-auth-source scenarios -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; TODO add another test with autojoin and channel keys
+
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-scenarios-common)))
+
+(ert-deftest erc-scenarios-join-auth-source--network ()
+ :tags '(:expensive-test)
+ (should erc-auth-source-join-function)
+ (erc-scenarios-common-with-cleanup
+ ((entries
+ '("machine 127.0.0.1 port %d login \"#foo\" password spam"
+ "machine irc.foonet.org port %d login tester password fake"
+ "machine irc.foonet.org login \"#spam\" password secret"
+ "machine foonet port %d login dummy password fake"
+ "machine 127.0.0.1 port %d login dummy password changeme"))
+ (erc-scenarios-common-dialog "join/auth-source")
+ (erc-server-flood-penalty 0.1)
+ (dumb-server (erc-d-run "localhost" t 'foonet))
+ (port (process-contact dumb-server :service))
+ (ents (mapcar (lambda (fmt) (format fmt port)) entries))
+ (netrc-file (make-temp-file "auth-source-test" nil nil
+ (string-join ents "\n")))
+ (auth-sources (list netrc-file))
+ (auth-source-do-cache nil)
+ (expect (erc-d-t-make-expecter))
+ (erc-scenarios-common-extra-teardown (lambda ()
+ (delete-file netrc-file))))
+
+ (ert-info ("Connect without password")
+ (with-current-buffer (erc :server "127.0.0.1"
+ :port port
+ :nick "dummy"
+ :full-name "dummy")
+ (should (string= (buffer-name) (format "127.0.0.1:%d" port)))
+ (erc-d-t-wait-for 8 (eq erc-network 'foonet))
+ (funcall expect 10 "user modes")
+ (erc-scenarios-common-say "/JOIN #spam")))
+
+ (ert-info ("Join #spam")
+ (with-current-buffer (erc-d-t-wait-for 10 (get-buffer "#spam"))
+ (funcall expect 10 "#spam was created on")))))
+
+;;; erc-scenarios-join-auth-source.el ends here
diff --git a/test/lisp/erc/erc-scenarios-join-netid-newcmd-id.el b/test/lisp/erc/erc-scenarios-join-netid-newcmd-id.el
new file mode 100644
index 00000000000..e2e437321d9
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-join-netid-newcmd-id.el
@@ -0,0 +1,50 @@
+;;; erc-scenarios-join-netid-newcmd-id.el --- join netid newcmd scenarios -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-scenarios-common)))
+
+(ert-deftest erc-scenarios-join-netid--newcmd-id ()
+ :tags '(:expensive-test)
+ (let ((connect (lambda ()
+ (erc :server "127.0.0.1"
+ :port (with-current-buffer "oofnet"
+ (process-contact erc-server-process :service))
+ :nick "tester"
+ :password "foonet:changeme"
+ :full-name "tester"
+ :id 'oofnet))))
+ (erc-scenarios-common--join-network-id connect 'oofnet nil)))
+
+(ert-deftest erc-scenarios-join-netid--newcmd-ids ()
+ :tags '(:expensive-test)
+ (let ((connect (lambda ()
+ (erc :server "127.0.0.1"
+ :port (with-current-buffer "oofnet"
+ (process-contact erc-server-process :service))
+ :nick "tester"
+ :password "foonet:changeme"
+ :full-name "tester"
+ :id 'oofnet))))
+ (erc-scenarios-common--join-network-id connect 'oofnet 'rabnet)))
+
+;;; erc-scenarios-join-netid-newcmd-id.el ends here
diff --git a/test/lisp/erc/erc-scenarios-join-netid-newcmd.el b/test/lisp/erc/erc-scenarios-join-netid-newcmd.el
new file mode 100644
index 00000000000..1a541a46b3f
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-join-netid-newcmd.el
@@ -0,0 +1,37 @@
+;;; erc-scenarios-join-netid-newcmd.el --- join netid newcmd scenarios -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-scenarios-common)))
+
+(ert-deftest erc-scenarios-join-netid--newcmd ()
+ :tags '(:expensive-test)
+ (let ((connect (lambda ()
+ (erc :server "127.0.0.1"
+ :port (with-current-buffer "foonet"
+ (process-contact erc-server-process :service))
+ :nick "tester"
+ :password "foonet:changeme"
+ :full-name "tester"))))
+ (erc-scenarios-common--join-network-id connect nil nil)))
+
+;;; erc-scenarios-join-netid-newcmd.el ends here
diff --git a/test/lisp/erc/erc-scenarios-join-netid-recon-id.el b/test/lisp/erc/erc-scenarios-join-netid-recon-id.el
new file mode 100644
index 00000000000..92bdd643de8
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-join-netid-recon-id.el
@@ -0,0 +1,46 @@
+;;; erc-scenarios-join-netid-recon-id.el --- join-netid-recon scenarios -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-scenarios-common)))
+
+(ert-deftest erc-scenarios-join-netid--recon-id ()
+ :tags '(:expensive-test)
+ (let ((connect (lambda ()
+ (with-current-buffer "oofnet"
+ (erc-cmd-RECONNECT)
+ (should (eq (current-buffer)
+ (process-buffer erc-server-process)))
+ (current-buffer)))))
+ (erc-scenarios-common--join-network-id connect 'oofnet nil)))
+
+(ert-deftest erc-scenarios-join-netid--recon-ids ()
+ :tags '(:expensive-test)
+ (let ((connect (lambda ()
+ (with-current-buffer "oofnet"
+ (erc-cmd-RECONNECT)
+ (should (eq (current-buffer)
+ (process-buffer erc-server-process)))
+ (current-buffer)))))
+ (erc-scenarios-common--join-network-id connect 'oofnet 'rabnet)))
+
+;;; erc-scenarios-join-netid-recon-id.el ends here
diff --git a/test/lisp/erc/erc-scenarios-join-netid-recon.el b/test/lisp/erc/erc-scenarios-join-netid-recon.el
new file mode 100644
index 00000000000..cbdba07e256
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-join-netid-recon.el
@@ -0,0 +1,36 @@
+;;; erc-scenarios-join-netid-recon.el --- join-netid-recon scenarios -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-scenarios-common)))
+
+(ert-deftest erc-scenarios-join-netid--recon ()
+ :tags '(:expensive-test)
+ (let ((connect (lambda ()
+ (with-current-buffer "foonet"
+ (erc-cmd-RECONNECT)
+ (should (eq (current-buffer)
+ (process-buffer erc-server-process)))
+ (current-buffer)))))
+ (erc-scenarios-common--join-network-id connect nil nil)))
+
+;;; erc-scenarios-join-netid-recon.el ends here
diff --git a/test/lisp/erc/erc-scenarios-misc.el b/test/lisp/erc/erc-scenarios-misc.el
new file mode 100644
index 00000000000..ded620ccc1d
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-misc.el
@@ -0,0 +1,180 @@
+;;; erc-scenarios-misc.el --- Misc scenarios for ERC -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-scenarios-common)))
+
+(eval-when-compile (require 'erc-join))
+
+(ert-deftest erc-scenarios-base-flood ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "base/flood")
+ (dumb-server (erc-d-run "localhost" t 'soju))
+ (port (process-contact dumb-server :service))
+ (erc-server-flood-penalty 0.5) ; this ratio MUST match
+ (erc-server-flood-margin 1.5) ; the default of 3:10
+ (expect (erc-d-t-make-expecter))
+ erc-autojoin-channels-alist)
+
+ (ert-info ("Connect to bouncer")
+ (with-current-buffer
+ (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :password "changeme"
+ :full-name "tester")
+ (should (string= (buffer-name) (format "127.0.0.1:%d" port)))
+ (funcall expect 5 "Soju")))
+
+ (ert-info ("#chan@foonet exists")
+ (with-current-buffer (erc-d-t-wait-for 5 (get-buffer "#chan/foonet"))
+ (erc-d-t-search-for 2 "<bob/foonet>")
+ (erc-d-t-absent-for 0.1 "<joe")
+ (funcall expect 3 "was created on")))
+
+ (ert-info ("#chan@barnet exists")
+ (with-current-buffer (erc-d-t-wait-for 5 (get-buffer "#chan/barnet"))
+ (erc-d-t-search-for 2 "<joe/barnet>")
+ (erc-d-t-absent-for 0.1 "<bob")
+ (funcall expect 3 "was created on")
+ (funcall expect 5 "To get good guard")))
+
+ (ert-info ("Message not held in queue limbo")
+ (with-current-buffer "#chan/foonet"
+ ;; Without 'no-penalty param in `erc-server-send', should fail
+ ;; after ~10 secs with:
+ ;;
+ ;; (erc-d-timeout "Timed out awaiting request: (:name ~privmsg
+ ;; :pattern \\`PRIVMSG #chan/foonet :alice: hi :timeout 2
+ ;; :dialog soju)")
+ ;;
+ ;; Try reversing commit and spying on queue interactively
+ (erc-cmd-MSG "#chan/foonet alice: hi")
+ (funcall expect 5 "tester: Good, very good")))
+
+ (ert-info ("All output sent")
+ (with-current-buffer "#chan/foonet"
+ (funcall expect 8 "Some man or other"))
+ (with-current-buffer "#chan/barnet"
+ (funcall expect 10 "That's he that was Othello")))))
+
+;; Corner case demoing fallback behavior for an absent 004 RPL but a
+;; present 422 or 375. If this is unlikely enough, remove or guard
+;; with `ert-skip' plus some condition so it only runs when explicitly
+;; named via ERT specifier
+
+(ert-deftest erc-scenarios-networks-announced-missing ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "networks/announced-missing")
+ (expect (erc-d-t-make-expecter))
+ (dumb-server (erc-d-run "localhost" t 'foonet))
+ (port (process-contact dumb-server :service)))
+
+ (ert-info ("Connect without password")
+ (with-current-buffer (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :full-name "tester")
+ (should (string= (buffer-name) (format "127.0.0.1:%d" port)))
+ (let ((err (should-error (sleep-for 1))))
+ (should (string-match-p "Failed to determine" (cadr err))))
+ (funcall expect 1 "Failed to determine")
+ (funcall expect 1 "Failed to determine")
+ (should-not erc-network)
+ (should (string= erc-server-announced-name "irc.foonet.org"))))))
+
+;; Targets that are host/server masks like $*, $$*, and #* are routed
+;; to the server buffer: https://github.com/ircdocs/wooooms/issues/5
+
+(ert-deftest erc-scenarios-base-mask-target-routing ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "base/mask-target-routing")
+ (dumb-server (erc-d-run "localhost" t 'foonet))
+ (port (process-contact dumb-server :service))
+ (expect (erc-d-t-make-expecter)))
+
+ (ert-info ("Connect to foonet")
+ (with-current-buffer (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :password "changeme"
+ :full-name "tester")
+ (should (string= (buffer-name) (format "127.0.0.1:%d" port)))))
+
+ (erc-d-t-wait-for 10 (get-buffer "foonet"))
+
+ (ert-info ("Channel buffer #foo playback received")
+ (with-current-buffer (erc-d-t-wait-for 3 (get-buffer "#foo"))
+ (funcall expect 10 "Excellent workman")))
+
+ (ert-info ("Global notices routed to server buffer")
+ (with-current-buffer "foonet"
+ (funcall expect 10 "going down soon")
+ (funcall expect 10 "this is a warning")
+ (funcall expect 10 "second warning")
+ (funcall expect 10 "final warning")))
+
+ (should-not (get-buffer "$*"))))
+
+(ert-deftest erc-scenarios-dcc-chat-accept ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "dcc/chat")
+ (dcc-server (erc-d-run "127.0.0.1" t "erc-dcc-server" 'accept-dcc
+ :ending "\n"))
+ (dcc-port (process-contact dcc-server :service))
+ (dumb-server (erc-d-run "localhost" t 'accept :tmpl-vars
+ `((port . ,(number-to-string dcc-port)))))
+ (port (process-contact dumb-server :service))
+ (expect (erc-d-t-make-expecter)))
+
+ (ert-info ("Connect to foonet")
+ (with-current-buffer (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :password "changeme"
+ :full-name "tester")
+ (should (string= (buffer-name) (format "127.0.0.1:%d" port)))))
+
+ (ert-info ("Offer received")
+ (with-current-buffer (erc-d-t-wait-for 10 (get-buffer "foonet"))
+ (funcall expect 10 "DCC: chat offered by dummy")
+ (erc-cmd-DCC "CHAT" "dummy")))
+
+ ;; Regression
+ (erc-d-t-ensure-for 1 (not (get-buffer "tester")))
+
+ ;; Becomes current buffer by default (because `erc-join-buffer')
+ (erc-d-t-wait-for 10 (get-buffer "DCC-CHAT-dummy"))
+
+ (with-current-buffer "foonet"
+ (funcall expect 10 "*** DCC: accepting chat from dummy"))
+
+ (ert-info ("Chat with dummy")
+ (with-current-buffer "DCC-CHAT-dummy"
+ (erc-scenarios-common-say "Hi")
+ (funcall expect 10 "Hola")))))
+
+;;; erc-scenarios-misc.el ends here
diff --git a/test/lisp/erc/erc-scenarios-services-misc.el b/test/lisp/erc/erc-scenarios-services-misc.el
new file mode 100644
index 00000000000..cb1aa6ff324
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-services-misc.el
@@ -0,0 +1,86 @@
+;;; erc-scenarios-services-misc.el --- Services-misc scenarios -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-scenarios-common)))
+
+(eval-when-compile (require 'erc-join)
+ (require 'erc-services))
+
+(ert-deftest erc-scenarios-services-password ()
+ :tags '(:expensive-test)
+
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "services/password")
+ (erc-server-flood-penalty 0.1)
+ (erc-modules (cons 'services erc-modules))
+ (erc-nickserv-passwords '((Libera.Chat (("joe" . "bar")
+ ("tester" . "changeme")))))
+ (expect (erc-d-t-make-expecter))
+ (dumb-server (erc-d-run "localhost" t 'libera))
+ (port (process-contact dumb-server :service)))
+
+ (ert-info ("Connect without password")
+ (with-current-buffer (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :full-name "tester")
+ (should (string= (buffer-name) (format "127.0.0.1:%d" port)))
+ (erc-d-t-wait-for 5 (eq erc-network 'Libera.Chat))
+ (funcall expect 5 "This nickname is registered.")
+ (funcall expect 2 "You are now identified")
+ (funcall expect 1 "Last login from")
+ (erc-cmd-QUIT "")))
+
+ (erc-services-mode -1)
+
+ (should-not (memq 'services erc-modules))))
+
+(ert-deftest erc-scenarios-services-prompt ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "services/password")
+ (erc-server-flood-penalty 0.1)
+ (inhibit-interaction nil)
+ (erc-modules (cons 'services erc-modules))
+ (expect (erc-d-t-make-expecter))
+ (dumb-server (erc-d-run "localhost" t 'libera))
+ (port (process-contact dumb-server :service)))
+
+ (ert-info ("Connect without password")
+ (with-current-buffer (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :full-name "tester")
+ (should (string= (buffer-name) (format "127.0.0.1:%d" port)))
+ (ert-simulate-keys "changeme\r"
+ (erc-d-t-wait-for 10 (eq erc-network 'Libera.Chat))
+ (funcall expect 3 "This nickname is registered.")
+ (funcall expect 3 "You are now identified")
+ (funcall expect 3 "Last login from"))
+ (erc-cmd-QUIT "")))
+
+ (erc-services-mode -1)
+
+ (should-not (memq 'services erc-modules))))
+
+;;; erc-scenarios-services-misc.el ends here
diff --git a/test/lisp/erc/erc-services-tests.el b/test/lisp/erc/erc-services-tests.el
new file mode 100644
index 00000000000..8e2b8d29273
--- /dev/null
+++ b/test/lisp/erc/erc-services-tests.el
@@ -0,0 +1,574 @@
+;;; erc-services-tests.el --- Tests for erc-services. -*- lexical-binding:t -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+;;
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published
+;; by the Free Software Foundation, either version 3 of the License,
+;; or (at your option) any later version.
+;;
+;; GNU Emacs is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; TODO: move the auth-source tests somewhere else. They've been
+;; stashed here for pragmatic reasons.
+
+;;; Code:
+
+(require 'ert-x)
+(require 'erc-services)
+(require 'erc-compat)
+(require 'secrets)
+
+;;;; Core auth-source
+
+(ert-deftest erc--auth-source-determine-params-merge ()
+ (let ((erc-session-server "irc.gnu.org")
+ (erc-server-announced-name "my.gnu.org")
+ (erc-session-port 6697)
+ (erc-network 'fake)
+ (erc-server-current-nick "tester")
+ (erc-networks--id (erc-networks--id-create 'GNU.chat)))
+
+ (should (equal (erc--auth-source-determine-params-merge)
+ '(:host ("GNU.chat" "my.gnu.org" "irc.gnu.org")
+ :port ("6697" "irc")
+ :require (:secret))))
+
+ (should (equal (erc--auth-source-determine-params-merge :host "fake")
+ '(:host ("fake" "GNU.chat" "my.gnu.org" "irc.gnu.org")
+ :port ("6697" "irc")
+ :require (:secret))))
+
+ (should (equal (erc--auth-source-determine-params-merge
+ :host '("fake") :require :host)
+ '(:host ("fake" "GNU.chat" "my.gnu.org" "irc.gnu.org")
+ :require (:host :secret)
+ :port ("6697" "irc"))))
+
+ (should (equal (erc--auth-source-determine-params-merge
+ :host '("fake" "GNU.chat") :port "1234" :x "x")
+ '(:host ("fake" "GNU.chat" "my.gnu.org" "irc.gnu.org")
+ :port ("1234" "6697" "irc")
+ :x ("x")
+ :require (:secret))))))
+
+;; Some of the following may be related to bug#23438.
+
+(defun erc-services-tests--auth-source-standard (search)
+
+ (ert-info ("Session wins")
+ (let ((erc-session-server "irc.gnu.org")
+ (erc-server-announced-name "my.gnu.org")
+ (erc-session-port 6697)
+ (erc-network 'fake)
+ (erc-server-current-nick "tester")
+ (erc-networks--id (erc-networks--id-create 'GNU.chat)))
+ (should (string= (funcall search :user "#chan") "foo"))))
+
+ (ert-info ("Network wins")
+ (let* ((erc-session-server "irc.gnu.org")
+ (erc-server-announced-name "my.gnu.org")
+ (erc-session-port 6697)
+ (erc-network 'GNU.chat)
+ (erc-server-current-nick "tester")
+ (erc-networks--id (erc-networks--id-create nil)))
+ (should (string= (funcall search :user "#chan") "foo"))))
+
+ (ert-info ("Announced wins")
+ (let ((erc-session-server "irc.gnu.org")
+ (erc-server-announced-name "my.gnu.org")
+ (erc-session-port 6697)
+ erc-network
+ (erc-networks--id (erc-networks--id-create nil)))
+ (should (string= (funcall search :user "#chan") "baz")))))
+
+(defun erc-services-tests--auth-source-announced (search)
+ (let* ((erc--isupport-params (make-hash-table))
+ (erc-server-parameters '(("CHANTYPES" . "&#")))
+ (erc--target (erc--target-from-string "&chan")))
+
+ (ert-info ("Announced prioritized")
+
+ (ert-info ("Announced wins")
+ (let* ((erc-session-server "irc.gnu.org")
+ (erc-server-announced-name "my.gnu.org")
+ (erc-session-port 6697)
+ (erc-network 'GNU.chat)
+ (erc-server-current-nick "tester")
+ (erc-networks--id (erc-networks--id-create nil)))
+ (should (string= (funcall search :user "#chan") "baz"))))
+
+ (ert-info ("Peer next")
+ (let* ((erc-server-announced-name "irc.gnu.org")
+ (erc-session-port 6697)
+ (erc-network 'GNU.chat)
+ (erc-server-current-nick "tester")
+ (erc-networks--id (erc-networks--id-create nil)))
+ (should (string= (funcall search :user "#chan") "bar"))))
+
+ (ert-info ("Network used as fallback")
+ (let* ((erc-session-port 6697)
+ (erc-network 'GNU.chat)
+ (erc-server-current-nick "tester")
+ (erc-networks--id (erc-networks--id-create nil)))
+ (should (string= (funcall search :user "#chan") "foo")))))))
+
+(defun erc-services-tests--auth-source-overrides (search)
+ (let* ((erc-session-server "irc.gnu.org")
+ (erc-server-announced-name "my.gnu.org")
+ (erc-network 'GNU.chat)
+ (erc-server-current-nick "tester")
+ (erc-networks--id (erc-networks--id-create nil))
+ (erc-session-port 6667))
+
+ (ert-info ("Specificity and overrides")
+
+ (ert-info ("More specific port")
+ (let ((erc-session-port 6697))
+ (should (string= (funcall search :user "#chan") "spam"))))
+
+ (ert-info ("More specific user (network loses)")
+ (should (string= (funcall search :user '("#fsf")) "42")))
+
+ (ert-info ("Actual override")
+ (should (string= (funcall search :port "6667") "sesame")))
+
+ (ert-info ("Overrides don't interfere with post-processing")
+ (should (string= (funcall search :host "MyHost") "123"))))))
+
+;; auth-source netrc backend
+
+(defvar erc-services-tests--auth-source-entries
+ '("machine irc.gnu.org port irc user \"#chan\" password bar"
+ "machine my.gnu.org port irc user \"#chan\" password baz"
+ "machine GNU.chat port irc user \"#chan\" password foo"))
+
+;; FIXME explain what this is for
+(defun erc-services-tests--auth-source-shuffle (&rest extra)
+ (string-join `(,@(sort (append erc-services-tests--auth-source-entries extra)
+ (lambda (&rest _) (zerop (random 2))))
+ "")
+ "\n"))
+
+(ert-deftest erc--auth-source-search--netrc-standard ()
+ (ert-with-temp-file netrc-file
+ :prefix "erc--auth-source-search--standard"
+ :text (erc-services-tests--auth-source-shuffle)
+
+ (let ((auth-sources (list netrc-file))
+ (auth-source-do-cache nil))
+ (erc-services-tests--auth-source-standard #'erc-auth-source-search))))
+
+(ert-deftest erc--auth-source-search--netrc-announced ()
+ (ert-with-temp-file netrc-file
+ :prefix "erc--auth-source-search--announced"
+ :text (erc-services-tests--auth-source-shuffle)
+
+ (let ((auth-sources (list netrc-file))
+ (auth-source-do-cache nil))
+ (erc-services-tests--auth-source-announced #'erc-auth-source-search))))
+
+(ert-deftest erc--auth-source-search--netrc-overrides ()
+ (ert-with-temp-file netrc-file
+ :prefix "erc--auth-source-search--overrides"
+ :text (erc-services-tests--auth-source-shuffle
+ "machine GNU.chat port 6697 user \"#chan\" password spam"
+ "machine my.gnu.org port irc user \"#fsf\" password 42"
+ "machine irc.gnu.org port 6667 password sesame"
+ "machine MyHost port irc password 456"
+ "machine MyHost port 6667 password 123")
+
+ (let ((auth-sources (list netrc-file))
+ (auth-source-do-cache nil))
+ (erc-services-tests--auth-source-overrides #'erc-auth-source-search))))
+
+;; auth-source plstore backend
+
+(defun erc-services-test--call-with-plstore (&rest args)
+ (advice-add 'epg-decrypt-string :override
+ (lambda (&rest r) (prin1-to-string (cadr r)))
+ '((name . erc--auth-source-plstore)))
+ (advice-add 'epg-find-configuration :override
+ (lambda (&rest _) "" '((program . "/bin/true")))
+ '((name . erc--auth-source-plstore)))
+ (unwind-protect
+ (apply #'erc-auth-source-search args)
+ (advice-remove 'epg-decrypt-string 'erc--auth-source-plstore)
+ (advice-remove 'epg-find-configuration 'erc--auth-source-plstore)))
+
+(defvar erc-services-tests--auth-source-plstore-standard-entries
+ '(("ba950d38118a76d71f9f0591bb373d6cb366a512"
+ :secret-secret t
+ :host "irc.gnu.org"
+ :user "#chan"
+ :port "irc")
+ ("7f17ca445d11158065e911a6d0f4cbf52ca250e3"
+ :secret-secret t
+ :host "my.gnu.org"
+ :user "#chan"
+ :port "irc")
+ ("fcd3c8bd6daf4509de0ad6ee98e744ce0fca9377"
+ :secret-secret t
+ :host "GNU.chat"
+ :user "#chan"
+ :port "irc")))
+
+(defvar erc-services-tests--auth-source-plstore-standard-secrets
+ '(("ba950d38118a76d71f9f0591bb373d6cb366a512" :secret "bar")
+ ("7f17ca445d11158065e911a6d0f4cbf52ca250e3" :secret "baz")
+ ("fcd3c8bd6daf4509de0ad6ee98e744ce0fca9377" :secret "foo")))
+
+(ert-deftest erc--auth-source-search--plstore-standard ()
+ (ert-with-temp-file plstore-file
+ :suffix ".plist"
+ :text (concat ";;; public entries -*- mode: plstore -*- \n"
+ (prin1-to-string
+ erc-services-tests--auth-source-plstore-standard-entries)
+ "\n;;; secret entries\n"
+ (prin1-to-string
+ erc-services-tests--auth-source-plstore-standard-secrets)
+ "\n")
+
+ (let ((auth-sources (list plstore-file))
+ (auth-source-do-cache nil))
+ (erc-services-tests--auth-source-standard
+ #'erc-services-test--call-with-plstore))))
+
+(ert-deftest erc--auth-source-search--plstore-announced ()
+ (ert-with-temp-file plstore-file
+ :suffix ".plist"
+ :text (concat ";;; public entries -*- mode: plstore -*- \n"
+ (prin1-to-string
+ erc-services-tests--auth-source-plstore-standard-entries)
+ "\n;;; secret entries\n"
+ (prin1-to-string
+ erc-services-tests--auth-source-plstore-standard-secrets)
+ "\n")
+
+ (let ((auth-sources (list plstore-file))
+ (auth-source-do-cache nil))
+ (erc-services-tests--auth-source-announced
+ #'erc-services-test--call-with-plstore))))
+
+(ert-deftest erc--auth-source-search--plstore-overrides ()
+ (ert-with-temp-file plstore-file
+ :suffix ".plist"
+ :text (concat
+ ";;; public entries -*- mode: plstore -*- \n"
+ (prin1-to-string
+ `(,@erc-services-tests--auth-source-plstore-standard-entries
+ ("1b3fab249a8dff77a4d8fe7eb4b0171b25cc711a"
+ :secret-secret t :host "GNU.chat" :user "#chan" :port "6697")
+ ("6cbcdc39476b8cfcca6f3e9a7876f41ec3f708cc"
+ :secret-secret t :host "my.gnu.org" :user "#fsf" :port "irc")
+ ("a33e2b3bd2d6f33995a4b88710a594a100c5e41d"
+ :secret-secret t :host "irc.gnu.org" :port "6667")
+ ("ab2fd349b2b7d6a9215bb35a92d054261b0b1537"
+ :secret-secret t :host "MyHost" :port "irc")
+ ("61a6bd552059494f479ff720e8de33e22574650a"
+ :secret-secret t :host "MyHost" :port "6667")))
+ "\n;;; secret entries\n"
+ (prin1-to-string
+ `(,@erc-services-tests--auth-source-plstore-standard-secrets
+ ("1b3fab249a8dff77a4d8fe7eb4b0171b25cc711a" :secret "spam")
+ ("6cbcdc39476b8cfcca6f3e9a7876f41ec3f708cc" :secret "42")
+ ("a33e2b3bd2d6f33995a4b88710a594a100c5e41d" :secret "sesame")
+ ("ab2fd349b2b7d6a9215bb35a92d054261b0b1537" :secret "456")
+ ("61a6bd552059494f479ff720e8de33e22574650a" :secret "123")))
+ "\n")
+
+ (let ((auth-sources (list plstore-file))
+ (auth-source-do-cache nil))
+ (erc-services-tests--auth-source-overrides
+ #'erc-services-test--call-with-plstore))))
+
+;; auth-source JSON backend
+
+(defvar erc-services-tests--auth-source-json-standard-entries
+ [(:host "irc.gnu.org" :port "irc" :user "#chan" :secret "bar")
+ (:host "my.gnu.org" :port "irc" :user "#chan" :secret "baz")
+ (:host "GNU.chat" :port "irc" :user "#chan" :secret "foo")])
+
+(ert-deftest erc--auth-source-search--json-standard ()
+ (ert-with-temp-file json-store
+ :suffix ".json"
+ :text (let ((json-object-type 'plist))
+ (json-encode
+ erc-services-tests--auth-source-json-standard-entries))
+ (let ((auth-sources (list json-store))
+ (auth-source-do-cache nil))
+ (erc-services-tests--auth-source-standard #'erc-auth-source-search))))
+
+(ert-deftest erc--auth-source-search--json-announced ()
+ (ert-with-temp-file plstore-file
+ :suffix ".json"
+ :text (let ((json-object-type 'plist))
+ (json-encode
+ erc-services-tests--auth-source-json-standard-entries))
+
+ (let ((auth-sources (list plstore-file))
+ (auth-source-do-cache nil))
+ (erc-services-tests--auth-source-announced #'erc-auth-source-search))))
+
+(ert-deftest erc--auth-source-search--json-overrides ()
+ (ert-with-temp-file json-file
+ :suffix ".json"
+ :text (let ((json-object-type 'plist))
+ (json-encode
+ (vconcat
+ erc-services-tests--auth-source-json-standard-entries
+ [(:secret "spam" :host "GNU.chat" :user "#chan" :port "6697")
+ (:secret "42" :host "my.gnu.org" :user "#fsf" :port "irc")
+ (:secret "sesame" :host "irc.gnu.org" :port "6667")
+ (:secret "456" :host "MyHost" :port "irc")
+ (:secret "123" :host "MyHost" :port "6667")])))
+
+ (let ((auth-sources (list json-file))
+ (auth-source-do-cache nil))
+ (erc-services-tests--auth-source-overrides #'erc-auth-source-search))))
+
+;; auth-source-secrets backend
+
+(defvar erc-services-tests--auth-source-secrets-standard-entries
+ '(("#chan@irc.gnu.org:irc" ; label
+ (:host . "irc.gnu.org")
+ (:user . "#chan")
+ (:port . "irc")
+ (:xdg:schema . "org.freedesktop.Secret.Generic"))
+ ("#chan@my.gnu.org:irc"
+ (:host . "my.gnu.org")
+ (:user . "#chan")
+ (:port . "irc")
+ (:xdg:schema . "org.freedesktop.Secret.Generic"))
+ ("#chan@GNU.chat:irc"
+ (:host . "GNU.chat")
+ (:user . "#chan")
+ (:port . "irc")
+ (:xdg:schema . "org.freedesktop.Secret.Generic"))))
+
+(defvar erc-services-tests--auth-source-secrets-standard-secrets
+ '(("#chan@irc.gnu.org:irc" . "bar")
+ ("#chan@my.gnu.org:irc" . "baz")
+ ("#chan@GNU.chat:irc" . "foo")))
+
+(ert-deftest erc--auth-source-search--secrets-standard ()
+ (skip-unless (bound-and-true-p secrets-enabled))
+ (let ((auth-sources '("secrets:Test"))
+ (auth-source-do-cache nil)
+ (entries erc-services-tests--auth-source-secrets-standard-entries)
+ (secrets erc-services-tests--auth-source-secrets-standard-secrets))
+
+ (cl-letf (((symbol-function 'secrets-search-items)
+ (lambda (col &rest r)
+ (should (equal col "Test"))
+ (should (plist-get r :user))
+ (map-keys entries)))
+ ((symbol-function 'secrets-get-secret)
+ (lambda (col label)
+ (should (equal col "Test"))
+ (assoc-default label secrets)))
+ ((symbol-function 'secrets-get-attributes)
+ (lambda (col label)
+ (should (equal col "Test"))
+ (assoc-default label entries))))
+
+ (erc-services-tests--auth-source-standard #'erc-auth-source-search))))
+
+(ert-deftest erc--auth-source-search--secrets-announced ()
+ (skip-unless (bound-and-true-p secrets-enabled))
+ (let ((auth-sources '("secrets:Test"))
+ (auth-source-do-cache nil)
+ (entries erc-services-tests--auth-source-secrets-standard-entries)
+ (secrets erc-services-tests--auth-source-secrets-standard-secrets))
+
+ (cl-letf (((symbol-function 'secrets-search-items)
+ (lambda (col &rest r)
+ (should (equal col "Test"))
+ (should (plist-get r :user))
+ (map-keys entries)))
+ ((symbol-function 'secrets-get-secret)
+ (lambda (col label)
+ (should (equal col "Test"))
+ (assoc-default label secrets)))
+ ((symbol-function 'secrets-get-attributes)
+ (lambda (col label)
+ (should (equal col "Test"))
+ (assoc-default label entries))))
+
+ (erc-services-tests--auth-source-announced #'erc-auth-source-search))))
+
+(ert-deftest erc--auth-source-search--secrets-overrides ()
+ (skip-unless (bound-and-true-p secrets-enabled))
+ (let ((auth-sources '("secrets:Test"))
+ (auth-source-do-cache nil)
+ (entries `(,@erc-services-tests--auth-source-secrets-standard-entries
+ ("#chan@GNU.chat:6697"
+ (:host . "GNU.chat") (:user . "#chan") (:port . "6697")
+ (:xdg:schema . "org.freedesktop.Secret.Generic"))
+ ("#fsf@my.gnu.org:irc"
+ (:host . "my.gnu.org") (:user . "#fsf") (:port . "irc")
+ (:xdg:schema . "org.freedesktop.Secret.Generic"))
+ ("irc.gnu.org:6667"
+ (:host . "irc.gnu.org") (:port . "6667")
+ (:xdg:schema . "org.freedesktop.Secret.Generic"))
+ ("MyHost:irc"
+ (:host . "MyHost") (:port . "irc")
+ (:xdg:schema . "org.freedesktop.Secret.Generic"))
+ ("MyHost:6667"
+ (:host . "MyHost") (:port . "6667")
+ (:xdg:schema . "org.freedesktop.Secret.Generic"))))
+ (secrets `(,@erc-services-tests--auth-source-secrets-standard-secrets
+ ("#chan@GNU.chat:6697" . "spam")
+ ("#fsf@my.gnu.org:irc" . "42" )
+ ("irc.gnu.org:6667" . "sesame")
+ ("MyHost:irc" . "456")
+ ("MyHost:6667" . "123"))))
+
+ (cl-letf (((symbol-function 'secrets-search-items)
+ (lambda (col &rest _)
+ (should (equal col "Test"))
+ (map-keys entries)))
+ ((symbol-function 'secrets-get-secret)
+ (lambda (col label)
+ (should (equal col "Test"))
+ (assoc-default label secrets)))
+ ((symbol-function 'secrets-get-attributes)
+ (lambda (col label)
+ (should (equal col "Test"))
+ (assoc-default label entries))))
+
+ (erc-services-tests--auth-source-overrides #'erc-auth-source-search))))
+
+;; auth-source-pass backend
+
+(require 'auth-source-pass)
+
+;; `auth-source-pass--find-match-unambiguous' returns something like:
+;;
+;; (list :host "irc.gnu.org"
+;; :port "6697"
+;; :user "rms"
+;; :secret
+;; #[0 "\301\302\300\"\207"
+;; [((secret . "freedom")) auth-source-pass--get-attr secret] 3])
+;;
+;; This function gives ^ (faked here to avoid gpg and file IO). See
+;; `auth-source-pass--with-store' in ../auth-source-pass-tests.el
+(defun erc-services-tests--asp-parse-entry (store entry)
+ (when-let ((found (cl-find entry store :key #'car :test #'string=)))
+ (list (assoc 'secret (cdr found)))))
+
+(defvar erc-join-tests--auth-source-pass-entries
+ '(("irc.gnu.org:irc/#chan"
+ ("port" . "irc") ("user" . "#chan") (secret . "bar"))
+ ("my.gnu.org:irc/#chan"
+ ("port" . "irc") ("user" . "#chan") (secret . "baz"))
+ ("GNU.chat:irc/#chan"
+ ("port" . "irc") ("user" . "#chan") (secret . "foo"))))
+
+(ert-deftest erc--auth-source-search--pass-standard ()
+ (ert-skip "Pass backend not yet supported")
+ (let ((store erc-join-tests--auth-source-pass-entries)
+ (auth-sources '(password-store))
+ (auth-source-do-cache nil))
+
+ (cl-letf (((symbol-function 'auth-source-pass-parse-entry)
+ (apply-partially #'erc-services-tests--asp-parse-entry store))
+ ((symbol-function 'auth-source-pass-entries)
+ (lambda () (mapcar #'car store))))
+
+ (erc-services-tests--auth-source-standard #'erc-auth-source-search))))
+
+(ert-deftest erc--auth-source-search--pass-announced ()
+ (ert-skip "Pass backend not yet supported")
+ (let ((store erc-join-tests--auth-source-pass-entries)
+ (auth-sources '(password-store))
+ (auth-source-do-cache nil))
+
+ (cl-letf (((symbol-function 'auth-source-pass-parse-entry)
+ (apply-partially #'erc-services-tests--asp-parse-entry store))
+ ((symbol-function 'auth-source-pass-entries)
+ (lambda () (mapcar #'car store))))
+
+ (erc-services-tests--auth-source-announced #'erc-auth-source-search))))
+
+(ert-deftest erc--auth-source-search--pass-overrides ()
+ (ert-skip "Pass backend not yet supported")
+ (let ((store
+ `(,@erc-join-tests--auth-source-pass-entries
+ ("GNU.chat:6697/#chan"
+ ("port" . "6697") ("user" . "#chan") (secret . "spam"))
+ ("my.gnu.org:irc/#fsf"
+ ("port" . "irc") ("user" . "#fsf") (secret . "42"))
+ ("irc.gnu.org:6667"
+ ("port" . "6667") (secret . "sesame"))
+ ("MyHost:irc"
+ ("port" . "irc") (secret . "456"))
+ ("MyHost:6667"
+ ("port" . "6667") (secret . "123"))))
+ (auth-sources '(password-store))
+ (auth-source-do-cache nil))
+
+ (cl-letf (((symbol-function 'auth-source-pass-parse-entry)
+ (apply-partially #'erc-services-tests--asp-parse-entry store))
+ ((symbol-function 'auth-source-pass-entries)
+ (lambda () (mapcar #'car store))))
+
+ (erc-services-tests--auth-source-overrides #'erc-auth-source-search))))
+
+;;;; The services module
+
+(ert-deftest erc-nickserv-get-password ()
+ (should erc-prompt-for-nickserv-password)
+ (ert-with-temp-file netrc-file
+ :prefix "erc-nickserv-get-password"
+ :text (mapconcat 'identity
+ '("machine GNU/chat port 6697 user bob password spam"
+ "machine FSF.chat port 6697 user bob password sesame"
+ "machine MyHost port irc password 123")
+ "\n")
+
+ (let* ((auth-sources (list netrc-file))
+ (auth-source-do-cache nil)
+ (erc-nickserv-passwords '((FSF.chat (("alice" . "foo")
+ ("joe" . "bar")))))
+ (erc-use-auth-source-for-nickserv-password t)
+ (erc-session-server "irc.gnu.org")
+ (erc-server-announced-name "my.gnu.org")
+ (erc-network 'FSF.chat)
+ (erc-server-current-nick "tester")
+ (erc-networks--id (erc-networks--id-create nil))
+ (erc-session-port 6697))
+
+ (ert-info ("Lookup custom option")
+ (should (string= (erc-nickserv-get-password "alice") "foo")))
+
+ (ert-info ("Auth source")
+ (ert-info ("Network")
+ (should (string= (erc-nickserv-get-password "bob") "sesame")))
+
+ (ert-info ("Network ID")
+ (let ((erc-networks--id (erc-networks--id-create 'GNU/chat)))
+ (should (string= (erc-nickserv-get-password "bob") "spam")))))
+
+ (ert-info ("Read input")
+ (should (string=
+ (ert-simulate-keys "baz\r" (erc-nickserv-get-password "mike"))
+ "baz")))
+
+ (ert-info ("Failed")
+ (should-not (ert-simulate-keys "\r"
+ (erc-nickserv-get-password "fake")))))))
+
+
+;;; erc-services-tests.el ends here
diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el
new file mode 100644
index 00000000000..b2ed29e80ec
--- /dev/null
+++ b/test/lisp/erc/erc-tests.el
@@ -0,0 +1,978 @@
+;;; erc-tests.el --- Tests for erc. -*- lexical-binding:t -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+;; Author: Lars Ingebrigtsen <larsi@gnus.org>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert-x)
+(require 'erc)
+(require 'erc-ring)
+(require 'erc-networks)
+
+(ert-deftest erc--read-time-period ()
+ (cl-letf (((symbol-function 'read-string) (lambda (&rest _) "")))
+ (should (equal (erc--read-time-period "foo: ") nil)))
+
+ (cl-letf (((symbol-function 'read-string) (lambda (&rest _) " ")))
+ (should (equal (erc--read-time-period "foo: ") nil)))
+
+ (cl-letf (((symbol-function 'read-string) (lambda (&rest _) " 432 ")))
+ (should (equal (erc--read-time-period "foo: ") 432)))
+
+ (cl-letf (((symbol-function 'read-string) (lambda (&rest _) "432")))
+ (should (equal (erc--read-time-period "foo: ") 432)))
+
+ (cl-letf (((symbol-function 'read-string) (lambda (&rest _) "1h")))
+ (should (equal (erc--read-time-period "foo: ") 3600)))
+
+ (cl-letf (((symbol-function 'read-string) (lambda (&rest _) "1h10s")))
+ (should (equal (erc--read-time-period "foo: ") 3610)))
+
+ (cl-letf (((symbol-function 'read-string) (lambda (&rest _) "1d")))
+ (should (equal (erc--read-time-period "foo: ") 86400))))
+
+(ert-deftest erc--meta--backend-dependencies ()
+ (with-temp-buffer
+ (insert-file-contents-literally
+ (concat (file-name-sans-extension (symbol-file 'erc)) ".el"))
+ (let ((beg (search-forward ";; Defined in erc-backend"))
+ (end (search-forward "\n\n"))
+ vars)
+ (save-excursion
+ (save-restriction
+ (narrow-to-region beg end)
+ (goto-char (point-min))
+ (with-syntax-table lisp-data-mode-syntax-table
+ (condition-case _
+ (while (push (cadr (read (current-buffer))) vars))
+ (end-of-file)))))
+ (should (= (point) end))
+ (dolist (var vars)
+ (setq var (concat "\\_<" (symbol-name var) "\\_>"))
+ (ert-info (var)
+ (should (save-excursion (search-forward-regexp var nil t))))))))
+
+(ert-deftest erc-with-all-buffers-of-server ()
+ (let (proc-exnet
+ proc-onet
+ erc-kill-channel-hook erc-kill-server-hook erc-kill-buffer-hook)
+
+ (with-current-buffer (get-buffer-create "OtherNet")
+ (erc-mode)
+ (setq proc-onet (start-process "sleep" (current-buffer) "sleep" "1")
+ erc-server-process proc-onet
+ erc-network 'OtherNet)
+ (set-process-query-on-exit-flag erc-server-process nil))
+
+ (with-current-buffer (get-buffer-create "ExampleNet")
+ (erc-mode)
+ (setq proc-exnet (start-process "sleep" (current-buffer) "sleep" "1")
+ erc-server-process proc-exnet
+ erc-network 'ExampleNet)
+ (set-process-query-on-exit-flag erc-server-process nil))
+
+ (with-current-buffer (get-buffer-create "#foo")
+ (erc-mode)
+ (setq erc-server-process proc-exnet)
+ (setq erc-default-recipients '("#foo")))
+
+ (with-current-buffer (get-buffer-create "#spam")
+ (erc-mode)
+ (setq erc-server-process proc-onet)
+ (setq erc-default-recipients '("#spam")))
+
+ (with-current-buffer (get-buffer-create "#bar")
+ (erc-mode)
+ (setq erc-server-process proc-onet)
+ (setq erc-default-recipients '("#bar")))
+
+ (with-current-buffer (get-buffer-create "#baz")
+ (erc-mode)
+ (setq erc-server-process proc-exnet)
+ (setq erc-default-recipients '("#baz")))
+
+ (should (eq (get-buffer-process "ExampleNet") proc-exnet))
+ (erc-with-all-buffers-of-server (get-buffer-process "ExampleNet")
+ nil
+ (kill-buffer))
+
+ (should-not (get-buffer "ExampleNet"))
+ (should-not (get-buffer "#foo"))
+ (should-not (get-buffer "#baz"))
+ (should (get-buffer "OtherNet"))
+ (should (get-buffer "#bar"))
+ (should (get-buffer "#spam"))
+
+ (let* ((test (lambda () (not (string= (buffer-name) "#spam"))))
+ (calls 0)
+ (get-test (lambda () (cl-incf calls) test)))
+
+ (erc-with-all-buffers-of-server proc-onet
+ (funcall get-test)
+ (kill-buffer))
+
+ (should (= calls 1)))
+
+ (should-not (get-buffer "OtherNet"))
+ (should-not (get-buffer "#bar"))
+ (should (get-buffer "#spam"))
+ (kill-buffer "#spam")))
+
+(defun erc-tests--send-prep ()
+ ;; Caller should probably shadow `erc-insert-modify-hook' or
+ ;; populate user tables for erc-button.
+ (erc-mode)
+ (insert "\n\n")
+ (setq erc-input-marker (make-marker)
+ erc-insert-marker (make-marker))
+ (set-marker erc-insert-marker (point-max))
+ (erc-display-prompt)
+ (should (= (point) erc-input-marker)))
+
+(defun erc-tests--set-fake-server-process (&rest args)
+ (setq erc-server-process
+ (apply #'start-process (car args) (current-buffer) args))
+ (set-process-query-on-exit-flag erc-server-process nil))
+
+(ert-deftest erc-hide-prompt ()
+ (let (erc-kill-channel-hook erc-kill-server-hook erc-kill-buffer-hook)
+
+ (with-current-buffer (get-buffer-create "ServNet")
+ (erc-tests--send-prep)
+ (goto-char erc-insert-marker)
+ (should (looking-at-p (regexp-quote erc-prompt)))
+ (erc-tests--set-fake-server-process "sleep" "1")
+ (set-process-sentinel erc-server-process #'ignore)
+ (setq erc-network 'ServNet)
+ (set-process-query-on-exit-flag erc-server-process nil))
+
+ (with-current-buffer (get-buffer-create "#chan")
+ (erc-tests--send-prep)
+ (goto-char erc-insert-marker)
+ (should (looking-at-p (regexp-quote erc-prompt)))
+ (setq erc-server-process (buffer-local-value 'erc-server-process
+ (get-buffer "ServNet"))
+ erc-default-recipients '("#chan")))
+
+ (with-current-buffer (get-buffer-create "bob")
+ (erc-tests--send-prep)
+ (goto-char erc-insert-marker)
+ (should (looking-at-p (regexp-quote erc-prompt)))
+ (setq erc-server-process (buffer-local-value 'erc-server-process
+ (get-buffer "ServNet"))
+ erc-default-recipients '("bob")))
+
+ (ert-info ("Value: t (default)")
+ (should (eq erc-hide-prompt t))
+ (with-current-buffer "ServNet"
+ (should (= (point) erc-insert-marker))
+ (erc--hide-prompt erc-server-process)
+ (should (string= ">" (get-text-property (point) 'display))))
+
+ (with-current-buffer "#chan"
+ (goto-char erc-insert-marker)
+ (should (string= ">" (get-text-property (point) 'display)))
+ (should (memq #'erc--unhide-prompt-on-self-insert pre-command-hook))
+ (goto-char erc-input-marker)
+ (ert-simulate-command '(self-insert-command 1 ?/))
+ (goto-char erc-insert-marker)
+ (should-not (get-text-property (point) 'display))
+ (should-not (memq #'erc--unhide-prompt-on-self-insert
+ pre-command-hook)))
+
+ (with-current-buffer "bob"
+ (goto-char erc-insert-marker)
+ (should (string= ">" (get-text-property (point) 'display)))
+ (should (memq #'erc--unhide-prompt-on-self-insert pre-command-hook))
+ (goto-char erc-input-marker)
+ (ert-simulate-command '(self-insert-command 1 ?/))
+ (goto-char erc-insert-marker)
+ (should-not (get-text-property (point) 'display))
+ (should-not (memq #'erc--unhide-prompt-on-self-insert
+ pre-command-hook)))
+
+ (with-current-buffer "ServNet"
+ (should (get-text-property erc-insert-marker 'display))
+ (should (memq #'erc--unhide-prompt-on-self-insert pre-command-hook))
+ (erc--unhide-prompt)
+ (should-not (memq #'erc--unhide-prompt-on-self-insert
+ pre-command-hook))
+ (should-not (get-text-property erc-insert-marker 'display))))
+
+ (ert-info ("Value: server")
+ (setq erc-hide-prompt '(server))
+ (with-current-buffer "ServNet"
+ (erc--hide-prompt erc-server-process)
+ (should (string= ">" (get-text-property erc-insert-marker 'display))))
+
+ (with-current-buffer "#chan"
+ (should-not (get-text-property erc-insert-marker 'display)))
+
+ (with-current-buffer "bob"
+ (should-not (get-text-property erc-insert-marker 'display)))
+
+ (with-current-buffer "ServNet"
+ (erc--unhide-prompt)
+ (should-not (get-text-property erc-insert-marker 'display))))
+
+ (ert-info ("Value: channel")
+ (setq erc-hide-prompt '(channel))
+ (with-current-buffer "ServNet"
+ (erc--hide-prompt erc-server-process)
+ (should-not (get-text-property erc-insert-marker 'display)))
+
+ (with-current-buffer "bob"
+ (should-not (get-text-property erc-insert-marker 'display)))
+
+ (with-current-buffer "#chan"
+ (should (string= ">" (get-text-property erc-insert-marker 'display)))
+ (erc--unhide-prompt)
+ (should-not (get-text-property erc-insert-marker 'display))))
+
+ (ert-info ("Value: query")
+ (setq erc-hide-prompt '(query))
+ (with-current-buffer "ServNet"
+ (erc--hide-prompt erc-server-process)
+ (should-not (get-text-property erc-insert-marker 'display)))
+
+ (with-current-buffer "bob"
+ (should (string= ">" (get-text-property erc-insert-marker 'display)))
+ (erc--unhide-prompt)
+ (should-not (get-text-property erc-insert-marker 'display)))
+
+ (with-current-buffer "#chan"
+ (should-not (get-text-property erc-insert-marker 'display))))
+
+ (ert-info ("Value: nil")
+ (setq erc-hide-prompt nil)
+ (with-current-buffer "ServNet"
+ (erc--hide-prompt erc-server-process)
+ (should-not (get-text-property erc-insert-marker 'display)))
+
+ (with-current-buffer "bob"
+ (should-not (get-text-property erc-insert-marker 'display)))
+
+ (with-current-buffer "#chan"
+ (should-not (get-text-property erc-insert-marker 'display))
+ (erc--unhide-prompt) ; won't blow up when prompt already showing
+ (should-not (get-text-property erc-insert-marker 'display))))
+
+ (when noninteractive
+ (kill-buffer "#chan")
+ (kill-buffer "bob")
+ (kill-buffer "ServNet"))))
+
+(ert-deftest erc--switch-to-buffer ()
+ (defvar erc-modified-channels-alist) ; lisp/erc/erc-track.el
+
+ (let ((proc (start-process "aNet" (current-buffer) "true"))
+ (erc-modified-channels-alist `(("fake") (,(messages-buffer))))
+ (inhibit-message noninteractive)
+ (completion-fail-discreetly t) ; otherwise ^G^G printed to .log file
+ ;;
+ erc-kill-channel-hook erc-kill-server-hook erc-kill-buffer-hook)
+
+ (with-current-buffer (get-buffer-create "server")
+ (erc-mode)
+ (set-process-buffer (setq erc-server-process proc) (current-buffer))
+ (set-process-query-on-exit-flag erc-server-process nil)
+ (with-current-buffer (get-buffer-create "#chan")
+ (erc-mode)
+ (setq erc-server-process proc))
+ (with-current-buffer (get-buffer-create "#foo")
+ (erc-mode)
+ (setq erc-server-process proc))
+
+ (ert-info ("Channel #chan selectable from server buffer")
+ (ert-simulate-keys (list ?# ?c ?h ?a ?n ?\C-m)
+ (should (string= "#chan" (erc--switch-to-buffer))))))
+
+ (ert-info ("Channel #foo selectable from non-ERC buffer")
+ (ert-simulate-keys (list ?# ?f ?o ?o ?\C-m)
+ (should (string= "#foo" (erc--switch-to-buffer)))))
+
+ (ert-info ("Default selectable")
+ (ert-simulate-keys (list ?\C-m)
+ (should (string= "*Messages*" (erc--switch-to-buffer)))))
+
+ (ert-info ("Extant but non-ERC buffer not selectable")
+ (get-buffer-create "#fake") ; not ours
+ (ert-simulate-keys (kbd "#fake C-m C-a C-k C-m")
+ ;; Initial query fails ~~~~~~^; clearing input accepts default
+ (should (string= "*Messages*" (erc--switch-to-buffer)))))
+
+ (with-current-buffer (get-buffer-create "other")
+ (erc-mode)
+ (setq erc-server-process (start-process "bNet" (current-buffer) "true"))
+ (set-process-query-on-exit-flag erc-server-process nil))
+
+ (ert-info ("Foreign ERC buffer not selectable")
+ (ert-simulate-keys (kbd "other C-m C-a C-k C-m")
+ (with-current-buffer "server"
+ (should (string= "*Messages*" (erc--switch-to-buffer))))))
+
+ (ert-info ("Any ERC-buffer selectable from non-ERC buffer")
+ (should-not (eq major-mode 'erc-mode))
+ (ert-simulate-keys (list ?o ?t ?h ?e ?r ?\C-m)
+ (should (string= "other" (erc--switch-to-buffer)))))
+
+ (dolist (b '("server" "other" "#chan" "#foo" "#fake"))
+ (kill-buffer b))))
+
+(ert-deftest erc-lurker-maybe-trim ()
+ (let (erc-lurker-trim-nicks
+ (erc-lurker-ignore-chars "_`"))
+
+ (should (string= "nick`" (erc-lurker-maybe-trim "nick`")))
+
+ (setq erc-lurker-trim-nicks t)
+ (should (string= "nick" (erc-lurker-maybe-trim "nick`")))
+ (should (string= "ni`_ck" (erc-lurker-maybe-trim "ni`_ck__``")))
+
+ (setq erc-lurker-ignore-chars "_-`") ; set of chars, not character alts
+ (should (string= "nick" (erc-lurker-maybe-trim "nick-_`")))))
+
+(ert-deftest erc--parse-isupport-value ()
+ (should (equal (erc--parse-isupport-value "a,b") '("a" "b")))
+ (should (equal (erc--parse-isupport-value "a,b,c") '("a" "b" "c")))
+
+ (should (equal (erc--parse-isupport-value "abc") '("abc")))
+ (should (equal (erc--parse-isupport-value "\\x20foo") '(" foo")))
+ (should (equal (erc--parse-isupport-value "foo\\x20") '("foo ")))
+ (should (equal (erc--parse-isupport-value "a\\x20b\\x20c") '("a b c")))
+ (should (equal (erc--parse-isupport-value "a\\x20b\\x20c\\x20") '("a b c ")))
+ (should (equal (erc--parse-isupport-value "\\x20a\\x20b\\x20c") '(" a b c")))
+ (should (equal (erc--parse-isupport-value "a\\x20\\x20c") '("a c")))
+ (should (equal (erc--parse-isupport-value "\\x20\\x20\\x20") '(" ")))
+ (should (equal (erc--parse-isupport-value "\\x5Co/") '("\\o/")))
+ (should (equal (erc--parse-isupport-value "\\x7F,\\x19") '("\\x7F" "\\x19")))
+ (should (equal (erc--parse-isupport-value "a\\x2Cb,c") '("a,b" "c"))))
+
+(ert-deftest erc--get-isupport-entry ()
+ (let ((erc--isupport-params (make-hash-table))
+ (erc-server-parameters '(("FOO" . "1") ("BAR") ("BAZ" . "A,B,C")))
+ (items (lambda ()
+ (cl-loop for k being the hash-keys of erc--isupport-params
+ using (hash-values v) collect (cons k v)))))
+
+ (should-not (erc--get-isupport-entry 'FAKE))
+ (should-not (erc--get-isupport-entry 'FAKE 'single))
+ (should (zerop (hash-table-count erc--isupport-params)))
+
+ (should (equal (erc--get-isupport-entry 'BAR) '(BAR)))
+ (should-not (erc--get-isupport-entry 'BAR 'single))
+ (should (= 1 (hash-table-count erc--isupport-params)))
+
+ (should (equal (erc--get-isupport-entry 'BAZ) '(BAZ "A" "B" "C")))
+ (should (equal (erc--get-isupport-entry 'BAZ 'single) "A"))
+ (should (= 2 (hash-table-count erc--isupport-params)))
+
+ (should (equal (erc--get-isupport-entry 'FOO 'single) "1"))
+ (should (equal (erc--get-isupport-entry 'FOO) '(FOO "1")))
+
+ (should (equal (funcall items)
+ '((BAR . --empty--) (BAZ "A" "B" "C") (FOO "1"))))))
+
+(ert-deftest erc-server-005 ()
+ (let* ((hooked 0)
+ (verify #'ignore)
+ (hook (lambda (_ _) (funcall verify) (cl-incf hooked)))
+ (erc-server-005-functions (list #'erc-server-005 hook #'ignore))
+ erc-server-parameters
+ erc--isupport-params
+ erc-timer-hook
+ calls
+ args
+ parsed)
+
+ (cl-letf (((symbol-function 'erc-display-message)
+ (lambda (_ _ _ line) (push line calls))))
+
+ (ert-info ("Baseline")
+ (setq args '("tester" "BOT=B" "EXCEPTS" "PREFIX=(ov)@+" "are supp...")
+ parsed (make-erc-response :command-args args :command "005"))
+
+ (setq verify
+ (lambda ()
+ (should (equal erc-server-parameters
+ '(("PREFIX" . "(ov)@+") ("EXCEPTS")
+ ("BOT" . "B"))))
+ (should (zerop (hash-table-count erc--isupport-params)))
+ (should (equal "(ov)@+" (erc--get-isupport-entry 'PREFIX t)))
+ (should (equal '(EXCEPTS) (erc--get-isupport-entry 'EXCEPTS)))
+ (should (equal "B" (erc--get-isupport-entry 'BOT t)))
+ (should (string= (pop calls)
+ "BOT=B EXCEPTS PREFIX=(ov)@+ are supp..."))
+ (should (equal args (erc-response.command-args parsed)))))
+
+ (erc-call-hooks nil parsed))
+
+ (ert-info ("Negated, updated")
+ (setq args '("tester" "-EXCEPTS" "-FAKE" "PREFIX=(ohv)@%+" "are su...")
+ parsed (make-erc-response :command-args args :command "005"))
+
+ (setq verify
+ (lambda ()
+ (should (equal erc-server-parameters
+ '(("PREFIX" . "(ohv)@%+") ("BOT" . "B"))))
+ (should (string= (pop calls)
+ "-EXCEPTS -FAKE PREFIX=(ohv)@%+ are su..."))
+ (should (equal "(ohv)@%+" (erc--get-isupport-entry 'PREFIX t)))
+ (should (equal "B" (erc--get-isupport-entry 'BOT t)))
+ (should-not (erc--get-isupport-entry 'EXCEPTS))
+ (should (equal args (erc-response.command-args parsed)))))
+
+ (erc-call-hooks nil parsed))
+ (should (= hooked 2)))))
+
+(ert-deftest erc-downcase ()
+ (let ((erc--isupport-params (make-hash-table)))
+
+ (puthash 'PREFIX '("(ov)@+") erc--isupport-params)
+ (puthash 'BOT '("B") erc--isupport-params)
+
+ (ert-info ("ascii")
+ (puthash 'CASEMAPPING '("ascii") erc--isupport-params)
+ (should (equal (erc-downcase "Bob[m]`") "bob[m]`"))
+ (should (equal (erc-downcase "Tilde~") "tilde~" ))
+ (should (equal (erc-downcase "\\O/") "\\o/" )))
+
+ (ert-info ("rfc1459")
+ (puthash 'CASEMAPPING '("rfc1459") erc--isupport-params)
+ (should (equal (erc-downcase "Bob[m]`") "bob{m}`" ))
+ (should (equal (erc-downcase "Tilde~") "tilde^" ))
+ (should (equal (erc-downcase "\\O/") "|o/" )))
+
+ (ert-info ("rfc1459-strict")
+ (puthash 'CASEMAPPING '("rfc1459-strict") erc--isupport-params)
+ (should (equal (erc-downcase "Bob[m]`") "bob{m}`"))
+ (should (equal (erc-downcase "Tilde~") "tilde~" ))
+ (should (equal (erc-downcase "\\O/") "|o/" )))))
+
+(ert-deftest erc--valid-local-channel-p ()
+ (ert-info ("Local channels not supported")
+ (let ((erc--isupport-params (make-hash-table)))
+ (puthash 'CHANTYPES '("#") erc--isupport-params)
+ (should-not (erc--valid-local-channel-p "#chan"))
+ (should-not (erc--valid-local-channel-p "&local"))))
+ (ert-info ("Local channels supported")
+ (let ((erc--isupport-params (make-hash-table)))
+ (puthash 'CHANTYPES '("&#") erc--isupport-params)
+ (should-not (erc--valid-local-channel-p "#chan"))
+ (should (erc--valid-local-channel-p "&local")))))
+
+(ert-deftest erc--target-from-string ()
+ (should (equal (erc--target-from-string "#chan")
+ #s(erc--target-channel "#chan" \#chan)))
+
+ (should (equal (erc--target-from-string "Bob")
+ #s(erc--target "Bob" bob)))
+
+ (let ((erc--isupport-params (make-hash-table)))
+ (puthash 'CHANTYPES '("&#") erc--isupport-params)
+ (should (equal (erc--target-from-string "&Bitlbee")
+ #s(erc--target-channel-local "&Bitlbee" &bitlbee)))))
+
+(ert-deftest erc-ring-previous-command-base-case ()
+ (ert-info ("Create ring when nonexistent and do nothing")
+ (let (erc-input-ring
+ erc-input-ring-index)
+ (erc-previous-command)
+ (should (ring-p erc-input-ring))
+ (should (zerop (ring-length erc-input-ring)))
+ (should-not erc-input-ring-index)))
+ (should-not erc-input-ring))
+
+(ert-deftest erc-ring-previous-command ()
+ (with-current-buffer (get-buffer-create "*#fake*")
+ (erc-mode)
+ (erc-tests--send-prep)
+ (setq-local erc-last-input-time 0)
+ (should-not (local-variable-if-set-p 'erc-send-completed-hook))
+ (set (make-local-variable 'erc-send-completed-hook) nil) ; skip t (globals)
+ ;; Just in case erc-ring-mode is already on
+ (setq-local erc-pre-send-functions nil)
+ (add-hook 'erc-pre-send-functions #'erc-add-to-input-ring)
+ ;;
+ (cl-letf (((symbol-function 'erc-process-input-line)
+ (lambda (&rest _)
+ (insert-before-markers
+ (erc-display-message-highlight 'notice "echo: one\n"))))
+ ((symbol-function 'erc-command-no-process-p)
+ (lambda (&rest _) t)))
+ (ert-info ("Create ring, populate, recall")
+ (insert "/one")
+ (erc-send-current-line)
+ (should (ring-p erc-input-ring))
+ (should (zerop (ring-member erc-input-ring "/one"))) ; equal
+ (should (save-excursion (forward-line -1)
+ (looking-at-p "[*]+ echo: one")))
+ (should-not erc-input-ring-index)
+ (erc-bol)
+ (should (looking-at "$"))
+ (erc-previous-command)
+ (erc-bol)
+ (should (looking-at "/one"))
+ (should (zerop erc-input-ring-index)))
+ (ert-info ("Back to one")
+ (should (= (ring-length erc-input-ring) (1+ erc-input-ring-index)))
+ (erc-previous-command)
+ (should-not erc-input-ring-index)
+ (erc-bol)
+ (should (looking-at "$"))
+ (should (equal (ring-ref erc-input-ring 0) "/one")))
+ (ert-info ("Swap input after prompt with previous (#bug46339)")
+ (insert "abc")
+ (erc-previous-command)
+ (should (= 1 erc-input-ring-index))
+ (erc-bol)
+ (should (looking-at "/one"))
+ (should (equal (ring-ref erc-input-ring 0) "abc"))
+ (should (equal (ring-ref erc-input-ring 1) "/one"))
+ (erc-next-command)
+ (erc-bol)
+ (should (looking-at "abc")))))
+ (when noninteractive
+ (kill-buffer "*#fake*")))
+
+(ert-deftest erc-log-irc-protocol ()
+ (should-not erc-debug-irc-protocol)
+ (with-temp-buffer
+ (setq erc-server-process (start-process "fake" (current-buffer) "true")
+ erc-server-current-nick "tester"
+ erc-session-server "myproxy.localhost"
+ erc-session-port 6667)
+ (let ((inhibit-message noninteractive))
+ (erc-toggle-debug-irc-protocol)
+ (erc-log-irc-protocol "PASS changeme\r\n" 'outgoing)
+ (setq erc-server-announced-name "irc.gnu.org")
+ (erc-log-irc-protocol ":irc.gnu.org 001 tester :Welcome")
+ (erc-log-irc-protocol ":irc.gnu.org 002 tester :Your host is irc.gnu.org")
+ (setq erc-network 'FooNet)
+ (setq erc-networks--id (erc-networks--id-create nil))
+ (erc-log-irc-protocol ":irc.gnu.org 422 tester :MOTD missing")
+ (setq erc-networks--id (erc-networks--id-create 'BarNet))
+ (erc-log-irc-protocol ":irc.gnu.org 221 tester +i")
+ (set-process-query-on-exit-flag erc-server-process nil)))
+ (with-current-buffer "*erc-protocol*"
+ (goto-char (point-min))
+ (search-forward "Version")
+ (search-forward "\r\n\r\n")
+ (search-forward "myproxy.localhost:6667 >> PASS" (pos-eol))
+ (forward-line)
+ (search-forward "irc.gnu.org << :irc.gnu.org 001" (pos-eol))
+ (forward-line)
+ (search-forward "irc.gnu.org << :irc.gnu.org 002" (pos-eol))
+ (forward-line)
+ (search-forward "FooNet << :irc.gnu.org 422" (pos-eol))
+ (forward-line)
+ (search-forward "BarNet << :irc.gnu.org 221" (pos-eol)))
+ (when noninteractive
+ (kill-buffer "*erc-protocol*")
+ (should-not erc-debug-irc-protocol)))
+
+(ert-deftest erc--input-line-delim-regexp ()
+ (let ((p erc--input-line-delim-regexp))
+ ;; none
+ (should (equal '("a" "b") (split-string "a\r\nb" p)))
+ (should (equal '("a" "b") (split-string "a\nb" p)))
+ (should (equal '("a" "b") (split-string "a\rb" p)))
+
+ ;; one
+ (should (equal '("") (split-string "" p)))
+ (should (equal '("a" "" "b") (split-string "a\r\rb" p)))
+ (should (equal '("a" "" "b") (split-string "a\n\rb" p)))
+ (should (equal '("a" "" "b") (split-string "a\n\nb" p)))
+ (should (equal '("a" "" "b") (split-string "a\r\r\nb" p)))
+ (should (equal '("a" "" "b") (split-string "a\n\r\nb" p)))
+ (should (equal '("a" "") (split-string "a\n" p)))
+ (should (equal '("a" "") (split-string "a\r" p)))
+ (should (equal '("a" "") (split-string "a\r\n" p)))
+ (should (equal '("" "b") (split-string "\nb" p)))
+ (should (equal '("" "b") (split-string "\rb" p)))
+ (should (equal '("" "b") (split-string "\r\nb" p)))
+
+ ;; two
+ (should (equal '("" "") (split-string "\r" p)))
+ (should (equal '("" "") (split-string "\n" p)))
+ (should (equal '("" "") (split-string "\r\n" p)))
+
+ ;; three
+ (should (equal '("" "" "") (split-string "\r\r" p)))
+ (should (equal '("" "" "") (split-string "\n\n" p)))
+ (should (equal '("" "" "") (split-string "\n\r" p)))))
+
+(ert-deftest erc--blank-in-multiline-input-p ()
+ (let ((check (lambda (s)
+ (erc--blank-in-multiline-input-p
+ (split-string s erc--input-line-delim-regexp)))))
+
+ (ert-info ("With `erc-send-whitespace-lines'")
+ (let ((erc-send-whitespace-lines t))
+ (should (funcall check ""))
+ (should-not (funcall check "\na"))
+ (should-not (funcall check "/msg a\n")) ; real /cmd
+ (should-not (funcall check "a\n\nb")) ; "" allowed
+ (should-not (funcall check "/msg a\n\nb")) ; non-/cmd
+ (should-not (funcall check " "))
+ (should-not (funcall check "\t"))
+ (should-not (funcall check "a\nb"))
+ (should-not (funcall check "a\n "))
+ (should-not (funcall check "a\n \t"))
+ (should-not (funcall check "a\n \f"))
+ (should-not (funcall check "a\n \nb"))
+ (should-not (funcall check "a\n \t\nb"))
+ (should-not (funcall check "a\n \f\nb"))))
+
+ (should (funcall check ""))
+ (should (funcall check " "))
+ (should (funcall check "\t"))
+ (should (funcall check "a\n\nb"))
+ (should (funcall check "a\n\nb"))
+ (should (funcall check "a\n "))
+ (should (funcall check "a\n \t"))
+ (should (funcall check "a\n \f"))
+ (should (funcall check "a\n \nb"))
+ (should (funcall check "a\n \t\nb"))
+
+ (should-not (funcall check "a\rb"))
+ (should-not (funcall check "a\nb"))
+ (should-not (funcall check "a\r\nb"))))
+
+(defun erc-tests--with-process-input-spy (test)
+ (with-current-buffer (get-buffer-create "FakeNet")
+ (let* ((erc-pre-send-functions
+ (remove #'erc-add-to-input-ring erc-pre-send-functions)) ; for now
+ (inhibit-message noninteractive)
+ (erc-server-current-nick "tester")
+ (erc-last-input-time 0)
+ erc-accidental-paste-threshold-seconds
+ erc-send-modify-hook
+ ;;
+ calls)
+ (cl-letf (((symbol-function 'erc-process-input-line)
+ (lambda (&rest r) (push r calls)))
+ ((symbol-function 'erc-server-buffer)
+ (lambda () (current-buffer))))
+ (erc-tests--send-prep)
+ (funcall test (lambda () (pop calls)))))
+ (when noninteractive (kill-buffer))))
+
+(ert-deftest erc--check-prompt-input-functions ()
+ (erc-tests--with-process-input-spy
+ (lambda (next)
+
+ (ert-info ("Errors when point not in prompt area") ; actually just dings
+ (insert "/msg #chan hi")
+ (forward-line -1)
+ (let ((e (should-error (erc-send-current-line))))
+ (should (equal "Point is not in the input area" (cadr e))))
+ (goto-char (point-max))
+ (ert-info ("Input remains untouched")
+ (should (save-excursion (erc-bol) (looking-at "/msg #chan hi")))))
+
+ (ert-info ("Errors when no process running")
+ (let ((e (should-error (erc-send-current-line))))
+ (should (equal "ERC: No process running" (cadr e))))
+ (ert-info ("Input remains untouched")
+ (should (save-excursion (erc-bol) (looking-at "/msg #chan hi")))))
+
+ (ert-info ("Errors when line contains empty newline")
+ (erc-bol)
+ (delete-region (point) (point-max))
+ (insert "one\n")
+ (let ((e (should-error (erc-send-current-line))))
+ (should (equal "Blank line - ignoring..." (cadr e))))
+ (goto-char (point-max))
+ (ert-info ("Input remains untouched")
+ (should (save-excursion (goto-char erc-input-marker)
+ (looking-at "one\n")))))
+
+ (should (= 0 erc-last-input-time))
+ (should-not (funcall next)))))
+
+;; These also indirectly tests `erc-send-input'
+
+(ert-deftest erc-send-current-line ()
+ (erc-tests--with-process-input-spy
+ (lambda (next)
+ (erc-tests--set-fake-server-process "sleep" "1")
+ (should (= 0 erc-last-input-time))
+
+ (ert-info ("Simple command")
+ (insert "/msg #chan hi")
+ (erc-send-current-line)
+ (ert-info ("Prompt restored")
+ (forward-line 0)
+ (should (looking-at-p erc-prompt)))
+ (ert-info ("Input cleared")
+ (erc-bol)
+ (should (eq (point) (point-max))))
+ ;; Commands are forced (no flood protection)
+ (should (equal (funcall next) '("/msg #chan hi\n" t nil))))
+
+ (ert-info ("Simple non-command")
+ (insert "hi")
+ (erc-send-current-line)
+ (should (eq (point) (point-max)))
+ (should (save-excursion (forward-line -1)
+ (search-forward "<tester> hi")))
+ ;; Non-ommands are forced only when `erc-flood-protect' is nil
+ (should (equal (funcall next) '("hi\n" nil t))))
+
+ (should (consp erc-last-input-time)))))
+
+(ert-deftest erc-send-whitespace-lines ()
+ (erc-tests--with-process-input-spy
+ (lambda (next)
+ (erc-tests--set-fake-server-process "sleep" "1")
+ (setq-local erc-send-whitespace-lines t)
+
+ (ert-info ("Multiline hunk with blank line correctly split")
+ (insert "one\n\ntwo")
+ (erc-send-current-line)
+ (ert-info ("Prompt restored")
+ (forward-line 0)
+ (should (looking-at-p erc-prompt)))
+ (ert-info ("Input cleared")
+ (erc-bol)
+ (should (eq (point) (point-max))))
+ (should (equal (funcall next) '("two\n" nil t)))
+ (should (equal (funcall next) '("\n" nil t)))
+ (should (equal (funcall next) '("one\n" nil t))))
+
+ (ert-info ("Multiline hunk with trailing newline filtered")
+ (insert "hi\n")
+ (erc-send-current-line)
+ (ert-info ("Input cleared")
+ (erc-bol)
+ (should (eq (point) (point-max))))
+ (should (equal (funcall next) '("hi\n" nil t)))
+ (should-not (funcall next)))
+
+ (ert-info ("Multiline hunk with trailing carriage filtered")
+ (insert "hi\r")
+ (erc-send-current-line)
+ (ert-info ("Input cleared")
+ (erc-bol)
+ (should (eq (point) (point-max))))
+ (should (equal (funcall next) '("hi\n" nil t)))
+ (should-not (funcall next)))
+
+ (ert-info ("Multiline command with trailing blank filtered")
+ (pcase-dolist (`(,p . ,q)
+ '(("/a b\r" "/a b\n") ("/a b\n" "/a b\n")
+ ("/a b\n\n" "/a b\n") ("/a b\r\n" "/a b\n")
+ ("a b\nc\n\n" "c\n" "a b\n")
+ ("/a b\nc\n\n" "c\n" "/a b\n")
+ ("/a b\n\nc\n\n" "c\n" "\n" "/a b\n")))
+ (insert p)
+ (erc-send-current-line)
+ (erc-bol)
+ (should (eq (point) (point-max)))
+ (while q
+ (should (equal (funcall next) (list (pop q) nil t))))
+ (should-not (funcall next))))
+
+ (ert-info ("Multiline hunk with trailing whitespace not filtered")
+ (insert "there\n ")
+ (erc-send-current-line)
+ (should (equal (funcall next) '(" \n" nil t)))
+ (should (equal (funcall next) '("there\n" nil t)))
+ (should-not (funcall next))))))
+
+(ert-deftest erc--check-prompt-input-for-excess-lines ()
+ (ert-info ("Without `erc-inhibit-multiline-input'")
+ (should-not erc-inhibit-multiline-input)
+ (should-not (erc--check-prompt-input-for-excess-lines "" '("a" "b"))))
+
+ (ert-info ("With `erc-inhibit-multiline-input' as t (2)")
+ (let ((erc-inhibit-multiline-input t))
+ (should-not (erc--check-prompt-input-for-excess-lines "" '("a")))
+ (should-not (erc--check-prompt-input-for-excess-lines "" '("a" "")))
+ (should (erc--check-prompt-input-for-excess-lines "" '("a" "b")))))
+
+ (ert-info ("With `erc-inhibit-multiline-input' as 3")
+ (let ((erc-inhibit-multiline-input 3))
+ (should-not (erc--check-prompt-input-for-excess-lines "" '("a" "b")))
+ (should-not (erc--check-prompt-input-for-excess-lines "" '("a" "b" "")))
+ (should (erc--check-prompt-input-for-excess-lines "" '("a" "b" "c")))))
+
+ (ert-info ("With `erc-ask-about-multiline-input'")
+ (let ((erc-inhibit-multiline-input t)
+ (erc-ask-about-multiline-input t))
+ (ert-simulate-keys '(?n ?\r ?y ?\r)
+ (should (erc--check-prompt-input-for-excess-lines "" '("a" "b")))
+ (should-not (erc--check-prompt-input-for-excess-lines "" '("a" "b")))))
+ (should-not erc-ask-about-multiline-input)))
+
+;; The point of this test is to ensure output is handled identically
+;; regardless of whether a command handler is summoned.
+
+(ert-deftest erc-process-input-line ()
+ (let (erc-server-last-sent-time
+ erc-server-flood-queue
+ (orig-erc-cmd-MSG (symbol-function 'erc-cmd-MSG))
+ (erc-default-recipients '("#chan"))
+ calls)
+ (with-temp-buffer
+ (cl-letf (((symbol-function 'erc-cmd-MSG)
+ (lambda (line)
+ (push line calls)
+ (funcall orig-erc-cmd-MSG line)))
+ ((symbol-function 'erc-server-buffer)
+ (lambda () (current-buffer)))
+ ((symbol-function 'erc-server-process-alive)
+ (lambda () t))
+ ((symbol-function 'erc-server-send-queue)
+ #'ignore))
+
+ (ert-info ("Dispatch to user command handler")
+
+ (ert-info ("Baseline")
+ (erc-process-input-line "/msg #chan hi\n")
+ (should (equal (pop calls) " #chan hi"))
+ (should (equal (pop erc-server-flood-queue)
+ '("PRIVMSG #chan :hi\r\n" . utf-8))))
+
+ (ert-info ("Quote preserves line intact")
+ (erc-process-input-line "/QUOTE FAKE foo bar\n")
+ (should (equal (pop erc-server-flood-queue)
+ '("FAKE foo bar\r\n" . utf-8))))
+
+ (ert-info ("Unknown command respected")
+ (erc-process-input-line "/FAKE foo bar\n")
+ (should (equal (pop erc-server-flood-queue)
+ '("FAKE foo bar\r\n" . utf-8))))
+
+ (ert-info ("Spaces preserved")
+ (erc-process-input-line "/msg #chan hi you\n")
+ (should (equal (pop calls) " #chan hi you"))
+ (should (equal (pop erc-server-flood-queue)
+ '("PRIVMSG #chan :hi you\r\n" . utf-8))))
+
+ (ert-info ("Empty line honored")
+ (erc-process-input-line "/msg #chan\n")
+ (should (equal (pop calls) " #chan"))
+ (should (equal (pop erc-server-flood-queue)
+ '("PRIVMSG #chan :\r\n" . utf-8)))))
+
+ (ert-info ("Implicit cmd via `erc-send-input-line-function'")
+
+ (ert-info ("Baseline")
+ (erc-process-input-line "hi\n")
+ (should (equal (pop erc-server-flood-queue)
+ '("PRIVMSG #chan :hi\r\n" . utf-8))))
+
+ (ert-info ("Spaces preserved")
+ (erc-process-input-line "hi you\n")
+ (should (equal (pop erc-server-flood-queue)
+ '("PRIVMSG #chan :hi you\r\n" . utf-8))))
+
+ (ert-info ("Empty line transmitted with injected-space kludge")
+ (erc-process-input-line "\n")
+ (should (equal (pop erc-server-flood-queue)
+ '("PRIVMSG #chan : \r\n" . utf-8))))
+
+ (should-not calls))))))
+
+;; Note: if adding an erc-backend-tests.el, please relocate this there.
+
+(ert-deftest erc-message ()
+ (should-not erc-server-last-peers)
+ (let (server-proc
+ calls
+ erc-kill-channel-hook erc-kill-server-hook erc-kill-buffer-hook)
+ (cl-letf (((symbol-function 'erc-display-message)
+ (lambda (_ _ _ line) (push line calls)))
+ ((symbol-function 'erc-server-send)
+ (lambda (line _) (push line calls)))
+ ((symbol-function 'erc-server-buffer)
+ (lambda () (process-buffer server-proc))))
+ (with-current-buffer (get-buffer-create "ExampleNet")
+ (erc-mode)
+ (setq erc-server-current-nick "tester"
+ server-proc (start-process "sleep" (current-buffer) "sleep" "1")
+ erc-server-process server-proc
+ erc-server-last-peers (cons nil nil)
+ erc-server-users (make-hash-table :test 'equal)
+ erc-network 'ExampleNet)
+ (set-process-query-on-exit-flag erc-server-process nil))
+
+ (with-current-buffer (get-buffer-create "#chan")
+ (erc-mode)
+ (setq erc-server-process (buffer-local-value 'erc-server-process
+ (get-buffer "ExampleNet"))
+ erc-default-recipients '("#chan")
+ erc-channel-users (make-hash-table :test 'equal)
+ erc-network 'ExampleNet)
+ (erc-update-current-channel-member "alice" "alice")
+ (erc-update-current-channel-member "tester" "tester"))
+
+ (with-current-buffer "ExampleNet"
+ (erc-server-PRIVMSG erc-server-process
+ (make-erc-response
+ :sender "alice!~u@fsf.org"
+ :command "PRIVMSG"
+ :command-args '("#chan" "hi")
+ :unparsed ":alice!~u@fsf.org PRIVMSG #chan :hi"))
+ (should (equal erc-server-last-peers '("alice")))
+ (should (string-match "<alice>" (pop calls))))
+
+ (with-current-buffer "#chan"
+ (ert-info ("Shortcuts usable in target buffers")
+ (should-not (local-variable-p 'erc-server-last-peers))
+ (should-not erc-server-last-peers)
+ (erc-message "PRIVMSG" ". hi")
+ (should-not erc-server-last-peers)
+ (should (eq 'no-target (pop calls)))
+ (erc-message "PRIVMSG" ", hi")
+ (should-not erc-server-last-peers)
+ (should (string-match "alice :hi" (pop calls)))))
+
+ (with-current-buffer "ExampleNet"
+ (ert-info ("Shortcuts local in server bufs")
+ (should (equal erc-server-last-peers '("alice" . "alice")))
+ (erc-message "PRIVMSG" ", hi")
+ (should (equal erc-server-last-peers '("alice" . "alice")))
+ (should (string-match "PRIVMSG alice :hi" (pop calls)))
+ (setcdr erc-server-last-peers "bob")
+ (erc-message "PRIVMSG" ". hi")
+ (should (equal erc-server-last-peers '("alice" . "bob")))
+ (should (string-match "PRIVMSG bob :hi" (pop calls)))))
+
+ (with-current-buffer "#chan"
+ (ert-info ("Non-shortcuts are local to server buffer")
+ (should-not (local-variable-p 'erc-server-last-peers))
+ (should-not erc-server-last-peers)
+ (erc-message "PRIVMSG" "#chan hola")
+ (should-not erc-server-last-peers)
+ (should-not (default-value 'erc-server-last-peers))
+ (should (equal (buffer-local-value 'erc-server-last-peers
+ (get-buffer "ExampleNet"))
+ '("alice" . "#chan")))
+ (should (string-match "hola" (pop calls))))))
+
+ (should-not erc-server-last-peers)
+ (should-not calls)
+ (kill-buffer "ExampleNet")
+ (kill-buffer "#chan")))
+
+;;; erc-tests.el ends here
diff --git a/test/lisp/erc/erc-track-tests.el b/test/lisp/erc/erc-track-tests.el
index 6e36ed4071b..475a436bb1d 100644
--- a/test/lisp/erc/erc-track-tests.el
+++ b/test/lisp/erc/erc-track-tests.el
@@ -1,6 +1,6 @@
-;;; erc-track-tests.el --- Tests for erc-track.
+;;; erc-track-tests.el --- Tests for erc-track. -*- lexical-binding:t -*-
-;; Copyright (C) 2016-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2022 Free Software Foundation, Inc.
;; Author: Mario Lang <mlang@delysid.org>
;; Author: Vivek Dasmohapatra <vivek@etla.org>
@@ -24,7 +24,6 @@
(require 'ert)
(require 'erc-track)
-(require 'font-core)
(ert-deftest erc-track--shorten-aggressive-nil ()
"Test non-aggressive erc track buffer name shortening."
@@ -107,8 +106,8 @@
(ert-deftest erc-track--erc-faces-in ()
"`erc-faces-in' should pick up both 'face and 'font-lock-face properties."
- (let ((str0 "is bold")
- (str1 "is bold"))
+ (let ((str0 (copy-sequence "is bold"))
+ (str1 (copy-sequence "is bold")))
;; Turn on Font Lock mode: this initialize `char-property-alias-alist'
;; to '((face font-lock-face)). Note that `font-lock-mode' don't
;; turn on the mode if the test is run on batch mode or if the
@@ -120,3 +119,5 @@
'(bold erc-current-nick-face) str1)
(should (erc-faces-in str0))
(should (erc-faces-in str1)) ))
+
+;;; erc-track-tests.el ends here
diff --git a/test/lisp/erc/resources/base/assoc/bouncer-history/barnet.eld b/test/lisp/erc/resources/base/assoc/bouncer-history/barnet.eld
new file mode 100644
index 00000000000..35a9a570b6d
--- /dev/null
+++ b/test/lisp/erc/resources/base/assoc/bouncer-history/barnet.eld
@@ -0,0 +1,44 @@
+;; -*- mode: lisp-data; -*-
+((pass 3 "PASS :barnet:changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.barnet.org 001 tester :Welcome to the barnet IRC Network tester")
+ (0 ":irc.barnet.org 002 tester :Your host is irc.barnet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.barnet.org 003 tester :This server was created Wed, 28 Apr 2021 06:59:59 UTC")
+ (0 ":irc.barnet.org 004 tester irc.barnet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.barnet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.barnet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=barnet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.barnet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.barnet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.barnet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.barnet.org 254 tester 1 :channels formed")
+ (0 ":irc.barnet.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.barnet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.barnet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.barnet.org 422 tester :MOTD File is missing"))
+
+((mode-user 3.2 "MODE tester +i")
+ ;; No mode answer ^
+ (0 ":irc.znc.in 306 tester :You have been marked as being away")
+ (0 ":tester!~u@xrir8fpe4d7ak.irc JOIN #chan")
+ (0 ":irc.barnet.org 353 tester = #chan :joe @mike tester")
+ (0 ":irc.barnet.org 366 tester #chan :End of /NAMES list.")
+ (0 ":***!znc@znc.in PRIVMSG #chan :Buffer Playback...")
+ (0 ":joe!~u@xrir8fpe4d7ak.irc PRIVMSG #chan :[07:04:25] mike: Belike, for joy the emperor hath a son.")
+ (0 ":mike!~u@xrir8fpe4d7ak.irc PRIVMSG #chan :[07:04:27] joe: Protest their first of manhood.")
+ (0 ":joe!~u@xrir8fpe4d7ak.irc PRIVMSG #chan :[07:04:29] mike: As frozen water to a starved snake.")
+ (0 ":mike!~u@xrir8fpe4d7ak.irc PRIVMSG #chan :[07:04:34] joe: My mirth it much displeas'd, but pleas'd my woe.")
+ (0 ":joe!~u@xrir8fpe4d7ak.irc PRIVMSG #chan :[07:04:38] mike: Why, Marcus, no man should be mad but I.")
+ (0 ":mike!~u@xrir8fpe4d7ak.irc PRIVMSG #chan :[07:04:44] joe: Faith, I have heard too much, for your words and performances are no kin together.")
+ (0 ":***!znc@znc.in PRIVMSG #chan :Playback Complete.")
+ (0 ":irc.barnet.org NOTICE tester :[07:00:01] This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")
+ (0 ":irc.barnet.org 305 tester :You are no longer marked as being away"))
+
+((mode 6 "MODE #chan")
+ (0 ":irc.barnet.org 324 tester #chan +nt")
+ (0 ":irc.barnet.org 329 tester #chan 1619593200")
+ (0.25 ":joe!~u@svpn88yjcdj42.irc PRIVMSG #chan :mike: But, in defense, by mercy, 'tis most just.")
+ (0.25 ":mike!~u@xrir8fpe4d7ak.irc PRIVMSG #chan :joe: The Marshal of France, Monsieur la Far.")
+ (0.25 ":joe!~u@xrir8fpe4d7ak.irc PRIVMSG #chan :mike: And bide the penance of each three years' day.")
+ (0.25 ":mike!~u@xrir8fpe4d7ak.irc PRIVMSG #chan :joe: Madam, within; but never man so chang'd.")
+ (0.25 ":joe!~u@xrir8fpe4d7ak.irc PRIVMSG #chan :mike: As much in private, and I'll bid adieu."))
diff --git a/test/lisp/erc/resources/base/assoc/bouncer-history/foonet.eld b/test/lisp/erc/resources/base/assoc/bouncer-history/foonet.eld
new file mode 100644
index 00000000000..58df79e19fa
--- /dev/null
+++ b/test/lisp/erc/resources/base/assoc/bouncer-history/foonet.eld
@@ -0,0 +1,48 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS :foonet:changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.foonet.org 003 tester :This server was created Wed, 28 Apr 2021 07:00:00 UTC")
+ (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 3.2 "MODE tester +i")
+ ;; No mode answer ^
+ (0 ":irc.znc.in 306 tester :You have been marked as being away")
+ (0 ":tester!~u@nvfhxvqm92rm6.irc JOIN #chan")
+ (0 ":irc.foonet.org 353 tester = #chan :alice @bob tester")
+ (0 ":irc.foonet.org 366 tester #chan :End of /NAMES list.")
+ (0 ":***!znc@znc.in PRIVMSG #chan :Buffer Playback...")
+ (0 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #chan :[07:04:02] alice: Here come the lovers, full of joy and mirth.")
+ (0 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #chan :[07:04:07] bob: According to the fool's bolt, sir, and such dulcet diseases.")
+ (0 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #chan :[07:04:10] alice: And hang himself. I pray you, do my greeting.")
+ (0 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #chan :[07:04:18] bob: And you sat smiling at his cruel prey.")
+ (0 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #chan :[07:04:21] alice: Or never after look me in the face.")
+ (0 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #chan :[07:04:25] bob: If that may be, than all is well. Come, sit down, every mother's son, and rehearse your parts. Pyramus, you begin: when you have spoken your speech, enter into that brake; and so every one according to his cue.")
+ (0 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #chan :[07:04:30] alice: Where I espied the panther fast asleep.")
+ (0 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #chan :[07:04:32] bob: Alas! he is too young: yet he looks successfully.")
+ (0 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #chan :[07:04:37] alice: Here, at your lordship's service.")
+ (0 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #chan :[07:04:42] bob: By my troth, and in good earnest, and so God mend me, and by all pretty oaths that are not dangerous, if you break one jot of your promise or come one minute behind your hour, I will think you the most pathetical break-promise, and the most hollow lover, and the most unworthy of her you call Rosalind, that may be chosen out of the gross band of the unfaithful. Therefore, beware my censure, and keep your promise.")
+ (0 ":***!znc@znc.in PRIVMSG #chan :Playback Complete.")
+ (0 ":irc.foonet.org NOTICE tester :[07:00:32] This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")
+ (0 ":irc.foonet.org 305 tester :You are no longer marked as being away"))
+
+((mode 6 "MODE #chan")
+ (0 ":irc.foonet.org 324 tester #chan +nt")
+ (0 ":irc.foonet.org 329 tester #chan 1619593200")
+ (0.9 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #chan :bob: Grows, lives, and dies, in single blessedness.")
+ (0.25 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #chan :alice: For these two hours, Rosalind, I will leave thee.")
+ (0.25 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #chan :bob: By this hand, it will not kill a fly. But come, now I will be your Rosalind in a more coming-on disposition; and ask me what you will, I will grant it.")
+ (0.25 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #chan :alice: That I must love a loathed enemy.")
+ (0.25 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #chan :bob: As't please your lordship: I'll leave you."))
diff --git a/test/lisp/erc/resources/base/assoc/bumped/again.eld b/test/lisp/erc/resources/base/assoc/bumped/again.eld
new file mode 100644
index 00000000000..ab3c7b06214
--- /dev/null
+++ b/test/lisp/erc/resources/base/assoc/bumped/again.eld
@@ -0,0 +1,30 @@
+;; -*- mode: lisp-data; -*-
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0.0 ":irc.foonet.org 433 * tester :Nickname is reserved by a different account")
+ (0.0 ":irc.foonet.org FAIL NICK NICKNAME_RESERVED tester :Nickname is reserved by a different account"))
+
+((nick 3 "NICK tester`")
+ (0.1 ":irc.foonet.org 001 tester` :Welcome to the foonet IRC Network tester`")
+ (0.0 ":irc.foonet.org 002 tester` :Your host is irc.foonet.org, running version oragono-2.6.1-937b9b02368748e5")
+ (0.0 ":irc.foonet.org 003 tester` :This server was created Fri, 24 Sep 2021 01:38:36 UTC")
+ (0.0 ":irc.foonet.org 004 tester` irc.foonet.org oragono-2.6.1-937b9b02368748e5 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0.0 ":irc.foonet.org 005 tester` AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0.1 ":irc.foonet.org 005 tester` MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0.1 ":irc.foonet.org 005 tester` draft/CHATHISTORY=100 :are supported by this server")
+ (0.0 ":irc.foonet.org 251 tester` :There are 0 users and 3 invisible on 1 server(s)")
+ (0.0 ":irc.foonet.org 252 tester` 0 :IRC Operators online")
+ (0.0 ":irc.foonet.org 253 tester` 0 :unregistered connections")
+ (0.0 ":irc.foonet.org 254 tester` 1 :channels formed")
+ (0.0 ":irc.foonet.org 255 tester` :I have 3 clients and 0 servers")
+ (0.0 ":irc.foonet.org 265 tester` 3 3 :Current local users 3, max 3")
+ (0.2 ":irc.foonet.org 266 tester` 3 3 :Current global users 3, max 3")
+ (0.0 ":irc.foonet.org 422 tester` :MOTD File is missing"))
+
+((mode-user 3.2 "MODE tester` +i")
+ (0.0 ":irc.foonet.org 221 tester` +i")
+ (0.0 ":irc.foonet.org NOTICE tester` :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect."))
+
+((privmsg 42.6 "PRIVMSG NickServ :IDENTIFY tester changeme")
+ (0.01 ":tester`!~u@rpaau95je67ci.irc NICK tester")
+ (0.0 ":NickServ!NickServ@localhost NOTICE tester :You're now logged in as tester"))
diff --git a/test/lisp/erc/resources/base/assoc/bumped/foisted.eld b/test/lisp/erc/resources/base/assoc/bumped/foisted.eld
new file mode 100644
index 00000000000..5c36e58d9d3
--- /dev/null
+++ b/test/lisp/erc/resources/base/assoc/bumped/foisted.eld
@@ -0,0 +1,30 @@
+;; -*- mode: lisp-data; -*-
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0.0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0.0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.1-937b9b02368748e5")
+ (0.0 ":irc.foonet.org 003 tester :This server was created Fri, 24 Sep 2021 01:38:36 UTC")
+ (0.0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.1-937b9b02368748e5 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0.0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0.01 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0.01 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0.0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0.0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0.0 ":irc.foonet.org 253 tester 0 :unregistered connections")
+ (0.0 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0.0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers")
+ (0.0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0.0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0.0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 1.2 "MODE tester +i")
+ (0.0 ":irc.foonet.org 221 tester +i")
+ (0.0 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect."))
+
+((privmsg 17.21 "PRIVMSG bob :hi")
+ (0.02 ":bob!~u@ecnnh95wr67pv.net PRIVMSG tester :hola")
+ (0.01 ":bob!~u@ecnnh95wr67pv.net PRIVMSG tester :how r u?"))
+
+((quit 18.19 "QUIT :" quit)
+ (0.01 ":tester!~u@rpaau95je67ci.irc QUIT :Quit: " quit))
+((drop 1 DROP))
diff --git a/test/lisp/erc/resources/base/assoc/bumped/refoisted.eld b/test/lisp/erc/resources/base/assoc/bumped/refoisted.eld
new file mode 100644
index 00000000000..33e4168ac46
--- /dev/null
+++ b/test/lisp/erc/resources/base/assoc/bumped/refoisted.eld
@@ -0,0 +1,31 @@
+;; -*- mode: lisp-data; -*-
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0.1 ":irc.foonet.org 001 dummy :Welcome to the foonet IRC Network dummy")
+ (0.0 ":irc.foonet.org 002 dummy :Your host is irc.foonet.org, running version oragono-2.6.1-937b9b02368748e5")
+ (0.0 ":irc.foonet.org 003 dummy :This server was created Fri, 24 Sep 2021 01:38:36 UTC")
+ (0.0 ":irc.foonet.org 004 dummy irc.foonet.org oragono-2.6.1-937b9b02368748e5 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0.0 ":irc.foonet.org 005 dummy AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0.1 ":irc.foonet.org 005 dummy MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0.1 ":irc.foonet.org 005 dummy draft/CHATHISTORY=100 :are supported by this server")
+ (0.0 ":irc.foonet.org 251 dummy :There are 0 users and 3 invisible on 1 server(s)")
+ (0.0 ":irc.foonet.org 252 dummy 0 :IRC Operators online")
+ (0.0 ":irc.foonet.org 253 dummy 0 :unregistered connections")
+ (0.0 ":irc.foonet.org 254 dummy 1 :channels formed")
+ (0.0 ":irc.foonet.org 255 dummy :I have 3 clients and 0 servers")
+ (0.0 ":irc.foonet.org 265 dummy 3 3 :Current local users 3, max 3")
+ (0.2 ":irc.foonet.org 266 dummy 3 3 :Current global users 3, max 3")
+ ;; Could arrive anytime around this point
+ (0.0 ":tester!~u@rpaau95je67ci.irc NICK :dummy")
+ (0.0 ":irc.foonet.org 422 dummy :MOTD File is missing")
+ ;; Playback
+ (0.01 ":bob!~u@ecnnh95wr67pv.net PRIVMSG dummy :back?")
+ )
+
+((mode-user 1.2 "MODE dummy +i")
+ (0.0 ":irc.foonet.org 221 dummy +i")
+ (0.0 ":irc.foonet.org NOTICE dummy :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect."))
+
+((renick 42.6 "NICK tester")
+ (0.01 ":dummy!~u@rpaau95je67ci.irc NICK tester")
+ (0.0 ":NickServ!NickServ@localhost NOTICE dummy :You're now logged in as tester"))
diff --git a/test/lisp/erc/resources/base/assoc/bumped/renicked.eld b/test/lisp/erc/resources/base/assoc/bumped/renicked.eld
new file mode 100644
index 00000000000..4e96fd73045
--- /dev/null
+++ b/test/lisp/erc/resources/base/assoc/bumped/renicked.eld
@@ -0,0 +1,30 @@
+;; -*- mode: lisp-data; -*-
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0.0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0.0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.1-937b9b02368748e5")
+ (0.0 ":irc.foonet.org 003 tester :This server was created Fri, 24 Sep 2021 01:38:36 UTC")
+ (0.0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.1-937b9b02368748e5 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0.0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0.01 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0.01 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0.0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0.0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0.0 ":irc.foonet.org 253 tester 0 :unregistered connections")
+ (0.0 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0.0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers")
+ (0.0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0.0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0.0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 12 "MODE tester +i")
+ (0.0 ":irc.foonet.org 221 tester +i")
+ (0.0 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect."))
+
+((privmsg 17.21 "PRIVMSG NickServ :REGISTER changeme")
+ (0.02 ":NickServ!NickServ@localhost NOTICE tester :Account created")
+ (0.01 ":NickServ!NickServ@localhost NOTICE tester :You're now logged in as tester"))
+
+((quit 18.19 "QUIT :" quit)
+ (0.01 ":tester!~u@rpaau95je67ci.irc QUIT :Quit: " quit))
+((drop 1 DROP))
diff --git a/test/lisp/erc/resources/base/assoc/multi-net/barnet.eld b/test/lisp/erc/resources/base/assoc/multi-net/barnet.eld
new file mode 100644
index 00000000000..c62a22a11c7
--- /dev/null
+++ b/test/lisp/erc/resources/base/assoc/multi-net/barnet.eld
@@ -0,0 +1,42 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS :changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.barnet.org 001 tester :Welcome to the barnet IRC Network tester")
+ (0 ":irc.barnet.org 002 tester :Your host is irc.barnet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.barnet.org 003 tester :This server was created Tue, 04 May 2021 05:06:19 UTC")
+ (0 ":irc.barnet.org 004 tester irc.barnet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.barnet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.barnet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=barnet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.barnet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.barnet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.barnet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.barnet.org 253 tester 0 :unregistered connections")
+ (0 ":irc.barnet.org 254 tester 1 :channels formed")
+ (0 ":irc.barnet.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.barnet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.barnet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.barnet.org 422 tester :MOTD File is missing"))
+
+((mode-user 8 "MODE tester +i")
+ (0 ":irc.barnet.org 221 tester +i")
+ (0 ":irc.barnet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect."))
+
+((join 2 "JOIN #chan")
+ (0 ":tester!~u@jnu48g2wrycbw.irc JOIN #chan")
+ (0 ":irc.barnet.org 353 tester = #chan :@mike joe tester")
+ (0 ":irc.barnet.org 366 tester #chan :End of NAMES list"))
+
+((mode 2 "MODE #chan")
+ (0 ":irc.barnet.org 324 tester #chan +nt")
+ (0 ":irc.barnet.org 329 tester #chan 1620104779")
+ (0.1 ":mike!~u@kd7gmjbnbkn8c.irc PRIVMSG #chan :tester, welcome!")
+ (0.1 ":joe!~u@kd7gmjbnbkn8c.irc PRIVMSG #chan :tester, welcome!")
+ (0.1 ":mike!~u@kd7gmjbnbkn8c.irc PRIVMSG #chan :joe: Whipp'd first, sir, and hang'd after.")
+ (0.1 ":joe!~u@kd7gmjbnbkn8c.irc PRIVMSG #chan :mike: We have yet many among us can gripe as hard as Cassibelan; I do not say I am one, but I have a hand. Why tribute ? why should we pay tribute ? If C sar can hide the sun from us with a blanket, or put the moon in his pocket, we will pay him tribute for light; else, sir, no more tribute, pray you now.")
+ (0.1 ":mike!~u@kd7gmjbnbkn8c.irc PRIVMSG #chan :joe: Double and treble admonition, and still forfeit in the same kind ? This would make mercy swear, and play the tyrant.")
+ (0.1 ":joe!~u@kd7gmjbnbkn8c.irc PRIVMSG #chan :mike: And secretly to greet the empress' friends.")
+ (0.1 ":mike!~u@kd7gmjbnbkn8c.irc PRIVMSG #chan :joe: You have not been inquired after: I have sat here all day.")
+ (0.1 ":joe!~u@kd7gmjbnbkn8c.irc PRIVMSG #chan :mike: That same Berowne I'll torture ere I go.")
+ (0.1 ":mike!~u@kd7gmjbnbkn8c.irc PRIVMSG #chan :joe: For mine own part,no offence to the general, nor any man of quality,I hope to be saved.")
+ (0.1 ":joe!~u@kd7gmjbnbkn8c.irc PRIVMSG #chan :mike: Mehercle! if their sons be ingenuous, they shall want no instruction; if their daughters be capable, I will put it to them. But, vir sapit qui pauca loquitur. A soul feminine saluteth us."))
diff --git a/test/lisp/erc/resources/base/assoc/multi-net/foonet.eld b/test/lisp/erc/resources/base/assoc/multi-net/foonet.eld
new file mode 100644
index 00000000000..f30b7deca11
--- /dev/null
+++ b/test/lisp/erc/resources/base/assoc/multi-net/foonet.eld
@@ -0,0 +1,45 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS :changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.foonet.org 003 tester :This server was created Tue, 04 May 2021 05:06:18 UTC")
+ (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.foonet.org 253 tester 0 :unregistered connections")
+ (0 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 8 "MODE tester +i")
+ (0 ":irc.foonet.org 221 tester +i")
+ (0 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect."))
+
+((join 2 "JOIN #chan")
+ (0 ":tester!~u@9g6b728983yd2.irc JOIN #chan")
+ (0 ":irc.foonet.org 353 tester = #chan :alice tester @bob")
+ (0 ":irc.foonet.org 366 tester #chan :End of NAMES list"))
+
+((mode 2 "MODE #chan")
+ (0 ":irc.foonet.org 324 tester #chan +nt")
+ (0 ":irc.foonet.org 329 tester #chan 1620104779")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :tester, welcome!")
+ (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :tester, welcome!")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: But, as it seems, did violence on herself.")
+ (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :bob: Well, this is the forest of Arden.")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: Signior Iachimo will not from it. Pray, let us follow 'em.")
+ (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :bob: Our queen and all her elves come here anon.")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: The ground is bloody; search about the churchyard.")
+ (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :bob: You have discharged this honestly: keep it to yourself. Many likelihoods informed me of this before, which hung so tottering in the balance that I could neither believe nor misdoubt. Pray you, leave me: stall this in your bosom; and I thank you for your honest care. I will speak with you further anon.")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: Give me that mattock, and the wrenching iron.")
+ (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :bob: Stand you! You have land enough of your own; but he added to your having, gave you some ground.")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: Excellent workman! Thou canst not paint a man so bad as is thyself.")
+ (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :bob: And will you, being a man of your breeding, be married under a bush, like a beggar ? Get you to church, and have a good priest that can tell you what marriage is: this fellow will but join you together as they join wainscot; then one of you will prove a shrunk panel, and like green timber, warp, warp.")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: Live, and be prosperous; and farewell, good fellow."))
diff --git a/test/lisp/erc/resources/base/assoc/reconplay/again.eld b/test/lisp/erc/resources/base/assoc/reconplay/again.eld
new file mode 100644
index 00000000000..4210c07e41a
--- /dev/null
+++ b/test/lisp/erc/resources/base/assoc/reconplay/again.eld
@@ -0,0 +1,42 @@
+;; -*- mode: lisp-data; -*-
+((pass 4.0 "PASS :changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0.0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0.0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0.0 ":irc.foonet.org 003 tester :This server was created Wed, 16 Jun 2021 04:15:00 UTC")
+ (0.0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0.0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0.0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0.0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0.0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0.0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0.0 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0.0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers")
+ (0.0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0.0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0.0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 10 "MODE tester +i")
+ ;; No mode answer
+ (0.0 ":tester!~u@mw6kegwt77kwe.irc JOIN #chan")
+ (0.0 ":irc.foonet.org 353 tester = #chan :alice @bob tester")
+ (0.0 ":irc.foonet.org 366 tester #chan :End of /NAMES list.")
+ (0.0 ":***!znc@znc.in PRIVMSG #chan :Buffer Playback...")
+ (0.0 ":alice!~u@mw6kegwt77kwe.irc PRIVMSG #chan :[10:37:52] bob: Thou pout'st upon thy fortune and thy love.")
+ (0.0 ":bob!~u@mw6kegwt77kwe.irc PRIVMSG #chan :[10:37:56] alice: With these mortals on the ground.")
+ (0.0 ":***!znc@znc.in PRIVMSG #chan :Playback Complete."))
+
+((mode 10 "MODE #chan")
+ (0.0 ":irc.foonet.org 324 tester #chan +nt")
+ (0.0 ":irc.foonet.org 329 tester #chan 1623816901")
+ (0.1 ":bob!~u@mw6kegwt77kwe.irc PRIVMSG #chan :alice: My name, my good lord, is Parolles.")
+ (0.1 ":alice!~u@mw6kegwt77kwe.irc PRIVMSG #chan :bob: Wilt thou rest damned ? God help thee, shallow man! God make incision in thee! thou art raw."))
+
+((privmsg 3.0 "PRIVMSG *status :help")
+ (0.0 ":*status!znc@znc.in PRIVMSG tester :In the following list all occurrences of <#chan> support wildcards (* and ?) except ListNicks")
+ (0.0 ":*status!znc@znc.in PRIVMSG tester :\2Version\17: Print which version of ZNC this is")
+ (0.0 ":*status!znc@znc.in PRIVMSG tester :\2Shutdown [message]\17: Shut down ZNC completely")
+ (0.0 ":*status!znc@znc.in PRIVMSG tester :\2Restart [message]\17: Restart ZNC")
+ (0.1 ":bob!~u@mw6kegwt77kwe.irc PRIVMSG #chan :alice: In that word's death; no words can that woe sound.")
+ (0.1 ":alice!~u@mw6kegwt77kwe.irc PRIVMSG #chan :bob: Look, sir, here comes the lady towards my cell."))
diff --git a/test/lisp/erc/resources/base/assoc/reconplay/foonet.eld b/test/lisp/erc/resources/base/assoc/reconplay/foonet.eld
new file mode 100644
index 00000000000..f916fea2374
--- /dev/null
+++ b/test/lisp/erc/resources/base/assoc/reconplay/foonet.eld
@@ -0,0 +1,52 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS :changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0.0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0.0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0.0 ":irc.foonet.org 003 tester :This server was created Wed, 16 Jun 2021 04:15:00 UTC")
+ (0.0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0.0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0.0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0.0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0.0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0.0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0.0 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0.0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers")
+ (0.0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0.0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0.0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 5 "MODE tester +i")
+ ;; No mode answer
+ (0.0 ":irc.znc.in 306 tester :You have been marked as being away")
+ (0.0 ":tester!~u@mw6kegwt77kwe.irc JOIN #chan")
+ (0.0 ":irc.foonet.org 353 tester = #chan :alice @bob tester")
+ (0.0 ":irc.foonet.org 366 tester #chan :End of /NAMES list.")
+ (0.0 ":***!znc@znc.in PRIVMSG #chan :Buffer Playback...")
+ (0.0 ":alice!~u@mw6kegwt77kwe.irc PRIVMSG #chan :[10:35:50] bob: To Laced mon did my land extend.")
+ (0.0 ":bob!~u@mw6kegwt77kwe.irc PRIVMSG #chan :[10:35:55] alice: This is but a custom in your tongue; you bear a graver purpose, I hope.")
+ (0.0 ":alice!~u@mw6kegwt77kwe.irc PRIVMSG #chan :[10:37:16] bob: To imitate them; faults that are rich are fair.")
+ (0.0 ":bob!~u@mw6kegwt77kwe.irc PRIVMSG #chan :[10:37:18] alice: Our Romeo hath not been in bed to-night.")
+ (0.0 ":alice!~u@mw6kegwt77kwe.irc PRIVMSG #chan :[10:37:21] bob: But, in defense, by mercy, 'tis most just.")
+ (0.0 ":bob!~u@mw6kegwt77kwe.irc PRIVMSG #chan :[10:37:25] alice: Younger than she are happy mothers made.")
+ (0.0 ":***!znc@znc.in PRIVMSG #chan :Playback Complete.")
+ (0.0 ":irc.foonet.org 305 tester :You are no longer marked as being away"))
+
+((mode 3 "MODE #chan")
+ (1.0 ":irc.foonet.org 324 tester #chan +nt")
+ (0.0 ":irc.foonet.org 329 tester #chan 1623816901")
+ (0.1 ":alice!~u@mw6kegwt77kwe.irc PRIVMSG #chan :bob: At thy good heart's oppression.")
+ (0.1 ":bob!~u@mw6kegwt77kwe.irc PRIVMSG #chan :alice: But purgatory, torture, hell itself."))
+
+((privmsg 3 "PRIVMSG *status :help")
+ (0.0 ":*status!znc@znc.in PRIVMSG tester :In the following list all occurrences of <#chan> support wildcards (* and ?) except ListNicks")
+ (0.0 ":*status!znc@znc.in PRIVMSG tester :\2AddPort <[+]port> <ipv4|ipv6|all> <web|irc|all> [bindhost [uriprefix]]\17: Add another port for ZNC to listen on")
+ (0.0 ":*status!znc@znc.in PRIVMSG tester :\2DelPort <port> <ipv4|ipv6|all> [bindhost]\17: Remove a port from ZNC")
+ (0.0 ":*status!znc@znc.in PRIVMSG tester :\2Rehash\17: Reload global settings, modules, and listeners from znc.conf")
+ (0.1 ":alice!~u@mw6kegwt77kwe.irc PRIVMSG #chan :bob: And at my suit, sweet, pardon what is past.")
+ (0.1 ":bob!~u@mw6kegwt77kwe.irc PRIVMSG #chan :alice: My lord, you give me most egregious indignity."))
+
+((quit 2 "QUIT :\2ERC\2"))
+
+((drop 0 DROP))
diff --git a/test/lisp/erc/resources/base/assoc/samenet/chester.eld b/test/lisp/erc/resources/base/assoc/samenet/chester.eld
new file mode 100644
index 00000000000..0132de677cb
--- /dev/null
+++ b/test/lisp/erc/resources/base/assoc/samenet/chester.eld
@@ -0,0 +1,40 @@
+;; -*- mode: lisp-data; -*-
+((pass 10 "PASS :changeme"))
+((nick 1 "NICK chester"))
+((user 1 "USER user 0 * :chester")
+ (0 ":irc.foonet.org 001 chester :Welcome to the foonet IRC Network chester")
+ (0 ":irc.foonet.org 002 chester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.foonet.org 003 chester :This server was created Sun, 13 Jun 2021 05:45:20 UTC")
+ (0 ":irc.foonet.org 004 chester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.foonet.org 005 chester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.foonet.org 005 chester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.foonet.org 005 chester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.foonet.org 251 chester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.foonet.org 252 chester 0 :IRC Operators online")
+ (0 ":irc.foonet.org 253 chester 1 :unregistered connections")
+ (0 ":irc.foonet.org 254 chester 1 :channels formed")
+ (0 ":irc.foonet.org 255 chester :I have 3 clients and 0 servers")
+ (0 ":irc.foonet.org 265 chester 3 4 :Current local users 3, max 4")
+ (0 ":irc.foonet.org 266 chester 3 4 :Current global users 3, max 4")
+ (0 ":irc.foonet.org 422 chester :MOTD File is missing"))
+
+((mode-user 12 "MODE chester +i")
+ (0 ":irc.foonet.org 221 chester +i")
+ (0 ":chester!~u@yuvqisyu7m7qs.irc JOIN #chan")
+ (0 ":irc.foonet.org 353 chester = #chan :tester chester @alice bob")
+ (0 ":irc.foonet.org 366 chester #chan :End of NAMES list")
+ (0 ":irc.foonet.org NOTICE chester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect."))
+
+((mode 10 "MODE #chan")
+ (0.0 ":irc.foonet.org 324 chester #chan +nt")
+ (0.0 ":irc.foonet.org 329 chester #chan 1623563121")
+ (0.0 ":alice!~u@wyb9b355rgzi8.irc PRIVMSG #chan :chester, welcome!")
+ (0.0 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :chester, welcome!")
+ (0.1 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :alice: Dispatch, I say, and find the forester.")
+ (0.0 ":tester!~u@yuvqisyu7m7qs.irc QUIT :Quit: " quit)
+ (0.5 ":tester!~u@yuvqisyu7m7qs.irc JOIN #chan")
+ (0.1 ":alice!~u@wyb9b355rgzi8.irc PRIVMSG #chan :tester, welcome again!")
+ (0.1 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :tester, welcome again!"))
+
+((quit 20 "QUIT :" quit)
+ (0.0 ":chester!~u@yuvqisyu7m7qs.irc QUIT :Quit: " quit))
diff --git a/test/lisp/erc/resources/base/assoc/samenet/tester.eld b/test/lisp/erc/resources/base/assoc/samenet/tester.eld
new file mode 100644
index 00000000000..995fab00f7d
--- /dev/null
+++ b/test/lisp/erc/resources/base/assoc/samenet/tester.eld
@@ -0,0 +1,42 @@
+;; -*- mode: lisp-data; -*-
+((pass 10 "PASS :changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.foonet.org 003 tester :This server was created Sun, 13 Jun 2021 05:45:20 UTC")
+ (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.foonet.org 251 tester :There are 0 users and 4 invisible on 1 server(s)")
+ (0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.foonet.org 253 tester 0 :unregistered connections")
+ (0 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0 ":irc.foonet.org 255 tester :I have 4 clients and 0 servers")
+ (0 ":irc.foonet.org 265 tester 4 4 :Current local users 4, max 4")
+ (0 ":irc.foonet.org 266 tester 4 4 :Current global users 4, max 4")
+ (0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 12 "MODE tester +i")
+ (0 ":irc.foonet.org 221 tester +i")
+ (0 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect."))
+
+((join 15 "JOIN #chan")
+ (0 ":tester!~u@yuvqisyu7m7qs.irc JOIN #chan")
+ (0 ":irc.foonet.org 353 tester = #chan :tester @alice bob")
+ (0 ":irc.foonet.org 366 tester #chan :End of NAMES list"))
+
+((mode 10 "MODE #chan")
+ (0.0 ":irc.foonet.org 324 tester #chan +nt")
+ (0.0 ":irc.foonet.org 329 tester #chan 1623563121")
+ (0.0 ":alice!~u@wyb9b355rgzi8.irc PRIVMSG #chan :tester, welcome!")
+ (0.0 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :tester, welcome!")
+ (0.0 ":chester!~u@yuvqisyu7m7qs.irc JOIN #chan")
+ (0.1 ":alice!~u@wyb9b355rgzi8.irc PRIVMSG #chan :chester, welcome!")
+ (0.0 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :chester, welcome!")
+ (0.1 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :alice: Dispatch, I say, and find the forester."))
+
+((quit 4 "QUIT "))
+
+((drop 0 DROP))
diff --git a/test/lisp/erc/resources/base/assoc/samenet/tester2.eld b/test/lisp/erc/resources/base/assoc/samenet/tester2.eld
new file mode 100644
index 00000000000..33a05fe2611
--- /dev/null
+++ b/test/lisp/erc/resources/base/assoc/samenet/tester2.eld
@@ -0,0 +1,39 @@
+;; -*- mode: lisp-data; -*-
+((pass 10 "PASS :changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.foonet.org 003 tester :This server was created Sun, 13 Jun 2021 05:45:20 UTC")
+ (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.foonet.org 251 tester :There are 0 users and 4 invisible on 1 server(s)")
+ (0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.foonet.org 253 tester 0 :unregistered connections")
+ (0 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0 ":irc.foonet.org 255 tester :I have 4 clients and 0 servers")
+ (0 ":irc.foonet.org 265 tester 4 4 :Current local users 4, max 4")
+ (0 ":irc.foonet.org 266 tester 4 4 :Current global users 4, max 4")
+ (0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 4.2 "MODE tester +i")
+ (0 ":irc.foonet.org 221 tester +i")
+ (0 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")
+ (0 ":tester!~u@yuvqisyu7m7qs.irc JOIN #chan")
+ (0 ":irc.foonet.org 353 tester = #chan :tester @alice bob chester")
+ (0 ":irc.foonet.org 366 tester #chan :End of NAMES list"))
+
+((~useless-join 10 "JOIN #chan"))
+
+((mode 10 "MODE #chan")
+ (0.0 ":irc.foonet.org 324 tester #chan +nt")
+ (0.0 ":irc.foonet.org 329 tester #chan 1623563121")
+ (0.0 ":alice!~u@wyb9b355rgzi8.irc PRIVMSG #chan :tester, welcome again!")
+ (0.0 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :tester, welcome again!"))
+
+((quit 4 "QUIT :" quit)
+ (0 ":tester!~u@yuvqisyu7m7qs.irc QUIT :Quit: " quit))
+
+((linger 5 LINGER))
diff --git a/test/lisp/erc/resources/base/auth-source/foonet.eld b/test/lisp/erc/resources/base/auth-source/foonet.eld
new file mode 100644
index 00000000000..1fe772c7e23
--- /dev/null
+++ b/test/lisp/erc/resources/base/auth-source/foonet.eld
@@ -0,0 +1,23 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS :changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.foonet.org 003 tester :This server was created Tue, 04 May 2021 05:06:18 UTC")
+ (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=FooNet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.foonet.org 253 tester 0 :unregistered connections")
+ (0 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 1.2 "MODE tester +i")
+ (0 ":irc.foonet.org 221 tester +i")
+ (0 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect."))
diff --git a/test/lisp/erc/resources/base/auth-source/nopass.eld b/test/lisp/erc/resources/base/auth-source/nopass.eld
new file mode 100644
index 00000000000..3fdb4ecf7bc
--- /dev/null
+++ b/test/lisp/erc/resources/base/auth-source/nopass.eld
@@ -0,0 +1,22 @@
+;; -*- mode: lisp-data; -*-
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.foonet.org 003 tester :This server was created Tue, 04 May 2021 05:06:18 UTC")
+ (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=FooNet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.foonet.org 253 tester 0 :unregistered connections")
+ (0 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 1.2 "MODE tester +i")
+ (0 ":irc.foonet.org 221 tester +i")
+ (0 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect."))
diff --git a/test/lisp/erc/resources/base/channel-buffer-revival/foonet.eld b/test/lisp/erc/resources/base/channel-buffer-revival/foonet.eld
new file mode 100644
index 00000000000..b09692327c7
--- /dev/null
+++ b/test/lisp/erc/resources/base/channel-buffer-revival/foonet.eld
@@ -0,0 +1,45 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS :changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.foonet.org 003 tester :This server was created Tue, 04 May 2021 05:06:18 UTC")
+ (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=FooNet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.foonet.org 253 tester 0 :unregistered connections")
+ (0 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 12 "MODE tester +i")
+ (0 ":irc.foonet.org 221 tester +i")
+ (0 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect."))
+
+((join 6 "JOIN #chan")
+ (0 ":tester!~u@9g6b728983yd2.irc JOIN #chan")
+ (0 ":irc.foonet.org 353 tester = #chan :alice tester @bob")
+ (0 ":irc.foonet.org 366 tester #chan :End of NAMES list"))
+
+((mode 8 "MODE #chan")
+ (0 ":irc.foonet.org 324 tester #chan +nt")
+ (0 ":irc.foonet.org 329 tester #chan 1620104779")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :tester, welcome!")
+ (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :tester, welcome!")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: But, as it seems, did violence on herself.")
+ (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :bob: Well, this is the forest of Arden.")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: Signior Iachimo will not from it. Pray, let us follow 'em.")
+ (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :bob: Our queen and all her elves come here anon.")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: The ground is bloody; search about the churchyard.")
+ (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :bob: You have discharged this honestly: keep it to yourself. Many likelihoods informed me of this before, which hung so tottering in the balance that I could neither believe nor misdoubt. Pray you, leave me: stall this in your bosom; and I thank you for your honest care. I will speak with you further anon.")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: Give me that mattock, and the wrenching iron.")
+ (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :bob: Stand you! You have land enough of your own; but he added to your having, gave you some ground.")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: Excellent workman! Thou canst not paint a man so bad as is thyself.")
+ (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :bob: And will you, being a man of your breeding, be married under a bush, like a beggar ? Get you to church, and have a good priest that can tell you what marriage is: this fellow will but join you together as they join wainscot; then one of you will prove a shrunk panel, and like green timber, warp, warp.")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: Live, and be prosperous; and farewell, good fellow."))
diff --git a/test/lisp/erc/resources/base/flood/soju.eld b/test/lisp/erc/resources/base/flood/soju.eld
new file mode 100644
index 00000000000..05266ca9411
--- /dev/null
+++ b/test/lisp/erc/resources/base/flood/soju.eld
@@ -0,0 +1,87 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS :changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0.13 ":soju.im 001 tester :Welcome to soju, tester")
+ (0.0 ":soju.im 002 tester :Your host is soju.im")
+ (0.0 ":soju.im 004 tester soju.im soju aiwroO OovaimnqpsrtklbeI")
+ (0.0 ":soju.im 005 tester CHATHISTORY=1000 CASEMAPPING=ascii NETWORK=Soju :are supported")
+ (0.0 ":soju.im 422 tester :No MOTD"))
+
+((mode 1 "MODE tester +i")
+ (0.0 ":tester!tester@10.0.2.100 JOIN #chan/foonet")
+ (0.25 ":soju.im 331 tester #chan/foonet :No topic is set")
+ (0.0 ":soju.im 353 tester = #chan/foonet :@bob/foonet alice/foonet tester")
+ (0.01 ":soju.im 366 tester #chan/foonet :End of /NAMES list")
+ (0.0 ":tester!tester@10.0.2.100 JOIN #chan/barnet")
+ (0.04 ":soju.im 331 tester #chan/barnet :No topic is set")
+ (0.0 ":soju.im 353 tester = #chan/barnet :tester @mike/barnet joe/barnet")
+ (0.01 ":soju.im 366 tester #chan/barnet :End of /NAMES list")
+ (0.01 ":bob/foonet PRIVMSG #chan/foonet :alice: Then this breaking of his has been but a try for his friends.")
+ (0.16 ":alice/foonet PRIVMSG #chan/foonet :bob: By my troth, I take my young lord to be a very melancholy man.")
+ (0.91 ":bob/foonet PRIVMSG #chan/foonet :alice: No, truly, for the truest poetry is the most feigning; and lovers are given to poetry, and what they swear in poetry may be said as lovers they do feign.")
+ (0.01 ":alice/foonet PRIVMSG #chan/foonet :bob: Sir, his wife some two months since fled from his house: her pretence is a pilgrimage to Saint Jaques le Grand; which holy undertaking with most austere sanctimony she accomplished; and, there residing, the tenderness of her nature became as a prey to her grief; in fine, made a groan of her last breath, and now she sings in heaven.")
+ (0.0 ":mike/barnet PRIVMSG #chan/barnet :joe: Who ? not the duke ? yes, your beggar of fifty, and his use was to put a ducat in her clack-dish; the duke had crotchets in him. He would be drunk too; that let me inform you.")
+ (0.01 ":joe/barnet PRIVMSG #chan/barnet :mike: Prove it before these varlets here, thou honourable man, prove it.")
+ (0.0 ":mike/barnet PRIVMSG #chan/barnet :joe: That my report is just and full of truth.")
+ (0.0 ":joe/barnet PRIVMSG #chan/barnet :mike: It is impossible they bear it out.")
+ ;; Expected, since we blindly send +i
+ (0.0 ":soju.im 501 tester :Cannot change user mode in multi-upstream mode"))
+
+((~mode-foonet 5 "MODE #chan/foonet")
+ (0.0 ":soju.im 324 tester #chan/foonet +nt")
+ (0.16 ":soju.im 329 tester #chan/foonet 1647158643")
+ ;; Start frantic pinging
+ (0.0 "PING :soju-msgid-1"))
+
+((~mode-barnet 5 "MODE #chan/barnet")
+ (0.0 ":soju.im 324 tester #chan/barnet +nt")
+ (0.0 ":soju.im 329 tester #chan/barnet 1647158643"))
+
+((pong-1 5 "PONG :soju-msgid-1")
+ (0.0 ":bob/foonet!~u@g56t7uz8xjj4e.irc PRIVMSG #chan/foonet :alice: The king's coming; I know by his trumpets. Sirrah, inquire further after me; I had talk of you last night: though you are a fool and a knave, you shall eat: go to, follow.")
+ (0.0 ":mike/barnet!~u@qsidzk5cytcai.irc PRIVMSG #chan/barnet :joe: Up: so. How is 't ? Feel you your legs ? You stand.")
+ (0.0 ":alice/foonet!~u@g56t7uz8xjj4e.irc PRIVMSG #chan/foonet :bob: Consider then we come but in despite.")
+ (0.1 "PING :soju-msgid-2"))
+
+((pong-2 2 "PONG :soju-msgid-2")
+ (0.1 ":joe/barnet!~u@qsidzk5cytcai.irc PRIVMSG #chan/barnet :mike: All hail, Macbeth! that shalt be king hereafter.")
+ (0.1 "PING :soju-msgid-3"))
+
+((pong-3 2 "PONG :soju-msgid-3")
+ (0.1 ":bob/foonet!~u@g56t7uz8xjj4e.irc PRIVMSG #chan/foonet :alice: And that at my bidding you could so stand up.")
+ (0.1 "PING :soju-msgid-4"))
+
+((pong-4 2 "PONG :soju-msgid-4")
+ (0.03 ":mike/barnet!~u@qsidzk5cytcai.irc PRIVMSG #chan/barnet :joe: Now he tells how she plucked him to my chamber. O! I see that nose of yours, but not the dog I shall throw it to.")
+ (0.1 "PING :soju-msgid-5"))
+
+((pong-5 2 "PONG :soju-msgid-5")
+ (0.1 ":alice/foonet!~u@g56t7uz8xjj4e.irc PRIVMSG #chan/foonet :bob: For policy sits above conscience.")
+ (0.1 "PING :soju-msgid-6"))
+
+((pong-6 2 "PONG :soju-msgid-6")
+ (0.0 ":joe/barnet!~u@qsidzk5cytcai.irc PRIVMSG #chan/barnet :mike: Take heed o' the foul fiend. Obey thy parents; keep thy word justly; swear not; commit not with man's sworn spouse; set not thy sweet heart on proud array. Tom's a-cold.")
+ (0.1 "PING :soju-msgid-7"))
+
+((pong-7 2 "PONG :soju-msgid-7")
+ (0.08 ":mike/barnet!~u@qsidzk5cytcai.irc PRIVMSG #chan/barnet :joe: To suffer with him. Good love, call him back.")
+ (0.1 "PING :soju-msgid-8"))
+
+((pong-9 2 "PONG :soju-msgid-8")
+ (0.1 ":bob/foonet!~u@g56t7uz8xjj4e.irc PRIVMSG #chan/foonet :alice: Be not obdurate, open thy deaf ears.")
+ (0.0 "PING :soju-msgid-9"))
+
+((pong-10 2 "PONG :soju-msgid-9")
+ (0.04 ":joe/barnet!~u@qsidzk5cytcai.irc PRIVMSG #chan/barnet :mike: To get good guard and go along with me.")
+ (0.1 "PING :soju-msgid-10"))
+
+((~privmsg 2 "PRIVMSG #chan/foonet :alice: hi")
+ (0.1 ":alice/foonet!~u@g56t7uz8xjj4e.irc PRIVMSG #chan/foonet :tester: Good, very good; it is so then: good, very good. Let it be concealed awhile."))
+
+((pong-11 2 "PONG :soju-msgid-10")
+ (0.1 ":alice/foonet!~u@g56t7uz8xjj4e.irc PRIVMSG #chan/foonet :bob: Some man or other must present Wall; and let him have some plaster, or some loam, or some rough-cast about him, to signify wall; and let him hold his fingers thus, and through that cranny shall Pyramus and Thisby whisper.")
+ (0.0 "PING :soju-msgid-11"))
+
+((pong-12 5 "PONG :soju-msgid-11")
+ (0.1 ":mike/barnet!~u@qsidzk5cytcai.irc PRIVMSG #chan/barnet :joe: That's he that was Othello; here I am."))
diff --git a/test/lisp/erc/resources/base/gapless-connect/barnet.eld b/test/lisp/erc/resources/base/gapless-connect/barnet.eld
new file mode 100644
index 00000000000..4e658802ef6
--- /dev/null
+++ b/test/lisp/erc/resources/base/gapless-connect/barnet.eld
@@ -0,0 +1,40 @@
+;; -*- mode: lisp-data; -*-
+((pass 10 "PASS :barnet:changeme"))
+((nick 10 "NICK tester"))
+((user 0.2 "USER user 0 * :tester")
+ (0 ":irc.barnet.org 001 tester :Welcome to the barnet IRC Network tester")
+ (0 ":irc.barnet.org 002 tester :Your host is irc.barnet.org, running version oragono-2.5.1-4860c5cad0179db1")
+ (0 ":irc.barnet.org 003 tester :This server was created Fri, 19 Mar 2021 10:23:19 UTC")
+ (0 ":irc.barnet.org 004 tester irc.barnet.org oragono-2.5.1-4860c5cad0179db1 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.barnet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m INVEX KICKLEN=390 MAXLIST=beI:60 :are supported by this server")
+ (0 ":irc.barnet.org 005 tester MAXTARGETS=4 MODES MONITOR=100 NETWORK=barnet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.barnet.org 251 tester :There are 0 users and 1 invisible on 1 server(s)")
+ (0 ":irc.barnet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.barnet.org 254 tester 0 :channels formed")
+ (0 ":irc.barnet.org 255 tester :I have 1 clients and 0 servers")
+ (0 ":irc.barnet.org 265 tester 1 1 :Current local users 1, max 1")
+ (0 ":irc.barnet.org 266 tester 1 1 :Current global users 1, max 1")
+ (0 ":irc.barnet.org 422 tester :MOTD File is missing"))
+
+((mode-user 10.2 "MODE tester +i")
+ ;; No mode answer
+ (0 ":irc.znc.in 306 tester :You have been marked as being away")
+ (0 ":tester!~u@8cgjyczyrjgby.irc JOIN #bar")
+ (0 ":irc.barnet.org 353 tester = #bar :@mike joe tester")
+ (0 ":irc.barnet.org 366 tester #bar :End of /NAMES list.")
+ (0 ":***!znc@znc.in PRIVMSG #bar :Buffer Playback...")
+ (0 ":joe!~u@8cgjyczyrjgby.irc PRIVMSG #bar :[10:23:28] tester, welcome!")
+ (0 ":mike!~u@8cgjyczyrjgby.irc PRIVMSG #bar :[10:23:28] tester, welcome!")
+ (0 ":joe!~u@8cgjyczyrjgby.irc PRIVMSG #bar :[10:24:49] mike: Bid me farewell, and let me hear thee going.")
+ (0 ":mike!~u@8cgjyczyrjgby.irc PRIVMSG #bar :[10:24:54] joe: By heaven, thy love is black as ebony.")
+ (0 ":***!znc@znc.in PRIVMSG #bar :Playback Complete.")
+ (0 ":irc.barnet.org NOTICE tester :[10:23:22] This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")
+ (0 ":irc.barnet.org 305 tester :You are no longer marked as being away"))
+
+((mode 20 "MODE #bar")
+ (0 ":irc.barnet.org 324 tester #bar +nt")
+ (0 ":irc.barnet.org 329 tester #bar 1616149403")
+ (0.1 ":mike!~u@8cgjyczyrjgby.irc PRIVMSG #bar :joe: To ask of whence you are: report it.")
+ (0.1 ":joe!~u@8cgjyczyrjgby.irc PRIVMSG #bar :mike: Friar, thou knowest not the duke so well as I do: he's a better woodman than thou takest him for.")
+ (0.1 ":mike!~u@8cgjyczyrjgby.irc PRIVMSG #bar :joe: Like the sequel, I. Signior Costard, adieu.")
+ (0.1 ":joe!~u@8cgjyczyrjgby.irc PRIVMSG #bar :mike: This is his second fit; he had one yesterday."))
diff --git a/test/lisp/erc/resources/base/gapless-connect/foonet.eld b/test/lisp/erc/resources/base/gapless-connect/foonet.eld
new file mode 100644
index 00000000000..4ac4a3e5968
--- /dev/null
+++ b/test/lisp/erc/resources/base/gapless-connect/foonet.eld
@@ -0,0 +1,41 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS :foonet:changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.foonet.org 003 tester :This server was created Sun, 25 Apr 2021 11:28:28 UTC")
+ (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 10.2 "MODE tester +i")
+ ;; No mode answer
+ (0 ":irc.znc.in 306 tester :You have been marked as being away")
+ (0 ":tester!~u@xrir8fpe4d7ak.irc JOIN #foo")
+ (0 ":irc.foonet.org 353 tester = #foo :joe @mike tester")
+ (0 ":irc.foonet.org 366 tester #foo :End of /NAMES list.")
+ (0 ":***!znc@znc.in PRIVMSG #foo :Buffer Playback...")
+ (0 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #foo :[07:02:41] bob: To-morrow is the joyful day, Audrey; to-morrow will we be married.")
+ (0 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #foo :[07:02:44] alice: Why dost thou call them knaves ? thou know'st them not.")
+ (0 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #foo :[07:03:05] bob: Now, by the faith of my love, I will: tell me where it is.")
+ (0 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #foo :[07:03:09] alice: Give me the letter; I will look on it.")
+ (0 ":***!znc@znc.in PRIVMSG #foo :Playback Complete.")
+ (0 ":irc.foonet.org NOTICE tester :[11:29:00] This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")
+ (0 ":irc.foonet.org 305 tester :You are no longer marked as being away"))
+
+((mode 8 "MODE #foo")
+ (0 ":irc.foonet.org 324 tester #foo +nt")
+ (0 ":irc.foonet.org 329 tester #foo 1619593200")
+ (0.1 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #foo :bob: By this hand, it will not kill a fly. But come, now I will be your Rosalind in a more coming-on disposition; and ask me what you will, I will grant it.")
+ (0.1 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #foo :alice: That I must love a loathed enemy.")
+ (0.1 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #foo :bob: His discretion, I am sure, cannot carry his valour, for the goose carries not the fox. It is well: leave it to his discretion, and let us listen to the moon.")
+ (0.1 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #foo :alice: As living here and you no use of him."))
diff --git a/test/lisp/erc/resources/base/gapless-connect/pass-stub.eld b/test/lisp/erc/resources/base/gapless-connect/pass-stub.eld
new file mode 100644
index 00000000000..0c8dfd19d00
--- /dev/null
+++ b/test/lisp/erc/resources/base/gapless-connect/pass-stub.eld
@@ -0,0 +1,4 @@
+;; -*- mode: lisp-data; -*-
+((pass 3 "PASS :" token ":changeme"))
+
+((fake 1 "FAKE no op"))
diff --git a/test/lisp/erc/resources/base/mask-target-routing/foonet.eld b/test/lisp/erc/resources/base/mask-target-routing/foonet.eld
new file mode 100644
index 00000000000..796d5566b65
--- /dev/null
+++ b/test/lisp/erc/resources/base/mask-target-routing/foonet.eld
@@ -0,0 +1,45 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS :changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.foonet.org 003 tester :This server was created Mon, 31 May 2021 09:56:24 UTC")
+ (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.foonet.org 251 tester :There are 0 users and 4 invisible on 1 server(s)")
+ (0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.foonet.org 254 tester 2 :channels formed")
+ (0 ":irc.foonet.org 255 tester :I have 4 clients and 0 servers")
+ (0 ":irc.foonet.org 265 tester 4 4 :Current local users 4, max 4")
+ (0 ":irc.foonet.org 266 tester 4 4 :Current global users 4, max 4")
+ (0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 1.2 "MODE tester +i")
+ ;; No mode answer
+ (0 ":irc.znc.in 306 tester :You have been marked as being away")
+ (0 ":tester!~u@gq7yjr7gsu7nn.irc JOIN #foo")
+ (0 ":irc.foonet.org 353 tester = #foo :alice @bob rando tester")
+ (0 ":irc.foonet.org 366 tester #foo :End of /NAMES list.")
+ (0 ":***!znc@znc.in PRIVMSG #foo :Buffer Playback...")
+ (0 ":alice!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :[10:00:02] bob: All that he is hath reference to your highness.")
+ (0 ":bob!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :[10:00:06] alice: Excellent workman! Thou canst not paint a man so bad as is thyself.")
+ (0 ":***!znc@znc.in PRIVMSG #foo :Playback Complete.")
+ (0 ":irc.foonet.org NOTICE tester :[09:56:57] This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")
+ (0 ":irc.foonet.org 305 tester :You are no longer marked as being away"))
+
+((mode 5 "MODE #foo")
+ (0 ":irc.foonet.org 324 tester #foo +nt")
+ (0 ":irc.foonet.org 329 tester #foo 1622454985")
+ ;; Invalid msg
+ (0.1 ":rando!~u@em2i467d4ejul.irc PRIVMSG :")
+ (0.1 ":alice!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :bob: Farewell, pretty lady: you must hold the credit of your father.")
+ (0.1 ":bob!~u@gq7yjr7gsu7nn.irc NOTICE $* :[Global notice] going down soon.")
+ (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #foo :bob: Well, this is the forest of Arden.")
+ (0.1 ":bob!~u@gq7yjr7gsu7nn.irc NOTICE $$* :[Global notice] this is a warning.")
+ (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #foo :bob: Be married under a bush, like a beggar ? Get you to church, and have a good priest that can tell you what marriage is: this fellow will but join you together as they join wainscot; then one of you will prove a shrunk panel, and like green timber, warp, warp.")
+ (0.1 ":bob!~u@gq7yjr7gsu7nn.irc PRIVMSG $* :[Global msg] second warning.")
+ (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #foo :bob: And will you, being a man of your breeding.")
+ (0.1 ":bob!~u@gq7yjr7gsu7nn.irc NOTICE #* :[Global notice] final warning."))
diff --git a/test/lisp/erc/resources/base/netid/bouncer/barnet-again.eld b/test/lisp/erc/resources/base/netid/bouncer/barnet-again.eld
new file mode 100644
index 00000000000..e2fe1430283
--- /dev/null
+++ b/test/lisp/erc/resources/base/netid/bouncer/barnet-again.eld
@@ -0,0 +1,50 @@
+;; -*- mode: lisp-data; -*-
+((pass 10 "PASS :barnet:changeme"))
+((nick 3 "NICK tester"))
+((user 3 "USER user 0 * :tester")
+ (0 ":irc.barnet.org 001 tester :Welcome to the barnet IRC Network tester")
+ (0 ":irc.barnet.org 002 tester :Your host is irc.barnet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.barnet.org 003 tester :This server was created Wed, 12 May 2021 07:41:08 UTC")
+ (0 ":irc.barnet.org 004 tester irc.barnet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.barnet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.barnet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=barnet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.barnet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.barnet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.barnet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.barnet.org 254 tester 1 :channels formed")
+ (0 ":irc.barnet.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.barnet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.barnet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.barnet.org 422 tester :MOTD File is missing"))
+
+((mode-user 10.2 "MODE tester +i")
+ ;; No mode answer ^
+
+ (0 ":tester!~u@xrir8fpe4d7ak.irc JOIN #chan")
+ (0 ":irc.barnet.org 353 tester = #chan :joe @mike tester")
+ (0 ":irc.barnet.org 366 tester #chan :End of /NAMES list.")
+ (0 ":***!znc@znc.in PRIVMSG #chan :Buffer Playback...")
+ (0 ":joe!~u@xrir8fpe4d7ak.irc PRIVMSG #chan :[07:04:25] mike: Belike, for joy the emperor hath a son.")
+ (0 ":mike!~u@xrir8fpe4d7ak.irc PRIVMSG #chan :[07:04:27] joe: Protest their first of manhood.")
+ (0 ":joe!~u@xrir8fpe4d7ak.irc PRIVMSG #chan :[07:04:29] mike: As frozen water to a starved snake.")
+ (0 ":mike!~u@xrir8fpe4d7ak.irc PRIVMSG #chan :[07:04:34] joe: My mirth it much displeas'd, but pleas'd my woe.")
+ (0 ":joe!~u@xrir8fpe4d7ak.irc PRIVMSG #chan :[07:04:38] mike: Why, Marcus, no man should be mad but I.")
+ (0 ":mike!~u@xrir8fpe4d7ak.irc PRIVMSG #chan :[07:04:44] joe: Faith, I have heard too much, for your words and performances are no kin together.")
+ (0 ":***!znc@znc.in PRIVMSG #chan :Playback Complete.")
+ (0 ":irc.barnet.org NOTICE tester :[07:00:01] This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")
+
+ (0 ":irc.znc.in 306 tester :You have been marked as being away")
+ (0 ":irc.barnet.org 305 tester :You are no longer marked as being away"))
+
+((~join 3 "JOIN #chan"))
+
+((mode 5 "MODE #chan")
+ (0 ":irc.barnet.org 324 tester #chan +nt")
+ (0 ":irc.barnet.org 329 tester #chan 1620805269")
+ (0.1 ":joe!~u@svpn88yjcdj42.irc PRIVMSG #chan :mike: But, in defense, by mercy, 'tis most just.")
+ (0.1 ":mike!~u@xrir8fpe4d7ak.irc PRIVMSG #chan :joe: The Marshal of France, Monsieur la Far.")
+ (0.1 ":joe!~u@xrir8fpe4d7ak.irc PRIVMSG #chan :mike: And bide the penance of each three years' day.")
+ (0.1 ":mike!~u@xrir8fpe4d7ak.irc PRIVMSG #chan :joe: Madam, within; but never man so chang'd.")
+ (0.1 ":joe!~u@xrir8fpe4d7ak.irc PRIVMSG #chan :mike: As much in private, and I'll bid adieu."))
+
+((linger 10 LINGER))
diff --git a/test/lisp/erc/resources/base/netid/bouncer/barnet-drop.eld b/test/lisp/erc/resources/base/netid/bouncer/barnet-drop.eld
new file mode 100644
index 00000000000..2c3d297b9cf
--- /dev/null
+++ b/test/lisp/erc/resources/base/netid/bouncer/barnet-drop.eld
@@ -0,0 +1,41 @@
+;; -*- mode: lisp-data; -*-
+((pass 10 "PASS :barnet:changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.barnet.org 001 tester :Welcome to the barnet IRC Network tester")
+ (0 ":irc.barnet.org 002 tester :Your host is irc.barnet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.barnet.org 003 tester :This server was created Wed, 12 May 2021 07:41:08 UTC")
+ (0 ":irc.barnet.org 004 tester irc.barnet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.barnet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.barnet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=barnet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.barnet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.barnet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.barnet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.barnet.org 254 tester 1 :channels formed")
+ (0 ":irc.barnet.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.barnet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.barnet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.barnet.org 422 tester :MOTD File is missing"))
+
+((mode-user 10.2 "MODE tester +i")
+ ;; No mode answer ^
+ (0 ":irc.znc.in 306 tester :You have been marked as being away")
+ (0 ":irc.barnet.org 305 tester :You are no longer marked as being away"))
+
+((join 1 "JOIN #chan")
+ (0 ":tester!~u@awyxgybtkx7uq.irc JOIN #chan")
+ (0 ":irc.barnet.org 353 tester = #chan :@joe mike tester")
+ (0 ":irc.barnet.org 366 tester #chan :End of NAMES list")
+ (0.1 ":joe!~u@awyxgybtkx7uq.irc PRIVMSG #chan :tester, welcome!")
+ (0 ":mike!~u@awyxgybtkx7uq.irc PRIVMSG #chan :tester, welcome!"))
+
+((mode 1 "MODE #chan")
+ (0 ":irc.barnet.org 324 tester #chan +nt")
+ (0 ":irc.barnet.org 329 tester #chan 1620805269")
+ (0.1 ":mike!~u@awyxgybtkx7uq.irc PRIVMSG #chan :joe: But you have outfaced them all.")
+ (0.1 ":joe!~u@awyxgybtkx7uq.irc PRIVMSG #chan :mike: Why, will shall break it; will, and nothing else.")
+ (0.1 ":mike!~u@awyxgybtkx7uq.irc PRIVMSG #chan :joe: Yes, a dozen; and as many to the vantage, as would store the world they played for.")
+ (0.05 ":joe!~u@awyxgybtkx7uq.irc PRIVMSG #chan :mike: As he regards his aged father's life.")
+ (0.05 ":mike!~u@awyxgybtkx7uq.irc PRIVMSG #chan :joe: It is a rupture that you may easily heal; and the cure of it not only saves your brother, but keeps you from dishonour in doing it."))
+
+((drop 0 DROP))
diff --git a/test/lisp/erc/resources/base/netid/bouncer/barnet.eld b/test/lisp/erc/resources/base/netid/bouncer/barnet.eld
new file mode 100644
index 00000000000..abfcc6ed481
--- /dev/null
+++ b/test/lisp/erc/resources/base/netid/bouncer/barnet.eld
@@ -0,0 +1,41 @@
+;; -*- mode: lisp-data; -*-
+((pass 3 "PASS :barnet:changeme"))
+((nick 3 "NICK tester"))
+((user 3 "USER user 0 * :tester")
+ (0 ":irc.barnet.org 001 tester :Welcome to the barnet IRC Network tester")
+ (0 ":irc.barnet.org 002 tester :Your host is irc.barnet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.barnet.org 003 tester :This server was created Wed, 12 May 2021 07:41:08 UTC")
+ (0 ":irc.barnet.org 004 tester irc.barnet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.barnet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.barnet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=barnet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.barnet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.barnet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.barnet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.barnet.org 254 tester 1 :channels formed")
+ (0 ":irc.barnet.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.barnet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.barnet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.barnet.org 422 tester :MOTD File is missing"))
+
+((mode-user 10.2 "MODE tester +i")
+ ;; No mode answer ^
+ (0 ":irc.znc.in 306 tester :You have been marked as being away")
+ (0 ":irc.barnet.org 305 tester :You are no longer marked as being away"))
+
+((join 1 "JOIN #chan")
+ (0 ":tester!~u@awyxgybtkx7uq.irc JOIN #chan")
+ (0 ":irc.barnet.org 353 tester = #chan :@joe mike tester")
+ (0 ":irc.barnet.org 366 tester #chan :End of NAMES list")
+ (0.1 ":joe!~u@awyxgybtkx7uq.irc PRIVMSG #chan :tester, welcome!")
+ (0 ":mike!~u@awyxgybtkx7uq.irc PRIVMSG #chan :tester, welcome!"))
+
+((mode 3 "MODE #chan")
+ (0 ":irc.barnet.org 324 tester #chan +nt")
+ (0 ":irc.barnet.org 329 tester #chan 1620805269")
+ (0.1 ":mike!~u@awyxgybtkx7uq.irc PRIVMSG #chan :joe: But you have outfaced them all.")
+ (0.1 ":joe!~u@awyxgybtkx7uq.irc PRIVMSG #chan :mike: Why, will shall break it; will, and nothing else.")
+ (0.1 ":mike!~u@awyxgybtkx7uq.irc PRIVMSG #chan :joe: Yes, a dozen; and as many to the vantage, as would store the world they played for.")
+ (0.05 ":joe!~u@awyxgybtkx7uq.irc PRIVMSG #chan :mike: As he regards his aged father's life.")
+ (0.05 ":mike!~u@awyxgybtkx7uq.irc PRIVMSG #chan :joe: It is a rupture that you may easily heal; and the cure of it not only saves your brother, but keeps you from dishonour in doing it."))
+
+((linger 1 LINGER))
diff --git a/test/lisp/erc/resources/base/netid/bouncer/foonet-again.eld b/test/lisp/erc/resources/base/netid/bouncer/foonet-again.eld
new file mode 100644
index 00000000000..bf8712305a4
--- /dev/null
+++ b/test/lisp/erc/resources/base/netid/bouncer/foonet-again.eld
@@ -0,0 +1,50 @@
+;; -*- mode: lisp-data; -*-
+((pass 10 "PASS :foonet:changeme"))
+((nick 3 "NICK tester"))
+((user 3 "USER user 0 * :tester")
+ (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.foonet.org 003 tester :This server was created Wed, 12 May 2021 07:41:09 UTC")
+ (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 10.2 "MODE tester +i")
+ ;; No mode answer ^
+ (0 ":tester!~u@nvfhxvqm92rm6.irc JOIN #chan")
+ (0 ":irc.foonet.org 353 tester = #chan :alice @bob tester")
+ (0 ":irc.foonet.org 366 tester #chan :End of /NAMES list.")
+ (0 ":***!znc@znc.in PRIVMSG #chan :Buffer Playback...")
+ (0 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #chan :[07:04:02] alice: Here come the lovers, full of joy and mirth.")
+ (0 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #chan :[07:04:07] bob: According to the fool's bolt, sir, and such dulcet diseases.")
+ (0 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #chan :[07:04:10] alice: And hang himself. I pray you, do my greeting.")
+ (0 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #chan :[07:04:18] bob: And you sat smiling at his cruel prey.")
+ (0 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #chan :[07:04:21] alice: Or never after look me in the face.")
+ (0 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #chan :[07:04:25] bob: If that may be, than all is well. Come, sit down, every mother's son, and rehearse your parts. Pyramus, you begin: when you have spoken your speech, enter into that brake; and so every one according to his cue.")
+ (0 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #chan :[07:04:30] alice: Where I espied the panther fast asleep.")
+ (0 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #chan :[07:04:32] bob: Alas! he is too young: yet he looks successfully.")
+ (0 ":***!znc@znc.in PRIVMSG #chan :Playback Complete.")
+
+ (0 ":irc.foonet.org NOTICE tester :[07:00:32] This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")
+ (0 ":irc.foonet.org 305 tester :You are no longer marked as being away"))
+
+((~join 3 "JOIN #chan"))
+
+((mode 8 "MODE #chan")
+ (0 ":irc.foonet.org 324 tester #chan +nt")
+ (0 ":irc.foonet.org 329 tester #chan 1620805271")
+ (0.1 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #chan :bob: Grows, lives, and dies, in single blessedness.")
+ (0.1 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #chan :alice: For these two hours, Rosalind, I will leave thee.")
+ (0.1 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #chan :bob: By this hand, it will not kill a fly. But come, now I will be your Rosalind in a more coming-on disposition; and ask me what you will, I will grant it.")
+ (0.1 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #chan :alice: That I must love a loathed enemy.")
+ (0.1 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #chan :bob: As't please your lordship: I'll leave you."))
+
+((linger 10 LINGER))
diff --git a/test/lisp/erc/resources/base/netid/bouncer/foonet-drop.eld b/test/lisp/erc/resources/base/netid/bouncer/foonet-drop.eld
new file mode 100644
index 00000000000..b99621cc311
--- /dev/null
+++ b/test/lisp/erc/resources/base/netid/bouncer/foonet-drop.eld
@@ -0,0 +1,46 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS :foonet:changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.foonet.org 003 tester :This server was created Wed, 12 May 2021 07:41:09 UTC")
+ (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 10.2 "MODE tester +i")
+ ;; No mode answer ^
+ (0 ":irc.znc.in 306 tester :You have been marked as being away")
+ (0 ":irc.foonet.org 305 tester :You are no longer marked as being away"))
+
+((join 1 "JOIN #chan")
+ (0 ":tester!~u@ertp7idh9jtgi.irc JOIN #chan")
+ (0 ":irc.foonet.org 353 tester = #chan :@alice bob tester")
+ (0 ":irc.foonet.org 366 tester #chan :End of NAMES list")
+ (0.1 ":alice!~u@ertp7idh9jtgi.irc PRIVMSG #chan :tester, welcome!")
+ (0 ":bob!~u@ertp7idh9jtgi.irc PRIVMSG #chan :tester, welcome!"))
+
+((mode 1 "MODE #chan")
+ (0 ":irc.foonet.org 324 tester #chan +nt")
+ (0 ":irc.foonet.org 329 tester #chan 1620805271")
+ (0.1 ":alice!~u@ertp7idh9jtgi.irc PRIVMSG #chan :bob: He cannot be heard of. Out of doubt he is transported.")
+ (0.1 ":bob!~u@ertp7idh9jtgi.irc PRIVMSG #chan :alice: More evident than this; for this was stol'n.")
+ (0.1 ":alice!~u@ertp7idh9jtgi.irc PRIVMSG #chan :bob: Sell when you can; you are not for all markets.")
+ (0.1 ":bob!~u@ertp7idh9jtgi.irc PRIVMSG #chan :alice: There's the fool hangs on your back already.")
+ (0.1 ":alice!~u@ertp7idh9jtgi.irc PRIVMSG #chan :bob: Why, if you have a stomach to't, monsieur, if you think your mystery in stratagem can bring this instrument of honor again into its native quarter, be magnanimous in the enterprise and go on; I will grace the attempt for a worthy exploit: if you speed well in it, the duke shall both speak of it, and extend to you what further becomes his greatness, even to the utmost syllable of your worthiness.")
+ (0.1 ":bob!~u@ertp7idh9jtgi.irc PRIVMSG #chan :alice: For he hath still been tried a holy man.")
+ (0.1 ":alice!~u@ertp7idh9jtgi.irc PRIVMSG #chan :bob: To have the touches dearest priz'd.")
+ (0.1 ":bob!~u@ertp7idh9jtgi.irc PRIVMSG #chan :alice: And must advise the emperor for his good.")
+ (0.1 ":alice!~u@ertp7idh9jtgi.irc PRIVMSG #chan :bob: Orlando, my liege; the youngest son of Sir Rowland de Boys.")
+ (0.1 ":bob!~u@ertp7idh9jtgi.irc PRIVMSG #chan :alice: The ape is dead, and I must conjure him."))
+
+((drop 0 DROP))
diff --git a/test/lisp/erc/resources/base/netid/bouncer/foonet.eld b/test/lisp/erc/resources/base/netid/bouncer/foonet.eld
new file mode 100644
index 00000000000..b0964fb9537
--- /dev/null
+++ b/test/lisp/erc/resources/base/netid/bouncer/foonet.eld
@@ -0,0 +1,46 @@
+;; -*- mode: lisp-data; -*-
+((pass 3 "PASS :foonet:changeme"))
+((nick 3 "NICK tester"))
+((user 3 "USER user 0 * :tester")
+ (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.foonet.org 003 tester :This server was created Wed, 12 May 2021 07:41:09 UTC")
+ (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 4.2 "MODE tester +i")
+ ;; No mode answer ^
+ (0 ":irc.znc.in 306 tester :You have been marked as being away")
+ (0 ":irc.foonet.org 305 tester :You are no longer marked as being away"))
+
+((join 1 "JOIN #chan")
+ (0 ":tester!~u@ertp7idh9jtgi.irc JOIN #chan")
+ (0 ":irc.foonet.org 353 tester = #chan :@alice bob tester")
+ (0 ":irc.foonet.org 366 tester #chan :End of NAMES list")
+ (0.1 ":alice!~u@ertp7idh9jtgi.irc PRIVMSG #chan :tester, welcome!")
+ (0 ":bob!~u@ertp7idh9jtgi.irc PRIVMSG #chan :tester, welcome!"))
+
+((mode 3 "MODE #chan")
+ (0 ":irc.foonet.org 324 tester #chan +nt")
+ (0 ":irc.foonet.org 329 tester #chan 1620805271")
+ (0.1 ":alice!~u@ertp7idh9jtgi.irc PRIVMSG #chan :bob: He cannot be heard of. Out of doubt he is transported.")
+ (0.1 ":bob!~u@ertp7idh9jtgi.irc PRIVMSG #chan :alice: More evident than this; for this was stol'n.")
+ (0.1 ":alice!~u@ertp7idh9jtgi.irc PRIVMSG #chan :bob: Sell when you can; you are not for all markets.")
+ (0.1 ":bob!~u@ertp7idh9jtgi.irc PRIVMSG #chan :alice: There's the fool hangs on your back already.")
+ (0.1 ":alice!~u@ertp7idh9jtgi.irc PRIVMSG #chan :bob: Why, if you have a stomach to't, monsieur, if you think your mystery in stratagem can bring this instrument of honor again into its native quarter, be magnanimous in the enterprise and go on; I will grace the attempt for a worthy exploit: if you speed well in it, the duke shall both speak of it, and extend to you what further becomes his greatness, even to the utmost syllable of your worthiness.")
+ (0.1 ":bob!~u@ertp7idh9jtgi.irc PRIVMSG #chan :alice: For he hath still been tried a holy man.")
+ (0.1 ":alice!~u@ertp7idh9jtgi.irc PRIVMSG #chan :bob: To have the touches dearest priz'd.")
+ (0.1 ":bob!~u@ertp7idh9jtgi.irc PRIVMSG #chan :alice: And must advise the emperor for his good.")
+ (0.1 ":alice!~u@ertp7idh9jtgi.irc PRIVMSG #chan :bob: Orlando, my liege; the youngest son of Sir Rowland de Boys.")
+ (0.1 ":bob!~u@ertp7idh9jtgi.irc PRIVMSG #chan :alice: The ape is dead, and I must conjure him."))
+
+((linger 1 LINGER))
diff --git a/test/lisp/erc/resources/base/netid/bouncer/stub-again.eld b/test/lisp/erc/resources/base/netid/bouncer/stub-again.eld
new file mode 100644
index 00000000000..c666ee4fa0f
--- /dev/null
+++ b/test/lisp/erc/resources/base/netid/bouncer/stub-again.eld
@@ -0,0 +1,4 @@
+;; -*- mode: lisp-data; -*-
+((pass 10 "PASS :" token ":changeme"))
+
+((fake 1 "FAKE no op"))
diff --git a/test/lisp/erc/resources/base/netid/samenet/chester.eld b/test/lisp/erc/resources/base/netid/samenet/chester.eld
new file mode 100644
index 00000000000..7b4bfee9c9a
--- /dev/null
+++ b/test/lisp/erc/resources/base/netid/samenet/chester.eld
@@ -0,0 +1,48 @@
+;; -*- mode: lisp-data; -*-
+((pass 10 "PASS :changeme"))
+((nick 1 "NICK chester"))
+((user 1 "USER user 0 * :chester")
+ (0 ":irc.foonet.org 001 chester :Welcome to the foonet IRC Network chester")
+ (0 ":irc.foonet.org 002 chester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.foonet.org 003 chester :This server was created Sun, 13 Jun 2021 05:45:20 UTC")
+ (0 ":irc.foonet.org 004 chester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.foonet.org 005 chester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.foonet.org 005 chester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.foonet.org 005 chester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.foonet.org 251 chester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.foonet.org 252 chester 0 :IRC Operators online")
+ (0 ":irc.foonet.org 253 chester 1 :unregistered connections")
+ (0 ":irc.foonet.org 254 chester 1 :channels formed")
+ (0 ":irc.foonet.org 255 chester :I have 3 clients and 0 servers")
+ (0 ":irc.foonet.org 265 chester 3 4 :Current local users 3, max 4")
+ (0 ":irc.foonet.org 266 chester 3 4 :Current global users 3, max 4")
+ (0 ":irc.foonet.org 422 chester :MOTD File is missing"))
+
+((mode-user 10.2 "MODE chester +i")
+ (0 ":irc.foonet.org 221 chester +i")
+ (0 ":irc.foonet.org NOTICE chester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect."))
+
+((join 14 "JOIN #chan")
+ (0 ":chester!~u@yuvqisyu7m7qs.irc JOIN #chan")
+ (0 ":irc.foonet.org 353 chester = #chan :tester chester @alice bob")
+ (0 ":irc.foonet.org 366 chester #chan :End of NAMES list"))
+
+((mode 10 "MODE #chan")
+ (0.0 ":irc.foonet.org 324 chester #chan +nt")
+ (0.0 ":irc.foonet.org 329 chester #chan 1623563121")
+ (0.0 ":alice!~u@wyb9b355rgzi8.irc PRIVMSG #chan :chester, welcome!")
+ (0.0 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :chester, welcome!")
+ (0.1 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :alice: That ever eye with sight made heart lament.")
+ (0.1 ":alice!~u@wyb9b355rgzi8.irc PRIVMSG #chan :bob: The bitter past, more welcome is the sweet.")
+ (0.1 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :alice: Dispatch, I say, and find the forester.")
+ (0.1 ":tester!~u@yuvqisyu7m7qs.irc PRIVMSG #chan :chester: hi")
+ (0.1 ":alice!~u@wyb9b355rgzi8.irc PRIVMSG #chan :bob: This was lofty! Now name the rest of the players. This is Ercles' vein, a tyrant's vein; a lover is more condoling."))
+
+((privmsg 4 "PRIVMSG #chan :hi tester")
+ (0.1 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :alice: As the ox hath his bow, sir, the horse his curb, and the falcon her bells, so man hath his desires; and as pigeons bill, so wedlock would be nibbling.")
+ (0.1 ":alice!~u@wyb9b355rgzi8.irc PRIVMSG #chan :bob: Most friendship is feigning, most loving mere folly.")
+ (0.1 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :alice: To employ you towards this Roman. Come, our queen."))
+
+((quit 5 "QUIT :" quit)
+ (0.0 ":tester!~u@yuvqisyu7m7qs.irc QUIT :Quit: " quit)
+ (0.0 ":chester!~u@yuvqisyu7m7qs.irc QUIT :Quit: " quit))
diff --git a/test/lisp/erc/resources/base/netid/samenet/tester.eld b/test/lisp/erc/resources/base/netid/samenet/tester.eld
new file mode 100644
index 00000000000..f41b041db4b
--- /dev/null
+++ b/test/lisp/erc/resources/base/netid/samenet/tester.eld
@@ -0,0 +1,52 @@
+;; -*- mode: lisp-data; -*-
+((pass 10 "PASS :changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.foonet.org 003 tester :This server was created Sun, 13 Jun 2021 05:45:20 UTC")
+ (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.foonet.org 251 tester :There are 0 users and 4 invisible on 1 server(s)")
+ (0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.foonet.org 253 tester 0 :unregistered connections")
+ (0 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0 ":irc.foonet.org 255 tester :I have 4 clients and 0 servers")
+ (0 ":irc.foonet.org 265 tester 4 4 :Current local users 4, max 4")
+ (0 ":irc.foonet.org 266 tester 4 4 :Current global users 4, max 4")
+ (0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 10.2 "MODE tester +i")
+ (0 ":irc.foonet.org 221 tester +i")
+ (0 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect."))
+
+((join 15 "JOIN #chan")
+ (0 ":tester!~u@yuvqisyu7m7qs.irc JOIN #chan")
+ (0 ":irc.foonet.org 353 tester = #chan :tester @alice bob")
+ (0 ":irc.foonet.org 366 tester #chan :End of NAMES list"))
+
+((mode 10 "MODE #chan")
+ (0.0 ":irc.foonet.org 324 tester #chan +nt")
+ (0.0 ":irc.foonet.org 329 tester #chan 1623563121")
+ (0.0 ":alice!~u@wyb9b355rgzi8.irc PRIVMSG #chan :tester, welcome!")
+ (0.0 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :tester, welcome!")
+ (0.1 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :alice: Marry, that, I think, be young Petruchio.")
+ (0.4 ":alice!~u@wyb9b355rgzi8.irc PRIVMSG #chan :bob: You speak of him when he was less furnished than now he is with that which makes him both without and within.")
+ (0.2 ":chester!~u@yuvqisyu7m7qs.irc JOIN #chan")
+ (0.1 ":alice!~u@wyb9b355rgzi8.irc PRIVMSG #chan :chester, welcome!")
+ (0.1 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :chester, welcome!")
+ (0.1 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :alice: That ever eye with sight made heart lament.")
+ (0.1 ":alice!~u@wyb9b355rgzi8.irc PRIVMSG #chan :bob: The bitter past, more welcome is the sweet.")
+ (0.1 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :alice: Dispatch, I say, and find the forester."))
+
+((privmsg 3 "PRIVMSG #chan :chester: hi")
+ (0.1 ":alice!~u@wyb9b355rgzi8.irc PRIVMSG #chan :bob: This was lofty! Now name the rest of the players. This is Ercles' vein, a tyrant's vein; a lover is more condoling.")
+ (0.1 ":chester!~u@yuvqisyu7m7qs.irc PRIVMSG #chan :hi tester")
+ (0.1 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :alice: As the ox hath his bow, sir, the horse his curb, and the falcon her bells, so man hath his desires; and as pigeons bill, so wedlock would be nibbling.")
+ (0.1 ":alice!~u@wyb9b355rgzi8.irc PRIVMSG #chan :bob: Most friendship is feigning, most loving mere folly.")
+ (0.1 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :alice: To employ you towards this Roman. Come, our queen."))
+
+((quit 4 "QUIT :" quit)
+ (0 ":tester!~u@yuvqisyu7m7qs.irc QUIT :Quit: " quit))
diff --git a/test/lisp/erc/resources/base/reconnect/aborted-dupe.eld b/test/lisp/erc/resources/base/reconnect/aborted-dupe.eld
new file mode 100644
index 00000000000..8e299ec44c0
--- /dev/null
+++ b/test/lisp/erc/resources/base/reconnect/aborted-dupe.eld
@@ -0,0 +1,28 @@
+;; -*- mode: lisp-data; -*-
+((pass 3 "PASS :changeme"))
+((nick 1 "NICK tester"))
+
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.foonet.org 003 tester :This server was created Tue, 04 May 2021 05:06:18 UTC")
+ (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=FooNet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (-0.02 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (-0.02 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (-0.02 ":irc.foonet.org 253 tester 0 :unregistered connections")
+ (-0.02 ":irc.foonet.org 254 tester 1 :channels formed")
+ (-0.02 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers")
+ (-0.02 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3")
+ (-0.02 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
+ (-0.02 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((~mode-user 3.2 "MODE tester +i")
+ (-0.02 ":irc.foonet.org 221 tester +i")
+ (-0.02 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect."))
+
+((~join 10 "JOIN #chan"))
+((eof 5 EOF))
+((drop 0 DROP))
diff --git a/test/lisp/erc/resources/base/reconnect/aborted.eld b/test/lisp/erc/resources/base/reconnect/aborted.eld
new file mode 100644
index 00000000000..5c32070d85f
--- /dev/null
+++ b/test/lisp/erc/resources/base/reconnect/aborted.eld
@@ -0,0 +1,45 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS :changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.foonet.org 003 tester :This server was created Tue, 04 May 2021 05:06:18 UTC")
+ (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=FooNet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.foonet.org 253 tester 0 :unregistered connections")
+ (0 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 3.2 "MODE tester +i")
+ (0 ":irc.foonet.org 221 tester +i")
+ (0 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect."))
+
+((join 12 "JOIN #chan")
+ (0 ":tester!~u@9g6b728983yd2.irc JOIN #chan")
+ (0 ":irc.foonet.org 353 tester = #chan :alice tester @bob")
+ (0 ":irc.foonet.org 366 tester #chan :End of NAMES list"))
+
+((mode 10 "MODE #chan")
+ (0 ":irc.foonet.org 324 tester #chan +nt")
+ (0 ":irc.foonet.org 329 tester #chan 1620104779")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :tester, welcome!")
+ (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :tester, welcome!")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: But, as it seems, did violence on herself.")
+ (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :bob: Well, this is the forest of Arden.")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: Signior Iachimo will not from it. Pray, let us follow 'em.")
+ (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :bob: Our queen and all her elves come here anon.")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: The ground is bloody; search about the churchyard.")
+ (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :bob: You have discharged this honestly: keep it to yourself. Many likelihoods informed me of this before, which hung so tottering in the balance that I could neither believe nor misdoubt. Pray you, leave me: stall this in your bosom; and I thank you for your honest care. I will speak with you further anon.")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: Give me that mattock, and the wrenching iron.")
+ (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :bob: Stand you! You have land enough of your own; but he added to your having, gave you some ground.")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: Excellent workman! Thou canst not paint a man so bad as is thyself.")
+ (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :bob: And will you, being a man of your breeding, be married under a bush, like a beggar ? Get you to church, and have a good priest that can tell you what marriage is: this fellow will but join you together as they join wainscot; then one of you will prove a shrunk panel, and like green timber, warp, warp.")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: Live, and be prosperous; and farewell, good fellow."))
diff --git a/test/lisp/erc/resources/base/reconnect/options-again.eld b/test/lisp/erc/resources/base/reconnect/options-again.eld
new file mode 100644
index 00000000000..f1fcc439cc3
--- /dev/null
+++ b/test/lisp/erc/resources/base/reconnect/options-again.eld
@@ -0,0 +1,45 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS :changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.foonet.org 003 tester :This server was created Tue, 04 May 2021 05:06:18 UTC")
+ (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=FooNet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.foonet.org 253 tester 0 :unregistered connections")
+ (0 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 3.2 "MODE tester +i")
+ (0 ":irc.foonet.org 221 tester +i")
+ (0 ":irc.foonet.org NOTICE tester :This server is still in debug mode."))
+
+((~join-chan 12 "JOIN #chan")
+ (0 ":tester!~u@9g6b728983yd2.irc JOIN #chan")
+ (0 ":irc.foonet.org 353 tester = #chan :alice tester @bob")
+ (0 ":irc.foonet.org 366 tester #chan :End of NAMES list"))
+
+((~join-spam 12 "JOIN #spam")
+ (0 ":tester!~u@9g6b728983yd2.irc JOIN #spam")
+ (0 ":irc.foonet.org 353 tester = #spam :alice tester @bob")
+ (0 ":irc.foonet.org 366 tester #spam :End of NAMES list"))
+
+((~mode-chan 4 "MODE #chan")
+ (0 ":irc.foonet.org 324 tester #chan +nt")
+ (0 ":irc.foonet.org 329 tester #chan 1620104779")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: But, as it seems, did violence on herself.")
+ (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :bob: Well, this is the forest of Arden."))
+
+((mode-spam 4 "MODE #spam")
+ (0 ":irc.foonet.org 324 tester #spam +nt")
+ (0 ":irc.foonet.org 329 tester #spam 1620104779")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #spam :alice: Signior Iachimo will not from it. Pray, let us follow 'em.")
+ (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #spam :bob: Our queen and all her elves come here anon."))
diff --git a/test/lisp/erc/resources/base/reconnect/options.eld b/test/lisp/erc/resources/base/reconnect/options.eld
new file mode 100644
index 00000000000..3b305d85594
--- /dev/null
+++ b/test/lisp/erc/resources/base/reconnect/options.eld
@@ -0,0 +1,35 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS :changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.foonet.org 003 tester :This server was created Tue, 04 May 2021 05:06:18 UTC")
+ (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=FooNet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.foonet.org 253 tester 0 :unregistered connections")
+ (0 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 3.2 "MODE tester +i")
+ (0 ":irc.foonet.org 221 tester +i")
+ (0 ":irc.foonet.org NOTICE tester :This server is in debug mode.")
+
+ (0 ":tester!~u@9g6b728983yd2.irc JOIN #chan")
+ (0 ":irc.foonet.org 353 tester = #chan :alice tester @bob")
+ (0 ":irc.foonet.org 366 tester #chan :End of NAMES list"))
+
+((mode-chan 4 "MODE #chan")
+ (0 ":irc.foonet.org 324 tester #chan +nt")
+ (0 ":irc.foonet.org 329 tester #chan 1620104779")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :tester, welcome!")
+ (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :tester, welcome!"))
+
+((drop 0 DROP))
diff --git a/test/lisp/erc/resources/base/reconnect/timer-last.eld b/test/lisp/erc/resources/base/reconnect/timer-last.eld
new file mode 100644
index 00000000000..23849bc1bad
--- /dev/null
+++ b/test/lisp/erc/resources/base/reconnect/timer-last.eld
@@ -0,0 +1,6 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS :changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.znc.in 464 tester :Invalid Password"))
+((linger 1 LINGER))
diff --git a/test/lisp/erc/resources/base/reconnect/timer.eld b/test/lisp/erc/resources/base/reconnect/timer.eld
new file mode 100644
index 00000000000..95c6af8d880
--- /dev/null
+++ b/test/lisp/erc/resources/base/reconnect/timer.eld
@@ -0,0 +1,6 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS :changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.znc.in 464 tester :Invalid Password"))
+((drop 0 DROP))
diff --git a/test/lisp/erc/resources/base/renick/queries/bouncer-barnet.eld b/test/lisp/erc/resources/base/renick/queries/bouncer-barnet.eld
new file mode 100644
index 00000000000..0c8cdac0379
--- /dev/null
+++ b/test/lisp/erc/resources/base/renick/queries/bouncer-barnet.eld
@@ -0,0 +1,54 @@
+;; -*- mode: lisp-data; -*-
+((pass 3 "PASS :barnet:changeme"))
+((nick 3 "NICK tester"))
+((user 3 "USER user 0 * :tester")
+ (0 ":irc.barnet.org 001 tester :Welcome to the barnet IRC Network tester")
+ (0 ":irc.barnet.org 002 tester :Your host is irc.barnet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.barnet.org 003 tester :This server was created Tue, 01 Jun 2021 07:49:23 UTC")
+ (0 ":irc.barnet.org 004 tester irc.barnet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.barnet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.barnet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=barnet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.barnet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.barnet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.barnet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.barnet.org 254 tester 1 :channels formed")
+ (0 ":irc.barnet.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.barnet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.barnet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.barnet.org 422 tester :MOTD File is missing"))
+
+((mode-user 3.2 "MODE tester +i")
+ ;; No mode answer
+ (0 ":irc.znc.in 306 tester :You have been marked as being away")
+ (0 ":tester!~u@286u8jcpis84e.irc JOIN #chan")
+ (0 ":irc.barnet.org 353 tester = #chan :@joe mike rando tester")
+ (0 ":irc.barnet.org 366 tester #chan :End of /NAMES list.")
+ (0 ":***!znc@znc.in PRIVMSG #chan :Buffer Playback...")
+ (0 ":joe!~u@286u8jcpis84e.irc PRIVMSG #chan :[09:19:19] mike: Chi non te vede, non te pretia.")
+ (0 ":mike!~u@286u8jcpis84e.irc PRIVMSG #chan :[09:19:28] joe: The valiant heart's not whipt out of his trade.")
+ (0 ":***!znc@znc.in PRIVMSG #chan :Playback Complete.")
+ (0 ":rando!~u@95i756tt32ym8.irc PRIVMSG tester :[09:18:20] Why'd you pull that scene at the arcade?")
+ (0 ":rando!~u@95i756tt32ym8.irc PRIVMSG tester :[09:18:32] I had to mess up this rentacop came after me with nunchucks.")
+ (0 ":irc.barnet.org NOTICE tester :[09:13:24] This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")
+ (0 ":irc.barnet.org 305 tester :You are no longer marked as being away"))
+
+((mode 5 "MODE #chan")
+ (0 ":irc.barnet.org 324 tester #chan +nt")
+ (0 ":irc.barnet.org 329 tester #chan 1622538742")
+ (0.1 ":joe!~u@286u8jcpis84e.irc PRIVMSG #chan :mike: By favors several which they did bestow.")
+ (0.1 ":mike!~u@286u8jcpis84e.irc PRIVMSG #chan :joe: You, Roderigo! come, sir, I am for you."))
+
+((privmsg-a 5 "PRIVMSG rando :Linda said you were gonna kill me.")
+ (0.1 ":joe!~u@286u8jcpis84e.irc PRIVMSG #chan :mike: Play, music, then! Nay, you must do it soon.")
+ (0.1 ":rando!~u@95i756tt32ym8.irc PRIVMSG tester :Linda said? I never saw her before I came up here.")
+ (0.1 ":mike!~u@286u8jcpis84e.irc PRIVMSG #chan :joe: Of arts inhibited and out of warrant."))
+
+((privmsg-b 3 "PRIVMSG rando :You aren't with Wage?")
+ (0.1 ":joe!~u@286u8jcpis84e.irc PRIVMSG #chan :mike: But most of all, agreeing with the proclamation.")
+ (0.1 ":rando!~u@95i756tt32ym8.irc PRIVMSG tester :I think you screwed up, Case.")
+ (0.1 ":mike!~u@286u8jcpis84e.irc PRIVMSG #chan :joe: Good gentleman, go your gait, and let poor volk pass. An chud ha' bin zwaggered out of my life, 'twould not ha' bin zo long as 'tis by a vortnight. Nay, come not near th' old man; keep out, che vor ye, or ise try whether your costard or my ballow be the harder. Chill be plain with you.")
+ ;; Nick change
+ (0.1 ":rando!~u@95i756tt32ym8.irc NICK frenemy")
+ (0.1 ":joe!~u@286u8jcpis84e.irc PRIVMSG #chan :mike: Till time beget some careful remedy.")
+ (0.1 ":frenemy!~u@95i756tt32ym8.irc PRIVMSG tester :I showed up and you just fit me right into your reality picture.")
+ (0.1 ":mike!~u@286u8jcpis84e.irc PRIVMSG #chan :joe: For I have lost him on a dangerous sea."))
diff --git a/test/lisp/erc/resources/base/renick/queries/bouncer-foonet.eld b/test/lisp/erc/resources/base/renick/queries/bouncer-foonet.eld
new file mode 100644
index 00000000000..162e8bf9655
--- /dev/null
+++ b/test/lisp/erc/resources/base/renick/queries/bouncer-foonet.eld
@@ -0,0 +1,52 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS :foonet:changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.foonet.org 003 tester :This server was created Tue, 01 Jun 2021 07:49:22 UTC")
+ (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 5.2 "MODE tester +i")
+ ;; No mode answer
+ (0 ":irc.znc.in 306 tester :You have been marked as being away")
+ (0 ":tester!~u@u4mvbswyw8gbg.irc JOIN #chan")
+ (0 ":irc.foonet.org 353 tester = #chan :alice @bob rando tester")
+ (0 ":irc.foonet.org 366 tester #chan :End of /NAMES list.")
+ (0 ":***!znc@znc.in PRIVMSG #chan :Buffer Playback...")
+ (0 ":bob!~u@u4mvbswyw8gbg.irc PRIVMSG #chan :[09:19:28] alice: Great men should drink with harness on their throats.")
+ (0 ":alice!~u@u4mvbswyw8gbg.irc PRIVMSG #chan :[09:19:31] bob: Your lips will feel them the sooner: shallow again. A more sounder instance; come.")
+ (0 ":***!znc@znc.in PRIVMSG #chan :Playback Complete.")
+ (0 ":rando!~u@bivkhq8yav938.irc PRIVMSG tester :[09:17:51] u thur?")
+ (0 ":rando!~u@bivkhq8yav938.irc PRIVMSG tester :[09:17:58] guess not")
+ (0 ":irc.foonet.org NOTICE tester :[09:12:53] This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")
+ (0 ":irc.foonet.org 305 tester :You are no longer marked as being away"))
+
+((mode 10 "MODE #chan")
+ (0 ":irc.foonet.org 324 tester #chan +nt")
+ (0 ":irc.foonet.org 329 tester #chan 1622538742")
+ (0.1 ":bob!~u@u4mvbswyw8gbg.irc PRIVMSG #chan :alice: When there is nothing living but thee, thou shalt be welcome. I had rather be a beggar's dog than Apemantus.")
+ (0.1 ":alice!~u@u4mvbswyw8gbg.irc PRIVMSG #chan :bob: You have simply misused our sex in your love-prate: we must have your doublot and hose plucked over your head, and show the world what the bird hath done to her own nest."))
+
+((privmsg-a 6 "PRIVMSG rando :I here")
+ (0.1 ":bob!~u@u4mvbswyw8gbg.irc PRIVMSG #chan :alice: And I will make thee think thy swan a crow.")
+ (0.1 ":rando!~u@bivkhq8yav938.irc PRIVMSG tester :u are dumb")
+ (0.1 ":alice!~u@u4mvbswyw8gbg.irc PRIVMSG #chan :bob: Lie not, to say mine eyes are murderers."))
+
+((privmsg-b 3 "PRIVMSG rando :not so")
+ (0.1 ":bob!~u@u4mvbswyw8gbg.irc PRIVMSG #chan :alice: Commit myself, my person, and the cause.")
+ ;; Nick change
+ (0.1 ":rando!~u@bivkhq8yav938.irc NICK frenemy")
+ (0.1 ":alice!~u@u4mvbswyw8gbg.irc PRIVMSG #chan :bob: Of raging waste! It cannot hold; it will not.")
+ (0.1 ":frenemy!~u@bivkhq8yav938.irc PRIVMSG tester :doubly so")
+ (0.1 ":bob!~u@u4mvbswyw8gbg.irc PRIVMSG #chan :alice: These words are razors to my wounded heart."))
diff --git a/test/lisp/erc/resources/base/renick/queries/solo.eld b/test/lisp/erc/resources/base/renick/queries/solo.eld
new file mode 100644
index 00000000000..12fa7d264e9
--- /dev/null
+++ b/test/lisp/erc/resources/base/renick/queries/solo.eld
@@ -0,0 +1,55 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS :foonet:changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.foonet.org 003 tester :This server was created Mon, 31 May 2021 09:56:24 UTC")
+ (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.foonet.org 251 tester :There are 0 users and 4 invisible on 1 server(s)")
+ (0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.foonet.org 254 tester 2 :channels formed")
+ (0 ":irc.foonet.org 255 tester :I have 4 clients and 0 servers")
+ (0 ":irc.foonet.org 265 tester 4 4 :Current local users 4, max 4")
+ (0 ":irc.foonet.org 266 tester 4 4 :Current global users 4, max 4")
+ (0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 8 "MODE tester +i")
+ ;; No mode answer
+ (0 ":irc.znc.in 306 tester :You have been marked as being away")
+ (0 ":tester!~u@gq7yjr7gsu7nn.irc JOIN #foo")
+ (0 ":irc.foonet.org 353 tester = #foo :alice @bob Lal tester")
+ (0 ":irc.foonet.org 366 tester #foo :End of /NAMES list.")
+ (0 ":***!znc@znc.in PRIVMSG #foo :Buffer Playback...")
+ (0 ":alice!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :[10:00:02] bob: All that he is hath reference to your highness.")
+ (0 ":bob!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :[10:00:06] alice: Excellent workman! Thou canst not paint a man so bad as is thyself.")
+ (0 ":***!znc@znc.in PRIVMSG #foo :Playback Complete.")
+ (0 ":irc.foonet.org NOTICE tester :[09:56:57] This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")
+ (0 ":irc.foonet.org 305 tester :You are no longer marked as being away"))
+
+((mode 1 "MODE #foo")
+ (0 ":irc.foonet.org 324 tester #foo +nt")
+ (0 ":irc.foonet.org 329 tester #foo 1622454985")
+ (0.1 ":alice!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :bob: Farewell, pretty lady: you must hold the credit of your father.")
+ (0.1 ":bob!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :alice: On Thursday, sir ? the time is very short."))
+
+((privmsg-a 10 "PRIVMSG #foo :hi")
+ (0.2 ":Lal!~u@b82mytupn2t5k.irc PRIVMSG tester :hello")
+ (0.2 ":bob!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :alice: And brought to yoke, the enemies of Rome.")
+ (0.2 ":alice!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :bob: Thou art thy father's daughter; there's enough."))
+
+((privmsg-b 10 "PRIVMSG Lal :hi")
+ (0.2 ":bob!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :alice: Here are the beetle brows shall blush for me.")
+ (0.2 ":Lal!~u@b82mytupn2t5k.irc NICK Linguo")
+ (0.2 ":alice!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :bob: He hath abandoned his physicians, madam; under whose practices he hath persecuted time with hope, and finds no other advantage in the process but only the losing of hope by time."))
+
+((privmsg-c 10 "PRIVMSG Linguo :howdy Linguo")
+ (0.1 ":bob!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :alice: And brought to yoke, the enemies of Rome.")
+ (0.2 ":Linguo!~u@b82mytupn2t5k.irc PART #foo"))
+
+((part 10 "PART #foo :\2ERC\2")
+ (0 ":tester!~u@gq7yjr7gsu7nn.irc PART #foo :\2ERC\2")
+ (0.1 ":Linguo!~u@b82mytupn2t5k.irc PRIVMSG tester :get along little doggie"))
diff --git a/test/lisp/erc/resources/base/renick/self/auto.eld b/test/lisp/erc/resources/base/renick/self/auto.eld
new file mode 100644
index 00000000000..851db7f1cf7
--- /dev/null
+++ b/test/lisp/erc/resources/base/renick/self/auto.eld
@@ -0,0 +1,46 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS :foonet:changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.foonet.org 001 tester :Welcome to the FooNet Internet Relay Chat Network tester")
+ (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org[188.240.145.101/6697], running version solanum-1.0-dev")
+ (0 ":irc.foonet.org 003 tester :This server was created Sat May 22 2021 at 19:04:17 UTC")
+ (0 ":irc.foonet.org 004 tester irc.foonet.org solanum-1.0-dev DGQRSZaghilopsuwz CFILMPQSbcefgijklmnopqrstuvz bkloveqjfI")
+ (0 ":irc.foonet.org 005 tester WHOX FNC KNOCK SAFELIST ELIST=CTU CALLERID=g MONITOR=100 ETRACE CHANTYPES=# EXCEPTS INVEX CHANMODES=eIbq,k,flj,CFLMPQScgimnprstuz :are supported by this server")
+ (0 ":irc.foonet.org 005 tester CHANLIMIT=#:250 PREFIX=(ov)@+ MAXLIST=bqeI:100 MODES=4 NETWORK=foonet STATUSMSG=@+ CASEMAPPING=rfc1459 NICKLEN=16 MAXNICKLEN=16 CHANNELLEN=50 TOPICLEN=390 DEAF=D :are supported by this server")
+ (0 ":irc.foonet.org 005 tester TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,PRIVMSG:4,NOTICE:4,ACCEPT:,MONITOR: EXTBAN=$,ajrxz CLIENTVER=3.0 :are supported by this server")
+ (0 ":irc.foonet.org 251 tester :There are 33 users and 14113 invisible on 17 servers")
+ (0 ":irc.foonet.org 252 tester 34 :IRC Operators online")
+ (0 ":irc.foonet.org 254 tester 12815 :channels formed")
+ (0 ":irc.foonet.org 255 tester :I have 726 clients and 1 servers")
+ (0 ":irc.foonet.org 265 tester 726 739 :Current local users 726, max 739")
+ (0 ":irc.foonet.org 266 tester 14146 14541 :Current global users 14146, max 14541")
+ (0 ":irc.foonet.org 250 tester :Highest connection count: 740 (739 clients) (3790 connections received)")
+ (0 ":tester!~u@gq7yjr7gsu7nn.irc NICK :dummy")
+ (0 ":irc.foonet.org 375 dummy :- irc.foonet.org Message of the Day - ")
+ (0 ":irc.foonet.org 372 dummy :- This server provided by NORDUnet/SUNET")
+ (0 ":irc.foonet.org 372 dummy :- Welcome to foonet, the IRC network for free & open-source software")
+ (0 ":irc.foonet.org 372 dummy :- and peer directed projects.")
+ (0 ":irc.foonet.org 372 dummy :- ")
+ (0 ":irc.foonet.org 372 dummy :- Please visit us in #libera for questions and support.")
+ (0 ":irc.foonet.org 376 dummy :End of /MOTD command."))
+
+((mode-user 10.2 "MODE dummy +i")
+ (0 ":dummy!~u@gq7yjr7gsu7nn.irc MODE dummy :+RZi")
+ (0 ":irc.znc.in 306 dummy :You have been marked as being away")
+ (0 ":dummy!~u@gq7yjr7gsu7nn.irc JOIN #foo")
+
+ (0 ":irc.foonet.org 353 dummy = #foo :alice @bob Lal dummy")
+ (0 ":irc.foonet.org 366 dummy #foo :End of /NAMES list.")
+ (0 ":***!znc@znc.in PRIVMSG #foo :Buffer Playback...")
+ (0 ":alice!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :[10:00:02] bob: All that he is hath reference to your highness.")
+ (0 ":bob!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :[10:00:06] alice: Excellent workman! Thou canst not paint a man so bad as is thyself.")
+ (0 ":***!znc@znc.in PRIVMSG #foo :Playback Complete.")
+ (0 ":irc.foonet.org NOTICE dummy :[09:56:57] This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")
+ (0 ":irc.foonet.org 305 dummy :You are no longer marked as being away"))
+
+((mode 10 "MODE #foo")
+ (0 ":irc.foonet.org 324 dummy #foo +nt")
+ (0 ":irc.foonet.org 329 dummy #foo 1622454985")
+ (0.1 ":alice!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :bob: Farewell, pretty lady: you must hold the credit of your father.")
+ (0.1 ":bob!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :alice: On Thursday, sir ? the time is very short."))
diff --git a/test/lisp/erc/resources/base/renick/self/manual.eld b/test/lisp/erc/resources/base/renick/self/manual.eld
new file mode 100644
index 00000000000..dd107b806d5
--- /dev/null
+++ b/test/lisp/erc/resources/base/renick/self/manual.eld
@@ -0,0 +1,50 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS :foonet:changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.foonet.org 001 tester :Welcome to the FooNet Internet Relay Chat Network tester")
+ (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org[188.240.145.101/6697], running version solanum-1.0-dev")
+ (0 ":irc.foonet.org 003 tester :This server was created Sat May 22 2021 at 19:04:17 UTC")
+ (0 ":irc.foonet.org 004 tester irc.foonet.org solanum-1.0-dev DGQRSZaghilopsuwz CFILMPQSbcefgijklmnopqrstuvz bkloveqjfI")
+ (0 ":irc.foonet.org 005 tester WHOX FNC KNOCK SAFELIST ELIST=CTU CALLERID=g MONITOR=100 ETRACE CHANTYPES=# EXCEPTS INVEX CHANMODES=eIbq,k,flj,CFLMPQScgimnprstuz :are supported by this server")
+ (0 ":irc.foonet.org 005 tester CHANLIMIT=#:250 PREFIX=(ov)@+ MAXLIST=bqeI:100 MODES=4 NETWORK=foonet STATUSMSG=@+ CASEMAPPING=rfc1459 NICKLEN=16 MAXNICKLEN=16 CHANNELLEN=50 TOPICLEN=390 DEAF=D :are supported by this server")
+ (0 ":irc.foonet.org 005 tester TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,PRIVMSG:4,NOTICE:4,ACCEPT:,MONITOR: EXTBAN=$,ajrxz CLIENTVER=3.0 :are supported by this server")
+ (0 ":irc.foonet.org 251 tester :There are 33 users and 14113 invisible on 17 servers")
+ (0 ":irc.foonet.org 252 tester 34 :IRC Operators online")
+ (0 ":irc.foonet.org 254 tester 12815 :channels formed")
+ (0 ":irc.foonet.org 255 tester :I have 726 clients and 1 servers")
+ (0 ":irc.foonet.org 265 tester 726 739 :Current local users 726, max 739")
+ (0 ":irc.foonet.org 266 tester 14146 14541 :Current global users 14146, max 14541")
+ (0 ":irc.foonet.org 250 tester :Highest connection count: 740 (739 clients) (3790 connections received)")
+ (0 ":irc.foonet.org 375 tester :- irc.foonet.org Message of the Day - ")
+ (0 ":irc.foonet.org 372 tester :- This server provided by NORDUnet/SUNET")
+ (0 ":irc.foonet.org 372 tester :- Welcome to foonet, the IRC network for free & open-source software")
+ (0 ":irc.foonet.org 372 tester :- and peer directed projects.")
+ (0 ":irc.foonet.org 372 tester :- ")
+ (0 ":irc.foonet.org 372 tester :- Please visit us in #libera for questions and support.")
+ (0 ":irc.foonet.org 376 tester :End of /MOTD command."))
+
+((mode-user 1.2 "MODE tester +i")
+ (0 ":tester!~u@gq7yjr7gsu7nn.irc MODE tester :+RZi")
+ (0 ":irc.znc.in 306 tester :You have been marked as being away")
+ (0 ":tester!~u@gq7yjr7gsu7nn.irc JOIN #foo")
+
+ (0 ":irc.foonet.org 353 tester = #foo :alice @bob Lal tester")
+ (0 ":irc.foonet.org 366 tester #foo :End of /NAMES list.")
+ (0 ":***!znc@znc.in PRIVMSG #foo :Buffer Playback...")
+ (0 ":alice!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :[10:00:02] bob: All that he is hath reference to your highness.")
+ (0 ":bob!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :[10:00:06] alice: Excellent workman! Thou canst not paint a man so bad as is thyself.")
+ (0 ":***!znc@znc.in PRIVMSG #foo :Playback Complete.")
+ (0 ":irc.foonet.org NOTICE tester :[09:56:57] This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")
+ (0 ":irc.foonet.org 305 tester :You are no longer marked as being away"))
+
+((mode 1 "MODE #foo")
+ (0 ":irc.foonet.org 324 tester #foo +nt")
+ (0 ":irc.foonet.org 329 tester #foo 1622454985")
+ (0.1 ":alice!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :bob: Farewell, pretty lady: you must hold the credit of your father.")
+ (0.1 ":bob!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :alice: On Thursday, sir ? the time is very short."))
+
+((nick 2 "NICK dummy")
+ (0 ":tester!~u@gq7yjr7gsu7nn.irc NICK :dummy")
+ (0.1 ":dummy!~u@gq7yjr7gsu7nn.irc MODE dummy :+RZi")
+ (0.1 ":bob!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :dummy: Hi."))
diff --git a/test/lisp/erc/resources/base/renick/self/qual-chester.eld b/test/lisp/erc/resources/base/renick/self/qual-chester.eld
new file mode 100644
index 00000000000..75b50fe68bd
--- /dev/null
+++ b/test/lisp/erc/resources/base/renick/self/qual-chester.eld
@@ -0,0 +1,40 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS :changeme"))
+((nick 1 "NICK chester"))
+((user 1 "USER user 0 * :chester")
+ (0 ":irc.foonet.org 001 chester :Welcome to the foonet IRC Network chester")
+ (0 ":irc.foonet.org 002 chester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.foonet.org 003 chester :This server was created Sun, 13 Jun 2021 05:45:20 UTC")
+ (0 ":irc.foonet.org 004 chester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.foonet.org 005 chester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.foonet.org 005 chester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.foonet.org 005 chester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.foonet.org 251 chester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.foonet.org 252 chester 0 :IRC Operators online")
+ (0 ":irc.foonet.org 253 chester 1 :unregistered connections")
+ (0 ":irc.foonet.org 254 chester 1 :channels formed")
+ (0 ":irc.foonet.org 255 chester :I have 3 clients and 0 servers")
+ (0 ":irc.foonet.org 265 chester 3 4 :Current local users 3, max 4")
+ (0 ":irc.foonet.org 266 chester 3 4 :Current global users 3, max 4")
+ (0 ":irc.foonet.org 422 chester :MOTD File is missing"))
+
+((mode-user 1.2 "MODE chester +i")
+ (0 ":irc.foonet.org 221 chester +i")
+ (0 ":irc.foonet.org NOTICE chester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect."))
+
+((join 14 "JOIN #chan")
+ (0 ":chester!~u@yuvqisyu7m7qs.irc JOIN #chan")
+ (0 ":irc.foonet.org 353 chester = #chan :tester chester @alice bob")
+ (0 ":irc.foonet.org 366 chester #chan :End of NAMES list"))
+
+((mode 10 "MODE #chan")
+ (0.0 ":irc.foonet.org 324 chester #chan +nt")
+ (0.0 ":irc.foonet.org 329 chester #chan 1623563121")
+ (0.0 ":alice!~u@wyb9b355rgzi8.irc PRIVMSG #chan :chester, welcome!")
+ (0.0 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :chester, welcome!")
+ (0 ":tester!~u@gq7yjr7gsu7nn.irc NICK :dummy")
+ (0.1 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :alice: That ever eye with sight made heart lament.")
+ (0.1 ":alice!~u@wyb9b355rgzi8.irc PRIVMSG #chan :bob: The bitter past, more welcome is the sweet.")
+ (0.1 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :alice: Dispatch, I say, and find the forester."))
+
+((linger 10 LINGER))
diff --git a/test/lisp/erc/resources/base/renick/self/qual-tester.eld b/test/lisp/erc/resources/base/renick/self/qual-tester.eld
new file mode 100644
index 00000000000..25199226658
--- /dev/null
+++ b/test/lisp/erc/resources/base/renick/self/qual-tester.eld
@@ -0,0 +1,46 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS :changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.foonet.org 003 tester :This server was created Sun, 13 Jun 2021 05:45:20 UTC")
+ (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.foonet.org 251 tester :There are 0 users and 4 invisible on 1 server(s)")
+ (0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.foonet.org 253 tester 0 :unregistered connections")
+ (0 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0 ":irc.foonet.org 255 tester :I have 4 clients and 0 servers")
+ (0 ":irc.foonet.org 265 tester 4 4 :Current local users 4, max 4")
+ (0 ":irc.foonet.org 266 tester 4 4 :Current global users 4, max 4")
+ (0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 1.2 "MODE tester +i")
+ (0 ":irc.foonet.org 221 tester +i")
+ (0 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect."))
+
+((join 15 "JOIN #chan")
+ (0 ":tester!~u@yuvqisyu7m7qs.irc JOIN #chan")
+ (0 ":irc.foonet.org 353 tester = #chan :tester @alice bob")
+ (0 ":irc.foonet.org 366 tester #chan :End of NAMES list"))
+
+((mode 10 "MODE #chan")
+ (0.0 ":irc.foonet.org 324 tester #chan +nt")
+ (0.0 ":irc.foonet.org 329 tester #chan 1623563121")
+ (0.0 ":alice!~u@wyb9b355rgzi8.irc PRIVMSG #chan :tester, welcome!")
+ (0.0 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :tester, welcome!")
+ (0.1 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :alice: Marry, that, I think, be young Petruchio.")
+ (0.4 ":alice!~u@wyb9b355rgzi8.irc PRIVMSG #chan :bob: You speak of him when he was less furnished than now he is with that which makes him both without and within.")
+ (0.2 ":chester!~u@yuvqisyu7m7qs.irc JOIN #chan")
+ (0.1 ":alice!~u@wyb9b355rgzi8.irc PRIVMSG #chan :chester, welcome!")
+ (0.1 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :chester, welcome!"))
+
+((nick 5 "NICK dummy")
+ (0 ":tester!~u@gq7yjr7gsu7nn.irc NICK :dummy")
+ (0.1 ":dummy!~u@gq7yjr7gsu7nn.irc MODE dummy :+RZi")
+ (0.1 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :alice: That ever eye with sight made heart lament.")
+ (0.1 ":alice!~u@wyb9b355rgzi8.irc PRIVMSG #chan :bob: The bitter past, more welcome is the sweet.")
+ (0.1 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :alice: Dispatch, I say, and find the forester."))
diff --git a/test/lisp/erc/resources/base/reuse-buffers/channel/barnet.eld b/test/lisp/erc/resources/base/reuse-buffers/channel/barnet.eld
new file mode 100644
index 00000000000..efc2506fd6f
--- /dev/null
+++ b/test/lisp/erc/resources/base/reuse-buffers/channel/barnet.eld
@@ -0,0 +1,68 @@
+;; -*- mode: lisp-data; -*-
+((pass 3 "PASS :barnet:changeme"))
+((nick 3 "NICK tester"))
+((user 3 "USER user 0 * :tester")
+ (0 ":irc.barnet.org 001 tester :Welcome to the barnet IRC Network tester")
+ (0 ":irc.barnet.org 002 tester :Your host is irc.barnet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.barnet.org 003 tester :This server was created Wed, 05 May 2021 09:05:33 UTC")
+ (0 ":irc.barnet.org 004 tester irc.barnet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.barnet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.barnet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=barnet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.barnet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.barnet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.barnet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.barnet.org 254 tester 1 :channels formed")
+ (0 ":irc.barnet.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.barnet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.barnet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.barnet.org 422 tester :MOTD File is missing"))
+
+((mode-user 10.2 "MODE tester +i")
+ ;; No mode answer
+ (0 ":irc.znc.in 306 tester :You have been marked as being away")
+ (0 ":tester!~u@wvys46tx8tpmk.irc JOIN #chan")
+ (0 ":irc.barnet.org 353 tester = #chan :joe @mike tester")
+ (0 ":irc.barnet.org 366 tester #chan :End of /NAMES list.")
+ (0 ":***!znc@znc.in PRIVMSG #chan :Buffer Playback...")
+ (0 ":mike!~u@wvys46tx8tpmk.irc PRIVMSG #chan :[09:09:16] joe: Tush! none but minstrels like of sonneting.")
+ (0 ":joe!~u@wvys46tx8tpmk.irc PRIVMSG #chan :[09:09:19] mike: Prithee, nuncle, be contented; 'tis a naughty night to swim in. Now a little fire in a wide field were like an old lecher's heart; a small spark, all the rest on's body cold. Look! here comes a walking fire.")
+ (0 ":mike!~u@wvys46tx8tpmk.irc PRIVMSG #chan :[09:09:22] joe: My name is Edgar, and thy father's son.")
+ (0 ":joe!~u@wvys46tx8tpmk.irc PRIVMSG #chan :[09:09:26] mike: Good my lord, be good to me; your honor is accounted a merciful man; good my lord.")
+ (0 ":mike!~u@wvys46tx8tpmk.irc PRIVMSG #chan :[09:09:31] joe: Thy child shall live, and I will see it nourish'd.")
+ (0 ":joe!~u@wvys46tx8tpmk.irc PRIVMSG #chan :[09:09:33] mike: Quick, quick; fear nothing; I'll be at thy elbow.")
+ (0 ":***!znc@znc.in PRIVMSG #chan :Playback Complete.")
+ (0 ":irc.barnet.org NOTICE tester :[09:05:35] This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")
+ (0 ":irc.barnet.org 305 tester :You are no longer marked as being away"))
+
+((mode 3 "MODE #chan")
+ (0 ":irc.barnet.org 324 tester #chan +nt")
+ (0 ":irc.barnet.org 329 tester #chan 1620205534")
+ (0.1 ":mike!~u@wvys46tx8tpmk.irc PRIVMSG #chan :joe: That will be given to the loudest noise we make.")
+ (0.1 ":joe!~u@wvys46tx8tpmk.irc PRIVMSG #chan :mike: If it please your honor, I am the poor duke's constable, and my name is Elbow: I do lean upon justice, sir; and do bring in here before your good honor two notorious benefactors.")
+ (0.1 ":mike!~u@wvys46tx8tpmk.irc PRIVMSG #chan :joe: Following the signs, woo'd but the sign of she.")
+ (0.5 ":joe!~u@wvys46tx8tpmk.irc PRIVMSG #chan :mike: That, sir, which I will not report after her.")
+ (0.1 ":mike!~u@wvys46tx8tpmk.irc PRIVMSG #chan :joe: Boyet, prepare: I will away to-night.")
+ (0.1 ":joe!~u@wvys46tx8tpmk.irc PRIVMSG #chan :mike: If the man be a bachelor, sir, I can; but if he be a married man, he is his wife's head, and I can never cut off a woman's head.")
+ (0.1 ":mike!~u@wvys46tx8tpmk.irc PRIVMSG #chan :joe: Thyself upon thy virtues, they on thee.")
+ (0.1 ":joe!~u@wvys46tx8tpmk.irc PRIVMSG #chan :mike: Arm it in rags, a pigmy's straw doth pierce it."))
+
+((part 5.1 "PART #chan :" quit)
+ (0 ":tester!~u@wvys46tx8tpmk.irc PART #chan :" quit))
+
+((join 10.1 "JOIN #chan")
+ (0 ":tester!~u@wvys46tx8tpmk.irc JOIN #chan")
+ (0 ":irc.barnet.org 353 tester = #chan :@mike joe tester")
+ (0 ":irc.barnet.org 366 tester #chan :End of NAMES list")
+ (0.1 ":mike!~u@wvys46tx8tpmk.irc PRIVMSG #chan :tester, welcome!")
+ (0 ":joe!~u@wvys46tx8tpmk.irc PRIVMSG #chan :tester, welcome!"))
+
+((mode 1 "MODE #chan")
+ (0 ":irc.barnet.org 324 tester #chan +nt")
+ (0 ":irc.barnet.org 329 tester #chan 1620205534")
+ (0.1 ":mike!~u@wvys46tx8tpmk.irc PRIVMSG #chan :joe: Chi non te vede, non te pretia.")
+ (0.1 ":joe!~u@wvys46tx8tpmk.irc PRIVMSG #chan :mike: Well, if ever thou dost fall from this faith, thou wilt prove a notable argument.")
+ (0.1 ":mike!~u@wvys46tx8tpmk.irc PRIVMSG #chan :joe: Of heavenly oaths, vow'd with integrity.")
+ (0.1 ":joe!~u@wvys46tx8tpmk.irc PRIVMSG #chan :mike: These herblets shall, which we upon you strew.")
+ (0.1 ":mike!~u@wvys46tx8tpmk.irc PRIVMSG #chan :joe: Aaron will have his soul black like his face."))
+
+((linger 0.5 LINGER))
diff --git a/test/lisp/erc/resources/base/reuse-buffers/channel/foonet.eld b/test/lisp/erc/resources/base/reuse-buffers/channel/foonet.eld
new file mode 100644
index 00000000000..a11cfac2e73
--- /dev/null
+++ b/test/lisp/erc/resources/base/reuse-buffers/channel/foonet.eld
@@ -0,0 +1,66 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS :foonet:changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.foonet.org 003 tester :This server was created Wed, 05 May 2021 09:05:34 UTC")
+ (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 12 "MODE tester +i")
+ ;; No mode answer
+ (0 ":irc.znc.in 306 tester :You have been marked as being away")
+ (0 ":tester!~u@247eaxkrufj44.irc JOIN #chan")
+ (0 ":irc.foonet.org 353 tester = #chan :alice @bob tester")
+ (0 ":irc.foonet.org 366 tester #chan :End of /NAMES list.")
+ (0 ":***!znc@znc.in PRIVMSG #chan :Buffer Playback...")
+ (0 ":alice!~u@yppdd5tt4admc.irc PRIVMSG #chan :[09:07:19] bob: Is this; she hath bought the name of whore thus dearly.")
+ (0 ":bob!~u@yppdd5tt4admc.irc PRIVMSG #chan :[09:07:24] alice: He sent to me, sir,Here he comes.")
+ (0 ":alice!~u@yppdd5tt4admc.irc PRIVMSG #chan :[09:07:26] bob: Till I torment thee for this injury.")
+ (0 ":bob!~u@yppdd5tt4admc.irc PRIVMSG #chan :[09:07:29] alice: There's an Italian come; and 'tis thought, one of Leonatus' friends.")
+ (0 ":alice!~u@yppdd5tt4admc.irc PRIVMSG #chan :[09:09:33] bob: Ay, and the particular confirmations, point from point, to the full arming of the verity.")
+ (0 ":bob!~u@yppdd5tt4admc.irc PRIVMSG #chan :[09:09:35] alice: Kneel in the streets and beg for grace in vain.")
+ (0 ":***!znc@znc.in PRIVMSG #chan :Playback Complete.")
+ (0 ":irc.foonet.org NOTICE tester :[09:06:05] This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")
+ (0 ":irc.foonet.org 305 tester :You are no longer marked as being away"))
+
+((mode 10 "MODE #chan")
+ (0 ":irc.foonet.org 324 tester #chan +nt")
+ (0 ":irc.foonet.org 329 tester #chan 1620205534")
+ (0.5 ":bob!~u@yppdd5tt4admc.irc PRIVMSG #chan :alice: Nor I no strength to climb without thy help.")
+ (0.1 ":alice!~u@yppdd5tt4admc.irc PRIVMSG #chan :bob: Nothing, but let him have thanks. Demand of him my condition, and what credit I have with the duke.")
+ (0.1 ":bob!~u@yppdd5tt4admc.irc PRIVMSG #chan :alice: Show me this piece. I am joyful of your sights.")
+ (0.2 ":alice!~u@yppdd5tt4admc.irc PRIVMSG #chan :bob: Whilst I can shake my sword or hear the drum."))
+
+((part 5 "PART #chan :" quit)
+ (0 ":tester!~u@247eaxkrufj44.irc PART #chan :" quit))
+
+((join 10 "JOIN #chan")
+ (0 ":tester!~u@247eaxkrufj44.irc JOIN #chan")
+ (0 ":irc.foonet.org 353 tester = #chan :@bob alice tester")
+ (0 ":irc.foonet.org 366 tester #chan :End of NAMES list")
+ (0.1 ":alice!~u@yppdd5tt4admc.irc PRIVMSG #chan :tester, welcome!")
+ (0 ":bob!~u@yppdd5tt4admc.irc PRIVMSG #chan :tester, welcome!"))
+
+((mode 1 "MODE #chan")
+ (0 ":irc.foonet.org 324 tester #chan +nt")
+ (0 ":irc.foonet.org 329 tester #chan 1620205534")
+ (0.1 ":bob!~u@yppdd5tt4admc.irc PRIVMSG #chan :alice: Thou desirest me to stop in my tale against the hair.")
+ (0.1 ":alice!~u@yppdd5tt4admc.irc PRIVMSG #chan :bob: And dar'st not stand, nor look me in the face.")
+ (0.1 ":bob!~u@yppdd5tt4admc.irc PRIVMSG #chan :alice: It should not be, by the persuasion of his new feasting.")
+ (0.1 ":alice!~u@yppdd5tt4admc.irc PRIVMSG #chan :bob: It was not given me, nor I did not buy it.")
+ (0.1 ":bob!~u@yppdd5tt4admc.irc PRIVMSG #chan :alice: He that would vouch it in any place but here.")
+ (0.1 ":alice!~u@yppdd5tt4admc.irc PRIVMSG #chan :bob: In everything I wait upon his will.")
+ (0.1 ":bob!~u@yppdd5tt4admc.irc PRIVMSG #chan :alice: Thou counterfeit'st most lively."))
+
+((linger 8 LINGER))
diff --git a/test/lisp/erc/resources/base/reuse-buffers/server/barnet.eld b/test/lisp/erc/resources/base/reuse-buffers/server/barnet.eld
new file mode 100644
index 00000000000..cc7aff10076
--- /dev/null
+++ b/test/lisp/erc/resources/base/reuse-buffers/server/barnet.eld
@@ -0,0 +1,24 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS :barnet:changeme"))
+((nick 1 "NICK tester"))
+((user 2 "USER user 0 * :tester")
+ (0 ":irc.barnet.org 001 tester :Welcome to the barnet IRC Network tester")
+ (0 ":irc.barnet.org 002 tester :Your host is irc.barnet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.barnet.org 003 tester :This server was created Sun, 25 Apr 2021 11:28:28 UTC")
+ (0 ":irc.barnet.org 004 tester irc.barnet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.barnet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.barnet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=barnet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.barnet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.barnet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.barnet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.barnet.org 254 tester 1 :channels formed")
+ (0 ":irc.barnet.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.barnet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.barnet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.barnet.org 422 tester :MOTD File is missing"))
+
+((mode-user 10.2 "MODE tester +i")
+ ;; No mode answer
+ (0 ":irc.znc.in 306 tester :You have been marked as being away")
+ (0 ":irc.barnet.org NOTICE tester :[11:29:00] This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")
+ (0 ":irc.barnet.org 305 tester :You are no longer marked as being away"))
diff --git a/test/lisp/erc/resources/base/reuse-buffers/server/foonet.eld b/test/lisp/erc/resources/base/reuse-buffers/server/foonet.eld
new file mode 100644
index 00000000000..3a846108466
--- /dev/null
+++ b/test/lisp/erc/resources/base/reuse-buffers/server/foonet.eld
@@ -0,0 +1,24 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS :foonet:changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.foonet.org 003 tester :This server was created Sun, 25 Apr 2021 11:28:28 UTC")
+ (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 10.2 "MODE tester +i")
+ ;; No mode answer
+ (0 ":irc.znc.in 306 tester :You have been marked as being away")
+ (0 ":irc.foonet.org NOTICE tester :[11:29:00] This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")
+ (0 ":irc.foonet.org 305 tester :You are no longer marked as being away"))
diff --git a/test/lisp/erc/resources/base/upstream-reconnect/soju-barnet.eld b/test/lisp/erc/resources/base/upstream-reconnect/soju-barnet.eld
new file mode 100644
index 00000000000..3711eb8f8e6
--- /dev/null
+++ b/test/lisp/erc/resources/base/upstream-reconnect/soju-barnet.eld
@@ -0,0 +1,64 @@
+;; -*- mode: lisp-data; -*-
+((pass 6 "PASS :changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER tester@vanilla/barnet 0 * :tester")
+ (0.01 ":soju.im 001 tester :Welcome to soju, tester")
+ (0.01 ":soju.im 002 tester :Your host is soju.im")
+ (0.00 ":soju.im 004 tester soju.im soju aiwroO OovaimnqpsrtklbeI")
+ (0.53 ":soju.im 005 tester CHATHISTORY=1000 CASEMAPPING=ascii BOUNCER_NETID=2 AWAYLEN=390 CHANLIMIT=#:100 INVEX NETWORK=barnet NICKLEN=32 WHOX MODES BOT=B ELIST=U MAXLIST=beI:60 :are supported")
+ (0.01 ":soju.im 005 tester TOPICLEN=390 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 EXCEPTS EXTBAN=,m KICKLEN=390 TARGMAX=NAMES:1,LIST:1,KICK:,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 MAXTARGETS=4 MONITOR=100 CHANTYPES=# PREFIX=(qaohv)~&@%+ UTF8ONLY :are supported")
+ (0.22 ":soju.im 221 tester +Zi")
+ (0.00 ":soju.im 422 tester :Use /motd to read the message of the day"))
+
+((mode 5 "MODE tester +i")
+ (0.00 ":tester!tester@10.0.2.100 JOIN #chan")
+ (0.06 ":soju.im 353 tester = #chan :tester @mike joe")
+ (0.01 ":soju.im 366 tester #chan :End of /NAMES list")
+ (0.23 ":irc.barnet.org 221 tester +Zi"))
+
+((mode 5 "MODE #chan")
+ (0.00 ":soju.im 324 tester #chan +tn")
+ (0.01 ":soju.im 329 tester #chan 1652878846")
+ (0.01 ":joe!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :mike: There is five in the first show.")
+ (0.00 ":mike!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :joe: Sir, I was an inward of his. A shy fellow was the duke; and, I believe I know the cause of his withdrawing.")
+ (0.00 ":joe!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :mike: Proud of employment, willingly I go.")
+ (0.09 ":mike!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :joe: Dull not device by coldness and delay.")
+ (0.09 ":joe!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :mike: Our states are forfeit: seek not to undo us.")
+ (0.06 ":mike!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :joe: Come, you are too severe a moraler. As the time, the place, and the condition of this country stands, I could heartily wish this had not befallen, but since it is as it is, mend it for your own good.")
+ (0.06 ":joe!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :mike: Who hath upon him still that natural stamp.")
+ (0.07 ":mike!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :joe: Arraign her first; 'tis Goneril. I here take my oath before this honourable assembly, she kicked the poor king her father.")
+ (0.06 ":joe!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :mike: Lady, I will commend you to mine own heart.")
+ (0.08 ":mike!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :joe: Look, what I will not, that I cannot do.")
+ (0.08 ":joe!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :mike: That he would wed me, or else die my lover.")
+ (0.08 ":mike!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :joe: Come your way, sir. Bless you, good father friar.")
+ (0.08 ":joe!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :mike: Under correction, sir, we know whereuntil it doth amount.")
+ (0.08 ":mike!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :joe: For I am nothing if not critical.")
+ (0.06 ":joe!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :mike: Once more I'll read the ode that I have writ.")
+ (0.06 ":mike!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :joe: This is the foul fiend Flibbertigibbet: he begins at curfew, and walks till the first cock; he gives the web and the pin, squints the eye, and makes the harelip; mildews the white wheat, and hurts the poor creature of earth.")
+ (0.06 ":joe!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :mike: Sir, I praise the Lord for you, and so may my parishioners; for their sons are well tutored by you, and their daughters profit very greatly under you: you are a good member of the commonwealth.")
+ (0.08 ":mike!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :joe: If it please your honor, I know not well what they are; but precise villains they are, that I am sure of, and void of all profanation in the world that good Christians ought to have.")
+ ;; Unexpected disconnect
+ (0.03 ":BouncerServ!BouncerServ@BouncerServ NOTICE tester :disconnected from barnet: failed to handle messages: failed to read IRC command: read tcp [::1]:54990->[::1]:6668: read: software caused connection abort")
+ ;; Eventual reconnect
+ (0.79 ":BouncerServ!BouncerServ@BouncerServ NOTICE tester :connected to barnet")
+ ;; No MOTD or other numerics
+ (0.01 ":soju.im 005 tester AWAYLEN=390 BOT=B CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m INVEX KICKLEN=390 :are supported")
+ (0.01 ":soju.im 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=barnet NICKLEN=32 PREFIX=(qaohv)~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8ONLY WHOX :are supported")
+ (0.22 ":irc.barnet.org 221 tester +Zi")
+ (0.01 ":irc.barnet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")
+ ;; Server-initialed join
+ (0.01 ":tester!tester@10.0.2.100 JOIN #chan"))
+
+((mode 5 "MODE #chan")
+ (0.22 ":soju.im 353 tester = #chan :@mike joe tester")
+ (0.00 ":soju.im 366 tester #chan :End of /NAMES list")
+ (0.00 ":soju.im 324 tester #chan +nt")
+ (0.00 ":soju.im 329 tester #chan 1652878846")
+ (0.00 ":mike!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :tester, welcome!")
+ (0.00 ":joe!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :tester, welcome!")
+ (0.06 ":soju.im 324 tester #chan +nt")
+ (0.00 ":soju.im 329 tester #chan 1652878846")
+ (0.62 ":joe!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :mike: Thou art my brother; so we'll hold thee ever.")
+ (0.00 ":mike!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :joe: Very well! go to! I cannot go to, man; nor 'tis not very well: by this hand, I say, it is very scurvy, and begin to find myself fobbed in it.")
+ (0.00 ":joe!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :mike: The heir of Alen on, Katharine her name.")
+ (0.09 ":mike!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :joe: Go to; farewell! put money enough in your purse."))
diff --git a/test/lisp/erc/resources/base/upstream-reconnect/soju-foonet.eld b/test/lisp/erc/resources/base/upstream-reconnect/soju-foonet.eld
new file mode 100644
index 00000000000..63dfcb184c8
--- /dev/null
+++ b/test/lisp/erc/resources/base/upstream-reconnect/soju-foonet.eld
@@ -0,0 +1,72 @@
+;; -*- mode: lisp-data; -*-
+((pass 5 "PASS :changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER tester@vanilla/foonet 0 * :tester")
+ (0.01 ":soju.im 001 tester :Welcome to soju, tester")
+ (0.02 ":soju.im 002 tester :Your host is soju.im")
+ (0.01 ":soju.im 004 tester soju.im soju aiwroO OovaimnqpsrtklbeI")
+ (0.00 ":soju.im 005 tester CHATHISTORY=1000 CASEMAPPING=ascii BOUNCER_NETID=1 CHANTYPES=# PREFIX=(qaohv)~&@%+ UTF8ONLY AWAYLEN=390 NICKLEN=32 WHOX CHANLIMIT=#:100 INVEX NETWORK=foonet MODES :are supported")
+ (0.00 ":soju.im 005 tester TOPICLEN=390 BOT=B ELIST=U MAXLIST=beI:60 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 TARGMAX=NAMES:1,LIST:1,KICK:,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 EXCEPTS EXTBAN=,m KICKLEN=390 MAXTARGETS=4 MONITOR=100 :are supported")
+ (0.00 ":soju.im 221 tester +Zi")
+ (0.00 ":soju.im 422 tester :Use /motd to read the message of the day"))
+
+((mode 5 "MODE tester +i")
+ (0.2 ":irc.foonet.org 221 tester +Zi")
+ (0.0 ":tester!tester@10.0.2.100 JOIN #chan")
+ (0.0 ":soju.im 353 tester = #chan :tester @alice bob")
+ (0.1 ":soju.im 366 tester #chan :End of /NAMES list")
+ (0.0 ":bob!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :alice: Princely shall be thy usage every way.")
+ (0.1 ":alice!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :bob: Tell me thy reason why thou wilt marry."))
+
+((mode 5 "MODE #chan")
+ (0.00 ":soju.im 324 tester #chan +nt")
+ (0.01 ":soju.im 329 tester #chan 1652878847")
+ (0.02 ":bob!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :alice: There is no leprosy but what thou speak'st.")
+ (0.09 ":alice!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :bob: For I upon this bank will rest my head.")
+ (0.01 ":bob!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :alice: To ruffle in the commonwealth of Rome.")
+ (0.08 ":alice!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :bob: For I can nowhere find him like a man.")
+ (0.09 ":bob!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :alice: Ay, sir; but she will none, she gives you thanks.")
+ (0.05 ":alice!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :bob: That man should be at woman's command, and yet no hurt done! Though honesty be no puritan, yet it will do no hurt; it will wear the surplice of humility over the black gown of a big heart. I am going, forsooth: the business is for Helen to come hither.")
+ (0.07 ":bob!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :alice: Indeed, I should have asked you that before.")
+ (0.09 ":alice!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :bob: Faith, we met, and found the quarrel was upon the seventh cause.")
+ (0.05 ":bob!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :alice: And then, I hope, thou wilt be satisfied.")
+ (0.06 ":alice!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :bob: Well, I will forget the condition of my estate, to rejoice in yours.")
+ (0.05 ":bob!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :alice: Ah! sirrah, this unlook'd-for sport comes well.")
+ (0.01 ":alice!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :bob: Mayst thou inherit too! Welcome to Paris.")
+ (0.04 ":bob!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :alice: That I would choose, were I to choose anew.")
+ (0.08 ":alice!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :bob: Good Tom Drum, lend me a handkercher: so, I thank thee. Wait on me home, I'll make sport with thee: let thy curtsies alone, they are scurvy ones.")
+ (0.06 ":bob!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :alice: Excellent workman! Thou canst not paint a man so bad as is thyself.")
+ (0.07 ":alice!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :bob: That every braggart shall be found an ass.")
+ (0.07 ":bob!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :alice: This is but a custom in your tongue; you bear a graver purpose, I hope.")
+ (0.02 ":alice!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :bob: Well, we will have such a prologue, and it shall be written in eight and six.")
+ (0.01 ":bob!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :alice: Tell me thy reason why thou wilt marry.")
+ (0.06 ":alice!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :bob: According to the measure of their states.")
+
+ ;; Unexpected disconnect
+ (0.07 ":BouncerServ!BouncerServ@BouncerServ NOTICE tester :disconnected from foonet: failed to handle messages: failed to read IRC command: read tcp [::1]:57224->[::1]:6667: read: software caused connection abort")
+ ;; Eventual reconnect
+ (1.02 ":BouncerServ!BouncerServ@BouncerServ NOTICE tester :connected to foonet")
+ ;; No MOTD or other numerics
+ (0.01 ":soju.im 005 tester AWAYLEN=390 BOT=B CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m INVEX KICKLEN=390 :are supported")
+ (0.02 ":soju.im 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8ONLY WHOX :are supported")
+ (0.02 ":irc.foonet.org 221 tester +Zi")
+ (0.23 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")
+ ;; Server-initialed join
+ (0.02 ":tester!tester@10.0.2.100 JOIN #chan"))
+
+((mode 5 "MODE #chan")
+ (0.03 ":soju.im 353 tester = #chan :@alice bob tester")
+ (0.03 ":soju.im 366 tester #chan :End of /NAMES list")
+ (0.00 ":soju.im 324 tester #chan +nt")
+ (0.00 ":soju.im 329 tester #chan 1652878847")
+ (0.00 ":bob!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :tester, welcome!")
+ (0.00 ":alice!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :tester, welcome!")
+ (0.46 ":soju.im 324 tester #chan +nt")
+ (0.01 ":soju.im 329 tester #chan 1652878847")
+ (0.00 ":bob!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :alice: Thou desirest me to stop in my tale against the hair.")
+ (0.07 ":alice!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :bob: But my intents are fix'd and will not leave me.")
+ (0.09 ":bob!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :alice: That last is true; the sweeter rest was mine.")
+ (0.09 ":alice!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :bob: No matter whither, so you come not here.")
+ (0.09 ":bob!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :alice: My lord, in heart; and let the health go round."))
+
+((linger 12 LINGER))
diff --git a/test/lisp/erc/resources/base/upstream-reconnect/znc-barnet.eld b/test/lisp/erc/resources/base/upstream-reconnect/znc-barnet.eld
new file mode 100644
index 00000000000..bf5c2b5a749
--- /dev/null
+++ b/test/lisp/erc/resources/base/upstream-reconnect/znc-barnet.eld
@@ -0,0 +1,93 @@
+;; -*- mode: lisp-data; -*-
+((pass 6 "PASS :changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER tester@vanilla/barnet 0 * :tester")
+ (0.00 ":irc.barnet.org 001 tester :Welcome to the barnet IRC Network tester")
+ (0.01 ":irc.barnet.org 002 tester :Your host is irc.barnet.org, running version ergo-v2.8.0")
+ (0.01 ":irc.barnet.org 003 tester :This server was created Thu, 19 May 2022 05:33:02 UTC")
+ (0.00 ":irc.barnet.org 004 tester irc.barnet.org ergo-v2.8.0 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0.00 ":irc.barnet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0.01 ":irc.barnet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=barnet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0.01 ":irc.barnet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0.00 ":irc.barnet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0.00 ":irc.barnet.org 252 tester 0 :IRC Operators online")
+ (0.11 ":irc.barnet.org 254 tester 1 :channels formed")
+ (0.00 ":irc.barnet.org 255 tester :I have 3 clients and 0 servers")
+ (0.00 ":irc.barnet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0.00 ":irc.barnet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0.00 ":irc.barnet.org 422 tester :MOTD File is missing"))
+
+((mode 5 "MODE tester +i")
+ (0.0 ":tester!~u@fsr9fwzfeeybc.irc JOIN #chan")
+ (0.05 ":irc.barnet.org 353 tester = #chan :@joe mike tester")
+ (0.01 ":irc.barnet.org 366 tester #chan :End of /NAMES list.")
+ (0.0 ":***!znc@znc.in PRIVMSG #chan :Buffer Playback...")
+ (0.0 ":joe!~u@6t6jcije78we2.irc PRIVMSG #chan :[05:48:13] mike: But send the midwife presently to me.")
+ (0.01 ":mike!~u@6t6jcije78we2.irc PRIVMSG #chan :[05:48:18] joe: Alas! poor rogue, I think, i' faith, she loves me.")
+ (0.01 ":joe!~u@6t6jcije78we2.irc PRIVMSG #chan :[05:48:20] mike: They did not bless us with one happy word.")
+ (0.01 ":mike!~u@6t6jcije78we2.irc PRIVMSG #chan :[05:48:24] joe: And hear the sentence of your moved prince.")
+ (0.21 ":joe!~u@6t6jcije78we2.irc PRIVMSG #chan :[05:48:29] mike: Swear me to this, and I will ne'er say no.")
+ (0.01 ":mike!~u@6t6jcije78we2.irc PRIVMSG #chan :[05:48:32] joe: As they had seen me with these hangman's hands.")
+ (0.01 ":joe!~u@6t6jcije78we2.irc PRIVMSG #chan :[05:48:34] mike: Boyet, prepare: I will away to-night.")
+ (0.01 ":mike!~u@6t6jcije78we2.irc PRIVMSG #chan :[05:48:36] joe: For being a little bad: so may my husband.")
+ (0.04 ":***!znc@znc.in PRIVMSG #chan :Playback Complete.")
+ (0.0 ":irc.barnet.org 221 tester +Zi")
+ (2.55 ":joe!~u@6t6jcije78we2.irc PRIVMSG #chan :mike: And whirl along with thee about the globe."))
+
+((mode 5 "MODE #chan")
+ (0.00 ":irc.barnet.org 324 tester #chan +nt")
+ (0.00 ":irc.barnet.org 329 tester #chan 1652938384")
+ (0.06 ":mike!~u@6t6jcije78we2.irc PRIVMSG #chan :joe: Unless good-counsel may the cause remove.")
+ (0.00 ":joe!~u@6t6jcije78we2.irc PRIVMSG #chan :mike: Thyself domestic officers thine enemy.")
+ (0.01 ":mike!~u@6t6jcije78we2.irc PRIVMSG #chan :joe: Go after her: she's desperate; govern her.")
+ (0.30 ":joe!~u@6t6jcije78we2.irc PRIVMSG #chan :mike: Or else to heaven she heaves them for revenge.")
+ (0.01 ":mike!~u@6t6jcije78we2.irc PRIVMSG #chan :joe: Keep up your bright swords, for the dew will rust them.")
+ (0.04 ":*status!znc@znc.in PRIVMSG tester :Disconnected from IRC (Connection aborted). Reconnecting...")
+ (0.41 ":*status!znc@znc.in PRIVMSG tester :Disconnected from IRC. Reconnecting...")
+ (0.59 ":*status!znc@znc.in PRIVMSG tester :Connected!")
+ (0.02 ":irc.barnet.org 001 tester :Welcome to the barnet IRC Network tester")
+ (0.01 ":irc.barnet.org 002 tester :Your host is irc.barnet.org, running version ergo-v2.8.0")
+ (0.01 ":irc.barnet.org 003 tester :This server was created Thu, 19 May 2022 05:33:02 UTC")
+ (0.01 ":irc.barnet.org 004 tester irc.barnet.org ergo-v2.8.0 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0.01 ":irc.barnet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0.01 ":irc.barnet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=barnet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0.22 ":irc.barnet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0.00 ":irc.barnet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0.01 ":irc.barnet.org 252 tester 0 :IRC Operators online")
+ (0.00 ":irc.barnet.org 253 tester 0 :unregistered connections")
+ (0.00 ":irc.barnet.org 254 tester 1 :channels formed")
+ (0.00 ":irc.barnet.org 255 tester :I have 3 clients and 0 servers")
+ (0.00 ":irc.barnet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0.17 ":irc.barnet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0.00 ":irc.barnet.org 422 tester :MOTD File is missing")
+ (0.01 ":irc.barnet.org 221 tester +Zi")
+ (0.00 ":irc.barnet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")
+ (0.05 ":irc.barnet.org 352 tester * ~u fsr9fwzfeeybc.irc irc.barnet.org tester H :0 ZNC - https://znc.in")
+ (0.02 ":irc.barnet.org 315 tester tester!*@* :End of WHO list")
+ (0.08 ":tester!~u@fsr9fwzfeeybc.irc JOIN #chan"))
+
+((mode 5 "MODE #chan")
+ (0.05 ":irc.barnet.org 353 tester = #chan :mike tester @joe")
+ (0.01 ":irc.barnet.org 366 tester #chan :End of NAMES list")
+ (0.00 ":mike!~u@6t6jcije78we2.irc PRIVMSG #chan :tester, welcome!")
+ (0.00 ":joe!~u@6t6jcije78we2.irc PRIVMSG #chan :tester, welcome!")
+ (0.02 ":irc.barnet.org 324 tester #chan +nt")
+ (0.01 ":irc.barnet.org 329 tester #chan 1652938384")
+ (0.00 ":joe!~u@6t6jcije78we2.irc PRIVMSG #chan :mike: See, here he comes, and I must ply my theme.")
+ (0.00 ":mike!~u@6t6jcije78we2.irc PRIVMSG #chan :joe: Confine yourself but in a patient list.")
+ (0.00 ":joe!~u@6t6jcije78we2.irc PRIVMSG #chan :mike: And bide the penance of each three years' day.")
+ (0.00 ":mike!~u@6t6jcije78we2.irc PRIVMSG #chan :joe: Bid me farewell, and let me hear thee going.")
+ (0.00 ":joe!~u@6t6jcije78we2.irc PRIVMSG #chan :mike: Nor shall not, if I do as I intend.")
+ (0.00 ":mike!~u@6t6jcije78we2.irc PRIVMSG #chan :joe: Our corn's to reap, for yet our tithe's to sow.")
+ (0.00 ":joe!~u@6t6jcije78we2.irc PRIVMSG #chan :mike: And almost broke my heart with extreme laughter.")
+ (0.00 ":mike!~u@6t6jcije78we2.irc PRIVMSG #chan :joe: Of modern seeming do prefer against him.")
+ (0.00 ":joe!~u@6t6jcije78we2.irc PRIVMSG #chan :mike: Like humble-visag'd suitors, his high will.")
+ (0.00 ":mike!~u@6t6jcije78we2.irc PRIVMSG #chan :joe: But yet, poor Claudio! There's no remedy.")
+ (0.00 ":joe!~u@6t6jcije78we2.irc PRIVMSG #chan :mike: Let him make treble satisfaction.")
+ (0.00 ":mike!~u@6t6jcije78we2.irc PRIVMSG #chan :joe: He's that he is; I may not breathe my censure.")
+ (0.00 ":joe!~u@6t6jcije78we2.irc PRIVMSG #chan :mike: To check their folly, passion's solemn tears.")
+ (0.00 ":mike!~u@6t6jcije78we2.irc PRIVMSG #chan :joe: Villain, I have done thy mother.")
+ (0.00 ":joe!~u@6t6jcije78we2.irc PRIVMSG #chan :mike: Please you, therefore, draw nigh, and take your places.")
+ (0.00 ":mike!~u@6t6jcije78we2.irc PRIVMSG #chan :joe: You shall not be admitted to his sight.")
+ (0.00 ":joe!~u@6t6jcije78we2.irc PRIVMSG #chan :mike: Sir, you shall present before her the Nine Worthies. Sir Nathaniel, as concerning some entertainment of time, some show in the posterior of this day, to be rendered by our assistance, at the king's command, and this most gallant, illustrate, and learned gentleman, before the princess; I say, none so fit as to present the Nine Worthies.")
+ (0.00 ":mike!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :joe: Go to; farewell! put money enough in your purse."))
diff --git a/test/lisp/erc/resources/base/upstream-reconnect/znc-foonet.eld b/test/lisp/erc/resources/base/upstream-reconnect/znc-foonet.eld
new file mode 100644
index 00000000000..39c2950aa09
--- /dev/null
+++ b/test/lisp/erc/resources/base/upstream-reconnect/znc-foonet.eld
@@ -0,0 +1,86 @@
+;; -*- mode: lisp-data; -*-
+((pass 6 "PASS :changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER tester@vanilla/foonet 0 * :tester")
+ (0.16 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0.00 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version ergo-v2.8.0")
+ (0.00 ":irc.foonet.org 003 tester :This server was created Thu, 19 May 2022 05:33:02 UTC")
+ (0.00 ":irc.foonet.org 004 tester irc.foonet.org ergo-v2.8.0 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0.00 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0.01 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0.01 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0.00 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0.00 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0.00 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0.00 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers")
+ (0.00 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0.00 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0.00 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode 6 "MODE tester +i")
+ (0.00 ":tester!~u@rmtvrz9zcwbdq.irc JOIN #chan")
+ (0.09 ":irc.foonet.org 353 tester = #chan :@alice bob tester")
+ (0.00 ":irc.foonet.org 366 tester #chan :End of /NAMES list.")
+ (0.00 ":***!znc@znc.in PRIVMSG #chan :Buffer Playback...")
+ (0.00 ":bob!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :[05:48:11] alice: And be aveng'd on cursed Tamora.")
+ (0.00 ":alice!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :[05:48:13] bob: The stronger part of it by her own letters, which make her story true, even to the point of her death: her death itself, which could not be her office to say is come, was faithfully confirmed by the rector of the place.")
+ (0.01 ":bob!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :[05:48:15] alice: The ape is dead, and I must conjure him.")
+ (0.00 ":alice!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :[05:48:17] bob: Not so; but I answer you right painted cloth, from whence you have studied your questions.")
+ (0.01 ":bob!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :[05:48:21] alice: The valiant Paris seeks you for his love.")
+ (0.00 ":alice!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :[05:48:26] bob: To prison with her; and away with him.")
+ (0.00 ":bob!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :[05:48:30] alice: Tell them there I have gold; look, so I have.")
+ (0.00 ":alice!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :[05:48:35] bob: Will even weigh, and both as light as tales.")
+ (0.00 ":***!znc@znc.in PRIVMSG #chan :Playback Complete.")
+ (0.00 ":irc.foonet.org 221 tester +Zi")
+ (0.08 ":bob!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :alice: By some vile forfeit of untimely death."))
+
+((mode 3.51 "MODE #chan")
+ (0.1 ":irc.foonet.org 324 tester #chan +nt")
+ (0.0 ":irc.foonet.org 329 tester #chan 1652938384")
+ (0.0 ":alice!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :bob: What does this knave here ? Get you gone, sirrah: the complaints I have heard of you I do not all believe: 'tis my slowness that I do not; for I know you lack not folly to commit them, and have ability enough to make such knaveries yours.")
+ (0.0 ":bob!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :alice: When sects and factions were newly born.")
+ (0.1 ":alice!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :bob: Fall, when Love please! marry, to each, but one.")
+ (0.1 ":bob!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :alice: For I ne'er saw true beauty till this night.")
+ (0.1 ":alice!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :bob: Or say, sweet love, what thou desir'st to eat.")
+ (0.1 ":bob!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :alice: Yes, and will nobly him remunerate.")
+ (0.1 ":*status!znc@znc.in PRIVMSG tester :Disconnected from IRC (Connection aborted). Reconnecting...")
+ (0.4 ":*status!znc@znc.in PRIVMSG tester :Disconnected from IRC. Reconnecting...")
+ (0.9 ":*status!znc@znc.in PRIVMSG tester :Connected!")
+ (0.0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0.0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version ergo-v2.8.0")
+ (0.0 ":irc.foonet.org 003 tester :This server was created Thu, 19 May 2022 05:33:02 UTC")
+ (0.0 ":irc.foonet.org 004 tester irc.foonet.org ergo-v2.8.0 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0.1 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0.0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0.0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0.0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0.0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0.0 ":irc.foonet.org 253 tester 0 :unregistered connections")
+ (0.1 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0.0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers")
+ (0.0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0.0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0.0 ":irc.foonet.org 422 tester :MOTD File is missing")
+ (0.0 ":irc.foonet.org 221 tester +Zi")
+ (0.0 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")
+ (0.6 ":irc.foonet.org 352 tester * ~u rmtvrz9zcwbdq.irc irc.foonet.org tester H :0 ZNC - https://znc.in")
+ (0.0 ":irc.foonet.org 315 tester tester!*@* :End of WHO list")
+ (0.0 ":tester!~u@rmtvrz9zcwbdq.irc JOIN #chan"))
+
+((mode 6 "MODE #chan")
+ (0.0 ":irc.foonet.org 353 tester = #chan :@alice bob tester")
+ (0.0 ":irc.foonet.org 366 tester #chan :End of NAMES list")
+ (0.0 ":alice!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :tester, welcome!")
+ (0.0 ":bob!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :tester, welcome!")
+ (0.0 ":alice!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :bob: Being of no power to make his wishes good.")
+ (0.0 ":irc.foonet.org 324 tester #chan +nt")
+ (0.0 ":irc.foonet.org 329 tester #chan 1652938384")
+ (0.0 ":bob!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :alice: In everything I wait upon his will.")
+ (0.0 ":alice!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :bob: Make choice of which your highness will see first.")
+ (0.0 ":bob!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :alice: We waste our lights in vain, like lamps by day.")
+ (0.0 ":alice!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :bob: No, I know that; but it is fit I should commit offence to my inferiors.")
+ (0.1 ":bob!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :alice: By my head, here come the Capulets.")
+ (0.0 ":alice!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :bob: Well, I will forget the condition of my estate, to rejoice in yours.")
+ (0.0 ":bob!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :alice: My lord, in heart; and let the health go round."))
+
+((linger 12 LINGER))
diff --git a/test/lisp/erc/resources/dcc/chat/accept-dcc.eld b/test/lisp/erc/resources/dcc/chat/accept-dcc.eld
new file mode 100644
index 00000000000..23828a8115e
--- /dev/null
+++ b/test/lisp/erc/resources/dcc/chat/accept-dcc.eld
@@ -0,0 +1,3 @@
+;; -*- mode: lisp-data; -*-
+((open 10 "Hi")
+ (0 "Hola"))
diff --git a/test/lisp/erc/resources/dcc/chat/accept.eld b/test/lisp/erc/resources/dcc/chat/accept.eld
new file mode 100644
index 00000000000..a23e9580bcc
--- /dev/null
+++ b/test/lisp/erc/resources/dcc/chat/accept.eld
@@ -0,0 +1,23 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS :changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.foonet.org 003 tester :This server was created Mon, 31 May 2021 09:56:24 UTC")
+ (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.foonet.org 251 tester :There are 0 users and 4 invisible on 1 server(s)")
+ (0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.foonet.org 254 tester 2 :channels formed")
+ (0 ":irc.foonet.org 255 tester :I have 4 clients and 0 servers")
+ (0 ":irc.foonet.org 265 tester 4 4 :Current local users 4, max 4")
+ (0 ":irc.foonet.org 266 tester 4 4 :Current global users 4, max 4")
+ (0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 1.2 "MODE tester +i")
+ ;; No mode answer
+ (0 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")
+ (0.2 ":dummy!~u@34n9brushbpj2.irc PRIVMSG tester :\C-aDCC CHAT chat 2130706433 " port "\C-a"))
diff --git a/test/lisp/erc/resources/erc-d/erc-d-i.el b/test/lisp/erc/resources/erc-d/erc-d-i.el
new file mode 100644
index 00000000000..db113335a82
--- /dev/null
+++ b/test/lisp/erc/resources/erc-d/erc-d-i.el
@@ -0,0 +1,124 @@
+;;; erc-d-i.el --- IRC helpers for ERC test server -*- lexical-binding: t -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'cl-lib)
+
+(cl-defstruct (erc-d-i-message (:conc-name erc-d-i-message.))
+ "Identical to `erc-response'.
+When member `compat' is nil, it means the raw message was decoded as
+UTF-8 text before parsing, which is nonstandard."
+ (unparsed "" :type string)
+ (sender "" :type string)
+ (command "" :type string)
+ (command-args nil :type (list-of string))
+ (contents "" :type string)
+ (tags nil :type (list-of (cons symbol string)))
+ (compat t :type boolean))
+
+(defconst erc-d-i--tag-escapes
+ '((";" . "\\:") (" " . "\\s") ("\\" . "\\\\") ("\r" . "\\r") ("\n" . "\\n")))
+
+;; These are not mirror inverses; unescaping may drop stranded or
+;; misplaced backslashes.
+
+(defconst erc-d-i--tag-escaped-regexp (rx (or ?\; ?\ ?\\ ?\r ?\n)))
+
+(defconst erc-d-i--tag-unescaped-regexp
+ (rx (or "\\:" "\\s" "\\\\" "\\r" "\\n"
+ (seq "\\" (or string-end (not (or ":" "s" "n" "r" "\\")))))))
+
+(defun erc-d-i--unescape-tag-value (str)
+ "Undo substitution of char placeholders in raw tag value STR."
+ (replace-regexp-in-string erc-d-i--tag-unescaped-regexp
+ (lambda (s)
+ (or (car (rassoc s erc-d-i--tag-escapes))
+ (substring s 1)))
+ str t t))
+
+(defun erc-d-i--escape-tag-value (str)
+ "Swap out banned chars in tag value STR with message representation."
+ (replace-regexp-in-string erc-d-i--tag-escaped-regexp
+ (lambda (s)
+ (cdr (assoc s erc-d-i--tag-escapes)))
+ str t t))
+
+(defconst erc-d-i--invalid-tag-regexp (rx (any "\0\7\r\n; ")))
+
+(defun erc-d-i--validate-tags (raw)
+ "Validate tags portion of some RAW incoming message.
+RAW must not have a leading \"@\" or a trailing space. The spec says
+validation shouldn't be performed on keys and that undecodeable values
+or ones with illegal (unescaped) chars may be dropped. This does not
+respect any of that. Its purpose is to catch bad input created by us."
+ (unless (> 4094 (string-bytes raw))
+ ;; 417 ERR_INPUTTOOLONG Input line was too long
+ (error "Message tags exceed 4094 bytes: %S" raw))
+ (let (tags
+ (tag-strings (split-string raw ";")))
+ (dolist (s tag-strings (nreverse tags))
+ (let* ((m (if (>= emacs-major-version 28)
+ (string-search "=" s)
+ (string-match-p "=" s)))
+ (key (if m (substring s 0 m) s))
+ (val (when-let* (m ; check first, like (m), but shadow
+ (v (substring s (1+ m)))
+ ((not (string-equal v ""))))
+ (when (string-match-p erc-d-i--invalid-tag-regexp v)
+ (error "Bad tag: %s" s))
+ (thread-first v
+ (decode-coding-string 'utf-8 t)
+ (erc-d-i--unescape-tag-value)))))
+ (when (string-empty-p key)
+ (error "Tag missing key: %S" s))
+ (setf (alist-get (intern key) tags) val)))))
+
+(defun erc-d-i--parse-message (s &optional decode)
+ "Parse string S into `erc-d-i-message' object.
+With DECODE, decode as UTF-8 text."
+ (when (string-suffix-p "\r\n" s)
+ (error "Unstripped message encountered"))
+ (when decode
+ (setq s (decode-coding-string s 'utf-8 t)))
+ (let ((mes (make-erc-d-i-message :unparsed s :compat (not decode)))
+ tokens)
+ (when-let* (((not (string-empty-p s)))
+ ((eq ?@ (aref s 0)))
+ (m (string-match " " s))
+ (u (substring s 1 m)))
+ (setf (erc-d-i-message.tags mes) (erc-d-i--validate-tags u)
+ s (substring s (1+ m))))
+ (if-let* ((m (string-match " :" s))
+ (other-toks (split-string (substring s 0 m) " " t))
+ (rest (substring s (+ 2 m))))
+ (setf (erc-d-i-message.contents mes) rest
+ tokens (nconc other-toks (list rest)))
+ (setq tokens (split-string s " " t " ")))
+ (when (and tokens (eq ?: (aref (car tokens) 0)))
+ (setf (erc-d-i-message.sender mes) (substring (pop tokens) 1)))
+ (setf (erc-d-i-message.command mes) (or (pop tokens) "")
+ (erc-d-i-message.command-args mes) tokens)
+ mes))
+
+(provide 'erc-d-i)
+;;; erc-d-i.el ends here
diff --git a/test/lisp/erc/resources/erc-d/erc-d-t.el b/test/lisp/erc/resources/erc-d/erc-d-t.el
new file mode 100644
index 00000000000..a1a7e7e88d5
--- /dev/null
+++ b/test/lisp/erc/resources/erc-d/erc-d-t.el
@@ -0,0 +1,170 @@
+;;; erc-d-t.el --- ERT helpers for ERC test server -*- lexical-binding: t -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+(eval-and-compile
+ (let* ((d (file-name-directory (or (macroexp-file-name) buffer-file-name)))
+ (load-path (cons (directory-file-name d) load-path)))
+ (require 'erc-d-u)))
+
+(require 'ert)
+
+(defun erc-d-t-kill-related-buffers ()
+ "Kill all erc- or erc-d- related buffers."
+ (let (buflist)
+ (dolist (buf (buffer-list))
+ (with-current-buffer buf
+ (when (or erc-d-u--process-buffer
+ (derived-mode-p 'erc-mode))
+ (push buf buflist))))
+ (dolist (buf buflist)
+ (when (and (boundp 'erc-server-flood-timer)
+ (timerp erc-server-flood-timer))
+ (cancel-timer erc-server-flood-timer))
+ (when-let ((proc (get-buffer-process buf)))
+ (delete-process proc))
+ (when (buffer-live-p buf)
+ (kill-buffer buf))))
+ (while (when-let ((buf (pop erc-d-u--canned-buffers)))
+ (kill-buffer buf))))
+
+(defun erc-d-t-silence-around (orig &rest args)
+ "Run ORIG function with ARGS silently.
+Use this on `erc-handle-login' and `erc-server-connect'."
+ (let ((inhibit-message t))
+ (apply orig args)))
+
+(defvar erc-d-t-cleanup-sleep-secs 0.1)
+
+(defmacro erc-d-t-with-cleanup (bindings cleanup &rest body)
+ "Execute BODY and run CLEANUP form regardless of outcome.
+`let*'-bind BINDINGS and make them available in BODY and CLEANUP.
+After CLEANUP, destroy any values in BINDINGS that remain bound to
+buffers or processes. Sleep `erc-d-t-cleanup-sleep-secs' before
+returning."
+ (declare (indent 2))
+ `(let* ,bindings
+ (unwind-protect
+ (progn ,@body)
+ ,cleanup
+ (when noninteractive
+ (let (bufs procs)
+ (dolist (o (list ,@(mapcar (lambda (b) (or (car-safe b) b))
+ bindings)))
+ (when (bufferp o)
+ (push o bufs))
+ (when (processp o)
+ (push o procs)))
+ (dolist (proc procs)
+ (delete-process proc)
+ (when-let ((buf (process-buffer proc)))
+ (push buf bufs)))
+ (dolist (buf bufs)
+ (when-let ((proc (get-buffer-process buf)))
+ (delete-process proc))
+ (when (bufferp buf)
+ (ignore-errors (kill-buffer buf)))))
+ (sleep-for erc-d-t-cleanup-sleep-secs)))))
+
+(defmacro erc-d-t-wait-for (max-secs msg &rest body)
+ "Wait for BODY to become non-nil.
+Or signal error with MSG after MAX-SECS. When MAX-SECS is negative,
+signal if BODY is ever non-nil before MAX-SECS elapses. On success,
+return BODY's value.
+
+Note: this assumes BODY is waiting on a peer's output. It tends to
+artificially accelerate consumption of all process output, which may not
+be desirable."
+ (declare (indent 2))
+ (unless (or (stringp msg) (memq (car-safe msg) '(format concat)))
+ (push msg body)
+ (setq msg (prin1-to-string body)))
+ (let ((inverted (make-symbol "inverted"))
+ (time-out (make-symbol "time-out"))
+ (result (make-symbol "result")))
+ `(ert-info ((concat "Awaiting: " ,msg))
+ (let ((,time-out (abs ,max-secs))
+ (,inverted (< ,max-secs 0))
+ (,result ',result))
+ (with-timeout (,time-out (if ,inverted
+ (setq ,inverted nil)
+ (error "Failed awaiting: %s" ,msg)))
+ (while (not (setq ,result (progn ,@body)))
+ (when (and (accept-process-output nil 0.1) (not noninteractive))
+ (redisplay))))
+ (when ,inverted
+ (error "Failed awaiting: %s" ,msg))
+ ,result))))
+
+(defmacro erc-d-t-ensure-for (max-secs msg &rest body)
+ "Ensure BODY remains non-nil for MAX-SECS.
+On failure, emit MSG."
+ (declare (indent 2))
+ (unless (or (stringp msg) (memq (car-safe msg) '(format concat)))
+ (push msg body)
+ (setq msg (prin1-to-string body)))
+ `(erc-d-t-wait-for (- (abs ,max-secs)) ,msg (not (progn ,@body))))
+
+(defun erc-d-t-search-for (timeout text &optional from on-success)
+ "Wait for TEXT to appear in current buffer before TIMEOUT secs.
+With marker or number FROM, only consider the portion of the buffer from
+that point forward. If TEXT is a cons, interpret it as an RX regular
+expression. If ON-SUCCESS is a function, call it when TEXT is found."
+ (save-restriction
+ (widen)
+ (let* ((rxp (consp text))
+ (fun (if rxp #'search-forward-regexp #'search-forward))
+ (pat (if rxp (rx-to-string text) text))
+ res)
+ (erc-d-t-wait-for timeout (format "string: %s" text)
+ (goto-char (or from (point-min)))
+ (setq res (funcall fun pat nil t))
+ (if (and on-success res)
+ (funcall on-success)
+ res)))))
+
+(defun erc-d-t-absent-for (timeout text &optional from on-success)
+ "Assert TEXT doesn't appear in current buffer for TIMEOUT secs."
+ (erc-d-t-search-for (- (abs timeout)) text from on-success))
+
+(defun erc-d-t-make-expecter ()
+ "Return function to search for new output in buffer.
+Assume new text is only inserted at or after `erc-insert-marker'.
+
+The returned function works like `erc-d-t-search-for', but it never
+revisits previously covered territory, and the optional fourth argument,
+ON-SUCCESS, is nonexistent. To reset, specify a FROM argument."
+ (let (positions)
+ (lambda (timeout text &optional reset-from)
+ (let* ((pos (cdr (assq (current-buffer) positions)))
+ (cb (lambda ()
+ (unless pos
+ (push (cons (current-buffer) (setq pos (make-marker)))
+ positions))
+ (marker-position
+ (set-marker pos (min (point) (1- (point-max))))))))
+ (when reset-from
+ (set-marker pos reset-from))
+ (erc-d-t-search-for timeout text pos cb)))))
+
+(provide 'erc-d-t)
+;;; erc-d-t.el ends here
diff --git a/test/lisp/erc/resources/erc-d/erc-d-tests.el b/test/lisp/erc/resources/erc-d/erc-d-tests.el
new file mode 100644
index 00000000000..a4befd96b5e
--- /dev/null
+++ b/test/lisp/erc/resources/erc-d/erc-d-tests.el
@@ -0,0 +1,1373 @@
+;;; erc-d-tests.el --- tests for erc-d -*- lexical-binding: t -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (expand-file-name ".." (ert-resource-directory))
+ load-path)))
+ (require 'erc-d)
+ (require 'erc-d-t)))
+
+(require 'erc)
+
+;; Temporary kludge to silence warning
+(put 'erc-parse-tags 'erc-v3-warned-p t)
+
+(ert-deftest erc-d-u--canned-load-dialog--basic ()
+ (should-not (get-buffer "basic.eld"))
+ (should-not erc-d-u--canned-buffers)
+ (let* ((exes (erc-d-u--canned-load-dialog 'basic))
+ (reap (lambda ()
+ (cl-loop with e = (erc-d-u--read-dialog exes)
+ for s = (erc-d-u--read-exchange e)
+ while s collect s))))
+ (should (get-buffer "basic.eld"))
+ (should (memq (get-buffer "basic.eld") erc-d-u--canned-buffers))
+ (should (equal (funcall reap) '((pass 10.0 "PASS " (? ?:) "changeme"))))
+ (should (equal (funcall reap) '((nick 0.2 "NICK tester"))))
+ (let ((r (funcall reap)))
+ (should (equal (car r) '(user 0.2 "USER user 0 * :tester")))
+ (should (equal
+ (car (last r))
+ '(0 ":irc.example.org 422 tester :MOTD File is missing"))))
+ (should (equal (car (funcall reap)) '(mode-user 5 "MODE tester +i")))
+ (should (equal (funcall reap)
+ '((mode-chan 1.2 "MODE #chan")
+ (0.1 ":bob!~bob@example.org PRIVMSG #chan :hey"))))
+ ;; See `define-error' site for `iter-end-of-sequence'
+ (ert-info ("EOB detected") (should-not (erc-d-u--read-dialog exes))))
+ (should-not (get-buffer "basic.eld"))
+ (should-not erc-d-u--canned-buffers))
+
+(defun erc-d-tests--make-hunk-reader (hunks)
+ (let ((p (erc-d-u--read-dialog hunks)))
+ (lambda () (erc-d-u--read-exchange p))))
+
+;; Fuzzies need to be able to access any non-exhausted genny.
+(ert-deftest erc-d-u--canned-load-dialog--intermingled ()
+ (should-not (get-buffer "basic.eld"))
+ (should-not erc-d-u--canned-buffers)
+ (let* ((exes (erc-d-u--canned-load-dialog 'basic))
+ (pass (erc-d-tests--make-hunk-reader exes))
+ (nick (erc-d-tests--make-hunk-reader exes))
+ (user (erc-d-tests--make-hunk-reader exes))
+ (modu (erc-d-tests--make-hunk-reader exes))
+ (modc (erc-d-tests--make-hunk-reader exes)))
+
+ (should (equal (funcall user) '(user 0.2 "USER user 0 * :tester")))
+ (should (equal (funcall modu) '(mode-user 5 "MODE tester +i")))
+ (should (equal (funcall modc) '(mode-chan 1.2 "MODE #chan")))
+
+ (cl-loop repeat 8 do (funcall user)) ; skip a few
+ (should (equal (funcall user)
+ '(0 ":irc.example.org 254 tester 1 :channels formed")))
+ (should (equal (funcall modu)
+ '(0 ":irc.example.org 221 tester +Zi")))
+ (should (equal (cl-loop for s = (funcall modc) while s collect s) ; done
+ '((0.1 ":bob!~bob@example.org PRIVMSG #chan :hey"))))
+
+ (cl-loop repeat 3 do (funcall user))
+ (cl-loop repeat 3 do (funcall modu))
+
+ (ert-info ("Change up the order")
+ (should
+ (equal (funcall modu)
+ '(0 ":irc.example.org 366 alice #chan :End of NAMES list")))
+ (should
+ (equal (funcall user)
+ '(0 ":irc.example.org 422 tester :MOTD File is missing"))))
+
+ ;; Exhaust these
+ (should (equal (cl-loop for s = (funcall pass) while s collect s) ; done
+ '((pass 10.0 "PASS " (? ?:) "changeme"))))
+ (should (equal (cl-loop for s = (funcall nick) while s collect s) ; done
+ '((nick 0.2 "NICK tester"))))
+
+ (ert-info ("End of file but no teardown because hunks outstanding")
+ (should-not (erc-d-u--read-dialog exes))
+ (should (get-buffer "basic.eld")))
+
+ ;; Finish
+ (should-not (funcall user))
+ (should-not (funcall modu)))
+
+ (should-not (get-buffer "basic.eld"))
+ (should-not erc-d-u--canned-buffers))
+
+;; This indirectly tests `erc-d-u--canned-read' cleanup/teardown
+
+(ert-deftest erc-d-u--rewrite-for-slow-mo ()
+ (should-not (get-buffer "basic.eld"))
+ (should-not (get-buffer "basic.eld<2>"))
+ (should-not (get-buffer "basic.eld<3>"))
+ (should-not erc-d-u--canned-buffers)
+ (let ((exes (erc-d-u--canned-load-dialog 'basic))
+ (exes-lower (erc-d-u--canned-load-dialog 'basic))
+ (exes-custom (erc-d-u--canned-load-dialog 'basic))
+ (reap (lambda (e) (cl-loop with p = (erc-d-u--read-dialog e)
+ for s = (erc-d-u--read-exchange p)
+ while s collect s))))
+ (should (get-buffer "basic.eld"))
+ (should (get-buffer "basic.eld<2>"))
+ (should (get-buffer "basic.eld<3>"))
+ (should (equal (list (get-buffer "basic.eld<3>")
+ (get-buffer "basic.eld<2>")
+ (get-buffer "basic.eld"))
+ erc-d-u--canned-buffers))
+
+ (ert-info ("Rewrite for slowmo basic")
+ (setq exes (erc-d-u--rewrite-for-slow-mo 10 exes))
+ (should (equal (funcall reap exes)
+ '((pass 20.0 "PASS " (? ?:) "changeme"))))
+ (should (equal (funcall reap exes)
+ '((nick 10.2 "NICK tester"))))
+ (let ((r (funcall reap exes)))
+ (should (equal (car r) '(user 10.2 "USER user 0 * :tester")))
+ (should (equal
+ (car (last r))
+ '(0 ":irc.example.org 422 tester :MOTD File is missing"))))
+ (should (equal (car (funcall reap exes))
+ '(mode-user 15 "MODE tester +i")))
+ (should (equal (car (funcall reap exes))
+ '(mode-chan 11.2 "MODE #chan")))
+ (should-not (erc-d-u--read-dialog exes)))
+
+ (ert-info ("Rewrite for slowmo bounded")
+ (setq exes-lower (erc-d-u--rewrite-for-slow-mo -5 exes-lower))
+ (should (equal (funcall reap exes-lower)
+ '((pass 10.0 "PASS " (? ?:) "changeme"))))
+ (should (equal (funcall reap exes-lower)
+ '((nick 5 "NICK tester"))))
+ (should (equal (car (funcall reap exes-lower))
+ '(user 5 "USER user 0 * :tester")))
+ (should (equal (car (funcall reap exes-lower))
+ '(mode-user 5 "MODE tester +i")))
+ (should (equal (car (funcall reap exes-lower))
+ '(mode-chan 5 "MODE #chan")))
+ (should-not (erc-d-u--read-dialog exes-lower)))
+
+ (ert-info ("Rewrite for slowmo custom")
+ (setq exes-custom (erc-d-u--rewrite-for-slow-mo
+ (lambda (n) (* 2 n)) exes-custom))
+ (should (equal (funcall reap exes-custom)
+ '((pass 20.0 "PASS " (? ?:) "changeme"))))
+ (should (equal (funcall reap exes-custom)
+ '((nick 0.4 "NICK tester"))))
+ (should (equal (car (funcall reap exes-custom))
+ '(user 0.4 "USER user 0 * :tester")))
+ (should (equal (car (funcall reap exes-custom))
+ '(mode-user 10 "MODE tester +i")))
+ (should (equal (car (funcall reap exes-custom))
+ '(mode-chan 2.4 "MODE #chan")))
+ (should-not (erc-d-u--read-dialog exes-custom))))
+
+ (should-not (get-buffer "basic.eld"))
+ (should-not (get-buffer "basic.eld<2>"))
+ (should-not (get-buffer "basic.eld<3>"))
+ (should-not erc-d-u--canned-buffers))
+
+(ert-deftest erc-d--active-ex-p ()
+ (let ((ring (make-ring 5)))
+ (ert-info ("Empty ring returns nil for not active")
+ (should-not (erc-d--active-ex-p ring)))
+ (ert-info ("One fuzzy member returns nil for not active")
+ (ring-insert ring (make-erc-d-exchange :tag '~foo))
+ (should-not (erc-d--active-ex-p ring)))
+ (ert-info ("One active member returns t for active")
+ (ring-insert-at-beginning ring (make-erc-d-exchange :tag 'bar))
+ (should (erc-d--active-ex-p ring)))))
+
+(defun erc-d-tests--parse-message-upstream (raw)
+ "Hack shim for parsing RAW line recvd from peer."
+ (cl-letf (((symbol-function #'erc-handle-parsed-server-response)
+ (lambda (_ p) p)))
+ (let ((erc-active-buffer nil))
+ (erc-parse-server-response nil raw))))
+
+(ert-deftest erc-d-i--validate-tags ()
+ (should (erc-d-i--validate-tags
+ (concat "batch=4cc99692bf24a4bec4aa03da437364f5;"
+ "time=2021-01-04T00:32:13.839Z")))
+ (should (erc-d-i--validate-tags "+foo=bar;baz=spam"))
+ (should (erc-d-i--validate-tags "foo=\\:ok;baz=\\s"))
+ (should (erc-d-i--validate-tags "foo=\303\247edilla"))
+ (should (erc-d-i--validate-tags "foo=\\"))
+ (should (erc-d-i--validate-tags "foo=bar\\baz"))
+ (should-error (erc-d-i--validate-tags "foo=\\\\;baz=\\\r\\\n"))
+ (should-error (erc-d-i--validate-tags "foo=\n"))
+ (should-error (erc-d-i--validate-tags "foo=\0ok"))
+ (should-error (erc-d-i--validate-tags "foo=bar baz"))
+ (should-error (erc-d-i--validate-tags "foo=bar\r"))
+ (should-error (erc-d-i--validate-tags "foo=bar;")))
+
+(ert-deftest erc-d-i--parse-message ()
+ (let* ((raw (concat "@time=2020-11-23T09:10:33.088Z "
+ ":tilde.chat BATCH +1 chathistory :#meta"))
+ (upstream (erc-d-tests--parse-message-upstream raw))
+ (ours (erc-d-i--parse-message raw)))
+
+ (ert-info ("Baseline upstream")
+ (should (equal (erc-response.unparsed upstream) raw))
+ (should (equal (erc-response.sender upstream) "tilde.chat"))
+ (should (equal (erc-response.command upstream) "BATCH"))
+ (should (equal (erc-response.command-args upstream)
+ '("+1" "chathistory" "#meta")))
+ (should (equal (erc-response.contents upstream) "#meta")))
+
+ (ert-info ("Ours my not compare cl-equalp but is otherwise the same")
+ (should (equal (erc-d-i-message.unparsed ours) raw))
+ (should (equal (erc-d-i-message.sender ours) "tilde.chat"))
+ (should (equal (erc-d-i-message.command ours) "BATCH"))
+ (should (equal (erc-d-i-message.command-args ours)
+ '("+1" "chathistory" "#meta")))
+ (should (equal (erc-d-i-message.contents ours) "#meta"))
+ (should (equal (erc-d-i-message.tags ours)
+ '((time . "2020-11-23T09:10:33.088Z")))))
+
+ (ert-info ("No compat decodes the whole message as utf-8")
+ (setq ours (erc-d-i--parse-message
+ "@foo=\303\247edilla TAGMSG #ch\303\240n"
+ 'decode))
+ (should-not (erc-d-i-message.compat ours))
+ (should (equal (erc-d-i-message.command-args ours) '("#chàn")))
+ (should (equal (erc-d-i-message.contents ours) ""))
+ (should (equal (erc-d-i-message.tags ours) '((foo . "çedilla")))))))
+
+(ert-deftest erc-d-i--unescape-tag-value ()
+ (should (equal (erc-d-i--unescape-tag-value
+ "\\sabc\\sdef\\s\\sxyz\\s")
+ " abc def xyz "))
+ (should (equal (erc-d-i--unescape-tag-value
+ "\\\\abc\\\\def\\\\\\\\xyz\\\\")
+ "\\abc\\def\\\\xyz\\"))
+ (should (equal (erc-d-i--unescape-tag-value "a\\bc") "abc"))
+ (should (equal (erc-d-i--unescape-tag-value
+ "\\\\abc\\\\def\\\\\\\\xyz\\")
+ "\\abc\\def\\\\xyz"))
+ (should (equal (erc-d-i--unescape-tag-value "a\\:b\\r\\nc\\sd")
+ "a;b\r\nc d")))
+
+(ert-deftest erc-d-i--escape-tag-value ()
+ (should (equal (erc-d-i--escape-tag-value " abc def xyz ")
+ "\\sabc\\sdef\\s\\sxyz\\s"))
+ (should (equal (erc-d-i--escape-tag-value "\\abc\\def\\\\xyz\\")
+ "\\\\abc\\\\def\\\\\\\\xyz\\\\"))
+ (should (equal (erc-d-i--escape-tag-value "a;b\r\nc d")
+ "a\\:b\\r\\nc\\sd")))
+
+;; TODO add tests for msg-join, mask-match, userhost-split,
+;; validate-hostname
+
+(ert-deftest erc-d-i--parse-message--irc-parser-tests ()
+ (let* ((data (with-temp-buffer
+ (insert-file-contents
+ (expand-file-name "irc-parser-tests.eld"
+ (ert-resource-directory)))
+ (read (current-buffer))))
+ (tests (assoc-default 'tests (assoc-default 'msg-split data)))
+ input atoms m ours)
+ (dolist (test tests)
+ (setq input (assoc-default 'input test)
+ atoms (assoc-default 'atoms test)
+ m (erc-d-i--parse-message input))
+ (ert-info ("Parses tags correctly")
+ (setq ours (erc-d-i-message.tags m))
+ (if-let ((tags (assoc-default 'tags atoms)))
+ (pcase-dolist (`(,key . ,value) ours)
+ (should (string= (cdr (assq key tags)) (or value ""))))
+ (should-not ours)))
+ (ert-info ("Parses verbs correctly")
+ (setq ours (erc-d-i-message.command m))
+ (if-let ((verbs (assoc-default 'verb atoms)))
+ (should (string= (downcase verbs) (downcase ours)))
+ (should (string-empty-p ours))))
+ (ert-info ("Parses sources correctly")
+ (setq ours (erc-d-i-message.sender m))
+ (if-let ((source (assoc-default 'source atoms)))
+ (should (string= source ours))
+ (should (string-empty-p ours))))
+ (ert-info ("Parses params correctly")
+ (setq ours (erc-d-i-message.command-args m))
+ (if-let ((params (assoc-default 'params atoms)))
+ (should (equal ours params))
+ (should-not ours))))))
+
+(defun erc-d-tests--new-ex (existing raw-hunk)
+ (let* ((f (lambda (_) (pop raw-hunk)))
+ (sd (make-erc-d-u-scan-d :f f)))
+ (setf (erc-d-exchange-hunk existing) (make-erc-d-u-scan-e :sd sd)
+ (erc-d-exchange-spec existing) (make-erc-d-spec)))
+ (erc-d--iter existing))
+
+(ert-deftest erc-d--render-entries ()
+ (let* ((erc-nick "foo")
+ (dialog (make-erc-d-dialog :vars `((:a . 1)
+ (c . ((a b) (: a space b)))
+ (d . (c alpha digit))
+ (bee . 2)
+ (f . ,(lambda () "3"))
+ (i . erc-nick))))
+ (exchange (make-erc-d-exchange :dialog dialog))
+ (mex (apply-partially #'erc-d-tests--new-ex exchange))
+ it)
+
+ (erc-d-exchange-reload dialog exchange)
+
+ (ert-info ("Baseline Outgoing")
+ (setq it (funcall mex '((0 "abc"))))
+ (should (equal (funcall it) 0))
+ (should (equal (funcall it) "abc")))
+
+ (ert-info ("Incoming are regexp escaped")
+ (setq it (funcall mex '((i 0.0 "fsf" ".org"))))
+ (should (equal (cons (funcall it) (funcall it)) '(i . 0.0)))
+ (should (equal (funcall it) "\\`fsf\\.org")))
+
+ (ert-info ("Incoming can access vars via rx-let")
+ (setq it (funcall mex '((i 0.0 bee))))
+ (should (equal (cons (funcall it) (funcall it)) '(i . 0.0)))
+ (should (equal (funcall it) "\\`\002")))
+
+ (ert-info ("Incoming rx-let params")
+ (setq it (funcall mex '((i 0.0 d))))
+ (should (equal (cons (funcall it) (funcall it)) '(i . 0.0)))
+ (should (equal (funcall it) "\\`[[:alpha:]][[:space:]][[:digit:]]")))
+
+ (ert-info ("Incoming literal rx forms")
+ (setq it (funcall mex '((i 0.0 (= 3 alpha) ".org"))))
+ (should (equal (cons (funcall it) (funcall it)) '(i . 0.0)))
+ (should (equal (funcall it) "\\`[[:alpha:]]\\{3\\}\\.org")))
+
+ (ert-info ("Self-quoting disallowed")
+ (setq it (funcall mex '((0 :a "abc"))))
+ (should (equal (funcall it) 0))
+ (should-error (funcall it)))
+
+ (ert-info ("Global vars and short vars")
+ (setq it (funcall mex '((0 i f erc-nick))))
+ (should (equal (funcall it) 0))
+ (should (equal (funcall it) "foo3foo")))
+
+ (ert-info ("Exits clean")
+ (when (listp (alist-get 'f (erc-d-dialog-vars dialog))) ; may be compiled
+ (should (eq 'closure (car (alist-get 'f (erc-d-dialog-vars dialog))))))
+ (should-not (funcall it))
+ (should (equal (erc-d-dialog-vars dialog)
+ `((:a . 1)
+ (c . ((a b) (: a space b)))
+ (d . (c alpha digit))
+ (bee . 2)
+ (f . ,(alist-get 'f (erc-d-dialog-vars dialog)))
+ (i . erc-nick)))))))
+
+(ert-deftest erc-d--render-entries--matches ()
+ (let* ((alist (list
+ (cons 'f (lambda (a) (funcall a :match 1)))
+ (cons 'g (lambda () (match-string 2 "foo bar baz")))
+ (cons 'h (lambda (a) (concat (funcall a :match 0)
+ (funcall a :request))))
+ (cons 'i (lambda (_ e) (erc-d-exchange-request e)))
+ (cons 'j (lambda ()
+ (set-match-data '(0 1))
+ (match-string 0 "j")))))
+ (dialog (make-erc-d-dialog :vars alist))
+ (exchange (make-erc-d-exchange :dialog dialog
+ :request "foo bar baz"
+ ;; 11 222
+ :match-data '(4 11 4 6 8 11)))
+ (mex (apply-partially #'erc-d-tests--new-ex exchange))
+ it)
+
+ (erc-d-exchange-reload dialog exchange)
+
+ (ert-info ("One arg, match")
+ (setq it (funcall mex '((0 f))))
+ (should (equal (funcall it) 0))
+ (should (equal (funcall it) "ba")))
+
+ (ert-info ("No args")
+ (setq it (funcall mex '((0 g))))
+ (should (equal (funcall it) 0))
+ (should (equal (funcall it) "baz")))
+
+ (ert-info ("Second arg is exchange object")
+ (setq it (funcall mex '((0 i))))
+ (should (equal (funcall it) 0))
+ (should (equal (funcall it) "foo bar baz")))
+
+ (ert-info ("One arg, multiple calls")
+ (setq it (funcall mex '((0 h))))
+ (should (equal (funcall it) 0))
+ (should (equal (funcall it) "bar bazfoo bar baz")))
+
+ (ert-info ("Match data restored")
+ (setq it (funcall mex '((0 j))))
+ (should (equal (funcall it) 0))
+ (should (equal (funcall it) "j"))
+
+ (setq it (funcall mex '((0 g))))
+ (should (equal (funcall it) 0))
+ (should (equal (funcall it) "baz")))
+
+ (ert-info ("Bad signature")
+ (let ((qlist (list 'f '(lambda (p q x) (ignore)))))
+ (setf (erc-d-dialog-vars dialog) qlist)
+ (should-error (erc-d-exchange-reload dialog exchange))))))
+
+(ert-deftest erc-d--render-entries--dynamic ()
+ (let* ((alist (list
+ (cons 'foo "foo")
+ (cons 'f (lambda (a) (funcall a :get-binding 'foo)))
+ (cons 'h (lambda (a) (upcase (funcall a :get-var 'foo))))
+ (cons 'g (lambda (a)
+ (funcall a :rebind 'g (funcall a :get-var 'f))
+ "bar"))
+ (cons 'j (lambda (a) (funcall a :set "123") "abc"))
+ (cons 'k (lambda () "abc"))))
+ (dialog (make-erc-d-dialog :vars alist))
+ (exchange (make-erc-d-exchange :dialog dialog))
+ (mex (apply-partially #'erc-d-tests--new-ex exchange))
+ it)
+
+ (erc-d-exchange-reload dialog exchange)
+
+ (ert-info ("Initial reference calls function")
+ (setq it (funcall mex '((0 j) (0 j))))
+ (should (equal (funcall it) 0))
+ (should (equal (funcall it) "abc")))
+
+ (ert-info ("Subsequent reference expands to string")
+ (should (equal (funcall it) 0))
+ (should (equal (funcall it) "123")))
+
+ (ert-info ("Outside manipulation: initial reference calls function")
+ (setq it (funcall mex '((0 k) (0 k))))
+ (should (equal (funcall it) 0))
+ (should (equal (funcall it) "abc")))
+
+ (ert-info ("Outside manipulation: subsequent reference expands to string")
+ (erc-d-exchange-rebind dialog exchange 'k "123")
+ (should (equal (funcall it) 0))
+ (should (equal (funcall it) "123")))
+
+ (ert-info ("Swap one function for another")
+ (setq it (funcall mex '((0 g) (0 g))))
+ (should (equal (funcall it) 0))
+ (should (equal (funcall it) "bar"))
+ (should (equal (funcall it) 0))
+ (should (equal (funcall it) "foo")))
+
+ (ert-info ("Bindings accessible inside functions")
+ (setq it (funcall mex '((0 f h))))
+ (should (equal (funcall it) 0))
+ (should (equal (funcall it) "fooFOO")))
+
+ (ert-info ("Rebuild alist by sending flag")
+ (setq it (funcall mex '((0 f) (1 f) (2 f) (i 3 f))))
+ (should (equal (funcall it) 0))
+ (should (equal (funcall it) "foo"))
+ (erc-d-exchange-rebind dialog exchange 'f "bar")
+ (should (equal (funcall it) 1))
+ (should (equal (funcall it) "bar"))
+ (setq alist (setf (alist-get 'f (erc-d-dialog-vars dialog))
+ (lambda nil "baz")))
+ (should (eq (funcall it) 2))
+ (should (equal (funcall it 'reload) "baz"))
+ (setq alist (setf (alist-get 'f (erc-d-dialog-vars dialog)) "spam"))
+ (should (eq (funcall it) 'i))
+ (should (eq (funcall it 'reload) 3))
+ (should (equal (funcall it) "\\`spam")))))
+
+(ert-deftest erc-d-t-with-cleanup ()
+ (should-not (get-buffer "*echo*"))
+ (should-not (get-buffer "*foo*"))
+ (should-not (get-buffer "*bar*"))
+ (should-not (get-buffer "*baz*"))
+ (erc-d-t-with-cleanup
+ ((echo (start-process "echo" (get-buffer-create "*echo*") "sleep" "1"))
+ (buffer-foo (get-buffer-create "*foo*"))
+ (buffer-bar (get-buffer-create "*bar*"))
+ (clean-up (list (intern (process-name echo)))) ; let*
+ buffer-baz)
+ (ert-info ("Clean Up")
+ (should (equal clean-up '(ran echo)))
+ (should (bufferp buffer-baz))
+ (should (bufferp buffer-foo))
+ (setq buffer-foo nil))
+ (setq buffer-baz (get-buffer-create "*baz*"))
+ (push 'ran clean-up))
+ (ert-info ("Buffers and procs destroyed")
+ (should-not (get-buffer "*echo*"))
+ (should-not (get-buffer "*bar*"))
+ (should-not (get-buffer "*baz*")))
+ (ert-info ("Buffer foo spared")
+ (should (get-buffer "*foo*"))
+ (kill-buffer "*foo*")))
+
+(ert-deftest erc-d-t-wait-for ()
+ :tags '(:unstable)
+ (let (v)
+ (run-at-time 0.2 nil (lambda () (setq v t)))
+ (should (erc-d-t-wait-for 0.4 "result becomes non-nil" v))
+ (should-error (erc-d-t-wait-for 0.4 "result stays nil" (not v)))
+ (setq v nil)
+ (should-not (erc-d-t-wait-for -0.4 "inverted stays nil" v))
+ (run-at-time 0.2 nil (lambda () (setq v t)))
+ (setq v nil)
+ (should-error (erc-d-t-wait-for -0.4 "inverted becomes non-nil" v))))
+
+(defvar erc-d-tests-with-server-password "changeme")
+
+;; Compromise between removing `autojoin' from `erc-modules' entirely
+;; and allowing side effects to meddle excessively
+(defvar erc-autojoin-channels-alist)
+
+;; This is only meant to be used by tests in this file.
+(cl-defmacro erc-d-tests-with-server ((dumb-server-var erc-server-buffer-var)
+ dialog &rest body)
+ "Create server for DIALOG and run BODY.
+DIALOG may also be a list of dialogs. ERC-SERVER-BUFFER-VAR and
+DUMB-SERVER-VAR are bound accordingly in BODY."
+ (declare (indent 2))
+ (when (eq '_ dumb-server-var)
+ (setq dumb-server-var (make-symbol "dumb-server-var")))
+ (when (eq '_ erc-server-buffer-var)
+ (setq erc-server-buffer-var (make-symbol "erc-server-buffer-var")))
+ (if (listp dialog)
+ (setq dialog (mapcar (lambda (f) (list 'quote f)) dialog))
+ (setq dialog `((quote ,dialog))))
+ `(let* (auth-source-do-cache
+ (,dumb-server-var (erc-d-run "localhost" t ,@dialog))
+ ,erc-server-buffer-var
+ ;;
+ (erc-server-flood-penalty 0.05)
+ erc-autojoin-channels-alist
+ erc-server-auto-reconnect)
+ (should-not erc-d--slow-mo)
+ (with-current-buffer "*erc-d-server*" (erc-d-t-search-for 4 "Starting"))
+ ;; Allow important messages through, even in -batch mode.
+ (advice-add #'erc-handle-login :around #'erc-d-t-silence-around)
+ (advice-add #'erc-server-connect :around #'erc-d-t-silence-around)
+ (unless (or noninteractive erc-debug-irc-protocol)
+ (erc-toggle-debug-irc-protocol))
+ (setq ,erc-server-buffer-var
+ (erc :server "localhost"
+ :password erc-d-tests-with-server-password
+ :port (process-contact ,dumb-server-var :service)
+ :nick "tester"
+ :full-name "tester"))
+ (unwind-protect
+ (progn
+ ,@body
+ (erc-d-t-wait-for 1 "dumb-server death"
+ (not (process-live-p ,dumb-server-var))))
+ (when (process-live-p erc-server-process)
+ (delete-process erc-server-process))
+ (advice-remove #'erc-handle-login #'erc-d-t-silence-around)
+ (advice-remove #'erc-server-connect #'erc-d-t-silence-around)
+ (when noninteractive
+ (kill-buffer ,erc-server-buffer-var)
+ (erc-d-t-kill-related-buffers)))))
+
+(defmacro erc-d-tests-with-failure-spy (found func-syms &rest body)
+ "Wrap functions with advice for inspecting errors caused by BODY.
+Do this for functions whose names appear in FUNC-SYMS. When running
+advice code, add errors to list FOUND. Note: the teardown finalizer is
+not added by default. Also, `erc-d-linger-secs' likely has to be
+nonzero for this to work."
+ (declare (indent 2))
+ ;; Catch errors thrown by timers that `should-error'ignores
+ `(progn
+ (let ((ad (lambda (f o &rest r)
+ (condition-case err
+ (apply o r)
+ (error (push err ,found)
+ (advice-remove f 'spy))))))
+ (dolist (sym ,func-syms)
+ (advice-add sym :around (apply-partially ad sym) '((name . spy)))))
+ (progn ,@body)
+ (dolist (sym ,func-syms)
+ (advice-remove sym 'spy))
+ (setq ,found (nreverse ,found))))
+
+(ert-deftest erc-d-run-nonstandard-messages ()
+ :tags '(:expensive-test)
+ (let* ((erc-d-linger-secs 0.2)
+ (dumb-server (erc-d-run "localhost" t 'nonstandard))
+ (dumb-server-buffer (get-buffer "*erc-d-server*"))
+ (expect (erc-d-t-make-expecter))
+ client)
+ (with-current-buffer "*erc-d-server*" (erc-d-t-search-for 4 "Starting"))
+ (setq client (open-network-stream "erc-d-client" nil
+ "localhost"
+ (process-contact dumb-server :service)
+ :coding 'binary))
+ (ert-info ("Server splits CRLF delimited lines")
+ (process-send-string client "ONE one\r\nTWO two\r\n")
+ (with-current-buffer dumb-server-buffer
+ (funcall expect 1 '(: "<- nonstandard:" (+ digit) " ONE one" eol))
+ (funcall expect 1 '(regex "<- nonstandard:[[:digit:]]+ TWO two$"))))
+ (ert-info ("Server doesn't discard empty lines")
+ (process-send-string client "\r\n")
+ (with-current-buffer dumb-server-buffer
+ (funcall expect 1 '(regex "<- nonstandard:[[:digit:]]+ $"))))
+ (ert-info ("Server preserves spaces")
+ (process-send-string client " \r\n")
+ (with-current-buffer dumb-server-buffer
+ (funcall expect 1 '(regex "<- nonstandard:[[:digit:]]+ \\{2\\}$")))
+ (process-send-string client " \r\n")
+ (with-current-buffer dumb-server-buffer
+ (funcall expect 1 '(regex "<- nonstandard:[[:digit:]]+ \\{3\\}$"))))
+ (erc-d-t-wait-for 3 "dumb-server death"
+ (not (process-live-p dumb-server)))
+ (delete-process client)
+ (when noninteractive
+ (kill-buffer dumb-server-buffer))))
+
+(ert-deftest erc-d-run-basic ()
+ :tags '(:expensive-test)
+ (erc-d-tests-with-server (_ _) basic
+ (with-current-buffer (erc-d-t-wait-for 3 (get-buffer "#chan"))
+ (erc-d-t-search-for 2 "hey"))
+ (when noninteractive
+ (kill-buffer "#chan"))))
+
+(ert-deftest erc-d-run-eof ()
+ :tags '(:expensive-test)
+ (skip-unless noninteractive)
+ (erc-d-tests-with-server (_ erc-s-buf) eof
+ (with-current-buffer (erc-d-t-wait-for 3 (get-buffer "#chan"))
+ (erc-d-t-search-for 2 "hey"))
+ (with-current-buffer erc-s-buf
+ (process-send-eof erc-server-process))))
+
+(ert-deftest erc-d-run-eof-fail ()
+ :tags '(:expensive-test)
+ (let (errors)
+ (erc-d-tests-with-failure-spy errors '(erc-d--teardown)
+ (erc-d-tests-with-server (_ _) eof
+ (with-current-buffer (erc-d-t-wait-for 5 (get-buffer "#chan"))
+ (erc-d-t-search-for 2 "hey"))
+ (erc-d-t-wait-for 10 errors)))
+ (should (string-match-p "Timed out awaiting request.*__EOF__"
+ (cadr (pop errors))))))
+
+(ert-deftest erc-d-run-linger ()
+ :tags '(:unstable :expensive-test)
+ (erc-d-tests-with-server (dumb-s _) linger
+ (with-current-buffer (erc-d-t-wait-for 6 (get-buffer "#chan"))
+ (erc-d-t-search-for 2 "hey"))
+ (with-current-buffer (process-buffer dumb-s)
+ (erc-d-t-search-for 2 "Lingering for 1.00 seconds"))
+ (with-current-buffer (process-buffer dumb-s)
+ (erc-d-t-search-for 3 "Lingered for 1.00 seconds"))))
+
+(ert-deftest erc-d-run-linger-fail ()
+ :tags '(:unstable :expensive-test)
+ (let ((erc-server-flood-penalty 0.1)
+ errors)
+ (erc-d-tests-with-failure-spy
+ errors '(erc-d--teardown erc-d-command)
+ (erc-d-tests-with-server (_ _) linger
+ (with-current-buffer (erc-d-t-wait-for 5 (get-buffer "#chan"))
+ (erc-d-t-search-for 2 "hey")
+ (erc-cmd-MSG "#chan hi"))
+ (erc-d-t-wait-for 10 "Bad match" errors)))
+ (should (string-match-p "Match failed.*hi" (cadr (pop errors))))))
+
+(ert-deftest erc-d-run-linger-direct ()
+ :tags '(:unstable :expensive-test)
+ (let* ((dumb-server (erc-d-run "localhost" t
+ 'linger-multi-a 'linger-multi-b))
+ (port (process-contact dumb-server :service))
+ (dumb-server-buffer (get-buffer "*erc-d-server*"))
+ (client-buffer-a (get-buffer-create "*erc-d-client-a*"))
+ (client-buffer-b (get-buffer-create "*erc-d-client-b*"))
+ (start (current-time))
+ client-a client-b)
+ (with-current-buffer "*erc-d-server*" (erc-d-t-search-for 4 "Starting"))
+ (setq client-a (open-network-stream "erc-d-client-a" client-buffer-a
+ "localhost" port
+ :coding 'binary)
+ client-b (open-network-stream "erc-d-client-b" client-buffer-b
+ "localhost" port
+ :coding 'binary))
+ (process-send-string client-a "PASS :a\r\n")
+ (sleep-for 0.01)
+ (process-send-string client-b "PASS :b\r\n")
+ (sleep-for 0.01)
+ (erc-d-t-wait-for 3 "dumb-server death"
+ (not (process-live-p dumb-server)))
+ (ert-info ("Ensure linger of one second")
+ (should (time-less-p 1 (time-subtract (current-time) start)))
+ (should (time-less-p (time-subtract (current-time) start) 1.5)))
+ (delete-process client-a)
+ (delete-process client-b)
+ (when noninteractive
+ (kill-buffer client-buffer-a)
+ (kill-buffer client-buffer-b)
+ (kill-buffer dumb-server-buffer))))
+
+(ert-deftest erc-d-run-drop-direct ()
+ :tags '(:unstable)
+ (let* ((dumb-server (erc-d-run "localhost" t 'drop-a 'drop-b))
+ (port (process-contact dumb-server :service))
+ (dumb-server-buffer (get-buffer "*erc-d-server*"))
+ (client-buffer-a (get-buffer-create "*erc-d-client-a*"))
+ (client-buffer-b (get-buffer-create "*erc-d-client-b*"))
+ (start (current-time))
+ client-a client-b)
+ (with-current-buffer "*erc-d-server*" (erc-d-t-search-for 4 "Starting"))
+ (setq client-a (open-network-stream "erc-d-client-a" client-buffer-a
+ "localhost" port
+ :coding 'binary)
+ client-b (open-network-stream "erc-d-client-b" client-buffer-b
+ "localhost" port
+ :coding 'binary))
+ (process-send-string client-a "PASS :a\r\n")
+ (sleep-for 0.01)
+ (process-send-string client-b "PASS :b\r\n")
+ (erc-d-t-wait-for 3 "client-a dies" (not (process-live-p client-a)))
+ (should (time-less-p (time-subtract (current-time) start) 0.32))
+ (erc-d-t-wait-for 3 "dumb-server death"
+ (not (process-live-p dumb-server)))
+ (ert-info ("Ensure linger of one second")
+ (should (time-less-p 1 (time-subtract (current-time) start))))
+ (delete-process client-a)
+ (delete-process client-b)
+ (when noninteractive
+ (kill-buffer client-buffer-a)
+ (kill-buffer client-buffer-b)
+ (kill-buffer dumb-server-buffer))))
+
+(ert-deftest erc-d-run-no-match ()
+ :tags '(:expensive-test)
+ (let ((erc-d-linger-secs 1)
+ erc-server-auto-reconnect
+ errors)
+ (erc-d-tests-with-failure-spy errors '(erc-d--teardown erc-d-command)
+ (erc-d-tests-with-server (_ erc-server-buffer) no-match
+ (with-current-buffer erc-server-buffer
+ (erc-d-t-search-for 2 "away")
+ (erc-cmd-JOIN "#foo")
+ (erc-d-t-wait-for 10 "Bad match" errors))))
+ (should (string-match-p "Match failed.*foo.*chan" (cadr (pop errors))))
+ (should-not (get-buffer "#foo"))))
+
+(ert-deftest erc-d-run-timeout ()
+ :tags '(:expensive-test)
+ (let ((erc-d-linger-secs 1)
+ err errors)
+ (erc-d-tests-with-failure-spy errors '(erc-d--teardown)
+ (erc-d-tests-with-server (_ _) timeout
+ (erc-d-t-wait-for 10 "error caught" errors)))
+ (setq err (pop errors))
+ (should (eq (car err) 'erc-d-timeout))
+ (should (string-match-p "Timed out" (cadr err)))))
+
+(ert-deftest erc-d-run-unexpected ()
+ :tags '(:expensive-test)
+ (let ((erc-d-linger-secs 2)
+ errors)
+ (erc-d-tests-with-failure-spy
+ errors '(erc-d--teardown erc-d-command)
+ (erc-d-tests-with-server (_ _) unexpected
+ (ert-info ("All specs consumed when more input arrives")
+ (erc-d-t-wait-for 10 "error caught" (cdr errors)))))
+ (should (string-match-p "unexpected.*MODE" (cadr (pop errors))))
+ ;; Nonsensical normally because func would have already exited when
+ ;; first error was thrown
+ (should (string-match-p "Match failed" (cadr (pop errors))))))
+
+(ert-deftest erc-d-run-unexpected-depleted ()
+ :tags '(:expensive-test)
+ (let ((erc-d-linger-secs 3)
+ errors)
+ (erc-d-tests-with-failure-spy errors '(erc-d--teardown erc-d-command)
+ (let* ((dumb-server-buffer (get-buffer-create "*erc-d-server*"))
+ (dumb-server (erc-d-run "localhost" t 'depleted))
+ (expect (erc-d-t-make-expecter))
+ (client-buf (get-buffer-create "*erc-d-client*"))
+ client-proc)
+ (with-current-buffer dumb-server-buffer
+ (erc-d-t-search-for 3 "Starting"))
+ (setq client-proc (make-network-process
+ :buffer client-buf
+ :name "erc-d-client"
+ :family 'ipv4
+ :noquery t
+ :coding 'binary
+ :service (process-contact dumb-server :service)
+ :host "localhost"))
+ (with-current-buffer dumb-server-buffer
+ (funcall expect 3 "open from"))
+ (process-send-string client-proc "PASS :changeme\r\n")
+ (sleep-for 0.01)
+ (process-send-string client-proc "NICK tester\r\n")
+ (sleep-for 0.01)
+ (process-send-string client-proc "USER user 0 * :tester\r\n")
+ (sleep-for 0.01)
+ (when (process-live-p client-proc)
+ (process-send-string client-proc "BLAH :too much\r\n")
+ (sleep-for 0.01))
+ (with-current-buffer client-buf
+ (funcall expect 3 "Welcome to the Internet"))
+ (erc-d-t-wait-for 2 "dumb-server death"
+ (not (process-live-p dumb-server)))
+ (delete-process client-proc)
+ (when noninteractive
+ (kill-buffer client-buf)
+ (kill-buffer dumb-server-buffer))))
+ (should (string-match-p "unexpected.*BLAH" (cadr (pop errors))))
+ ;; Wouldn't happen IRL
+ (should (string-match-p "unexpected.*BLAH" (cadr (pop errors))))
+ (should-not errors)))
+
+(defun erc-d-tests--dynamic-match-user (_dialog exchange)
+ "Shared pattern/response handler for canned dynamic DIALOG test."
+ (should (string= (match-string 1 (erc-d-exchange-request exchange))
+ "tester")))
+
+(defun erc-d-tests--run-dynamic ()
+ "Perform common assertions for \"dynamic\" dialog."
+ (erc-d-tests-with-server (dumb-server erc-server-buffer) dynamic
+ (with-current-buffer (erc-d-t-wait-for 10 (get-buffer "#chan"))
+ (erc-d-t-search-for 2 "tester: hey"))
+ (with-current-buffer erc-server-buffer
+ (let ((expect (erc-d-t-make-expecter)))
+ (funcall expect 2 "host is irc.fsf.org")
+ (funcall expect 2 "modes for tester")))
+ (with-current-buffer (process-buffer dumb-server)
+ (erc-d-t-search-for 2 "irc.fsf.org"))
+ (when noninteractive
+ (kill-buffer "#chan"))))
+
+(ert-deftest erc-d-run-dynamic-default-match ()
+ :tags '(:expensive-test)
+ (let* (dynamic-tally
+ (erc-d-tmpl-vars '((user . "user")
+ (ignored . ((a b) (: a space b)))
+ (realname . (group (+ graph)))))
+ (nick (lambda (a)
+ (push '(nick . match-user) dynamic-tally)
+ (funcall a :set (funcall a :match 1) 'export)))
+ (dom (lambda (a)
+ (push '(dom . match-user) dynamic-tally)
+ (funcall a :set erc-d-server-fqdn)))
+ (erc-d-match-handlers
+ (list :user (lambda (d e)
+ (erc-d-exchange-rebind d e 'nick nick)
+ (erc-d-exchange-rebind d e 'dom dom)
+ (erc-d-tests--dynamic-match-user d e))
+ :mode-user (lambda (d e)
+ (erc-d-exchange-rebind d e 'nick "tester")
+ (erc-d-exchange-rebind d e 'dom dom))))
+ (erc-d-server-fqdn "irc.fsf.org"))
+ (erc-d-tests--run-dynamic)
+ (should (equal '((dom . match-user) (nick . match-user) (dom . match-user))
+ dynamic-tally))))
+
+(ert-deftest erc-d-run-dynamic-default-match-rebind ()
+ :tags '(:expensive-test)
+ (let* (tally
+ ;;
+ (erc-d-tmpl-vars '((user . "user")
+ (ignored . ((a b) (: a space b)))
+ (realname . (group (+ graph)))))
+ (erc-d-match-handlers
+ (list :user
+ (lambda (d e)
+ (erc-d-exchange-rebind
+ d e 'nick
+ (lambda (a)
+ (push 'bind-nick tally)
+ (funcall a :rebind 'nick (funcall a :match 1) 'export)))
+ (erc-d-exchange-rebind
+ d e 'dom
+ (lambda ()
+ (push 'bind-dom tally)
+ (erc-d-exchange-rebind d e 'dom erc-d-server-fqdn)))
+ (erc-d-tests--dynamic-match-user d e))
+ :mode-user
+ (lambda (d e)
+ (erc-d-exchange-rebind d e 'nick "tester")
+ (erc-d-exchange-rebind d e 'dom erc-d-server-fqdn))))
+ (erc-d-server-fqdn "irc.fsf.org"))
+ (erc-d-tests--run-dynamic)
+ (should (equal '(bind-nick bind-dom) tally))))
+
+(ert-deftest erc-d-run-dynamic-runtime-stub ()
+ :tags '(:expensive-test)
+ (let ((erc-d-tmpl-vars '((token . (group (or "barnet" "foonet")))))
+ (erc-d-match-handlers
+ (list :pass (lambda (d _e)
+ (erc-d-load-replacement-dialog d 'dynamic-foonet))))
+ (erc-d-tests-with-server-password "foonet:changeme"))
+ (erc-d-tests-with-server (_ erc-server-buffer)
+ (dynamic-stub dynamic-foonet)
+ (with-current-buffer (erc-d-t-wait-for 3 (get-buffer "#chan"))
+ (erc-d-t-search-for 2 "alice:")
+ (erc-d-t-absent-for 0.1 "joe"))
+ (with-current-buffer erc-server-buffer
+ (let ((expect (erc-d-t-make-expecter)))
+ (funcall expect 2 "host is irc.foonet.org")
+ (funcall expect 2 "NETWORK=FooNet")))
+ (when noninteractive
+ (kill-buffer "#chan")))))
+
+(ert-deftest erc-d-run-dynamic-runtime-stub-skip ()
+ :tags '(:expensive-test)
+ (let ((erc-d-tmpl-vars '((token . "barnet")))
+ (erc-d-match-handlers
+ (list :pass (lambda (d _e)
+ (erc-d-load-replacement-dialog
+ d 'dynamic-barnet 1))))
+ (erc-d-tests-with-server-password "barnet:changeme"))
+ (erc-d-tests-with-server (_ erc-server-buffer)
+ (dynamic-stub dynamic-barnet)
+ (with-current-buffer (erc-d-t-wait-for 3 (get-buffer "#chan"))
+ (erc-d-t-search-for 2 "joe:")
+ (erc-d-t-absent-for 0.1 "alice"))
+ (with-current-buffer erc-server-buffer
+ (let ((expect (erc-d-t-make-expecter)))
+ (funcall expect 2 "host is irc.barnet.org")
+ (funcall expect 2 "NETWORK=BarNet")))
+ (when noninteractive
+ (kill-buffer "#chan")))))
+
+;; Two servers, in-process, one client per
+(ert-deftest erc-d-run-dual-direct ()
+ :tags '(:expensive-test)
+ (let* ((erc-d--slow-mo -1)
+ (server-a (erc-d-run "localhost" t "erc-d-server-a" 'dynamic-foonet))
+ (server-b (erc-d-run "localhost" t "erc-d-server-b" 'dynamic-barnet))
+ (server-a-buffer (get-buffer "*erc-d-server-a*"))
+ (server-b-buffer (get-buffer "*erc-d-server-b*"))
+ (client-a-buffer (get-buffer-create "*erc-d-client-a*"))
+ (client-b-buffer (get-buffer-create "*erc-d-client-b*"))
+ client-a client-b)
+ (with-current-buffer server-a-buffer (erc-d-t-search-for 4 "Starting"))
+ (with-current-buffer server-b-buffer (erc-d-t-search-for 4 "Starting"))
+ (setq client-a (make-network-process
+ :buffer client-a-buffer
+ :name "erc-d-client-a"
+ :family 'ipv4
+ :noquery t
+ :coding 'binary
+ :service (process-contact server-a :service)
+ :host "localhost")
+ client-b (make-network-process
+ :buffer client-b-buffer
+ :name "erc-d-client-b"
+ :family 'ipv4
+ :noquery t
+ :coding 'binary
+ :service (process-contact server-b :service)
+ :host "localhost"))
+ ;; Also tests slo-mo indirectly because FAKE would fail without it
+ (process-send-string client-a "NICK tester\r\n")
+ (process-send-string client-b "FAKE noop\r\nNICK tester\r\n")
+ (sleep-for 0.01)
+ (process-send-string client-a "USER user 0 * :tester\r\n")
+ (process-send-string client-b "USER user 0 * :tester\r\n")
+ (sleep-for 0.01)
+ (process-send-string client-a "MODE tester +i\r\n")
+ (process-send-string client-b "MODE tester +i\r\n")
+ (sleep-for 0.01)
+ (process-send-string client-a "MODE #chan\r\n")
+ (process-send-string client-b "MODE #chan\r\n")
+ (sleep-for 0.01)
+ (erc-d-t-wait-for 2 "server-a death" (not (process-live-p server-a)))
+ (erc-d-t-wait-for 2 "server-b death" (not (process-live-p server-b)))
+ (when noninteractive
+ (kill-buffer client-a-buffer)
+ (kill-buffer client-b-buffer)
+ (kill-buffer server-a-buffer)
+ (kill-buffer server-b-buffer))))
+
+;; This can be removed; only exists to get a baseline for next test
+(ert-deftest erc-d-run-fuzzy-direct ()
+ :tags '(:expensive-test)
+ (let* ((erc-d-tmpl-vars
+ `((now . ,(lambda () (format-time-string "%FT%T.%3NZ" nil t)))))
+ (dumb-server (erc-d-run "localhost" t 'fuzzy))
+ (dumb-server-buffer (get-buffer "*erc-d-server*"))
+ (client-buffer (get-buffer-create "*erc-d-client*"))
+ client)
+ (with-current-buffer "*erc-d-server*" (erc-d-t-search-for 4 "Starting"))
+ (setq client (make-network-process
+ :buffer client-buffer
+ :name "erc-d-client"
+ :family 'ipv4
+ :noquery t
+ :coding 'binary
+ :service (process-contact dumb-server :service)
+ :host "localhost"))
+ ;; We could also just send this as a single fatty
+ (process-send-string client "PASS :changeme\r\n")
+ (sleep-for 0.01)
+ (process-send-string client "NICK tester\r\n")
+ (sleep-for 0.01)
+ (process-send-string client "USER user 0 * :tester\r\n")
+ (sleep-for 0.01)
+ (process-send-string client "MODE tester +i\r\n")
+ (sleep-for 0.01)
+ (process-send-string client "JOIN #bar\r\n")
+ (sleep-for 0.01)
+ (process-send-string client "JOIN #foo\r\n")
+ (sleep-for 0.01)
+ (process-send-string client "MODE #bar\r\n")
+ (sleep-for 0.01)
+ (process-send-string client "MODE #foo\r\n")
+ (sleep-for 0.01)
+ (erc-d-t-wait-for 1 "dumb-server death"
+ (not (process-live-p dumb-server)))
+ (when noninteractive
+ (kill-buffer client-buffer)
+ (kill-buffer dumb-server-buffer))))
+
+;; Without adjusting penalty, takes ~15 secs. With is comparable to direct ^.
+(ert-deftest erc-d-run-fuzzy ()
+ :tags '(:expensive-test)
+ (let ((erc-server-flood-penalty 1.2) ; penalty < margin/sends is basically 0
+ (erc-d-linger-secs 0.1)
+ (erc-d-tmpl-vars
+ `((now . ,(lambda () (format-time-string "%FT%T.%3NZ" nil t)))))
+ erc-server-auto-reconnect)
+ (erc-d-tests-with-server (_ erc-server-buffer) fuzzy
+ (with-current-buffer erc-server-buffer
+ (erc-d-t-search-for 2 "away")
+ (goto-char erc-input-marker)
+ (erc-cmd-JOIN "#bar"))
+ (erc-d-t-wait-for 2 (get-buffer "#bar"))
+ (with-current-buffer erc-server-buffer
+ (erc-cmd-JOIN "#foo"))
+ (erc-d-t-wait-for 20 (get-buffer "#foo"))
+ (with-current-buffer "#bar"
+ (erc-d-t-search-for 1 "was created on"))
+ (with-current-buffer "#foo"
+ (erc-d-t-search-for 5 "was created on")))))
+
+(ert-deftest erc-d-run-no-block ()
+ :tags '(:expensive-test)
+ (let ((erc-server-flood-penalty 1)
+ (erc-d-linger-secs 1.2)
+ (expect (erc-d-t-make-expecter))
+ erc-server-auto-reconnect)
+ (erc-d-tests-with-server (_ erc-server-buffer) no-block
+ (with-current-buffer erc-server-buffer
+ (funcall expect 2 "away")
+ (funcall expect 1 erc-prompt)
+ (with-current-buffer erc-server-buffer (erc-cmd-JOIN "#foo")))
+ (with-current-buffer (erc-d-t-wait-for 2 (get-buffer "#foo"))
+ (funcall expect 2 "was created on"))
+
+ (ert-info ("Join #bar")
+ (with-current-buffer erc-server-buffer (erc-cmd-JOIN "#bar"))
+ (erc-d-t-wait-for 2 (get-buffer "#bar")))
+
+ (with-current-buffer "#bar" (funcall expect 1 "was created on"))
+
+ (ert-info ("Server expects next pattern but keeps sending")
+ (with-current-buffer "#foo" (funcall expect 2 "Rosalind, I will "))
+ (with-current-buffer "#bar" (funcall expect 1 "hi 123"))
+ (with-current-buffer "#foo"
+ (should-not (search-forward "<bob> I am heard" nil t))
+ (funcall expect 1.5 "<bob> I am heard"))))))
+
+(defun erc-d-tests--run-proxy-direct (dumb-server dumb-server-buffer port)
+ "Start DUMB-SERVER with DUMB-SERVER-BUFFER and PORT.
+These are steps shared by in-proc and subproc variants testing a
+bouncer-like setup."
+ (when (version< emacs-version "28") (ert-skip "TODO connection refused"))
+ (let ((client-buffer-foo (get-buffer-create "*erc-d-client-foo*"))
+ (client-buffer-bar (get-buffer-create "*erc-d-client-bar*"))
+ (expect (erc-d-t-make-expecter))
+ client-foo
+ client-bar)
+ (setq client-foo (make-network-process
+ :buffer client-buffer-foo
+ :name "erc-d-client-foo"
+ :family 'ipv4
+ :noquery t
+ :coding 'binary
+ :service port
+ :host "localhost")
+ client-bar (make-network-process
+ :buffer client-buffer-bar
+ :name "erc-d-client-bar"
+ :family 'ipv4
+ :noquery t
+ :coding 'binary
+ :service port
+ :host "localhost"))
+ (with-current-buffer dumb-server-buffer
+ (funcall expect 3 "open from"))
+ (process-send-string client-foo "PASS :foo:changeme\r\n")
+ (process-send-string client-bar "PASS :bar:changeme\r\n")
+ (sleep-for 0.01)
+ (process-send-string client-foo "NICK tester\r\n")
+ (process-send-string client-bar "NICK tester\r\n")
+ (sleep-for 0.01)
+ (process-send-string client-foo "USER user 0 * :tester\r\n")
+ (process-send-string client-bar "USER user 0 * :tester\r\n")
+ (sleep-for 0.01)
+ (process-send-string client-foo "MODE tester +i\r\n")
+ (process-send-string client-bar "MODE tester +i\r\n")
+ (sleep-for 0.01)
+ (with-current-buffer client-buffer-foo
+ (funcall expect 3 "FooNet")
+ (funcall expect 3 "irc.foo.net")
+ (funcall expect 3 "marked as being away")
+ (goto-char (point-min))
+ (should-not (search-forward "bar" nil t)))
+ (with-current-buffer client-buffer-bar
+ (funcall expect 3 "BarNet")
+ (funcall expect 3 "irc.bar.net")
+ (funcall expect 3 "marked as being away")
+ (goto-char (point-min))
+ (should-not (search-forward "foo" nil t)))
+ (erc-d-t-wait-for 2 "dumb-server death"
+ (not (process-live-p dumb-server)))
+ (delete-process client-foo)
+ (delete-process client-bar)
+ (when noninteractive
+ (kill-buffer client-buffer-foo)
+ (kill-buffer client-buffer-bar)
+ (kill-buffer dumb-server-buffer))))
+
+;; This test shows the simplest way to set up template variables: put
+;; everything needed for the whole session in `erc-d-tmpl-vars' before
+;; starting the server.
+
+(ert-deftest erc-d-run-proxy-direct-spec-vars ()
+ :tags '(:expensive-test)
+ (let* ((dumb-server-buffer (get-buffer-create "*erc-d-server*"))
+ (erc-d-linger-secs 0.5)
+ (erc-d-tmpl-vars
+ `((network . (group (+ alpha)))
+ (fqdn . ,(lambda (a)
+ (let ((network (funcall a :match 1 'pass)))
+ (should (member network '("foo" "bar")))
+ (funcall a :set (concat "irc." network ".net")))))
+ (net . ,(lambda (a)
+ (let ((network (funcall a :match 1 'pass)))
+ (should (member network '("foo" "bar")))
+ (concat (capitalize network) "Net"))))))
+ (dumb-server (erc-d-run "localhost" t 'proxy-foonet 'proxy-barnet))
+ (port (process-contact dumb-server :service)))
+ (with-current-buffer dumb-server-buffer
+ (erc-d-t-search-for 3 "Starting"))
+ (erc-d-tests--run-proxy-direct dumb-server dumb-server-buffer port)))
+
+(cl-defun erc-d-tests--start-server (&key dialogs buffer linger program libs)
+ "Start and return a server in a subprocess using BUFFER and PORT.
+DIALOGS are symbols representing the base names of dialog files in
+`erc-d-u-canned-dialog-dir'. LIBS are extra files to load."
+ (push (locate-library "erc-d" nil (list erc-d-u--library-directory)) libs)
+ (cl-assert (car libs))
+ (let* ((args `("erc-d-server" ,buffer
+ ,(concat invocation-directory invocation-name)
+ "-Q" "-batch" "-L" ,erc-d-u--library-directory
+ ,@(let (o) (while libs (push (pop libs) o) (push "-l" o)) o)
+ "-eval" ,(format "%S" program) "-f" "erc-d-serve"
+ ,@(when linger (list "--linger" (number-to-string linger)))
+ ,@(mapcar #'erc-d-u--expand-dialog-symbol dialogs)))
+ (proc (apply #'start-process args)))
+ (set-process-query-on-exit-flag proc nil)
+ (with-current-buffer buffer
+ (erc-d-t-search-for 5 "Starting")
+ (search-forward " (")
+ (backward-char))
+ (let ((pair (read buffer)))
+ (cons proc (cdr pair)))))
+
+(ert-deftest erc-d-run-proxy-direct-subprocess ()
+ :tags '(:expensive-test)
+ (let* ((buffer (get-buffer-create "*erc-d-server*"))
+ ;; These are quoted because they're passed as printed forms to subproc
+ (fqdn '(lambda (a e)
+ (let* ((d (erc-d-exchange-dialog e))
+ (name (erc-d-dialog-name d)))
+ (funcall a :set (if (eq name 'proxy-foonet)
+ "irc.foo.net"
+ "irc.bar.net")))))
+ (net '(lambda (a)
+ (funcall a :rebind 'net
+ (if (eq (funcall a :dialog-name) 'proxy-foonet)
+ "FooNet"
+ "BarNet"))))
+ (program `(setq erc-d-tmpl-vars '((fqdn . ,fqdn)
+ (net . ,net)
+ (network . (group (+ alpha))))))
+ (port (erc-d-tests--start-server
+ :linger 0.3
+ :program program
+ :buffer buffer
+ :dialogs '(proxy-foonet proxy-barnet)))
+ (server (pop port)))
+ (erc-d-tests--run-proxy-direct server buffer port)))
+
+(ert-deftest erc-d-run-proxy-direct-subprocess-lib ()
+ :tags '(:expensive-test)
+ (let* ((buffer (get-buffer-create "*erc-d-server*"))
+ (lib (expand-file-name "proxy-subprocess.el"
+ (ert-resource-directory)))
+ (port (erc-d-tests--start-server :linger 0.3
+ :buffer buffer
+ :dialogs '(proxy-foonet proxy-barnet)
+ :libs (list lib)))
+ (server (pop port)))
+ (erc-d-tests--run-proxy-direct server buffer port)))
+
+(ert-deftest erc-d-run-no-pong ()
+ :tags '(:expensive-test)
+ (let* (erc-d-auto-pong
+ ;;
+ (erc-d-tmpl-vars
+ `((nonce . (group (: digit digit)))
+ (echo . ,(lambda (a)
+ (should (string= (funcall a :match 1) "42")) "42"))))
+ (dumb-server-buffer (get-buffer-create "*erc-d-server*"))
+ (dumb-server (erc-d-run "localhost" t 'no-pong))
+ (expect (erc-d-t-make-expecter))
+ (client-buf (get-buffer-create "*erc-d-client*"))
+ client-proc)
+ (with-current-buffer dumb-server-buffer
+ (erc-d-t-search-for 3 "Starting"))
+ (setq client-proc (make-network-process
+ :buffer client-buf
+ :name "erc-d-client"
+ :family 'ipv4
+ :noquery t
+ :coding 'binary
+ :service (process-contact dumb-server :service)
+ :host "localhost"))
+ (with-current-buffer dumb-server-buffer
+ (funcall expect 3 "open from"))
+ (process-send-string client-proc "PASS :changeme\r\nNICK tester\r\n")
+ (sleep-for 0.01)
+ (process-send-string client-proc "USER user 0 * :tester\r\n")
+ (sleep-for 0.01)
+ (process-send-string client-proc "MODE tester +i\r\n")
+ (sleep-for 0.01)
+ (with-current-buffer client-buf
+ (funcall expect 3 "ExampleOrg")
+ (funcall expect 3 "irc.example.org")
+ (funcall expect 3 "marked as being away"))
+ (ert-info ("PING is not intercepted by specialized method")
+ (process-send-string client-proc "PING 42\r\n")
+ (with-current-buffer client-buf
+ (funcall expect 3 "PONG")))
+ (erc-d-t-wait-for 2 "dumb-server death"
+ (not (process-live-p dumb-server)))
+ (delete-process client-proc)
+ (when noninteractive
+ (kill-buffer client-buf)
+ (kill-buffer dumb-server-buffer))))
+
+;; Inspect replies as they arrive within a single exchange, i.e., ensure we
+;; don't regress to prior buggy version in which inspection wasn't possible
+;; until all replies had been sent by the server.
+(ert-deftest erc-d-run-incremental ()
+ :tags '(:expensive-test)
+ (let ((erc-server-flood-penalty 0)
+ (expect (erc-d-t-make-expecter))
+ erc-d-linger-secs)
+ (erc-d-tests-with-server (_ erc-server-buffer) incremental
+ (with-current-buffer erc-server-buffer
+ (funcall expect 3 "marked as being away"))
+ (with-current-buffer erc-server-buffer
+ (erc-cmd-JOIN "#foo"))
+ (with-current-buffer (erc-d-t-wait-for 1 (get-buffer "#foo"))
+ (funcall expect 1 "Users on #foo")
+ (funcall expect 1 "Look for me")
+ (not (search-forward "Done" nil t))
+ (funcall expect 10 "Done")
+ (erc-send-message "Hi")))))
+
+(ert-deftest erc-d-unix-socket-direct ()
+ :tags '(:expensive-test)
+ (skip-unless (featurep 'make-network-process '(:family local)))
+ (let* ((erc-d-linger-secs 0.1)
+ (sock (expand-file-name "erc-d.sock" temporary-file-directory))
+ (dumb-server (erc-d-run nil sock 'basic))
+ (dumb-server-buffer (get-buffer "*erc-d-server*"))
+ (client-buffer (get-buffer-create "*erc-d-client*"))
+ client)
+ (with-current-buffer "*erc-d-server*"
+ (erc-d-t-search-for 4 "Starting"))
+ (unwind-protect
+ (progn
+ (setq client (make-network-process
+ :buffer client-buffer
+ :name "erc-d-client"
+ :family 'local
+ :noquery t
+ :coding 'binary
+ :service sock))
+ (process-send-string client "PASS :changeme\r\n")
+ (sleep-for 0.01)
+ (process-send-string client "NICK tester\r\n")
+ (sleep-for 0.01)
+ (process-send-string client "USER user 0 * :tester\r\n")
+ (sleep-for 0.1)
+ (process-send-string client "MODE tester +i\r\n")
+ (sleep-for 0.01)
+ (process-send-string client "MODE #chan\r\n")
+ (sleep-for 0.01)
+ (erc-d-t-wait-for 1 "dumb-server death"
+ (not (process-live-p dumb-server)))
+ (when noninteractive
+ (kill-buffer client-buffer)
+ (kill-buffer dumb-server-buffer)))
+ (delete-file sock))))
+
+(ert-deftest erc-d-run-direct-foreign-protocol ()
+ :tags '(:expensive-test)
+ (let* ((server (erc-d-run "localhost" t "erc-d-server" 'foreign
+ :ending "\n"))
+ (server-buffer (get-buffer "*erc-d-server*"))
+ (client-buffer (get-buffer-create "*erc-d-client*"))
+ client)
+ (with-current-buffer server-buffer (erc-d-t-search-for 4 "Starting"))
+ (setq client (make-network-process
+ :buffer client-buffer
+ :name "erc-d-client"
+ :family 'ipv4
+ :noquery t
+ :coding 'binary
+ :service (process-contact server :service)
+ :host "localhost"))
+ (process-send-string client "ONE one\n")
+ (with-current-buffer client-buffer
+ (erc-d-t-search-for 5 "echo ONE one"))
+ (process-send-string client "TWO two\n")
+ (with-current-buffer client-buffer
+ (erc-d-t-search-for 2 "echo TWO two"))
+ (erc-d-t-wait-for 2 "server death" (not (process-live-p server)))
+ (when noninteractive
+ (kill-buffer client-buffer)
+ (kill-buffer server-buffer))))
+
+;;; erc-d-tests.el ends here
diff --git a/test/lisp/erc/resources/erc-d/erc-d-u.el b/test/lisp/erc/resources/erc-d/erc-d-u.el
new file mode 100644
index 00000000000..ce13efef624
--- /dev/null
+++ b/test/lisp/erc/resources/erc-d/erc-d-u.el
@@ -0,0 +1,213 @@
+;;; erc-d-u.el --- Helpers for ERC test server -*- lexical-binding: t -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; The utilities here are kept separate from those in `erc-d' so that
+;; tests running the server in a subprocess can use them without
+;; having to require the main lib. If migrating outside of test/lisp,
+;; there may be no reason to continue this.
+;;
+;; Another (perhaps misguided) goal here is to avoid having ERC itself
+;; as a dependency.
+;;
+;; FIXME this ^ is no longer the case (ERC is not a dependency)
+
+;;; Code:
+(require 'rx)
+(require 'subr-x)
+(eval-when-compile (require 'ert))
+
+(defvar erc-d-u--canned-buffers nil
+ "List of canned dialog buffers currently open for reading.")
+
+(cl-defstruct (erc-d-u-scan-d) ; dialog scanner
+ (buf nil :type buffer)
+ (done nil :type boolean)
+ (last nil :type integer)
+ (hunks nil :type (list-of marker))
+ (f #'erc-d-u--read-exchange-default :type function))
+
+(cl-defstruct (erc-d-u-scan-e) ; exchange scanner
+ (sd nil :type erc-d-u-scan-d)
+ (pos nil :type marker))
+
+(defun erc-d-u--read-dialog (info)
+ "Read dialog file and stash relevant state in `erc-d-u-scan-d' INFO."
+ (if (and (buffer-live-p (erc-d-u-scan-d-buf info))
+ (with-current-buffer (erc-d-u-scan-d-buf info)
+ (condition-case _err
+ (progn
+ (when (erc-d-u-scan-d-last info)
+ (goto-char (erc-d-u-scan-d-last info))
+ (forward-list))
+ (setf (erc-d-u-scan-d-last info) (point))
+ (down-list)
+ (push (set-marker (make-marker) (point))
+ (erc-d-u-scan-d-hunks info)))
+ ((end-of-buffer scan-error)
+ (setf (erc-d-u-scan-d-done info) t)
+ nil))))
+ (make-erc-d-u-scan-e :sd info :pos (car (erc-d-u-scan-d-hunks info)))
+ (unless (erc-d-u-scan-d-hunks info)
+ (kill-buffer (erc-d-u-scan-d-buf info))
+ nil)))
+
+(defun erc-d-u--read-exchange-default (info)
+ "Read from marker in exchange `erc-d-u-scan-e' object INFO."
+ (let ((hunks (erc-d-u-scan-e-sd info))
+ (pos (erc-d-u-scan-e-pos info)))
+ (or (and (erc-d-u-scan-d-hunks hunks)
+ (with-current-buffer (erc-d-u-scan-d-buf hunks)
+ (goto-char pos)
+ (condition-case _err
+ (read pos)
+ ;; Raised unless malformed
+ (invalid-read-syntax
+ nil))))
+ (unless (or (cl-callf (lambda (s) (delq pos s)) ; flip
+ (erc-d-u-scan-d-hunks hunks))
+ (not (erc-d-u-scan-d-done hunks)))
+ (kill-buffer (erc-d-u-scan-d-buf hunks))
+ nil))))
+
+(defun erc-d-u--read-exchange (info)
+ "Call exchange reader assigned in `erc-d-u-scan-e' object INFO."
+ (funcall (erc-d-u-scan-d-f (erc-d-u-scan-e-sd info)) info))
+
+(defun erc-d-u--canned-read (file)
+ "Dispense a reader for each exchange in dialog FILE."
+ (let ((buf (generate-new-buffer (file-name-nondirectory file))))
+ (push buf erc-d-u--canned-buffers)
+ (with-current-buffer buf
+ (setq-local parse-sexp-ignore-comments t
+ coding-system-for-read 'utf-8)
+ (add-hook 'kill-buffer-hook
+ (lambda () (setq erc-d-u--canned-buffers
+ (delq buf erc-d-u--canned-buffers)))
+ nil 'local)
+ (insert-file-contents-literally file)
+ (lisp-data-mode))
+ (make-erc-d-u-scan-d :buf buf)))
+
+(defvar erc-d-u--library-directory (file-name-directory load-file-name))
+(defvar erc-d-u-canned-dialog-dir
+ (file-name-as-directory (expand-file-name "resources"
+ erc-d-u--library-directory)))
+
+(defun erc-d-u--normalize-canned-name (dialog)
+ "Return DIALOG name as a symbol without validating it."
+ (if (symbolp dialog)
+ dialog
+ (intern (file-name-base dialog))))
+
+(defvar erc-d-u-canned-file-name-extension ".eld")
+
+(defun erc-d-u--expand-dialog-symbol (dialog)
+ "Return filename based on symbol DIALOG."
+ (let ((name (symbol-name dialog)))
+ (unless (equal (file-name-extension name)
+ erc-d-u-canned-file-name-extension)
+ (setq name (concat name erc-d-u-canned-file-name-extension)))
+ (expand-file-name name erc-d-u-canned-dialog-dir)))
+
+(defun erc-d-u--massage-canned-name (dialog)
+ "Return DIALOG in a form acceptable to `erc-d-run'."
+ (if (or (symbolp dialog) (file-exists-p dialog))
+ dialog
+ (erc-d-u--expand-dialog-symbol (intern dialog))))
+
+(defun erc-d-u--canned-load-dialog (dialog)
+ "Load dispensing exchanges from DIALOG.
+If DIALOG is a string, consider it a filename. Otherwise find a file
+in `erc-d-u-canned-dialog-dir' with a base name matching the symbol's
+name.
+
+Return an iterator that yields exchanges, each one an iterator of spec
+forms. The first is a so-called request spec and the rest are composed
+of zero or more response specs."
+ (when (symbolp dialog)
+ (setq dialog (erc-d-u--expand-dialog-symbol dialog)))
+ (unless (file-exists-p dialog)
+ (error "File not found: %s" dialog))
+ (erc-d-u--canned-read dialog))
+
+(defun erc-d-u--read-exchange-slowly (num orig info)
+ (when-let ((spec (funcall orig info)))
+ (when (symbolp (car spec))
+ (setf spec (copy-sequence spec)
+ (nth 1 spec) (cond ((functionp num) (funcall num (nth 1 spec)))
+ ((< num 0) (max (nth 1 spec) (- num)))
+ (t (+ (nth 1 spec) num)))))
+ spec))
+
+(defun erc-d-u--rewrite-for-slow-mo (num read-info)
+ "Return READ-INFO with a modified reader.
+When NUM is a positive number, delay incoming requests by NUM more
+seconds. If NUM is negative, raise insufficient incoming delays to at
+least -NUM seconds. If NUM is a function, set each delay to whatever it
+returns when called with the existing value."
+ (let ((orig (erc-d-u-scan-d-f read-info)))
+ (setf (erc-d-u-scan-d-f read-info)
+ (apply-partially #'erc-d-u--read-exchange-slowly num orig))
+ read-info))
+
+(defun erc-d-u--get-remote-port (process)
+ "Return peer TCP port for client PROCESS.
+When absent, just generate an id."
+ (let ((remote (plist-get (process-contact process t) :remote)))
+ (if (vectorp remote)
+ (aref remote (1- (length remote)))
+ (format "%s:%d" (process-contact process :local)
+ (logand 1023 (time-convert nil 'integer))))))
+
+(defun erc-d-u--format-bind-address (process)
+ "Return string or (STRING . INT) for bind address of network PROCESS."
+ (let ((local (process-contact process :local)))
+ (if (vectorp local) ; inet
+ (cons (mapconcat #'number-to-string (seq-subseq local 0 -1) ".")
+ (aref local (1- (length local))))
+ local)))
+
+(defun erc-d-u--unkeyword (plist)
+ "Return a copy of PLIST with keywords keys converted to non-keywords."
+ (cl-loop for (key value) on plist by #'cddr
+ when (keywordp key)
+ do (setq key (intern (substring (symbol-name key) 1)))
+ append (list key value)))
+
+(defun erc-d-u--massage-rx-args (key val)
+ " Massage val so it's suitable for an `rx-let' binding.
+Handle cases in which VAL is ([ARGLIST] RX-FORM) rather than just
+RX-FORM. KEY becomes the binding name."
+ (if (and (listp val)
+ (cdr val)
+ (not (cddr val))
+ (consp (car val)))
+ (cons key val)
+ (list key val)))
+
+(defvar-local erc-d-u--process-buffer nil
+ "Beacon for erc-d process buffers.
+The server process is usually deleted first, but we may want to examine
+the buffer afterward.")
+
+(provide 'erc-d-u)
+;;; erc-d-u.el ends here
diff --git a/test/lisp/erc/resources/erc-d/erc-d.el b/test/lisp/erc/resources/erc-d/erc-d.el
new file mode 100644
index 00000000000..d6082227c52
--- /dev/null
+++ b/test/lisp/erc/resources/erc-d/erc-d.el
@@ -0,0 +1,1009 @@
+;;; erc-d.el --- A dumb test server for ERC -*- lexical-binding: t -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This is a netcat style server for testing ERC. The "d" in the name
+;; stands for "daemon" as well as for "dialog" (as well as for "dumb"
+;; because this server isn't very smart). It either spits out a
+;; canned reply when an incoming request matches the expected regexp
+;; or signals an error and dies. The entry point function is
+;; `erc-d-run'.
+;;
+;; Canned scripts, or "dialogs," should be Lisp-Data files containing
+;; one or more request/reply forms like this:
+;;
+;; | ((mode-chan 1.5 "MODE #chan") ; request: tag, expr, regex
+;; | (0.1 ":irc.org 324 bob #chan +Cint") ; reply: delay, content
+;; | (0.0 ":irc.org 329 bob #chan 12345")) ; reply: ...
+;;
+;; These are referred to as "exchanges." The first element is a list
+;; whose CAR is a descriptive "tag" and whose CDR is an incoming
+;; "spec" representing an inbound message from the client. The rest
+;; of the exchange is composed of outgoing specs representing
+;; server-to-client messages. A tag can be any symbol (ideally unique
+;; in the dialog), but a leading tilde means the request should be
+;; allowed to arrive out of order (within the allotted time).
+;;
+;; The first element in an incoming spec is a number indicating the
+;; maximum number of seconds to wait for a match before raising an
+;; error. The CDR is interpreted as the collective arguments of an
+;; `rx' form to be matched against the raw request (stripped of its
+;; CRLF line ending). A "string-start" backslash assertion, "\\`", is
+;; prepended to all patterns.
+;;
+;; Similarly, the leading number in an *outgoing* spec indicates how
+;; many seconds to wait before sending the line, which is rendered by
+;; concatenating the other members after evaluating each in place.
+;; CRLF line endings are appended on the way out and should be absent.
+;;
+;; Recall that IRC is "asynchronous," meaning some flow intervals
+;; don't jibe with lockstep request-reply semantics. However, for our
+;; purposes, grouping things as [input, output1, ..., outputN] makes
+;; sense, even though input and output may be completely unrelated.
+;;
+;; Template interpolation:
+;;
+;; A rudimentary templating facility is provided for additional
+;; flexibility. However, it's best to keep things simple (even if
+;; overly verbose), so others can easily tell what's going on at a
+;; glance. If necessary, consult existing tests for examples (grep
+;; for the variables `erc-d-tmpl-vars' and `erc-d-match-handlers').
+;;
+;; Subprocess or in-process?:
+;;
+;; Running in-process confers better visibility and easier setup at
+;; the cost of additional cleanup and resource wrangling. With a
+;; subprocess, cleanup happens by pulling the plug, but configuration
+;; means loading a separate file or passing -eval "(forms...)" during
+;; invocation. In some cases, a subprocess may be the only option,
+;; like when trying to avoid `require'ing this file.
+;;
+;; Dialog objects:
+;;
+;; For a given exchange, the first argument passed to a request
+;; handler is the `erc-d-dialog' object representing the overall
+;; conversation with the connecting peer. It can be used to pass
+;; information between handlers during a session. Some important
+;; items are:
+;;
+;; * name (symbol); name of the current dialog
+;;
+;; * queue (ring); a backlog of unhandled raw requests, minus CRLF
+;; endings.
+;;
+;; * timers (list of timers); when run, these send messages originally
+;; deferred as per the most recently matched exchange's delay info.
+;; Normally, all outgoing messages must be sent before another request
+;; is considered. (See `erc-d--send-outgoing' for an escape hatch.)
+;;
+;; * hunks (iterator of iterators); unconsumed exchanges as read from
+;; a Lisp-Data dialog file. The exchange iterators being dispensed
+;; themselves yield portions of member forms as a 2- or 3-part
+;; sequence: [tag] spec. (Here, "hunk" just means "list of raw,
+;; unrendered exchange elements")
+;;
+;; * vars (alist of cons pairs); for sharing state among template
+;; functions during the lifetime of an exchange. Initially populated
+;; by `erc-d-tmpl-vars', these KEY/VALUE pairs are expanded in the
+;; templates and optionally updated by "exchange handlers" (see
+;; `erc-d-match-handlers'). When VALUE is a function, occurrences of
+;; KEY in an outgoing spec are replaced with the result of calling
+;; VALUE with match data set appropriately. See
+;; `erc-d--render-entries' for details.
+;;
+;; * exchanges (ring of erc-d-exchange objects); activated hunks
+;; allowed to match out of order, plus the current active exchange
+;; being yielded from, if any. See `erc-d-exchange'.
+;;
+;; TODO
+;;
+;; - Remove un(der)used functionality and simplify API
+;; - Maybe migrate d-u and d-i dependencies here
+
+;;; Code:
+(eval-and-compile
+ (let* ((d (file-name-directory (or (macroexp-file-name) buffer-file-name)))
+ (load-path (cons (directory-file-name d) load-path)))
+ (require 'erc-d-i)
+ (require 'erc-d-u)))
+
+(require 'ring)
+
+(defvar erc-d-server-name "erc-d-server"
+ "Default name of a server process and basis for its buffer name.
+Only relevant when starting a server with `erc-d-run'.")
+
+(defvar erc-d-server-fqdn "irc.example.org"
+ "Usually the same as the server's RPL_MYINFO \"announced name\".
+Possibly used by overriding handlers, like the one for PING, and/or
+dialog templates for the sender portion of a reply message.")
+
+(defvar erc-d-line-ending "\r\n"
+ "Protocol line delimiter for sending and receiving.")
+
+(defvar erc-d-linger-secs nil
+ "Seconds to wait before quitting for all dialogs.
+For more granular control, use the provided LINGER `rx' variable (alone)
+as the incoming template spec of a dialog's last exchange.")
+
+(defvar erc-d-tmpl-vars nil
+ "An alist of template bindings available to client dialogs.
+Populate it when calling `erc-d-run', and the contents will be made
+available to all client dialogs through the `erc-d-dialog' \"vars\"
+field and (therefore) to all templates as variables when rendering. For
+example, a key/value pair like (network . \"oftc\") will cause instances
+of the (unquoted) symbol `network' to be replaced with \"oftc\" in the
+rendered template string.
+
+This list provides default template bindings common to all dialogs.
+Each new client-connection process makes a shallow copy on init, but the
+usual precautions apply when mutating member items. Within the span of
+a dialog, updates not applicable to all exchanges should die with their
+exchange. See `erc-d--render-entries' for details. In the unlikely
+event that an exchange-specific handler is needed, see
+`erc-d-match-handlers'.")
+
+(defvar erc-d-match-handlers nil
+ "A plist of exchange-tag symbols mapped to request-handler functions.
+This is meant to address edge cases for which `erc-d-tmpl-vars' comes up
+short. These may include (1) needing access to the client process
+itself and/or (2) adding or altering outgoing response templates before
+rendering. Note that (2) requires using `erc-d-exchange-rebind' instead
+of manipulating exchange bindings directly.
+
+The hook-like function `erc-d-on-match' calls any handler whose key is
+`eq' to the tag of the currently matched exchange (passing the client
+`erc-d-dialog' as the first argument and the current `erc-d-exchange'
+object as the second). The handler runs just prior to sending the first
+response.")
+
+(defvar erc-d-auto-pong t
+ "Handle PING requests automatically.")
+
+(defvar erc-d--in-process t
+ "Whether the server is running in the same Emacs as ERT.")
+
+(defvar erc-d--slow-mo nil
+ "Adjustment for all incoming timeouts.
+This is to allow for human interaction or a slow Emacs or CI runner.
+The value is the number of seconds to extend all incoming spec timeouts
+by on init. If the value is a negative number, it's negated and
+interpreted as a lower bound to raise all incoming timeouts to. If the
+value is a function, it should take an existing timeout in seconds and
+return a replacement.")
+
+(defconst erc-d--eof-sentinel "__EOF__")
+(defconst erc-d--linger-sentinel "__LINGER__")
+(defconst erc-d--drop-sentinel "__DROP__")
+
+(defvar erc-d--clients nil
+ "List containing all clients for this server session.")
+
+;; Some :type names may just be made up (not actual CL types)
+
+(cl-defstruct (erc-d-spec) ; see `erc-d--render-entries'
+ (head nil :type symbol) ; or number?
+ (entry nil :type list)
+ (state 0 :type integer))
+
+(cl-defstruct (erc-d-exchange)
+ "Object representing a request/response unit from a canned dialog."
+ (dialog nil :type erc-d-dialog) ; owning dialog
+ (tag nil :type symbol) ; a.k.a. tag, the caar
+ (pattern nil :type string) ; regexp to match requests against
+ (inspec nil :type list) ; original unrendered incoming spec
+ (hunk nil :type erc-d-u-scan-e) ; active raw exchange hunk being yielded
+ (spec nil :type erc-d-spec) ; active spec, see `erc-d--render-entries'
+ (timeout nil :type number) ; time allotted for current request
+ (timer nil :type timer) ; match timer fires when timeout expires
+ (bindings nil :type list) ; `eval'-style env pairs (KEY . VAL) ...
+ (rx-bindings nil :type list) ; rx-let bindings
+ (deferred nil :type boolean) ; whether sender is paused
+ ;; Post-match
+ (match-data nil :type match-data) ; from the latest matched request
+ (request nil :type string)) ; the original request sans CRLF
+
+(cl-defstruct (erc-d-dialog)
+ "Session state for managing a client conversation."
+ (process nil :type process) ; client-connection process
+ (name nil :type symbol) ; likely the interned stem of the file
+ (queue nil :type ring) ; backlog of incoming lines to process
+ (hunks nil :type erc-d-u-scan-d) ; nil when done; info on raw exchange hunks
+ (timers nil :type list) ; unsent replies
+ (vars nil :type list) ; template bindings for rendering
+ (exchanges nil :type ring) ; ring of erc-d-exchange objects
+ (state nil :type symbol) ; handler's last recorded control state
+ (matched nil :type erc-d-exchange) ; currently matched exchange
+ (message nil :type erc-d-i-message) ; `erc-d-i-message'
+ (match-handlers nil :type list) ; copy of `erc-d-match-handlers'
+ (server-fqdn nil :type string) ; copy of `erc-d-server-fqdn'
+ (finalizer nil :type function) ; custom teardown, passed dialog and exchange
+ ;; Post-match history is a plist whose keys are exchange tags
+ ;; (symbols) and whose values are a cons of match-data and request
+ ;; values from prior matches.
+ (history nil :type list))
+
+(defun erc-d--initialize-client (process)
+ "Initialize state variables used by a client PROCESS."
+ ;; Discard server-only/owned props
+ (process-put process :dialog-dialogs nil)
+ (let* ((server (process-get process :server))
+ (reader (pop (process-get server :dialog-dialogs)))
+ (name (pop reader))
+ ;; Copy handlers so they can self-mutate per process
+ (mat-h (copy-sequence (process-get process :dialog-match-handlers)))
+ (fqdn (copy-sequence (process-get process :dialog-server-fqdn)))
+ (vars (copy-sequence (process-get process :dialog-vars)))
+ (ending (process-get process :dialog-ending))
+ (dialog (make-erc-d-dialog :name name
+ :process process
+ :queue (make-ring 5)
+ :exchanges (make-ring 10)
+ :match-handlers mat-h
+ :server-fqdn fqdn)))
+ ;; Add items expected by convenience commands like `erc-d-exchange-reload'.
+ (setf (alist-get 'EOF vars) `(: ,erc-d--eof-sentinel eot)
+ (alist-get 'LINGER vars) `(: ,erc-d--linger-sentinel eot)
+ (alist-get 'DROP vars) `(: ,erc-d--drop-sentinel eot)
+ (erc-d-dialog-vars dialog) vars
+ (erc-d-dialog-hunks dialog) reader)
+ ;; Add reverse link, register client, launch
+ (process-put process :dialog dialog)
+ (process-put process :ending ending)
+ (process-put process :ending-regexp (rx-to-string `(+ ,ending)))
+ (push process erc-d--clients)
+ (erc-d--command-refresh dialog nil)
+ (erc-d--on-request process)))
+
+(defun erc-d-load-replacement-dialog (dialog replacement &optional skip)
+ "Find REPLACEMENT among backlog and swap out current DIALOG's iterator.
+With int SKIP, advance past that many exchanges."
+ (let* ((process (erc-d-dialog-process dialog))
+ (server (process-get process :server))
+ (reader (assoc-default replacement
+ (process-get server :dialog-dialogs)
+ #'eq)))
+ (when skip (while (not (zerop skip))
+ (erc-d-u--read-dialog reader)
+ (cl-decf skip)))
+ (dolist (timer (erc-d-dialog-timers dialog))
+ (cancel-timer timer))
+ (dolist (exchange (ring-elements (erc-d-dialog-exchanges dialog)))
+ (cancel-timer (erc-d-exchange-timer exchange)))
+ (setf (erc-d-dialog-hunks dialog) reader)
+ (erc-d--command-refresh dialog nil)))
+
+(defvar erc-d--m-debug (getenv "ERC_D_DEBUG"))
+
+(defmacro erc-d--m (process format-string &rest args)
+ "Output ARGS using FORMAT-STRING somewhere depending on context.
+PROCESS should be a client connection or a server network process."
+ `(let ((format-string (if erc-d--m-debug
+ (concat (format-time-string "%s.%N: ")
+ ,format-string)
+ ,format-string))
+ (want-insert (and ,process erc-d--in-process)))
+ (when want-insert
+ (with-current-buffer (process-buffer (process-get ,process :server))
+ (goto-char (point-max))
+ (insert (concat (format ,format-string ,@args) "\n"))))
+ (when (or erc-d--m-debug (not want-insert))
+ (message format-string ,@args))))
+
+(defmacro erc-d--log (process string &optional outbound)
+ "Log STRING sent to (OUTBOUND) or received from PROCESS peer."
+ `(let ((id (or (process-get ,process :log-id)
+ (let ((port (erc-d-u--get-remote-port ,process)))
+ (process-put ,process :log-id port)
+ port)))
+ (name (erc-d-dialog-name (process-get ,process :dialog))))
+ (if ,outbound
+ (erc-d--m process "-> %s:%s %s" name id ,string)
+ (dolist (line (split-string ,string (process-get process :ending)))
+ (erc-d--m process "<- %s:%s %s" name id line)))))
+
+(defun erc-d--log-process-event (server process msg)
+ (erc-d--m server "%s: %s" process (string-trim-right msg)))
+
+(defun erc-d--send (process string)
+ "Send STRING to PROCESS peer."
+ (erc-d--log process string 'outbound)
+ (process-send-string process (concat string (process-get process :ending))))
+
+(define-inline erc-d--fuzzy-p (exchange)
+ (inline-letevals (exchange)
+ (inline-quote
+ (let ((tag (symbol-name (erc-d-exchange-tag ,exchange))))
+ (eq ?~ (aref tag 0))))))
+
+(define-error 'erc-d-timeout "Timed out awaiting expected request")
+
+(defun erc-d--finalize-dialog (dialog)
+ "Delete client-connection and finalize DIALOG.
+Return associated server."
+ (let ((process (erc-d-dialog-process dialog)))
+ (setq erc-d--clients (delq process erc-d--clients))
+ (dolist (timer (erc-d-dialog-timers dialog))
+ (cancel-timer timer))
+ (dolist (exchange (ring-elements (erc-d-dialog-exchanges dialog)))
+ (cancel-timer (erc-d-exchange-timer exchange)))
+ (prog1 (process-get process :server)
+ (delete-process process))))
+
+(defun erc-d--teardown (&optional sig &rest msg)
+ "Clean up processes and maybe send signal SIG using MSG."
+ (unless erc-d--in-process
+ (when sig
+ (erc-d--m nil "%s %s" sig (apply #'format-message msg)))
+ (kill-emacs (if msg 1 0)))
+ (let (process servers)
+ (while (setq process (pop erc-d--clients))
+ (push (erc-d--finalize-dialog (process-get process :dialog)) servers))
+ (dolist (server servers)
+ (delete-process server)))
+ (dolist (timer timer-list)
+ (when (memq (timer--function timer)
+ '(erc-d--send erc-d--command-handle-all))
+ (erc-d--m nil "Stray timer found: %S" (timer--function timer))
+ (cancel-timer timer)))
+ (when sig
+ (dolist (buf erc-d-u--canned-buffers)
+ (kill-buffer buf))
+ (setq erc-d-u--canned-buffers nil)
+ (signal sig (list (apply #'format-message msg)))))
+
+(defun erc-d--teardown-this-dialog-at-least (dialog)
+ "Run `erc-d--teardown' after destroying DIALOG if it's the last one."
+ (let ((server (process-get (erc-d-dialog-process dialog) :server))
+ (us (erc-d-dialog-process dialog)))
+ (erc-d--finalize-dialog dialog)
+ (cl-assert (not (memq us erc-d--clients)))
+ (unless (or (process-get server :dialog-dialogs)
+ (catch 'other
+ (dolist (process erc-d--clients)
+ (when (eq (process-get process :server) server)
+ (throw 'other process)))))
+ (push us erc-d--clients)
+ (erc-d--teardown))))
+
+(defun erc-d--expire (dialog exchange)
+ "Raise timeout error for EXCHANGE.
+This will start the teardown for DIALOG."
+ (setf (erc-d-exchange-spec exchange) nil)
+ (if-let ((finalizer (erc-d-dialog-finalizer dialog)))
+ (funcall finalizer dialog exchange)
+ (erc-d--teardown 'erc-d-timeout "Timed out awaiting request: %s"
+ (list :name (erc-d-exchange-tag exchange)
+ :pattern (erc-d-exchange-pattern exchange)
+ :timeout (erc-d-exchange-timeout exchange)
+ :dialog (erc-d-dialog-name dialog)))))
+
+;; Using `run-at-time' here allows test cases to examine replies as
+;; they arrive instead of forcing tests to wait until an exchange
+;; completes. The `run-at-time' in `erc-d--command-meter-replies'
+;; does the same. When running as a subprocess, a normal while loop
+;; with a `sleep-for' works fine (including with multiple dialogs).
+;; FYI, this issue was still present in older versions that called
+;; this directly from `erc-d--filter'.
+
+(defun erc-d--on-request (process)
+ "Handle one request for client-connection PROCESS."
+ (when (process-live-p process)
+ (let* ((dialog (process-get process :dialog))
+ (queue (erc-d-dialog-queue dialog)))
+ (unless (ring-empty-p queue)
+ (let* ((parsed (ring-remove queue))
+ (cmd (intern (erc-d-i-message.command parsed))))
+ (setf (erc-d-dialog-message dialog) parsed)
+ (erc-d-command dialog cmd)))
+ (run-at-time nil nil #'erc-d--on-request process))))
+
+(defun erc-d--drop-p (exchange)
+ (memq 'DROP (erc-d-exchange-inspec exchange)))
+
+(defun erc-d--linger-p (exchange)
+ (memq 'LINGER (erc-d-exchange-inspec exchange)))
+
+(defun erc-d--fake-eof (dialog)
+ "Simulate receiving a fictitious \"EOF\" message from peer."
+ (setf (erc-d-dialog-message dialog) ; use downcase for internal cmds
+ (make-erc-d-i-message :command "eof" :unparsed erc-d--eof-sentinel))
+ (run-at-time nil nil #'erc-d-command dialog 'eof))
+
+(defun erc-d--process-sentinel (process event)
+ "Set up or tear down client-connection PROCESS depending on EVENT."
+ (erc-d--log-process-event process process event)
+ (if (eq 'open (process-status process))
+ (erc-d--initialize-client process)
+ (let* ((dialog (process-get process :dialog))
+ (exes (and dialog (erc-d-dialog-exchanges dialog))))
+ (if (and exes (not (ring-empty-p exes)))
+ (cond ((string-prefix-p "connection broken" event)
+ (erc-d--fake-eof dialog))
+ ;; Ignore disconnecting peer when pattern is DROP
+ ((and (string-prefix-p "deleted" event)
+ (erc-d--drop-p (ring-ref exes -1))))
+ (t (erc-d--teardown)))
+ (erc-d--teardown)))))
+
+(defun erc-d--filter (process string)
+ "Handle input received from peer.
+PROCESS represents a client peer connection and STRING is a raw request
+including line delimiters."
+ (let ((queue (erc-d-dialog-queue (process-get process :dialog)))
+ (delim (process-get process :ending-regexp)))
+ (setq string (concat (process-get process :stashed-input) string))
+ (while (and string (string-match delim string))
+ (let ((line (substring string 0 (match-beginning 0))))
+ (setq string (unless (= (match-end 0) (length string))
+ (substring string (match-end 0))))
+ (erc-d--log process line nil)
+ (ring-insert queue (erc-d-i--parse-message line 'decode))))
+ (when string
+ (setf (process-get process :stashed-input) string))))
+
+;; Misc process properties:
+;;
+;; The server property `:dialog-dialogs' is an alist of (symbol
+;; . erc-d-u-scan-d) conses, each of which pairs a dialogs name with
+;; info on its read progress (described above in the Commentary).
+;; This list is populated by `erc-d-run' at the start of each session.
+;;
+;; Client-connection processes keep a reference to their server via a
+;; `:server' property, which can be used to share info with other
+;; clients. There is currently no built-in way to do the same with
+;; clients of other servers. Clients also keep references to their
+;; dialogs and raw messages via `:dialog' and `:stashed-input'.
+;;
+;; The logger stores a unique, human-friendly process name in the
+;; client-process property `:log-id'.
+
+(defun erc-d--start (host service name &rest plist)
+ "Serve canned replies on HOST at SERVICE.
+Return the new server process immediately when `erc-d--in-process' is
+non-nil. Otherwise, serve forever. PLIST becomes the plist of the
+server process and is used to initialize the plists of connection
+processes. NAME is used for the process and the buffer."
+ (let* ((buf (get-buffer-create (concat "*" name "*")))
+ (proc (make-network-process :server t
+ :buffer buf
+ :noquery t
+ :filter #'erc-d--filter
+ :log #'erc-d--log-process-event
+ :sentinel #'erc-d--process-sentinel
+ :name name
+ :family (if host 'ipv4 'local)
+ :coding 'binary
+ :service (or service t)
+ :host host
+ :plist plist)))
+ (process-put proc :server proc)
+ ;; We don't have a minor mode, so use an arbitrary variable to mark
+ ;; buffers owned by us instead
+ (with-current-buffer buf (setq erc-d-u--process-buffer t))
+ (erc-d--m proc "Starting network process: %S %S"
+ proc (erc-d-u--format-bind-address proc))
+ (if erc-d--in-process
+ proc
+ (while (process-live-p proc)
+ (accept-process-output nil 0.01)))))
+
+(defun erc-d--wrap-func-val (dialog exchange key func)
+ "Return a form invoking FUNC when evaluated.
+Arrange for FUNC to be called with the args it expects based on
+the description in `erc-d--render-entries'."
+ (let (args)
+ ;; Ignore &rest or &optional
+ (pcase-let ((`(,n . ,_) (func-arity func)))
+ (pcase n
+ (0)
+ (1 (push (apply-partially #'erc-d-exchange-multi dialog exchange key)
+ args))
+ (2 (push exchange args)
+ (push (apply-partially #'erc-d-exchange-multi dialog exchange key)
+ args))
+ (_ (error "Incompatible function: %s" func))))
+ (lambda () (apply func args))))
+
+(defun erc-d-exchange-reload (dialog exchange)
+ "Rebuild all bindings for EXCHANGE from those in DIALOG."
+ (cl-loop for (key . val) in (erc-d-dialog-vars dialog)
+ unless (keywordp key)
+ do (push (erc-d-u--massage-rx-args key val)
+ (erc-d-exchange-rx-bindings exchange))
+ when (functionp val) do
+ (setq val (erc-d--wrap-func-val dialog exchange key val))
+ do (push (cons key val) (erc-d-exchange-bindings exchange))))
+
+(defun erc-d-exchange-rebind (dialog exchange key val &optional export)
+ "Modify a binding between renders.
+
+Bind symbol KEY to VAL, replacing whatever existed before, which may
+have been a function. A third, optional argument, if present and
+non-nil, results in the DIALOG's bindings for all EXCHANGEs adopting
+this binding. VAL can either be a function of the type described in
+`erc-d--render-entries' or any value acceptable as an argument to the
+function `concat'.
+
+DIALOG and EXCHANGE are the current `erc-d-dialog' and `erc-d-exchange'
+objects for the request context."
+ (when export
+ (setf (alist-get key (erc-d-dialog-vars dialog)) val))
+ (if (functionp val)
+ (setf (alist-get key (erc-d-exchange-bindings exchange))
+ (erc-d--wrap-func-val dialog exchange key val))
+ (setf (alist-get key (erc-d-exchange-rx-bindings exchange)) (list val)
+ (alist-get key (erc-d-exchange-bindings exchange)) val))
+ val)
+
+(defun erc-d-exchange-match (exchange match-number &optional tag)
+ "Return match portion of current or previous request.
+MATCH-NUMBER is the match group number. TAG, if provided, means the
+exchange tag (name) from some previously matched request."
+ (if tag
+ (pcase-let* ((dialog (erc-d-exchange-dialog exchange))
+ (`(,m-d . ,req) (plist-get (erc-d-dialog-history dialog)
+ tag)))
+ (set-match-data m-d)
+ (match-string match-number req))
+ (match-string match-number (erc-d-exchange-request exchange))))
+
+(defun erc-d-exchange-multi (dialog exchange key cmd &rest args)
+ "Call CMD with ARGS.
+This is a utility passed as the first argument to all template
+functions. DIALOG and EXCHANGE are pre-applied. A few pseudo
+commands, like `:request', are provided for convenience so that
+the caller's definition doesn't have to include this file. The
+rest are access and mutation utilities, such as `:set', which
+assigns KEY a new value, `:get-binding', which looks up KEY in
+`erc-d-exchange-bindings', and `:get-var', which looks up KEY in
+`erc-d-dialog-vars'."
+ (pcase cmd
+ (:set (apply #'erc-d-exchange-rebind dialog exchange key args))
+ (:reload (apply #'erc-d-exchange-reload dialog exchange args))
+ (:rebind (apply #'erc-d-exchange-rebind dialog exchange args))
+ (:match (apply #'erc-d-exchange-match exchange args))
+ (:request (erc-d-exchange-request exchange))
+ (:match-data (erc-d-exchange-match-data exchange))
+ (:dialog-name (erc-d-dialog-name dialog))
+ (:get-binding (cdr (assq (car args) (erc-d-exchange-bindings exchange))))
+ (:get-var (alist-get (car args) (erc-d-dialog-vars dialog)))))
+
+(defun erc-d--render-incoming-entry (exchange spec)
+ (let ((rx--local-definitions (rx--extend-local-defs
+ (erc-d-exchange-rx-bindings exchange))))
+ (rx-to-string `(: bos ,@(erc-d-spec-entry spec)) 'no-group)))
+
+(defun erc-d--render-outgoing-entry (exchange entry)
+ (let (out this)
+ (while (setq this (pop entry))
+ (set-match-data (erc-d-exchange-match-data exchange))
+ (unless (stringp this)
+ (cl-assert (symbolp this))
+ (setq this (or (alist-get this (erc-d-exchange-bindings exchange))
+ (symbol-value this)))
+ ;; Allow reference to overlong var name unbecoming of a template
+ (when this
+ (when (symbolp this) (setq this (symbol-value this)))
+ (when (functionp this) (setq this (save-match-data (funcall this))))
+ (unless (stringp this) (error "Unexpected token %S" this))))
+ (push this out))
+ (apply #'concat (nreverse out))))
+
+(defun erc-d--render-entries (exchange &optional yield-result)
+ "Act as an iterator producing rendered strings from EXCHANGE hunks.
+When an entry's CAR is an arbitrary symbol, yield that back first, and
+consider the entry an \"incoming\" entry. Then, regardless of the
+entry's type (incoming or outgoing), yield back the next element, which
+should be a number representing either a timeout (incoming) or a
+delay (outgoing). After that, yield a rendered template (outgoing) or a
+regular expression (incoming); both should be treated as immutable.
+
+When evaluating a template, bind the keys in the alist stored in the
+dialog's `vars' field to its values, but skip any self-quoters, like
+:foo. When an entry is incoming, replace occurrences of a key with its
+value, which can be any valid `rx' form (see Info node `(elisp)
+Extending Rx'). Do the same when an entry is outgoing, but expect a
+value's form to be (anything that evaluates to) something acceptable by
+`concat' or, alternatively, a function that returns a string or nil.
+
+Repeat the last two steps for the remaining entries, all of which are
+assumed to be outgoing. That is, continue yielding a timeout/delay and
+a rendered string for each entry, and yield nil when exhausted.
+
+Once again, for an incoming entry, the yielded string is a regexp to be
+matched against the raw request. For outgoing, it's the final response,
+ready to be sent out (after adding the appropriate line ending).
+
+To help with testing, bindings are not automatically created from
+DIALOG's \"vars\" alist when this function is invoked. But this can be
+forced by sending a non-nil YIELD-RESULT into the generator on the
+second \"next\" invocation of a given iteration. This clobbers any
+temporary bindings that don't exist in the DIALOG's `vars' alist, such
+as those added via `erc-d-exchange-rebind' (unless \"exported\").
+
+As noted earlier, template symbols can be bound to functions. When
+called during rendering, the match data from the current (matched)
+request is accessible by calling the function `match-data'.
+
+A function may ask for up to two required args, which are provided as
+needed. When applicable, the first required arg is a `funcall'-able
+helper that accepts various keyword-based commands, like :rebind, and a
+variable number of args. See `erc-d-exchange-multi' for details. When
+specified, the second required arg is the current `erc-d-exchange'
+object, which has among its members its owning `erc-d-dialog' object.
+This should suffice as a safety valve for any corner-case needs.
+Non-required args are ignored."
+ (let ((spec (erc-d-exchange-spec exchange))
+ (dialog (erc-d-exchange-dialog exchange))
+ (entries (erc-d-exchange-hunk exchange)))
+ (unless (erc-d-spec-entry spec)
+ (setf (erc-d-spec-entry spec) (erc-d-u--read-exchange entries)))
+ (catch 'yield
+ (while (erc-d-spec-entry spec)
+ (pcase (erc-d-spec-state spec)
+ (0 (cl-incf (erc-d-spec-state spec))
+ (throw 'yield (setf (erc-d-spec-head spec)
+ (pop (erc-d-spec-entry spec)))))
+ (1 (cl-incf (erc-d-spec-state spec))
+ (when yield-result
+ (erc-d-exchange-reload dialog exchange))
+ (unless (numberp (erc-d-spec-head spec))
+ (setf (erc-d-exchange-inspec exchange) (erc-d-spec-entry spec))
+ (throw 'yield
+ (prog1 (pop (erc-d-spec-entry spec))
+ (setf (erc-d-spec-entry spec)
+ (erc-d--render-incoming-entry exchange spec))))))
+ (2 (setf (erc-d-spec-state spec) 0)
+ (throw 'yield
+ (let ((entry (erc-d-spec-entry spec)))
+ (setf (erc-d-spec-entry spec) nil)
+ (if (stringp entry)
+ entry
+ (erc-d--render-outgoing-entry exchange entry))))))))))
+
+(defun erc-d--iter (exchange)
+ (apply-partially #'erc-d--render-entries exchange))
+
+(defun erc-d-on-match (dialog exchange)
+ "Handle matched exchange request.
+Allow the first handler in `erc-d-match-handlers' whose key matches TAG
+to manipulate replies before they're sent to the DIALOG peer."
+ (when-let* ((tag (erc-d-exchange-tag exchange))
+ (handler (plist-get (erc-d-dialog-match-handlers dialog) tag)))
+ (let ((md (erc-d-exchange-match-data exchange)))
+ (set-match-data md)
+ (funcall handler dialog exchange))))
+
+(defun erc-d--send-outgoing (dialog exchange)
+ "Send outgoing lines for EXCHANGE to DIALOG peer.
+Assume the next spec is outgoing. If its delay value is zero, render
+the template and send the resulting message straight away. Do the same
+when DELAY is negative, only arrange for its message to be sent (abs
+DELAY) seconds later, and then keep on processing. If DELAY is
+positive, pause processing and yield DELAY."
+ (let ((specs (erc-d--iter exchange))
+ (process (erc-d-dialog-process dialog))
+ (deferred (erc-d-exchange-deferred exchange))
+ delay)
+ ;; Could stash/pass thunk instead to ensure specs can't be mutated
+ ;; between calls (by temporarily replacing dialog member with a fugazi)
+ (when deferred
+ (erc-d--send process (funcall specs))
+ (setf deferred nil (erc-d-exchange-deferred exchange) deferred))
+ (while (and (not deferred) (setq delay (funcall specs)))
+ (cond ((zerop delay) (erc-d--send process (funcall specs)))
+ ((< delay 0) (push (run-at-time (- delay) nil #'erc-d--send
+ process (funcall specs))
+ (erc-d-dialog-timers dialog)))
+ ((setf deferred t (erc-d-exchange-deferred exchange) deferred))))
+ delay))
+
+(defun erc-d--add-dialog-linger (dialog exchange)
+ "Add finalizer for EXCHANGE in DIALOG."
+ (erc-d--m (erc-d-dialog-process dialog)
+ "Lingering for %.2f seconds" (erc-d-exchange-timeout exchange))
+ (let ((start (current-time)))
+ (setf (erc-d-dialog-finalizer dialog)
+ (lambda (&rest _)
+ (erc-d--m (erc-d-dialog-process dialog)
+ "Lingered for %.2f seconds"
+ (float-time (time-subtract (current-time) start)))
+ (erc-d--teardown-this-dialog-at-least dialog)))))
+
+(defun erc-d--add-dialog-drop (dialog exchange)
+ "Add finalizer for EXCHANGE in DIALOG."
+ (erc-d--m (erc-d-dialog-process dialog)
+ "Dropping in %.2f seconds" (erc-d-exchange-timeout exchange))
+ (setf (erc-d-dialog-finalizer dialog)
+ (lambda (&rest _)
+ (erc-d--m (erc-d-dialog-process dialog)
+ "Dropping %S" (erc-d-dialog-name dialog))
+ (erc-d--finalize-dialog dialog))))
+
+(defun erc-d--create-exchange (dialog hunk)
+ "Initialize next exchange HUNK for DIALOG."
+ (let* ((spec (make-erc-d-spec))
+ (exchange (make-erc-d-exchange :dialog dialog :hunk hunk :spec spec))
+ (specs (erc-d--iter exchange)))
+ (setf (erc-d-exchange-tag exchange) (funcall specs)
+ (erc-d-exchange-timeout exchange) (funcall specs t)
+ (erc-d-exchange-pattern exchange) (funcall specs))
+ (cond ((erc-d--linger-p exchange)
+ (erc-d--add-dialog-linger dialog exchange))
+ ((erc-d--drop-p exchange)
+ (erc-d--add-dialog-drop dialog exchange)))
+ (setf (erc-d-exchange-timer exchange)
+ (run-at-time (erc-d-exchange-timeout exchange)
+ nil #'erc-d--expire dialog exchange))
+ exchange))
+
+(defun erc-d--command-consider-prep-fail (dialog line exes)
+ (list 'error "Match failed: %S %S" line
+ (list :exes (mapcar #'erc-d-exchange-pattern
+ (ring-elements exes))
+ :dialog (erc-d-dialog-name dialog))))
+
+(defun erc-d--command-consider-prep-success (dialog line exes matched)
+ (setf (erc-d-exchange-request matched) line
+ (erc-d-exchange-match-data matched) (match-data)
+ ;; Also add current to match history, indexed by exchange tag
+ (plist-get (erc-d-dialog-history dialog)
+ (erc-d-exchange-tag matched))
+ (cons (match-data) line)) ; do we need to make a copy of this?
+ (cancel-timer (erc-d-exchange-timer matched))
+ (ring-remove exes (ring-member exes matched)))
+
+(cl-defun erc-d--command-consider (dialog)
+ "Maybe return next matched exchange for DIALOG.
+Upon encountering a mismatch, return an error of the form (ERROR-SYMBOL
+DATA). But when only fuzzies remain in the exchange pool, return nil."
+ (let* ((parsed (erc-d-dialog-message dialog))
+ (line (erc-d-i-message.unparsed parsed))
+ (exes (erc-d-dialog-exchanges dialog))
+ ;;
+ matched)
+ (let ((elts (ring-elements exes)))
+ (while (and (setq matched (pop elts))
+ (not (string-match (erc-d-exchange-pattern matched) line)))
+ (if (and (not elts) (erc-d--fuzzy-p matched))
+ ;; Nothing to do, so advance
+ (cl-return-from erc-d--command-consider nil)
+ (cl-assert (or (not elts) (erc-d--fuzzy-p matched))))))
+ (if matched
+ (erc-d--command-consider-prep-success dialog line exes matched)
+ (erc-d--command-consider-prep-fail dialog line exes))))
+
+(defun erc-d--active-ex-p (ring)
+ "Return non-nil when RING has a non-fuzzy exchange.
+That is, return nil when RING is empty or when it only has exchanges
+with leading-tilde tags."
+ (let ((i 0)
+ (len (ring-length ring))
+ ex found)
+ (while (and (not found) (< i len))
+ (unless (erc-d--fuzzy-p (setq ex (ring-ref ring i)))
+ (setq found ex))
+ (cl-incf i))
+ found))
+
+(defun erc-d--finalize-done (dialog)
+ ;; Linger logic for individual dialogs is handled elsewhere
+ (if-let ((finalizer (erc-d-dialog-finalizer dialog)))
+ (funcall finalizer dialog)
+ (let ((d (process-get (erc-d-dialog-process dialog) :dialog-linger-secs)))
+ (push (run-at-time d nil #'erc-d--teardown)
+ (erc-d-dialog-timers dialog)))))
+
+(defun erc-d--advance-or-die (dialog)
+ "Govern the lifetime of DIALOG.
+Replenish exchanges from reader and insert them into the pool of
+expected matches, as produced. Return a symbol indicating session
+status: deferring, matching, depleted, or done."
+ (let ((exes (erc-d-dialog-exchanges dialog))
+ hunk)
+ (cond ((erc-d--active-ex-p exes) 'deferring)
+ ((setq hunk (erc-d-u--read-dialog (erc-d-dialog-hunks dialog)))
+ (let ((exchange (erc-d--create-exchange dialog hunk)))
+ (if (erc-d--fuzzy-p exchange)
+ (ring-insert exes exchange)
+ (ring-insert-at-beginning exes exchange)))
+ 'matching)
+ ((not (ring-empty-p exes)) 'depleted)
+ (t 'done))))
+
+(defun erc-d--command-meter-replies (dialog exchange &optional cmd)
+ "Ignore requests until all replies have been sent.
+Do this for some previously matched EXCHANGE in DIALOG based on CMD, a
+symbol. As a side effect, maybe schedule the resumption of the main
+loop after some delay."
+ (let (delay)
+ (if (or (not cmd) (eq 'resume cmd))
+ (when (setq delay (erc-d--send-outgoing dialog exchange))
+ (push (run-at-time delay nil #'erc-d--command-handle-all
+ dialog 'resume)
+ (erc-d-dialog-timers dialog))
+ (erc-d-dialog-state dialog))
+ (setf (erc-d-dialog-state dialog) 'sending))))
+
+(defun erc-d--die-unexpected (dialog)
+ (erc-d--teardown 'error "Received unexpected input: %S"
+ (erc-d-i-message.unparsed (erc-d-dialog-message dialog))))
+
+(defun erc-d--command-refresh (dialog matched)
+ (let ((state (erc-d--advance-or-die dialog)))
+ (when (eq state 'done)
+ (erc-d--finalize-done dialog))
+ (unless matched
+ (when (eq state 'depleted)
+ (erc-d--die-unexpected dialog))
+ (cl-assert (memq state '(matching depleted)) t))
+ (setf (erc-d-dialog-state dialog) state)))
+
+(defun erc-d--command-handle-all (dialog cmd)
+ "Create handler to act as control agent and process DIALOG requests.
+Have it ingest internal control commands (lowercase symbols) and yield
+back others indicating the lifecycle stage of the current dialog."
+ (let ((matched (erc-d-dialog-matched dialog)))
+ (cond
+ (matched
+ (or (erc-d--command-meter-replies dialog matched cmd)
+ (setf (erc-d-dialog-matched dialog) nil)
+ (erc-d--command-refresh dialog t)))
+ ((pcase cmd ; FIXME remove command facility or make extensible
+ ('resume nil)
+ ('eof (erc-d--m (erc-d-dialog-process dialog) "Received an EOF") nil)))
+ (t ; matching
+ (setq matched nil)
+ (catch 'yield
+ (while (not matched)
+ (when (ring-empty-p (erc-d-dialog-exchanges dialog))
+ (erc-d--die-unexpected dialog))
+ (when (setq matched (erc-d--command-consider dialog))
+ (if (eq (car-safe matched) 'error)
+ (apply #'erc-d--teardown matched)
+ (erc-d-on-match dialog matched)
+ (setf (erc-d-dialog-matched dialog) matched)
+ (if-let ((s (erc-d--command-meter-replies dialog matched nil)))
+ (throw 'yield s)
+ (setf (erc-d-dialog-matched dialog) nil))))
+ (erc-d--command-refresh dialog matched)))))))
+
+;;;; Handlers for IRC commands
+
+(cl-defgeneric erc-d-command (dialog cmd)
+ "Handle new CMD from client for DIALOG.
+By default, defer to this dialog's `erc-d--command-handle-all' instance,
+which is stored in its `handler' field.")
+
+(cl-defmethod erc-d-command ((dialog erc-d-dialog) cmd)
+ (when (eq 'sending (erc-d--command-handle-all dialog cmd))
+ (ring-insert-at-beginning (erc-d-dialog-queue dialog)
+ (erc-d-dialog-message dialog))))
+
+;; A similar PONG handler would be useless because we know when to
+;; expect them
+
+(cl-defmethod erc-d-command ((dialog erc-d-dialog) (_cmd (eql PING))
+ &context (erc-d-auto-pong (eql t)))
+ "Respond to PING request from DIALOG peer when ERC-D-AUTO-PONG is t."
+ (let* ((parsed (erc-d-dialog-message dialog))
+ (process (erc-d-dialog-process dialog))
+ (nonce (car (erc-d-i-message.command-args parsed)))
+ (fqdn (erc-d-dialog-server-fqdn dialog)))
+ (erc-d--send process (format ":%s PONG %s :%s" fqdn fqdn nonce))))
+
+
+;;;; Entry points
+
+(defun erc-d-run (host service &optional server-name &rest dialogs)
+ "Start serving DIALOGS on HOST at SERVICE.
+Pass HOST and SERVICE directly to `make-network-process'. When present,
+use string SERVER-NAME for the server-process name as well as that of
+its buffer (w. surrounding asterisks). When absent, do the same with
+`erc-d-server-name'. When running \"in process,\" return the server
+process; otherwise sleep until it dies.
+
+A dialog must be a symbol matching the base name of a dialog file in
+`erc-d-u-canned-dialog-dir'. Global variables `erc-d-server-fqdn',
+`erc-d-linger-secs', and `erc-d-tmpl-vars' determine the process's
+`erc-d-dialog' fields `:server-fqdn', `:linger-secs', and `:vars',
+respectively. The latter may also be populated via keyword pairs
+appearing among DIALOGS."
+ (when (and server-name (symbolp server-name))
+ (push server-name dialogs)
+ (setq server-name nil))
+ (let (loaded kwds defaults args)
+ (while dialogs
+ (if-let* ((dlog (pop dialogs))
+ ((keywordp dlog)))
+ (progn (push (pop dialogs) kwds) (push dlog kwds))
+ (let ((reader (erc-d-u--canned-load-dialog dlog)))
+ (when erc-d--slow-mo
+ (setq reader (erc-d-u--rewrite-for-slow-mo erc-d--slow-mo reader)))
+ (push (cons (erc-d-u--normalize-canned-name dlog) reader) loaded))))
+ (setq kwds (erc-d-u--unkeyword kwds)
+ defaults `((ending . ,erc-d-line-ending)
+ (server-fqdn . ,erc-d-server-fqdn)
+ (linger-secs . ,erc-d-linger-secs)
+ (vars . ,(or (plist-get kwds 'tmpl-vars) erc-d-tmpl-vars))
+ (dialogs . ,(nreverse loaded)))
+ args (list :dialog-match-handlers
+ (erc-d-u--unkeyword (or (plist-get kwds 'match-handlers)
+ erc-d-match-handlers))))
+ (pcase-dolist (`(,var . ,def) defaults)
+ (push (or (plist-get kwds var) def) args)
+ (push (intern (format ":dialog-%s" var)) args))
+ (apply #'erc-d--start host service (or server-name erc-d-server-name)
+ args)))
+
+(defun erc-d-serve ()
+ "Start serving canned dialogs from the command line.
+Although not autoloaded, this function is meant to be summoned via the
+Emacs -f flag while starting a batch session. It prints incoming and
+outgoing messages to standard out.
+
+The main options are --host HOST and --port PORT, which default to
+localhost and auto, respectively. The args are the dialogs to run.
+Unlike with `erc-d-run', dialogs here *must* be files, meaning Lisp-Data
+files adhering to the required format. (These consist of \"specs\"
+detailing timing and template info; see commentary for specifics.)
+
+An optional --add-time N option can also be passed to hike up timeouts
+by some number of seconds N. For example, you might run:
+
+ $ emacs -Q -batch -L . \\
+ > -l erc-d.el \\
+ > -f erc-d-serve \\
+ > --host 192.168.124.1 \\
+ > --port 16667 \\
+ > --add-time 10 \\
+ > ./my-dialog.eld
+
+from a Makefile or manually with \\<global-map>\\[compile]. And then in
+another terminal, do:
+
+ $ nc -C 192.168.124.1 16667 ; or telnet if your nc doesn't have -C
+ > PASS changeme
+ ...
+
+Use `erc-d-run' instead to start the server from within Emacs."
+ (unless noninteractive
+ (error "Command-line func erc-d-serve not run in -batch session"))
+ (setq erc-d--in-process nil)
+ (let (port host dialogs erc-d--slow-mo)
+ (while command-line-args-left
+ (pcase (pop command-line-args-left)
+ ("--add-time" (setq erc-d--slow-mo
+ (string-to-number (pop command-line-args-left))))
+ ("--linger" (setq erc-d-linger-secs
+ (string-to-number (pop command-line-args-left))))
+ ("--host" (setq host (pop command-line-args-left)))
+ ("--port" (setq port (string-to-number (pop command-line-args-left))))
+ (dialog (push dialog dialogs))))
+ (setq dialogs (mapcar #'erc-d-u--massage-canned-name dialogs))
+ (when erc-d--slow-mo
+ (message "Slow mo is ON"))
+ (apply #'erc-d-run (or host "localhost") port nil (nreverse dialogs))))
+
+(provide 'erc-d)
+
+;;; erc-d.el ends here
diff --git a/test/lisp/erc/resources/erc-d/resources/basic.eld b/test/lisp/erc/resources/erc-d/resources/basic.eld
new file mode 100644
index 00000000000..a020eec3fff
--- /dev/null
+++ b/test/lisp/erc/resources/erc-d/resources/basic.eld
@@ -0,0 +1,32 @@
+;;; -*- mode: lisp-data -*-
+
+((pass 10.0 "PASS " (? ?:) "changeme"))
+((nick 0.2 "NICK tester"))
+
+((user 0.2 "USER user 0 * :tester")
+ (0 ":irc.example.org 001 tester :Welcome to the Internet Relay Network tester")
+ (0 ":irc.example.org 002 tester :Your host is irc.example.org")
+ (0 ":irc.example.org 003 tester :This server was created just now")
+ (0 ":irc.example.org 004 tester irc.example.org BERios CEIRabehiklmnoqstv Iabehkloqv")
+ (0 ":irc.example.org 005 tester MODES NETWORK=ExampleOrg NICKLEN=32 PREFIX=(qaohv)~&@%+"
+ " :are supported by this server")
+ (0 ":irc.example.org 251 tester :There are 3 users and 0 invisible on 1 server(s)")
+ ;; Just to mix thing's up (force handler to schedule timer)
+ (0.1 ":irc.example.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.example.org 253 tester 0 :unregistered connections")
+ (0 ":irc.example.org 254 tester 1 :channels formed")
+ (0 ":irc.example.org 255 tester :I have 3 clients and 0 servers")
+ (0.1 ":irc.example.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.example.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.example.org 422 tester :MOTD File is missing"))
+
+((mode-user 5 "MODE tester +i")
+ (0 ":irc.example.org 221 tester +Zi")
+ (0 ":irc.example.org 306 tester :You have been marked as being away")
+ (0 ":tester!~tester@localhost JOIN #chan")
+ (0 ":irc.example.org 353 alice = #chan :+alice!~alice@example.com @%+bob!~bob@example.org")
+ (0 ":irc.example.org 366 alice #chan :End of NAMES list"))
+
+;; Some comment (to prevent regression)
+((mode-chan 1.2 "MODE #chan")
+ (0.1 ":bob!~bob@example.org PRIVMSG #chan :hey"))
diff --git a/test/lisp/erc/resources/erc-d/resources/depleted.eld b/test/lisp/erc/resources/erc-d/resources/depleted.eld
new file mode 100644
index 00000000000..e5a7f03efb7
--- /dev/null
+++ b/test/lisp/erc/resources/erc-d/resources/depleted.eld
@@ -0,0 +1,12 @@
+;;; -*- mode: lisp-data -*-
+
+((pass 10.0 "PASS :changeme"))
+
+((~fake 3.2 "FAKE ")
+ (0.1 ":irc.example.org FAKE irc.example.com :ok"))
+
+((nick 0.2 "NICK tester"))
+
+((user 0.2 "USER user 0 * :tester")
+ (0 ":irc.example.org 001 tester :Welcome to the Internet tester")
+ (0 ":irc.example.org 422 tester :MOTD File is missing"))
diff --git a/test/lisp/erc/resources/erc-d/resources/drop-a.eld b/test/lisp/erc/resources/erc-d/resources/drop-a.eld
new file mode 100644
index 00000000000..2e23eeb20ff
--- /dev/null
+++ b/test/lisp/erc/resources/erc-d/resources/drop-a.eld
@@ -0,0 +1,4 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS " (? ?:) "a")
+ (0 "hi"))
+((drop 0.01 DROP))
diff --git a/test/lisp/erc/resources/erc-d/resources/drop-b.eld b/test/lisp/erc/resources/erc-d/resources/drop-b.eld
new file mode 100644
index 00000000000..facecd5e812
--- /dev/null
+++ b/test/lisp/erc/resources/erc-d/resources/drop-b.eld
@@ -0,0 +1,4 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS " (? ?:) "b")
+ (0 "hi"))
+((linger 1 LINGER))
diff --git a/test/lisp/erc/resources/erc-d/resources/dynamic-barnet.eld b/test/lisp/erc/resources/erc-d/resources/dynamic-barnet.eld
new file mode 100644
index 00000000000..36b1cc23081
--- /dev/null
+++ b/test/lisp/erc/resources/erc-d/resources/dynamic-barnet.eld
@@ -0,0 +1,33 @@
+;;; -*- mode: lisp-data -*-
+((fake 0 "FAKE noop"))
+
+((nick 1.2 "NICK tester"))
+
+((user 2.2 "USER user 0 * :tester")
+ (0. ":irc.barnet.org 001 tester :Welcome to the BAR Network tester")
+ (0. ":irc.barnet.org 002 tester :Your host is irc.barnet.org")
+ (0. ":irc.barnet.org 003 tester :This server was created just now")
+ (0. ":irc.barnet.org 004 tester irc.barnet.org BERios CEIRabehiklmnoqstv Iabehkloqv")
+ (0. ":irc.barnet.org 005 tester MODES NETWORK=BarNet NICKLEN=32 PREFIX=(qaohv)~&@%+ :are supported by this server")
+ (0. ":irc.barnet.org 251 tester :There are 3 users and 0 invisible on 1 server(s)")
+ (0. ":irc.barnet.org 252 tester 0 :IRC Operators online")
+ (0. ":irc.barnet.org 253 tester 0 :unregistered connections")
+ (0. ":irc.barnet.org 254 tester 1 :channels formed")
+ (0. ":irc.barnet.org 255 tester :I have 3 clients and 0 servers")
+ (0. ":irc.barnet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0. ":irc.barnet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0. ":irc.barnet.org 422 tester :MOTD File is missing"))
+
+((mode-user 1.2 "MODE tester +i")
+ (0. ":irc.barnet.org 221 tester +Zi")
+ (0. ":irc.barnet.org 306 tester :You have been marked as being away")
+ (0 ":tester!~u@awyxgybtkx7uq.irc JOIN #chan")
+ (0 ":irc.barnet.org 353 joe = #chan :+joe!~joe@example.com @%+mike!~mike@example.org")
+ (0 ":irc.barnet.org 366 joe #chan :End of NAMES list"))
+
+((mode 1 "MODE #chan")
+ (0 ":irc.barnet.org 324 tester #chan +nt")
+ (0 ":irc.barnet.org 329 tester #chan 1620805269")
+ (0.1 ":joe!~u@awyxgybtkx7uq.irc PRIVMSG #chan :mike: Yes, a dozen; and as many to the vantage, as would store the world they played for.")
+ (0.05 ":mike!~u@awyxgybtkx7uq.irc PRIVMSG #chan :joe: As he regards his aged father's life.")
+ (0.05 ":joe!~u@awyxgybtkx7uq.irc PRIVMSG #chan :mike: It is a rupture that you may easily heal; and the cure of it not only saves your brother, but keeps you from dishonour in doing it."))
diff --git a/test/lisp/erc/resources/erc-d/resources/dynamic-foonet.eld b/test/lisp/erc/resources/erc-d/resources/dynamic-foonet.eld
new file mode 100644
index 00000000000..5dbea50f865
--- /dev/null
+++ b/test/lisp/erc/resources/erc-d/resources/dynamic-foonet.eld
@@ -0,0 +1,32 @@
+;;; -*- mode: lisp-data -*-
+
+((nick 1.2 "NICK tester"))
+
+((user 2.2 "USER user 0 * :tester")
+ (0. ":irc.foonet.org 001 tester :Welcome to the FOO Network tester")
+ (0. ":irc.foonet.org 002 tester :Your host is irc.foonet.org")
+ (0. ":irc.foonet.org 003 tester :This server was created just now")
+ (0. ":irc.foonet.org 004 tester irc.foonet.org BERios CEIRabehiklmnoqstv Iabehkloqv")
+ (0. ":irc.foonet.org 005 tester MODES NETWORK=FooNet NICKLEN=32 PREFIX=(qaohv)~&@%+ :are supported by this server")
+ (0. ":irc.foonet.org 251 tester :There are 3 users and 0 invisible on 1 server(s)")
+ (0. ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0. ":irc.foonet.org 253 tester 0 :unregistered connections")
+ (0. ":irc.foonet.org 254 tester 1 :channels formed")
+ (0. ":irc.foonet.org 255 tester :I have 3 clients and 0 servers")
+ (0. ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0. ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0. ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 1.2 "MODE tester +i")
+ (0. ":irc.foonet.org 221 tester +Zi")
+ (0. ":irc.foonet.org 306 tester :You have been marked as being away")
+ (0 ":tester!~u@awyxgybtkx7uq.irc JOIN #chan")
+ (0 ":irc.foonet.org 353 alice = #chan :+alice!~alice@example.com @%+bob!~bob@example.org")
+ (0 ":irc.foonet.org 366 alice #chan :End of NAMES list"))
+
+((mode 2 "MODE #chan")
+ (0 ":irc.foonet.org 324 tester #chan +nt")
+ (0 ":irc.foonet.org 329 tester #chan 1620805269")
+ (0.1 ":alice!~u@awyxgybtkx7uq.irc PRIVMSG #chan :bob: Yes, a dozen; and as many to the vantage, as would store the world they played for.")
+ (0.05 ":bob!~u@awyxgybtkx7uq.irc PRIVMSG #chan :alice: As he regards his aged father's life.")
+ (0.05 ":alice!~u@awyxgybtkx7uq.irc PRIVMSG #chan :bob: It is a rupture that you may easily heal; and the cure of it not only saves your brother, but keeps you from dishonour in doing it."))
diff --git a/test/lisp/erc/resources/erc-d/resources/dynamic-stub.eld b/test/lisp/erc/resources/erc-d/resources/dynamic-stub.eld
new file mode 100644
index 00000000000..d93313023d0
--- /dev/null
+++ b/test/lisp/erc/resources/erc-d/resources/dynamic-stub.eld
@@ -0,0 +1,4 @@
+;;; -*- mode: lisp-data -*-
+((pass 10.0 "PASS " (? ?:) token ":changeme"))
+
+((fake 0 "FAKE"))
diff --git a/test/lisp/erc/resources/erc-d/resources/dynamic.eld b/test/lisp/erc/resources/erc-d/resources/dynamic.eld
new file mode 100644
index 00000000000..459b6e52bfe
--- /dev/null
+++ b/test/lisp/erc/resources/erc-d/resources/dynamic.eld
@@ -0,0 +1,30 @@
+;;; -*- mode: lisp-data -*-
+((pass 10.0 "PASS " (? ?:) "changeme"))
+((nick 2.2 "NICK tester"))
+
+((user 2.2 "USER " user " " (ignored digit "*") " :" realname)
+ (0.0 ":" dom " 001 " nick " :Welcome to the Internet Relay Network tester")
+ (0.0 ":" dom " 002 " nick " :Your host is " dom)
+ (0.0 ":" dom " 003 " nick " :This server was created just now")
+ (0.0 ":" dom " 004 " nick " " dom " BERios CEIRabehiklmnoqstv Iabehkloqv")
+ (0.0 ":" dom " 005 " nick " MODES NETWORK=ExampleOrg NICKLEN=32 PREFIX=(qaohv)~&@%+"
+ " :are supported by this server")
+ (0.0 ":" dom " 251 " nick " :There are 3 users and 0 invisible on 1 server(s)")
+ (0.0 ":" dom " 252 " nick " 0 :IRC Operators online")
+ (0.0 ":" dom " 253 " nick " 0 :unregistered connections")
+ (0.0 ":" dom " 254 " nick " 1 :channels formed")
+ (0.0 ":" dom " 255 " nick " :I have 3 clients and 0 servers")
+ (0.0 ":" dom " 265 " nick " 3 3 :Current local users 3, max 3")
+ (0.0 ":" dom " 266 " nick " 3 3 :Current global users 3, max 3")
+ (0.0 ":" dom " 422 " nick " :MOTD File is missing"))
+
+((mode-user 2.2 "MODE tester +i")
+ (0.0 ":" dom " 221 " nick " +Zi")
+
+ (0.0 ":" dom " 306 " nick " :You have been marked as being away")
+ (0.0 ":" nick "!~" nick "@localhost JOIN #chan")
+ (0.0 ":" dom " 353 alice = #chan :+alice!~alice@example.com @%+bob!~bob@example.org")
+ (0.0 ":" dom " 366 alice #chan :End of NAMES list"))
+
+((mode 2.2 "MODE #chan")
+ (0.1 ":bob!~bob@example.org PRIVMSG #chan :" nick ": hey"))
diff --git a/test/lisp/erc/resources/erc-d/resources/eof.eld b/test/lisp/erc/resources/erc-d/resources/eof.eld
new file mode 100644
index 00000000000..5da84b2e74f
--- /dev/null
+++ b/test/lisp/erc/resources/erc-d/resources/eof.eld
@@ -0,0 +1,33 @@
+;;; -*- mode: lisp-data -*-
+
+((pass 10.0 "PASS " (? ?:) "changeme"))
+((nick 0.2 "NICK tester"))
+
+((user 0.2 "USER user 0 * :tester")
+ (0 ":irc.example.org 001 tester :Welcome to the Internet Relay Network tester")
+ (0 ":irc.example.org 002 tester :Your host is irc.example.org")
+ (0 ":irc.example.org 003 tester :This server was created just now")
+ (0 ":irc.example.org 004 tester irc.example.org BERios CEIRabehiklmnoqstv Iabehkloqv")
+ (0 ":irc.example.org 005 tester MODES NETWORK=ExampleOrg NICKLEN=32 PREFIX=(qaohv)~&@%+"
+ " :are supported by this server")
+ (0 ":irc.example.org 251 tester :There are 3 users and 0 invisible on 1 server(s)")
+ ;; Just to mix thing's up (force handler to schedule timer)
+ (0.1 ":irc.example.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.example.org 253 tester 0 :unregistered connections")
+ (0 ":irc.example.org 254 tester 1 :channels formed")
+ (0 ":irc.example.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.example.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.example.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.example.org 422 tester :MOTD File is missing"))
+
+((mode-user 1.2 "MODE tester +i")
+ (0 ":irc.example.org 221 tester +Zi")
+ (0 ":irc.example.org 306 tester :You have been marked as being away")
+ (0 ":tester!~tester@localhost JOIN #chan")
+ (0 ":irc.example.org 353 alice = #chan :+alice!~alice@example.com @%+bob!~bob@example.org")
+ (0 ":irc.example.org 366 alice #chan :End of NAMES list"))
+
+((mode-chan 1.2 "MODE #chan")
+ (0.1 ":bob!~bob@example.org PRIVMSG #chan :hey"))
+
+((eof 1.0 EOF))
diff --git a/test/lisp/erc/resources/erc-d/resources/foreign.eld b/test/lisp/erc/resources/erc-d/resources/foreign.eld
new file mode 100644
index 00000000000..64a5dca8b10
--- /dev/null
+++ b/test/lisp/erc/resources/erc-d/resources/foreign.eld
@@ -0,0 +1,5 @@
+;;; -*- mode: lisp-data -*-
+((one 5 "ONE one")
+ (0 "echo ONE one"))
+((two 5 "TWO two")
+ (0 "echo TWO two"))
diff --git a/test/lisp/erc/resources/erc-d/resources/fuzzy.eld b/test/lisp/erc/resources/erc-d/resources/fuzzy.eld
new file mode 100644
index 00000000000..0504b6a6682
--- /dev/null
+++ b/test/lisp/erc/resources/erc-d/resources/fuzzy.eld
@@ -0,0 +1,42 @@
+;;; -*- mode: lisp-data -*-
+((pass 10.0 "PASS " (? ?:) "changeme"))
+((nick 0.2 "NICK tester"))
+
+((user 0.5 "USER user 0 * :tester")
+ (0.0 "@time=" now " :irc.org 001 tester :Welcome to the Internet Relay Network tester")
+ (0.0 "@time=" now " :irc.org 002 tester :Your host is irc.org")
+ (0.0 "@time=" now " :irc.org 003 tester :This server was created just now")
+ (0.0 "@time=" now " :irc.org 004 tester irc.org BERios CEIRabehiklmnoqstv Iabehkloqv")
+ (0.0 "@time=" now " :irc.org 005 tester MODES NETWORK=ExampleOrg NICKLEN=32 PREFIX=(qaohv)~&@%+ :are supported by this server")
+ (0.0 "@time=" now " :irc.org 251 tester :There are 3 users and 0 invisible on 1 server(s)")
+ (0.0 "@time=" now " :irc.org 252 tester 0 :IRC Operators online")
+ (0.0 "@time=" now " :irc.org 253 tester 0 :unregistered connections")
+ (0.0 "@time=" now " :irc.org 254 tester 1 :channels formed")
+ (0.0 "@time=" now " :irc.org 255 tester :I have 3 clients and 0 servers")
+ (0.0 "@time=" now " :irc.org 265 tester 3 3 :Current local users 3, max 3")
+ (0.0 "@time=" now " :irc.org 266 tester 3 3 :Current global users 3, max 3")
+ (0.0 "@time=" now " :irc.org 422 tester :MOTD File is missing"))
+
+((mode-user 1.2 "MODE tester +i")
+ (0.0 "@time=" now " :irc.org 221 tester +Zi")
+ (0.0 "@time=" now " :irc.org 306 tester :You have been marked as being away"))
+
+((~join-foo 3.2 "JOIN #foo")
+ (0 "@time=" now " :tester!~tester@localhost JOIN #foo")
+ (0 "@time=" now " :irc.example.org 353 alice = #foo :+alice!~alice@example.com @%+bob!~bob@example.org")
+ (0 "@time=" now " :irc.example.org 366 alice #foo :End of NAMES list"))
+
+((~join-bar 1.2 "JOIN #bar")
+ (0 "@time=" now " :tester!~tester@localhost JOIN #bar")
+ (0 "@time=" now " :irc.example.org 353 alice = #bar :+alice!~alice@example.com @%+bob!~bob@example.org")
+ (0 "@time=" now " :irc.example.org 366 alice #bar :End of NAMES list"))
+
+((~mode-foo 3.2 "MODE #foo")
+ (0.0 "@time=" now " :irc.example.org 324 tester #foo +Cint")
+ (0.0 "@time=" now " :irc.example.org 329 tester #foo 1519850102")
+ (0.1 "@time=" now " :bob!~bob@example.org PRIVMSG #foo :hey"))
+
+((mode-bar 10.2 "MODE #bar")
+ (0.0 "@time=" now " :irc.example.org 324 tester #bar +HMfnrt 50:5h :10:5")
+ (0.0 "@time=" now " :irc.example.org 329 tester #bar :1602642829")
+ (0.1 "@time=" now " :alice!~alice@example.com PRIVMSG #bar :hi"))
diff --git a/test/lisp/erc/resources/erc-d/resources/incremental.eld b/test/lisp/erc/resources/erc-d/resources/incremental.eld
new file mode 100644
index 00000000000..a1b48495ec3
--- /dev/null
+++ b/test/lisp/erc/resources/erc-d/resources/incremental.eld
@@ -0,0 +1,43 @@
+;;; -*- mode: lisp-data -*-
+((pass 10.0 "PASS " (? ?:) "changeme"))
+((nick 0.2 "NICK tester"))
+
+((user 0.2 "USER user 0 * :tester")
+ (0.0 ":irc.foo.net 001 tester :Welcome to the Internet Relay Network tester")
+ (0.0 ":irc.foo.net 002 tester :Your host is irc.foo.net")
+ (0.0 ":irc.foo.net 003 tester :This server was created just now")
+ (0.0 ":irc.foo.net 004 tester irc.foo.net BERios CEIRabehiklmnoqstv Iabehkloqv")
+ (0.0 ":irc.foo.net 005 tester MODES NETWORK=FooNet NICKLEN=32 PREFIX=(qaohv)~&@%+"
+ " :are supported by this server")
+ (0.0 ":irc.foo.net 251 tester :There are 3 users and 0 invisible on 1 server(s)")
+ (0.0 ":irc.foo.net 252 tester 0 :IRC Operators online")
+ (0.0 ":irc.foo.net 253 tester 0 :unregistered connections")
+ (0.0 ":irc.foo.net 254 tester 1 :channels formed")
+ (0.0 ":irc.foo.net 255 tester :I have 3 clients and 0 servers")
+ (0.0 ":irc.foo.net 265 tester 3 3 :Current local users 3, max 3")
+ (0.0 ":irc.foo.net 266 tester 3 3 :Current global users 3, max 3")
+ (0.0 ":irc.foo.net 422 tester :MOTD File is missing"))
+
+((mode-user 1.2 "MODE tester +i")
+ (0.0 ":irc.foo.net 221 tester +Zi")
+ (0.0 ":irc.foo.net 306 tester :You have been marked as being away"))
+
+((join 3 "JOIN #foo")
+ (0 ":tester!~tester@localhost JOIN #foo")
+ (0 ":irc.foo.net 353 alice = #foo :+alice!~alice@example.com @%+bob!~bob@example.org")
+ (0 ":irc.foo.net 366 alice #foo :End of NAMES list"))
+
+((mode 3 "MODE #foo")
+ (0.0 ":irc.foo.net 324 tester #foo +Cint")
+ (0.0 ":irc.foo.net 329 tester #foo 1519850102")
+ (0.1 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #foo :alice: But, in defense, by mercy, 'tis most just.")
+ (0.1 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #foo :bob: Grows, lives, and dies, in single blessedness.")
+ (0.1 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #foo :Look for me.")
+ (0.1 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #foo :bob: By this hand, it will not kill a fly. But come, now I will be your Rosalind in a more coming-on disposition; and ask me what you will, I will grant it.")
+ (0.1 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #foo :alice: That I must love a loathed enemy.")
+ (0.1 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #foo :bob: As't please your lordship: I'll leave you.")
+ (0.1 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #foo :alice: Then there is no true lover in the forest; else sighing every minute and groaning every hour would detect the lazy foot of Time as well as a clock.")
+ (0.1 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #foo :bob: His discretion, I am sure, cannot carry his valour, for the goose carries not the fox. It is well: leave it to his discretion, and let us listen to the moon.")
+ (0.1 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #foo :Done"))
+
+((hi 10 "PRIVMSG #foo :Hi"))
diff --git a/test/lisp/erc/resources/erc-d/resources/irc-parser-tests.eld b/test/lisp/erc/resources/erc-d/resources/irc-parser-tests.eld
new file mode 100644
index 00000000000..168569f5481
--- /dev/null
+++ b/test/lisp/erc/resources/erc-d/resources/irc-parser-tests.eld
@@ -0,0 +1,380 @@
+;;; -*- mode: lisp-data; -*-
+
+;; https://github.com/DanielOaks/irc-parser-tests
+((mask-match
+ (tests
+ ((mask . "*@127.0.0.1")
+ (matches "coolguy!ab@127.0.0.1" "cooldud3!~bc@127.0.0.1")
+ (fails "coolguy!ab@127.0.0.5" "cooldud3!~d@124.0.0.1"))
+ ((mask . "cool*@*")
+ (matches "coolguy!ab@127.0.0.1" "cooldud3!~bc@127.0.0.1" "cool132!ab@example.com")
+ (fails "koolguy!ab@127.0.0.5" "cooodud3!~d@124.0.0.1"))
+ ((mask . "cool!*@*")
+ (matches "cool!guyab@127.0.0.1" "cool!~dudebc@127.0.0.1" "cool!312ab@example.com")
+ (fails "coolguy!ab@127.0.0.1" "cooldud3!~bc@127.0.0.1" "koolguy!ab@127.0.0.5" "cooodud3!~d@124.0.0.1"))
+ ((mask . "cool!?username@*")
+ (matches "cool!ausername@127.0.0.1" "cool!~username@127.0.0.1")
+ (fails "cool!username@127.0.0.1"))
+ ((mask . "cool!a?*@*")
+ (matches "cool!ab@127.0.0.1" "cool!abc@127.0.0.1")
+ (fails "cool!a@127.0.0.1"))
+ ((mask . "cool[guy]!*@*")
+ (matches "cool[guy]!guy@127.0.0.1" "cool[guy]!a@example.com")
+ (fails "coolg!ab@127.0.0.1" "cool[!ac@127.0.1.1"))))
+ (msg-join
+ (tests
+ ((desc . "Simple test with verb and params.")
+ (atoms
+ (verb . "foo")
+ (params "bar" "baz" "asdf"))
+ (matches "foo bar baz asdf" "foo bar baz :asdf"))
+ ((desc . "Simple test with source and no params.")
+ (atoms
+ (source . "src")
+ (verb . "AWAY"))
+ (matches ":src AWAY"))
+ ((desc . "Simple test with source and empty trailing param.")
+ (atoms
+ (source . "src")
+ (verb . "AWAY")
+ (params ""))
+ (matches ":src AWAY :"))
+ ((desc . "Simple test with source.")
+ (atoms
+ (source . "coolguy")
+ (verb . "foo")
+ (params "bar" "baz" "asdf"))
+ (matches ":coolguy foo bar baz asdf" ":coolguy foo bar baz :asdf"))
+ ((desc . "Simple test with trailing param.")
+ (atoms
+ (verb . "foo")
+ (params "bar" "baz" "asdf quux"))
+ (matches "foo bar baz :asdf quux"))
+ ((desc . "Simple test with empty trailing param.")
+ (atoms
+ (verb . "foo")
+ (params "bar" "baz" ""))
+ (matches "foo bar baz :"))
+ ((desc . "Simple test with trailing param containing colon.")
+ (atoms
+ (verb . "foo")
+ (params "bar" "baz" ":asdf"))
+ (matches "foo bar baz ::asdf"))
+ ((desc . "Test with source and trailing param.")
+ (atoms
+ (source . "coolguy")
+ (verb . "foo")
+ (params "bar" "baz" "asdf quux"))
+ (matches ":coolguy foo bar baz :asdf quux"))
+ ((desc . "Test with trailing containing beginning+end whitespace.")
+ (atoms
+ (source . "coolguy")
+ (verb . "foo")
+ (params "bar" "baz" " asdf quux "))
+ (matches ":coolguy foo bar baz : asdf quux "))
+ ((desc . "Test with trailing containing what looks like another trailing param.")
+ (atoms
+ (source . "coolguy")
+ (verb . "PRIVMSG")
+ (params "bar" "lol :) "))
+ (matches ":coolguy PRIVMSG bar :lol :) "))
+ ((desc . "Simple test with source and empty trailing.")
+ (atoms
+ (source . "coolguy")
+ (verb . "foo")
+ (params "bar" "baz" ""))
+ (matches ":coolguy foo bar baz :"))
+ ((desc . "Trailing contains only spaces.")
+ (atoms
+ (source . "coolguy")
+ (verb . "foo")
+ (params "bar" "baz" " "))
+ (matches ":coolguy foo bar baz : "))
+ ((desc . "Param containing tab (tab is not considered SPACE for message splitting).")
+ (atoms
+ (source . "coolguy")
+ (verb . "foo")
+ (params "b ar" "baz"))
+ (matches ":coolguy foo b ar baz" ":coolguy foo b ar :baz"))
+ ((desc . "Tag with no value and space-filled trailing.")
+ (atoms
+ (tags
+ (asd . ""))
+ (source . "coolguy")
+ (verb . "foo")
+ (params "bar" "baz" " "))
+ (matches "@asd :coolguy foo bar baz : "))
+ ((desc . "Tags with escaped values.")
+ (atoms
+ (verb . "foo")
+ (tags
+ (a . "b\\and\nk")
+ (d . "gh;764")))
+ (matches "@a=b\\\\and\\nk;d=gh\\:764 foo" "@d=gh\\:764;a=b\\\\and\\nk foo"))
+ ((desc . "Tags with escaped values and params.")
+ (atoms
+ (verb . "foo")
+ (tags
+ (a . "b\\and\nk")
+ (d . "gh;764"))
+ (params "par1" "par2"))
+ (matches "@a=b\\\\and\\nk;d=gh\\:764 foo par1 par2" "@a=b\\\\and\\nk;d=gh\\:764 foo par1 :par2" "@d=gh\\:764;a=b\\\\and\\nk foo par1 par2" "@d=gh\\:764;a=b\\\\and\\nk foo par1 :par2"))
+ ((desc . "Tag with long, strange values (including LF and newline).")
+ (atoms
+ (tags
+ (foo . "\\\\;\\s \n"))
+ (verb . "COMMAND"))
+ (matches "@foo=\\\\\\\\\\:\\\\s\\s\\r\\n COMMAND"))))
+ (msg-split
+ (tests
+ ((input . "foo bar baz asdf")
+ (atoms
+ (verb . "foo")
+ (params "bar" "baz" "asdf")))
+ ((input . ":coolguy foo bar baz asdf")
+ (atoms
+ (source . "coolguy")
+ (verb . "foo")
+ (params "bar" "baz" "asdf")))
+ ((input . "foo bar baz :asdf quux")
+ (atoms
+ (verb . "foo")
+ (params "bar" "baz" "asdf quux")))
+ ((input . "foo bar baz :")
+ (atoms
+ (verb . "foo")
+ (params "bar" "baz" "")))
+ ((input . "foo bar baz ::asdf")
+ (atoms
+ (verb . "foo")
+ (params "bar" "baz" ":asdf")))
+ ((input . ":coolguy foo bar baz :asdf quux")
+ (atoms
+ (source . "coolguy")
+ (verb . "foo")
+ (params "bar" "baz" "asdf quux")))
+ ((input . ":coolguy foo bar baz : asdf quux ")
+ (atoms
+ (source . "coolguy")
+ (verb . "foo")
+ (params "bar" "baz" " asdf quux ")))
+ ((input . ":coolguy PRIVMSG bar :lol :) ")
+ (atoms
+ (source . "coolguy")
+ (verb . "PRIVMSG")
+ (params "bar" "lol :) ")))
+ ((input . ":coolguy foo bar baz :")
+ (atoms
+ (source . "coolguy")
+ (verb . "foo")
+ (params "bar" "baz" "")))
+ ((input . ":coolguy foo bar baz : ")
+ (atoms
+ (source . "coolguy")
+ (verb . "foo")
+ (params "bar" "baz" " ")))
+ ((input . "@a=b;c=32;k;rt=ql7 foo")
+ (atoms
+ (verb . "foo")
+ (tags
+ (a . "b")
+ (c . "32")
+ (k . "")
+ (rt . "ql7"))))
+ ((input . "@a=b\\\\and\\nk;c=72\\s45;d=gh\\:764 foo")
+ (atoms
+ (verb . "foo")
+ (tags
+ (a . "b\\and\nk")
+ (c . "72 45")
+ (d . "gh;764"))))
+ ((input . "@c;h=;a=b :quux ab cd")
+ (atoms
+ (tags
+ (c . "")
+ (h . "")
+ (a . "b"))
+ (source . "quux")
+ (verb . "ab")
+ (params "cd")))
+ ((input . ":src JOIN #chan")
+ (atoms
+ (source . "src")
+ (verb . "JOIN")
+ (params "#chan")))
+ ((input . ":src JOIN :#chan")
+ (atoms
+ (source . "src")
+ (verb . "JOIN")
+ (params "#chan")))
+ ((input . ":src AWAY")
+ (atoms
+ (source . "src")
+ (verb . "AWAY")))
+ ((input . ":src AWAY ")
+ (atoms
+ (source . "src")
+ (verb . "AWAY")))
+ ((input . ":cool guy foo bar baz")
+ (atoms
+ (source . "cool guy")
+ (verb . "foo")
+ (params "bar" "baz")))
+ ((input . ":coolguy!ag@net5work.admin PRIVMSG foo :bar baz")
+ (atoms
+ (source . "coolguy!ag@net5work.admin")
+ (verb . "PRIVMSG")
+ (params "foo" "bar baz")))
+ ((input . ":coolguy!~ag@net05work.admin PRIVMSG foo :bar baz")
+ (atoms
+ (source . "coolguy!~ag@net05work.admin")
+ (verb . "PRIVMSG")
+ (params "foo" "bar baz")))
+ ((input . "@tag1=value1;tag2;vendor1/tag3=value2;vendor2/tag4= :irc.example.com COMMAND param1 param2 :param3 param3")
+ (atoms
+ (tags
+ (tag1 . "value1")
+ (tag2 . "")
+ (vendor1/tag3 . "value2")
+ (vendor2/tag4 . ""))
+ (source . "irc.example.com")
+ (verb . "COMMAND")
+ (params "param1" "param2" "param3 param3")))
+ ((input . ":irc.example.com COMMAND param1 param2 :param3 param3")
+ (atoms
+ (source . "irc.example.com")
+ (verb . "COMMAND")
+ (params "param1" "param2" "param3 param3")))
+ ((input . "@tag1=value1;tag2;vendor1/tag3=value2;vendor2/tag4 COMMAND param1 param2 :param3 param3")
+ (atoms
+ (tags
+ (tag1 . "value1")
+ (tag2 . "")
+ (vendor1/tag3 . "value2")
+ (vendor2/tag4 . ""))
+ (verb . "COMMAND")
+ (params "param1" "param2" "param3 param3")))
+ ((input . "COMMAND")
+ (atoms
+ (verb . "COMMAND")))
+ ((input . "@foo=\\\\\\\\\\:\\\\s\\s\\r\\n COMMAND")
+ (atoms
+ (tags
+ (foo . "\\\\;\\s \n"))
+ (verb . "COMMAND")))
+ ((input . ":gravel.mozilla.org 432 #momo :Erroneous Nickname: Illegal characters")
+ (atoms
+ (source . "gravel.mozilla.org")
+ (verb . "432")
+ (params "#momo" "Erroneous Nickname: Illegal characters")))
+ ((input . ":gravel.mozilla.org MODE #tckk +n ")
+ (atoms
+ (source . "gravel.mozilla.org")
+ (verb . "MODE")
+ (params "#tckk" "+n")))
+ ((input . ":services.esper.net MODE #foo-bar +o foobar ")
+ (atoms
+ (source . "services.esper.net")
+ (verb . "MODE")
+ (params "#foo-bar" "+o" "foobar")))
+ ((input . "@tag1=value\\\\ntest COMMAND")
+ (atoms
+ (tags
+ (tag1 . "value\\ntest"))
+ (verb . "COMMAND")))
+ ((input . "@tag1=value\\1 COMMAND")
+ (atoms
+ (tags
+ (tag1 . "value1"))
+ (verb . "COMMAND")))
+ ((input . "@tag1=value1\\ COMMAND")
+ (atoms
+ (tags
+ (tag1 . "value1"))
+ (verb . "COMMAND")))
+ ((input . "@tag1=1;tag2=3;tag3=4;tag1=5 COMMAND")
+ (atoms
+ (tags
+ (tag1 . "5")
+ (tag2 . "3")
+ (tag3 . "4"))
+ (verb . "COMMAND")))
+ ((input . "@tag1=1;tag2=3;tag3=4;tag1=5;vendor/tag2=8 COMMAND")
+ (atoms
+ (tags
+ (tag1 . "5")
+ (tag2 . "3")
+ (tag3 . "4")
+ (vendor/tag2 . "8"))
+ (verb . "COMMAND")))
+ ((input . ":SomeOp MODE #channel :+i")
+ (atoms
+ (source . "SomeOp")
+ (verb . "MODE")
+ (params "#channel" "+i")))
+ ((input . ":SomeOp MODE #channel +oo SomeUser :AnotherUser")
+ (atoms
+ (source . "SomeOp")
+ (verb . "MODE")
+ (params "#channel" "+oo" "SomeUser" "AnotherUser")))))
+ (userhost-split
+ (tests
+ ((source . "coolguy")
+ (atoms
+ (nick . "coolguy")))
+ ((source . "coolguy!ag@127.0.0.1")
+ (atoms
+ (nick . "coolguy")
+ (user . "ag")
+ (host . "127.0.0.1")))
+ ((source . "coolguy!~ag@localhost")
+ (atoms
+ (nick . "coolguy")
+ (user . "~ag")
+ (host . "localhost")))
+ ((source . "coolguy@127.0.0.1")
+ (atoms
+ (nick . "coolguy")
+ (host . "127.0.0.1")))
+ ((source . "coolguy!ag")
+ (atoms
+ (nick . "coolguy")
+ (user . "ag")))
+ ((source . "coolguy!ag@net5work.admin")
+ (atoms
+ (nick . "coolguy")
+ (user . "ag")
+ (host . "net5work.admin")))
+ ((source . "coolguy!~ag@net05work.admin")
+ (atoms
+ (nick . "coolguy")
+ (user . "~ag")
+ (host . "net05work.admin")))))
+ (validate-hostname
+ (tests
+ ((host . "irc.example.com")
+ (valid . t))
+ ((host . "i.coolguy.net")
+ (valid . t))
+ ((host . "irc-srv.net.uk")
+ (valid . t))
+ ((host . "iRC.CooLguY.NeT")
+ (valid . t))
+ ((host . "gsf.ds342.co.uk")
+ (valid . t))
+ ((host . "324.net.uk")
+ (valid . t))
+ ((host . "xn--bcher-kva.ch")
+ (valid . t))
+ ((host . "-lol-.net.uk")
+ (valid . :false))
+ ((host . "-lol.net.uk")
+ (valid . :false))
+ ((host . "_irc._sctp.lol.net.uk")
+ (valid . :false))
+ ((host . "irc")
+ (valid . :false))
+ ((host . "com")
+ (valid . :false))
+ ((host . "")
+ (valid . :false)))))
diff --git a/test/lisp/erc/resources/erc-d/resources/linger-multi-a.eld b/test/lisp/erc/resources/erc-d/resources/linger-multi-a.eld
new file mode 100644
index 00000000000..751500537d9
--- /dev/null
+++ b/test/lisp/erc/resources/erc-d/resources/linger-multi-a.eld
@@ -0,0 +1,3 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS " (? ?:) "a"))
+((linger 100 LINGER)) \ No newline at end of file
diff --git a/test/lisp/erc/resources/erc-d/resources/linger-multi-b.eld b/test/lisp/erc/resources/erc-d/resources/linger-multi-b.eld
new file mode 100644
index 00000000000..c906c9e649b
--- /dev/null
+++ b/test/lisp/erc/resources/erc-d/resources/linger-multi-b.eld
@@ -0,0 +1,3 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS " (? ?:) "b"))
+((linger 1 LINGER))
diff --git a/test/lisp/erc/resources/erc-d/resources/linger.eld b/test/lisp/erc/resources/erc-d/resources/linger.eld
new file mode 100644
index 00000000000..36c81a3af4b
--- /dev/null
+++ b/test/lisp/erc/resources/erc-d/resources/linger.eld
@@ -0,0 +1,33 @@
+;;; -*- mode: lisp-data -*-
+
+((pass 10.0 "PASS " (? ?:) "changeme"))
+((nick 0.2 "NICK tester"))
+
+((user 0.2 "USER user 0 * :tester")
+ (0 ":irc.example.org 001 tester :Welcome to the Internet Relay Network tester")
+ (0 ":irc.example.org 002 tester :Your host is irc.example.org")
+ (0 ":irc.example.org 003 tester :This server was created just now")
+ (0 ":irc.example.org 004 tester irc.example.org BERios CEIRabehiklmnoqstv Iabehkloqv")
+ (0 ":irc.example.org 005 tester MODES NETWORK=ExampleOrg NICKLEN=32 PREFIX=(qaohv)~&@%+"
+ " :are supported by this server")
+ (0 ":irc.example.org 251 tester :There are 3 users and 0 invisible on 1 server(s)")
+ ;; Just to mix thing's up (force handler to schedule timer)
+ (0.1 ":irc.example.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.example.org 253 tester 0 :unregistered connections")
+ (0 ":irc.example.org 254 tester 1 :channels formed")
+ (0 ":irc.example.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.example.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.example.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.example.org 422 tester :MOTD File is missing"))
+
+((mode-user 1.2 "MODE tester +i")
+ (0 ":irc.example.org 221 tester +Zi")
+ (0 ":irc.example.org 306 tester :You have been marked as being away")
+ (0 ":tester!~tester@localhost JOIN #chan")
+ (0 ":irc.example.org 353 alice = #chan :+alice!~alice@example.com @%+bob!~bob@example.org")
+ (0 ":irc.example.org 366 alice #chan :End of NAMES list"))
+
+((mode-chan 1.2 "MODE #chan")
+ (0 ":bob!~bob@example.org PRIVMSG #chan :hey"))
+
+((linger 1.0 LINGER))
diff --git a/test/lisp/erc/resources/erc-d/resources/no-block.eld b/test/lisp/erc/resources/erc-d/resources/no-block.eld
new file mode 100644
index 00000000000..2811923d8ac
--- /dev/null
+++ b/test/lisp/erc/resources/erc-d/resources/no-block.eld
@@ -0,0 +1,55 @@
+;;; -*- mode: lisp-data -*-
+((pass 10.0 "PASS " (? ?:) "changeme"))
+((nick 0.2 "NICK tester"))
+
+((user 0.2 "USER user 0 * :tester")
+ (0.0 ":irc.org 001 tester :Welcome to the Internet Relay Network tester")
+ (0.0 ":irc.org 002 tester :Your host is irc.org")
+ (0.0 ":irc.org 003 tester :This server was created just now")
+ (0.0 ":irc.org 004 tester irc.org BERios CEIRabehiklmnoqstv Iabehkloqv")
+ (0.0 ":irc.org 005 tester MODES NETWORK=ExampleOrg NICKLEN=32 PREFIX=(qaohv)~&@%+"
+ " :are supported by this server")
+ (0.0 ":irc.org 251 tester :There are 3 users and 0 invisible on 1 server(s)")
+ (0.0 ":irc.org 252 tester 0 :IRC Operators online")
+ (0.0 ":irc.org 253 tester 0 :unregistered connections")
+ (0.0 ":irc.org 254 tester 1 :channels formed")
+ (0.0 ":irc.org 255 tester :I have 3 clients and 0 servers")
+ (0.0 ":irc.org 265 tester 3 3 :Current local users 3, max 3")
+ (0.0 ":irc.org 266 tester 3 3 :Current global users 3, max 3")
+ (0.0 ":irc.org 422 tester :MOTD File is missing"))
+
+((mode-user 1.2 "MODE tester +i")
+ (0.0 ":irc.org 221 tester +Zi")
+ (0.0 ":irc.org 306 tester :You have been marked as being away"))
+
+((join-foo 1.2 "JOIN #foo")
+ (0 ":tester!~tester@localhost JOIN #foo")
+ (0 ":irc.example.org 353 alice = #foo :+alice!~alice@example.com @%+bob!~bob@example.org")
+ (0 ":irc.example.org 366 alice #foo :End of NAMES list"))
+
+;; This would time out if the mode-foo's outgoing blocked (remove minus signs to see)
+((~join-bar 1.5 "JOIN #bar")
+ (0 ":tester!~tester@localhost JOIN #bar")
+ (0 ":irc.example.org 353 alice = #bar :+alice!~alice@example.com @%+bob!~bob@example.org")
+ (0 ":irc.example.org 366 alice #bar :End of NAMES list"))
+
+((mode-foo 1.2 "MODE #foo")
+ (0.0 ":irc.example.org 324 tester #foo +Cint")
+ (0.0 ":irc.example.org 329 tester #foo 1519850102")
+ (-0.1 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #foo :alice: But, in defense, by mercy, 'tis most just.")
+ (-0.2 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #foo :bob: Grows, lives, and dies, in single blessedness.")
+ (-0.3 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #foo :alice: For these two hours, Rosalind, I will leave thee.")
+ (-0.4 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #foo :bob: By this hand, it will not kill a fly. But come, now I will be your Rosalind in a more coming-on disposition; and ask me what you will, I will grant it.")
+ (-0.5 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #foo :alice: That I must love a loathed enemy.")
+ (-0.6 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #foo :bob: As't please your lordship: I'll leave you.")
+ (-0.7 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #foo :alice: Then there is no true lover in the forest; else sighing every minute and groaning every hour would detect the lazy foot of Time as well as a clock.")
+ (-0.8 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #foo :bob: His discretion, I am sure, cannot carry his valour, for the goose carries not the fox. It is well: leave it to his discretion, and let us listen to the moon.")
+ (-0.9 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #foo :alice: As living here and you no use of him.")
+ (-1.0 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #foo :bob: If there be truth in sight, you are my Rosalind.")
+ (-1.1 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #foo :alice: That is another's lawful promis'd love.")
+ (-1.1 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #foo :I am heard."))
+
+((mode-bar 1.5 "MODE #bar")
+ (0.0 ":irc.example.org 324 tester #bar +HMfnrt 50:5h :10:5")
+ (0.0 ":irc.example.org 329 tester #bar :1602642829")
+ (0.1 ":alice!~alice@example.com PRIVMSG #bar :hi 123"))
diff --git a/test/lisp/erc/resources/erc-d/resources/no-match.eld b/test/lisp/erc/resources/erc-d/resources/no-match.eld
new file mode 100644
index 00000000000..d147be1e084
--- /dev/null
+++ b/test/lisp/erc/resources/erc-d/resources/no-match.eld
@@ -0,0 +1,32 @@
+;;; -*- mode: lisp-data -*-
+
+((pass 10.0 "PASS " (? ?:) "changeme"))
+((nick 0.2 "NICK tester"))
+
+((user 0.2 "USER user 0 * :tester")
+ (0 ":irc.example.org 001 tester :Welcome to the Internet Relay Network tester")
+ (0 ":irc.example.org 002 tester :Your host is irc.example.org")
+ (0 ":irc.example.org 003 tester :This server was created just now")
+ (0 ":irc.example.org 004 tester irc.example.org BERios CEIRabehiklmnoqstv Iabehkloqv")
+ (0 ":irc.example.org 005 tester MODES NETWORK=ExampleOrg NICKLEN=32 PREFIX=(qaohv)~&@%+"
+ " :are supported by this server")
+ (0 ":irc.example.org 251 tester :There are 3 users and 0 invisible on 1 server(s)")
+ (0 ":irc.example.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.example.org 253 tester 0 :unregistered connections")
+ (0 ":irc.example.org 254 tester 1 :channels formed")
+ (0 ":irc.example.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.example.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.example.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.example.org 422 tester :MOTD File is missing"))
+
+((mode-user 1.2 "MODE tester +i")
+ (0 ":irc.example.org 221 tester +Zi")
+ (0 ":irc.example.org 306 tester :You have been marked as being away"))
+
+((join 1.2 "JOIN #chan")
+ (0 ":tester!~tester@localhost JOIN #chan")
+ (0 ":irc.example.org 353 alice = #chan :+alice!~alice@example.com @%+bob!~bob@example.org")
+ (0 ":irc.example.org 366 alice #chan :End of NAMES list"))
+
+((mode-chan 0.2 "MODE #chan")
+ (0.1 ":bob!~bob@example.org PRIVMSG #chan :hey"))
diff --git a/test/lisp/erc/resources/erc-d/resources/no-pong.eld b/test/lisp/erc/resources/erc-d/resources/no-pong.eld
new file mode 100644
index 00000000000..30cd805d76c
--- /dev/null
+++ b/test/lisp/erc/resources/erc-d/resources/no-pong.eld
@@ -0,0 +1,27 @@
+;;; -*- mode: lisp-data -*-
+
+((pass 10.0 "PASS " (? ?:) "changeme"))
+((nick 0.2 "NICK tester"))
+
+((~ping 1.2 "PING " nonce)
+ (0.1 ":irc.example.org PONG irc.example.com " echo))
+
+((user 0.2 "USER user 0 * :tester")
+ (0 ":irc.example.org 001 tester :Welcome to the Internet Relay Network tester")
+ (0 ":irc.example.org 002 tester :Your host is irc.example.org")
+ (0 ":irc.example.org 003 tester :This server was created just now")
+ (0 ":irc.example.org 004 tester irc.example.org BERios CEIRabehiklmnoqstv Iabehkloqv")
+ (0 ":irc.example.org 005 tester MODES NETWORK=ExampleOrg NICKLEN=32 PREFIX=(qaohv)~&@%+"
+ " :are supported by this server")
+ (0 ":irc.example.org 251 tester :There are 3 users and 0 invisible on 1 server(s)")
+ (0 ":irc.example.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.example.org 253 tester 0 :unregistered connections")
+ (0 ":irc.example.org 254 tester 1 :channels formed")
+ (0 ":irc.example.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.example.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.example.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.example.org 422 tester :MOTD File is missing"))
+
+((mode-user 1.2 "MODE tester +i")
+ (0 ":irc.example.org 221 tester +Zi")
+ (0 ":irc.example.org 306 tester :You have been marked as being away"))
diff --git a/test/lisp/erc/resources/erc-d/resources/nonstandard.eld b/test/lisp/erc/resources/erc-d/resources/nonstandard.eld
new file mode 100644
index 00000000000..c9cd608e6be
--- /dev/null
+++ b/test/lisp/erc/resources/erc-d/resources/nonstandard.eld
@@ -0,0 +1,6 @@
+;;; -*- mode: lisp-data -*-
+((one 1 "ONE one"))
+((two 1 "TWO two"))
+((blank 1 ""))
+((one-space 1 " "))
+((two-spaces 1 " "))
diff --git a/test/lisp/erc/resources/erc-d/resources/proxy-barnet.eld b/test/lisp/erc/resources/erc-d/resources/proxy-barnet.eld
new file mode 100644
index 00000000000..e74d20d5b37
--- /dev/null
+++ b/test/lisp/erc/resources/erc-d/resources/proxy-barnet.eld
@@ -0,0 +1,24 @@
+;;; -*- mode: lisp-data -*-
+
+((pass 10.0 "PASS " (? ?:) network ":changeme"))
+((nick 1.2 "NICK tester"))
+
+((user 1.2 "USER user 0 * :tester")
+ (0.001 ":" fqdn " 001 tester :Welcome to the BAR Network tester")
+ (0.002 ":" fqdn " 002 tester :Your host is " fqdn)
+ (0.003 ":" fqdn " 003 tester :This server was created just now")
+ (0.004 ":" fqdn " 004 tester " fqdn " BERios CEIRabehiklmnoqstv Iabehkloqv")
+ (0.005 ":" fqdn " 005 tester MODES NETWORK=" net " NICKLEN=32 PREFIX=(qaohv)~&@%+"
+ " :are supported by this server")
+ (0.006 ":" fqdn " 251 tester :There are 3 users and 0 invisible on 1 server(s)")
+ (0.007 ":" fqdn " 252 tester 0 :IRC Operators online")
+ (0.008 ":" fqdn " 253 tester 0 :unregistered connections")
+ (0.009 ":" fqdn " 254 tester 1 :channels formed")
+ (0.010 ":" fqdn " 255 tester :I have 3 clients and 0 servers")
+ (0.011 ":" fqdn " 265 tester 3 3 :Current local users 3, max 3")
+ (0.012 ":" fqdn " 266 tester 3 3 :Current global users 3, max 3")
+ (0.013 ":" fqdn " 422 tester :MOTD File is missing"))
+
+((mode-user 1.2 "MODE tester +i")
+ (0.014 ":" fqdn " 221 tester +Zi")
+ (0.015 ":" fqdn " 306 tester :You have been marked as being away"))
diff --git a/test/lisp/erc/resources/erc-d/resources/proxy-foonet.eld b/test/lisp/erc/resources/erc-d/resources/proxy-foonet.eld
new file mode 100644
index 00000000000..cc2e9d253c1
--- /dev/null
+++ b/test/lisp/erc/resources/erc-d/resources/proxy-foonet.eld
@@ -0,0 +1,24 @@
+;;; -*- mode: lisp-data -*-
+
+((pass 10.0 "PASS " (? ?:) network ":changeme"))
+((nick 1.2 "NICK tester"))
+
+((user 2.2 "USER user 0 * :tester")
+ (0.015 ":" fqdn " 001 tester :Welcome to the FOO Network tester")
+ (0.014 ":" fqdn " 002 tester :Your host is " fqdn)
+ (0.013 ":" fqdn " 003 tester :This server was created just now")
+ (0.012 ":" fqdn " 004 tester " fqdn " BERios CEIRabehiklmnoqstv Iabehkloqv")
+ (0.011 ":" fqdn " 005 tester MODES NETWORK=" net " NICKLEN=32 PREFIX=(qaohv)~&@%+"
+ " :are supported by this server")
+ (0.010 ":" fqdn " 251 tester :There are 3 users and 0 invisible on 1 server(s)")
+ (0.009 ":" fqdn " 252 tester 0 :IRC Operators online")
+ (0.008 ":" fqdn " 253 tester 0 :unregistered connections")
+ (0.007 ":" fqdn " 254 tester 1 :channels formed")
+ (0.006 ":" fqdn " 255 tester :I have 3 clients and 0 servers")
+ (0.005 ":" fqdn " 265 tester 3 3 :Current local users 3, max 3")
+ (0.004 ":" fqdn " 266 tester 3 3 :Current global users 3, max 3")
+ (0.003 ":" fqdn " 422 tester :MOTD File is missing"))
+
+((mode-user 1.2 "MODE tester +i")
+ (0.002 ":" fqdn " 221 tester +Zi")
+ (0.001 ":" fqdn " 306 tester :You have been marked as being away"))
diff --git a/test/lisp/erc/resources/erc-d/resources/proxy-solo.eld b/test/lisp/erc/resources/erc-d/resources/proxy-solo.eld
new file mode 100644
index 00000000000..af216c80edc
--- /dev/null
+++ b/test/lisp/erc/resources/erc-d/resources/proxy-solo.eld
@@ -0,0 +1,9 @@
+;;; -*- mode: lisp-data -*-
+
+((pass 10.0 "PASS " (? ?:) "changeme"))
+((nick 0.2 "NICK tester"))
+
+((user 0.2 "USER user 0 * :" (group (+ alpha)) eos)
+ (0 ":*status!znc@znc.in NOTICE " nick " :You have no networks configured."
+ " Use /znc AddNetwork <network> to add one.")
+ (0 ":irc.znc.in 001 " nick " :Welcome " nick "!"))
diff --git a/test/lisp/erc/resources/erc-d/resources/proxy-subprocess.el b/test/lisp/erc/resources/erc-d/resources/proxy-subprocess.el
new file mode 100644
index 00000000000..bb8869dff69
--- /dev/null
+++ b/test/lisp/erc/resources/erc-d/resources/proxy-subprocess.el
@@ -0,0 +1,45 @@
+;;; proxy-subprocess.el --- Example setup file for erc-d -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+;;; Code:
+
+(defvar erc-d-tmpl-vars)
+
+(setq erc-d-tmpl-vars
+
+ (list
+ (cons 'fqdn (lambda (helper)
+ (let ((name (funcall helper :dialog-name)))
+ (funcall helper :set
+ (if (eq name 'proxy-foonet)
+ "irc.foo.net"
+ "irc.bar.net")))))
+
+ (cons 'net (lambda (helper)
+ (let ((name (funcall helper :dialog-name)))
+ (funcall helper :set
+ (if (eq name 'proxy-foonet)
+ "FooNet"
+ "BarNet")))))
+
+ (cons 'network '(group (+ alpha)))))
+
+;;; proxy-subprocess.el ends here
diff --git a/test/lisp/erc/resources/erc-d/resources/timeout.eld b/test/lisp/erc/resources/erc-d/resources/timeout.eld
new file mode 100644
index 00000000000..9cfad4fa8cd
--- /dev/null
+++ b/test/lisp/erc/resources/erc-d/resources/timeout.eld
@@ -0,0 +1,27 @@
+;;; -*- mode: lisp-data -*-
+
+((pass 10.0 "PASS " (? ?:) "changeme"))
+((nick 0.2 "NICK tester"))
+
+((user 0.2 "USER user 0 * :tester")
+ (0 ":irc.example.org 001 tester :Welcome to the Internet Relay Network tester")
+ (0 ":irc.example.org 002 tester :Your host is irc.example.org")
+ (0 ":irc.example.org 003 tester :This server was created just now")
+ (0 ":irc.example.org 004 tester irc.example.org BERios CEIRabehiklmnoqstv Iabehkloqv")
+ (0 ":irc.example.org 005 tester MODES NETWORK=ExampleOrg NICKLEN=32 PREFIX=(qaohv)~&@%+"
+ " :are supported by this server")
+ (0 ":irc.example.org 251 tester :There are 3 users and 0 invisible on 1 server(s)")
+ (0 ":irc.example.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.example.org 253 tester 0 :unregistered connections")
+ (0 ":irc.example.org 254 tester 1 :channels formed")
+ (0 ":irc.example.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.example.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.example.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.example.org 422 tester :MOTD File is missing"))
+
+((mode-user 1.2 "MODE tester +i")
+ (0 ":irc.example.org 221 tester +Zi")
+ (0 ":irc.example.org 306 tester :You have been marked as being away"))
+
+((mode 0.2 "MODE #chan")
+ (0.1 ":bob!~bob@example.org PRIVMSG #chan :hey"))
diff --git a/test/lisp/erc/resources/erc-d/resources/unexpected.eld b/test/lisp/erc/resources/erc-d/resources/unexpected.eld
new file mode 100644
index 00000000000..ac0a8fecfa6
--- /dev/null
+++ b/test/lisp/erc/resources/erc-d/resources/unexpected.eld
@@ -0,0 +1,28 @@
+;;; -*- mode: lisp-data -*-
+((t 10.0 "PASS " (? ?:) "changeme"))
+((t 0.2 "NICK tester"))
+
+((t 0.2 "USER user 0 * :tester")
+ (0.0 ":irc.example.org 001 tester :Welcome to the Internet Relay Network tester")
+ (0.0 ":irc.example.org 002 tester :Your host is irc.example.org")
+ (0.0 ":irc.example.org 003 tester :This server was created just now")
+ (0.0 ":irc.example.org 004 tester irc.example.org BERios CEIRabehiklmnoqstv Iabehkloqv")
+ (0.0 ":irc.example.org 005 tester MODES NETWORK=ExampleOrg NICKLEN=32 PREFIX=(qaohv)~&@%+"
+ " :are supported by this server")
+ (0.0 ":irc.example.org 251 tester :There are 3 users and 0 invisible on 1 server(s)")
+ (0.0 ":irc.example.org 252 tester 0 :IRC Operators online")
+ (0.0 ":irc.example.org 253 tester 0 :unregistered connections")
+ (0.0 ":irc.example.org 254 tester 1 :channels formed")
+ (0.0 ":irc.example.org 255 tester :I have 3 clients and 0 servers")
+ (0.0 ":irc.example.org 265 tester 3 3 :Current local users 3, max 3")
+ (0.0 ":irc.example.org 266 tester 3 3 :Current global users 3, max 3")
+ (0.0 ":irc.example.org 422 tester :MOTD File is missing"))
+
+((mode-user 1.2 "MODE tester +i")
+ (0.0 ":irc.example.org 221 tester +Zi")
+
+ (0.0 ":irc.example.org 306 tester :You have been marked as being away")
+ (0.0 ":tester!~tester@localhost JOIN #chan")
+ (0.0 ":irc.example.org 353 alice = #chan :+alice!~alice@example.com @%+bob!~bob@example.org")
+ (0.0 ":irc.example.org 366 alice #chan :End of NAMES list")
+ (0.1 ":bob!~bob@example.org PRIVMSG #chan :hey"))
diff --git a/test/lisp/erc/resources/erc-scenarios-common.el b/test/lisp/erc/resources/erc-scenarios-common.el
new file mode 100644
index 00000000000..bc2cb68cd86
--- /dev/null
+++ b/test/lisp/erc/resources/erc-scenarios-common.el
@@ -0,0 +1,516 @@
+;;; erc-scenarios-common.el --- Common helpers for ERC scenarios -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; These are e2e-ish test cases primarily intended to assert core,
+;; fundamental behavior expected of any modern IRC client. Tests may
+;; also simulate specific scenarios drawn from bug reports. Incoming
+;; messages are provided by playback scripts resembling I/O logs. In
+;; place of time stamps, they have time deltas, which are used to
+;; govern the test server in a fashion reminiscent of music rolls (or
+;; the script(1) UNIX program). These scripts can be found in the
+;; other directories under test/lisp/erc/resources.
+;;
+;; Isolation:
+;;
+;; The set of enabled modules is shared among all tests. The function
+;; `erc-update-modules' activates them (as minor modes), but it never
+;; deactivates them. So there's no going back, and let-binding
+;; `erc-modules' is useless. The safest route is therefore to (1)
+;; assume the set of default modules is already activated or will be
+;; over the course of the test session and (2) let-bind relevant user
+;; options as needed. For example, to limit the damage of
+;; `erc-autojoin-channels-alist' to a given test, assume the
+;; `erc-join' library has already been loaded or will be on the next
+;; call to `erc-open'. And then just let-bind
+;; `erc-autojoin-channels-alist' for the duration of the test.
+;;
+;; Playing nice:
+;;
+;; Right now, these tests all rely on an ugly fixture macro named
+;; `erc-scenarios-common-with-cleanup', which is defined just below.
+;; It helps restore (but not really prepare) the environment by
+;; destroying any stray processes or buffers named in the first
+;; argument, a `let*'-style VAR-LIST. Relying on such a macro is
+;; unfortunate because in many ways it actually hampers readability by
+;; favoring magic over verbosity. But without it (or something
+;; similar), any failing test would cause all subsequent tests in this
+;; file to fail like dominoes (making all but the first backtrace
+;; useless).
+;;
+;; Misc:
+;;
+;; Note that in the following examples, nicknames Alice and Bob are
+;; always associated with the fake network FooNet, while nicks Joe and
+;; Mike are always on BarNet. (Networks are sometimes downcased.)
+;;
+;; XXX This file should *not* contain any test cases.
+
+;;; Code:
+
+(require 'ert-x) ; cl-lib
+(eval-and-compile
+ (let* ((d (expand-file-name ".." (ert-resource-directory)))
+ (load-path (cons (concat d "/erc-d") load-path)))
+ (require 'erc-d-t)
+ (require 'erc-d)))
+
+(require 'erc-backend)
+
+(eval-when-compile (require 'erc-join)
+ (require 'erc-services))
+
+(declare-function erc-network "erc-networks")
+(defvar erc-network)
+
+(defvar erc-scenarios-common--resources-dir
+ (expand-file-name "../" (ert-resource-directory)))
+
+;; Teardown is already inhibited when running interactively, which
+;; prevents subsequent tests from succeeding, so we might as well
+;; treat inspection as the goal.
+(unless noninteractive
+ (setq erc-server-auto-reconnect nil))
+
+(defvar erc-scenarios-common-dialog nil)
+(defvar erc-scenarios-common-extra-teardown nil)
+
+(defun erc-scenarios-common--add-silence ()
+ (advice-add #'erc-login :around #'erc-d-t-silence-around)
+ (advice-add #'erc-handle-login :around #'erc-d-t-silence-around)
+ (advice-add #'erc-server-connect :around #'erc-d-t-silence-around))
+
+(defun erc-scenarios-common--remove-silence ()
+ (advice-remove #'erc-login #'erc-d-t-silence-around)
+ (advice-remove #'erc-handle-login #'erc-d-t-silence-around)
+ (advice-remove #'erc-server-connect #'erc-d-t-silence-around))
+
+(defun erc-scenarios-common--print-trace ()
+ (when (and (boundp 'trace-buffer) (get-buffer trace-buffer))
+ (with-current-buffer trace-buffer
+ (message "%S" (buffer-string))
+ (kill-buffer))))
+
+(eval-and-compile
+ (defun erc-scenarios-common--make-bindings (bindings)
+ `((erc-d-u-canned-dialog-dir (expand-file-name
+ (or erc-scenarios-common-dialog
+ (cadr (assq 'erc-scenarios-common-dialog
+ ',bindings)))
+ erc-scenarios-common--resources-dir))
+ (erc-d-tmpl-vars `(,@erc-d-tmpl-vars
+ (quit . ,(erc-quit/part-reason-default))
+ (erc-version . ,erc-version)))
+ (erc-modules (copy-sequence erc-modules))
+ (inhibit-interaction t)
+ (auth-source-do-cache nil)
+ (erc-auth-source-parameters-join-function nil)
+ (erc-autojoin-channels-alist nil)
+ (erc-server-auto-reconnect nil)
+ (erc-d-linger-secs 10)
+ ,@bindings)))
+
+(defmacro erc-scenarios-common-with-cleanup (bindings &rest body)
+ "Provide boilerplate cleanup tasks after calling BODY with BINDINGS.
+
+If an `erc-d' process exists, wait for it to start before running BODY.
+If `erc-autojoin-mode' mode is bound, restore it during cleanup if
+disabled by BODY. Other defaults common to these test cases are added
+below and can be overridden, except when wanting the \"real\" default
+value, which must be looked up or captured outside of the calling form.
+
+Dialog resource directories are located by expanding the variable
+`erc-scenarios-common-dialog' or its value in BINDINGS."
+ (declare (indent 1))
+
+ (let* ((orig-autojoin-mode (make-symbol "orig-autojoin-mode"))
+ (combined `((,orig-autojoin-mode (bound-and-true-p erc-autojoin-mode))
+ ,@(erc-scenarios-common--make-bindings bindings))))
+
+ `(erc-d-t-with-cleanup (,@combined)
+
+ (ert-info ("Restore autojoin, etc., kill ERC buffers")
+ (dolist (buf (buffer-list))
+ (when-let ((erc-d-u--process-buffer)
+ (proc (get-buffer-process buf)))
+ (delete-process proc)))
+
+ (erc-scenarios-common--remove-silence)
+
+ (when erc-scenarios-common-extra-teardown
+ (ert-info ("Running extra teardown")
+ (funcall erc-scenarios-common-extra-teardown)))
+
+ (when (and (boundp 'erc-autojoin-mode)
+ (not (eq erc-autojoin-mode ,orig-autojoin-mode)))
+ (erc-autojoin-mode (if ,orig-autojoin-mode +1 -1)))
+
+ (when noninteractive
+ (erc-scenarios-common--print-trace)
+ (erc-d-t-kill-related-buffers)
+ (delete-other-windows)))
+
+ (erc-scenarios-common--add-silence)
+
+ (ert-info ("Wait for dumb server")
+ (dolist (buf (buffer-list))
+ (with-current-buffer buf
+ (when erc-d-u--process-buffer
+ (erc-d-t-search-for 3 "Starting")))))
+
+ (ert-info ("Activate erc-debug-irc-protocol")
+ (unless (and noninteractive (not erc-debug-irc-protocol))
+ (erc-toggle-debug-irc-protocol)))
+
+ ,@body)))
+
+(defun erc-scenarios-common-assert-initial-buf-name (id port)
+ ;; Assert no limbo period when explicit ID given
+ (should (string= (if id
+ (symbol-name id)
+ (format "127.0.0.1:%d" port))
+ (buffer-name))))
+
+(defun erc-scenarios-common-buflist (prefix)
+ "Return list of buffers with names sharing PREFIX."
+ (let (case-fold-search)
+ (erc-networks--id-sort-buffers
+ (delq nil
+ (mapcar (lambda (b)
+ (when (string-prefix-p prefix (buffer-name b)) b))
+ (buffer-list))))))
+
+;; This is more realistic than `erc-send-message' because it runs
+;; `erc-pre-send-functions', etc. Keyboard macros may be preferable,
+;; but they sometimes experience complications when an earlier test
+;; has failed.
+(defun erc-scenarios-common-say (str)
+ (let (erc-accidental-paste-threshold-seconds)
+ (goto-char erc-input-marker)
+ (insert str)
+ (erc-send-current-line)))
+
+
+;;;; Fixtures
+
+(cl-defun erc-scenarios-common--base-network-id-bouncer
+ ((&key autop foo-id bar-id after
+ &aux
+ (foo-id (and foo-id 'oofnet))
+ (bar-id (and bar-id 'rabnet))
+ (serv-buf-foo (if foo-id "oofnet" "foonet"))
+ (serv-buf-bar (if bar-id "rabnet" "barnet"))
+ (chan-buf-foo (if foo-id "#chan@oofnet" "#chan@foonet"))
+ (chan-buf-bar (if bar-id "#chan@rabnet" "#chan@barnet")))
+ &rest dialogs)
+ "Ensure retired option `erc-rename-buffers' is now the default behavior.
+The option `erc-rename-buffers' is now deprecated and on by default, so
+this now just asserts baseline behavior. Originally from scenario
+clash-of-chans/rename-buffers as explained in Bug#48598: 28.0.50;
+buffer-naming collisions involving bouncers in ERC."
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "base/netid/bouncer")
+ (erc-d-t-cleanup-sleep-secs 1)
+ (erc-server-flood-penalty 0.1)
+ (dumb-server (apply #'erc-d-run "localhost" t dialogs))
+ (port (process-contact dumb-server :service))
+ (expect (erc-d-t-make-expecter))
+ (erc-server-auto-reconnect autop)
+ erc-server-buffer-foo erc-server-process-foo
+ erc-server-buffer-bar erc-server-process-bar)
+
+ (ert-info ("Connect to foonet")
+ (with-current-buffer
+ (setq erc-server-buffer-foo (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :password "foonet:changeme"
+ :full-name "tester"
+ :id foo-id))
+ (setq erc-server-process-foo erc-server-process)
+ (erc-scenarios-common-assert-initial-buf-name foo-id port)
+ (erc-d-t-wait-for 3 (eq (erc-network) 'foonet))
+ (erc-d-t-wait-for 3 (string= (buffer-name) serv-buf-foo))
+ (funcall expect 5 "foonet")))
+
+ (ert-info ("Join #chan@foonet")
+ (with-current-buffer erc-server-buffer-foo (erc-cmd-JOIN "#chan"))
+ (with-current-buffer (erc-d-t-wait-for 5 (get-buffer "#chan"))
+ (funcall expect 5 "<alice>")))
+
+ (ert-info ("Connect to barnet")
+ (with-current-buffer
+ (setq erc-server-buffer-bar (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :password "barnet:changeme"
+ :full-name "tester"
+ :id bar-id))
+ (setq erc-server-process-bar erc-server-process)
+ (erc-scenarios-common-assert-initial-buf-name bar-id port)
+ (erc-d-t-wait-for 6 (eq (erc-network) 'barnet))
+ (erc-d-t-wait-for 3 (string= (buffer-name) serv-buf-bar))
+ (funcall expect 5 "barnet")))
+
+ (ert-info ("Server buffers are unique, no names based on IPs")
+ (should-not (eq erc-server-buffer-foo erc-server-buffer-bar))
+ (should-not (erc-scenarios-common-buflist "127.0.0.1")))
+
+ (ert-info ("Join #chan@barnet")
+ (with-current-buffer erc-server-buffer-bar (erc-cmd-JOIN "#chan")))
+
+ (erc-d-t-wait-for 5 "Exactly 2 #chan-prefixed buffers exist"
+ (equal (list (get-buffer chan-buf-bar)
+ (get-buffer chan-buf-foo))
+ (erc-scenarios-common-buflist "#chan")))
+
+ (ert-info ("#chan@<esid> is exclusive to foonet")
+ (with-current-buffer chan-buf-foo
+ (erc-d-t-search-for 1 "<bob>")
+ (erc-d-t-absent-for 0.1 "<joe>")
+ (should (eq erc-server-process erc-server-process-foo))
+ (erc-d-t-search-for 10 "ape is dead")
+ (erc-d-t-wait-for 5 (not (erc-server-process-alive)))))
+
+ (ert-info ("#chan@<esid> is exclusive to barnet")
+ (with-current-buffer chan-buf-bar
+ (erc-d-t-search-for 1 "<joe>")
+ (erc-d-t-absent-for 0.1 "<bob>")
+ (erc-d-t-wait-for 5 (eq erc-server-process erc-server-process-bar))
+ (erc-d-t-search-for 15 "keeps you from dishonour")
+ (erc-d-t-wait-for 5 (not (erc-server-process-alive)))))
+
+ (when after (funcall after))))
+
+(defun erc-scenarios-common--clash-rename-pass-handler (dialog exchange)
+ (when (eq (erc-d-dialog-name dialog) 'stub-again)
+ (let* ((match (erc-d-exchange-match exchange 1))
+ (sym (if (string= match "foonet") 'foonet-again 'barnet-again)))
+ (should (member match (list "foonet" "barnet")))
+ (erc-d-load-replacement-dialog dialog sym 1))))
+
+(defun erc-scenarios-common--base-network-id-bouncer--reconnect (foo-id bar-id)
+ (let ((erc-d-tmpl-vars '((token . (group (| "barnet" "foonet")))))
+ (erc-d-match-handlers
+ ;; Auto reconnect is nondeterministic, so let computer decide
+ (list :pass #'erc-scenarios-common--clash-rename-pass-handler))
+ (after
+ (lambda ()
+ ;; Simulate disconnection and `erc-server-auto-reconnect'
+ (ert-info ("Reconnect to foonet and barnet back-to-back")
+ (with-current-buffer (if foo-id "oofnet" "foonet")
+ (erc-d-t-wait-for 10 (erc-server-process-alive)))
+ (with-current-buffer (if bar-id "rabnet" "barnet")
+ (erc-d-t-wait-for 10 (erc-server-process-alive))))
+
+ (ert-info ("#chan@foonet is exclusive to foonet")
+ (with-current-buffer (if foo-id "#chan@oofnet" "#chan@foonet")
+ (erc-d-t-search-for 1 "<alice>")
+ (erc-d-t-absent-for 0.1 "<joe>")
+ (erc-d-t-search-for 20 "please your lordship")))
+
+ (ert-info ("#chan@barnet is exclusive to barnet")
+ (with-current-buffer (if bar-id "#chan@rabnet" "#chan@barnet")
+ (erc-d-t-search-for 1 "<joe>")
+ (erc-d-t-absent-for 0.1 "<bob>")
+ (erc-d-t-search-for 20 "much in private")))
+
+ ;; XXX this is important (reconnects overlapped, so we'd get
+ ;; chan@127.0.0.1:6667)
+ (should-not (erc-scenarios-common-buflist "127.0.0.1"))
+ ;; Reconnection order doesn't matter here because session objects
+ ;; are persisted, meaning original timestamps preserved.
+ (should (equal (list (get-buffer (if bar-id "#chan@rabnet"
+ "#chan@barnet"))
+ (get-buffer (if foo-id "#chan@oofnet"
+ "#chan@foonet")))
+ (erc-scenarios-common-buflist "#chan"))))))
+ (erc-scenarios-common--base-network-id-bouncer
+ (list :autop t :foo-id foo-id :bar-id bar-id :after after)
+ 'foonet-drop 'barnet-drop
+ 'stub-again 'stub-again
+ 'foonet-again 'barnet-again)))
+
+(defun erc-scenarios-common--upstream-reconnect (test &rest dialogs)
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "base/upstream-reconnect")
+ (erc-d-t-cleanup-sleep-secs 1)
+ (erc-server-flood-penalty 0.1)
+ (dumb-server (apply #'erc-d-run "localhost" t dialogs))
+ (port (process-contact dumb-server :service))
+ (expect (erc-d-t-make-expecter)))
+
+ (ert-info ("Connect to foonet")
+ (with-current-buffer (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :user "tester@vanilla/foonet"
+ :password "changeme"
+ :full-name "tester")
+ (erc-scenarios-common-assert-initial-buf-name nil port)
+ (erc-d-t-wait-for 3 (eq (erc-network) 'foonet))
+ (erc-d-t-wait-for 3 (string= (buffer-name) "foonet"))
+ (funcall expect 5 "foonet")))
+
+ (ert-info ("Join #chan@foonet")
+ (with-current-buffer (erc-d-t-wait-for 5 (get-buffer "#chan"))
+ (funcall expect 5 "<alice>")))
+
+ (ert-info ("Connect to barnet")
+ (with-current-buffer (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :user "tester@vanilla/barnet"
+ :password "changeme"
+ :full-name "tester")
+ (erc-scenarios-common-assert-initial-buf-name nil port)
+ (erc-d-t-wait-for 10 (eq (erc-network) 'barnet))
+ (erc-d-t-wait-for 3 (string= (buffer-name) "barnet"))
+ (funcall expect 5 "barnet")))
+
+ (ert-info ("Server buffers are unique, no names based on IPs")
+ (should-not (erc-scenarios-common-buflist "127.0.0.1")))
+
+ (with-current-buffer (erc-d-t-wait-for 5 (get-buffer "#chan@foonet"))
+ (funcall expect 5 "#chan was created on ")
+ (ert-info ("Joined again #chan@foonet")
+ (funcall expect 10 "#chan was created on "))
+ (funcall expect 10 "My lord, in heart"))
+
+ (with-current-buffer (erc-d-t-wait-for 5 (get-buffer "#chan@barnet"))
+ (funcall expect 5 "#chan was created on ")
+ (ert-info ("Joined again #chan@barnet")
+ (funcall expect 10 "#chan was created on "))
+ (funcall expect 10 "Go to; farewell"))
+
+ (funcall test)))
+
+;; XXX this is okay, but we also need to check that target buffers are
+;; already associated with a new process *before* a JOIN is sent by a
+;; server's playback burst. This doesn't do that.
+;;
+;; This *does* check that superfluous JOINs sent by the autojoin
+;; module are harmless when they're not acked (superfluous because the
+;; bouncer/server intitates the JOIN).
+
+(defun erc-scenarios-common--join-network-id (foo-reconnector foo-id bar-id)
+ "Ensure channels rejoined by erc-join.el DTRT.
+Originally from scenario clash-of-chans/autojoin as described in
+Bug#48598: 28.0.50; buffer-naming collisions involving bouncers in ERC."
+ (erc-scenarios-common-with-cleanup
+ ((chan-buf-foo (format "#chan@%s" (or foo-id "foonet")))
+ (chan-buf-bar (format "#chan@%s" (or bar-id "barnet")))
+ (erc-scenarios-common-dialog "join/network-id")
+ (erc-d-t-cleanup-sleep-secs 1)
+ (erc-server-flood-penalty 0.5)
+ (dumb-server (erc-d-run "localhost" t 'foonet 'barnet 'foonet-again))
+ (port (process-contact dumb-server :service))
+ (expect (erc-d-t-make-expecter))
+ erc-server-buffer-foo erc-server-process-foo
+ erc-server-buffer-bar erc-server-process-bar)
+
+ (should (memq 'autojoin erc-modules))
+
+ (ert-info ("Connect to foonet")
+ (with-current-buffer
+ (setq erc-server-buffer-foo (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :password "foonet:changeme"
+ :full-name "tester"
+ :id foo-id))
+ (setq erc-server-process-foo erc-server-process)
+ (erc-scenarios-common-assert-initial-buf-name foo-id port)
+ (erc-d-t-wait-for 5 (eq (erc-network) 'foonet))
+ (funcall expect 5 "foonet")))
+
+ (ert-info ("Join #chan, find sentinel, quit")
+ (with-current-buffer erc-server-buffer-foo (erc-cmd-JOIN "#chan"))
+ (with-current-buffer (erc-d-t-wait-for 5 (get-buffer "#chan"))
+ (funcall expect 5 "vile thing")
+ (erc-cmd-QUIT "")))
+
+ (erc-d-t-wait-for 2 "Foonet connection deceased"
+ (not (erc-server-process-alive erc-server-buffer-foo)))
+
+ (should (equal erc-autojoin-channels-alist
+ (if foo-id '((oofnet "#chan")) '((foonet "#chan")))))
+
+ (ert-info ("Connect to barnet")
+ (with-current-buffer
+ (setq erc-server-buffer-bar (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :password "barnet:changeme"
+ :full-name "tester"
+ :id bar-id))
+ (setq erc-server-process-bar erc-server-process)
+ (erc-d-t-wait-for 5 (eq erc-network 'barnet))
+ (should (string= (buffer-name) (if bar-id "rabnet" "barnet")))))
+
+ (ert-info ("Server buffers are unique, no stray IP-based names")
+ (should-not (eq erc-server-buffer-foo erc-server-buffer-bar))
+ (should-not (erc-scenarios-common-buflist "127.0.0.1")))
+
+ (ert-info ("Only one #chan buffer exists")
+ (should (equal (list (get-buffer "#chan"))
+ (erc-scenarios-common-buflist "#chan"))))
+
+ (ert-info ("#chan is not auto-joined")
+ (with-current-buffer "#chan"
+ (erc-d-t-absent-for 0.1 "<joe>")
+ (should-not (process-live-p erc-server-process))
+ (erc-d-t-ensure-for 0.1 "server buffer remains foonet"
+ (eq erc-server-process erc-server-process-foo))))
+
+ (with-current-buffer erc-server-buffer-bar
+ (erc-cmd-JOIN "#chan")
+ (erc-d-t-wait-for 3 (get-buffer chan-buf-foo))
+ (erc-d-t-wait-for 3 (get-buffer chan-buf-bar))
+ (with-current-buffer chan-buf-bar
+ (erc-d-t-wait-for 3 (eq erc-server-process erc-server-process-bar))
+ (funcall expect 5 "marry her instantly")))
+
+ (ert-info ("Reconnect to foonet")
+ (with-current-buffer (setq erc-server-buffer-foo
+ (funcall foo-reconnector))
+ (should (member (if foo-id '(oofnet "#chan") '(foonet "#chan"))
+ erc-autojoin-channels-alist))
+ (erc-d-t-wait-for 3 (erc-server-process-alive))
+ (setq erc-server-process-foo erc-server-process)
+ (erc-d-t-wait-for 2 (eq erc-network 'foonet))
+ (should (string= (buffer-name) (if foo-id "oofnet" "foonet")))
+ (funcall expect 5 "foonet")))
+
+ (ert-info ("#chan@foonet is clean, no cross-contamination")
+ (with-current-buffer chan-buf-foo
+ (erc-d-t-wait-for 3 (eq erc-server-process erc-server-process-foo))
+ (funcall expect 3 "<bob>")
+ (erc-d-t-absent-for 0.1 "<joe>")
+ (funcall expect 10 "not given me")))
+
+ (ert-info ("All #chan@barnet output received")
+ (with-current-buffer chan-buf-bar
+ (funcall expect 10 "hath an uncle here")))))
+
+(provide 'erc-scenarios-common)
+
+;;; erc-scenarios-common.el ends here
diff --git a/test/lisp/erc/resources/join/auth-source/foonet.eld b/test/lisp/erc/resources/join/auth-source/foonet.eld
new file mode 100644
index 00000000000..32b9e3fa0b6
--- /dev/null
+++ b/test/lisp/erc/resources/join/auth-source/foonet.eld
@@ -0,0 +1,33 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS :changeme"))
+((nick 1 "NICK dummy"))
+((user 1 "USER user 0 * :dummy")
+ (0.00 ":irc.foonet.org 001 dummy :Welcome to the foonet IRC Network dummy")
+ (0.01 ":irc.foonet.org 002 dummy :Your host is irc.foonet.org, running version ergo-v2.8.0")
+ (0.00 ":irc.foonet.org 003 dummy :This server was created Tue, 24 May 2022 05:28:42 UTC")
+ (0.00 ":irc.foonet.org 004 dummy irc.foonet.org ergo-v2.8.0 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0.00 ":irc.foonet.org 005 dummy AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0.01 ":irc.foonet.org 005 dummy MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0.01 ":irc.foonet.org 005 dummy draft/CHATHISTORY=100 :are supported by this server")
+ (0.00 ":irc.foonet.org 251 dummy :There are 0 users and 4 invisible on 1 server(s)")
+ (0.00 ":irc.foonet.org 252 dummy 0 :IRC Operators online")
+ (0.00 ":irc.foonet.org 253 dummy 0 :unregistered connections")
+ (0.00 ":irc.foonet.org 254 dummy 2 :channels formed")
+ (0.00 ":irc.foonet.org 255 dummy :I have 4 clients and 0 servers")
+ (0.00 ":irc.foonet.org 265 dummy 4 4 :Current local users 4, max 4")
+ (0.00 ":irc.foonet.org 266 dummy 4 4 :Current global users 4, max 4")
+ (0.00 ":irc.foonet.org 422 dummy :MOTD File is missing"))
+
+((mode 6 "MODE dummy +i")
+ (0.00 ":irc.foonet.org 221 dummy +i")
+ (0.00 ":irc.foonet.org NOTICE dummy :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")
+ (0.02 ":irc.foonet.org 221 dummy +i"))
+
+((join 6.47 "JOIN #spam secret")
+ (0.03 ":dummy!~u@w9rfqveugz722.irc JOIN #spam"))
+
+((mode 1 "MODE #spam")
+ (0.01 ":irc.foonet.org 353 dummy = #spam :~tester dummy")
+ (0.00 ":irc.foonet.org 366 dummy #spam :End of NAMES list")
+ (0.01 ":irc.foonet.org 324 dummy #spam +knt secret")
+ (0.03 ":irc.foonet.org 329 dummy #spam 1653370308"))
diff --git a/test/lisp/erc/resources/join/legacy/foonet.eld b/test/lisp/erc/resources/join/legacy/foonet.eld
new file mode 100644
index 00000000000..344ba7c1daf
--- /dev/null
+++ b/test/lisp/erc/resources/join/legacy/foonet.eld
@@ -0,0 +1,38 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS :changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.foonet.org 003 tester :This server was created Tue, 04 May 2021 05:06:18 UTC")
+ (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=FooNet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.foonet.org 253 tester 0 :unregistered connections")
+ (0 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 3.2 "MODE tester +i")
+ (0 ":irc.foonet.org 221 tester +i")
+ (0 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect."))
+
+((join 6 "JOIN #chan")
+ (0 ":tester!~u@9g6b728983yd2.irc JOIN #chan")
+ (0 ":irc.foonet.org 353 tester = #chan :alice tester @bob")
+ (0 ":irc.foonet.org 366 tester #chan :End of NAMES list"))
+
+((mode 5 "MODE #chan")
+ (0 ":irc.foonet.org 324 tester #chan +nt")
+ (0 ":irc.foonet.org 329 tester #chan 1620104779")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :tester, welcome!")
+ (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :tester, welcome!")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: But, as it seems, did violence on herself.")
+ (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :bob: Well, this is the forest of Arden.")
+ (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :bob: And will you, being a man of your breeding, be married under a bush, like a beggar ? Get you to church, and have a good priest that can tell you what marriage is: this fellow will but join you together as they join wainscot; then one of you will prove a shrunk panel, and like green timber, warp, warp.")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: Live, and be prosperous; and farewell, good fellow."))
diff --git a/test/lisp/erc/resources/join/network-id/barnet.eld b/test/lisp/erc/resources/join/network-id/barnet.eld
new file mode 100644
index 00000000000..e33dd6be29e
--- /dev/null
+++ b/test/lisp/erc/resources/join/network-id/barnet.eld
@@ -0,0 +1,43 @@
+;; -*- mode: lisp-data; -*-
+((pass 2 "PASS :barnet:changeme"))
+((nick 2 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.barnet.org 001 tester :Welcome to the barnet IRC Network tester")
+ (0 ":irc.barnet.org 002 tester :Your host is irc.barnet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.barnet.org 003 tester :This server was created Mon, 10 May 2021 00:58:22 UTC")
+ (0 ":irc.barnet.org 004 tester irc.barnet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.barnet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.barnet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=barnet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.barnet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.barnet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.barnet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.barnet.org 254 tester 1 :channels formed")
+ (0 ":irc.barnet.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.barnet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.barnet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.barnet.org 422 tester :MOTD File is missing"))
+
+((mode-user 12 "MODE tester +i"))
+;; No mode answer
+
+((join 2 "JOIN #chan")
+ (0 ":tester!~u@6yximxrnkg65a.irc JOIN #chan")
+ (0 ":irc.barnet.org 353 tester = #chan :@joe mike tester")
+ (0 ":irc.barnet.org 366 tester #chan :End of NAMES list")
+ (0.1 ":joe!~u@6yximxrnkg65a.irc PRIVMSG #chan :tester, welcome!")
+ (0 ":mike!~u@6yximxrnkg65a.irc PRIVMSG #chan :tester, welcome!"))
+
+((mode 1 "MODE #chan")
+ (0 ":irc.barnet.org 324 tester #chan +nt")
+ (0 ":irc.barnet.org 329 tester #chan 1620608304")
+ ;; Wait for foonet's buffer playback
+ (0.1 ":mike!~u@6yximxrnkg65a.irc PRIVMSG #chan :joe: Go take her hence, and marry her instantly.")
+ (0.1 ":joe!~u@6yximxrnkg65a.irc PRIVMSG #chan :mike: Of all the four, or the three, or the two, or one of the four.")
+ (0.1 ":mike!~u@6yximxrnkg65a.irc PRIVMSG #chan :joe: And gives the crutch the cradle's infancy.")
+ (0.1 ":joe!~u@6yximxrnkg65a.irc PRIVMSG #chan :mike: Such is the simplicity of man to hearken after the flesh.")
+ (0.05 ":mike!~u@6yximxrnkg65a.irc PRIVMSG #chan :joe: The leaf to read them. Let us toward the king.")
+ (0.05 ":joe!~u@6yximxrnkg65a.irc PRIVMSG #chan :mike: Many can brook the weather that love not the wind.")
+ (0.05 ":mike!~u@6yximxrnkg65a.irc PRIVMSG #chan :joe: And now, dear maid, be you as free to us.")
+ (0.00 ":joe!~u@6yximxrnkg65a.irc PRIVMSG #chan :mike: He hath an uncle here in Messina will be very much glad of it."))
+
+((linger 3.5 LINGER))
diff --git a/test/lisp/erc/resources/join/network-id/foonet-again.eld b/test/lisp/erc/resources/join/network-id/foonet-again.eld
new file mode 100644
index 00000000000..b230eff27c7
--- /dev/null
+++ b/test/lisp/erc/resources/join/network-id/foonet-again.eld
@@ -0,0 +1,46 @@
+;; -*- mode: lisp-data; -*-
+((pass-redux 10 "PASS :foonet:changeme"))
+((nick-redux 1 "NICK tester"))
+
+((user-redux 1 "USER user 0 * :tester")
+ (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.foonet.org 003 tester :This server was created Mon, 10 May 2021 00:58:22 UTC")
+ (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 10.2 "MODE tester +i")
+ ;; No mode answer ^
+
+ ;; History
+ (0 ":tester!~u@q6ddatxcq6txy.irc JOIN #chan")
+ (0 ":irc.foonet.org 353 tester = #chan :@alice bob tester")
+ (0 ":irc.foonet.org 366 tester #chan :End of /NAMES list.")
+ (0 ":***!znc@znc.in PRIVMSG #chan :Buffer Playback...")
+ (0 ":bob!~u@q6ddatxcq6txy.irc PRIVMSG #chan :[02:43:23] alice: And soar with them above a common bound.")
+ (0 ":alice!~u@q6ddatxcq6txy.irc PRIVMSG #chan :[02:43:27] bob: And be aveng'd on cursed Tamora.")
+ (0 ":bob!~u@q6ddatxcq6txy.irc PRIVMSG #chan :[02:43:29] alice: He did love her, sir, as a gentleman loves a woman.")
+ (0 ":***!znc@znc.in PRIVMSG #chan :Playback Complete."))
+
+;; As a server, we ignore useless join sent by autojoin module
+((~join 10 "JOIN #chan"))
+
+((mode-redux 10 "MODE #chan")
+ (0 ":irc.foonet.org 324 tester #chan +nt")
+ (0 ":irc.foonet.org 329 tester #chan 1620608304")
+ (0.1 ":alice!~u@q6ddatxcq6txy.irc PRIVMSG #chan :bob: Ay, madam, with the swiftest wing of speed.")
+ (0.1 ":bob!~u@q6ddatxcq6txy.irc PRIVMSG #chan :alice: Five times in that ere once in our five wits.")
+ (0.1 ":alice!~u@q6ddatxcq6txy.irc PRIVMSG #chan :bob: And bid him come to take his last farewell.")
+ (0.1 ":bob!~u@q6ddatxcq6txy.irc PRIVMSG #chan :alice: But we are spirits of another sort.")
+ (0.1 ":alice!~u@q6ddatxcq6txy.irc PRIVMSG #chan :bob: It was not given me, nor I did not buy it."))
+
+((linger 6 LINGER))
diff --git a/test/lisp/erc/resources/join/network-id/foonet.eld b/test/lisp/erc/resources/join/network-id/foonet.eld
new file mode 100644
index 00000000000..7d63f5f0c6c
--- /dev/null
+++ b/test/lisp/erc/resources/join/network-id/foonet.eld
@@ -0,0 +1,39 @@
+;; -*- mode: lisp-data; -*-
+((pass 10 "PASS :foonet:changeme"))
+((nick 1 "NICK tester"))
+
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.foonet.org 003 tester :This server was created Mon, 10 May 2021 00:58:22 UTC")
+ (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 10.2 "MODE tester +i"))
+;; No mode answer ^
+
+((join 3 "JOIN #chan")
+ (0 ":tester!~u@q6ddatxcq6txy.irc JOIN #chan")
+ (0 ":irc.foonet.org 353 tester = #chan :@alice bob tester")
+ (0 ":irc.foonet.org 366 tester #chan :End of NAMES list")
+ (0.1 ":bob!~u@q6ddatxcq6txy.irc PRIVMSG #chan :tester, welcome!")
+ (0 ":alice!~u@q6ddatxcq6txy.irc PRIVMSG #chan :tester, welcome!"))
+
+((mode 3 "MODE #chan")
+ (0 ":irc.foonet.org 324 tester #chan +nt")
+ (0 ":irc.foonet.org 329 tester #chan 1620608304")
+ (0.1 ":bob!~u@q6ddatxcq6txy.irc PRIVMSG #chan :alice: Pray you, sir, deliver me this paper.")
+ (0.1 ":alice!~u@q6ddatxcq6txy.irc PRIVMSG #chan :bob: Wake when some vile thing is near."))
+
+((quit 3 "QUIT :\2ERC\2"))
+
+((drop 0 DROP))
diff --git a/test/lisp/erc/resources/join/reconnect/foonet-again.eld b/test/lisp/erc/resources/join/reconnect/foonet-again.eld
new file mode 100644
index 00000000000..f1fcc439cc3
--- /dev/null
+++ b/test/lisp/erc/resources/join/reconnect/foonet-again.eld
@@ -0,0 +1,45 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS :changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.foonet.org 003 tester :This server was created Tue, 04 May 2021 05:06:18 UTC")
+ (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=FooNet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.foonet.org 253 tester 0 :unregistered connections")
+ (0 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 3.2 "MODE tester +i")
+ (0 ":irc.foonet.org 221 tester +i")
+ (0 ":irc.foonet.org NOTICE tester :This server is still in debug mode."))
+
+((~join-chan 12 "JOIN #chan")
+ (0 ":tester!~u@9g6b728983yd2.irc JOIN #chan")
+ (0 ":irc.foonet.org 353 tester = #chan :alice tester @bob")
+ (0 ":irc.foonet.org 366 tester #chan :End of NAMES list"))
+
+((~join-spam 12 "JOIN #spam")
+ (0 ":tester!~u@9g6b728983yd2.irc JOIN #spam")
+ (0 ":irc.foonet.org 353 tester = #spam :alice tester @bob")
+ (0 ":irc.foonet.org 366 tester #spam :End of NAMES list"))
+
+((~mode-chan 4 "MODE #chan")
+ (0 ":irc.foonet.org 324 tester #chan +nt")
+ (0 ":irc.foonet.org 329 tester #chan 1620104779")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: But, as it seems, did violence on herself.")
+ (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :bob: Well, this is the forest of Arden."))
+
+((mode-spam 4 "MODE #spam")
+ (0 ":irc.foonet.org 324 tester #spam +nt")
+ (0 ":irc.foonet.org 329 tester #spam 1620104779")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #spam :alice: Signior Iachimo will not from it. Pray, let us follow 'em.")
+ (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #spam :bob: Our queen and all her elves come here anon."))
diff --git a/test/lisp/erc/resources/join/reconnect/foonet.eld b/test/lisp/erc/resources/join/reconnect/foonet.eld
new file mode 100644
index 00000000000..efb269f5ae5
--- /dev/null
+++ b/test/lisp/erc/resources/join/reconnect/foonet.eld
@@ -0,0 +1,45 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS :changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.foonet.org 003 tester :This server was created Tue, 04 May 2021 05:06:18 UTC")
+ (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=FooNet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.foonet.org 253 tester 0 :unregistered connections")
+ (0 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 3.2 "MODE tester +i")
+ (0 ":irc.foonet.org 221 tester +i")
+ (0 ":irc.foonet.org NOTICE tester :This server is in debug mode.")
+
+ (0 ":tester!~u@9g6b728983yd2.irc JOIN #chan")
+ (0 ":irc.foonet.org 353 tester = #chan :alice tester @bob")
+ (0 ":irc.foonet.org 366 tester #chan :End of NAMES list")
+
+ (0 ":tester!~u@9g6b728983yd2.irc JOIN #spam")
+ (0 ":irc.foonet.org 353 tester = #spam :alice tester @bob")
+ (0 ":irc.foonet.org 366 tester #spam :End of NAMES list"))
+
+((mode-chan 4 "MODE #chan")
+ (0 ":irc.foonet.org 324 tester #chan +nt")
+ (0 ":irc.foonet.org 329 tester #chan 1620104779")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :tester, welcome!")
+ (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :tester, welcome!"))
+
+((mode-spam 4 "MODE #spam")
+ (0 ":irc.foonet.org 324 tester #spam +nt")
+ (0 ":irc.foonet.org 329 tester #spam 1620104779")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #spam :tester, welcome!")
+ (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #spam :tester, welcome!"))
+
+((drop 0 DROP))
diff --git a/test/lisp/erc/resources/networks/announced-missing/foonet.eld b/test/lisp/erc/resources/networks/announced-missing/foonet.eld
new file mode 100644
index 00000000000..79b0fb462a8
--- /dev/null
+++ b/test/lisp/erc/resources/networks/announced-missing/foonet.eld
@@ -0,0 +1,8 @@
+;; -*- mode: lisp-data; -*-
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.foonet.org 001 tester :Welcome to the FooNet Internet Relay Chat Network tester")
+ (0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 1.2 "MODE tester +i")
+ (0 ":tester MODE tester :+Zi"))
diff --git a/test/lisp/erc/resources/services/auth-source/libera.eld b/test/lisp/erc/resources/services/auth-source/libera.eld
new file mode 100644
index 00000000000..c8dbc9d425a
--- /dev/null
+++ b/test/lisp/erc/resources/services/auth-source/libera.eld
@@ -0,0 +1,49 @@
+;; -*- mode: lisp-data; -*-
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0.26 ":zirconium.libera.chat NOTICE * :*** Checking Ident")
+ (0.01 ":zirconium.libera.chat NOTICE * :*** Looking up your hostname...")
+ (0.01 ":zirconium.libera.chat NOTICE * :*** No Ident response")
+ (0.02 ":zirconium.libera.chat NOTICE * :*** Found your hostname: static-198-54-131-100.cust.tzulo.com")
+ (0.02 ":zirconium.libera.chat 001 tester :Welcome to the Libera.Chat Internet Relay Chat Network tester")
+ (0.01 ":zirconium.libera.chat 002 tester :Your host is zirconium.libera.chat[46.16.175.175/6697], running version solanum-1.0-dev")
+ (0.03 ":zirconium.libera.chat 003 tester :This server was created Wed Jun 9 2021 at 01:38:28 UTC")
+ (0.02 ":zirconium.libera.chat 004 tester zirconium.libera.chat solanum-1.0-dev DGQRSZaghilopsuwz CFILMPQSbcefgijklmnopqrstuvz bkloveqjfI")
+ (0.00 ":zirconium.libera.chat 005 tester ETRACE WHOX FNC MONITOR=100 SAFELIST ELIST=CTU CALLERID=g KNOCK CHANTYPES=# EXCEPTS INVEX CHANMODES=eIbq,k,flj,CFLMPQScgimnprstuz :are supported by this server")
+ (0.03 ":zirconium.libera.chat 005 tester CHANLIMIT=#:250 PREFIX=(ov)@+ MAXLIST=bqeI:100 MODES=4 NETWORK=Libera.Chat STATUSMSG=@+ CASEMAPPING=rfc1459 NICKLEN=16 MAXNICKLEN=16 CHANNELLEN=50 TOPICLEN=390 DEAF=D :are supported by this server")
+ (0.02 ":zirconium.libera.chat 005 tester TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,PRIVMSG:4,NOTICE:4,ACCEPT:,MONITOR: EXTBAN=$,ajrxz CLIENTVER=3.0 :are supported by this server")
+ (0.02 ":zirconium.libera.chat 251 tester :There are 68 users and 37640 invisible on 25 servers")
+ (0.00 ":zirconium.libera.chat 252 tester 36 :IRC Operators online")
+ (0.01 ":zirconium.libera.chat 253 tester 5 :unknown connection(s)")
+ (0.00 ":zirconium.libera.chat 254 tester 19341 :channels formed")
+ (0.01 ":zirconium.libera.chat 255 tester :I have 3321 clients and 1 servers")
+ (0.01 ":zirconium.libera.chat 265 tester 3321 4289 :Current local users 3321, max 4289")
+ (0.00 ":zirconium.libera.chat 266 tester 37708 38929 :Current global users 37708, max 38929")
+ (0.01 ":zirconium.libera.chat 250 tester :Highest connection count: 4290 (4289 clients) (38580 connections received)")
+ (0.21 ":zirconium.libera.chat 375 tester :- zirconium.libera.chat Message of the Day - ")
+ (0.00 ":zirconium.libera.chat 372 tester :- This server provided by Seeweb <https://www.seeweb.it/>")
+ (0.01 ":zirconium.libera.chat 372 tester :- Welcome to Libera Chat, the IRC network for")
+ (0.01 ":zirconium.libera.chat 372 tester :- free & open-source software and peer directed projects.")
+ (0.00 ":zirconium.libera.chat 372 tester :- ")
+ (0.00 ":zirconium.libera.chat 372 tester :- Use of Libera Chat is governed by our network policies.")
+ (0.00 ":zirconium.libera.chat 372 tester :- ")
+ (0.01 ":zirconium.libera.chat 372 tester :- Please visit us in #libera for questions and support.")
+ (0.01 ":zirconium.libera.chat 372 tester :- ")
+ (0.01 ":zirconium.libera.chat 372 tester :- Website and documentation: https://libera.chat")
+ (0.01 ":zirconium.libera.chat 372 tester :- Webchat: https://web.libera.chat")
+ (0.01 ":zirconium.libera.chat 372 tester :- Network policies: https://libera.chat/policies")
+ (0.01 ":zirconium.libera.chat 372 tester :- Email: support@libera.chat")
+ (0.00 ":zirconium.libera.chat 376 tester :End of /MOTD command."))
+
+((mode-user 1.2 "MODE tester +i")
+ (0.02 ":tester MODE tester :+Zi")
+ (0.02 ":NickServ!NickServ@services.libera.chat NOTICE tester :This nickname is registered. Please choose a different nickname, or identify via \2/msg NickServ IDENTIFY tester <password>\2"))
+
+((privmsg 2 "PRIVMSG NickServ :IDENTIFY changeme")
+ (0.96 ":NickServ!NickServ@services.libera.chat NOTICE tester :You are now identified for \2tester\2.")
+ (0.25 ":NickServ!NickServ@services.libera.chat NOTICE tester :Last login from: \2~tester@school.edu/tester\2 on Jun 18 01:15:56 2021 +0000."))
+
+((quit 5 "QUIT :\2ERC\2")
+ (0.19 ":tester!~user@static-198-54-131-100.cust.tzulo.com QUIT :Client Quit"))
+
+((linger 1 LINGER))
diff --git a/test/lisp/erc/resources/services/password/libera.eld b/test/lisp/erc/resources/services/password/libera.eld
new file mode 100644
index 00000000000..c8dbc9d425a
--- /dev/null
+++ b/test/lisp/erc/resources/services/password/libera.eld
@@ -0,0 +1,49 @@
+;; -*- mode: lisp-data; -*-
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0.26 ":zirconium.libera.chat NOTICE * :*** Checking Ident")
+ (0.01 ":zirconium.libera.chat NOTICE * :*** Looking up your hostname...")
+ (0.01 ":zirconium.libera.chat NOTICE * :*** No Ident response")
+ (0.02 ":zirconium.libera.chat NOTICE * :*** Found your hostname: static-198-54-131-100.cust.tzulo.com")
+ (0.02 ":zirconium.libera.chat 001 tester :Welcome to the Libera.Chat Internet Relay Chat Network tester")
+ (0.01 ":zirconium.libera.chat 002 tester :Your host is zirconium.libera.chat[46.16.175.175/6697], running version solanum-1.0-dev")
+ (0.03 ":zirconium.libera.chat 003 tester :This server was created Wed Jun 9 2021 at 01:38:28 UTC")
+ (0.02 ":zirconium.libera.chat 004 tester zirconium.libera.chat solanum-1.0-dev DGQRSZaghilopsuwz CFILMPQSbcefgijklmnopqrstuvz bkloveqjfI")
+ (0.00 ":zirconium.libera.chat 005 tester ETRACE WHOX FNC MONITOR=100 SAFELIST ELIST=CTU CALLERID=g KNOCK CHANTYPES=# EXCEPTS INVEX CHANMODES=eIbq,k,flj,CFLMPQScgimnprstuz :are supported by this server")
+ (0.03 ":zirconium.libera.chat 005 tester CHANLIMIT=#:250 PREFIX=(ov)@+ MAXLIST=bqeI:100 MODES=4 NETWORK=Libera.Chat STATUSMSG=@+ CASEMAPPING=rfc1459 NICKLEN=16 MAXNICKLEN=16 CHANNELLEN=50 TOPICLEN=390 DEAF=D :are supported by this server")
+ (0.02 ":zirconium.libera.chat 005 tester TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,PRIVMSG:4,NOTICE:4,ACCEPT:,MONITOR: EXTBAN=$,ajrxz CLIENTVER=3.0 :are supported by this server")
+ (0.02 ":zirconium.libera.chat 251 tester :There are 68 users and 37640 invisible on 25 servers")
+ (0.00 ":zirconium.libera.chat 252 tester 36 :IRC Operators online")
+ (0.01 ":zirconium.libera.chat 253 tester 5 :unknown connection(s)")
+ (0.00 ":zirconium.libera.chat 254 tester 19341 :channels formed")
+ (0.01 ":zirconium.libera.chat 255 tester :I have 3321 clients and 1 servers")
+ (0.01 ":zirconium.libera.chat 265 tester 3321 4289 :Current local users 3321, max 4289")
+ (0.00 ":zirconium.libera.chat 266 tester 37708 38929 :Current global users 37708, max 38929")
+ (0.01 ":zirconium.libera.chat 250 tester :Highest connection count: 4290 (4289 clients) (38580 connections received)")
+ (0.21 ":zirconium.libera.chat 375 tester :- zirconium.libera.chat Message of the Day - ")
+ (0.00 ":zirconium.libera.chat 372 tester :- This server provided by Seeweb <https://www.seeweb.it/>")
+ (0.01 ":zirconium.libera.chat 372 tester :- Welcome to Libera Chat, the IRC network for")
+ (0.01 ":zirconium.libera.chat 372 tester :- free & open-source software and peer directed projects.")
+ (0.00 ":zirconium.libera.chat 372 tester :- ")
+ (0.00 ":zirconium.libera.chat 372 tester :- Use of Libera Chat is governed by our network policies.")
+ (0.00 ":zirconium.libera.chat 372 tester :- ")
+ (0.01 ":zirconium.libera.chat 372 tester :- Please visit us in #libera for questions and support.")
+ (0.01 ":zirconium.libera.chat 372 tester :- ")
+ (0.01 ":zirconium.libera.chat 372 tester :- Website and documentation: https://libera.chat")
+ (0.01 ":zirconium.libera.chat 372 tester :- Webchat: https://web.libera.chat")
+ (0.01 ":zirconium.libera.chat 372 tester :- Network policies: https://libera.chat/policies")
+ (0.01 ":zirconium.libera.chat 372 tester :- Email: support@libera.chat")
+ (0.00 ":zirconium.libera.chat 376 tester :End of /MOTD command."))
+
+((mode-user 1.2 "MODE tester +i")
+ (0.02 ":tester MODE tester :+Zi")
+ (0.02 ":NickServ!NickServ@services.libera.chat NOTICE tester :This nickname is registered. Please choose a different nickname, or identify via \2/msg NickServ IDENTIFY tester <password>\2"))
+
+((privmsg 2 "PRIVMSG NickServ :IDENTIFY changeme")
+ (0.96 ":NickServ!NickServ@services.libera.chat NOTICE tester :You are now identified for \2tester\2.")
+ (0.25 ":NickServ!NickServ@services.libera.chat NOTICE tester :Last login from: \2~tester@school.edu/tester\2 on Jun 18 01:15:56 2021 +0000."))
+
+((quit 5 "QUIT :\2ERC\2")
+ (0.19 ":tester!~user@static-198-54-131-100.cust.tzulo.com QUIT :Client Quit"))
+
+((linger 1 LINGER))
diff --git a/test/lisp/eshell/em-alias-tests.el b/test/lisp/eshell/em-alias-tests.el
new file mode 100644
index 00000000000..aca622220e3
--- /dev/null
+++ b/test/lisp/eshell/em-alias-tests.el
@@ -0,0 +1,87 @@
+;;; em-alias-tests.el --- em-alias test suite -*- lexical-binding:t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Tests for Eshell's alias module.
+
+;;; Code:
+
+(require 'ert)
+(require 'esh-mode)
+(require 'eshell)
+(require 'em-alias)
+
+(require 'eshell-tests-helpers
+ (expand-file-name "eshell-tests-helpers"
+ (file-name-directory (or load-file-name
+ default-directory))))
+;;; Tests:
+
+(ert-deftest em-alias-test/simple-alias ()
+ "Test a simple alias with no arguments"
+ (with-temp-eshell
+ (eshell-insert-command "alias say-hi 'echo hi'")
+ (eshell-match-command-output "say-hi" "hi\n")
+ (eshell-match-command-output "say-hi bye" "hi\n")))
+
+(ert-deftest em-alias-test/alias-arg-vars ()
+ "Test alias with $0, $1, ... variables"
+ (with-temp-eshell
+ (eshell-insert-command "alias show-args 'printnl $0 \"$1 $2\"'")
+ (eshell-match-command-output "show-args one two" "show-args\none two\n")))
+
+(ert-deftest em-alias-test/alias-arg-vars-indices ()
+ "Test alias with $1, $2, ... variables using indices"
+ (with-temp-eshell
+ (eshell-insert-command "alias funny-sum '+ $1[0] $2[1]'")
+ (eshell-match-command-output "funny-sum (list 1 2) (list 3 4)"
+ "5\n")))
+
+(ert-deftest em-alias-test/alias-arg-vars-split-indices ()
+ "Test alias with $0, $1, ... variables using split indices"
+ (with-temp-eshell
+ (eshell-insert-command "alias my-prefix 'echo $0[- 0]'")
+ (eshell-match-command-output "my-prefix"
+ "my\n")
+ (eshell-insert-command "alias funny-sum '+ $1[: 0] $2[: 1]'")
+ (eshell-match-command-output "funny-sum 1:2 3:4"
+ "5\n")))
+
+(ert-deftest em-alias-test/alias-all-args-var ()
+ "Test alias with the $* variable"
+ (with-temp-eshell
+ (eshell-insert-command "alias show-all-args 'printnl $*'")
+ (eshell-match-command-output "show-all-args" "\\`\\'")
+ (eshell-match-command-output "show-all-args a" "a\n")
+ (eshell-match-command-output "show-all-args a b c" "a\nb\nc\n")))
+
+(ert-deftest em-alias-test/alias-all-args-var-indices ()
+ "Test alias with the $* variable using indices"
+ (with-temp-eshell
+ (eshell-insert-command "alias add-pair '+ $*[0] $*[1]'")
+ (eshell-match-command-output "add-pair 1 2" "3\n")))
+
+(ert-deftest em-alias-test/alias-all-args-var-split-indices ()
+ "Test alias with the $* variable using split indices"
+ (with-temp-eshell
+ (eshell-insert-command "alias add-funny-pair '+ $*[0][: 0] $*[1][: 1]'")
+ (eshell-match-command-output "add-funny-pair 1:2 3:4" "5\n")))
+
+;; em-alias-tests.el ends here
diff --git a/test/lisp/eshell/em-basic-tests.el b/test/lisp/eshell/em-basic-tests.el
new file mode 100644
index 00000000000..bc8baeaa035
--- /dev/null
+++ b/test/lisp/eshell/em-basic-tests.el
@@ -0,0 +1,71 @@
+;;; em-basic-tests.el --- em-basic test suite -*- lexical-binding:t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Tests for basic Eshell commands.
+
+;;; Code:
+
+(require 'ert)
+(require 'em-basic)
+
+(require 'eshell-tests-helpers
+ (expand-file-name "eshell-tests-helpers"
+ (file-name-directory (or load-file-name
+ default-directory))))
+
+;;; Tests:
+
+(ert-deftest em-basic-test/umask-print-numeric ()
+ "Test printing umask numerically."
+ (cl-letf (((symbol-function 'default-file-modes) (lambda () #o775)))
+ (eshell-command-result-equal "umask" "002\n"))
+ (cl-letf (((symbol-function 'default-file-modes) (lambda () #o654)))
+ (eshell-command-result-equal "umask" "123\n"))
+ ;; Make sure larger numbers don't cause problems.
+ (cl-letf (((symbol-function 'default-file-modes) (lambda () #o1775)))
+ (eshell-command-result-equal "umask" "002\n")))
+
+(ert-deftest em-basic-test/umask-read-symbolic ()
+ "Test printing umask symbolically."
+ (cl-letf (((symbol-function 'default-file-modes) (lambda () #o775)))
+ (eshell-command-result-equal "umask -S"
+ "u=rwx,g=rwx,o=rx\n"))
+ (cl-letf (((symbol-function 'default-file-modes) (lambda () #o654)))
+ (eshell-command-result-equal "umask -S"
+ "u=wx,g=rx,o=x\n"))
+ ;; Make sure larger numbers don't cause problems.
+ (cl-letf (((symbol-function 'default-file-modes) (lambda () #o1775)))
+ (eshell-command-result-equal "umask -S"
+ "u=rwx,g=rwx,o=rx\n")))
+
+(ert-deftest em-basic-test/umask-set ()
+ "Test setting umask."
+ (let ((file-modes 0))
+ (cl-letf (((symbol-function 'set-default-file-modes)
+ (lambda (mode) (setq file-modes mode))))
+ (eshell-test-command-result "umask 002")
+ (should (= file-modes #o775))
+ (eshell-test-command-result "umask 123")
+ (should (= file-modes #o654))
+ (eshell-test-command-result "umask $(identity #o222)")
+ (should (= file-modes #o555)))))
+
+;; em-basic-tests.el ends here
diff --git a/test/lisp/eshell/em-dirs-tests.el b/test/lisp/eshell/em-dirs-tests.el
new file mode 100644
index 00000000000..f72d708dcae
--- /dev/null
+++ b/test/lisp/eshell/em-dirs-tests.el
@@ -0,0 +1,102 @@
+;;; em-dirs-tests.el --- em-dirs test suite -*- lexical-binding:t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Tests for Eshell's dirs module.
+
+;;; Code:
+
+(require 'ert)
+(require 'esh-mode)
+(require 'eshell)
+(require 'em-dirs)
+
+(require 'eshell-tests-helpers
+ (expand-file-name "eshell-tests-helpers"
+ (file-name-directory (or load-file-name
+ default-directory))))
+;;; Tests:
+
+(ert-deftest em-dirs-test/pwd-var ()
+ "Test using the $PWD variable."
+ (let ((default-directory "/some/path"))
+ (eshell-command-result-equal "echo $PWD"
+ (expand-file-name default-directory))))
+
+(ert-deftest em-dirs-test/pwd-var-indices ()
+ "Test using the $PWD variable with indices."
+ (let ((default-directory "/some/path/here"))
+ (eshell-command-result-equal "echo $PWD[/ 1]"
+ "some")
+ (eshell-command-result-equal "echo $PWD[/ 1 3]"
+ '("some" "here"))))
+
+(ert-deftest em-dirs-test/short-pwd-var ()
+ "Test using the $+ (current directory) variable."
+ (let ((default-directory "/some/path"))
+ (eshell-command-result-equal "echo $+"
+ (expand-file-name default-directory))))
+
+(ert-deftest em-dirs-test/oldpwd-var ()
+ "Test using the $OLDPWD variable."
+ (let (eshell-last-dir-ring-file-name)
+ (with-temp-eshell
+ (eshell-match-command-output "echo $OLDPWD"
+ "\\`\\'")
+ (ring-insert eshell-last-dir-ring "/some/path")
+ (eshell-match-command-output "echo $OLDPWD"
+ "/some/path\n"))))
+
+(ert-deftest em-dirs-test/oldpwd-var-indices ()
+ "Test using the $OLDPWD variable with indices."
+ (let (eshell-last-dir-ring-file-name)
+ (with-temp-eshell
+ (ring-insert eshell-last-dir-ring "/some/path/here")
+ (eshell-match-command-output "echo $OLDPWD[/ 1]"
+ "some\n")
+ (eshell-match-command-output "echo $OLDPWD[/ 1 3]"
+ "(\"some\" \"here\")\n"))))
+
+(ert-deftest em-dirs-test/directory-ring-var ()
+ "Test using the $- (directory ring) variable."
+ (let (eshell-last-dir-ring-file-name)
+ (with-temp-eshell
+ (eshell-match-command-output "echo $-"
+ "\\`\\'")
+ (ring-insert eshell-last-dir-ring "/some/path")
+ (ring-insert eshell-last-dir-ring "/other/path")
+ (eshell-match-command-output "echo $-"
+ "/other/path\n")
+ (eshell-match-command-output "echo $-[0]"
+ "/other/path\n")
+ (eshell-match-command-output "echo $-[1]"
+ "/some/path\n"))))
+
+(ert-deftest em-dirs-test/directory-ring-var-indices ()
+ "Test using the $- (directory ring) variable with multiple indices."
+ (let (eshell-last-dir-ring-file-name)
+ (with-temp-eshell
+ (ring-insert eshell-last-dir-ring "/some/path/here")
+ (eshell-match-command-output "echo $-[0][/ 1]"
+ "some\n")
+ (eshell-match-command-output "echo $-[1][/ 1 3]"
+ "(\"some\" \"here\")\n"))))
+
+;; em-dirs-tests.el ends here
diff --git a/test/lisp/eshell/em-extpipe-tests.el b/test/lisp/eshell/em-extpipe-tests.el
new file mode 100644
index 00000000000..04e78279427
--- /dev/null
+++ b/test/lisp/eshell/em-extpipe-tests.el
@@ -0,0 +1,205 @@
+;;; em-extpipe-tests.el --- em-extpipe test suite -*- lexical-binding:t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; Author: Sean Whitton <spwhitton@spwhitton.name>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'ert)
+(require 'ert-x)
+(require 'em-extpipe)
+(require 'eshell-tests-helpers
+ (expand-file-name "eshell-tests-helpers"
+ (file-name-directory (or load-file-name
+ default-directory))))
+
+(defmacro em-extpipe-tests--deftest (name input &rest body)
+ (declare (indent 2))
+ `(ert-deftest ,name ()
+ (cl-macrolet
+ ((should-parse (expected)
+ `(let ((shell-file-name "sh")
+ (shell-command-switch "-c"))
+ ;; Strip `eshell-trap-errors'.
+ (should (equal ,expected
+ (cadr (eshell-parse-command input))))))
+ (with-substitute-for-temp (&rest body)
+ ;; Substitute name of an actual temporary file and/or
+ ;; buffer into `input'. The substitution logic is
+ ;; appropriate for only the use we put it to in this file.
+ `(ert-with-temp-file temp
+ (let ((temp-buffer (generate-new-buffer " *temp*" t)))
+ (unwind-protect
+ (let ((input
+ (replace-regexp-in-string
+ "temp\\([^>]\\|\\'\\)" temp
+ (string-replace "#<buffer temp>"
+ (buffer-name temp-buffer)
+ input))))
+ ,@body)
+ (when (buffer-name temp-buffer)
+ (kill-buffer temp-buffer))))))
+ (temp-should-string= (expected)
+ `(string= ,expected (string-trim-right
+ (with-temp-buffer
+ (insert-file-contents temp)
+ (buffer-string)))))
+ (temp-buffer-should-string= (expected)
+ `(string= ,expected (string-trim-right
+ (with-current-buffer temp-buffer
+ (buffer-string))))))
+ (skip-unless shell-file-name)
+ (skip-unless shell-command-switch)
+ (skip-unless (executable-find shell-file-name))
+ (let ((input ,input))
+ (with-temp-eshell ,@body)))))
+
+(em-extpipe-tests--deftest em-extpipe-test-1
+ "echo \"bar\" *| rev >temp"
+ (skip-unless (executable-find "rev"))
+ (should-parse '(eshell-named-command
+ "sh" (list "-c" "echo \"bar\" | rev >temp")))
+ (with-substitute-for-temp
+ (eshell-match-command-output input "^$")
+ (temp-should-string= "rab")))
+
+(em-extpipe-tests--deftest em-extpipe-test-2
+ "echo \"bar\" | rev *>temp"
+ (skip-unless (executable-find "rev"))
+ (should-parse
+ '(eshell-execute-pipeline
+ '((eshell-named-command "echo" (list (eshell-escape-arg "bar")))
+ (eshell-named-command "sh" (list "-c" "rev >temp")))))
+ (with-substitute-for-temp
+ (eshell-match-command-output input "^$")
+ (temp-should-string= "rab")))
+
+(em-extpipe-tests--deftest em-extpipe-test-3 "foo *| bar | baz -d"
+ (should-parse
+ '(eshell-execute-pipeline
+ '((eshell-named-command "sh" (list "-c" "foo | bar"))
+ (eshell-named-command "baz" (list "-d"))))))
+
+(em-extpipe-tests--deftest em-extpipe-test-4
+ "echo \"bar\" *| rev >#<buffer temp>"
+ (skip-unless (executable-find "rev"))
+ (should-parse
+ '(progn
+ (ignore
+ (eshell-set-output-handle 1 'overwrite
+ (get-buffer-create "temp")))
+ (eshell-named-command "sh"
+ (list "-c" "echo \"bar\" | rev"))))
+ (with-substitute-for-temp
+ (eshell-match-command-output input "^$")
+ (temp-buffer-should-string= "rab")))
+
+(em-extpipe-tests--deftest em-extpipe-test-5
+ "foo *| bar >#<buffer quux> baz"
+ (should-parse '(eshell-named-command
+ "sh" (list "-c" "foo | bar >#<buffer quux> baz"))))
+
+(em-extpipe-tests--deftest em-extpipe-test-6
+ "foo >#<buffer quux> *| bar baz"
+ (should-parse '(eshell-named-command
+ "sh" (list "-c" "foo >#<buffer quux> | bar baz"))))
+
+(em-extpipe-tests--deftest em-extpipe-test-7
+ "foo *| bar >#<buffer quux> >>#<process other>"
+ (should-parse
+ '(progn
+ (ignore
+ (eshell-set-output-handle 1 'overwrite
+ (get-buffer-create "quux")))
+ (ignore
+ (eshell-set-output-handle 1 'append
+ (get-process "other")))
+ (eshell-named-command "sh"
+ (list "-c" "foo | bar")))))
+
+(em-extpipe-tests--deftest em-extpipe-test-8
+ "foo *| bar >/dev/kill | baz"
+ (should-parse
+ '(eshell-execute-pipeline
+ '((progn
+ (ignore
+ (eshell-set-output-handle 1 'overwrite "/dev/kill"))
+ (eshell-named-command "sh"
+ (list "-c" "foo | bar")))
+ (eshell-named-command "baz")))))
+
+(em-extpipe-tests--deftest em-extpipe-test-9 "foo \\*| bar"
+ (should-parse
+ '(eshell-execute-pipeline
+ '((eshell-named-command "foo"
+ (list (eshell-escape-arg "*")))
+ (eshell-named-command "bar")))))
+
+(em-extpipe-tests--deftest em-extpipe-test-10 "foo \"*|\" *>bar"
+ (should-parse
+ '(eshell-named-command "sh" (list "-c" "foo \"*|\" >bar"))))
+
+(em-extpipe-tests--deftest em-extpipe-test-11 "foo '*|' bar"
+ (should-parse '(eshell-named-command
+ "foo" (list (eshell-escape-arg "*|") "bar"))))
+
+(em-extpipe-tests--deftest em-extpipe-test-12 ">foo bar *| baz"
+ (should-parse
+ '(eshell-named-command "sh" (list "-c" ">foo bar | baz"))))
+
+(em-extpipe-tests--deftest em-extpipe-test-13 "foo*|bar"
+ (should-parse '(eshell-execute-pipeline
+ '((eshell-named-command (eshell-concat nil "foo" "*"))
+ (eshell-named-command "bar")))))
+
+(em-extpipe-tests--deftest em-extpipe-test-14 "tac *<temp"
+ (skip-unless (executable-find "tac"))
+ (should-parse '(eshell-named-command "sh" (list "-c" "tac <temp")))
+ (with-substitute-for-temp
+ (with-temp-buffer (insert "bar\nbaz\n") (write-file temp))
+ (eshell-match-command-output input "baz\nbar")))
+
+(em-extpipe-tests--deftest em-extpipe-test-15 "echo \"bar\" *| cat"
+ (skip-unless (executable-find "cat"))
+ (should-parse
+ '(eshell-named-command "sh" (list "-c" "echo \"bar\" | cat")))
+ (cl-letf (((symbol-function 'eshell/cat)
+ (lambda (&rest _args) (eshell-print "nonsense"))))
+ (eshell-match-command-output input "bar")
+ (eshell-match-command-output "echo \"bar\" | cat" "nonsense")))
+
+(em-extpipe-tests--deftest em-extpipe-test-16 "echo \"bar\" *| rev"
+ (skip-unless (executable-find "rev"))
+ (should-parse
+ '(eshell-named-command "sh" (list "-c" "echo \"bar\" | rev")))
+ (let ((eshell-prefer-lisp-functions t))
+ (cl-letf (((symbol-function 'rev)
+ (lambda (&rest _args) (eshell-print "nonsense"))))
+ (eshell-match-command-output input "rab")
+ (eshell-match-command-output "echo \"bar\" | rev" "nonsense"))))
+
+;; Confirm we don't break input of sharp-quoted symbols (Bug#53518).
+(em-extpipe-tests--deftest em-extpipe-test-17 "funcall #'upcase foo"
+ (eshell-match-command-output input "FOO"))
+
+;;; em-extpipe-tests.el ends here
diff --git a/test/lisp/eshell/em-glob-tests.el b/test/lisp/eshell/em-glob-tests.el
new file mode 100644
index 00000000000..b733be35d9a
--- /dev/null
+++ b/test/lisp/eshell/em-glob-tests.el
@@ -0,0 +1,197 @@
+;;; em-glob-tests.el --- em-glob test suite -*- lexical-binding:t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Tests for Eshell's glob expansion.
+
+;;; Code:
+
+(require 'ert)
+(require 'em-glob)
+
+(defmacro with-fake-files (files &rest body)
+ "Evaluate BODY forms, pretending that FILES exist on the filesystem.
+FILES is a list of file names that should be reported as
+appropriate by `file-name-all-completions'. Any file name
+component ending in \"symlink\" is treated as a symbolic link."
+ (declare (indent 1))
+ `(cl-letf (((symbol-function 'file-name-all-completions)
+ (lambda (file directory)
+ (cl-assert (string= file ""))
+ (setq directory (expand-file-name directory))
+ `("./" "../"
+ ,@(delete-dups
+ (remq nil
+ (mapcar
+ (lambda (file)
+ (setq file (expand-file-name file))
+ (when (string-prefix-p directory file)
+ (replace-regexp-in-string
+ "/.*" "/"
+ (substring file (length directory)))))
+ ,files))))))
+ ((symbol-function 'file-symlink-p)
+ (lambda (file)
+ (string-suffix-p "symlink" file))))
+ ,@body))
+
+;;; Tests:
+
+(ert-deftest em-glob-test/match-any-string ()
+ "Test that \"*\" pattern matches any string."
+ (with-fake-files '("a.el" "b.el" "c.txt" "dir/a.el")
+ (should (equal (eshell-extended-glob "*.el")
+ '("a.el" "b.el")))))
+
+(ert-deftest em-glob-test/match-any-directory ()
+ "Test that \"*/\" pattern matches any directory."
+ (with-fake-files '("a.el" "b.el" "dir/a.el" "dir/sub/a.el" "symlink/")
+ (should (equal (eshell-extended-glob "*/")
+ '("dir/" "symlink/")))))
+
+(ert-deftest em-glob-test/match-any-character ()
+ "Test that \"?\" pattern matches any character."
+ (with-fake-files '("a.el" "b.el" "ccc.el" "d.txt" "dir/a.el")
+ (should (equal (eshell-extended-glob "?.el")
+ '("a.el" "b.el")))))
+
+(ert-deftest em-glob-test/match-recursive ()
+ "Test that \"**/\" recursively matches directories."
+ (with-fake-files '("a.el" "b.el" "ccc.el" "d.txt" "dir/a.el" "dir/sub/a.el"
+ "dir/symlink/a.el" "symlink/a.el" "symlink/sub/a.el")
+ (should (equal (eshell-extended-glob "**/a.el")
+ '("a.el" "dir/a.el" "dir/sub/a.el")))
+ (should (equal (eshell-extended-glob "**/")
+ '("dir/" "dir/sub/")))))
+
+(ert-deftest em-glob-test/match-recursive-follow-symlinks ()
+ "Test that \"***/\" recursively matches directories, following symlinks."
+ (with-fake-files '("a.el" "b.el" "ccc.el" "d.txt" "dir/a.el" "dir/sub/a.el"
+ "dir/symlink/a.el" "symlink/a.el" "symlink/sub/a.el")
+ (should (equal (eshell-extended-glob "***/a.el")
+ '("a.el" "dir/a.el" "dir/sub/a.el" "dir/symlink/a.el"
+ "symlink/a.el" "symlink/sub/a.el")))
+ (should (equal (eshell-extended-glob "***/")
+ '("dir/" "dir/sub/" "dir/symlink/" "symlink/"
+ "symlink/sub/")))))
+
+(ert-deftest em-glob-test/match-recursive-mixed ()
+ "Test combination of \"**/\" and \"***/\"."
+ (with-fake-files '("dir/a.el" "dir/sub/a.el" "dir/sub2/a.el"
+ "dir/symlink/a.el" "dir/sub/symlink/a.el" "symlink/a.el"
+ "symlink/sub/a.el" "symlink/sub/symlink/a.el")
+ (should (equal (eshell-extended-glob "**/sub/***/a.el")
+ '("dir/sub/a.el" "dir/sub/symlink/a.el")))
+ (should (equal (eshell-extended-glob "***/sub/**/a.el")
+ '("dir/sub/a.el" "symlink/sub/a.el")))))
+
+(ert-deftest em-glob-test/match-character-set-individual ()
+ "Test \"[...]\" for individual characters."
+ (with-fake-files '("a.el" "b.el" "c.el" "d.el" "dir/a.el")
+ (should (equal (eshell-extended-glob "[ab].el")
+ '("a.el" "b.el")))
+ (should (equal (eshell-extended-glob "[^ab].el")
+ '("c.el" "d.el")))))
+
+(ert-deftest em-glob-test/match-character-set-range ()
+ "Test \"[...]\" for character ranges."
+ (with-fake-files '("a.el" "b.el" "c.el" "d.el" "dir/a.el")
+ (should (equal (eshell-extended-glob "[a-c].el")
+ '("a.el" "b.el" "c.el")))
+ (should (equal (eshell-extended-glob "[^a-c].el")
+ '("d.el")))))
+
+(ert-deftest em-glob-test/match-character-set-class ()
+ "Test \"[...]\" for character classes."
+ (with-fake-files '("1.el" "a.el" "b.el" "c.el" "dir/a.el")
+ (should (equal (eshell-extended-glob "[[:alpha:]].el")
+ '("a.el" "b.el" "c.el")))
+ (should (equal (eshell-extended-glob "[^[:alpha:]].el")
+ '("1.el")))))
+
+(ert-deftest em-glob-test/match-character-set-mixed ()
+ "Test \"[...]\" with multiple kinds of members at once."
+ (with-fake-files '("1.el" "a.el" "b.el" "c.el" "d.el" "dir/a.el")
+ (should (equal (eshell-extended-glob "[ac-d[:digit:]].el")
+ '("1.el" "a.el" "c.el" "d.el")))
+ (should (equal (eshell-extended-glob "[^ac-d[:digit:]].el")
+ '("b.el")))))
+
+(ert-deftest em-glob-test/match-group-alternative ()
+ "Test \"(x|y)\" matches either \"x\" or \"y\"."
+ (with-fake-files '("em-alias.el" "em-banner.el" "esh-arg.el" "misc.el"
+ "test/em-xtra.el")
+ (should (equal (eshell-extended-glob "e(m|sh)-*.el")
+ '("em-alias.el" "em-banner.el" "esh-arg.el")))))
+
+(ert-deftest em-glob-test/match-n-or-more-characters ()
+ "Test that \"x#\" and \"x#\" match zero or more instances of \"x\"."
+ (with-fake-files '("h.el" "ha.el" "hi.el" "hii.el" "dir/hi.el")
+ (should (equal (eshell-extended-glob "hi#.el")
+ '("h.el" "hi.el" "hii.el")))
+ (should (equal (eshell-extended-glob "hi##.el")
+ '("hi.el" "hii.el")))))
+
+(ert-deftest em-glob-test/match-n-or-more-groups ()
+ "Test that \"(x)#\" and \"(x)#\" match zero or more instances of \"(x)\"."
+ (with-fake-files '("h.el" "ha.el" "hi.el" "hii.el" "dir/hi.el")
+ (should (equal (eshell-extended-glob "hi#.el")
+ '("h.el" "hi.el" "hii.el")))
+ (should (equal (eshell-extended-glob "hi##.el")
+ '("hi.el" "hii.el")))))
+
+(ert-deftest em-glob-test/match-n-or-more-character-sets ()
+ "Test that \"[x]#\" and \"[x]#\" match zero or more instances of \"[x]\"."
+ (with-fake-files '("w.el" "wh.el" "wha.el" "whi.el" "whaha.el" "dir/wha.el")
+ (should (equal (eshell-extended-glob "w[ah]#.el")
+ '("w.el" "wh.el" "wha.el" "whaha.el")))
+ (should (equal (eshell-extended-glob "w[ah]##.el")
+ '("wh.el" "wha.el" "whaha.el")))))
+
+(ert-deftest em-glob-test/match-x-but-not-y ()
+ "Test that \"x~y\" matches \"x\" but not \"y\"."
+ (with-fake-files '("1" "12" "123" "42" "dir/1")
+ (should (equal (eshell-extended-glob "[[:digit:]]##~4?")
+ '("1" "12" "123")))))
+
+(ert-deftest em-glob-test/match-dot-files ()
+ "Test that dot files are matched correctly."
+ (with-fake-files '("foo.el" ".emacs")
+ (should (equal (eshell-extended-glob ".*")
+ '("../" "./" ".emacs")))
+ (let (eshell-glob-include-dot-dot)
+ (should (equal (eshell-extended-glob ".*")
+ '(".emacs"))))
+ (let ((eshell-glob-include-dot-files t))
+ (should (equal (eshell-extended-glob "*")
+ '("../" "./" ".emacs" "foo.el")))
+ (let (eshell-glob-include-dot-dot)
+ (should (equal (eshell-extended-glob "*")
+ '(".emacs" "foo.el")))))))
+
+(ert-deftest em-glob-test/no-matches ()
+ "Test behavior when a glob fails to match any files."
+ (with-fake-files '("foo.el" "bar.el")
+ (should (equal (eshell-extended-glob "*.txt")
+ "*.txt"))
+ (let ((eshell-error-if-no-glob t))
+ (should-error (eshell-extended-glob "*.txt")))))
+
+;; em-glob-tests.el ends here
diff --git a/test/lisp/eshell/em-hist-tests.el b/test/lisp/eshell/em-hist-tests.el
new file mode 100644
index 00000000000..634e9819839
--- /dev/null
+++ b/test/lisp/eshell/em-hist-tests.el
@@ -0,0 +1,38 @@
+;;; em-hist-tests.el --- em-hist test suite -*- lexical-binding:t -*-
+
+;; Copyright (C) 2017-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'ert-x)
+(require 'em-hist)
+
+(ert-deftest eshell-write-readonly-history ()
+ "Test that having read-only strings in history is okay."
+ (ert-with-temp-file histfile
+ (let ((eshell-history-ring (make-ring 2)))
+ (ring-insert eshell-history-ring
+ (propertize "echo foo" 'read-only t))
+ (ring-insert eshell-history-ring
+ (propertize "echo bar" 'read-only t))
+ (eshell-write-history histfile))))
+
+(provide 'em-hist-test)
+
+;;; em-hist-tests.el ends here
diff --git a/test/lisp/eshell/em-ls-tests.el b/test/lisp/eshell/em-ls-tests.el
index 35d6171400f..272280e81c7 100644
--- a/test/lisp/eshell/em-ls-tests.el
+++ b/test/lisp/eshell/em-ls-tests.el
@@ -1,6 +1,6 @@
-;;; tests/em-ls-tests.el --- em-ls test suite
+;;; em-ls-tests.el --- em-ls test suite -*- lexical-binding:t -*-
-;; Copyright (C) 2017 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2022 Free Software Foundation, Inc.
;; Author: Tino Calancha <tino.calancha@gmail.com>
@@ -25,29 +25,30 @@
;;; Code:
(require 'ert)
+(require 'ert-x)
(require 'em-ls)
+(require 'dired)
(ert-deftest em-ls-test-bug27631 ()
"Test for https://debbugs.gnu.org/27631 ."
- (let* ((dir (make-temp-file "bug27631" 'dir))
- (dir1 (expand-file-name "dir1" dir))
- (dir2 (expand-file-name "dir2" dir))
- (default-directory dir)
- (orig eshell-ls-use-in-dired)
- buf)
- (unwind-protect
- (progn
- (customize-set-value 'eshell-ls-use-in-dired t)
- (make-directory dir1)
- (make-directory dir2)
- (with-temp-file (expand-file-name "a.txt" dir1))
- (with-temp-file (expand-file-name "b.txt" dir2))
- (setq buf (dired (expand-file-name "dir*/*.txt" dir)))
- (dired-toggle-marks)
- (should (cdr (dired-get-marked-files))))
- (customize-set-variable 'eshell-ls-use-in-dired orig)
- (delete-directory dir 'recursive)
- (when (buffer-live-p buf) (kill-buffer buf)))))
+ (ert-with-temp-directory dir
+ (let* ((dir1 (expand-file-name "dir1" dir))
+ (dir2 (expand-file-name "dir2" dir))
+ (default-directory dir)
+ (orig eshell-ls-use-in-dired)
+ buf)
+ (unwind-protect
+ (progn
+ (customize-set-value 'eshell-ls-use-in-dired t)
+ (make-directory dir1)
+ (make-directory dir2)
+ (with-temp-file (expand-file-name "a.txt" dir1))
+ (with-temp-file (expand-file-name "b.txt" dir2))
+ (setq buf (dired (expand-file-name "dir*/*.txt" dir)))
+ (dired-toggle-marks)
+ (should (cdr (dired-get-marked-files))))
+ (customize-set-variable 'eshell-ls-use-in-dired orig)
+ (when (buffer-live-p buf) (kill-buffer buf))))))
(ert-deftest em-ls-test-bug27817 ()
"Test for https://debbugs.gnu.org/27817 ."
@@ -77,6 +78,11 @@
(ert-deftest em-ls-test-bug27844 ()
"Test for https://debbugs.gnu.org/27844 ."
+ ;; FIXME: it would be better to use something other than source-directory
+ ;; in this test.
+ (skip-unless (and source-directory
+ (file-exists-p
+ (expand-file-name "lisp/subr.el" source-directory))))
(let ((orig eshell-ls-use-in-dired)
(dired-use-ls-dired 'unspecified)
buf insert-directory-program)
@@ -87,7 +93,14 @@
(dired-toggle-marks)
(should (cdr (dired-get-marked-files)))
(kill-buffer buf)
- (setq buf (dired (expand-file-name "lisp/subr.el" source-directory)))
+ ;; Eshell's default format duplicates the year for non-recent files,
+ ;; eg "2015-05-06 2015", which doesn't make a lot of sense,
+ ;; and causes this portion of the test to fail if subr.el
+ ;; is non-recent (eg if building from a tarfile unpacked
+ ;; with a fixed early timestamp for reproducibility). Bug#33734.
+ (let ((eshell-ls-date-format "%b %e"))
+ (setq buf (dired (expand-file-name "lisp/subr.el"
+ source-directory))))
(should (looking-at "subr\\.el")))
(customize-set-variable 'eshell-ls-use-in-dired orig)
(and (buffer-live-p buf) (kill-buffer)))))
diff --git a/test/lisp/eshell/em-pred-tests.el b/test/lisp/eshell/em-pred-tests.el
new file mode 100644
index 00000000000..0d6351ec826
--- /dev/null
+++ b/test/lisp/eshell/em-pred-tests.el
@@ -0,0 +1,566 @@
+;;; em-pred-tests.el --- em-pred test suite -*- lexical-binding:t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Tests for Eshell's argument predicates/modifiers.
+
+;;; Code:
+
+(require 'ert)
+(require 'esh-mode)
+(require 'eshell)
+(require 'em-glob)
+(require 'em-pred)
+
+(require 'eshell-tests-helpers
+ (expand-file-name "eshell-tests-helpers"
+ (file-name-directory (or load-file-name
+ default-directory))))
+
+(defvar eshell-test-value nil)
+
+(defun eshell-eval-predicate (initial-value predicate)
+ "Evaluate PREDICATE on INITIAL-VALUE, returning the result.
+PREDICATE is an Eshell argument predicate/modifier."
+ (let ((eshell-test-value initial-value))
+ (ignore-errors
+ (eshell-test-command-result
+ (format "echo $eshell-test-value(%s)" predicate)))))
+
+(defun eshell-parse-file-name-attributes (file)
+ "Parse a fake FILE name to determine its attributes.
+Fake file names are file names beginning with \"/fake/\". This
+allows defining file names for fake files with various properties
+to query via predicates. Attributes are written as a
+comma-separate list of ATTR=VALUE pairs as the file's base name,
+like:
+
+ /fake/type=-,modes=0755.el
+
+The following attributes are recognized:
+
+ * \"type\": A single character describing the file type;
+ accepts the same values as the first character of the file
+ modes in `ls -l'.
+ * \"modes\": The file's permission modes, in octal.
+ * \"links\": The number of links to this file.
+ * \"uid\": The UID of the file's owner.
+ * \"gid\": The UID of the file's group.
+ * \"atime\": The time the file was last accessed, in seconds
+ since the UNIX epoch.
+ * \"mtime\": As \"atime\", but for modification time.
+ * \"ctime\": As \"atime\", but for inode change time.
+ * \"size\": The file's size in bytes."
+ (mapcar (lambda (i)
+ (pcase (split-string i "=")
+ (`("modes" ,modes)
+ (cons 'modes (string-to-number modes 8)))
+ (`(,(and (or "links" "uid" "gid" "size") key) ,value)
+ (cons (intern key) (string-to-number value)))
+ (`(,(and (or "atime" "mtime" "ctime") key) ,value)
+ (cons (intern key) (time-convert (string-to-number value) t)))
+ (`(,key ,value)
+ (cons (intern key) value))
+ (_ (error "invalid format %S" i))))
+ (split-string (file-name-base file) ",")))
+
+(defmacro eshell-partial-let-func (overrides &rest body)
+ "Temporarily bind to FUNCTION-NAMEs and evaluate BODY.
+This is roughly analogous to advising functions, but only does so
+while BODY is executing, and only calls NEW-FUNCTION if its first
+argument is a string beginning with \"/fake/\".
+
+This allows selectively overriding functions to test file
+properties with fake files without altering the functions'
+behavior for real files.
+
+\(fn ((FUNCTION-NAME NEW-FUNCTION) ...) BODY...)"
+ (declare (indent 1))
+ `(cl-letf
+ ,(mapcar
+ (lambda (override)
+ `((symbol-function #',(car override))
+ (let ((orig-function (symbol-function #',(car override))))
+ (lambda (file &rest rest)
+ (apply
+ (if (and (stringp file) (string-prefix-p "/fake/" file))
+ ,(cadr override)
+ orig-function)
+ file rest)))))
+ overrides)
+ ,@body))
+
+(defmacro eshell-with-file-attributes-from-name (&rest body)
+ "Temporarily override file attribute functions and evaluate BODY."
+ (declare (indent 0))
+ `(eshell-partial-let-func
+ ((file-attributes
+ (lambda (file &optional _id-format)
+ (let ((attrs (eshell-parse-file-name-attributes file)))
+ (list (equal (alist-get 'type attrs) "d")
+ (or (alist-get 'links attrs) 1)
+ (or (alist-get 'uid attrs) 0)
+ (or (alist-get 'gid attrs) 0)
+ (or (alist-get 'atime attrs) nil)
+ (or (alist-get 'mtime attrs) nil)
+ (or (alist-get 'ctime attrs) nil)
+ (or (alist-get 'size attrs) 0)
+ (format "%s---------" (or (alist-get 'type attrs) "-"))
+ nil 0 0))))
+ (file-modes
+ (lambda (file _nofollow)
+ (let ((attrs (eshell-parse-file-name-attributes file)))
+ (or (alist-get 'modes attrs) 0))))
+ (file-exists-p #'always)
+ (file-regular-p
+ (lambda (file)
+ (let ((attrs (eshell-parse-file-name-attributes file)))
+ (member (or (alist-get 'type attrs) "-") '("-" "l")))))
+ (file-symlink-p
+ (lambda (file)
+ (let ((attrs (eshell-parse-file-name-attributes file)))
+ (equal (alist-get 'type attrs) "l"))))
+ (file-executable-p
+ (lambda (file)
+ (let ((attrs (eshell-parse-file-name-attributes file)))
+ ;; For simplicity, just return whether the file is
+ ;; world-executable.
+ (= (logand (or (alist-get 'modes attrs) 0) 1) 1)))))
+ ,@body))
+
+;;; Tests:
+
+
+;; Argument predicates
+
+(ert-deftest em-pred-test/predicate-file-types ()
+ "Test file type predicates."
+ (eshell-with-file-attributes-from-name
+ (let ((files (mapcar (lambda (i) (format "/fake/type=%s" i))
+ '("b" "c" "d/" "p" "s" "l" "-"))))
+ (should (equal (eshell-eval-predicate files "%")
+ '("/fake/type=b" "/fake/type=c")))
+ (should (equal (eshell-eval-predicate files "%b") '("/fake/type=b")))
+ (should (equal (eshell-eval-predicate files "%c") '("/fake/type=c")))
+ (should (equal (eshell-eval-predicate files "/") '("/fake/type=d/")))
+ (should (equal (eshell-eval-predicate files ".") '("/fake/type=-")))
+ (should (equal (eshell-eval-predicate files "p") '("/fake/type=p")))
+ (should (equal (eshell-eval-predicate files "=") '("/fake/type=s")))
+ (should (equal (eshell-eval-predicate files "@") '("/fake/type=l"))))))
+
+(ert-deftest em-pred-test/predicate-executable ()
+ "Test that \"*\" matches only regular, non-symlink executable files."
+ (eshell-with-file-attributes-from-name
+ (let ((files '("/fake/modes=0777" "/fake/modes=0666"
+ "/fake/type=d,modes=0777" "/fake/type=l,modes=0777")))
+ (should (equal (eshell-eval-predicate files "*")
+ '("/fake/modes=0777"))))))
+
+(defmacro em-pred-test--file-modes-deftest (name mode-template predicates
+ &optional docstring)
+ "Define NAME as a file-mode test.
+MODE-TEMPLATE is a format string to convert an integer from 0 to
+7 to an octal file mode. PREDICATES is a list of strings for the
+read, write, and execute predicates to query the file's modes."
+ (declare (indent 4) (doc-string 4))
+ `(ert-deftest ,name ()
+ ,docstring
+ (eshell-with-file-attributes-from-name
+ (let ((file-template (concat "/fake/modes=" ,mode-template)))
+ (cl-flet ((make-files (perms)
+ (mapcar (lambda (i) (format file-template i))
+ perms)))
+ (pcase-let ((files (make-files (number-sequence 0 7)))
+ (`(,read ,write ,exec) ,predicates))
+ (should (equal (eshell-eval-predicate files read)
+ (make-files '(4 5 6 7))))
+ (should (equal (eshell-eval-predicate files (concat "^" read))
+ (make-files '(0 1 2 3))))
+ (should (equal (eshell-eval-predicate files write)
+ (make-files '(2 3 6 7))))
+ (should (equal (eshell-eval-predicate files (concat "^" write))
+ (make-files '(0 1 4 5))))
+ (should (equal (eshell-eval-predicate files exec)
+ (make-files '(1 3 5 7))))
+ (should (equal (eshell-eval-predicate files (concat "^" exec))
+ (make-files '(0 2 4 6))))))))))
+
+(em-pred-test--file-modes-deftest em-pred-test/predicate-file-modes-owner
+ "0%o00" '("r" "w" "x")
+ "Test predicates for file permissions for the owner.")
+
+(em-pred-test--file-modes-deftest em-pred-test/predicate-file-modes-group
+ "00%o0" '("A" "I" "E")
+ "Test predicates for file permissions for the group.")
+
+(em-pred-test--file-modes-deftest em-pred-test/predicate-file-modes-world
+ "000%o" '("R" "W" "X")
+ "Test predicates for file permissions for the world.")
+
+(em-pred-test--file-modes-deftest em-pred-test/predicate-file-modes-flags
+ "%o000" '("s" "S" "t")
+ "Test predicates for \"s\" (setuid), \"S\" (setgid), and \"t\" (sticky).")
+
+(ert-deftest em-pred-test/predicate-effective-uid ()
+ "Test that \"U\" matches files owned by the effective UID."
+ (eshell-with-file-attributes-from-name
+ (cl-letf (((symbol-function 'user-uid) (lambda () 1)))
+ (let ((files '("/fake/uid=1" "/fake/uid=2")))
+ (should (equal (eshell-eval-predicate files "U")
+ '("/fake/uid=1")))))))
+
+(ert-deftest em-pred-test/predicate-effective-gid ()
+ "Test that \"G\" matches files owned by the effective GID."
+ (eshell-with-file-attributes-from-name
+ (cl-letf (((symbol-function 'group-gid) (lambda () 1)))
+ (let ((files '("/fake/gid=1" "/fake/gid=2")))
+ (should (equal (eshell-eval-predicate files "G")
+ '("/fake/gid=1")))))))
+
+(ert-deftest em-pred-test/predicate-links ()
+ "Test that \"l\" filters by number of links."
+ (eshell-with-file-attributes-from-name
+ (let ((files '("/fake/links=1" "/fake/links=2" "/fake/links=3")))
+ (should (equal (eshell-eval-predicate files "l1")
+ '("/fake/links=1")))
+ (should (equal (eshell-eval-predicate files "l+1")
+ '("/fake/links=2" "/fake/links=3")))
+ (should (equal (eshell-eval-predicate files "l-3")
+ '("/fake/links=1" "/fake/links=2"))))))
+
+(ert-deftest em-pred-test/predicate-uid ()
+ "Test that \"u\" filters by UID/user name."
+ (eshell-with-file-attributes-from-name
+ (let ((files '("/fake/uid=1" "/fake/uid=2"))
+ (user-names '("root" "one" "two")))
+ (should (equal (eshell-eval-predicate files "u1")
+ '("/fake/uid=1")))
+ (cl-letf (((symbol-function 'eshell-user-id)
+ (lambda (name) (seq-position user-names name))))
+ (should (equal (eshell-eval-predicate files "u'one'")
+ '("/fake/uid=1")))))))
+
+(ert-deftest em-pred-test/predicate-gid ()
+ "Test that \"g\" filters by GID/group name."
+ (eshell-with-file-attributes-from-name
+ (let ((files '("/fake/gid=1" "/fake/gid=2"))
+ (group-names '("root" "one" "two")))
+ (should (equal (eshell-eval-predicate files "g1")
+ '("/fake/gid=1")))
+ (cl-letf (((symbol-function 'eshell-group-id)
+ (lambda (name) (seq-position group-names name))))
+ (should (equal (eshell-eval-predicate files "g'one'")
+ '("/fake/gid=1")))))))
+
+(defmacro em-pred-test--time-deftest (name file-attribute predicate
+ &optional docstring)
+ "Define NAME as a file-time test.
+FILE-ATTRIBUTE is the file's attribute to set (e.g. \"atime\").
+PREDICATE is the predicate used to query that attribute."
+ (declare (indent 4) (doc-string 4))
+ `(ert-deftest ,name ()
+ ,docstring
+ (eshell-with-file-attributes-from-name
+ (cl-flet ((make-file (time)
+ (format "/fake/%s=%d" ,file-attribute time)))
+ (let* ((now (time-convert nil 'integer))
+ (yesterday (- now 86400))
+ (files (mapcar #'make-file (list now yesterday))))
+ ;; Test comparison against a number of days.
+ (should (equal (eshell-eval-predicate
+ files (concat ,predicate "-1"))
+ (mapcar #'make-file (list now))))
+ (should (equal (eshell-eval-predicate
+ files (concat ,predicate "+1"))
+ (mapcar #'make-file (list yesterday))))
+ (should (equal (eshell-eval-predicate
+ files (concat ,predicate "+2"))
+ nil))
+ ;; Test comparison against a number of hours.
+ (should (equal (eshell-eval-predicate
+ files (concat ,predicate "h-1"))
+ (mapcar #'make-file (list now))))
+ (should (equal (eshell-eval-predicate
+ files (concat ,predicate "h+1"))
+ (mapcar #'make-file (list yesterday))))
+ (should (equal (eshell-eval-predicate
+ files (concat ,predicate "+48"))
+ nil))
+ ;; Test comparison against another file.
+ (should (equal (eshell-eval-predicate
+ files (format "%s-'%s'" ,predicate (make-file now)))
+ nil))
+ (should (equal (eshell-eval-predicate
+ files (format "%s+'%s'" ,predicate (make-file now)))
+ (mapcar #'make-file (list yesterday)))))))))
+
+(em-pred-test--time-deftest em-pred-test/predicate-access-time
+ "atime" "a"
+ "Test that \"a\" filters by access time.")
+
+(em-pred-test--time-deftest em-pred-test/predicate-modification-time
+ "mtime" "m"
+ "Test that \"m\" filters by change time.")
+
+(em-pred-test--time-deftest em-pred-test/predicate-change-time
+ "ctime" "c"
+ "Test that \"c\" filters by change time.")
+
+(ert-deftest em-pred-test/predicate-size ()
+ "Test that \"L\" filters by file size."
+ (eshell-with-file-attributes-from-name
+ (let ((files '("/fake/size=0"
+ ;; 1 and 2 KiB.
+ "/fake/size=1024" "/fake/size=2048"
+ ;; 1 and 2 MiB.
+ "/fake/size=1048576" "/fake/size=2097152")))
+ ;; Size in bytes.
+ (should (equal (eshell-eval-predicate files "L2048")
+ '("/fake/size=2048")))
+ (should (equal (eshell-eval-predicate files "L+2048")
+ '("/fake/size=1048576" "/fake/size=2097152")))
+ (should (equal (eshell-eval-predicate files "L-2048")
+ '("/fake/size=0" "/fake/size=1024")))
+ ;; Size in blocks.
+ (should (equal (eshell-eval-predicate files "Lp4")
+ '("/fake/size=2048")))
+ (should (equal (eshell-eval-predicate files "Lp+4")
+ '("/fake/size=1048576" "/fake/size=2097152")))
+ (should (equal (eshell-eval-predicate files "Lp-4")
+ '("/fake/size=0" "/fake/size=1024")))
+ ;; Size in KiB.
+ (should (equal (eshell-eval-predicate files "Lk2")
+ '("/fake/size=2048")))
+ (should (equal (eshell-eval-predicate files "Lk+2")
+ '("/fake/size=1048576" "/fake/size=2097152")))
+ (should (equal (eshell-eval-predicate files "Lk-2")
+ '("/fake/size=0" "/fake/size=1024")))
+ ;; Size in MiB.
+ (should (equal (eshell-eval-predicate files "LM1")
+ '("/fake/size=1048576")))
+ (should (equal (eshell-eval-predicate files "LM+1")
+ '("/fake/size=2097152")))
+ (should (equal (eshell-eval-predicate files "LM-1")
+ '("/fake/size=0" "/fake/size=1024" "/fake/size=2048"))))))
+
+
+;; Argument modifiers
+
+(ert-deftest em-pred-test/modifier-eval ()
+ "Test that \":E\" re-evaluates the value."
+ (should (equal (eshell-eval-predicate "${echo hi}" ":E") "hi"))
+ (should (equal (eshell-eval-predicate
+ '("${echo hi}" "$(upcase \"bye\")") ":E")
+ '("hi" "BYE"))))
+
+(ert-deftest em-pred-test/modifier-downcase ()
+ "Test that \":L\" downcases values."
+ (should (equal (eshell-eval-predicate "FOO" ":L") "foo"))
+ (should (equal (eshell-eval-predicate '("FOO" "BAR") ":L")
+ '("foo" "bar"))))
+
+(ert-deftest em-pred-test/modifier-upcase ()
+ "Test that \":U\" upcases values."
+ (should (equal (eshell-eval-predicate "foo" ":U") "FOO"))
+ (should (equal (eshell-eval-predicate '("foo" "bar") ":U")
+ '("FOO" "BAR"))))
+
+(ert-deftest em-pred-test/modifier-capitalize ()
+ "Test that \":C\" capitalizes values."
+ (should (equal (eshell-eval-predicate "foo bar" ":C") "Foo Bar"))
+ (should (equal (eshell-eval-predicate '("foo bar" "baz") ":C")
+ '("Foo Bar" "Baz"))))
+
+(ert-deftest em-pred-test/modifier-dirname ()
+ "Test that \":h\" returns the dirname."
+ (should (equal (eshell-eval-predicate "/path/to/file.el" ":h") "/path/to/"))
+ (should (equal (eshell-eval-predicate
+ '("/path/to/file.el" "/other/path/") ":h")
+ '("/path/to/" "/other/path/"))))
+
+(ert-deftest em-pred-test/modifier-basename ()
+ "Test that \":t\" returns the basename."
+ (should (equal (eshell-eval-predicate "/path/to/file.el" ":t") "file.el"))
+ (should (equal (eshell-eval-predicate
+ '("/path/to/file.el" "/other/path/") ":t")
+ '("file.el" ""))))
+
+(ert-deftest em-pred-test/modifier-extension ()
+ "Test that \":e\" returns the extension."
+ (should (equal (eshell-eval-predicate "/path/to/file.el" ":e") "el"))
+ (should (equal (eshell-eval-predicate
+ '("/path/to/file.el" "/other/path/") ":e")
+ '("el" nil))))
+
+(ert-deftest em-pred-test/modifier-sans-extension ()
+ "Test that \":r\" returns the file name san extension."
+ (should (equal (eshell-eval-predicate "/path/to/file.el" ":r")
+ "/path/to/file"))
+ (should (equal (eshell-eval-predicate
+ '("/path/to/file.el" "/other/path/") ":r")
+ '("/path/to/file" "/other/path/"))))
+
+(ert-deftest em-pred-test/modifier-quote ()
+ "Test that \":q\" quotes arguments."
+ (should (equal-including-properties
+ (eshell-eval-predicate '("foo" "bar") ":q")
+ (list (eshell-escape-arg "foo") (eshell-escape-arg "bar")))))
+
+(ert-deftest em-pred-test/modifier-substitute ()
+ "Test that \":s/PAT/REP/\" replaces PAT with REP once."
+ (should (equal (eshell-eval-predicate "bar" ":s/a/*/") "b*r"))
+ (should (equal (eshell-eval-predicate "bar" ":s|a|*|") "b*r"))
+ (should (equal (eshell-eval-predicate "bar" ":s{a}{*}") "b*r"))
+ (should (equal (eshell-eval-predicate "bar" ":s{a}'*'") "b*r"))
+ (should (equal (eshell-eval-predicate '("foo" "bar" "baz") ":s/[ao]/*/")
+ '("f*o" "b*r" "b*z")))
+ (should (equal (eshell-eval-predicate '("foo" "bar" "baz") ":s|[ao]|*|")
+ '("f*o" "b*r" "b*z"))))
+
+(ert-deftest em-pred-test/modifier-global-substitute ()
+ "Test that \":s/PAT/REP/\" replaces PAT with REP for all occurrences."
+ (should (equal (eshell-eval-predicate "foo" ":gs/a/*/") "foo"))
+ (should (equal (eshell-eval-predicate "foo" ":gs|a|*|") "foo"))
+ (should (equal (eshell-eval-predicate "bar" ":gs/a/*/") "b*r"))
+ (should (equal (eshell-eval-predicate "bar" ":gs|a|*|") "b*r"))
+ (should (equal (eshell-eval-predicate "foo" ":gs/o/O/") "fOO"))
+ (should (equal (eshell-eval-predicate '("foo" "bar" "baz") ":gs/[aeiou]/*/")
+ '("f**" "b*r" "b*z")))
+ (should (equal (eshell-eval-predicate '("foo" "bar" "baz") ":gs|[aeiou]|*|")
+ '("f**" "b*r" "b*z"))))
+
+(ert-deftest em-pred-test/modifier-include ()
+ "Test that \":i/PAT/\" filters elements to include only ones matching PAT."
+ (should (equal (eshell-eval-predicate "foo" ":i/a/") nil))
+ (should (equal (eshell-eval-predicate "bar" ":i/a/") "bar"))
+ (should (equal (eshell-eval-predicate '("foo" "bar" "baz") ":i/a/")
+ '("bar" "baz"))))
+
+(ert-deftest em-pred-test/modifier-exclude ()
+ "Test that \":x/PAT/\" filters elements to exclude any matching PAT."
+ (should (equal (eshell-eval-predicate "foo" ":x/a/") "foo"))
+ (should (equal (eshell-eval-predicate "bar" ":x/a/") nil))
+ (should (equal (eshell-eval-predicate '("foo" "bar" "baz") ":x/a/")
+ '("foo"))))
+
+(ert-deftest em-pred-test/modifier-split ()
+ "Test that \":S\" and \":S/PAT/\" split elements by spaces (or PAT)."
+ (should (equal (eshell-eval-predicate "foo bar baz" ":S")
+ '("foo" "bar" "baz")))
+ (should (equal (eshell-eval-predicate '("foo bar" "baz") ":S")
+ '(("foo" "bar") ("baz"))))
+ (should (equal (eshell-eval-predicate "foo-bar-baz" ":S/-/")
+ '("foo" "bar" "baz")))
+ (should (equal (eshell-eval-predicate '("foo-bar" "baz") ":S/-/")
+ '(("foo" "bar") ("baz")))))
+
+(ert-deftest em-pred-test/modifier-join ()
+ "Test that \":j\" and \":j/DELIM/\" join elements by spaces (or DELIM)."
+ (should (equal (eshell-eval-predicate "foo" ":j") "foo"))
+ (should (equal (eshell-eval-predicate '("foo" "bar" "baz") ":j")
+ "foo bar baz"))
+ (should (equal (eshell-eval-predicate "foo" ":j/-/") "foo"))
+ (should (equal (eshell-eval-predicate '("foo" "bar" "baz") ":j/-/")
+ "foo-bar-baz")))
+
+(ert-deftest em-pred-test/modifier-sort ()
+ "Test that \":o\" sorts elements in lexicographic order."
+ (should (equal (eshell-eval-predicate "foo" ":o") "foo"))
+ (should (equal (eshell-eval-predicate '("foo" "bar" "baz") ":o")
+ '("bar" "baz" "foo"))))
+
+(ert-deftest em-pred-test/modifier-sort-reverse ()
+ "Test that \":o\" sorts elements in reverse lexicographic order."
+ (should (equal (eshell-eval-predicate "foo" ":O") "foo"))
+ (should (equal (eshell-eval-predicate '("foo" "bar" "baz") ":O")
+ '("foo" "baz" "bar"))))
+
+(ert-deftest em-pred-test/modifier-unique ()
+ "Test that \":u\" filters out duplicate elements."
+ (should (equal (eshell-eval-predicate "foo" ":u") "foo"))
+ (should (equal (eshell-eval-predicate '("foo" "bar" "baz") ":u")
+ '("foo" "bar" "baz")))
+ (should (equal (eshell-eval-predicate '("foo" "bar" "baz" "foo") ":u")
+ '("foo" "bar" "baz"))))
+
+(ert-deftest em-pred-test/modifier-reverse ()
+ "Test that \":r\" reverses the order of elements."
+ (should (equal (eshell-eval-predicate "foo" ":R") "foo"))
+ (should (equal (eshell-eval-predicate '("foo" "bar" "baz") ":R")
+ '("baz" "bar" "foo"))))
+
+
+;; Miscellaneous
+
+(ert-deftest em-pred-test/combine-predicate-and-modifier ()
+ "Test combination of predicates and modifiers."
+ (eshell-with-file-attributes-from-name
+ (let ((files '("/fake/type=-.el" "/fake/type=-.txt" "/fake/type=s.el"
+ "/fake/subdir/type=-.el")))
+ (should (equal (eshell-eval-predicate files ".:e:u")
+ '("el" "txt"))))))
+
+(ert-deftest em-pred-test/predicate-delimiters ()
+ "Test various delimiter pairs with predicates and modifiers."
+ (dolist (delims eshell-pred-delimiter-pairs)
+ (eshell-with-file-attributes-from-name
+ (let ((files '("/fake/uid=1" "/fake/uid=2"))
+ (user-names '("root" "one" "two")))
+ (cl-letf (((symbol-function 'eshell-user-id)
+ (lambda (name) (seq-position user-names name))))
+ (should (equal (eshell-eval-predicate
+ files (format "u%cone%c" (car delims) (cdr delims)))
+ '("/fake/uid=1"))))))
+ (should (equal (eshell-eval-predicate
+ '("foo" "bar" "baz")
+ (format ":j%c-%c" (car delims) (cdr delims)))
+ "foo-bar-baz"))))
+
+(ert-deftest em-pred-test/predicate-escaping ()
+ "Test string escaping in predicate and modifier parameters."
+ ;; Escaping the delimiter should remove the backslash.
+ (should (equal (eshell-eval-predicate '("foo" "bar" "baz") ":j'\\''")
+ "foo'bar'baz"))
+ ;; Escaping a backlash should remove the first backslash.
+ (should (equal (eshell-eval-predicate '("foo" "bar" "baz") ":j'\\\\'")
+ "foo\\bar\\baz"))
+ ;; Escaping a different character should keep the backslash.
+ (should (equal (eshell-eval-predicate '("foo" "bar" "baz") ":j'\\\"'")
+ "foo\\\"bar\\\"baz")))
+
+(ert-deftest em-pred-test/no-matches ()
+ "Test behavior when a predicate fails to match any files."
+ (eshell-with-file-attributes-from-name
+ (let ((files '("/fake/modes=0666" "/fake/type=d,modes=0777"
+ "/fake/type=l,modes=0777")))
+ (should (equal (eshell-eval-predicate files "*") nil))
+ (let ((eshell-error-if-no-glob t))
+ ;; Don't signal an error if the original list is empty.
+ (should (equal (eshell-eval-predicate nil "*") nil))
+ ;; Ensure this signals an error. This test case is a bit
+ ;; clumsy, since `eshell-do-eval' makes it hard to catch
+ ;; errors otherwise.
+ (let ((modifiers (with-temp-eshell
+ (eshell-with-temp-command "*"
+ (eshell-parse-modifiers)))))
+ (should-error (eshell-apply-modifiers files (car modifiers)
+ (cdr modifiers) "*")))))))
+
+;; em-pred-tests.el ends here
diff --git a/test/lisp/eshell/em-script-tests.el b/test/lisp/eshell/em-script-tests.el
new file mode 100644
index 00000000000..b837d464ccd
--- /dev/null
+++ b/test/lisp/eshell/em-script-tests.el
@@ -0,0 +1,62 @@
+;;; em-script-tests.el --- em-script test suite -*- lexical-binding:t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Tests for Eshell's script module.
+
+;;; Code:
+
+(require 'ert)
+(require 'esh-mode)
+(require 'eshell)
+(require 'em-script)
+
+(require 'eshell-tests-helpers
+ (expand-file-name "eshell-tests-helpers"
+ (file-name-directory (or load-file-name
+ default-directory))))
+;;; Tests:
+
+(ert-deftest em-script-test/source-script ()
+ "Test sourcing script with no argumentss"
+ (ert-with-temp-file temp-file :text "echo hi"
+ (with-temp-eshell
+ (eshell-match-command-output (format "source %s" temp-file)
+ "hi\n"))))
+
+(ert-deftest em-script-test/source-script-arg-vars ()
+ "Test sourcing script with $0, $1, ... variables"
+ (ert-with-temp-file temp-file :text "printnl $0 \"$1 $2\""
+ (with-temp-eshell
+ (eshell-match-command-output (format "source %s one two" temp-file)
+ (format "%s\none two\n" temp-file)))))
+
+(ert-deftest em-script-test/source-script-all-args-var ()
+ "Test sourcing script with the $* variable"
+ (ert-with-temp-file temp-file :text "printnl $*"
+ (with-temp-eshell
+ (eshell-match-command-output (format "source %s" temp-file)
+ "\\`\\'")
+ (eshell-match-command-output (format "source %s a" temp-file)
+ "a\n")
+ (eshell-match-command-output (format "source %s a b c" temp-file)
+ "a\nb\nc\n"))))
+
+;; em-script-tests.el ends here
diff --git a/test/lisp/eshell/em-tramp-tests.el b/test/lisp/eshell/em-tramp-tests.el
new file mode 100644
index 00000000000..8969c1e2294
--- /dev/null
+++ b/test/lisp/eshell/em-tramp-tests.el
@@ -0,0 +1,88 @@
+;;; em-tramp-tests.el --- em-tramp test suite -*- lexical-binding:t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'em-tramp)
+(require 'tramp)
+
+(ert-deftest em-tramp-test/su-default ()
+ "Test Eshell `su' command with no arguments."
+ (should (equal
+ (catch 'eshell-replace-command (eshell/su))
+ `(eshell-trap-errors
+ (eshell-named-command
+ "cd"
+ (list ,(format "/su:root@%s:%s"
+ tramp-default-host default-directory)))))))
+
+(ert-deftest em-tramp-test/su-user ()
+ "Test Eshell `su' command with USER argument."
+ (should (equal
+ (catch 'eshell-replace-command (eshell/su "USER"))
+ `(eshell-trap-errors
+ (eshell-named-command
+ "cd"
+ (list ,(format "/su:USER@%s:%s"
+ tramp-default-host default-directory)))))))
+
+(ert-deftest em-tramp-test/su-login ()
+ "Test Eshell `su' command with -/-l/--login option."
+ (dolist (args '(("--login")
+ ("-l")
+ ("-")))
+ (should (equal
+ (catch 'eshell-replace-command (apply #'eshell/su args))
+ `(eshell-trap-errors
+ (eshell-named-command
+ "cd"
+ (list ,(format "/su:root@%s:~/" tramp-default-host))))))))
+
+(defun mock-eshell-named-command (&rest args)
+ "Dummy function to test Eshell `sudo' command rewriting."
+ (list default-directory args))
+
+(ert-deftest em-tramp-test/sudo-basic ()
+ "Test Eshell `sudo' command with default user."
+ (cl-letf (((symbol-function 'eshell-named-command)
+ #'mock-eshell-named-command))
+ (should (equal
+ (catch 'eshell-external (eshell/sudo "echo" "hi"))
+ `(,(format "/sudo:root@%s:%s" tramp-default-host default-directory)
+ ("echo" ("hi")))))
+ (should (equal
+ (catch 'eshell-external (eshell/sudo "echo" "-u" "hi"))
+ `(,(format "/sudo:root@%s:%s" tramp-default-host default-directory)
+ ("echo" ("-u" "hi")))))))
+
+(ert-deftest em-tramp-test/sudo-user ()
+ "Test Eshell `sudo' command with specified user."
+ (cl-letf (((symbol-function 'eshell-named-command)
+ #'mock-eshell-named-command))
+ (should (equal
+ (catch 'eshell-external (eshell/sudo "-u" "USER" "echo" "hi"))
+ `(,(format "/sudo:USER@%s:%s" tramp-default-host default-directory)
+ ("echo" ("hi")))))
+ (should (equal
+ (catch 'eshell-external (eshell/sudo "-u" "USER" "echo" "-u" "hi"))
+ `(,(format "/sudo:USER@%s:%s" tramp-default-host default-directory)
+ ("echo" ("-u" "hi")))))))
+
+;;; em-tramp-tests.el ends here
diff --git a/test/lisp/eshell/esh-cmd-tests.el b/test/lisp/eshell/esh-cmd-tests.el
new file mode 100644
index 00000000000..92d785d7fdf
--- /dev/null
+++ b/test/lisp/eshell/esh-cmd-tests.el
@@ -0,0 +1,294 @@
+;;; esh-cmd-tests.el --- esh-cmd test suite -*- lexical-binding:t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Tests for Eshell's command invocation.
+
+;;; Code:
+
+(require 'ert)
+(require 'esh-mode)
+(require 'eshell)
+
+(require 'eshell-tests-helpers
+ (expand-file-name "eshell-tests-helpers"
+ (file-name-directory (or load-file-name
+ default-directory))))
+
+(defvar eshell-test-value nil)
+
+;;; Tests:
+
+
+;; Command invocation
+
+(ert-deftest esh-cmd-test/simple-command-result ()
+ "Test invocation with a simple command."
+ (eshell-command-result-equal "+ 1 2" 3))
+
+(ert-deftest esh-cmd-test/lisp-command ()
+ "Test invocation with an elisp command."
+ (eshell-command-result-equal "(+ 1 2)" 3))
+
+(ert-deftest esh-cmd-test/lisp-command-with-quote ()
+ "Test invocation with an elisp command containing a quote."
+ (eshell-command-result-equal "(eq 'foo nil)" nil))
+
+(ert-deftest esh-cmd-test/lisp-command-args ()
+ "Test invocation with elisp and trailing args.
+Test that trailing arguments outside the S-expression are
+ignored. e.g. \"(+ 1 2) 3\" => 3"
+ (eshell-command-result-equal "(+ 1 2) 3" 3))
+
+(ert-deftest esh-cmd-test/subcommand ()
+ "Test invocation with a simple subcommand."
+ (eshell-command-result-equal "{+ 1 2}" 3))
+
+(ert-deftest esh-cmd-test/subcommand-args ()
+ "Test invocation with a subcommand and trailing args.
+Test that trailing arguments outside the subcommand are ignored.
+e.g. \"{+ 1 2} 3\" => 3"
+ (eshell-command-result-equal "{+ 1 2} 3" 3))
+
+(ert-deftest esh-cmd-test/subcommand-lisp ()
+ "Test invocation with an elisp subcommand and trailing args.
+Test that trailing arguments outside the subcommand are ignored.
+e.g. \"{(+ 1 2)} 3\" => 3"
+ (eshell-command-result-equal "{(+ 1 2)} 3" 3))
+
+
+;; Lisp forms
+
+(ert-deftest esh-cmd-test/quoted-lisp-form ()
+ "Test parsing of a quoted Lisp form."
+ (eshell-command-result-equal "echo #'(1 2)" '(1 2)))
+
+(ert-deftest esh-cmd-test/backquoted-lisp-form ()
+ "Test parsing of a backquoted Lisp form."
+ (let ((eshell-test-value 42))
+ (eshell-command-result-equal "echo `(answer ,eshell-test-value)"
+ '(answer 42))))
+
+(ert-deftest esh-cmd-test/backquoted-lisp-form/splice ()
+ "Test parsing of a backquoted Lisp form using splicing."
+ (let ((eshell-test-value '(2 3)))
+ (eshell-command-result-equal "echo `(1 ,@eshell-test-value)"
+ '(1 2 3))))
+
+
+;; Logical operators
+
+(ert-deftest esh-cmd-test/and-operator ()
+ "Test logical && operator."
+ (skip-unless (executable-find "["))
+ (with-temp-eshell
+ (eshell-match-command-output "[ foo = foo ] && echo hi"
+ "hi\n")
+ (eshell-match-command-output "[ foo = bar ] && echo hi"
+ "\\`\\'")))
+
+(ert-deftest esh-cmd-test/or-operator ()
+ "Test logical || operator."
+ (skip-unless (executable-find "["))
+ (with-temp-eshell
+ (eshell-match-command-output "[ foo = foo ] || echo hi"
+ "\\`\\'")
+ (eshell-match-command-output "[ foo = bar ] || echo hi"
+ "hi\n")))
+
+
+;; Control flow statements
+
+(ert-deftest esh-cmd-test/for-loop ()
+ "Test invocation of a for loop."
+ (with-temp-eshell
+ (eshell-match-command-output "for i in 5 { echo $i }"
+ "5\n")))
+
+(ert-deftest esh-cmd-test/for-loop-list ()
+ "Test invocation of a for loop iterating over a list."
+ (with-temp-eshell
+ (eshell-match-command-output "for i in (list 1 2 (list 3 4)) { echo $i }"
+ "1\n2\n(3 4)\n")))
+
+(ert-deftest esh-cmd-test/for-loop-multiple-args ()
+ "Test invocation of a for loop iterating over multiple arguments."
+ (with-temp-eshell
+ (eshell-match-command-output "for i in 1 2 (list 3 4) { echo $i }"
+ "1\n2\n3\n4\n")))
+
+(ert-deftest esh-cmd-test/for-name-loop () ; bug#15231
+ "Test invocation of a for loop using `name'."
+ (let ((process-environment (cons "name" process-environment)))
+ (eshell-command-result-equal "for name in 3 { echo $name }"
+ 3)))
+
+(ert-deftest esh-cmd-test/for-name-shadow-loop () ; bug#15372
+ "Test invocation of a for loop using an env-var."
+ (let ((process-environment (cons "name=env-value" process-environment)))
+ (with-temp-eshell
+ (eshell-match-command-output
+ "echo $name; for name in 3 { echo $name }; echo $name"
+ "env-value\n3\nenv-value\n"))))
+
+(ert-deftest esh-cmd-test/while-loop ()
+ "Test invocation of a while loop."
+ (with-temp-eshell
+ (let ((eshell-test-value '(0 1 2)))
+ (eshell-match-command-output
+ (concat "while $eshell-test-value "
+ "{ setq eshell-test-value (cdr eshell-test-value) }")
+ "(1 2)\n(2)\n"))))
+
+(ert-deftest esh-cmd-test/while-loop-lisp-form ()
+ "Test invocation of a while loop using a Lisp form."
+ (with-temp-eshell
+ (let ((eshell-test-value 0))
+ (eshell-match-command-output
+ (concat "while (/= eshell-test-value 3) "
+ "{ setq eshell-test-value (1+ eshell-test-value) }")
+ "1\n2\n3\n"))))
+
+(ert-deftest esh-cmd-test/while-loop-ext-cmd ()
+ "Test invocation of a while loop using an external command."
+ (skip-unless (executable-find "["))
+ (with-temp-eshell
+ (let ((eshell-test-value 0))
+ (eshell-match-command-output
+ (concat "while {[ $eshell-test-value -ne 3 ]} "
+ "{ setq eshell-test-value (1+ eshell-test-value) }")
+ "1\n2\n3\n"))))
+
+(ert-deftest esh-cmd-test/until-loop ()
+ "Test invocation of an until loop."
+ (with-temp-eshell
+ (let ((eshell-test-value nil))
+ (eshell-match-command-output
+ (concat "until $eshell-test-value "
+ "{ setq eshell-test-value t }")
+ "t\n"))))
+
+(ert-deftest esh-cmd-test/until-loop-lisp-form ()
+ "Test invocation of an until loop using a Lisp form."
+ (skip-unless (executable-find "["))
+ (with-temp-eshell
+ (let ((eshell-test-value 0))
+ (eshell-match-command-output
+ (concat "until (= eshell-test-value 3) "
+ "{ setq eshell-test-value (1+ eshell-test-value) }")
+ "1\n2\n3\n"))))
+
+(ert-deftest esh-cmd-test/until-loop-ext-cmd ()
+ "Test invocation of an until loop using an external command."
+ (skip-unless (executable-find "["))
+ (with-temp-eshell
+ (let ((eshell-test-value 0))
+ (eshell-match-command-output
+ (concat "until {[ $eshell-test-value -eq 3 ]} "
+ "{ setq eshell-test-value (1+ eshell-test-value) }")
+ "1\n2\n3\n"))))
+
+(ert-deftest esh-cmd-test/if-statement ()
+ "Test invocation of an if statement."
+ (let ((eshell-test-value t))
+ (eshell-command-result-equal "if $eshell-test-value {echo yes}"
+ "yes"))
+ (let ((eshell-test-value nil))
+ (eshell-command-result-equal "if $eshell-test-value {echo yes}"
+ nil)))
+
+(ert-deftest esh-cmd-test/if-else-statement ()
+ "Test invocation of an if/else statement."
+ (let ((eshell-test-value t))
+ (eshell-command-result-equal "if $eshell-test-value {echo yes} {echo no}"
+ "yes"))
+ (let ((eshell-test-value nil))
+ (eshell-command-result-equal "if $eshell-test-value {echo yes} {echo no}"
+ "no")))
+
+(ert-deftest esh-cmd-test/if-else-statement-lisp-form ()
+ "Test invocation of an if/else statement using a Lisp form."
+ (eshell-command-result-equal "if (zerop 0) {echo yes} {echo no}"
+ "yes")
+ (eshell-command-result-equal "if (zerop 1) {echo yes} {echo no}"
+ "no")
+ (let ((debug-on-error nil))
+ (eshell-command-result-equal "if (zerop \"foo\") {echo yes} {echo no}"
+ "no")))
+
+(ert-deftest esh-cmd-test/if-else-statement-lisp-form-2 ()
+ "Test invocation of an if/else statement using a Lisp form.
+This tests when `eshell-lisp-form-nil-is-failure' is nil."
+ (let ((eshell-lisp-form-nil-is-failure nil))
+ (eshell-command-result-equal "if (zerop 0) {echo yes} {echo no}"
+ "yes")
+ (eshell-command-result-equal "if (zerop 1) {echo yes} {echo no}"
+ "yes")
+ (let ((debug-on-error nil))
+ (eshell-command-result-equal "if (zerop \"foo\") {echo yes} {echo no}"
+ "no"))))
+
+(ert-deftest esh-cmd-test/if-else-statement-ext-cmd ()
+ "Test invocation of an if/else statement using an external command."
+ (skip-unless (executable-find "["))
+ (eshell-command-result-equal "if {[ foo = foo ]} {echo yes} {echo no}"
+ "yes")
+ (eshell-command-result-equal "if {[ foo = bar ]} {echo yes} {echo no}"
+ "no"))
+
+(ert-deftest esh-cmd-test/unless-statement ()
+ "Test invocation of an unless statement."
+ (let ((eshell-test-value t))
+ (eshell-command-result-equal "unless $eshell-test-value {echo no}"
+ nil))
+ (let ((eshell-test-value nil))
+ (eshell-command-result-equal "unless $eshell-test-value {echo no}"
+ "no")))
+
+(ert-deftest esh-cmd-test/unless-else-statement ()
+ "Test invocation of an unless/else statement."
+ (let ((eshell-test-value t))
+ (eshell-command-result-equal
+ "unless $eshell-test-value {echo no} {echo yes}"
+ "yes"))
+ (let ((eshell-test-value nil))
+ (eshell-command-result-equal
+ "unless $eshell-test-value {echo no} {echo yes}"
+ "no")))
+
+(ert-deftest esh-cmd-test/unless-else-statement-lisp-form ()
+ "Test invocation of an unless/else statement using a Lisp form."
+ (eshell-command-result-equal "unless (zerop 0) {echo no} {echo yes}"
+ "yes")
+ (eshell-command-result-equal "unless (zerop 1) {echo no} {echo yes}"
+ "no")
+ (let ((debug-on-error nil))
+ (eshell-command-result-equal "unless (zerop \"foo\") {echo no} {echo yes}"
+ "no")))
+
+(ert-deftest esh-cmd-test/unless-else-statement-ext-cmd ()
+ "Test invocation of an unless/else statement using an external command."
+ (skip-unless (executable-find "["))
+ (eshell-command-result-equal "unless {[ foo = foo ]} {echo no} {echo yes}"
+ "yes")
+ (eshell-command-result-equal "unless {[ foo = bar ]} {echo no} {echo yes}"
+ "no"))
+
+;; esh-cmd-tests.el ends here
diff --git a/test/lisp/eshell/esh-io-tests.el b/test/lisp/eshell/esh-io-tests.el
new file mode 100644
index 00000000000..37b234eaf06
--- /dev/null
+++ b/test/lisp/eshell/esh-io-tests.el
@@ -0,0 +1,292 @@
+;;; esh-io-tests.el --- esh-io test suite -*- lexical-binding:t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'ert-x)
+(require 'esh-mode)
+(require 'eshell)
+
+(require 'eshell-tests-helpers
+ (expand-file-name "eshell-tests-helpers"
+ (file-name-directory (or load-file-name
+ default-directory))))
+
+(defvar eshell-test-value nil)
+
+(defun eshell-test-file-string (file)
+ "Return the contents of FILE as a string."
+ (with-temp-buffer
+ (insert-file-contents file)
+ (buffer-string)))
+
+(defun eshell/test-output ()
+ "Write some test output separately to stdout and stderr."
+ (eshell-printn "stdout")
+ (eshell-errorn "stderr"))
+
+;;; Tests:
+
+
+;; Basic redirection
+
+(ert-deftest esh-io-test/redirect-file/overwrite ()
+ "Check that redirecting to a file in overwrite mode works."
+ (ert-with-temp-file temp-file
+ :text "old"
+ (with-temp-eshell
+ (eshell-insert-command (format "echo new > %s" temp-file)))
+ (should (equal (eshell-test-file-string temp-file) "new"))))
+
+(ert-deftest esh-io-test/redirect-file/append ()
+ "Check that redirecting to a file in append mode works."
+ (ert-with-temp-file temp-file
+ :text "old"
+ (with-temp-eshell
+ (eshell-insert-command (format "echo new >> %s" temp-file)))
+ (should (equal (eshell-test-file-string temp-file) "oldnew"))))
+
+(ert-deftest esh-io-test/redirect-file/insert ()
+ "Check that redirecting to a file in insert works."
+ (ert-with-temp-file temp-file
+ :text "old"
+ (with-temp-eshell
+ (eshell-insert-command (format "echo new >>> %s" temp-file)))
+ (should (equal (eshell-test-file-string temp-file) "newold"))))
+
+(ert-deftest esh-io-test/redirect-buffer/overwrite ()
+ "Check that redirecting to a buffer in overwrite mode works."
+ (eshell-with-temp-buffer bufname "old"
+ (with-temp-eshell
+ (eshell-insert-command (format "echo new > #<%s>" bufname)))
+ (should (equal (buffer-string) "new"))))
+
+(ert-deftest esh-io-test/redirect-buffer/append ()
+ "Check that redirecting to a buffer in append mode works."
+ (eshell-with-temp-buffer bufname "old"
+ (with-temp-eshell
+ (eshell-insert-command (format "echo new >> #<%s>" bufname)))
+ (should (equal (buffer-string) "oldnew"))))
+
+(ert-deftest esh-io-test/redirect-buffer/insert ()
+ "Check that redirecting to a buffer in insert mode works."
+ (eshell-with-temp-buffer bufname "old"
+ (goto-char (point-min))
+ (with-temp-eshell
+ (eshell-insert-command (format "echo new >>> #<%s>" bufname)))
+ (should (equal (buffer-string) "newold"))))
+
+(ert-deftest esh-io-test/redirect-buffer/escaped ()
+ "Check that redirecting to a buffer with escaped characters works."
+ (with-temp-buffer
+ (rename-buffer "eshell\\temp\\buffer" t)
+ (let ((bufname (buffer-name)))
+ (with-temp-eshell
+ (eshell-insert-command (format "echo hi > #<%s>"
+ (string-replace "\\" "\\\\" bufname))))
+ (should (equal (buffer-string) "hi")))))
+
+(ert-deftest esh-io-test/redirect-symbol/overwrite ()
+ "Check that redirecting to a symbol in overwrite mode works."
+ (let ((eshell-test-value "old"))
+ (with-temp-eshell
+ (eshell-insert-command "echo new > #'eshell-test-value"))
+ (should (equal eshell-test-value "new"))))
+
+(ert-deftest esh-io-test/redirect-symbol/append ()
+ "Check that redirecting to a symbol in append mode works."
+ (let ((eshell-test-value "old"))
+ (with-temp-eshell
+ (eshell-insert-command "echo new >> #'eshell-test-value"))
+ (should (equal eshell-test-value "oldnew"))))
+
+(ert-deftest esh-io-test/redirect-marker ()
+ "Check that redirecting to a marker works."
+ (with-temp-buffer
+ (let ((eshell-test-value (point-marker)))
+ (with-temp-eshell
+ (eshell-insert-command "echo hi > $eshell-test-value"))
+ (should (equal (buffer-string) "hi")))))
+
+(ert-deftest esh-io-test/redirect-multiple ()
+ "Check that redirecting to multiple targets works."
+ (let ((eshell-test-value "old"))
+ (eshell-with-temp-buffer bufname "old"
+ (with-temp-eshell
+ (eshell-insert-command (format "echo new > #<%s> > #'eshell-test-value"
+ bufname)))
+ (should (equal (buffer-string) "new"))
+ (should (equal eshell-test-value "new")))))
+
+(ert-deftest esh-io-test/redirect-multiple/repeat ()
+ "Check that redirecting to multiple targets works when repeating a target."
+ (let ((eshell-test-value "old"))
+ (eshell-with-temp-buffer bufname "old"
+ (with-temp-eshell
+ (eshell-insert-command
+ (format "echo new > #<%s> > #'eshell-test-value > #<%s>"
+ bufname bufname)))
+ (should (equal (buffer-string) "new"))
+ (should (equal eshell-test-value "new")))))
+
+
+;; Redirecting specific handles
+
+(ert-deftest esh-io-test/redirect-stdout ()
+ "Check that redirecting to stdout doesn't redirect stderr."
+ (eshell-with-temp-buffer bufname "old"
+ (with-temp-eshell
+ (eshell-match-command-output (format "test-output > #<%s>" bufname)
+ "stderr\n"))
+ (should (equal (buffer-string) "stdout\n")))
+ ;; Also check explicitly specifying the stdout fd.
+ (eshell-with-temp-buffer bufname "old"
+ (with-temp-eshell
+ (eshell-match-command-output (format "test-output 1> #<%s>" bufname)
+ "stderr\n"))
+ (should (equal (buffer-string) "stdout\n"))))
+
+(ert-deftest esh-io-test/redirect-stderr/overwrite ()
+ "Check that redirecting to stderr doesn't redirect stdout."
+ (eshell-with-temp-buffer bufname "old"
+ (with-temp-eshell
+ (eshell-match-command-output (format "test-output 2> #<%s>" bufname)
+ "stdout\n"))
+ (should (equal (buffer-string) "stderr\n"))))
+
+(ert-deftest esh-io-test/redirect-stderr/append ()
+ "Check that redirecting to stderr doesn't redirect stdout."
+ (eshell-with-temp-buffer bufname "old"
+ (with-temp-eshell
+ (eshell-match-command-output (format "test-output 2>> #<%s>" bufname)
+ "stdout\n"))
+ (should (equal (buffer-string) "oldstderr\n"))))
+
+(ert-deftest esh-io-test/redirect-stderr/insert ()
+ "Check that redirecting to stderr doesn't redirect stdout."
+ (eshell-with-temp-buffer bufname "old"
+ (goto-char (point-min))
+ (with-temp-eshell
+ (eshell-match-command-output (format "test-output 2>>> #<%s>" bufname)
+ "stdout\n"))
+ (should (equal (buffer-string) "stderr\nold"))))
+
+(ert-deftest esh-io-test/redirect-stdout-and-stderr ()
+ "Check that redirecting to both stdout and stderr works."
+ (eshell-with-temp-buffer bufname-1 "old"
+ (eshell-with-temp-buffer bufname-2 "old"
+ (with-temp-eshell
+ (eshell-match-command-output (format "test-output > #<%s> 2> #<%s>"
+ bufname-1 bufname-2)
+ "\\`\\'"))
+ (should (equal (buffer-string) "stderr\n")))
+ (should (equal (buffer-string) "stdout\n"))))
+
+(ert-deftest esh-io-test/redirect-all/overwrite ()
+ "Check that redirecting to stdout and stderr via shorthand works."
+ (eshell-with-temp-buffer bufname "old"
+ (with-temp-eshell
+ (eshell-match-command-output (format "test-output &> #<%s>" bufname)
+ "\\`\\'"))
+ (should (equal (buffer-string) "stdout\nstderr\n")))
+ ;; Also check the alternate (and less-preferred in Bash) `>&' syntax.
+ (eshell-with-temp-buffer bufname "old"
+ (with-temp-eshell
+ (eshell-match-command-output (format "test-output >& #<%s>" bufname)
+ "\\`\\'"))
+ (should (equal (buffer-string) "stdout\nstderr\n"))))
+
+(ert-deftest esh-io-test/redirect-all/append ()
+ "Check that redirecting to stdout and stderr via shorthand works."
+ (eshell-with-temp-buffer bufname "old"
+ (with-temp-eshell
+ (eshell-match-command-output (format "test-output &>> #<%s>" bufname)
+ "\\`\\'"))
+ (should (equal (buffer-string) "oldstdout\nstderr\n")))
+ ;; Also check the alternate (and less-preferred in Bash) `>>&' syntax.
+ (eshell-with-temp-buffer bufname "old"
+ (with-temp-eshell
+ (eshell-match-command-output (format "test-output >>& #<%s>" bufname)
+ "\\`\\'"))
+ (should (equal (buffer-string) "oldstdout\nstderr\n"))))
+
+(ert-deftest esh-io-test/redirect-all/insert ()
+ "Check that redirecting to stdout and stderr via shorthand works."
+ (eshell-with-temp-buffer bufname "old"
+ (goto-char (point-min))
+ (with-temp-eshell
+ (eshell-match-command-output (format "test-output &>>> #<%s>" bufname)
+ "\\`\\'"))
+ (should (equal (buffer-string) "stdout\nstderr\nold")))
+ ;; Also check the alternate `>>>&' syntax.
+ (eshell-with-temp-buffer bufname "old"
+ (goto-char (point-min))
+ (with-temp-eshell
+ (eshell-match-command-output (format "test-output >>>& #<%s>" bufname)
+ "\\`\\'"))
+ (should (equal (buffer-string) "stdout\nstderr\nold"))))
+
+(ert-deftest esh-io-test/redirect-copy ()
+ "Check that redirecting stdout and then copying stdout to stderr works.
+This should redirect both stdout and stderr to the same place."
+ (eshell-with-temp-buffer bufname "old"
+ (with-temp-eshell
+ (eshell-match-command-output (format "test-output > #<%s> 2>&1" bufname)
+ "\\`\\'"))
+ (should (equal (buffer-string) "stdout\nstderr\n"))))
+
+(ert-deftest esh-io-test/redirect-copy-first ()
+ "Check that copying stdout to stderr and then redirecting stdout works.
+This should redirect stdout to a buffer, and stderr to where
+stdout originally pointed (the terminal)."
+ (eshell-with-temp-buffer bufname "old"
+ (with-temp-eshell
+ (eshell-match-command-output (format "test-output 2>&1 > #<%s>" bufname)
+ "stderr\n"))
+ (should (equal (buffer-string) "stdout\n"))))
+
+(ert-deftest esh-io-test/redirect-pipe ()
+ "Check that \"redirecting\" to a pipe works."
+ ;; `|' should only redirect stdout.
+ (eshell-command-result-equal "test-output | rev"
+ "stderr\ntuodts\n")
+ ;; `|&' should redirect stdout and stderr.
+ (eshell-command-result-equal "test-output |& rev"
+ "tuodts\nrredts\n"))
+
+
+;; Virtual targets
+
+(ert-deftest esh-io-test/virtual-dev-eshell ()
+ "Check that redirecting to /dev/eshell works."
+ (with-temp-eshell
+ (eshell-match-command-output "echo hi > /dev/eshell" "hi")))
+
+(ert-deftest esh-io-test/virtual-dev-kill ()
+ "Check that redirecting to /dev/kill works."
+ (with-temp-eshell
+ (eshell-insert-command "echo one > /dev/kill")
+ (should (equal (car kill-ring) "one"))
+ (eshell-insert-command "echo two > /dev/kill")
+ (should (equal (car kill-ring) "two"))
+ (eshell-insert-command "echo three >> /dev/kill")
+ (should (equal (car kill-ring) "twothree"))))
+
+;;; esh-io-tests.el ends here
diff --git a/test/lisp/eshell/esh-opt-tests.el b/test/lisp/eshell/esh-opt-tests.el
new file mode 100644
index 00000000000..5b30de414a3
--- /dev/null
+++ b/test/lisp/eshell/esh-opt-tests.el
@@ -0,0 +1,289 @@
+;;; esh-opt-tests.el --- esh-opt test suite -*- lexical-binding:t -*-
+
+;; Copyright (C) 2018-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'esh-opt)
+
+(ert-deftest esh-opt-test/process-args ()
+ "Test behavior of `eshell--process-args'."
+ (should
+ (equal '(t)
+ (eshell--process-args
+ "sudo" '("-a")
+ '((?a "all" nil show-all
+ "do not ignore entries starting with .")))))
+ (should
+ (equal '("root" "world")
+ (eshell--process-args
+ "sudo" '("-u" "root" "world")
+ '((?u "user" t user
+ "execute a command as another USER"))))))
+
+(ert-deftest esh-opt-test/process-args-parse-leading-options-only ()
+ "Test behavior of :parse-leading-options-only in `eshell--process-args'."
+ (should
+ (equal '(nil "emerge" "-uDN" "world")
+ (eshell--process-args
+ "sudo" '("emerge" "-uDN" "world")
+ '((?u "user" t user
+ "execute a command as another USER")
+ :parse-leading-options-only))))
+ (should
+ (equal '("root" "emerge" "-uDN" "world")
+ (eshell--process-args
+ "sudo" '("-u" "root" "emerge" "-uDN" "world")
+ '((?u "user" t user
+ "execute a command as another USER")
+ :parse-leading-options-only))))
+ (should
+ (equal '("DN" "emerge" "world")
+ (eshell--process-args
+ "sudo" '("-u" "root" "emerge" "-uDN" "world")
+ '((?u "user" t user
+ "execute a command as another USER"))))))
+
+(ert-deftest esh-opt-test/process-args-external ()
+ "Test behavior of :external in `eshell--process-args'."
+ (cl-letf (((symbol-function 'eshell-search-path) #'ignore))
+ (should
+ (equal '(nil "/some/path")
+ (eshell--process-args
+ "ls" '("/some/path")
+ '((?a "all" nil show-all
+ "do not ignore entries starting with .")
+ :external "ls")))))
+ (cl-letf (((symbol-function 'eshell-search-path) #'identity))
+ (should
+ (equal '(no-catch eshell-ext-command "ls")
+ (should-error
+ (eshell--process-args
+ "ls" '("-u" "/some/path")
+ '((?a "all" nil show-all
+ "do not ignore entries starting with .")
+ :external "ls"))
+ :type 'no-catch))))
+ (cl-letf (((symbol-function 'eshell-search-path) #'ignore))
+ (should-error
+ (eshell--process-args
+ "ls" '("-u" "/some/path")
+ '((?a "all" nil show-all
+ "do not ignore entries starting with .")
+ :external "ls"))
+ :type 'error)))
+
+(ert-deftest esh-opt-test/eval-using-options-short ()
+ "Test `eshell-eval-using-options' with short options."
+ (eshell-eval-using-options
+ "ls" '("-a" "/some/path")
+ '((?a "all" nil show-all
+ "do not ignore entries starting with ."))
+ (should (eq show-all t))
+ (should (equal args '("/some/path"))))
+ (eshell-eval-using-options
+ "ls" '("/some/path")
+ '((?a "all" nil show-all
+ "do not ignore entries starting with ."))
+ (should (eq show-all nil))
+ (should (equal args '("/some/path")))))
+
+(ert-deftest esh-opt-test/eval-using-options-long ()
+ "Test `eshell-eval-using-options' with long options."
+ (eshell-eval-using-options
+ "ls" '("--all" "/some/path")
+ '((?a "all" nil show-all
+ "do not ignore entries starting with ."))
+ (should (eq show-all t))
+ (should (equal args '("/some/path")))))
+
+(ert-deftest esh-opt-test/eval-using-options-constant ()
+ "Test `eshell-eval-using-options' with options with constant values."
+ (eshell-eval-using-options
+ "ls" '("/some/path" "-h")
+ '((?h "human-readable" 1024 human-readable
+ "print sizes in human readable format"))
+ (should (eql human-readable 1024))
+ (should (equal args '("/some/path"))))
+ (eshell-eval-using-options
+ "ls" '("/some/path" "--human-readable")
+ '((?h "human-readable" 1024 human-readable
+ "print sizes in human readable format"))
+ (should (eql human-readable 1024))
+ (should (equal args '("/some/path"))))
+ (eshell-eval-using-options
+ "ls" '("/some/path")
+ '((?h "human-readable" 1024 human-readable
+ "print sizes in human readable format"))
+ (should (eq human-readable nil))
+ (should (equal args '("/some/path")))))
+
+(ert-deftest esh-opt-test/eval-using-options-user-specified ()
+ "Test `eshell-eval-using-options' with options with user-specified values."
+ (eshell-eval-using-options
+ "ls" '("-I" "*.txt" "/some/path")
+ '((?I "ignore" t ignore-pattern
+ "do not list implied entries matching pattern"))
+ (should (equal ignore-pattern "*.txt"))
+ (should (equal args '("/some/path"))))
+ (eshell-eval-using-options
+ "ls" '("-I*.txt" "/some/path")
+ '((?I "ignore" t ignore-pattern
+ "do not list implied entries matching pattern"))
+ (should (equal ignore-pattern "*.txt"))
+ (should (equal args '("/some/path"))))
+ (eshell-eval-using-options
+ "ls" '("--ignore" "*.txt" "/some/path")
+ '((?I "ignore" t ignore-pattern
+ "do not list implied entries matching pattern"))
+ (should (equal ignore-pattern "*.txt"))
+ (should (equal args '("/some/path"))))
+ (eshell-eval-using-options
+ "ls" '("--ignore=*.txt" "/some/path")
+ '((?I "ignore" t ignore-pattern
+ "do not list implied entries matching pattern"))
+ (should (equal ignore-pattern "*.txt"))
+ (should (equal args '("/some/path")))))
+
+(ert-deftest esh-opt-test/eval-using-options-short-single-token ()
+ "Test `eshell-eval-using-options' with multiple short options in one token."
+ (eshell-eval-using-options
+ "ls" '("-al" "/some/path")
+ '((?a "all" nil show-all
+ "do not ignore entries starting with .")
+ (?l nil long-listing listing-style
+ "use a long listing format"))
+ (should (eq t show-all))
+ (should (eql listing-style 'long-listing))
+ (should (equal args '("/some/path"))))
+ (eshell-eval-using-options
+ "ls" '("-aI*.txt" "/some/path")
+ '((?a "all" nil show-all
+ "do not ignore entries starting with .")
+ (?I "ignore" t ignore-pattern
+ "do not list implied entries matching pattern"))
+ (should (eq t show-all))
+ (should (equal ignore-pattern "*.txt"))
+ (should (equal args '("/some/path")))))
+
+(ert-deftest esh-opt-test/eval-using-options-stdin ()
+ "Test that \"-\" is a positional arg in `eshell-eval-using-options'."
+ (eshell-eval-using-options
+ "cat" '("-")
+ '((?A "show-all" nil show-all
+ "show all characters"))
+ (should (eq show-all nil))
+ (should (equal args '("-"))))
+ (eshell-eval-using-options
+ "cat" '("-A" "-")
+ '((?A "show-all" nil show-all
+ "show all characters"))
+ (should (eq show-all t))
+ (should (equal args '("-"))))
+ (eshell-eval-using-options
+ "cat" '("-" "-A")
+ '((?A "show-all" nil show-all
+ "show all characters"))
+ (should (eq show-all t))
+ (should (equal args '("-")))))
+
+(ert-deftest esh-opt-test/eval-using-options-terminate-options ()
+ "Test that \"--\" terminates options in `eshell-eval-using-options'."
+ (eshell-eval-using-options
+ "ls" '("--" "-a")
+ '((?a "all" nil show-all
+ "do not ignore entries starting with ."))
+ (should (eq show-all nil))
+ (should (equal args '("-a"))))
+ (eshell-eval-using-options
+ "ls" '("--" "--all")
+ '((?a "all" nil show-all
+ "do not ignore entries starting with ."))
+ (should (eq show-all nil))
+ (should (equal args '("--all")))))
+
+(ert-deftest esh-opt-test/eval-using-options-parse-leading-options-only ()
+ "Test :parse-leading-options-only in `eshell-eval-using-options'."
+ (eshell-eval-using-options
+ "sudo" '("-u" "root" "whoami")
+ '((?u "user" t user "execute a command as another USER")
+ :parse-leading-options-only)
+ (should (equal user "root"))
+ (should (equal args '("whoami"))))
+ (eshell-eval-using-options
+ "sudo" '("--user" "root" "whoami")
+ '((?u "user" t user "execute a command as another USER")
+ :parse-leading-options-only)
+ (should (equal user "root"))
+ (should (equal args '("whoami"))))
+ (eshell-eval-using-options
+ "sudo" '("emerge" "-uDN" "world")
+ '((?u "user" t user "execute a command as another USER"))
+ (should (equal user "DN"))
+ (should (equal args '("emerge" "world"))))
+ (eshell-eval-using-options
+ "sudo" '("emerge" "-uDN" "world")
+ '((?u "user" t user "execute a command as another USER")
+ :parse-leading-options-only)
+ (should (eq user nil))
+ (should (equal args '("emerge" "-uDN" "world")))))
+
+(ert-deftest esh-opt-test/eval-using-options-unrecognized ()
+ "Test `eshell-eval-using-options' with unrecognized options."
+ (should-error
+ (eshell-eval-using-options
+ "ls" '("-u" "/some/path")
+ '((?a "all" nil _show-all
+ "do not ignore entries starting with ."))))
+ (should-error
+ (eshell-eval-using-options
+ "ls" '("-au" "/some/path")
+ '((?a "all" nil _show-all
+ "do not ignore entries starting with ."))))
+ (should-error
+ (eshell-eval-using-options
+ "ls" '("--unrecognized" "/some/path")
+ '((?a "all" nil _show-all
+ "do not ignore entries starting with .")))))
+
+(ert-deftest esh-opt-test/eval-using-options-external ()
+ "Test :external in `eshell-eval-using-options'."
+ (cl-letf (((symbol-function 'eshell-search-path) #'identity)
+ ((symbol-function 'eshell-external-command) #'list))
+ (should
+ (equal (catch 'eshell-external
+ (eshell-eval-using-options
+ "ls" '("/some/path" "-u")
+ '((?a "all" nil _show-all
+ "do not ignore entries starting with .")
+ :external "ls")))
+ '("ls" ("/some/path" "-u"))))
+ (should
+ (equal (catch 'eshell-external
+ (eshell-eval-using-options
+ "ls" '("/some/path2" "-u")
+ '((?a "all" nil _show-all
+ "do not ignore entries starting with .")
+ :preserve-args
+ :external "ls")))
+ '("ls" ("/some/path2" "-u"))))))
+
+(provide 'esh-opt-tests)
+
+;;; esh-opt-tests.el ends here
diff --git a/test/lisp/eshell/esh-proc-tests.el b/test/lisp/eshell/esh-proc-tests.el
new file mode 100644
index 00000000000..abe363bee0d
--- /dev/null
+++ b/test/lisp/eshell/esh-proc-tests.el
@@ -0,0 +1,249 @@
+;;; esh-proc-tests.el --- esh-proc test suite -*- lexical-binding:t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'esh-mode)
+(require 'eshell)
+
+(require 'eshell-tests-helpers
+ (expand-file-name "eshell-tests-helpers"
+ (file-name-directory (or load-file-name
+ default-directory))))
+
+(defvar esh-proc-test--output-cmd
+ (concat "sh -c '"
+ "echo stdout; "
+ "echo stderr >&2"
+ "'")
+ "A shell command that prints to both stdout and stderr.")
+
+(defvar esh-proc-test--detect-pty-cmd
+ (concat "sh -c '"
+ "if [ -t 0 ]; then echo stdin; fi; "
+ "if [ -t 1 ]; then echo stdout; fi; "
+ "if [ -t 2 ]; then echo stderr; fi"
+ "'")
+ "A shell command that prints the standard streams connected as TTYs.")
+
+;;; Tests:
+
+
+;; Output and redirection
+
+(ert-deftest esh-proc-test/output/to-screen ()
+ "Check that outputting stdout and stderr to the screen works."
+ (skip-unless (executable-find "sh"))
+ (with-temp-eshell
+ (eshell-match-command-output esh-proc-test--output-cmd
+ "stdout\nstderr\n")))
+
+(ert-deftest esh-proc-test/output/stdout-to-buffer ()
+ "Check that redirecting only stdout works."
+ (skip-unless (executable-find "sh"))
+ (eshell-with-temp-buffer bufname "old"
+ (with-temp-eshell
+ (eshell-match-command-output
+ (format "%s > #<%s>" esh-proc-test--output-cmd bufname)
+ "stderr\n"))
+ (should (equal (buffer-string) "stdout\n"))))
+
+(ert-deftest esh-proc-test/output/stderr-to-buffer ()
+ "Check that redirecting only stderr works."
+ (skip-unless (executable-find "sh"))
+ (eshell-with-temp-buffer bufname "old"
+ (with-temp-eshell
+ (eshell-match-command-output
+ (format "%s 2> #<%s>" esh-proc-test--output-cmd bufname)
+ "stdout\n"))
+ (should (equal (buffer-string) "stderr\n"))))
+
+(ert-deftest esh-proc-test/output/stdout-and-stderr-to-buffer ()
+ "Check that redirecting stdout and stderr works."
+ (skip-unless (executable-find "sh"))
+ (eshell-with-temp-buffer bufname "old"
+ (with-temp-eshell
+ (eshell-match-command-output
+ (format "%s &> #<%s>" esh-proc-test--output-cmd bufname)
+ "\\`\\'"))
+ (should (equal (buffer-string) "stdout\nstderr\n"))))
+
+
+;; Exit status
+
+(ert-deftest esh-proc-test/exit-status/success ()
+ "Check that successful execution is properly recorded."
+ (skip-unless (executable-find "sh"))
+ (with-temp-eshell
+ (eshell-insert-command "sh -c 'exit 0'")
+ (eshell-wait-for-subprocess)
+ (should (= eshell-last-command-status 0))
+ (should (eq eshell-last-command-result t))))
+
+(ert-deftest esh-proc-test/exit-status/failure ()
+ "Check that failed execution is properly recorded."
+ (skip-unless (executable-find "sh"))
+ (with-temp-eshell
+ (eshell-insert-command "sh -c 'exit 1'")
+ (eshell-wait-for-subprocess)
+ (should (= eshell-last-command-status 1))
+ (should (eq eshell-last-command-result nil))))
+
+(ert-deftest esh-proc-test/exit-status/with-stderr-pipe ()
+ "Check that failed execution is properly recorded even with a pipe process."
+ (skip-unless (executable-find "sh"))
+ (eshell-with-temp-buffer bufname "old"
+ (with-temp-eshell
+ (eshell-insert-command (format "sh -c 'exit 1' > #<%s>" bufname))
+ (eshell-wait-for-subprocess)
+ (should (= eshell-last-command-status 1))
+ (should (eq eshell-last-command-result nil)))))
+
+
+;; Pipelines
+
+(ert-deftest esh-proc-test/sigpipe-exits-process ()
+ "Test that a SIGPIPE is properly sent to a process if a pipe closes"
+ (skip-unless (and (executable-find "sh")
+ (executable-find "echo")
+ (executable-find "sleep")))
+ (with-temp-eshell
+ (eshell-match-command-output
+ ;; The first command is like `yes' but slower. This is to prevent
+ ;; it from taxing Emacs's process filter too much and causing a
+ ;; hang. Note that we use "|&" to connect the processes so that
+ ;; Emacs doesn't create an extra pipe process for the first "sh"
+ ;; invocation.
+ (concat "sh -c 'while true; do echo y; sleep 1; done' |& "
+ "sh -c 'read NAME; echo ${NAME}'")
+ "y\n")
+ (eshell-wait-for-subprocess t)
+ (should (eq (process-list) nil))))
+
+(ert-deftest esh-proc-test/pipeline-connection-type/no-pipeline ()
+ "Test that all streams are PTYs when a command is not in a pipeline."
+ (skip-unless (executable-find "sh"))
+ (eshell-command-result-equal
+ esh-proc-test--detect-pty-cmd
+ ;; PTYs aren't supported on MS-Windows.
+ (unless (eq system-type 'windows-nt)
+ "stdin\nstdout\nstderr\n")))
+
+(ert-deftest esh-proc-test/pipeline-connection-type/first ()
+ "Test that only stdin is a PTY when a command starts a pipeline."
+ (skip-unless (and (executable-find "sh")
+ (executable-find "cat")))
+ (eshell-command-result-equal
+ (concat esh-proc-test--detect-pty-cmd " | cat")
+ (unless (eq system-type 'windows-nt)
+ "stdin\n")))
+
+(ert-deftest esh-proc-test/pipeline-connection-type/middle ()
+ "Test that all streams are pipes when a command is in the middle of a
+pipeline."
+ (skip-unless (and (executable-find "sh")
+ (executable-find "cat")))
+ ;; An `eshell-pipe-broken' signal might occur internally; let Eshell
+ ;; handle it!
+ (let ((debug-on-error nil))
+ (eshell-command-result-equal
+ (concat "echo hi | " esh-proc-test--detect-pty-cmd " | cat")
+ nil)))
+
+(ert-deftest esh-proc-test/pipeline-connection-type/last ()
+ "Test that only output streams are PTYs when a command ends a pipeline."
+ (skip-unless (executable-find "sh"))
+ ;; An `eshell-pipe-broken' signal might occur internally; let Eshell
+ ;; handle it!
+ (let ((debug-on-error nil))
+ (eshell-command-result-equal
+ (concat "echo hi | " esh-proc-test--detect-pty-cmd)
+ (unless (eq system-type 'windows-nt)
+ "stdout\nstderr\n"))))
+
+
+;; Killing processes
+
+(ert-deftest esh-proc-test/kill-process/foreground-only ()
+ "Test that `eshell-kill-process' only kills foreground processes."
+ (with-temp-eshell
+ (eshell-insert-command "sleep 100 &")
+ (eshell-insert-command "sleep 100")
+ (should (equal (length eshell-process-list) 2))
+ ;; This should kill only the foreground process.
+ (eshell-kill-process)
+ (eshell-wait-for-subprocess)
+ (should (equal (length eshell-process-list) 1))
+ ;; Now kill everything, including the background process.
+ (eshell-process-interact 'kill-process t)
+ (eshell-wait-for-subprocess t)
+ (should (equal (length eshell-process-list) 0))))
+
+(ert-deftest esh-proc-test/kill-process/background-prompt ()
+ "Test that killing a background process doesn't emit a new
+prompt. See bug#54136."
+ (skip-unless (and (executable-find "sh")
+ (executable-find "sleep")))
+ (with-temp-eshell
+ (eshell-insert-command "sh -c 'while true; do sleep 1; done' &")
+ (kill-process (caar eshell-process-list))
+ (eshell-wait-for-subprocess)
+ (should (eshell-match-output "\\[sh\\(\\.exe\\)?\\] [[:digit:]]+\n"))))
+
+(ert-deftest esh-proc-test/kill-pipeline ()
+ "Test that killing a pipeline of processes only emits a single
+prompt. See bug#54136."
+ (skip-unless (and (executable-find "sh")
+ (executable-find "echo")
+ (executable-find "sleep")))
+ ;; This test doesn't work on EMBA with AOT nativecomp, but works
+ ;; fine elsewhere.
+ (skip-unless (not (getenv "EMACS_EMBA_CI")))
+ (with-temp-eshell
+ (eshell-insert-command
+ (concat "sh -c 'while true; do echo y; sleep 1; done' | "
+ "sh -c 'while true; do read NAME; done'"))
+ (let ((output-start (eshell-beginning-of-output)))
+ (eshell-kill-process)
+ (eshell-wait-for-subprocess t)
+ (should (string-match-p
+ ;; "interrupt\n" is for MS-Windows.
+ (rx (or "interrupt\n" "killed\n" "killed: 9\n"))
+ (buffer-substring-no-properties
+ output-start (eshell-end-of-output)))))))
+
+(ert-deftest esh-proc-test/kill-pipeline-head ()
+ "Test that killing the first process in a pipeline doesn't
+write the exit status to the pipe. See bug#54136."
+ (skip-unless (and (executable-find "sh")
+ (executable-find "echo")
+ (executable-find "sleep")))
+ (with-temp-eshell
+ (eshell-insert-command
+ (concat "sh -c 'while true; do sleep 1; done' | "
+ "sh -c 'while read NAME; do echo =${NAME}=; done'"))
+ (let ((output-start (eshell-beginning-of-output)))
+ (kill-process (eshell-head-process))
+ (eshell-wait-for-subprocess t)
+ (should (equal (buffer-substring-no-properties
+ output-start (eshell-end-of-output))
+ "")))))
+
+;;; esh-proc-tests.el ends here
diff --git a/test/lisp/eshell/esh-var-tests.el b/test/lisp/eshell/esh-var-tests.el
new file mode 100644
index 00000000000..cb5b1766bb5
--- /dev/null
+++ b/test/lisp/eshell/esh-var-tests.el
@@ -0,0 +1,569 @@
+;;; esh-var-tests.el --- esh-var test suite -*- lexical-binding:t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Tests for Eshell's variable handling.
+
+;;; Code:
+
+(require 'ert)
+(require 'esh-mode)
+(require 'eshell)
+
+(require 'eshell-tests-helpers
+ (expand-file-name "eshell-tests-helpers"
+ (file-name-directory (or load-file-name
+ default-directory))))
+
+(defvar eshell-test-value nil)
+
+;;; Tests:
+
+
+;; Variable interpolation
+
+(ert-deftest esh-var-test/interp-var ()
+ "Interpolate variable"
+ (eshell-command-result-equal "echo $user-login-name"
+ user-login-name))
+
+(ert-deftest esh-var-test/interp-quoted-var ()
+ "Interpolate quoted variable"
+ (eshell-command-result-equal "echo $'user-login-name'"
+ user-login-name)
+ (eshell-command-result-equal "echo $\"user-login-name\""
+ user-login-name))
+
+(ert-deftest esh-var-test/interp-quoted-var-concat ()
+ "Interpolate and concat quoted variable"
+ (eshell-command-result-equal "echo $'user-login-name'-foo"
+ (concat user-login-name "-foo"))
+ (eshell-command-result-equal "echo $\"user-login-name\"-foo"
+ (concat user-login-name "-foo")))
+
+(ert-deftest esh-var-test/interp-var-indices ()
+ "Interpolate list variable with indices"
+ (let ((eshell-test-value '("zero" "one" "two" "three" "four")))
+ (eshell-command-result-equal "echo $eshell-test-value[0]"
+ "zero")
+ (eshell-command-result-equal "echo $eshell-test-value[0 2]"
+ '("zero" "two"))
+ (eshell-command-result-equal "echo $eshell-test-value[0 2 4]"
+ '("zero" "two" "four"))))
+
+(ert-deftest esh-var-test/interp-var-split-indices ()
+ "Interpolate string variable with indices"
+ (let ((eshell-test-value "zero one two three four"))
+ (eshell-command-result-equal "echo $eshell-test-value[0]"
+ "zero")
+ (eshell-command-result-equal "echo $eshell-test-value[0 2]"
+ '("zero" "two"))
+ (eshell-command-result-equal "echo $eshell-test-value[0 2 4]"
+ '("zero" "two" "four"))))
+
+(ert-deftest esh-var-test/interp-var-string-split-indices ()
+ "Interpolate string variable with string splitter and indices"
+ (let ((eshell-test-value "zero:one:two:three:four"))
+ (eshell-command-result-equal "echo $eshell-test-value[: 0]"
+ "zero")
+ (eshell-command-result-equal "echo $eshell-test-value[: 0 2]"
+ '("zero" "two")))
+ (let ((eshell-test-value "zeroXoneXtwoXthreeXfour"))
+ (eshell-command-result-equal "echo $eshell-test-value[X 0]"
+ "zero")
+ (eshell-command-result-equal "echo $eshell-test-value[X 0 2]"
+ '("zero" "two"))))
+
+(ert-deftest esh-var-test/interp-var-regexp-split-indices ()
+ "Interpolate string variable with regexp splitter and indices"
+ (let ((eshell-test-value "zero:one!two:three!four"))
+ (eshell-command-result-equal "echo $eshell-test-value['[:!]' 0]"
+ "zero")
+ (eshell-command-result-equal "echo $eshell-test-value['[:!]' 0 2]"
+ '("zero" "two"))
+ (eshell-command-result-equal "echo $eshell-test-value[\"[:!]\" 0]"
+ "zero")
+ (eshell-command-result-equal "echo $eshell-test-value[\"[:!]\" 0 2]"
+ '("zero" "two"))))
+
+(ert-deftest esh-var-test/interp-var-assoc ()
+ "Interpolate alist variable with index"
+ (let ((eshell-test-value '(("foo" . 1) (bar . 2))))
+ (eshell-command-result-equal "echo $eshell-test-value[foo]"
+ 1)
+ (eshell-command-result-equal "echo $eshell-test-value[#'bar]"
+ 2)))
+
+(ert-deftest esh-var-test/interp-var-length-list ()
+ "Interpolate length of list variable"
+ (let ((eshell-test-value '((1 2) (3) (5 (6 7 8 9)))))
+ (eshell-command-result-equal "echo $#eshell-test-value" 3)
+ (eshell-command-result-equal "echo $#eshell-test-value[1]" 1)
+ (eshell-command-result-equal "echo $#eshell-test-value[2][1]" 4)))
+
+(ert-deftest esh-var-test/interp-var-length-string ()
+ "Interpolate length of string variable"
+ (let ((eshell-test-value "foobar"))
+ (eshell-command-result-equal "echo $#eshell-test-value" 6)))
+
+(ert-deftest esh-var-test/interp-var-length-alist ()
+ "Interpolate length of alist variable"
+ (let ((eshell-test-value '(("foo" . (1 2 3)))))
+ (eshell-command-result-equal "echo $#eshell-test-value" 1)
+ (eshell-command-result-equal "echo $#eshell-test-value[foo]" 3)))
+
+(ert-deftest esh-var-test/interp-lisp ()
+ "Interpolate Lisp form evaluation"
+ (eshell-command-result-equal "+ $(+ 1 2) 3" 6))
+
+(ert-deftest esh-var-test/interp-lisp-indices ()
+ "Interpolate Lisp form evaluation with index"
+ (eshell-command-result-equal "+ $(list 1 2)[1] 3" 5))
+
+(ert-deftest esh-var-test/interp-cmd ()
+ "Interpolate command result"
+ (eshell-command-result-equal "+ ${+ 1 2} 3" 6))
+
+(ert-deftest esh-var-test/interp-cmd-indices ()
+ "Interpolate command result with index"
+ (eshell-command-result-equal "+ ${listify 1 2}[1] 3" 5))
+
+(ert-deftest esh-var-test/interp-cmd-external ()
+ "Interpolate command result from external command"
+ (skip-unless (executable-find "echo"))
+ (with-temp-eshell
+ (eshell-match-command-output "echo ${*echo hi}"
+ "hi\n")))
+
+(ert-deftest esh-var-test/interp-cmd-external-indices ()
+ "Interpolate command result from external command with index"
+ (skip-unless (executable-find "echo"))
+ (with-temp-eshell
+ (eshell-match-command-output "echo ${*echo \"hi\nbye\"}[1]"
+ "bye\n")))
+
+(ert-deftest esh-var-test/interp-temp-cmd ()
+ "Interpolate command result redirected to temp file"
+ (eshell-command-result-equal "cat $<echo hi>" "hi"))
+
+(ert-deftest esh-var-test/interp-concat-lisp ()
+ "Interpolate and concat Lisp form"
+ (eshell-command-result-equal "+ $(+ 1 2)3 3" 36))
+
+(ert-deftest esh-var-test/interp-concat-lisp2 ()
+ "Interpolate and concat two Lisp forms"
+ (eshell-command-result-equal "+ $(+ 1 2)$(+ 1 2) 3" 36))
+
+(ert-deftest esh-var-test/interp-concat-cmd ()
+ "Interpolate and concat command with literal"
+ (eshell-command-result-equal "+ ${+ 1 2}3 3" 36)
+ (eshell-command-result-equal "echo ${*echo \"foo\nbar\"}-baz"
+ '("foo" "bar-baz"))
+ ;; Concatenating to a number in a list should produce a number...
+ (eshell-command-result-equal "echo ${*echo \"1\n2\"}3"
+ '(1 23))
+ ;; ... but concatenating to a string that looks like a number in a list
+ ;; should produce a string.
+ (eshell-command-result-equal "echo ${*echo \"hi\n2\"}3"
+ '("hi" "23")))
+
+(ert-deftest esh-var-test/interp-concat-cmd2 ()
+ "Interpolate and concat two commands"
+ (eshell-command-result-equal "+ ${+ 1 2}${+ 1 2} 3" 36))
+
+(ert-deftest esh-var-test/interp-concat-cmd-external ()
+ "Interpolate command result from external command with concatenation"
+ (skip-unless (executable-find "echo"))
+ (with-temp-eshell
+ (eshell-match-command-output "echo ${echo hi}-${*echo there}"
+ "hi-there\n")))
+
+(ert-deftest esh-var-test/quoted-interp-var ()
+ "Interpolate variable inside double-quotes"
+ (eshell-command-result-equal "echo \"$user-login-name\""
+ user-login-name))
+
+(ert-deftest esh-var-test/quoted-interp-quoted-var ()
+ "Interpolate quoted variable inside double-quotes"
+ (eshell-command-result-equal "echo \"hi, $'user-login-name'\""
+ (concat "hi, " user-login-name))
+ (eshell-command-result-equal "echo \"hi, $\\\"user-login-name\\\"\""
+ (concat "hi, " user-login-name)))
+
+(ert-deftest esh-var-test/quoted-interp-var-indices ()
+ "Interpolate string variable with indices inside double-quotes"
+ (let ((eshell-test-value '("zero" "one" "two" "three" "four")))
+ (eshell-command-result-equal "echo \"$eshell-test-value[0]\""
+ "zero")
+ ;; FIXME: These tests would use the 0th index like the other tests
+ ;; here, but evaluating the command just above adds an `escaped'
+ ;; property to the string "zero". This results in the output
+ ;; printing the string properties, which is probably the wrong
+ ;; behavior. See bug#54486.
+ (eshell-command-result-equal "echo \"$eshell-test-value[1 2]\""
+ "(\"one\" \"two\")")
+ (eshell-command-result-equal "echo \"$eshell-test-value[1 2 4]\""
+ "(\"one\" \"two\" \"four\")")))
+
+(ert-deftest esh-var-test/quoted-interp-var-split-indices ()
+ "Interpolate string variable with indices inside double-quotes"
+ (let ((eshell-test-value "zero one two three four"))
+ (eshell-command-result-equal "echo \"$eshell-test-value[0]\""
+ "zero")
+ (eshell-command-result-equal "echo \"$eshell-test-value[0 2]\""
+ "(\"zero\" \"two\")")))
+
+(ert-deftest esh-var-test/quoted-interp-var-string-split-indices ()
+ "Interpolate string variable with string splitter and indices
+inside double-quotes"
+ (let ((eshell-test-value "zero:one:two:three:four"))
+ (eshell-command-result-equal "echo \"$eshell-test-value[: 0]\""
+ "zero")
+ (eshell-command-result-equal "echo \"$eshell-test-value[: 0 2]\""
+ "(\"zero\" \"two\")"))
+ (let ((eshell-test-value "zeroXoneXtwoXthreeXfour"))
+ (eshell-command-result-equal "echo \"$eshell-test-value[X 0]\""
+ "zero")
+ (eshell-command-result-equal "echo \"$eshell-test-value[X 0 2]\""
+ "(\"zero\" \"two\")")))
+
+(ert-deftest esh-var-test/quoted-interp-var-regexp-split-indices ()
+ "Interpolate string variable with regexp splitter and indices"
+ (let ((eshell-test-value "zero:one!two:three!four"))
+ (eshell-command-result-equal "echo \"$eshell-test-value['[:!]' 0]\""
+ "zero")
+ (eshell-command-result-equal "echo \"$eshell-test-value['[:!]' 0 2]\""
+ "(\"zero\" \"two\")")
+ (eshell-command-result-equal "echo \"$eshell-test-value[\\\"[:!]\\\" 0]\""
+ "zero")
+ (eshell-command-result-equal
+ "echo \"$eshell-test-value[\\\"[:!]\\\" 0 2]\""
+ "(\"zero\" \"two\")")))
+
+(ert-deftest esh-var-test/quoted-interp-var-assoc ()
+ "Interpolate alist variable with index inside double-quotes"
+ (let ((eshell-test-value '(("foo" . 1) (bar . 2))))
+ (eshell-command-result-equal "echo \"$eshell-test-value[foo]\""
+ "1")
+ (eshell-command-result-equal "echo \"$eshell-test-value[#'bar]\""
+ "2")))
+
+(ert-deftest esh-var-test/quoted-interp-var-length-list ()
+ "Interpolate length of list variable inside double-quotes"
+ (let ((eshell-test-value '((1 2) (3) (5 (6 7 8 9)))))
+ (eshell-command-result-equal "echo \"$#eshell-test-value\""
+ "3")
+ (eshell-command-result-equal "echo \"$#eshell-test-value[1]\""
+ "1")
+ (eshell-command-result-equal "echo \"$#eshell-test-value[2][1]\""
+ "4")))
+
+(ert-deftest esh-var-test/quoted-interp-var-length-string ()
+ "Interpolate length of string variable inside double-quotes"
+ (let ((eshell-test-value "foobar"))
+ (eshell-command-result-equal "echo \"$#eshell-test-value\""
+ "6")))
+
+(ert-deftest esh-var-test/quoted-interp-var-length-alist ()
+ "Interpolate length of alist variable inside double-quotes"
+ (let ((eshell-test-value '(("foo" . (1 2 3)))))
+ (eshell-command-result-equal "echo \"$#eshell-test-value\""
+ "1")
+ (eshell-command-result-equal "echo \"$#eshell-test-value[foo]\""
+ "3"))
+
+(ert-deftest esh-var-test/quoted-interp-lisp ()
+ "Interpolate Lisp form evaluation inside double-quotes"
+ (eshell-command-result-equal "echo \"hi $(concat \\\"the\\\" \\\"re\\\")\""
+ "hi there"))
+
+(ert-deftest esh-var-test/quoted-interp-lisp-indices ()
+ "Interpolate Lisp form evaluation with index"
+ (eshell-command-result-equal "concat \"$(list 1 2)[1]\" cool"
+ "2cool"))
+
+(ert-deftest esh-var-test/quoted-interp-cmd ()
+ "Interpolate command result inside double-quotes"
+ (eshell-command-result-equal "echo \"hi ${echo \\\"there\\\"}\""
+ "hi there"))
+
+(ert-deftest esh-var-test/quoted-interp-cmd-indices ()
+ "Interpolate command result with index inside double-quotes"
+ (eshell-command-result-equal "concat \"${listify 1 2}[1]\" cool"
+ "2cool"))
+
+(ert-deftest esh-var-test/quoted-interp-temp-cmd ()
+ "Interpolate command result redirected to temp file inside double-quotes"
+ (let ((temporary-file-directory
+ (file-name-as-directory (make-temp-file "esh-vars-tests" t))))
+ (unwind-protect
+ (eshell-command-result-equal "cat \"$<echo hi>\"" "hi"))
+ (delete-directory temporary-file-directory t))))
+
+(ert-deftest esh-var-test/quoted-interp-concat-cmd ()
+ "Interpolate and concat command with literal"
+ (eshell-command-result-equal "echo \"${echo \\\"foo\nbar\\\"} baz\""
+ "foo\nbar baz"))
+
+
+;; Interpolated variable conversion
+
+(ert-deftest esh-var-test/interp-convert-var-number ()
+ "Interpolate numeric variable"
+ (let ((eshell-test-value 123))
+ (eshell-command-result-equal "type-of $eshell-test-value"
+ 'integer)))
+
+(ert-deftest esh-var-test/interp-convert-var-split-indices ()
+ "Interpolate and convert string variable with indices"
+ ;; Check that numeric forms are converted to numbers.
+ (let ((eshell-test-value "000 010 020 030 040"))
+ (eshell-command-result-equal "echo $eshell-test-value[0]"
+ 0)
+ (eshell-command-result-equal "echo $eshell-test-value[0 2]"
+ '(0 20)))
+ ;; Check that multiline forms are preserved as-is.
+ (let ((eshell-test-value "foo\nbar:baz\n"))
+ (eshell-command-result-equal "echo $eshell-test-value[: 0]"
+ "foo\nbar")
+ (eshell-command-result-equal "echo $eshell-test-value[: 1]"
+ "baz\n")))
+
+(ert-deftest esh-var-test/interp-convert-quoted-var-number ()
+ "Interpolate numeric quoted numeric variable"
+ (let ((eshell-test-value 123))
+ (eshell-command-result-equal "type-of $'eshell-test-value'"
+ 'integer)
+ (eshell-command-result-equal "type-of $\"eshell-test-value\""
+ 'integer)))
+
+(ert-deftest esh-var-test/interp-convert-quoted-var-split-indices ()
+ "Interpolate and convert quoted string variable with indices"
+ (let ((eshell-test-value "000 010 020 030 040"))
+ (eshell-command-result-equal "echo $'eshell-test-value'[0]"
+ 0)
+ (eshell-command-result-equal "echo $'eshell-test-value'[0 2]"
+ '(0 20))))
+
+(ert-deftest esh-var-test/interp-convert-cmd-string-newline ()
+ "Interpolate trailing-newline command result"
+ (eshell-command-result-equal "echo ${echo \"foo\n\"}" "foo"))
+
+(ert-deftest esh-var-test/interp-convert-cmd-multiline ()
+ "Interpolate multi-line command result"
+ (eshell-command-result-equal "echo ${echo \"foo\nbar\"}"
+ '("foo" "bar"))
+ ;; Numeric output should be converted to numbers...
+ (eshell-command-result-equal "echo ${echo \"01\n02\n03\"}"
+ '(1 2 3))
+ ;; ... but only if every line is numeric.
+ (eshell-command-result-equal "echo ${echo \"01\n02\nhi\"}"
+ '("01" "02" "hi")))
+
+(ert-deftest esh-var-test/interp-convert-cmd-number ()
+ "Interpolate numeric command result"
+ (eshell-command-result-equal "echo ${echo \"1\"}" 1))
+
+(ert-deftest esh-var-test/interp-convert-cmd-split-indices ()
+ "Interpolate command result with indices"
+ (eshell-command-result-equal "echo ${echo \"000 010 020\"}[0]"
+ 0)
+ (eshell-command-result-equal "echo ${echo \"000 010 020\"}[0 2]"
+ '(0 20)))
+
+(ert-deftest esh-var-test/quoted-interp-convert-var-number ()
+ "Interpolate numeric variable inside double-quotes"
+ (let ((eshell-test-value 123))
+ (eshell-command-result-equal "type-of \"$eshell-test-value\""
+ 'string)))
+
+(ert-deftest esh-var-test/quoted-interp-convert-var-split-indices ()
+ "Interpolate string variable with indices inside double-quotes"
+ (let ((eshell-test-value "000 010 020 030 040"))
+ (eshell-command-result-equal "echo \"$eshell-test-value[0]\""
+ "000")
+ (eshell-command-result-equal "echo \"$eshell-test-value[0 2]\""
+ "(\"000\" \"020\")")))
+
+(ert-deftest esh-var-test/quoted-interp-convert-quoted-var-number ()
+ "Interpolate numeric quoted variable inside double-quotes"
+ (let ((eshell-test-value 123))
+ (eshell-command-result-equal "type-of \"$'eshell-test-value'\""
+ 'string)
+ (eshell-command-result-equal "type-of \"$\\\"eshell-test-value\\\"\""
+ 'string)))
+
+(ert-deftest esh-var-test/quoted-interp-convert-quoted-var-split-indices ()
+ "Interpolate quoted string variable with indices inside double-quotes"
+ (let ((eshell-test-value "000 010 020 030 040"))
+ (eshell-command-result-equal "echo \"$eshell-test-value[0]\""
+ "000")
+ (eshell-command-result-equal "echo \"$eshell-test-value[0 2]\""
+ "(\"000\" \"020\")")))
+
+(ert-deftest esh-var-test/quoted-interp-convert-cmd-string-newline ()
+ "Interpolate trailing-newline command result inside double-quotes"
+ (eshell-command-result-equal "echo \"${echo \\\"foo\n\\\"}\""
+ "foo")
+ (eshell-command-result-equal "echo \"${echo \\\"foo\n\n\\\"}\""
+ "foo"))
+
+(ert-deftest esh-var-test/quoted-interp-convert-cmd-multiline ()
+ "Interpolate multi-line command result inside double-quotes"
+ (eshell-command-result-equal "echo \"${echo \\\"foo\nbar\\\"}\""
+ "foo\nbar"))
+
+(ert-deftest esh-var-test/quoted-interp-convert-cmd-number ()
+ "Interpolate numeric command result inside double-quotes"
+ (eshell-command-result-equal "echo \"${echo \\\"1\\\"}\"" "1"))
+
+(ert-deftest esh-var-test/quoted-interp-convert-cmd-split-indices ()
+ "Interpolate command result with indices inside double-quotes"
+ (eshell-command-result-equal "echo \"${echo \\\"000 010 020\\\"}[0]\""
+ "000"))
+
+
+;; Built-in variables
+
+(ert-deftest esh-var-test/lines-var ()
+ "$LINES should equal (window-body-height nil 'remap)"
+ (eshell-command-result-equal "echo $LINES"
+ (window-body-height nil 'remap)))
+
+(ert-deftest esh-var-test/columns-var ()
+ "$COLUMNS should equal (window-body-width nil 'remap)"
+ (eshell-command-result-equal "echo $COLUMNS"
+ (window-body-width nil 'remap)))
+
+(ert-deftest esh-var-test/inside-emacs-var ()
+ "Test presence of \"INSIDE_EMACS\" in subprocesses"
+ (with-temp-eshell
+ (eshell-match-command-output "env"
+ (format "INSIDE_EMACS=%s,eshell"
+ emacs-version))))
+
+(ert-deftest esh-var-test/inside-emacs-var-split-indices ()
+ "Test using \"INSIDE_EMACS\" with split indices"
+ (with-temp-eshell
+ (eshell-match-command-output "echo $INSIDE_EMACS[, 1]"
+ "eshell")))
+
+(ert-deftest esh-var-test/last-status-var-lisp-command ()
+ "Test using the \"last exit status\" ($?) variable with a Lisp command"
+ (with-temp-eshell
+ (eshell-match-command-output "zerop 0; echo $?"
+ "t\n0\n")
+ (eshell-match-command-output "zerop 1; echo $?"
+ "0\n")
+ (let ((debug-on-error nil))
+ (eshell-match-command-output "zerop foo; echo $?"
+ "1\n"))))
+
+(ert-deftest esh-var-test/last-status-var-lisp-form ()
+ "Test using the \"last exit status\" ($?) variable with a Lisp form"
+ (let ((eshell-lisp-form-nil-is-failure t))
+ (with-temp-eshell
+ (eshell-match-command-output "(zerop 0); echo $?"
+ "t\n0\n")
+ (eshell-match-command-output "(zerop 1); echo $?"
+ "2\n")
+ (let ((debug-on-error nil))
+ (eshell-match-command-output "(zerop \"foo\"); echo $?"
+ "1\n")))))
+
+(ert-deftest esh-var-test/last-status-var-lisp-form-2 ()
+ "Test using the \"last exit status\" ($?) variable with a Lisp form.
+This tests when `eshell-lisp-form-nil-is-failure' is nil."
+ (let ((eshell-lisp-form-nil-is-failure nil))
+ (with-temp-eshell
+ (eshell-match-command-output "(zerop 0); echo $?"
+ "0\n")
+ (eshell-match-command-output "(zerop 0); echo $?"
+ "0\n")
+ (let ((debug-on-error nil))
+ (eshell-match-command-output "(zerop \"foo\"); echo $?"
+ "1\n")))))
+
+(ert-deftest esh-var-test/last-status-var-ext-cmd ()
+ "Test using the \"last exit status\" ($?) variable with an external command"
+ (skip-unless (executable-find "["))
+ (with-temp-eshell
+ (eshell-match-command-output "[ foo = foo ]; echo $?"
+ "0\n")
+ (eshell-match-command-output "[ foo = bar ]; echo $?"
+ "1\n")))
+
+(ert-deftest esh-var-test/last-result-var ()
+ "Test using the \"last result\" ($$) variable"
+ (with-temp-eshell
+ (eshell-match-command-output "+ 1 2; + $$ 2"
+ "3\n5\n")))
+
+(ert-deftest esh-var-test/last-result-var-twice ()
+ "Test using the \"last result\" ($$) variable twice"
+ (with-temp-eshell
+ (eshell-match-command-output "+ 1 2; + $$ $$"
+ "3\n6\n")))
+
+(ert-deftest esh-var-test/last-result-var-ext-cmd ()
+ "Test using the \"last result\" ($$) variable with an external command"
+ (skip-unless (executable-find "["))
+ (with-temp-eshell
+ ;; MS-DOS/MS-Windows have an external command 'format', which we
+ ;; don't want here.
+ (let ((eshell-prefer-lisp-functions t))
+ (eshell-match-command-output "[ foo = foo ]; format \"%s\" $$"
+ "t\n")
+ (eshell-match-command-output "[ foo = bar ]; format \"%s\" $$"
+ "nil\n"))))
+
+(ert-deftest esh-var-test/last-result-var-split-indices ()
+ "Test using the \"last result\" ($$) variable with split indices"
+ (with-temp-eshell
+ (eshell-match-command-output
+ "string-join (list \"01\" \"02\") :; + $$[: 1] 3"
+ "01:02\n5\n")
+ (eshell-match-command-output
+ "string-join (list \"01\" \"02\") :; echo \"$$[: 1]\""
+ "01:02\n02\n")))
+
+(ert-deftest esh-var-test/last-arg-var ()
+ "Test using the \"last arg\" ($_) variable"
+ (with-temp-eshell
+ (eshell-match-command-output "+ 1 2; + $_ 4"
+ "3\n6\n")))
+
+(ert-deftest esh-var-test/last-arg-var-indices ()
+ "Test using the \"last arg\" ($_) variable with indices"
+ (with-temp-eshell
+ (eshell-match-command-output "+ 1 2; + $_[0] 4"
+ "3\n5\n")
+ (eshell-match-command-output "+ 1 2; + $_[1] 4"
+ "3\n6\n")))
+
+(ert-deftest esh-var-test/last-arg-var-split-indices ()
+ "Test using the \"last arg\" ($_) variable with split indices"
+ (with-temp-eshell
+ (eshell-match-command-output "concat 01:02 03:04; + $_[0][: 1] 5"
+ "01:0203:04\n7\n")
+ (eshell-match-command-output "concat 01:02 03:04; echo \"$_[0][: 1]\""
+ "01:0203:04\n02\n")))
+
+;; esh-var-tests.el ends here
diff --git a/test/lisp/eshell/eshell-tests-helpers.el b/test/lisp/eshell/eshell-tests-helpers.el
new file mode 100644
index 00000000000..73abfcbb557
--- /dev/null
+++ b/test/lisp/eshell/eshell-tests-helpers.el
@@ -0,0 +1,140 @@
+;;; eshell-tests-helpers.el --- Eshell test suite helpers -*- lexical-binding:t -*-
+
+;; Copyright (C) 1999-2022 Free Software Foundation, Inc.
+
+;; Author: John Wiegley <johnw@gnu.org>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Eshell test suite helpers.
+
+;;; Code:
+
+(require 'ert)
+(require 'ert-x)
+(require 'esh-mode)
+(require 'eshell)
+
+(defvar eshell-history-file-name nil)
+
+(defvar eshell-test--max-subprocess-time 5
+ "The maximum amount of time to wait for a subprocess to finish, in seconds.
+See `eshell-wait-for-subprocess'.")
+
+(defmacro with-temp-eshell (&rest body)
+ "Evaluate BODY in a temporary Eshell buffer."
+ `(save-current-buffer
+ (ert-with-temp-directory eshell-directory-name
+ (let* (;; We want no history file, so prevent Eshell from falling
+ ;; back on $HISTFILE.
+ (process-environment (cons "HISTFILE" process-environment))
+ (eshell-history-file-name nil)
+ (eshell-buffer (eshell t)))
+ (unwind-protect
+ (with-current-buffer eshell-buffer
+ ,@body)
+ (let (kill-buffer-query-functions)
+ (kill-buffer eshell-buffer)))))))
+
+(defmacro eshell-with-temp-buffer (bufname text &rest body)
+ "Create a temporary buffer containing TEXT and evaluate BODY there.
+BUFNAME will be set to the name of the temporary buffer."
+ (declare (indent 2))
+ `(with-temp-buffer
+ (insert ,text)
+ (rename-buffer "eshell-temp-buffer" t)
+ (let ((,bufname (buffer-name)))
+ ,@body)))
+
+(defun eshell-wait-for-subprocess (&optional all)
+ "Wait until there is no interactive subprocess running in Eshell.
+If ALL is non-nil, wait until there are no Eshell subprocesses at
+all running.
+
+If this takes longer than `eshell-test--max-subprocess-time',
+raise an error."
+ (let ((start (current-time)))
+ (while (if all eshell-process-list (eshell-interactive-process-p))
+ (when (> (float-time (time-since start))
+ eshell-test--max-subprocess-time)
+ (error "timed out waiting for subprocess(es)"))
+ (sit-for 0.1))))
+
+(defun eshell-insert-command (command &optional func)
+ "Insert a COMMAND at the end of the buffer.
+After inserting, call FUNC. If FUNC is nil, instead call
+`eshell-send-input'."
+ (goto-char eshell-last-output-end)
+ (insert-and-inherit command)
+ (funcall (or func 'eshell-send-input)))
+
+(defun eshell-match-output (regexp)
+ "Test whether the output of the last command matches REGEXP."
+ (string-match-p
+ regexp (buffer-substring-no-properties
+ (eshell-beginning-of-output) (eshell-end-of-output))))
+
+(defun eshell-match-output--explainer (regexp)
+ "Explain the result of `eshell-match-output'."
+ `(mismatched-output
+ (command ,(buffer-substring-no-properties
+ eshell-last-input-start eshell-last-input-end))
+ (output ,(buffer-substring-no-properties
+ (eshell-beginning-of-output) (eshell-end-of-output)))
+ (regexp ,regexp)))
+
+(put 'eshell-match-output 'ert-explainer #'eshell-match-output--explainer)
+
+(defun eshell-match-command-output (command regexp &optional func)
+ "Insert a COMMAND at the end of the buffer and match the output with REGEXP."
+ (eshell-insert-command command func)
+ (eshell-wait-for-subprocess)
+ (should (eshell-match-output regexp)))
+
+(defvar eshell-history-file-name)
+
+(defun eshell-test-command-result (command)
+ "Like `eshell-command-result', but not using HOME."
+ (ert-with-temp-directory eshell-directory-name
+ (let ((eshell-history-file-name nil))
+ (eshell-command-result command))))
+
+(defun eshell-command-result--equal (_command actual expected)
+ "Compare the ACTUAL result of a COMMAND with its EXPECTED value."
+ (equal actual expected))
+
+(defun eshell-command-result--equal-explainer (command actual expected)
+ "Explain the result of `eshell-command-result--equal'."
+ `(nonequal-result
+ (command ,command)
+ (result ,actual)
+ (expected ,expected)))
+
+(put 'eshell-command-result--equal 'ert-explainer
+ #'eshell-command-result--equal-explainer)
+
+(defun eshell-command-result-equal (command result)
+ "Execute COMMAND non-interactively and compare it to RESULT."
+ (should (eshell-command-result--equal
+ command
+ (eshell-test-command-result command)
+ result)))
+
+(provide 'eshell-tests-helpers)
+
+;;; eshell-tests-helpers.el ends here
diff --git a/test/lisp/eshell/eshell-tests.el b/test/lisp/eshell/eshell-tests.el
index 4e0d6dc7621..d5112146c2d 100644
--- a/test/lisp/eshell/eshell-tests.el
+++ b/test/lisp/eshell/eshell-tests.el
@@ -1,6 +1,6 @@
-;;; tests/eshell-tests.el --- Eshell test suite
+;;; eshell-tests.el --- Eshell test suite -*- lexical-binding:t -*-
-;; Copyright (C) 1999-2017 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2022 Free Software Foundation, Inc.
;; Author: John Wiegley <johnw@gnu.org>
@@ -26,176 +26,115 @@
;;; Code:
(require 'ert)
+(require 'ert-x)
+(require 'esh-mode)
(require 'eshell)
-
-(defmacro with-temp-eshell (&rest body)
- "Evaluate BODY in a temporary Eshell buffer."
- `(let* ((eshell-directory-name (make-temp-file "eshell" t))
- (eshell-history-file-name nil)
- (eshell-buffer (eshell t)))
- (unwind-protect
- (with-current-buffer eshell-buffer
- ,@body)
- (let (kill-buffer-query-functions)
- (kill-buffer eshell-buffer)
- (delete-directory eshell-directory-name t)))))
-
-(defun eshell-insert-command (text &optional func)
- "Insert a command at the end of the buffer."
- (goto-char eshell-last-output-end)
- (insert-and-inherit text)
- (funcall (or func 'eshell-send-input)))
-
-(defun eshell-match-result (regexp)
- "Check that text after `eshell-last-input-end' matches REGEXP."
- (goto-char eshell-last-input-end)
- (should (string-match-p regexp (buffer-substring-no-properties
- (point) (point-max)))))
-
-(defun eshell-command-result-p (text regexp &optional func)
- "Insert a command at the end of the buffer."
- (eshell-insert-command text func)
- (eshell-match-result regexp))
-
-(defun eshell-test-command-result (command)
- "Like `eshell-command-result', but not using HOME."
- (let ((eshell-directory-name (make-temp-file "eshell" t))
- (eshell-history-file-name nil))
- (unwind-protect
- (eshell-command-result command)
- (delete-directory eshell-directory-name t))))
+(require 'eshell-tests-helpers
+ (expand-file-name "eshell-tests-helpers"
+ (file-name-directory (or load-file-name
+ default-directory))))
;;; Tests:
-(ert-deftest eshell-test/simple-command-result ()
- "Test `eshell-command-result' with a simple command."
- (should (equal (eshell-test-command-result "+ 1 2") 3)))
-
-(ert-deftest eshell-test/lisp-command ()
- "Test `eshell-command-result' with an elisp command."
- (should (equal (eshell-test-command-result "(+ 1 2)") 3)))
-
-(ert-deftest eshell-test/for-loop ()
- "Test `eshell-command-result' with a for loop.."
- (let ((process-environment (cons "foo" process-environment)))
- (should (equal (eshell-test-command-result
- "for foo in 5 { echo $foo }") 5))))
-
-(ert-deftest eshell-test/for-name-loop () ;Bug#15231
- "Test `eshell-command-result' with a for loop using `name'."
- (let ((process-environment (cons "name" process-environment)))
- (should (equal (eshell-test-command-result
- "for name in 3 { echo $name }") 3))))
-
-(ert-deftest eshell-test/for-name-shadow-loop () ; bug#15372
- "Test `eshell-command-result' with a for loop using an env-var."
- (let ((process-environment (cons "name=env-value" process-environment)))
- (with-temp-eshell
- (eshell-command-result-p "echo $name; for name in 3 { echo $name }; echo $name"
- "env-value\n3\nenv-value\n"))))
-
-(ert-deftest eshell-test/lisp-command-args ()
- "Test `eshell-command-result' with elisp and trailing args.
-Test that trailing arguments outside the S-expression are
-ignored. e.g. \"(+ 1 2) 3\" => 3"
- (should (equal (eshell-test-command-result "(+ 1 2) 3") 3)))
-
-(ert-deftest eshell-test/subcommand ()
- "Test `eshell-command-result' with a simple subcommand."
- (should (equal (eshell-test-command-result "{+ 1 2}") 3)))
-
-(ert-deftest eshell-test/subcommand-args ()
- "Test `eshell-command-result' with a subcommand and trailing args.
-Test that trailing arguments outside the subcommand are ignored.
-e.g. \"{+ 1 2} 3\" => 3"
- (should (equal (eshell-test-command-result "{+ 1 2} 3") 3)))
-
-(ert-deftest eshell-test/subcommand-lisp ()
- "Test `eshell-command-result' with an elisp subcommand and trailing args.
-Test that trailing arguments outside the subcommand are ignored.
-e.g. \"{(+ 1 2)} 3\" => 3"
- (should (equal (eshell-test-command-result "{(+ 1 2)} 3") 3)))
-
-(ert-deftest eshell-test/interp-cmd ()
- "Interpolate command result"
- (should (equal (eshell-test-command-result "+ ${+ 1 2} 3") 6)))
-
-(ert-deftest eshell-test/interp-lisp ()
- "Interpolate Lisp form evaluation"
- (should (equal (eshell-test-command-result "+ $(+ 1 2) 3") 6)))
-
-(ert-deftest eshell-test/interp-concat ()
- "Interpolate and concat command"
- (should (equal (eshell-test-command-result "+ ${+ 1 2}3 3") 36)))
-
-(ert-deftest eshell-test/interp-concat-lisp ()
- "Interpolate and concat Lisp form"
- (should (equal (eshell-test-command-result "+ $(+ 1 2)3 3") 36)))
-
-(ert-deftest eshell-test/interp-concat2 ()
- "Interpolate and concat two commands"
- (should (equal (eshell-test-command-result "+ ${+ 1 2}${+ 1 2} 3") 36)))
-
-(ert-deftest eshell-test/interp-concat-lisp2 ()
- "Interpolate and concat two Lisp forms"
- (should (equal (eshell-test-command-result "+ $(+ 1 2)$(+ 1 2) 3") 36)))
-
-(ert-deftest eshell-test/window-height ()
- "$LINES should equal (window-height)"
- (should (eshell-test-command-result "= $LINES (window-height)")))
-
-(ert-deftest eshell-test/window-width ()
- "$COLUMNS should equal (window-width)"
- (should (eshell-test-command-result "= $COLUMNS (window-width)")))
-
-(ert-deftest eshell-test/last-result-var ()
- "Test using the \"last result\" ($$) variable"
+(ert-deftest eshell-test/pipe-headproc ()
+ "Check that piping a non-process to a process command waits for the process"
+ (skip-unless (executable-find "cat"))
+ (with-temp-eshell
+ (eshell-match-command-output "echo hi | *cat"
+ "hi")))
+
+(ert-deftest eshell-test/pipe-tailproc ()
+ "Check that piping a process to a non-process command waits for the process"
+ (skip-unless (executable-find "echo"))
(with-temp-eshell
- (eshell-command-result-p "+ 1 2; + $$ 2"
- "3\n5\n")))
+ (eshell-match-command-output "*echo hi | echo bye"
+ "bye\nhi\n")))
-(ert-deftest eshell-test/last-result-var2 ()
- "Test using the \"last result\" ($$) variable twice"
+(ert-deftest eshell-test/pipe-headproc-stdin ()
+ "Check that standard input is sent to the head process in a pipeline"
+ (skip-unless (and (executable-find "tr")
+ (executable-find "rev")))
+ (with-temp-eshell
+ (eshell-insert-command "tr a-z A-Z | rev")
+ (eshell-insert-command "hello")
+ (eshell-send-eof-to-process)
+ (eshell-wait-for-subprocess)
+ (should (eshell-match-output "OLLEH\n"))))
+
+(ert-deftest eshell-test/pipe-subcommand ()
+ "Check that piping with an asynchronous subcommand works"
+ (skip-unless (and (executable-find "echo")
+ (executable-find "cat")))
(with-temp-eshell
- (eshell-command-result-p "+ 1 2; + $$ $$"
- "3\n6\n")))
+ (eshell-match-command-output "echo ${*echo hi} | *cat"
+ "hi")))
-(ert-deftest eshell-test/last-arg-var ()
- "Test using the \"last arg\" ($_) variable"
+(ert-deftest eshell-test/pipe-subcommand-with-pipe ()
+ "Check that piping with an asynchronous subcommand with its own pipe works"
+ (skip-unless (and (executable-find "echo")
+ (executable-find "cat")))
(with-temp-eshell
- (eshell-command-result-p "+ 1 2; + $_ 4"
- "3\n6\n")))
+ (eshell-match-command-output "echo ${*echo hi | *cat} | *cat"
+ "hi")))
+
+(ert-deftest eshell-test/subcommand-reset-in-pipeline ()
+ "Check that subcommands reset `eshell-in-pipeline-p'."
+ (skip-unless (executable-find "cat"))
+ (dolist (template '("echo {%s} | *cat"
+ "echo ${%s} | *cat"
+ "*cat $<%s> | *cat"))
+ (eshell-command-result-equal
+ (format template "echo $eshell-in-pipeline-p")
+ nil)
+ (eshell-command-result-equal
+ (format template "echo | echo $eshell-in-pipeline-p")
+ "last")
+ (eshell-command-result-equal
+ (format template "echo $eshell-in-pipeline-p | echo")
+ "first")
+ (eshell-command-result-equal
+ (format template "echo | echo $eshell-in-pipeline-p | echo")
+ "t")))
+
+(ert-deftest eshell-test/lisp-reset-in-pipeline ()
+ "Check that interpolated Lisp forms reset `eshell-in-pipeline-p'."
+ (skip-unless (executable-find "cat"))
+ (dolist (template '("echo (%s) | *cat"
+ "echo $(%s) | *cat"))
+ (eshell-command-result-equal
+ (format template "format \"%s\" eshell-in-pipeline-p")
+ "nil")))
(ert-deftest eshell-test/escape-nonspecial ()
"Test that \"\\c\" and \"c\" are equivalent when \"c\" is not a
special character."
(with-temp-eshell
- (eshell-command-result-p "echo he\\llo"
- "hello\n")))
+ (eshell-match-command-output "echo he\\llo"
+ "hello\n")))
(ert-deftest eshell-test/escape-nonspecial-unicode ()
"Test that \"\\c\" and \"c\" are equivalent when \"c\" is a
unicode character (unicode characters are nonspecial by
definition)."
(with-temp-eshell
- (eshell-command-result-p "echo Vid\\éos"
- "Vidéos\n")))
+ (eshell-match-command-output "echo Vid\\éos"
+ "Vidéos\n")))
(ert-deftest eshell-test/escape-nonspecial-quoted ()
"Test that the backslash is preserved for escaped nonspecial
chars"
(with-temp-eshell
- (eshell-command-result-p "echo \"h\\i\""
- ;; Backslashes are doubled for regexp.
- "h\\\\i\n")))
+ (eshell-match-command-output "echo \"h\\i\""
+ ;; Backslashes are doubled for regexp.
+ "h\\\\i\n")))
(ert-deftest eshell-test/escape-special-quoted ()
"Test that the backslash is not preserved for escaped special
chars"
(with-temp-eshell
- (eshell-command-result-p "echo \"h\\\\i\""
- ;; Backslashes are doubled for regexp.
- "h\\\\i\n")))
+ (eshell-match-command-output "echo \"\\\"hi\\\\\""
+ ;; Backslashes are doubled for regexp.
+ "\\\"hi\\\\\n")))
(ert-deftest eshell-test/command-running-p ()
"Modeline should show no command running"
@@ -229,16 +168,15 @@ chars"
(> count 0))
(sit-for 1)
(setq count (1- count))))
- (eshell-match-result "alpha\n")))
+ (should (eshell-match-output "alpha\n"))))
(ert-deftest eshell-test/flush-output ()
"Test flushing of previous output"
(with-temp-eshell
(eshell-insert-command "echo alpha")
(eshell-kill-output)
- (eshell-match-result (regexp-quote "*** output flushed ***\n"))
- (should (forward-line))
- (should (= (point) eshell-last-output-start))))
+ (should (eshell-match-output
+ (concat "^" (regexp-quote "*** output flushed ***\n") "$")))))
(ert-deftest eshell-test/run-old-command ()
"Re-run an old command"
@@ -247,6 +185,6 @@ chars"
(goto-char eshell-last-input-start)
(string= (eshell-get-old-input) "echo alpha")))
-(provide 'esh-test)
+(provide 'eshell-tests)
-;;; tests/eshell-tests.el ends here
+;;; eshell-tests.el ends here
diff --git a/test/lisp/faces-resources/faces-test-dark-theme.el b/test/lisp/faces-resources/faces-test-dark-theme.el
new file mode 100644
index 00000000000..37f793a16ef
--- /dev/null
+++ b/test/lisp/faces-resources/faces-test-dark-theme.el
@@ -0,0 +1,35 @@
+;;; faces-test-dark-theme.el --- A dark theme from tests ;;; -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2019-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(deftheme faces-test-dark
+ "Dark test theme.")
+
+(custom-theme-set-faces
+ 'faces-test-dark
+ '(spiff-added ((t (:foreground "Green" :extend t))))
+ '(spiff-changed-face ((t (:foreground "Khaki"))))
+ '(spiff-file-header-face ((t (:background "grey20" :foreground "ivory1")))))
+
+(provide-theme 'faces-test-dark)
+
+;;; faces-test-dark-theme.el ends here
diff --git a/test/lisp/faces-resources/faces-test-light-theme.el b/test/lisp/faces-resources/faces-test-light-theme.el
new file mode 100644
index 00000000000..f89ccf36c5a
--- /dev/null
+++ b/test/lisp/faces-resources/faces-test-light-theme.el
@@ -0,0 +1,34 @@
+;;; faces-test-light-theme.el --- A dark theme from tests ;;; -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2019-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(deftheme faces-test-light
+ "Light test theme.")
+
+(custom-theme-set-faces
+ 'faces-test-light
+ '(spiff-added ((t (:inherit diff-changed :background "light green" :extend t))))
+ '(spiff-changed ((t (:background "light steel blue")))))
+
+(provide-theme 'faces-test-light)
+
+;;; faces-test-light-theme.el ends here
diff --git a/test/lisp/faces-tests.el b/test/lisp/faces-tests.el
index 056af68af91..f28f9e6aed4 100644
--- a/test/lisp/faces-tests.el
+++ b/test/lisp/faces-tests.el
@@ -1,29 +1,31 @@
;;; faces-tests.el --- Tests for faces.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2013-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2022 Free Software Foundation, Inc.
;; Author: Artur Malabarba <bruce.connor.am@gmail.com>
;; Keywords:
-;; This program is free software; you can redistribute it and/or modify
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
-;; This program is distributed in the hope that it will be useful,
+;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
-;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Code:
(require 'ert)
-(require 'faces)
+(require 'ert-x)
-(defgroup faces--test nil ""
+(defgroup faces--test nil "Group to test faces."
:group 'faces--test)
(defface faces--test1
@@ -36,6 +38,26 @@
""
:group 'faces--test)
+(defface faces--test-extend
+ '((t :extend t :background "blue"))
+ ""
+ :group 'faces--test)
+
+(defface faces--test-no-extend
+ '((t :extend nil :background "blue"))
+ ""
+ :group 'faces--test)
+
+(defface faces--test-inherit-extend
+ '((t :inherit (faces--test-extend faces--test2) :background "blue"))
+ ""
+ :group 'faces--test)
+
+(defface faces--test-inherit-no-extend
+ '((t :inherit (faces--test2 faces--test-no-extend) :background "blue"))
+ ""
+ :group 'faces--test)
+
(ert-deftest faces--test-color-at-point ()
(with-temp-buffer
(insert (propertize "STRING" 'face '(faces--test2 faces--test1)))
@@ -60,5 +82,148 @@
(should (equal (background-color-at-point) "black"))
(should (equal (foreground-color-at-point) "black"))))
+(ert-deftest faces--test-face-id ()
+ ;; Face ID of 0 is the 'default' face; no face should have the same ID.
+ (should (> (face-id 'faces--test1) 0))
+ ;; 'tooltip' is the last face defined by preloaded packages, so any
+ ;; face we define in Emacs should have a face ID greater than that,
+ ;; since the ID of a face is just its index in the array that maps
+ ;; face IDs to faces.
+ (should (> (face-id 'faces--test1) (face-id 'tooltip))))
+
+(ert-deftest faces--test-extend ()
+ (should (equal (face-attribute 'faces--test-extend :extend) t))
+ (should (equal (face-attribute 'faces--test-no-extend :extend) nil))
+ (should (equal (face-attribute 'faces--test1 :extend) 'unspecified))
+ (should (equal (face-attribute 'faces--test-inherit-extend :extend)
+ 'unspecified))
+ (should (equal (face-attribute 'faces--test-inherit-extend :extend nil t) t))
+ (should (equal (face-attribute 'faces--test-inherit-no-extend :extend)
+ 'unspecified))
+ (should (equal (face-attribute 'faces--test-inherit-no-extend :extend nil t)
+ nil))
+ )
+
+(ert-deftest faces--test-extend-with-themes ()
+ (defface spiff-changed-face
+ '((t :extend t :weight bold))
+ "")
+ (defface spiff-added
+ '((t :background "grey"))
+ "")
+ (defface spiff-file-header-face
+ '((t :extend nil :foreground "cyan"))
+ "")
+ (should (equal (face-attribute 'spiff-changed-face :extend) t))
+ (should (equal (face-attribute 'spiff-added :extend) 'unspecified))
+ (should (equal (face-attribute 'spiff-file-header-face :extend) nil))
+ (add-to-list 'custom-theme-load-path (ert-resource-directory))
+ (load-theme 'faces-test-dark t t)
+ (load-theme 'faces-test-light t t)
+ (should (equal (face-attribute 'faces--test-inherit-extend :extend)
+ 'unspecified))
+ (should (equal (face-attribute 'faces--test-inherit-extend :extend nil t) t))
+ (should (equal (face-attribute 'faces--test-inherit-no-extend :extend)
+ 'unspecified))
+ (should (equal (face-attribute 'faces--test-inherit-no-extend :extend nil t)
+ nil))
+ (should (equal (face-attribute 'spiff-changed-face :extend) t))
+ (should (equal (face-attribute 'spiff-added :extend) 'unspecified))
+ (should (equal (face-attribute 'spiff-file-header-face :extend) nil))
+ (enable-theme 'faces-test-dark)
+ (should (equal (face-attribute 'faces--test-inherit-extend :extend)
+ 'unspecified))
+ (should (equal (face-attribute 'faces--test-inherit-extend :extend nil t) t))
+ (should (equal (face-attribute 'faces--test-inherit-no-extend :extend)
+ 'unspecified))
+ (should (equal (face-attribute 'faces--test-inherit-no-extend :extend nil t)
+ nil))
+ (should (equal (face-attribute 'spiff-changed-face :extend) t))
+ (should (equal (face-attribute 'spiff-added :extend) t))
+ (should (equal (face-attribute 'spiff-file-header-face :extend) nil))
+ (defface faces--test-face3
+ '((t :inherit spiff-added :weight bold))
+ "")
+ (should (equal (face-attribute 'faces--test-face3 :extend nil t) t))
+ (disable-theme 'faces-test-dark)
+ (should (equal (face-attribute 'faces--test-inherit-extend :extend)
+ 'unspecified))
+ (should (equal (face-attribute 'faces--test-inherit-extend :extend nil t) t))
+ (should (equal (face-attribute 'faces--test-inherit-no-extend :extend)
+ 'unspecified))
+ (should (equal (face-attribute 'faces--test-inherit-no-extend :extend nil t)
+ nil))
+ (should (equal (face-attribute 'spiff-changed-face :extend) t))
+ (should (equal (face-attribute 'spiff-added :extend) 'unspecified))
+ (should (equal (face-attribute 'spiff-file-header-face :extend) nil))
+ (should (equal (face-attribute 'faces--test-face3 :extend nil t) 'unspecified))
+ (defface spiff-indicator-changed
+ '((t (:weight bold :extend t)))
+ "")
+ (enable-theme 'faces-test-light)
+ (should (equal (face-attribute 'faces--test-inherit-extend :extend)
+ 'unspecified))
+ (should (equal (face-attribute 'faces--test-inherit-extend :extend nil t) t))
+ (should (equal (face-attribute 'faces--test-inherit-no-extend :extend)
+ 'unspecified))
+ (should (equal (face-attribute 'faces--test-inherit-no-extend :extend nil t)
+ nil))
+ (should (equal (face-attribute 'spiff-changed-face :extend) t))
+ (should (equal (face-attribute 'spiff-added :extend) t))
+ (should (equal (face-attribute 'spiff-file-header-face :extend) nil))
+ (should (equal (face-attribute 'spiff-indicator-changed :extend) t))
+ (should (equal (face-attribute 'faces--test-face3 :extend nil t) t))
+ (frame-set-background-mode (selected-frame) 'dark)
+ (should (equal (face-attribute 'faces--test-inherit-extend :extend)
+ 'unspecified))
+ (should (equal (face-attribute 'faces--test-inherit-extend :extend nil t) t))
+ (should (equal (face-attribute 'faces--test-inherit-no-extend :extend)
+ 'unspecified))
+ (should (equal (face-attribute 'faces--test-inherit-no-extend :extend nil t)
+ nil))
+ (should (equal (face-attribute 'spiff-changed-face :extend) t))
+ (should (equal (face-attribute 'spiff-added :extend) t))
+ (should (equal (face-attribute 'spiff-file-header-face :extend) nil))
+ (should (equal (face-attribute 'spiff-indicator-changed :extend) t))
+ (should (equal (face-attribute 'faces--test-face3 :extend nil t) t))
+ (or noninteractive
+ (let ((fr (make-frame)))
+ (should (equal (face-attribute 'faces--test-inherit-extend :extend fr)
+ 'unspecified))
+ (should (equal (face-attribute 'faces--test-inherit-extend :extend fr t)
+ t))
+ (should (equal (face-attribute 'faces--test-inherit-no-extend
+ :extend fr)
+ 'unspecified))
+ (should (equal (face-attribute 'faces--test-inherit-no-extend
+ :extend fr t)
+ nil))
+ (should (equal (face-attribute 'spiff-changed-face :extend fr) t))
+ (should (equal (face-attribute 'spiff-added :extend fr) t))
+ (should (equal (face-attribute 'spiff-file-header-face :extend fr) nil))
+ (should (equal (face-attribute 'spiff-indicator-changed :extend fr) t))
+ (should (equal (face-attribute 'faces--test-face3 :extend nil t) t))
+ ))
+ (disable-theme 'faces-test-light)
+ (should (equal (face-attribute 'spiff-indicator-changed :extend) t))
+ (should (equal (face-attribute 'faces--test-face3 :extend nil t) 'unspecified))
+ (or noninteractive
+ (let ((fr (make-frame)))
+ (should (equal (face-attribute 'spiff-changed-face :extend fr) t))
+ (should (equal (face-attribute 'spiff-added :extend fr) 'unspecified))
+ (should (equal (face-attribute 'spiff-file-header-face :extend fr) nil))
+ (should (equal (face-attribute 'spiff-indicator-changed :extend fr) t))
+ (should (equal (face-attribute 'faces--test-face3 :extend nil t) 'unspecified))
+ ))
+ )
+
+(ert-deftest test-tty-find-type ()
+ (let ((pred (lambda (string)
+ (locate-library (concat "term/" string ".el")))))
+ (should (tty-find-type pred "cygwin"))
+ (should (tty-find-type pred "cygwin-foo"))
+ (should (equal (tty-find-type pred "xterm") "xterm"))
+ (should (equal (tty-find-type pred "screen.xterm") "screen"))))
+
(provide 'faces-tests)
;;; faces-tests.el ends here
diff --git a/test/lisp/ffap-tests.el b/test/lisp/ffap-tests.el
index 0b90d640364..076d8256421 100644
--- a/test/lisp/ffap-tests.el
+++ b/test/lisp/ffap-tests.el
@@ -1,6 +1,6 @@
;;; ffap-tests.el --- Test suite for ffap.el -*- lexical-binding: t -*-
-;; Copyright (C) 2016-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2022 Free Software Foundation, Inc.
;; Author: Tino Calancha <tino.calancha@gmail.com>
@@ -25,30 +25,53 @@
(require 'cl-lib)
(require 'ert)
+(require 'ert-x)
(require 'ffap)
+(ert-deftest ffap-replace-file-component ()
+ (should (equal
+ (ffap-replace-file-component "/ftp:who@foo.com:/whatever" "/new")
+ "/ftp:who@foo.com:/new")))
+
+(ert-deftest ffap-file-remote-p ()
+ (dolist (test '(("/user@foo.bar.com:/pub" .
+ "/user@foo.bar.com:/pub")
+ ("/cssun.mathcs.emory.edu://dir" .
+ "/cssun.mathcs.emory.edu:/dir")
+ ("/ffap.el:80" .
+ "/ffap.el:80")))
+ (let ((A (car test))
+ (B (cdr test)))
+ (should (equal (ffap-file-remote-p A) B)))))
+
+(ert-deftest ffap-machine-p ()
+ (should-not (ffap-machine-p "ftp"))
+ (should-not (ffap-machine-p "nonesuch"))
+ (should (eq (ffap-machine-p "ftp.mathcs.emory.edu") 'accept))
+ (should-not (ffap-machine-p "mathcs" 5678))
+ (should-not (ffap-machine-p "foo.bonk"))
+ (should (eq (ffap-machine-p "foo.bonk.com") 'accept)))
+
(ert-deftest ffap-tests-25243 ()
"Test for https://debbugs.gnu.org/25243 ."
- (let ((file (make-temp-file "test-Bug#25243")))
- (unwind-protect
- (with-temp-file file
- (let ((str "diff --git b/lisp/ffap.el a/lisp/ffap.el
+ (ert-with-temp-file file
+ :suffix "-bug25243"
+ (let ((str "diff --git b/lisp/ffap.el a/lisp/ffap.el
index 3d7cebadcf..ad4b70d737 100644
--- b/lisp/ffap.el
+++ a/lisp/ffap.el
@@ -203,6 +203,9 @@ ffap-foo-at-bar-prefix
"))
- (transient-mark-mode 1)
- (when (natnump ffap-max-region-length)
- (insert
- (concat
- str
- (make-string ffap-max-region-length #xa)
- (format "%s ENDS HERE" file)))
- (call-interactively 'mark-whole-buffer)
- (should (equal "" (ffap-string-at-point)))
- (should (equal '(1 1) ffap-string-at-point-region)))))
- (and (file-exists-p file) (delete-file file)))))
+ (transient-mark-mode 1)
+ (when (natnump ffap-max-region-length)
+ (insert
+ (concat
+ str
+ (make-string ffap-max-region-length #xa)
+ (format "%s ENDS HERE" file)))
+ (call-interactively 'mark-whole-buffer)
+ (should (equal "" (ffap-string-at-point)))
+ (should (equal '(1 1) ffap-string-at-point-region))))))
(ert-deftest ffap-gopher-at-point ()
(with-temp-buffer
@@ -71,14 +94,94 @@ Host = example.com\n")
"Test for Bug#25352. Checks that the window configuration is
left alone when opening a URL in an external browser."
(cl-letf* ((old (current-window-configuration))
- ((symbol-function 'ffap-prompter)
- (lambda () "https://www.gnu.org"))
(urls nil)
(ffap-url-fetcher (lambda (url) (push url urls) nil)))
- (should-not (ffap-other-window))
- (should (equal (current-window-configuration) old))
+ (should-not (ffap-other-window "https://www.gnu.org"))
+ (should (window-configuration-equal-p (current-window-configuration) old))
(should (equal urls '("https://www.gnu.org")))))
+(defun ffap-test-string (space string)
+ (let ((ffap-file-name-with-spaces space))
+ (with-temp-buffer
+ (insert string)
+ (goto-char (point-min))
+ (forward-char 10)
+ (ffap-string-at-point))))
+
+(ert-deftest ffap-test-with-spaces ()
+ (should
+ (equal
+ (ffap-test-string
+ t "c:/Program Files/Open Text Evaluation Media/Open Text Exceed 14 x86/Program here.txt")
+ "/Program Files/Open Text Evaluation Media/Open Text Exceed 14 x86/Program here.txt"))
+ (should
+ (equal
+ (ffap-test-string
+ nil "c:/Program Files/Open Text Evaluation Media/Open Text Exceed 14 x86/Program here.txt")
+ "c:/Program"))
+ (should
+ (equal
+ (ffap-test-string
+ t "c:/Program Files/Open Text Evaluation Media/Open Text Exceed 14 x86/Program Files/Hummingbird/")
+ "/Program Files/Open Text Evaluation Media/Open Text Exceed 14 x86/Program Files/Hummingbird/"))
+ (should
+ (equal
+ (ffap-test-string
+ t "c:\\Program Files\\Open Text Evaluation Media\\Open Text Exceed 14 x86\\Program Files\\Hummingbird\\")
+ "\\Program Files\\Open Text Evaluation Media\\Open Text Exceed 14 x86\\Program Files\\Hummingbird\\"))
+ (should
+ (equal
+ (ffap-test-string
+ t "c:\\Program Files\\Freescale\\CW for MPC55xx and MPC56xx 2.10\\PowerPC_EABI_Tools\\Command_Line_Tools\\CLT_Usage_Notes.txt")
+ "\\Program Files\\Freescale\\CW for MPC55xx and MPC56xx 2.10\\PowerPC_EABI_Tools\\Command_Line_Tools\\CLT_Usage_Notes.txt"))
+ (should
+ (equal
+ (ffap-test-string
+ t "C:\\temp\\program.log on Windows or /var/log/program.log on Unix.")
+ "\\temp\\program.log")))
+
+(ert-deftest ffap-test-no-newlines ()
+ (should-not
+ (with-temp-buffer
+ (save-excursion (insert "type="))
+ (ffap-guess-file-name-at-point))))
+
+(ert-deftest ffap-ido-mode ()
+ (require 'ido)
+ (with-temp-buffer
+ (let ((ido-mode t)
+ (read-file-name-function read-file-name-function)
+ (read-buffer-function read-buffer-function))
+ ;; Says ert-deftest:
+ ;; Macros in BODY are expanded when the test is defined, not when it
+ ;; is run. If a macro (possibly with side effects) is to be tested,
+ ;; it has to be wrapped in `(eval (quote ...))'.
+ (eval (quote (ido-everywhere)) t)
+ (let ((read-file-name-function (lambda (&rest args)
+ (expand-file-name
+ (nth 4 args)
+ (nth 1 args)))))
+ (save-excursion (insert "ffap-tests.el"))
+ (let (kill-buffer-query-functions)
+ (kill-buffer (call-interactively #'find-file-at-point)))))))
+
+(ert-deftest ffap-test-path ()
+ (skip-unless (file-exists-p "/bin"))
+ (skip-unless (file-exists-p "/usr/bin"))
+ (with-temp-buffer
+ (insert "/usr/bin:/bin")
+ (goto-char (point-min))
+ (should (equal (ffap-file-at-point) "/usr/bin")))
+ (with-temp-buffer
+ (insert "/usr/bin:/bin")
+ (goto-char (point-min))
+ (search-forward ":")
+ (should (equal (ffap-file-at-point) "/bin")))
+ (with-temp-buffer
+ (insert ":/bin")
+ (goto-char (point-min))
+ (should (equal (ffap-file-at-point) nil))))
+
(provide 'ffap-tests)
;;; ffap-tests.el ends here
diff --git a/test/lisp/filenotify-tests.el b/test/lisp/filenotify-tests.el
index 17840e8724b..d82e2dae7aa 100644
--- a/test/lisp/filenotify-tests.el
+++ b/test/lisp/filenotify-tests.el
@@ -1,21 +1,23 @@
;;; filenotify-tests.el --- Tests of file notifications -*- lexical-binding: t; -*-
-;; Copyright (C) 2013-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2022 Free Software Foundation, Inc.
;; Author: Michael Albinus <michael.albinus@gmx.de>
-;; This program is free software: you can redistribute it and/or
+;; This file is part of GNU Emacs.
+;;
+;; GNU Emacs is free software: you can redistribute it and/or
;; modify it under the terms of the GNU General Public License as
;; published by the Free Software Foundation, either version 3 of the
;; License, or (at your option) any later version.
;;
-;; This program is distributed in the hope that it will be useful, but
+;; GNU Emacs is distributed in the hope that it will be useful, but
;; WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
;; General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
-;; along with this program. If not, see `https://www.gnu.org/licenses/'.
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
@@ -31,38 +33,36 @@
;; remote host, set this environment variable to "/dev/null" or
;; whatever is appropriate on your system.
+;; For the remote file-notify library, Tramp checks for the existence
+;; of a respective command. The first command found is used. In
+;; order to use a dedicated one, the environment variable
+;; $REMOTE_FILE_NOTIFY_LIBRARY shall be set, possible values are
+;; "inotifywait", "gio-monitor" and "gvfs-monitor-dir".
+
+;; Local file-notify libraries are auto-detected during Emacs
+;; configuration. This can be changed with a respective configuration
+;; argument, like
+;;
+;; --with-file-notification=inotify
+;; --with-file-notification=kqueue
+;; --with-file-notification=gfile
+;; --with-file-notification=w32
+
;; A whole test run can be performed calling the command `file-notify-test-all'.
;;; Code:
-(require 'ert)
+(require 'tramp)
(require 'ert-x)
(require 'filenotify)
-(require 'tramp)
-;; There is no default value on w32 systems, which could work out of the box.
-(defconst file-notify-test-remote-temporary-file-directory
- (cond
- ((getenv "REMOTE_TEMPORARY_FILE_DIRECTORY"))
- ((eq system-type 'windows-nt) null-device)
- (t (add-to-list
- 'tramp-methods
- '("mock"
- (tramp-login-program "sh")
- (tramp-login-args (("-i")))
- (tramp-remote-shell "/bin/sh")
- (tramp-remote-shell-args ("-c"))
- (tramp-connection-timeout 10)))
- (add-to-list
- 'tramp-default-host-alist
- `("\\`mock\\'" nil ,(system-name)))
- ;; Emacs' Makefile sets $HOME to a nonexistent value. Needed in
- ;; batch mode only, therefore.
- (unless (and (null noninteractive) (file-directory-p "~/"))
- (setenv "HOME" temporary-file-directory))
- (format "/mock::%s" temporary-file-directory)))
- "Temporary directory for Tramp tests.")
+;; Filter suppressed remote file-notify libraries.
+(when (stringp (getenv "REMOTE_FILE_NOTIFY_LIBRARY"))
+ (dolist (lib '("inotifywait" "gio-monitor" "gvfs-monitor-dir"))
+ (unless (string-equal (getenv "REMOTE_FILE_NOTIFY_LIBRARY") lib)
+ (add-to-list 'tramp-connection-properties `(nil ,lib nil)))))
+(defvar file-notify--test-tmpdir nil)
(defvar file-notify--test-tmpfile nil)
(defvar file-notify--test-tmpfile1 nil)
(defvar file-notify--test-desc nil)
@@ -70,6 +70,7 @@
(defvar file-notify--test-desc2 nil)
(defvar file-notify--test-results nil)
(defvar file-notify--test-event nil)
+(defvar file-notify--test-file nil)
(defvar file-notify--test-events nil)
(defvar file-notify--test-monitors nil)
@@ -81,25 +82,23 @@ There are different timeouts for local and remote file notification libraries."
(cond
;; gio/gpollfilemonitor.c declares POLL_TIME_SECS 5. So we must
;; wait at least this time in the GPollFileMonitor case. A
- ;; similar timeout seems to be needed in the GFamFileMonitor case,
- ;; at least on Cygwin.
- ((and (string-equal (file-notify--test-library) "gfilenotify")
- (memq (file-notify--test-monitor)
- '(GFamFileMonitor GPollFileMonitor)))
- 7)
- ((string-equal (file-notify--test-library) "gvfs-monitor-dir.exe") 1)
+ ;; similar timeout seems to be needed in the
+ ;; GFam{File,Directory}Monitor case. So we use a large timeout
+ ;; for any monitor.
+ ((file-notify--test-monitor) 7)
((file-remote-p temporary-file-directory) 0.1)
(t 0.01))))
(defun file-notify--test-timeout ()
"Timeout to wait for arriving a bunch of events, in seconds."
(cond
- ((file-remote-p temporary-file-directory) 6)
+ ((file-remote-p temporary-file-directory) 20)
+ ((eq system-type 'cygwin) 10)
+ ((getenv "EMACS_EMBA_CI") 10)
((string-equal (file-notify--test-library) "w32notify") 4)
- ((eq system-type 'cygwin) 6)
(t 3)))
-(defmacro file-notify--wait-for-events (timeout until)
+(defmacro file-notify--test-wait-for-events (timeout until)
"Wait for and return file notification events until form UNTIL is true.
TIMEOUT is the maximum time to wait for, in seconds."
`(with-timeout (,timeout (ignore))
@@ -110,7 +109,7 @@ TIMEOUT is the maximum time to wait for, in seconds."
"Check that `file-notify-descriptors' is an empty hash table.
Return nil when any other file notification watch is still active."
;; Give read events a last chance.
- (file-notify--wait-for-events
+ (file-notify--test-wait-for-events
(file-notify--test-timeout)
(zerop (hash-table-count file-notify-descriptors)))
;; Now check.
@@ -138,9 +137,11 @@ Return nil when any other file notification watch is still active."
(defun file-notify--test-cleanup ()
"Cleanup after a test."
- (file-notify-rm-watch file-notify--test-desc)
- (file-notify-rm-watch file-notify--test-desc1)
- (file-notify-rm-watch file-notify--test-desc2)
+ ;; (when (getenv "EMACS_EMBA_CI")
+ ;; (dolist (buf (tramp-list-tramp-buffers))
+ ;; (message ";; %s\n%s" buf (tramp-get-buffer-string buf))
+ ;; (kill-buffer buf)))
+ (file-notify-rm-all-watches)
(ignore-errors
(delete-file (file-newest-backup file-notify--test-tmpfile)))
@@ -153,6 +154,8 @@ Return nil when any other file notification watch is still active."
(delete-directory file-notify--test-tmpfile1 'recursive)
(delete-file file-notify--test-tmpfile1)))
(ignore-errors
+ (delete-directory file-notify--test-tmpdir 'recursive))
+ (ignore-errors
(when (file-remote-p temporary-file-directory)
(tramp-cleanup-connection
(tramp-dissect-file-name temporary-file-directory) nil 'keep-password)))
@@ -160,22 +163,30 @@ Return nil when any other file notification watch is still active."
(when (hash-table-p file-notify-descriptors)
(clrhash file-notify-descriptors))
- (setq file-notify--test-tmpfile nil
+ (setq file-notify--test-tmpdir nil
+ file-notify--test-tmpfile nil
file-notify--test-tmpfile1 nil
file-notify--test-desc nil
file-notify--test-desc1 nil
file-notify--test-desc2 nil
file-notify--test-results nil
+ file-notify--test-event nil
+ file-notify--test-file nil
file-notify--test-events nil
file-notify--test-monitors nil))
-(setq password-cache-expiry nil
+(setq file-notify-debug nil
+ password-cache-expiry nil
+ ;; tramp-verbose (if (getenv "EMACS_EMBA_CI") 10 0)
tramp-verbose 0
- tramp-message-show-message nil)
+ ;; When the remote user id is 0, Tramp refuses unsafe temporary files.
+ tramp-allow-unsafe-temporary-files
+ (or tramp-allow-unsafe-temporary-files noninteractive))
-;; This should happen on hydra only.
-(when (getenv "EMACS_HYDRA_CI")
- (add-to-list 'tramp-remote-path 'tramp-own-remote-path))
+(defun file-notify--test-add-watch (file flags callback)
+ "Like `file-notify-add-watch', but also passing FILE to CALLBACK."
+ (file-notify-add-watch file flags
+ (lambda (event) (funcall callback event file))))
;; We do not want to try and fail `file-notify-add-watch'.
(defun file-notify--test-local-enabled ()
@@ -185,7 +196,8 @@ remote case we return always t."
(or file-notify--library
(file-remote-p temporary-file-directory)))
-(defvar file-notify--test-remote-enabled-checked nil
+(defvar file-notify--test-remote-enabled-checked
+ (if (getenv "EMACS_HYDRA_CI") '(t . nil))
"Cached result of `file-notify--test-remote-enabled'.
If the function did run, the value is a cons cell, the `cdr'
being the result.")
@@ -196,12 +208,12 @@ being the result.")
(let (desc)
(ignore-errors
(and
- (file-remote-p file-notify-test-remote-temporary-file-directory)
- (file-directory-p file-notify-test-remote-temporary-file-directory)
- (file-writable-p file-notify-test-remote-temporary-file-directory)
+ (file-remote-p ert-remote-temporary-file-directory)
+ (file-directory-p ert-remote-temporary-file-directory)
+ (file-writable-p ert-remote-temporary-file-directory)
(setq desc
(file-notify-add-watch
- file-notify-test-remote-temporary-file-directory
+ ert-remote-temporary-file-directory
'(change) #'ignore))))
(setq file-notify--test-remote-enabled-checked (cons t desc))
(when desc (file-notify-rm-watch desc))))
@@ -222,28 +234,48 @@ remote host, or nil."
(defun file-notify--test-monitor ()
"The used monitor for the test, as a symbol.
-This returns only for the local case and gfilenotify; otherwise it is nil.
-`file-notify--test-desc' must be a valid watch descriptor."
+This returns only for (local) gfilenotify or (remote) gio library;
+otherwise it is nil. `file-notify--test-desc' must be a valid
+watch descriptor."
;; We cache the result, because after `file-notify-rm-watch',
;; `gfile-monitor-name' does not return a proper result anymore.
- ;; But we still need this information.
- (unless (file-remote-p temporary-file-directory)
- (or (cdr (assq file-notify--test-desc file-notify--test-monitors))
- (when (functionp 'gfile-monitor-name)
- (add-to-list 'file-notify--test-monitors
- (cons file-notify--test-desc
- (gfile-monitor-name file-notify--test-desc)))
- (cdr (assq file-notify--test-desc file-notify--test-monitors))))))
-
-(defmacro file-notify--deftest-remote (test docstring)
- "Define ert `TEST-remote' for remote files."
+ ;; But we still need this information. So far, we know the monitors
+ ;; GFamFileMonitor (gfilenotify on cygwin), GFamDirectoryMonitor
+ ;; (gfilenotify on Solaris), GInotifyFileMonitor (gfilenotify and
+ ;; gio on GNU/Linux), GKqueueFileMonitor (gfilenotify and gio on
+ ;; FreeBSD) and GPollFileMonitor (gio on cygwin).
+ (when file-notify--test-desc
+ (or (alist-get file-notify--test-desc file-notify--test-monitors)
+ (when (member (file-notify--test-library) '("gfilenotify" "gio"))
+ (add-to-list
+ 'file-notify--test-monitors
+ (cons file-notify--test-desc
+ (if (file-remote-p temporary-file-directory)
+ ;; `file-notify--test-desc' is the connection process.
+ (progn
+ (while (not (tramp-connection-property-p
+ file-notify--test-desc "gio-file-monitor"))
+ (accept-process-output file-notify--test-desc 0))
+ (tramp-get-connection-property
+ file-notify--test-desc "gio-file-monitor" nil))
+ (and (functionp 'gfile-monitor-name)
+ (gfile-monitor-name file-notify--test-desc)))))
+ ;; If we don't know the monitor, there are good chances the
+ ;; test will fail. We let it fail already here, in order to
+ ;; know the real reason.
+ (should (alist-get file-notify--test-desc file-notify--test-monitors)))
+ (alist-get file-notify--test-desc file-notify--test-monitors))))
+
+(defmacro file-notify--deftest-remote (test docstring &optional unstable)
+ "Define ert `TEST-remote' for remote files.
+If UNSTABLE is non-nil, the test is tagged as `:unstable'."
(declare (indent 1))
`(ert-deftest ,(intern (concat (symbol-name test) "-remote")) ()
,docstring
- :tags '(:expensive-test)
- (let* ((temporary-file-directory
- file-notify-test-remote-temporary-file-directory)
- (ert-test (ert-get-test ',test)))
+ :tags (if ,unstable '(:expensive-test :unstable) '(:expensive-test))
+ (let* ((temporary-file-directory ert-remote-temporary-file-directory)
+ (ert-test (ert-get-test ',test))
+ vc-handled-backends)
(skip-unless (file-notify--test-remote-enabled))
(tramp-cleanup-connection
(tramp-dissect-file-name temporary-file-directory) nil 'keep-password)
@@ -274,6 +306,17 @@ This returns only for the local case and gfilenotify; otherwise it is nil.
(file-notify--deftest-remote file-notify-test00-availability
"Test availability of `file-notify' for remote files.")
+(defun file-notify--test-make-temp-name ()
+ "Create a temporary file name for test."
+ (unless (stringp file-notify--test-tmpdir)
+ (setq file-notify--test-tmpdir
+ (expand-file-name
+ (make-temp-name "file-notify-test") temporary-file-directory)))
+ (unless (file-directory-p file-notify--test-tmpdir)
+ (make-directory file-notify--test-tmpdir))
+ (expand-file-name
+ (make-temp-name "file-notify-test") file-notify--test-tmpdir))
+
(ert-deftest file-notify-test01-add-watch ()
"Check `file-notify-add-watch'."
(skip-unless (file-notify--test-local-enabled))
@@ -289,17 +332,17 @@ This returns only for the local case and gfilenotify; otherwise it is nil.
(should
(setq file-notify--test-desc
(file-notify-add-watch
- temporary-file-directory '(change) #'ignore)))
+ file-notify--test-tmpdir '(change) #'ignore)))
(file-notify-rm-watch file-notify--test-desc)
(should
(setq file-notify--test-desc
(file-notify-add-watch
- temporary-file-directory '(attribute-change) #'ignore)))
+ file-notify--test-tmpdir '(attribute-change) #'ignore)))
(file-notify-rm-watch file-notify--test-desc)
(should
(setq file-notify--test-desc
(file-notify-add-watch
- temporary-file-directory '(change attribute-change) #'ignore)))
+ file-notify--test-tmpdir '(change attribute-change) #'ignore)))
(file-notify-rm-watch file-notify--test-desc)
;; File monitors like kqueue insist, that the watched file
@@ -325,11 +368,11 @@ This returns only for the local case and gfilenotify; otherwise it is nil.
'(wrong-type-argument 1)))
(should
(equal (should-error
- (file-notify-add-watch temporary-file-directory 2 3))
+ (file-notify-add-watch file-notify--test-tmpdir 2 3))
'(wrong-type-argument 2)))
(should
(equal (should-error
- (file-notify-add-watch temporary-file-directory '(change) 3))
+ (file-notify-add-watch file-notify--test-tmpdir '(change) 3))
'(wrong-type-argument 3)))
;; The upper directory of a file must exist.
(should
@@ -349,14 +392,9 @@ This returns only for the local case and gfilenotify; otherwise it is nil.
(file-notify--deftest-remote file-notify-test01-add-watch
"Check `file-notify-add-watch' for remote files.")
-(defun file-notify--test-make-temp-name ()
- "Create a temporary file name for test."
- (expand-file-name
- (make-temp-name "file-notify-test") temporary-file-directory))
-
;; This test is inspired by Bug#26126 and Bug#26127.
(ert-deftest file-notify-test02-rm-watch ()
- "Check `file-notify-rm-watch'."
+ "Check `file-notify-rm-watch' and `file-notify-rm-all-watches'."
(skip-unless (file-notify--test-local-enabled))
(unwind-protect
@@ -412,39 +450,69 @@ This returns only for the local case and gfilenotify; otherwise it is nil.
(unwind-protect
;; Check, that removing watch descriptors out of order do not
- ;; harm. This fails on Cygwin because of timing issues unless a
+ ;; harm. This fails on cygwin because of timing issues unless a
;; long `sit-for' is added before the call to
;; `file-notify--test-read-event'.
- (if (not (eq system-type 'cygwin))
- (let (results)
- (cl-flet ((first-callback (event)
- (when (eq (nth 1 event) 'deleted) (push 1 results)))
- (second-callback (event)
- (when (eq (nth 1 event) 'deleted) (push 2 results))))
- (setq file-notify--test-tmpfile (file-notify--test-make-temp-name))
- (write-region
- "any text" nil file-notify--test-tmpfile nil 'no-message)
- (should
- (setq file-notify--test-desc
- (file-notify-add-watch
- file-notify--test-tmpfile
- '(change) #'first-callback)))
- (should
- (setq file-notify--test-desc1
- (file-notify-add-watch
- file-notify--test-tmpfile
- '(change) #'second-callback)))
- ;; Remove first watch.
- (file-notify-rm-watch file-notify--test-desc)
- ;; Only the second callback shall run.
- (file-notify--test-read-event)
- (delete-file file-notify--test-tmpfile)
- (file-notify--wait-for-events
- (file-notify--test-timeout) results)
- (should (equal results (list 2)))
+ (unless (eq system-type 'cygwin)
+ (let (results)
+ (cl-flet ((first-callback (event)
+ (when (eq (file-notify--test-event-action event) 'deleted)
+ (push 1 results)))
+ (second-callback (event)
+ (when (eq (file-notify--test-event-action event) 'deleted)
+ (push 2 results))))
+ (setq file-notify--test-tmpfile (file-notify--test-make-temp-name))
+ (write-region
+ "any text" nil file-notify--test-tmpfile nil 'no-message)
+ (should
+ (setq file-notify--test-desc
+ (file-notify-add-watch
+ file-notify--test-tmpfile
+ '(change) #'first-callback)))
+ (should
+ (setq file-notify--test-desc1
+ (file-notify-add-watch
+ file-notify--test-tmpfile
+ '(change) #'second-callback)))
+ ;; `file-notify-rm-watch' confuses `file-notify--test-monitor'.
+ ;; Initialize it in time.
+ (file-notify--test-monitor)
+ ;; Remove first watch.
+ (file-notify-rm-watch file-notify--test-desc)
+ ;; Only the second callback shall run.
+ (file-notify--test-read-event)
+ (delete-file file-notify--test-tmpfile)
+ (file-notify--test-wait-for-events
+ (file-notify--test-timeout) results)
+ (should (equal results (list 2)))
- ;; The environment shall be cleaned up.
- (file-notify--test-cleanup-p))))
+ ;; The environment shall be cleaned up.
+ (file-notify--test-cleanup-p))))
+
+ ;; Cleanup.
+ (file-notify--test-cleanup))
+
+ (unwind-protect
+ ;; Check `file-notify-rm-all-watches'.
+ (progn
+ (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)
+ file-notify--test-tmpfile1 (file-notify--test-make-temp-name))
+ (write-region "any text" nil file-notify--test-tmpfile nil 'no-message)
+ (write-region "any text" nil file-notify--test-tmpfile1 nil 'no-message)
+ (should
+ (setq file-notify--test-desc
+ (file-notify-add-watch
+ file-notify--test-tmpfile '(change) #'ignore)))
+ (should
+ (setq file-notify--test-desc1
+ (file-notify-add-watch
+ file-notify--test-tmpfile1 '(change) #'ignore)))
+ (file-notify-rm-all-watches)
+ (delete-file file-notify--test-tmpfile)
+ (delete-file file-notify--test-tmpfile1)
+
+ ;; The environment shall be cleaned up.
+ (file-notify--test-cleanup-p))
;; Cleanup.
(file-notify--test-cleanup)))
@@ -452,154 +520,188 @@ This returns only for the local case and gfilenotify; otherwise it is nil.
(file-notify--deftest-remote file-notify-test02-rm-watch
"Check `file-notify-rm-watch' for remote files.")
+;; Accessors for the callback argument.
+(defun file-notify--test-event-desc (event) (car event))
+(defun file-notify--test-event-action (event) (nth 1 event))
+(defun file-notify--test-event-file (event) (nth 2 event))
+(defun file-notify--test-event-file1 (event) (nth 3 event))
+
(defun file-notify--test-event-test ()
"Ert test function to be called by `file-notify--test-event-handler'.
We cannot pass arguments, so we assume that `file-notify--test-event'
-is bound somewhere."
+and `file-notify--test-file' are bound somewhere."
;; Check the descriptor.
- (should (equal (car file-notify--test-event) file-notify--test-desc))
+ (should (equal (file-notify--test-event-desc file-notify--test-event)
+ file-notify--test-desc))
;; Check the file name.
(should
(string-prefix-p
- (file-notify--event-watched-file file-notify--test-event)
- (file-notify--event-file-name file-notify--test-event)))
+ file-notify--test-file
+ (file-notify--test-event-file file-notify--test-event)))
;; Check the second file name if exists.
- (when (eq (nth 1 file-notify--test-event) 'renamed)
+ (when (eq (file-notify--test-event-action file-notify--test-event) 'renamed)
(should
(string-prefix-p
- (file-notify--event-watched-file file-notify--test-event)
- (file-notify--event-file1-name file-notify--test-event)))))
+ file-notify--test-file
+ (file-notify--test-event-file1 file-notify--test-event)))))
-(defun file-notify--test-event-handler (event)
+(defun file-notify--test-event-handler (event file)
"Run a test over FILE-NOTIFY--TEST-EVENT.
For later analysis, append the test result to `file-notify--test-results'
and the event to `file-notify--test-events'."
(let* ((file-notify--test-event event)
+ (file-notify--test-file file)
(result
(ert-run-test (make-ert-test :body 'file-notify--test-event-test))))
;; Do not add lock files, this would confuse the checks.
(unless (string-match
(regexp-quote ".#")
- (file-notify--event-file-name file-notify--test-event))
- ;;(message "file-notify--test-event-handler result: %s event: %S"
- ;;(null (ert-test-failed-p result)) file-notify--test-event)
+ (file-notify--test-event-file file-notify--test-event))
+ (when file-notify-debug
+ (message "file-notify--test-event-handler result: %s event: %S"
+ (null (ert-test-failed-p result)) file-notify--test-event))
(setq file-notify--test-events
(append file-notify--test-events `(,file-notify--test-event))
file-notify--test-results
(append file-notify--test-results `(,result))))))
-(defun file-notify--test-with-events-check (events)
- "Check whether received events match one of the EVENTS alternatives."
+(defun file-notify--test-event-actions ()
+ "Helper function to return retrieved actions, as list."
+ (mapcar #'file-notify--test-event-action file-notify--test-events))
+
+(defun file-notify--test-with-actions-check (actions)
+ "Check whether received actions match one of the ACTIONS alternatives."
(let (result)
- (dolist (elt events result)
+ (dolist (elt actions result)
(setq result
(or result
(if (eq (car elt) :random)
(equal (sort (cdr elt) 'string-lessp)
- (sort (mapcar #'cadr file-notify--test-events)
+ (sort (file-notify--test-event-actions)
'string-lessp))
- (equal elt (mapcar #'cadr file-notify--test-events))))))))
-
-(defun file-notify--test-with-events-explainer (events)
- "Explain why `file-notify--test-with-events-check' fails."
- (if (null (cdr events))
- (format "Received events do not match expected events\n%s\n%s"
- (mapcar #'cadr file-notify--test-events) (car events))
+ (equal elt (file-notify--test-event-actions))))))
+ ;; Do not report result in case we debug. Write messages instead.
+ (if file-notify-debug
+ (prog1 t
+ (if result
+ (message "Success\n%s" (file-notify--test-event-actions))
+ (message (file-notify--test-with-actions-explainer actions))))
+ result)))
+
+(defun file-notify--test-with-actions-explainer (actions)
+ "Explain why `file-notify--test-with-actions-check' fails."
+ (if (null (cdr actions))
+ (format "Received actions do not match expected actions\n%s\n%s"
+ (file-notify--test-event-actions) (car actions))
(format
- "Received events do not match any sequence of expected events\n%s\n%s"
- (mapcar #'cadr file-notify--test-events) events)))
+ "Received actions do not match any sequence of expected actions\n%s\n%s"
+ (file-notify--test-event-actions) actions)))
-(put 'file-notify--test-with-events-check 'ert-explainer
- 'file-notify--test-with-events-explainer)
+(put 'file-notify--test-with-actions-check 'ert-explainer
+ 'file-notify--test-with-actions-explainer)
-(defmacro file-notify--test-with-events (events &rest body)
- "Run BODY collecting events and then compare with EVENTS.
-EVENTS is either a simple list of events, or a list of lists of
-events, which represent different possible results. The first
+(defmacro file-notify--test-with-actions (actions &rest body)
+ "Run BODY collecting actions and then compare with ACTIONS.
+ACTIONS is either a simple list of actions, or a list of lists of
+actions, which represent different possible results. The first
event of a list could be the pseudo event `:random', which is
just an indicator for comparison.
-Don't wait longer than timeout seconds for the events to be
+Don't wait longer than timeout seconds for the actions to be
delivered."
- (declare (indent 1))
- `(let* ((events (if (consp (car ,events)) ,events (list ,events)))
+ (declare (indent 1) (debug (form body)))
+ `(let* ((actions (if (consp (car ,actions)) ,actions (list ,actions)))
(max-length
(apply
'max
(mapcar
(lambda (x) (length (if (eq (car x) :random) (cdr x) x)))
- events)))
+ actions)))
+ ;; Don't stop while debugging.
+ (while-no-input-ignore-events
+ (cons 'file-notify while-no-input-ignore-events))
create-lockfiles)
- ;; Flush pending events.
+ ;; Flush pending actions.
(file-notify--test-read-event)
- (file-notify--wait-for-events
+ (file-notify--test-wait-for-events
(file-notify--test-timeout)
(not (input-pending-p)))
(setq file-notify--test-events nil
file-notify--test-results nil)
,@body
- (file-notify--wait-for-events
- ;; More events need more time. Use some fudge factor.
+ (file-notify--test-wait-for-events
+ ;; More actions need more time. Use some fudge factor.
(* (ceiling max-length 100) (file-notify--test-timeout))
(= max-length (length file-notify--test-events)))
- ;; Check the result sequence just to make sure that all events
+ ;; Check the result sequence just to make sure that all actions
;; are as expected.
(dolist (result file-notify--test-results)
(when (ert-test-failed-p result)
(ert-fail
(cadr (ert-test-result-with-condition-condition result)))))
;; One of the possible event sequences shall match.
- (should (file-notify--test-with-events-check events))))
+ (should (file-notify--test-with-actions-check actions))))
(ert-deftest file-notify-test03-events ()
"Check file creation/change/removal notifications."
+ :tags (if (getenv "EMACS_EMBA_CI")
+ '(:expensive-test :unstable)
+ '(:expensive-test))
(skip-unless (file-notify--test-local-enabled))
(unwind-protect
- (progn
- ;; Check file creation, change and deletion. It doesn't work
- ;; for kqueue, because we don't use an implicit directory
- ;; monitor.
- (unless (string-equal (file-notify--test-library) "kqueue")
- (setq file-notify--test-tmpfile (file-notify--test-make-temp-name))
- (should
- (setq file-notify--test-desc
- (file-notify-add-watch
- file-notify--test-tmpfile
- '(change) #'file-notify--test-event-handler)))
- (file-notify--test-with-events
- (cond
- ;; gvfs-monitor-dir on cygwin does not detect the
- ;; `created' event reliably.
- ((string-equal
- (file-notify--test-library) "gvfs-monitor-dir.exe")
- '((deleted stopped)
- (created deleted stopped)))
- ;; cygwin does not raise a `changed' event.
- ((eq system-type 'cygwin)
- '(created deleted stopped))
- (t '(created changed deleted stopped)))
- (write-region
- "another text" nil file-notify--test-tmpfile nil 'no-message)
- (file-notify--test-read-event)
- (delete-file file-notify--test-tmpfile))
- (file-notify-rm-watch file-notify--test-desc))
+ ;; Check file creation, change and deletion. It doesn't work
+ ;; for kqueue, because we don't use an implicit directory
+ ;; monitor.
+ (unless (string-equal (file-notify--test-library) "kqueue")
+ (setq file-notify--test-tmpfile (file-notify--test-make-temp-name))
+ (should
+ (setq file-notify--test-desc
+ (file-notify--test-add-watch
+ file-notify--test-tmpfile
+ '(change) #'file-notify--test-event-handler)))
+ (file-notify--test-with-actions
+ (cond
+ ;; GFam{File,Directory}Monitor, GKqueueFileMonitor and
+ ;; GPollFileMonitor do not report the `changed' event.
+ ((memq (file-notify--test-monitor)
+ '(GFamFileMonitor GFamDirectoryMonitor
+ GKqueueFileMonitor GPollFileMonitor))
+ '(created deleted stopped))
+ (t '(created changed deleted stopped)))
+ (write-region
+ "another text" nil file-notify--test-tmpfile nil 'no-message)
+ (file-notify--test-read-event)
+ (delete-file file-notify--test-tmpfile))
+ (file-notify-rm-watch file-notify--test-desc)
+
+ ;; The environment shall be cleaned up.
+ (file-notify--test-cleanup-p))
+ ;; Cleanup.
+ (file-notify--test-cleanup))
+
+ (unwind-protect
+ (progn
;; Check file change and deletion.
(setq file-notify--test-tmpfile (file-notify--test-make-temp-name))
(write-region "any text" nil file-notify--test-tmpfile nil 'no-message)
(should
(setq file-notify--test-desc
- (file-notify-add-watch
+ (file-notify--test-add-watch
file-notify--test-tmpfile
'(change) #'file-notify--test-event-handler)))
- (file-notify--test-with-events
+ (file-notify--test-with-actions
(cond
- ;; gvfs-monitor-dir on cygwin does not detect the
- ;; `changed' event reliably.
- ((string-equal (file-notify--test-library) "gvfs-monitor-dir.exe")
+ ;; GFam{File,Directory}Monitor and GPollFileMonitor do
+ ;; not detect the `changed' event reliably.
+ ((memq (file-notify--test-monitor)
+ '(GFamFileMonitor GFamDirectoryMonitor GPollFileMonitor))
'((deleted stopped)
(changed deleted stopped)))
+ ;; GKqueueFileMonitor does not report the `changed' event.
+ ((eq (file-notify--test-monitor) 'GKqueueFileMonitor)
+ '(deleted stopped))
;; There could be one or two `changed' events.
(t '((changed deleted stopped)
(changed changed deleted stopped))))
@@ -609,163 +711,214 @@ delivered."
(delete-file file-notify--test-tmpfile))
(file-notify-rm-watch file-notify--test-desc)
- ;; Check file creation, change and deletion when watching a
- ;; directory. There must be a `stopped' event when deleting
- ;; the directory.
- (let ((temporary-file-directory
- (make-temp-file "file-notify-test-parent" t)))
- (should
- (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)
- file-notify--test-desc
- (file-notify-add-watch
- temporary-file-directory
- '(change) #'file-notify--test-event-handler)))
- (file-notify--test-with-events
- (cond
- ;; w32notify does not raise `deleted' and `stopped'
- ;; events for the watched directory.
- ((string-equal (file-notify--test-library) "w32notify")
- '(created changed deleted))
- ;; gvfs-monitor-dir on cygwin does not detect the
- ;; `created' event reliably.
- ((string-equal
- (file-notify--test-library) "gvfs-monitor-dir.exe")
- '((deleted stopped)
- (created deleted stopped)))
- ;; There are two `deleted' events, for the file and for
- ;; the directory. Except for cygwin and kqueue. And
- ;; cygwin does not raise a `changed' event.
- ((eq system-type 'cygwin)
- '(created deleted stopped))
- ((string-equal (file-notify--test-library) "kqueue")
- '(created changed deleted stopped))
- (t '(created changed deleted deleted stopped)))
- (write-region
- "any text" nil file-notify--test-tmpfile nil 'no-message)
- (file-notify--test-read-event)
- (delete-directory temporary-file-directory 'recursive))
- (file-notify-rm-watch file-notify--test-desc))
+ ;; The environment shall be cleaned up.
+ (file-notify--test-cleanup-p))
- ;; Check copy of files inside a directory.
- (let ((temporary-file-directory
- (make-temp-file "file-notify-test-parent" t)))
- (should
- (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)
- file-notify--test-tmpfile1 (file-notify--test-make-temp-name)
- file-notify--test-desc
- (file-notify-add-watch
- temporary-file-directory
- '(change) #'file-notify--test-event-handler)))
- (file-notify--test-with-events
- (cond
- ;; w32notify does not distinguish between `changed' and
- ;; `attribute-changed'. It does not raise `deleted'
- ;; and `stopped' events for the watched directory.
- ((string-equal (file-notify--test-library) "w32notify")
- '(created changed created changed
- changed changed changed
- deleted deleted))
- ;; gvfs-monitor-dir on cygwin does not detect the
- ;; `created' event reliably.
- ((string-equal
- (file-notify--test-library) "gvfs-monitor-dir.exe")
- '((deleted stopped)
- (created created deleted stopped)))
- ;; There are three `deleted' events, for two files and
- ;; for the directory. Except for cygwin and kqueue.
- ((eq system-type 'cygwin)
- '(created created changed changed deleted stopped))
- ((string-equal (file-notify--test-library) "kqueue")
- '(created changed created changed deleted stopped))
- (t '(created changed created changed
- deleted deleted deleted stopped)))
- (write-region
- "any text" nil file-notify--test-tmpfile nil 'no-message)
- (file-notify--test-read-event)
- (copy-file file-notify--test-tmpfile file-notify--test-tmpfile1)
- ;; The next two events shall not be visible.
- (file-notify--test-read-event)
- (set-file-modes file-notify--test-tmpfile 000)
- (file-notify--test-read-event)
- (set-file-times file-notify--test-tmpfile '(0 0))
- (file-notify--test-read-event)
- (delete-directory temporary-file-directory 'recursive))
- (file-notify-rm-watch file-notify--test-desc))
+ ;; Cleanup.
+ (file-notify--test-cleanup))
- ;; Check rename of files inside a directory.
- (let ((temporary-file-directory
- (make-temp-file "file-notify-test-parent" t)))
- (should
- (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)
- file-notify--test-tmpfile1 (file-notify--test-make-temp-name)
- file-notify--test-desc
- (file-notify-add-watch
- temporary-file-directory
- '(change) #'file-notify--test-event-handler)))
- (file-notify--test-with-events
- (cond
- ;; w32notify does not raise `deleted' and `stopped'
- ;; events for the watched directory.
- ((string-equal (file-notify--test-library) "w32notify")
- '(created changed renamed deleted))
- ;; gvfs-monitor-dir on cygwin does not detect the
- ;; `created' event reliably.
- ((string-equal
- (file-notify--test-library) "gvfs-monitor-dir.exe")
- '((deleted stopped)
- (created deleted stopped)))
- ;; There are two `deleted' events, for the file and for
- ;; the directory. Except for cygwin and kqueue. And
- ;; cygwin raises `created' and `deleted' events instead
- ;; of a `renamed' event.
- ((eq system-type 'cygwin)
- '(created created deleted deleted stopped))
- ((string-equal (file-notify--test-library) "kqueue")
- '(created changed renamed deleted stopped))
- (t '(created changed renamed deleted deleted stopped)))
- (write-region
- "any text" nil file-notify--test-tmpfile nil 'no-message)
- (file-notify--test-read-event)
- (rename-file file-notify--test-tmpfile file-notify--test-tmpfile1)
- ;; After the rename, we won't get events anymore.
- (file-notify--test-read-event)
- (delete-directory temporary-file-directory 'recursive))
- (file-notify-rm-watch file-notify--test-desc))
+ (unwind-protect
+ ;; Check file creation, change and deletion when watching a
+ ;; directory. There must be a `stopped' event when deleting the
+ ;; directory.
+ (let ((file-notify--test-tmpdir
+ (make-temp-file "file-notify-test-parent" t)))
+ (should
+ (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)
+ file-notify--test-desc
+ (file-notify--test-add-watch
+ file-notify--test-tmpdir
+ '(change) #'file-notify--test-event-handler)))
+ (file-notify--test-with-actions
+ (cond
+ ;; w32notify does not raise `deleted' and `stopped'
+ ;; events for the watched directory.
+ ((string-equal (file-notify--test-library) "w32notify")
+ '(created changed deleted))
+ ;; On emba, `deleted' and `stopped' events of the
+ ;; directory are not detected.
+ ((getenv "EMACS_EMBA_CI")
+ '(created changed deleted))
+ ;; There are two `deleted' events, for the file and for
+ ;; the directory. Except for
+ ;; GFam{File,Directory}Monitor, GPollFileMonitor and
+ ;; kqueue. And GFam{File,Directory}Monitor and
+ ;; GPollFileMonitor do not raise a `changed' event.
+ ((memq (file-notify--test-monitor)
+ '(GFamFileMonitor GFamDirectoryMonitor GPollFileMonitor))
+ '(created deleted stopped))
+ ((string-equal (file-notify--test-library) "kqueue")
+ '(created changed deleted stopped))
+ ;; GKqueueFileMonitor does not report the `changed' event.
+ ((eq (file-notify--test-monitor) 'GKqueueFileMonitor)
+ '(created deleted deleted stopped))
+ (t '(created changed deleted deleted stopped)))
+ (write-region
+ "any text" nil file-notify--test-tmpfile nil 'no-message)
+ (file-notify--test-read-event)
+ (delete-directory file-notify--test-tmpdir 'recursive))
+ (file-notify-rm-watch file-notify--test-desc)
- ;; Check attribute change. Does not work for cygwin.
- (unless (eq system-type 'cygwin)
- (setq file-notify--test-tmpfile (file-notify--test-make-temp-name))
+ ;; The environment shall be cleaned up.
+ (file-notify--test-cleanup-p))
+
+ ;; Cleanup.
+ (file-notify--test-cleanup))
+
+ (unwind-protect
+ ;; Check copy of files inside a directory.
+ (let ((file-notify--test-tmpdir
+ (make-temp-file "file-notify-test-parent" t)))
+ (should
+ (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)
+ file-notify--test-tmpfile1 (file-notify--test-make-temp-name)
+ file-notify--test-desc
+ (file-notify--test-add-watch
+ file-notify--test-tmpdir
+ '(change) #'file-notify--test-event-handler)))
+ (file-notify--test-with-actions
+ (cond
+ ;; w32notify does not distinguish between `changed' and
+ ;; `attribute-changed'. It does not raise `deleted' and
+ ;; `stopped' events for the watched directory.
+ ((string-equal (file-notify--test-library) "w32notify")
+ '(created changed created changed
+ changed changed changed
+ deleted deleted))
+ ;; There are three `deleted' events, for two files and
+ ;; for the directory. Except for
+ ;; GFam{File,Directory}Monitor, GPollFileMonitor and
+ ;; kqueue.
+ ((memq (file-notify--test-monitor)
+ '(GFamFileMonitor GFamDirectoryMonitor GPollFileMonitor))
+ '(created created changed changed deleted stopped))
+ ((string-equal (file-notify--test-library) "kqueue")
+ '(created changed created changed deleted stopped))
+ ;; On emba, `deleted' and `stopped' events of the
+ ;; directory are not detected.
+ ((getenv "EMACS_EMBA_CI")
+ '(created changed created changed deleted deleted))
+ ;; GKqueueFileMonitor does not report the `changed' event.
+ ((eq (file-notify--test-monitor) 'GKqueueFileMonitor)
+ '(created created deleted deleted deleted stopped))
+ (t '(created changed created changed
+ deleted deleted deleted stopped)))
(write-region
"any text" nil file-notify--test-tmpfile nil 'no-message)
- (should
- (setq file-notify--test-desc
- (file-notify-add-watch
- file-notify--test-tmpfile
- '(attribute-change) #'file-notify--test-event-handler)))
- (file-notify--test-with-events
- (cond
- ;; w32notify does not distinguish between `changed' and
- ;; `attribute-changed'. Under MS Windows 7, we get
- ;; four `changed' events, and under MS Windows 10 just
- ;; two. Strange.
- ((string-equal (file-notify--test-library) "w32notify")
- '((changed changed)
- (changed changed changed changed)))
- ;; For kqueue and in the remote case, `write-region'
- ;; raises also an `attribute-changed' event.
- ((or (string-equal (file-notify--test-library) "kqueue")
- (file-remote-p temporary-file-directory))
- '(attribute-changed attribute-changed attribute-changed))
- (t '(attribute-changed attribute-changed)))
- (write-region
- "any text" nil file-notify--test-tmpfile nil 'no-message)
- (file-notify--test-read-event)
- (set-file-modes file-notify--test-tmpfile 000)
- (file-notify--test-read-event)
- (set-file-times file-notify--test-tmpfile '(0 0))
- (file-notify--test-read-event)
- (delete-file file-notify--test-tmpfile))
- (file-notify-rm-watch file-notify--test-desc))
+ (file-notify--test-read-event)
+ (copy-file file-notify--test-tmpfile file-notify--test-tmpfile1)
+ ;; The next two events shall not be visible.
+ (file-notify--test-read-event)
+ (set-file-modes file-notify--test-tmpfile 000 'nofollow)
+ (file-notify--test-read-event)
+ (set-file-times file-notify--test-tmpfile '(0 0) 'nofollow)
+ (file-notify--test-read-event)
+ (delete-directory file-notify--test-tmpdir 'recursive))
+ (file-notify-rm-watch file-notify--test-desc)
+
+ ;; The environment shall be cleaned up.
+ (file-notify--test-cleanup-p))
+
+ ;; Cleanup.
+ (file-notify--test-cleanup))
+
+ (unwind-protect
+ ;; Check rename of files inside a directory.
+ (let ((file-notify--test-tmpdir
+ (make-temp-file "file-notify-test-parent" t)))
+ (should
+ (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)
+ file-notify--test-tmpfile1 (file-notify--test-make-temp-name)
+ file-notify--test-desc
+ (file-notify--test-add-watch
+ file-notify--test-tmpdir
+ '(change) #'file-notify--test-event-handler)))
+ (file-notify--test-with-actions
+ (cond
+ ;; w32notify does not raise `deleted' and `stopped'
+ ;; events for the watched directory.
+ ((string-equal (file-notify--test-library) "w32notify")
+ '(created changed renamed deleted))
+ ;; On emba, `deleted' and `stopped' events of the
+ ;; directory are not detected.
+ ((getenv "EMACS_EMBA_CI")
+ '(created changed renamed deleted))
+ ;; There are two `deleted' events, for the file and for
+ ;; the directory. Except for
+ ;; GFam{File,Directory}Monitor, GPollfileMonitor and
+ ;; kqueue. And GFam{File,Directory}Monitor and
+ ;; GPollFileMonitor raise `created' and `deleted' events
+ ;; instead of a `renamed' event.
+ ((memq (file-notify--test-monitor)
+ '(GFamFileMonitor GFamDirectoryMonitor GPollFileMonitor))
+ '(created created deleted deleted stopped))
+ ((string-equal (file-notify--test-library) "kqueue")
+ '(created changed renamed deleted stopped))
+ ;; GKqueueFileMonitor does not report the `changed' event.
+ ((eq (file-notify--test-monitor) 'GKqueueFileMonitor)
+ '(created renamed deleted deleted stopped))
+ (t '(created changed renamed deleted deleted stopped)))
+ (write-region
+ "any text" nil file-notify--test-tmpfile nil 'no-message)
+ (file-notify--test-read-event)
+ (rename-file file-notify--test-tmpfile file-notify--test-tmpfile1)
+ ;; After the rename, we won't get events anymore.
+ (file-notify--test-read-event)
+ (delete-directory file-notify--test-tmpdir 'recursive))
+ (file-notify-rm-watch file-notify--test-desc)
+
+ ;; The environment shall be cleaned up.
+ (file-notify--test-cleanup-p))
+
+ ;; Cleanup.
+ (file-notify--test-cleanup))
+
+ (unwind-protect
+ ;; Check attribute change.
+ (progn
+ (setq file-notify--test-tmpfile (file-notify--test-make-temp-name))
+ (write-region
+ "any text" nil file-notify--test-tmpfile nil 'no-message)
+ (should
+ (setq file-notify--test-desc
+ (file-notify--test-add-watch
+ file-notify--test-tmpfile
+ '(attribute-change) #'file-notify--test-event-handler)))
+ (file-notify--test-with-actions
+ (cond
+ ;; w32notify does not distinguish between `changed' and
+ ;; `attribute-changed'. Under MS Windows 7, we get four
+ ;; `changed' events, and under MS Windows 10 just two.
+ ;; Strange.
+ ((string-equal (file-notify--test-library) "w32notify")
+ '((changed changed)
+ (changed changed changed changed)))
+ ;; GFam{File,Directory}Monitor, GKqueueFileMonitor and
+ ;; GPollFileMonitor do not report the `attribute-changed'
+ ;; event.
+ ((memq (file-notify--test-monitor)
+ '(GFamFileMonitor GFamDirectoryMonitor
+ GKqueueFileMonitor GPollFileMonitor))
+ '())
+ ;; For GInotifyFileMonitor,`write-region' raises
+ ;; also an `attribute-changed' event on gio.
+ ((and (string-equal (file-notify--test-library) "gio")
+ (eq (file-notify--test-monitor) 'GInotifyFileMonitor))
+ '(attribute-changed attribute-changed attribute-changed))
+ ;; For kqueue, `write-region' raises also an
+ ;; `attribute-changed' event.
+ ((string-equal (file-notify--test-library) "kqueue")
+ '(attribute-changed attribute-changed attribute-changed))
+ (t '(attribute-changed attribute-changed)))
+ (write-region
+ "any text" nil file-notify--test-tmpfile nil 'no-message)
+ (file-notify--test-read-event)
+ (set-file-modes file-notify--test-tmpfile 000 'nofollow)
+ (file-notify--test-read-event)
+ (set-file-times file-notify--test-tmpfile '(0 0) 'nofollow)
+ (file-notify--test-read-event)
+ (delete-file file-notify--test-tmpfile))
+ (file-notify-rm-watch file-notify--test-desc)
;; The environment shall be cleaned up.
(file-notify--test-cleanup-p))
@@ -774,7 +927,7 @@ delivered."
(file-notify--test-cleanup)))
(file-notify--deftest-remote file-notify-test03-events
- "Check file creation/change/removal notifications for remote files.")
+ "Check file creation/change/removal notifications for remote files." t)
(require 'autorevert)
(setq auto-revert-notify-exclude-dir-regexp "nothing-to-be-excluded"
@@ -783,6 +936,7 @@ delivered."
(ert-deftest file-notify-test04-autorevert ()
"Check autorevert via file notification."
+ :tags '(:expensive-test)
(skip-unless (file-notify--test-local-enabled))
;; `auto-revert-buffers' runs every 5". And we must wait, until the
@@ -816,6 +970,10 @@ delivered."
;; timeouts.
(setq file-notify--test-desc auto-revert-notify-watch-descriptor)
+ ;; GKqueueFileMonitor does not report the `changed' event.
+ (skip-unless
+ (not (eq (file-notify--test-monitor) 'GKqueueFileMonitor)))
+
;; Check, that file notification has been used.
(should auto-revert-mode)
(should auto-revert-use-notify)
@@ -824,40 +982,46 @@ delivered."
;; Modify file. We wait for a second, in order to have
;; another timestamp.
(ert-with-message-capture captured-messages
- (sleep-for 1)
- (write-region
- "another text" nil file-notify--test-tmpfile nil 'no-message)
-
- ;; Check, that the buffer has been reverted.
- (file-notify--wait-for-events
- timeout
- (string-match
- (format-message "Reverting buffer `%s'." (buffer-name buf))
- captured-messages))
- (should (string-match "another text" (buffer-string))))
+ (let ((inhibit-message t))
+ (sleep-for 1)
+ (write-region
+ "another text" nil file-notify--test-tmpfile nil 'no-message)
+
+ ;; Check, that the buffer has been reverted.
+ (file-notify--test-wait-for-events
+ timeout
+ (string-match
+ (format-message "Reverting buffer `%s'." (buffer-name buf))
+ captured-messages))
+ (should (string-match "another text" (buffer-string)))))
;; Stop file notification. Autorevert shall still work via polling.
(file-notify-rm-watch auto-revert-notify-watch-descriptor)
- (file-notify--wait-for-events
- timeout (null auto-revert-use-notify))
- (should-not auto-revert-use-notify)
- (should-not auto-revert-notify-watch-descriptor)
+ (file-notify--test-wait-for-events
+ timeout (null auto-revert-notify-watch-descriptor))
+ (should auto-revert-use-notify)
+ (should-not
+ (file-notify-valid-p auto-revert-notify-watch-descriptor))
;; Modify file. We wait for two seconds, in order to
;; have another timestamp. One second seems to be too
- ;; short.
+ ;; short. And cygwin sporadically requires more than two.
(ert-with-message-capture captured-messages
- (sleep-for 2)
- (write-region
- "foo bla" nil file-notify--test-tmpfile nil 'no-message)
-
- ;; Check, that the buffer has been reverted.
- (file-notify--wait-for-events
- timeout
- (string-match
- (format-message "Reverting buffer `%s'." (buffer-name buf))
- captured-messages))
- (should (string-match "foo bla" (buffer-string)))))
+ (let ((inhibit-message t))
+ (sleep-for (if (eq system-type 'cygwin) 3 2))
+ (write-region
+ "foo bla" nil file-notify--test-tmpfile nil 'no-message)
+
+ ;; Check, that the buffer has been reverted.
+ (file-notify--test-wait-for-events
+ timeout
+ (string-match
+ (format-message "Reverting buffer `%s'." (buffer-name buf))
+ captured-messages))
+ (should (string-match "foo bla" (buffer-string)))))
+
+ ;; Stop autorevert, in order to cleanup descriptor.
+ (auto-revert-mode -1))
;; The environment shall be cleaned up.
(file-notify--test-cleanup-p))
@@ -872,6 +1036,7 @@ delivered."
(ert-deftest file-notify-test05-file-validity ()
"Check `file-notify-valid-p' for files."
+ :tags '(:expensive-test)
(skip-unless (file-notify--test-local-enabled))
(unwind-protect
@@ -901,17 +1066,21 @@ delivered."
(write-region "any text" nil file-notify--test-tmpfile nil 'no-message)
(should
(setq file-notify--test-desc
- (file-notify-add-watch
+ (file-notify--test-add-watch
file-notify--test-tmpfile
'(change) #'file-notify--test-event-handler)))
(should (file-notify-valid-p file-notify--test-desc))
- (file-notify--test-with-events
+ (file-notify--test-with-actions
(cond
- ;; gvfs-monitor-dir on cygwin does not detect the
- ;; `changed' event reliably.
- ((string-equal (file-notify--test-library) "gvfs-monitor-dir.exe")
+ ;; GFam{File,Directory}Monitor do not
+ ;; detect the `changed' event reliably.
+ ((memq (file-notify--test-monitor)
+ '(GFamFileMonitor GFamDirectoryMonitor))
'((deleted stopped)
(changed deleted stopped)))
+ ;; GKqueueFileMonitor does not report the `changed' event.
+ ((eq (file-notify--test-monitor) 'GKqueueFileMonitor)
+ '(deleted stopped))
;; There could be one or two `changed' events.
(t '((changed deleted stopped)
(changed changed deleted stopped))))
@@ -930,51 +1099,55 @@ delivered."
(file-notify--test-cleanup))
(unwind-protect
- (let ((temporary-file-directory
- (make-temp-file "file-notify-test-parent" t)))
- (should
- (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)
- file-notify--test-desc
- (file-notify-add-watch
- temporary-file-directory
- '(change) #'file-notify--test-event-handler)))
- (should (file-notify-valid-p file-notify--test-desc))
- (file-notify--test-with-events
- (cond
- ;; w32notify does not raise `deleted' and `stopped' events
- ;; for the watched directory.
- ((string-equal (file-notify--test-library) "w32notify")
- '(created changed deleted))
- ;; gvfs-monitor-dir on cygwin does not detect the `created'
- ;; event reliably.
- ((string-equal (file-notify--test-library) "gvfs-monitor-dir.exe")
- '((deleted stopped)
- (created deleted stopped)))
- ;; There are two `deleted' events, for the file and for the
- ;; directory. Except for cygwin and kqueue. And cygwin
- ;; does not raise a `changed' event.
- ((eq system-type 'cygwin)
- '(created deleted stopped))
- ((string-equal (file-notify--test-library) "kqueue")
- '(created changed deleted stopped))
- (t '(created changed deleted deleted stopped)))
- (write-region
- "any text" nil file-notify--test-tmpfile nil 'no-message)
- (file-notify--test-read-event)
- (delete-directory temporary-file-directory t))
- ;; After deleting the parent directory, the descriptor must
- ;; not be valid anymore.
- (should-not (file-notify-valid-p file-notify--test-desc))
- ;; w32notify doesn't generate `stopped' events when the parent
- ;; directory is deleted, which doesn't provide a chance for
- ;; filenotify.el to remove the descriptor from the internal
- ;; hash table it maintains. So we must remove the descriptor
- ;; manually.
- (if (string-equal (file-notify--test-library) "w32notify")
- (file-notify--rm-descriptor file-notify--test-desc))
+ ;; On emba, `deleted' and `stopped' events of the directory are
+ ;; not detected.
+ (unless (getenv "EMACS_EMBA_CI")
+ (let ((file-notify--test-tmpdir
+ (make-temp-file "file-notify-test-parent" t)))
+ (should
+ (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)
+ file-notify--test-desc
+ (file-notify--test-add-watch
+ file-notify--test-tmpdir
+ '(change) #'file-notify--test-event-handler)))
+ (should (file-notify-valid-p file-notify--test-desc))
+ (file-notify--test-with-actions
+ (cond
+ ;; w32notify does not raise `deleted' and `stopped'
+ ;; events for the watched directory.
+ ((string-equal (file-notify--test-library) "w32notify")
+ '(created changed deleted))
+ ;; There are two `deleted' events, for the file and for
+ ;; the directory. Except for
+ ;; GFam{File,Directory}Monitor, GPollFileMonitor and
+ ;; kqueue. And GFam{File,Directory}Monitor and
+ ;; GPollfileMonitor do not raise a `changed' event.
+ ((memq (file-notify--test-monitor)
+ '(GFamFileMonitor GFamDirectoryMonitor GPollFileMonitor))
+ '(created deleted stopped))
+ ((string-equal (file-notify--test-library) "kqueue")
+ '(created changed deleted stopped))
+ ;; GKqueueFileMonitor does not report the `changed' event.
+ ((eq (file-notify--test-monitor) 'GKqueueFileMonitor)
+ '(created deleted deleted stopped))
+ (t '(created changed deleted deleted stopped)))
+ (write-region
+ "any text" nil file-notify--test-tmpfile nil 'no-message)
+ (file-notify--test-read-event)
+ (delete-directory file-notify--test-tmpdir 'recursive))
+ ;; After deleting the parent directory, the descriptor must
+ ;; not be valid anymore.
+ (should-not (file-notify-valid-p file-notify--test-desc))
+ ;; w32notify doesn't generate `stopped' events when the
+ ;; parent directory is deleted, which doesn't provide a
+ ;; chance for filenotify.el to remove the descriptor from
+ ;; the internal hash table it maintains. So we must remove
+ ;; the descriptor manually.
+ (if (string-equal (file-notify--test-library) "w32notify")
+ (file-notify--rm-descriptor file-notify--test-desc))
- ;; The environment shall be cleaned up.
- (file-notify--test-cleanup-p))
+ ;; The environment shall be cleaned up.
+ (file-notify--test-cleanup-p)))
;; Cleanup.
(file-notify--test-cleanup)))
@@ -999,11 +1172,11 @@ delivered."
;; After removing the watch, the descriptor must not be valid
;; anymore.
(file-notify-rm-watch file-notify--test-desc)
- (file-notify--wait-for-events
+ (file-notify--test-wait-for-events
(file-notify--test-timeout)
(not (file-notify-valid-p file-notify--test-desc)))
(should-not (file-notify-valid-p file-notify--test-desc))
- (delete-directory file-notify--test-tmpfile t)
+ (delete-directory file-notify--test-tmpfile 'recursive)
;; The environment shall be cleaned up.
(file-notify--test-cleanup-p))
@@ -1012,7 +1185,9 @@ delivered."
(file-notify--test-cleanup))
(unwind-protect
- (progn
+ ;; On emba, `deleted' and `stopped' events of the directory are
+ ;; not detected.
+ (unless (getenv "EMACS_EMBA_CI")
(should
(setq file-notify--test-tmpfile
(make-temp-file "file-notify-test-parent" t)))
@@ -1023,8 +1198,8 @@ delivered."
(should (file-notify-valid-p file-notify--test-desc))
;; After deleting the directory, the descriptor must not be
;; valid anymore.
- (delete-directory file-notify--test-tmpfile t)
- (file-notify--wait-for-events
+ (delete-directory file-notify--test-tmpfile 'recursive)
+ (file-notify--test-wait-for-events
(file-notify--test-timeout)
(not (file-notify-valid-p file-notify--test-desc)))
(should-not (file-notify-valid-p file-notify--test-desc))
@@ -1050,11 +1225,11 @@ delivered."
(make-temp-file "file-notify-test-parent" t)))
(should
(setq file-notify--test-desc
- (file-notify-add-watch
+ (file-notify--test-add-watch
file-notify--test-tmpfile
'(change) #'file-notify--test-event-handler)))
(unwind-protect
- (let ((n 1000)
+ (let ((n 10);00)
source-file-list target-file-list
(default-directory file-notify--test-tmpfile))
(dotimes (i n)
@@ -1067,7 +1242,7 @@ delivered."
(push (expand-file-name (format "y%d" i)) target-file-list))
(push (expand-file-name (format "y%d" i)) source-file-list)
(push (expand-file-name (format "x%d" i)) target-file-list)))
- (file-notify--test-with-events (make-list (+ n n) 'created)
+ (file-notify--test-with-actions (make-list (+ n n) 'created)
(let ((source-file-list source-file-list)
(target-file-list target-file-list))
(while (and source-file-list target-file-list)
@@ -1075,31 +1250,36 @@ delivered."
(write-region "" nil (pop source-file-list) nil 'no-message)
(file-notify--test-read-event)
(write-region "" nil (pop target-file-list) nil 'no-message))))
- (file-notify--test-with-events
+ (file-notify--test-with-actions
(cond
;; w32notify fires both `deleted' and `renamed' events.
((string-equal (file-notify--test-library) "w32notify")
(let (r)
- (dotimes (_i n r)
- (setq r (append '(deleted renamed) r)))))
- ;; cygwin fires `changed' and `deleted' events, sometimes
- ;; in random order.
- ((eq system-type 'cygwin)
+ (dotimes (_i n)
+ (setq r (append '(deleted renamed) r)))
+ r))
+ ;; GFam{File,Directory}Monitor and GPollFileMonitor fire
+ ;; `changed' and `deleted' events, sometimes in random
+ ;; order.
+ ((memq (file-notify--test-monitor)
+ '(GFamFileMonitor GFamDirectoryMonitor GPollFileMonitor))
(let (r)
- (dotimes (_i n (cons :random r))
- (setq r (append '(changed deleted) r)))))
+ (dotimes (_i n)
+ (setq r (append '(changed deleted) r)))
+ (cons :random r)))
(t (make-list n 'renamed)))
(let ((source-file-list source-file-list)
(target-file-list target-file-list))
(while (and source-file-list target-file-list)
(file-notify--test-read-event)
(rename-file (pop source-file-list) (pop target-file-list) t))))
- (file-notify--test-with-events (make-list n 'deleted)
+ (file-notify--test-with-actions (make-list n 'deleted)
(dolist (file target-file-list)
(file-notify--test-read-event)
(delete-file file)))
(delete-directory file-notify--test-tmpfile)
- (if (string-equal (file-notify--test-library) "w32notify")
+ (if (or (string-equal (file-notify--test-library) "w32notify")
+ (getenv "EMACS_EMBA_CI"))
(file-notify--rm-descriptor file-notify--test-desc))
;; The environment shall be cleaned up.
@@ -1108,11 +1288,14 @@ delivered."
;; Cleanup.
(file-notify--test-cleanup)))
+;; Unpredictable failures, eg https://hydra.nixos.org/build/86016286
(file-notify--deftest-remote file-notify-test07-many-events
- "Check that events are not dropped for remote directories.")
+ "Check that events are not dropped for remote directories."
+ (or (getenv "EMACS_HYDRA_CI") (getenv "EMACS_EMBA_CI")))
(ert-deftest file-notify-test08-backup ()
"Check that backup keeps file notification."
+ :tags '(:expensive-test)
(skip-unless (file-notify--test-local-enabled))
(unwind-protect
@@ -1121,14 +1304,17 @@ delivered."
(write-region "any text" nil file-notify--test-tmpfile nil 'no-message)
(should
(setq file-notify--test-desc
- (file-notify-add-watch
+ (file-notify--test-add-watch
file-notify--test-tmpfile
'(change) #'file-notify--test-event-handler)))
(should (file-notify-valid-p file-notify--test-desc))
- (file-notify--test-with-events
- ;; There could be one or two `changed' events.
- '((changed)
- (changed changed))
+ (file-notify--test-with-actions
+ (cond
+ ;; GKqueueFileMonitor does not report the `changed' event.
+ ((eq (file-notify--test-monitor) 'GKqueueFileMonitor) '())
+ ;; There could be one or two `changed' events.
+ (t '((changed)
+ (changed changed))))
;; There shouldn't be any problem, because the file is kept.
(with-temp-buffer
(let ((buffer-file-name file-notify--test-tmpfile)
@@ -1157,14 +1343,20 @@ delivered."
"any text" nil file-notify--test-tmpfile nil 'no-message)
(should
(setq file-notify--test-desc
- (file-notify-add-watch
+ (file-notify--test-add-watch
file-notify--test-tmpfile
'(change) #'file-notify--test-event-handler)))
(should (file-notify-valid-p file-notify--test-desc))
- (file-notify--test-with-events
+ (file-notify--test-with-actions
(cond
- ;; On cygwin we only get the `changed' event.
- ((eq system-type 'cygwin) '(changed))
+ ;; GFam{File,Directory}Monitor and GPollFileMonitor
+ ;; report only the `changed' event.
+ ((memq (file-notify--test-monitor)
+ '(GFamFileMonitor GFamDirectoryMonitor GPollFileMonitor))
+ '(changed))
+ ;; GKqueueFileMonitor does not report the `changed' event.
+ ((eq (file-notify--test-monitor) 'GKqueueFileMonitor)
+ '(renamed created))
(t '(renamed created changed)))
;; The file is renamed when creating a backup. It shall
;; still be watched.
@@ -1197,7 +1389,9 @@ descriptors that were issued when registering the watches. This
test caters for the situation in bug#22736 where the callback for
the directory received events for the file with the descriptor of
the file watch."
- :tags '(:expensive-test)
+ :tags (if (getenv "EMACS_EMBA_CI")
+ '(:expensive-test :unstable)
+ '(:expensive-test))
(skip-unless (file-notify--test-local-enabled))
;; A directory to be watched.
@@ -1207,36 +1401,36 @@ the file watch."
;; A file to be watched.
(should
(setq file-notify--test-tmpfile1
- (let ((temporary-file-directory file-notify--test-tmpfile))
+ (let ((file-notify--test-tmpdir file-notify--test-tmpfile))
(file-notify--test-make-temp-name))))
(write-region "any text" nil file-notify--test-tmpfile1 nil 'no-message)
(unwind-protect
(cl-flet (;; Directory monitor.
- (dir-callback (event)
+ (dir-callback (event file)
(let ((file-notify--test-desc file-notify--test-desc1))
- (file-notify--test-event-handler event)))
+ (file-notify--test-event-handler event file)))
;; File monitor.
- (file-callback (event)
+ (file-callback (event file)
(let ((file-notify--test-desc file-notify--test-desc2))
- (file-notify--test-event-handler event))))
+ (file-notify--test-event-handler event file))))
(should
(setq file-notify--test-desc1
- (file-notify-add-watch
+ (file-notify--test-add-watch
file-notify--test-tmpfile
'(change) #'dir-callback)
;; This is needed for `file-notify--test-monitor'.
file-notify--test-desc file-notify--test-desc1))
(should
(setq file-notify--test-desc2
- (file-notify-add-watch
+ (file-notify--test-add-watch
file-notify--test-tmpfile1
'(change) #'file-callback)))
(should (file-notify-valid-p file-notify--test-desc1))
(should (file-notify-valid-p file-notify--test-desc2))
(should-not (equal file-notify--test-desc1 file-notify--test-desc2))
- (let ((n 100))
+ (let ((n 10));0))
;; Run the test.
- (file-notify--test-with-events
+ (file-notify--test-with-actions
;; There could be one or two `changed' events.
(list
;; cygwin.
@@ -1262,13 +1456,18 @@ the file watch."
(make-list (/ n 2) 'changed)
;; Just the directory monitor.
(make-list (/ n 2) 'created)
- (make-list (/ n 2) 'changed)))
+ (make-list (/ n 2) 'changed))
+ (append
+ '(:random)
+ ;; Just the directory monitor. GKqueueFileMonitor
+ ;; does not report the `changed' event.
+ (make-list (/ n 2) 'created)))
(dotimes (i n)
(file-notify--test-read-event)
(if (zerop (mod i 2))
(write-region
"any text" nil file-notify--test-tmpfile1 t 'no-message)
- (let ((temporary-file-directory file-notify--test-tmpfile))
+ (let ((file-notify--test-tmpdir file-notify--test-tmpfile))
(write-region
"any text" nil
(file-notify--test-make-temp-name) nil 'no-message))))))
@@ -1277,19 +1476,22 @@ the file watch."
;; active. We receive the `deleted' event from both the
;; directory and the file monitor. The `stopped' event is
;; from the file monitor. It's undecided in which order the
- ;; the directory and the file monitor are triggered.
- (file-notify--test-with-events '(:random deleted deleted stopped)
+ ;; directory and the file monitor are triggered.
+ (file-notify--test-with-actions '(:random deleted deleted stopped)
(delete-file file-notify--test-tmpfile1))
(should (file-notify-valid-p file-notify--test-desc1))
(should-not (file-notify-valid-p file-notify--test-desc2))
;; Now we delete the directory.
- (file-notify--test-with-events
+ (file-notify--test-with-actions
(cond
- ;; In kqueue and for cygwin, just one `deleted' event for
- ;; the directory is received.
- ((or (eq system-type 'cygwin)
- (string-equal (file-notify--test-library) "kqueue"))
+ ;; GFam{File,Directory}Monitor, GPollFileMonitor and
+ ;; kqueue raise just one `deleted' event for the
+ ;; directory.
+ ((memq (file-notify--test-monitor)
+ '(GFamFileMonitor GFamDirectoryMonitor GPollFileMonitor))
+ '(deleted stopped))
+ ((string-equal (file-notify--test-library) "kqueue")
'(deleted stopped))
(t (append
;; The directory monitor raises a `deleted' event for
@@ -1305,12 +1507,19 @@ the file watch."
(cond
;; w32notify does not raise `deleted' and `stopped'
;; events for the watched directory.
- ((string-equal (file-notify--test-library) "w32notify") '())
+ ((string-equal (file-notify--test-library) "w32notify")
+ '())
+ ;; On emba, `deleted' and `stopped' events of the
+ ;; directory are not detected.
+ ((getenv "EMACS_EMBA_CI")
+ '())
(t '(deleted stopped))))))
(delete-directory file-notify--test-tmpfile 'recursive))
- (should-not (file-notify-valid-p file-notify--test-desc1))
- (should-not (file-notify-valid-p file-notify--test-desc2))
- (when (string-equal (file-notify--test-library) "w32notify")
+ (unless (getenv "EMACS_EMBA_CI")
+ (should-not (file-notify-valid-p file-notify--test-desc1))
+ (should-not (file-notify-valid-p file-notify--test-desc2)))
+ (when (or (string-equal (file-notify--test-library) "w32notify")
+ (getenv "EMACS_EMBA_CI"))
(file-notify--rm-descriptor file-notify--test-desc1)
(file-notify--rm-descriptor file-notify--test-desc2))
@@ -1320,8 +1529,8 @@ the file watch."
;; Cleanup.
(file-notify--test-cleanup)))
-;(file-notify--deftest-remote file-notify-test09-watched-file-in-watched-dir
-; "Check `file-notify-test09-watched-file-in-watched-dir' for remote files.")
+(file-notify--deftest-remote file-notify-test09-watched-file-in-watched-dir
+ "Check `file-notify-test09-watched-file-in-watched-dir' for remote files." t)
(ert-deftest file-notify-test10-sufficient-resources ()
"Check that file notification does not use too many resources."
@@ -1334,7 +1543,7 @@ the file watch."
(setq file-notify--test-tmpfile
(make-temp-file "file-notify-test-parent" t)))
(unwind-protect
- (let ((temporary-file-directory file-notify--test-tmpfile)
+ (let ((file-notify--test-tmpdir file-notify--test-tmpfile)
descs)
(should-error
(while t
@@ -1367,6 +1576,136 @@ the file watch."
(file-notify--deftest-remote file-notify-test10-sufficient-resources
"Check `file-notify-test10-sufficient-resources' for remote files.")
+(ert-deftest file-notify-test11-symlinks ()
+ "Check that file notification do not follow symbolic links."
+ :tags '(:expensive-test)
+ (skip-unless (file-notify--test-local-enabled))
+ ;; This test does not work for kqueue (yet).
+ (skip-unless (not (string-equal (file-notify--test-library) "kqueue")))
+
+ (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)
+ file-notify--test-tmpfile1 (file-notify--test-make-temp-name))
+
+ ;; Symlink a file.
+ (unwind-protect
+ (progn
+ (write-region "any text" nil file-notify--test-tmpfile1 nil 'no-message)
+ ;; Some systems, like MS Windows w/o sufficient privileges, do
+ ;; not allow creation of symbolic links.
+ (condition-case nil
+ (make-symbolic-link
+ file-notify--test-tmpfile1 file-notify--test-tmpfile)
+ (error (ert-skip "`make-symbolic-link' not supported")))
+ (should
+ (setq file-notify--test-desc
+ (file-notify--test-add-watch
+ file-notify--test-tmpfile
+ '(attribute-change change) #'file-notify--test-event-handler)))
+ (should (file-notify-valid-p file-notify--test-desc))
+
+ ;; Writing to either the symlink or the target should not
+ ;; raise any event.
+ (file-notify--test-with-actions nil
+ (write-region
+ "another text" nil file-notify--test-tmpfile nil 'no-message)
+ (write-region
+ "another text" nil file-notify--test-tmpfile1 nil 'no-message))
+ ;; Sanity check.
+ (file-notify--test-wait-for-events
+ (file-notify--test-timeout)
+ (not (input-pending-p)))
+ (should-not file-notify--test-events)
+
+ ;; Changing timestamp of the target should not raise any
+ ;; event. We don't use `nofollow'.
+ (file-notify--test-with-actions nil
+ (set-file-times file-notify--test-tmpfile1 '(0 0))
+ (set-file-times file-notify--test-tmpfile '(0 0)))
+ ;; Sanity check.
+ (file-notify--test-wait-for-events
+ (file-notify--test-timeout)
+ (not (input-pending-p)))
+ (should-not file-notify--test-events)
+
+ ;; Changing timestamp of the symlink shows the event.
+ (file-notify--test-with-actions
+ (cond
+ ;; w32notify does not distinguish between `changed' and
+ ;; `attribute-changed'.
+ ((string-equal (file-notify--test-library) "w32notify")
+ '(changed))
+ ;; GFam{File,Directory}Monitor, GKqueueFileMonitor and
+ ;; GPollFileMonitor do not report the `attribute-changed'
+ ;; event.
+ ((memq (file-notify--test-monitor)
+ '(GFamFileMonitor GFamDirectoryMonitor
+ GKqueueFileMonitor GPollFileMonitor))
+ '())
+ (t '(attribute-changed)))
+ (set-file-times file-notify--test-tmpfile '(0 0) 'nofollow))
+
+ ;; Deleting the target should not raise any event.
+ (file-notify--test-with-actions nil
+ (delete-file file-notify--test-tmpfile1)
+ (delete-file file-notify--test-tmpfile))
+ ;; Sanity check.
+ (file-notify--test-wait-for-events
+ (file-notify--test-timeout)
+ (not (input-pending-p)))
+ (should-not file-notify--test-events)
+
+ ;; The environment shall be cleaned up.
+ (file-notify-rm-watch file-notify--test-desc)
+ (file-notify--test-cleanup-p))
+
+ ;; Cleanup.
+ (file-notify--test-cleanup))
+
+ (setq file-notify--test-tmpfile1 (file-notify--test-make-temp-name)
+ file-notify--test-tmpfile (file-notify--test-make-temp-name))
+
+ ;; Symlink a directory.
+ (unwind-protect
+ (let ((tmpfile (expand-file-name "foo" file-notify--test-tmpfile))
+ (tmpfile1 (expand-file-name "foo" file-notify--test-tmpfile1)))
+ (make-directory file-notify--test-tmpfile1)
+ (make-symbolic-link file-notify--test-tmpfile1 file-notify--test-tmpfile)
+ (write-region "any text" nil tmpfile1 nil 'no-message)
+ (should
+ (setq file-notify--test-desc
+ (file-notify--test-add-watch
+ file-notify--test-tmpfile
+ '(attribute-change change) #'file-notify--test-event-handler)))
+ (should (file-notify-valid-p file-notify--test-desc))
+
+ ;; None of the actions on a file in the symlinked directory
+ ;; will be reported.
+ (file-notify--test-with-actions nil
+ (write-region "another text" nil tmpfile nil 'no-message)
+ (write-region "another text" nil tmpfile1 nil 'no-message)
+ (set-file-times tmpfile '(0 0))
+ (set-file-times tmpfile '(0 0) 'nofollow)
+ (set-file-times tmpfile1 '(0 0))
+ (set-file-times tmpfile1 '(0 0) 'nofollow)
+ (delete-file tmpfile)
+ (delete-file tmpfile1))
+ ;; Sanity check.
+ (file-notify--test-wait-for-events
+ (file-notify--test-timeout)
+ (not (input-pending-p)))
+ (should-not file-notify--test-events)
+
+ ;; The environment shall be cleaned up.
+ (delete-directory file-notify--test-tmpdir 'recursive)
+ (file-notify-rm-watch file-notify--test-desc)
+ (file-notify--test-cleanup-p))
+
+ ;; Cleanup.
+ (file-notify--test-cleanup)))
+
+(file-notify--deftest-remote file-notify-test11-symlinks
+ "Check `file-notify-test11-symlinks' for remote files.")
+
(defun file-notify-test-all (&optional interactive)
"Run all tests for \\[file-notify]."
(interactive "p")
diff --git a/test/lisp/files-resources/.dir-locals.el b/test/lisp/files-resources/.dir-locals.el
new file mode 100644
index 00000000000..84393aa54d5
--- /dev/null
+++ b/test/lisp/files-resources/.dir-locals.el
@@ -0,0 +1,5 @@
+;; This is used by files-tests.el.
+((auto-mode-alist . (("\\.quux\\'" . tcl-mode)
+ ("\\.zot1\\'" . foobar)
+ ("\\.zot2\\'" . (lambda ()))
+ ("\\.zot3\\'" . dired-mode))))
diff --git a/test/lisp/files-resources/auto-test.zot1 b/test/lisp/files-resources/auto-test.zot1
new file mode 100644
index 00000000000..80acfcc9f7a
--- /dev/null
+++ b/test/lisp/files-resources/auto-test.zot1
@@ -0,0 +1 @@
+zot1
diff --git a/test/lisp/files-resources/auto-test.zot2 b/test/lisp/files-resources/auto-test.zot2
new file mode 100644
index 00000000000..975fc765513
--- /dev/null
+++ b/test/lisp/files-resources/auto-test.zot2
@@ -0,0 +1 @@
+zot2
diff --git a/test/lisp/files-resources/auto-test.zot3 b/test/lisp/files-resources/auto-test.zot3
new file mode 100644
index 00000000000..faa07151606
--- /dev/null
+++ b/test/lisp/files-resources/auto-test.zot3
@@ -0,0 +1 @@
+zot3
diff --git a/test/lisp/files-resources/compile-utf8.el b/test/lisp/files-resources/compile-utf8.el
new file mode 100644
index 00000000000..1f804dcf8dc
--- /dev/null
+++ b/test/lisp/files-resources/compile-utf8.el
@@ -0,0 +1,12 @@
+;; -*- lexical-binding: t; -*-
+(defun zot ()
+ "Yes."
+ nil)
+
+(defun foo ()
+ "Yés."
+ nil)
+
+(defun bar ()
+ "Nó."
+ nil)
diff --git a/test/lisp/files-resources/file-mode b/test/lisp/files-resources/file-mode
new file mode 100644
index 00000000000..92ac4c30ef5
--- /dev/null
+++ b/test/lisp/files-resources/file-mode
@@ -0,0 +1,3 @@
+Local variables:
+mode: text
+end:
diff --git a/test/lisp/files-resources/file-mode-multiple b/test/lisp/files-resources/file-mode-multiple
new file mode 100644
index 00000000000..ac051ccbcbd
--- /dev/null
+++ b/test/lisp/files-resources/file-mode-multiple
@@ -0,0 +1,5 @@
+Local variables:
+mode: text
+mode: test-mode-undef
+mode: outline
+end:
diff --git a/test/lisp/files-resources/file-mode-prop-line b/test/lisp/files-resources/file-mode-prop-line
new file mode 100644
index 00000000000..e0e7ad24d71
--- /dev/null
+++ b/test/lisp/files-resources/file-mode-prop-line
@@ -0,0 +1 @@
+-*- mode: notexist; mode: text -*-
diff --git a/test/data/files-bug18141.el.gz b/test/lisp/files-resources/files-bug18141.el.gz
index 53d463e85b5..53d463e85b5 100644
--- a/test/data/files-bug18141.el.gz
+++ b/test/lisp/files-resources/files-bug18141.el.gz
Binary files differ
diff --git a/test/lisp/files-resources/whatever.quux b/test/lisp/files-resources/whatever.quux
new file mode 100644
index 00000000000..595583b911e
--- /dev/null
+++ b/test/lisp/files-resources/whatever.quux
@@ -0,0 +1,2 @@
+# Used by files-test.el.
+# Due to .dir-locals.el this should end up in Tcl mode.
diff --git a/test/lisp/files-tests.el b/test/lisp/files-tests.el
index 285a884b695..682b5cdb449 100644
--- a/test/lisp/files-tests.el
+++ b/test/lisp/files-tests.el
@@ -1,6 +1,6 @@
;;; files-tests.el --- tests for files.el. -*- lexical-binding: t; -*-
-;; Copyright (C) 2012-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2022 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -20,7 +20,12 @@
;;; Code:
(require 'ert)
+(require 'ert-x)
(require 'nadvice)
+(eval-when-compile (require 'cl-lib))
+(require 'bytecomp) ; `byte-compiler-base-file-name'.
+(require 'dired) ; `dired-uncache'.
+(require 'filenotify) ; `file-notify-add-watch'.
;; Set to t if the local variable was set, `query' if the query was
;; triggered.
@@ -131,41 +136,56 @@ form.")
;; Prevent any dir-locals file interfering with the tests.
(enable-dir-local-variables nil))
(hack-local-variables)
- (eval (nth 2 test-settings)))))
+ (eval (nth 2 test-settings) t))))
-(ert-deftest files-test-local-variables ()
+(ert-deftest files-tests-local-variables ()
"Test the file-local variables implementation."
- (unwind-protect
- (progn
- (defadvice hack-local-variables-confirm (around files-test activate)
- (setq files-test-result 'query)
- nil)
- (dolist (test files-test-local-variable-data)
- (let ((str (concat "text\n\n;; Local Variables:\n;; "
- (mapconcat 'identity (car test) "\n;; ")
- "\n;; End:\n")))
- (dolist (subtest (cdr test))
- (should (file-test--do-local-variables-test str subtest))))))
- (ad-disable-advice 'hack-local-variables-confirm 'around 'files-test)))
+ (cl-letf (((symbol-function 'hack-local-variables-confirm)
+ (lambda (&rest _)
+ (setq files-test-result 'query)
+ nil)))
+ (dolist (test files-test-local-variable-data)
+ (let ((str (concat "text\n\n;; Local Variables:\n;; "
+ (mapconcat 'identity (car test) "\n;; ")
+ "\n;; End:\n")))
+ (dolist (subtest (cdr test))
+ (should (file-test--do-local-variables-test str subtest)))))))
+
+(ert-deftest files-tests-permanent-local-variables ()
+ (let ((enable-local-variables nil))
+ (with-temp-buffer
+ (setq lexical-binding nil)
+ (insert ";;; test-test.el --- tests -*- lexical-binding: t; -*-\n\n")
+ (hack-local-variables)
+ (should (eq lexical-binding t))))
+ (let ((enable-local-variables nil)
+ (permanently-enabled-local-variables nil))
+ (with-temp-buffer
+ (setq lexical-binding nil)
+ (insert ";;; test-test.el --- tests -*- lexical-binding: t; -*-\n\n")
+ (hack-local-variables)
+ (should (eq lexical-binding nil)))))
(defvar files-test-bug-18141-file
- (expand-file-name "data/files-bug18141.el.gz" (getenv "EMACS_TEST_DIRECTORY"))
+ (ert-resource-file "files-bug18141.el.gz")
"Test file for bug#18141.")
-(ert-deftest files-test-bug-18141 ()
+(ert-deftest files-tests-bug-18141 ()
"Test for https://debbugs.gnu.org/18141 ."
(skip-unless (executable-find "gzip"))
- (let ((tempfile (make-temp-file "files-test-bug-18141" nil ".gz")))
- (unwind-protect
- (progn
- (copy-file files-test-bug-18141-file tempfile t)
- (with-current-buffer (find-file-noselect tempfile)
- (set-buffer-modified-p t)
- (save-buffer)
- (should (eq buffer-file-coding-system 'iso-2022-7bit-unix))))
- (delete-file tempfile))))
-
-(ert-deftest files-test-make-temp-file-empty-prefix ()
+ ;; If called interactively, environment variable
+ ;; $EMACS_TEST_DIRECTORY does not exist.
+ (skip-unless (file-exists-p files-test-bug-18141-file))
+ (ert-with-temp-file tempfile
+ :prefix "emacs-test-files-bug-18141"
+ :suffix ".gz"
+ (copy-file files-test-bug-18141-file tempfile t)
+ (with-current-buffer (find-file-noselect tempfile)
+ (set-buffer-modified-p t)
+ (save-buffer)
+ (should (eq buffer-file-coding-system 'iso-2022-7bit-unix)))))
+
+(ert-deftest files-tests-make-temp-file-empty-prefix ()
"Test make-temp-file with an empty prefix."
(let ((tempfile (make-temp-file ""))
(tempdir (make-temp-file "" t))
@@ -183,18 +203,59 @@ form.")
;; Stop the above "Local Var..." confusing Emacs.
-(ert-deftest files-test-bug-21454 ()
+(ert-deftest files-tests-bug-21454 ()
"Test for https://debbugs.gnu.org/21454 ."
- :expected-result :failed
(let ((input-result
- '(("/foo/bar//baz/:/bar/foo/baz//" nil ("/foo/bar/baz/" "/bar/foo/baz/"))
- ("/foo/bar/:/bar/qux/:/qux/foo" nil ("/foo/bar/" "/bar/qux/" "/qux/foo/"))
- ("//foo/bar/:/bar/qux/:/qux/foo/" nil ("/foo/bar/" "/bar/qux/" "/qux/foo/"))
- ("/foo/bar/:/bar/qux/:/qux/foo/" nil ("/foo/bar/" "/bar/qux/" "/qux/foo/"))
- ("/foo//bar/:/bar/qux/:/qux/foo/" nil ("/foo/bar/" "/bar/qux/" "/qux/foo/"))
- ("/foo//bar/:/bar/qux/:/qux/foo" nil ("/foo/bar/" "/bar/qux/" "/qux/foo/"))
- ("/foo/bar" "$FOO/baz/:/qux/foo/" ("/foo/bar/baz/" "/qux/foo/"))
- ("//foo/bar/" "$FOO/baz/:/qux/foo/" ("/foo/bar/baz/" "/qux/foo/"))))
+ (if (memq system-type '(windows-nt ms-dos))
+ '(("/foo/bar//baz/;/bar/foo/baz//" nil
+ ("/foo/bar//baz/" "/bar/foo/baz//"))
+ ("x:/foo/bar/;y:/bar/qux/;z:/qux/foo" nil
+ ("x:/foo/bar/" "y:/bar/qux/" "z:/qux/foo/"))
+ ("x://foo/bar/;y:/bar/qux/;z:/qux/foo/" nil
+ ("x://foo/bar/" "y:/bar/qux/" "z:/qux/foo/"))
+ ("x:/foo/bar/;y:/bar/qux/;z:/qux/foo/" nil
+ ("x:/foo/bar/" "y:/bar/qux/" "z:/qux/foo/"))
+ ("x:/foo//bar/;y:/bar/qux/;z:/qux/foo/" nil
+ ("x:/foo//bar/" "y:/bar/qux/" "z:/qux/foo/"))
+ ("x:/foo//bar/;y:/bar/qux/;z:/qux/foo" nil
+ ("x:/foo//bar/" "y:/bar/qux/" "z:/qux/foo/"))
+ ("x:/foo/bar" "$FOO/baz/;z:/qux/foo/"
+ ("x:/foo/bar/baz/" "z:/qux/foo/"))
+ ("///foo/bar/" "$FOO/baz/;/qux/foo/"
+ ("//foo/bar//baz/" "/qux/foo/")))
+ (if (eq system-type 'cygwin)
+ '(("/foo/bar//baz/:/bar/foo/baz//" nil
+ ("/foo/bar//baz/" "/bar/foo/baz//"))
+ ("/foo/bar/:/bar/qux/:/qux/foo" nil
+ ("/foo/bar/" "/bar/qux/" "/qux/foo/"))
+ ("//foo/bar/:/bar/qux/:/qux/foo/" nil
+ ("//foo/bar/" "/bar/qux/" "/qux/foo/"))
+ ("/foo/bar/:/bar/qux/:/qux/foo/" nil
+ ("/foo/bar/" "/bar/qux/" "/qux/foo/"))
+ ("/foo//bar/:/bar/qux/:/qux/foo/" nil
+ ("/foo//bar/" "/bar/qux/" "/qux/foo/"))
+ ("/foo//bar/:/bar/qux/:/qux/foo" nil
+ ("/foo//bar/" "/bar/qux/" "/qux/foo/"))
+ ("/foo/bar" "$FOO/baz/:/qux/foo/"
+ ("/foo/bar/baz/" "/qux/foo/"))
+ ("///foo/bar/" "$FOO/baz/:/qux/foo/"
+ ("//foo/bar//baz/" "/qux/foo/")))
+ '(("/foo/bar//baz/:/bar/foo/baz//" nil
+ ("/foo/bar//baz/" "/bar/foo/baz//"))
+ ("/foo/bar/:/bar/qux/:/qux/foo" nil
+ ("/foo/bar/" "/bar/qux/" "/qux/foo/"))
+ ("//foo/bar/:/bar/qux/:/qux/foo/" nil
+ ("/foo/bar/" "/bar/qux/" "/qux/foo/"))
+ ("/foo/bar/:/bar/qux/:/qux/foo/" nil
+ ("/foo/bar/" "/bar/qux/" "/qux/foo/"))
+ ("/foo//bar/:/bar/qux/:/qux/foo/" nil
+ ("/foo//bar/" "/bar/qux/" "/qux/foo/"))
+ ("/foo//bar/:/bar/qux/:/qux/foo" nil
+ ("/foo//bar/" "/bar/qux/" "/qux/foo/"))
+ ("/foo/bar" "$FOO/baz/:/qux/foo/"
+ ("/foo/bar/baz/" "/qux/foo/"))
+ ("//foo/bar/" "$FOO/baz/:/qux/foo/"
+ ("/foo/bar//baz/" "/qux/foo/"))))))
(foo-env (getenv "FOO"))
(bar-env (getenv "BAR")))
(unwind-protect
@@ -211,7 +272,7 @@ form.")
(setenv "FOO" foo-env)
(setenv "BAR" bar-env))))
-(ert-deftest files-test--save-buffers-kill-emacs--confirm-kill-processes ()
+(ert-deftest files-tests-save-buffers-kill-emacs--confirm-kill-processes ()
"Test that `save-buffers-kill-emacs' honors
`confirm-kill-processes'."
(cl-letf* ((yes-or-no-p-prompts nil)
@@ -221,7 +282,7 @@ form.")
nil))
(kill-emacs-args nil)
((symbol-function #'kill-emacs)
- (lambda (&optional arg) (push arg kill-emacs-args)))
+ (lambda (&rest args) (push args kill-emacs-args)))
(process
(make-process
:name "sleep"
@@ -232,39 +293,57 @@ form.")
(save-buffers-kill-emacs)
(kill-process process)
(should-not yes-or-no-p-prompts)
- (should (equal kill-emacs-args '(nil)))))
+ (should (equal kill-emacs-args '((nil nil))))))
-(ert-deftest files-test-read-file-in-~ ()
- "Test file prompting in directory named '~'.
-If we are in a directory named '~', the default value should not
+(ert-deftest files-tests-read-file-in-~ ()
+ "Test file prompting in directory named `~'.
+If we are in a directory named `~', the default value should not
be $HOME."
(cl-letf (((symbol-function 'completing-read)
(lambda (_prompt _coll &optional _pred _req init _hist def _)
- (or def init)))
- (dir (make-temp-file "read-file-name-test" t)))
- (unwind-protect
- (let ((subdir (expand-file-name "./~/" dir)))
- (make-directory subdir t)
- (with-temp-buffer
- (setq default-directory subdir)
- (should-not (equal
- (expand-file-name (read-file-name "File: "))
- (expand-file-name "~/")))
- ;; Don't overquote either!
- (setq default-directory (concat "/:" subdir))
- (should-not (equal
- (expand-file-name (read-file-name "File: "))
- (concat "/:/:" subdir)))))
- (delete-directory dir 'recursive))))
+ (or def init))))
+ (ert-with-temp-directory dir
+ (let ((subdir (expand-file-name "./~/" dir)))
+ (make-directory subdir t)
+ (with-temp-buffer
+ (setq default-directory subdir)
+ (should-not (equal
+ (expand-file-name (read-file-name "File: "))
+ (expand-file-name "~/")))
+ ;; Don't overquote either!
+ (setq default-directory (concat "/:" subdir))
+ (should-not (equal
+ (expand-file-name (read-file-name "File: "))
+ (concat "/:/:" subdir))))))))
+
+(ert-deftest files-tests-file-name-non-special-quote-unquote ()
+ (let (;; Just in case it is quoted, who knows.
+ (temporary-file-directory (file-name-unquote temporary-file-directory)))
+ (should-not (file-name-quoted-p temporary-file-directory))
+ (should (file-name-quoted-p (file-name-quote temporary-file-directory)))
+ (should (equal temporary-file-directory
+ (file-name-unquote
+ (file-name-quote temporary-file-directory))))
+ ;; It does not hurt to quote/unquote a file several times.
+ (should (equal (file-name-quote temporary-file-directory)
+ (file-name-quote
+ (file-name-quote temporary-file-directory))))
+ (should (equal (file-name-unquote temporary-file-directory)
+ (file-name-unquote
+ (file-name-unquote temporary-file-directory))))))
-(ert-deftest files-tests--file-name-non-special--subprocess ()
- "Check that Bug#25949 is fixed."
- (skip-unless (executable-find "true"))
- (let ((defdir (if (memq system-type '(ms-dos windows-nt)) "/:c:/" "/:/")))
- (should (eq (let ((default-directory defdir)) (process-file "true")) 0))
- (should (processp (let ((default-directory defdir))
- (start-file-process "foo" nil "true"))))
- (should (eq (let ((default-directory defdir)) (shell-command "true")) 0))))
+(ert-deftest files-tests-file-name-non-special--subprocess ()
+ "Check that Bug#25949 and Bug#48177 are fixed."
+ (skip-unless (and (executable-find "true") (file-exists-p null-device)
+ ;; These systems cannot set date of the null device.
+ (not (memq system-type '(windows-nt ms-dos)))))
+ (let ((default-directory (file-name-quote temporary-file-directory))
+ (true (file-name-quote (executable-find "true")))
+ (null (file-name-quote null-device)))
+ (should (zerop (process-file true null `((:file ,null) ,null))))
+ (should (processp (start-file-process "foo" nil true)))
+ (should (zerop (shell-command true)))
+ (should (processp (make-process :name "foo" :command `(,true))))))
(defmacro files-tests--with-advice (symbol where function &rest body)
(declare (indent 3))
@@ -278,15 +357,7 @@ be $HOME."
(progn ,@body)
(advice-remove #',symbol ,function)))))
-(defmacro files-tests--with-temp-file (name &rest body)
- (declare (indent 1))
- (cl-check-type name symbol)
- `(let ((,name (make-temp-file "emacs")))
- (unwind-protect
- (progn ,@body)
- (delete-file ,name))))
-
-(ert-deftest files-tests--file-name-non-special--buffers ()
+(ert-deftest files-tests-file-name-non-special--buffers ()
"Check that Bug#25951 is fixed.
We call `verify-visited-file-modtime' on a buffer visiting a file
with a quoted name. We use two different variants: first with
@@ -294,13 +365,15 @@ the buffer current and a nil argument, second passing the buffer
object explicitly. In both cases no error should be raised and
the `file-name-non-special' handler for quoted file names should
be invoked with the right arguments."
- (files-tests--with-temp-file temp-file-name
+ (ert-with-temp-file temp-file-name
(with-temp-buffer
(let* ((buffer-visiting-file (current-buffer))
(actual-args ())
(log (lambda (&rest args) (push args actual-args))))
- (insert-file-contents (concat "/:" temp-file-name) :visit)
+ (insert-file-contents (file-name-quote temp-file-name) :visit)
(should (stringp buffer-file-name))
+ (should (file-name-quoted-p buffer-file-name))
+ ;; The following is not true for remote files.
(should (string-prefix-p "/:" buffer-file-name))
(should (consp (visited-file-modtime)))
(should (equal (find-file-name-handler buffer-file-name
@@ -327,7 +400,853 @@ be invoked with the right arguments."
`((verify-visited-file-modtime ,buffer-visiting-file)
(verify-visited-file-modtime nil))))))))
-(ert-deftest files-tests--insert-directory-wildcard-in-dir-p ()
+(cl-defmacro files-tests--with-temp-non-special
+ ((name non-special-name &optional dir-flag) &rest body)
+ "Run tests with quoted file name.
+NAME is the symbol which contains the name of a created temporary
+file. NON-SPECIAL-NAME is another symbol, which contains the
+temporary file name with quoted file name syntax. If DIR-FLAG is
+non-nil, a temporary directory is created instead.
+After evaluating BODY, the temporary file or directory is deleted."
+ (declare (indent 1) (debug ((symbolp symbolp &optional form) body)))
+ (cl-check-type name symbol)
+ (cl-check-type non-special-name symbol)
+ `(let* ((temporary-file-directory (file-truename temporary-file-directory))
+ (temporary-file-directory
+ (file-name-as-directory (make-temp-file "files-tests" t)))
+ (,name (make-temp-file "files-tests" ,dir-flag))
+ (,non-special-name (file-name-quote ,name)))
+ (unwind-protect
+ (progn ,@body)
+ (when (file-exists-p ,name)
+ (if ,dir-flag (delete-directory ,name t)
+ (delete-file ,name)))
+ (when (file-exists-p ,non-special-name)
+ (if ,dir-flag (delete-directory ,non-special-name t)
+ (delete-file ,non-special-name)))
+ (when (file-exists-p temporary-file-directory)
+ (delete-directory temporary-file-directory t)))))
+
+(defconst files-tests--special-file-name-extension ".special"
+ "Trailing string for test file name handler.")
+
+(defconst files-tests--special-file-name-regexp
+ (concat (regexp-quote files-tests--special-file-name-extension) "\\'")
+ "Regular expression for test file name handler.")
+
+(defun files-tests--special-file-name-handler (operation &rest args)
+ "File name handler for files with extension \".special\"."
+ (let ((arg args)
+ ;; Avoid cyclic call.
+ (file-name-handler-alist
+ (delete
+ (rassoc
+ 'files-tests--special-file-name-handler file-name-handler-alist)
+ file-name-handler-alist)))
+ ;; Remove trailing "\\.special\\'" from arguments, if they are not quoted.
+ (while arg
+ (when (and (stringp (car arg))
+ (not (file-name-quoted-p (car arg)))
+ (string-match files-tests--special-file-name-regexp (car arg)))
+ (setcar arg (replace-match "" nil nil (car arg))))
+ (setq arg (cdr arg)))
+ ;; Call it.
+ (apply operation args)))
+
+(cl-defmacro files-tests--with-temp-non-special-and-file-name-handler
+ ((name non-special-name &optional dir-flag) &rest body)
+ "Run tests with quoted file name, see `files-tests--with-temp-non-special'.
+Both file names in NAME and NON-SPECIAL-NAME have the extension
+\".special\". The created temporary file or directory does not have
+that extension.
+A file name handler is added which is activated for files with
+that extension. It simply removes the extension from file names.
+It is expected, that this file name handler works only for
+unquoted file names."
+ (declare (indent 1) (debug ((symbolp symbolp &optional form) body)))
+ (cl-check-type name symbol)
+ (cl-check-type non-special-name symbol)
+ `(let* ((temporary-file-directory (file-truename temporary-file-directory))
+ (temporary-file-directory
+ (file-name-as-directory (make-temp-file "files-tests" t)))
+ (file-name-handler-alist
+ `((,files-tests--special-file-name-regexp
+ . files-tests--special-file-name-handler)
+ . ,file-name-handler-alist))
+ (,name (concat
+ (make-temp-file "files-tests" ,dir-flag)
+ files-tests--special-file-name-extension))
+ (,non-special-name (file-name-quote ,name)))
+ (unwind-protect
+ (progn ,@body)
+ (when (file-exists-p ,name)
+ (if ,dir-flag (delete-directory ,name t)
+ (delete-file ,name)))
+ (when (file-exists-p ,non-special-name)
+ (if ,dir-flag (delete-directory ,non-special-name t)
+ (delete-file ,non-special-name)))
+ (when (file-exists-p temporary-file-directory)
+ (delete-directory temporary-file-directory t)))))
+
+(defun files-tests--new-name (name part)
+ (let (file-name-handler-alist)
+ (concat (file-name-sans-extension name) part (file-name-extension name t))))
+
+(ert-deftest files-tests-file-name-non-special-abbreviate-file-name ()
+ (let* ((homedir temporary-file-directory)
+ (process-environment (cons (format "HOME=%s" homedir)
+ process-environment))
+ (abbreviated-home-dir nil))
+ ;; Check that abbreviation doesn't occur for quoted file names.
+ (should (equal (concat "/:" homedir "foo/bar")
+ (abbreviate-file-name (concat "/:" homedir "foo/bar"))))))
+
+(ert-deftest files-tests-file-name-non-special-access-file ()
+ (files-tests--with-temp-non-special (tmpfile nospecial)
+ ;; Both versions of the file name work.
+ (should-not (access-file tmpfile "test"))
+ (should-not (access-file nospecial "test")))
+ (files-tests--with-temp-non-special-and-file-name-handler (tmpfile nospecial)
+ (should-not (access-file tmpfile "test"))
+ ;; The quoted file name does not work.
+ (should-error (access-file nospecial "test"))))
+
+(ert-deftest files-tests-file-name-non-special-add-name-to-file ()
+ (files-tests--with-temp-non-special (tmpfile nospecial)
+ (let ((newname (files-tests--new-name nospecial "add-name")))
+ ;; Both versions work.
+ (add-name-to-file tmpfile newname)
+ (should (file-exists-p newname))
+ (delete-file newname)
+ (add-name-to-file nospecial newname)
+ (should (file-exists-p newname))
+ (delete-file newname)))
+ (files-tests--with-temp-non-special-and-file-name-handler (tmpfile nospecial)
+ (let ((newname (files-tests--new-name tmpfile "add-name")))
+ ;; Using an unquoted file name works.
+ (add-name-to-file tmpfile newname)
+ (should (file-exists-p newname))
+ (delete-file newname))
+ (let ((newname (files-tests--new-name nospecial "add-name")))
+ (add-name-to-file tmpfile newname)
+ (should (file-exists-p newname))
+ (delete-file newname)
+ ;; The quoted special file name does not work.
+ (should-error (add-name-to-file nospecial newname)))))
+
+(ert-deftest files-tests-file-name-non-special-byte-compiler-base-file-name ()
+ (files-tests--with-temp-non-special (tmpfile nospecial)
+ (should (equal (byte-compiler-base-file-name nospecial)
+ (byte-compiler-base-file-name tmpfile))))
+ (files-tests--with-temp-non-special-and-file-name-handler (tmpfile nospecial)
+ (should (equal (byte-compiler-base-file-name nospecial) tmpfile))
+ (should-not (equal (byte-compiler-base-file-name tmpfile) tmpfile))))
+
+(ert-deftest files-tests-file-name-non-special-copy-directory ()
+ (files-tests--with-temp-non-special (tmpdir nospecial-dir t)
+ (let ((newname (files-tests--new-name
+ (directory-file-name nospecial-dir) "copy-dir")))
+ (copy-directory nospecial-dir newname)
+ (should (file-directory-p newname))
+ (delete-directory newname)
+ (should-not (file-directory-p newname))))
+ (files-tests--with-temp-non-special-and-file-name-handler
+ (tmpdir nospecial-dir t)
+ (let ((newname (files-tests--new-name
+ (directory-file-name nospecial-dir) "copy-dir")))
+ (should-error (copy-directory nospecial-dir newname))
+ (delete-directory newname))))
+
+(ert-deftest files-tests-file-name-non-special-copy-file ()
+ (files-tests--with-temp-non-special (tmpfile nospecial)
+ (let ((newname
+ (files-tests--new-name (directory-file-name nospecial) "copy-file")))
+ (copy-file nospecial newname)
+ (should (file-exists-p newname))
+ (delete-file newname)
+ (should-not (file-exists-p newname))))
+ (files-tests--with-temp-non-special-and-file-name-handler (tmpfile nospecial)
+ (let ((newname
+ (files-tests--new-name (directory-file-name nospecial) "copy-file")))
+ (should-error (copy-file nospecial newname)))))
+
+(ert-deftest files-tests-file-name-non-special-delete-directory ()
+ (files-tests--with-temp-non-special (tmpdir nospecial-dir t)
+ (delete-directory nospecial-dir))
+ (files-tests--with-temp-non-special-and-file-name-handler
+ (tmpdir nospecial-dir t)
+ (should-error (delete-directory nospecial-dir))))
+
+(ert-deftest files-tests-file-name-non-special-delete-file ()
+ (files-tests--with-temp-non-special (tmpfile nospecial)
+ (delete-file nospecial))
+ (files-tests--with-temp-non-special-and-file-name-handler (tmpfile nospecial)
+ (delete-file nospecial)
+ (should (file-exists-p tmpfile))))
+
+(ert-deftest files-tests-file-name-non-special-diff-latest-backup-file ()
+ (files-tests--with-temp-non-special (tmpfile nospecial)
+ (write-region "foo" nil (make-backup-file-name tmpfile))
+ (should (equal (diff-latest-backup-file nospecial)
+ (diff-latest-backup-file tmpfile)))
+ (delete-file (diff-latest-backup-file nospecial)))
+ (files-tests--with-temp-non-special-and-file-name-handler (tmpfile nospecial)
+ (write-region "foo" nil (make-backup-file-name tmpfile))
+ (should-not (equal (diff-latest-backup-file nospecial)
+ (diff-latest-backup-file tmpfile)))
+ (delete-file (diff-latest-backup-file nospecial))))
+
+(ert-deftest files-tests-file-name-non-special-directory-file-name ()
+ (files-tests--with-temp-non-special (tmpdir nospecial-dir t)
+ (should (equal (directory-file-name nospecial-dir)
+ (file-name-quote (directory-file-name tmpdir)))))
+ (files-tests--with-temp-non-special-and-file-name-handler
+ (tmpdir nospecial-dir t)
+ (should-not (equal (directory-file-name nospecial-dir)
+ (file-name-quote (directory-file-name tmpdir))))))
+
+(ert-deftest files-tests-file-name-non-special-directory-files ()
+ (files-tests--with-temp-non-special (tmpdir nospecial-dir t)
+ (should (equal (directory-files nospecial-dir)
+ (directory-files tmpdir))))
+ (files-tests--with-temp-non-special-and-file-name-handler
+ (tmpdir nospecial-dir t)
+ (should-error (directory-files nospecial-dir))))
+
+(defun files-tests-file-attributes-equal (attr1 attr2)
+ ;; Element 4 is access time, which may be changed by the act of
+ ;; checking the attributes.
+ (setf (nth 4 attr1) nil)
+ (setf (nth 4 attr2) nil)
+ ;; Element 9 is unspecified.
+ (setf (nth 9 attr1) nil)
+ (setf (nth 9 attr2) nil)
+ (equal attr1 attr2))
+
+(ert-deftest files-tests-file-name-non-special-directory-files-and-attributes ()
+ (files-tests--with-temp-non-special (tmpdir nospecial-dir t)
+ (cl-loop for (file1 . attr1) in (directory-files-and-attributes nospecial-dir)
+ for (file2 . attr2) in (directory-files-and-attributes tmpdir)
+ do
+ (should (equal file1 file2))
+ (should (files-tests-file-attributes-equal attr1 attr2))))
+ (files-tests--with-temp-non-special-and-file-name-handler
+ (tmpdir nospecial-dir t)
+ (should-error (directory-files-and-attributes nospecial-dir))))
+
+(ert-deftest files-tests-file-name-non-special-dired-compress-handler ()
+ ;; `dired-compress-file' can get confused by filenames with ":" in
+ ;; them, which causes this to fail on `windows-nt' systems.
+ (when (string-search ":" (expand-file-name temporary-file-directory))
+ (ert-skip "FIXME: `dired-compress-file' unreliable when filenames contain `:'."))
+ (files-tests--with-temp-non-special (tmpfile nospecial)
+ (let ((compressed (dired-compress-file nospecial)))
+ (when compressed
+ ;; FIXME: Should it return a still-quoted name?
+ (should (file-equal-p nospecial (dired-compress-file compressed))))))
+ (files-tests--with-temp-non-special-and-file-name-handler (tmpfile nospecial)
+ (should-not (dired-compress-file nospecial))))
+
+(ert-deftest files-tests-file-name-non-special-dired-uncache ()
+ ;; FIXME: This is not a real test. We need cached values, and check
+ ;; whether they disappear.
+ (files-tests--with-temp-non-special (tmpdir nospecial-dir t)
+ (dired-uncache nospecial-dir))
+ (files-tests--with-temp-non-special-and-file-name-handler
+ (tmpdir nospecial-dir t)
+ (dired-uncache nospecial-dir)))
+
+(ert-deftest files-tests-file-name-non-special-expand-file-name ()
+ (files-tests--with-temp-non-special (tmpfile nospecial)
+ (should (equal (expand-file-name nospecial) nospecial)))
+ (files-tests--with-temp-non-special-and-file-name-handler (tmpfile nospecial)
+ (should (equal (expand-file-name nospecial) nospecial))))
+
+(ert-deftest files-tests-file-name-non-special-file-accessible-directory-p ()
+ (files-tests--with-temp-non-special (tmpdir nospecial-dir t)
+ (should (file-accessible-directory-p nospecial-dir)))
+ (files-tests--with-temp-non-special-and-file-name-handler
+ (tmpdir nospecial-dir t)
+ (should-not (file-accessible-directory-p nospecial-dir))))
+
+(ert-deftest files-tests-file-name-non-special-file-acl ()
+ (files-tests--with-temp-non-special (tmpfile nospecial)
+ (should (equal (file-acl nospecial) (file-acl tmpfile))))
+ (files-tests--with-temp-non-special-and-file-name-handler (tmpfile nospecial)
+ (should-not (file-acl nospecial))))
+
+(ert-deftest files-tests-file-name-non-special-file-attributes ()
+ (files-tests--with-temp-non-special (tmpfile nospecial)
+ (should (files-tests-file-attributes-equal
+ (file-attributes nospecial) (file-attributes tmpfile))))
+ (files-tests--with-temp-non-special-and-file-name-handler (tmpfile nospecial)
+ (should-not (file-attributes nospecial))))
+
+(ert-deftest files-tests-file-name-non-special-file-directory-p ()
+ (files-tests--with-temp-non-special (tmpdir nospecial-dir t)
+ (should (file-directory-p nospecial-dir)))
+ (files-tests--with-temp-non-special-and-file-name-handler
+ (tmpdir nospecial-dir t)
+ (should-not (file-directory-p nospecial-dir))))
+
+(ert-deftest files-tests-file-name-non-special-file-equal-p ()
+ (files-tests--with-temp-non-special (tmpfile nospecial)
+ (should (file-equal-p nospecial tmpfile))
+ (should (file-equal-p tmpfile nospecial))
+ (should (file-equal-p nospecial nospecial)))
+ (files-tests--with-temp-non-special-and-file-name-handler (tmpfile nospecial)
+ (should (file-equal-p (file-name-unquote nospecial) tmpfile))
+ (should (file-equal-p tmpfile (file-name-unquote nospecial)))
+ ;; File `nospecial' does not exist, so it cannot be compared.
+ (should-not (file-equal-p nospecial nospecial))
+ (write-region "foo" nil nospecial)
+ (should (file-equal-p nospecial nospecial))))
+
+(ert-deftest files-tests-file-name-non-special-file-executable-p ()
+ (files-tests--with-temp-non-special (tmpfile nospecial)
+ (should-not (file-executable-p nospecial)))
+ (files-tests--with-temp-non-special-and-file-name-handler (tmpfile nospecial)
+ (should-not (file-executable-p nospecial))))
+
+(ert-deftest files-tests-file-name-non-special-file-exists-p ()
+ (files-tests--with-temp-non-special (tmpfile nospecial)
+ (should (file-exists-p tmpfile))
+ (should (file-exists-p nospecial)))
+ (files-tests--with-temp-non-special-and-file-name-handler (tmpfile nospecial)
+ (should (file-exists-p tmpfile))
+ (should-not (file-exists-p nospecial))))
+
+(ert-deftest files-tests-file-name-non-special-file-in-directory-p ()
+ (files-tests--with-temp-non-special (tmpfile nospecial)
+ (let ((nospecial-tempdir (file-name-quote temporary-file-directory)))
+ (should (file-in-directory-p nospecial temporary-file-directory))
+ (should (file-in-directory-p tmpfile nospecial-tempdir))
+ (should (file-in-directory-p nospecial nospecial-tempdir))))
+ (files-tests--with-temp-non-special-and-file-name-handler (tmpfile nospecial)
+ (let ((nospecial-tempdir (file-name-quote temporary-file-directory)))
+ (should (file-in-directory-p nospecial temporary-file-directory))
+ (should (file-in-directory-p tmpfile nospecial-tempdir))
+ (should (file-in-directory-p nospecial nospecial-tempdir)))))
+
+(ert-deftest files-tests-file-name-non-special-file-local-copy ()
+ (files-tests--with-temp-non-special (tmpfile nospecial)
+ (should-not (file-local-copy nospecial))) ; Already local.
+ (files-tests--with-temp-non-special-and-file-name-handler (tmpfile nospecial)
+ (should-not (file-local-copy nospecial)))) ; Already local.
+
+(ert-deftest files-tests-file-name-non-special-file-modes ()
+ (files-tests--with-temp-non-special (tmpfile nospecial)
+ (should (equal (file-modes nospecial) (file-modes tmpfile))))
+ (files-tests--with-temp-non-special-and-file-name-handler (tmpfile nospecial)
+ (should-not (equal (file-modes nospecial) (file-modes tmpfile)))))
+
+(ert-deftest files-tests-file-name-non-special-file-name-all-completions ()
+ (files-tests--with-temp-non-special (tmpfile nospecial)
+ (let ((nospecial-tempdir (file-name-quote temporary-file-directory))
+ (tmpdir temporary-file-directory)
+ (file (file-name-nondirectory tmpfile))
+ (nospecial-file (file-name-nondirectory nospecial)))
+ (should (string-equal file nospecial-file))
+ (should (equal (file-name-all-completions
+ nospecial-file nospecial-tempdir)
+ (file-name-all-completions file tmpdir)))
+ (should (equal (file-name-all-completions file nospecial-tempdir)
+ (file-name-all-completions file tmpdir)))
+ (should (equal (file-name-all-completions nospecial-file tmpdir)
+ (file-name-all-completions file tmpdir)))))
+ (files-tests--with-temp-non-special-and-file-name-handler (tmpfile nospecial)
+ (let ((nospecial-tempdir (file-name-quote temporary-file-directory))
+ (tmpdir temporary-file-directory)
+ (file (file-name-nondirectory tmpfile))
+ (nospecial-file (file-name-nondirectory nospecial)))
+ (should-not (string-equal file nospecial-file))
+ (should (equal (file-name-all-completions nospecial-file nospecial-tempdir)
+ (file-name-all-completions file tmpdir)))
+ (should (equal (file-name-all-completions file nospecial-tempdir)
+ (file-name-all-completions file tmpdir)))
+ (should (equal (file-name-all-completions nospecial-file tmpdir)
+ (file-name-all-completions file tmpdir))))))
+
+(ert-deftest files-tests-file-name-non-special-file-name-as-directory ()
+ (files-tests--with-temp-non-special (tmpdir nospecial-dir t)
+ (should (equal (file-name-as-directory nospecial-dir)
+ (file-name-quote (file-name-as-directory tmpdir)))))
+ (files-tests--with-temp-non-special-and-file-name-handler
+ (tmpdir nospecial-dir t)
+ (should-not (equal (file-name-as-directory nospecial-dir)
+ (file-name-quote (file-name-as-directory tmpdir))))))
+
+(ert-deftest files-tests-file-name-non-special-file-name-case-insensitive-p ()
+ (files-tests--with-temp-non-special (tmpfile nospecial)
+ (should (equal (file-name-case-insensitive-p nospecial)
+ (file-name-case-insensitive-p tmpfile))))
+ (files-tests--with-temp-non-special-and-file-name-handler (tmpfile nospecial)
+ (should (equal (file-name-case-insensitive-p nospecial)
+ (file-name-case-insensitive-p tmpfile)))))
+
+(ert-deftest files-tests-file-name-non-special-file-name-completion ()
+ (files-tests--with-temp-non-special (tmpfile nospecial)
+ (let ((nospecial-tempdir (file-name-quote temporary-file-directory))
+ (tmpdir temporary-file-directory)
+ (file (file-name-nondirectory tmpfile))
+ (nospecial-file (file-name-nondirectory nospecial)))
+ (should (string-equal file nospecial-file))
+ (should (equal (file-name-completion nospecial-file nospecial-tempdir)
+ (file-name-completion file tmpdir)))
+ (should (equal (file-name-completion file nospecial-tempdir)
+ (file-name-completion file tmpdir)))
+ (should (equal (file-name-completion nospecial-file tmpdir)
+ (file-name-completion file tmpdir)))))
+ (files-tests--with-temp-non-special-and-file-name-handler (tmpfile nospecial)
+ (let ((nospecial-tempdir (file-name-quote temporary-file-directory))
+ (tmpdir temporary-file-directory)
+ (file (file-name-nondirectory tmpfile))
+ (nospecial-file (file-name-nondirectory nospecial)))
+ (should-not (string-equal file nospecial-file))
+ (should (equal (file-name-completion nospecial-file nospecial-tempdir)
+ (file-name-completion file tmpdir)))
+ (should (equal (file-name-completion file nospecial-tempdir)
+ (file-name-completion file tmpdir)))
+ (should (equal (file-name-completion nospecial-file tmpdir)
+ (file-name-completion file tmpdir))))))
+
+(ert-deftest files-tests-file-name-non-special-file-name-directory ()
+ (files-tests--with-temp-non-special (tmpfile nospecial)
+ (should (equal (file-name-directory nospecial)
+ (file-name-quote temporary-file-directory))))
+ (files-tests--with-temp-non-special-and-file-name-handler (tmpfile nospecial)
+ (should (equal (file-name-directory nospecial)
+ (file-name-quote temporary-file-directory)))))
+
+(ert-deftest files-tests-file-name-non-special-file-name-nondirectory ()
+ (files-tests--with-temp-non-special (tmpfile nospecial)
+ (should (equal (file-name-nondirectory nospecial)
+ (file-name-nondirectory tmpfile))))
+ (files-tests--with-temp-non-special-and-file-name-handler (tmpfile nospecial)
+ (should-not (equal (file-name-nondirectory nospecial)
+ (file-name-nondirectory tmpfile)))))
+
+(ert-deftest files-tests-file-name-non-special-file-name-sans-versions ()
+ (files-tests--with-temp-non-special (tmpfile nospecial)
+ (should (equal (file-name-sans-versions nospecial) nospecial)))
+ (files-tests--with-temp-non-special-and-file-name-handler (tmpfile nospecial)
+ (should (equal (file-name-sans-versions nospecial) nospecial))))
+
+(ert-deftest files-tests-file-name-non-special-file-newer-than-file-p ()
+ (files-tests--with-temp-non-special (tmpfile nospecial)
+ (should-not (file-newer-than-file-p nospecial tmpfile))
+ (should-not (file-newer-than-file-p tmpfile nospecial))
+ (should-not (file-newer-than-file-p nospecial nospecial)))
+ (files-tests--with-temp-non-special-and-file-name-handler (tmpfile nospecial)
+ (should-not (file-newer-than-file-p nospecial tmpfile))
+ (should (file-newer-than-file-p tmpfile nospecial))
+ (should-not (file-newer-than-file-p nospecial nospecial))))
+
+(ert-deftest files-tests-file-name-non-special-notify-handlers ()
+ (skip-unless file-notify--library)
+ (files-tests--with-temp-non-special (tmpfile nospecial)
+ (let ((watch (file-notify-add-watch nospecial '(change) #'ignore)))
+ (should (file-notify-valid-p watch))
+ (file-notify-rm-watch watch)
+ (should-not (file-notify-valid-p watch))))
+ (files-tests--with-temp-non-special-and-file-name-handler (tmpfile nospecial)
+ (let ((watch (file-notify-add-watch nospecial '(change) #'ignore)))
+ (should (file-notify-valid-p watch))
+ (file-notify-rm-watch watch)
+ (should-not (file-notify-valid-p watch)))))
+
+(ert-deftest files-tests-file-name-non-special-file-ownership-preserved-p ()
+ (files-tests--with-temp-non-special (tmpfile nospecial)
+ (should (equal (file-ownership-preserved-p nospecial)
+ (file-ownership-preserved-p tmpfile))))
+ (files-tests--with-temp-non-special-and-file-name-handler (tmpfile nospecial)
+ (should (equal (file-ownership-preserved-p nospecial)
+ (file-ownership-preserved-p tmpfile)))))
+
+(ert-deftest files-tests-file-name-non-special-file-readable-p ()
+ (files-tests--with-temp-non-special (tmpfile nospecial)
+ (should (file-readable-p nospecial)))
+ (files-tests--with-temp-non-special-and-file-name-handler (tmpfile nospecial)
+ (should-not (file-readable-p nospecial))))
+
+(ert-deftest files-tests-file-name-non-special-file-regular-p ()
+ (files-tests--with-temp-non-special (tmpfile nospecial)
+ (should (file-regular-p nospecial)))
+ (files-tests--with-temp-non-special-and-file-name-handler (tmpfile nospecial)
+ (should-not (file-regular-p nospecial))))
+
+(ert-deftest files-tests-file-name-non-special-file-remote-p ()
+ (files-tests--with-temp-non-special (tmpfile nospecial)
+ (should-not (file-remote-p nospecial)))
+ (files-tests--with-temp-non-special-and-file-name-handler (tmpfile nospecial)
+ (should-not (file-remote-p nospecial))))
+
+(ert-deftest files-tests-file-name-non-special-file-selinux-context ()
+ (files-tests--with-temp-non-special (tmpfile nospecial)
+ (unless (equal (file-selinux-context tmpfile) '(nil nil nil nil))
+ (should (equal (file-selinux-context nospecial)
+ (file-selinux-context tmpfile)))))
+ (files-tests--with-temp-non-special-and-file-name-handler (tmpfile nospecial)
+ (unless (equal (file-selinux-context tmpfile) '(nil nil nil nil))
+ (should-not (equal (file-selinux-context nospecial)
+ (file-selinux-context tmpfile))))))
+
+(ert-deftest files-tests-file-name-non-special-file-symlink-p ()
+ (files-tests--with-temp-non-special (tmpfile nospecial)
+ (should-not (file-symlink-p nospecial)))
+ (files-tests--with-temp-non-special-and-file-name-handler (tmpfile nospecial)
+ (should-not (file-symlink-p nospecial))))
+
+(ert-deftest files-tests-file-name-non-special-file-truename ()
+ (files-tests--with-temp-non-special (tmpfile nospecial)
+ (should (equal nospecial (file-truename nospecial))))
+ (files-tests--with-temp-non-special-and-file-name-handler (tmpfile nospecial)
+ (should (equal nospecial (file-truename nospecial)))))
+
+(ert-deftest files-tests-file-name-non-special-file-writable-p ()
+ (files-tests--with-temp-non-special (tmpfile nospecial)
+ (should (file-writable-p nospecial)))
+ (files-tests--with-temp-non-special-and-file-name-handler (tmpfile nospecial)
+ (should (file-writable-p nospecial))))
+
+(ert-deftest files-tests-file-name-non-special-find-backup-file-name ()
+ (let (version-control delete-old-versions
+ (kept-old-versions (default-toplevel-value 'kept-old-versions))
+ (kept-new-versions (default-toplevel-value 'kept-new-versions)))
+ (files-tests--with-temp-non-special (tmpfile nospecial)
+ (should (equal (find-backup-file-name nospecial)
+ (mapcar #'file-name-quote
+ (find-backup-file-name tmpfile)))))
+ (files-tests--with-temp-non-special-and-file-name-handler
+ (tmpfile nospecial)
+ (should-not (equal (find-backup-file-name nospecial)
+ (mapcar #'file-name-quote
+ (find-backup-file-name tmpfile)))))))
+
+(ert-deftest files-tests-file-name-non-special-get-file-buffer ()
+ ;; Make sure these buffers don't exist.
+ (files-tests--with-temp-non-special (tmpfile nospecial)
+ (let ((fbuf (get-file-buffer nospecial)))
+ (if fbuf (kill-buffer fbuf))
+ (should-not (get-file-buffer nospecial))))
+ (files-tests--with-temp-non-special-and-file-name-handler (tmpfile nospecial)
+ (let ((fbuf (get-file-buffer nospecial)))
+ (if fbuf (kill-buffer fbuf))
+ (should-not (get-file-buffer nospecial)))))
+
+(ert-deftest files-tests-file-name-non-special-insert-directory ()
+ (files-tests--with-temp-non-special (tmpdir nospecial-dir t)
+ (should (equal (with-temp-buffer
+ (insert-directory nospecial-dir "")
+ (buffer-string))
+ (with-temp-buffer
+ (insert-directory tmpdir "")
+ (buffer-string)))))
+ (files-tests--with-temp-non-special-and-file-name-handler
+ (tmpdir nospecial-dir t)
+ (should-error (with-temp-buffer (insert-directory nospecial-dir "")))))
+
+(ert-deftest files-tests-file-name-non-special-insert-file-contents ()
+ (files-tests--with-temp-non-special (tmpfile nospecial)
+ (with-temp-buffer
+ (insert-file-contents nospecial)
+ (should (zerop (buffer-size)))))
+ (files-tests--with-temp-non-special-and-file-name-handler (tmpfile nospecial)
+ (should-error (with-temp-buffer (insert-file-contents nospecial)))))
+
+(ert-deftest files-tests-file-name-non-special-load ()
+ (files-tests--with-temp-non-special (tmpfile nospecial)
+ (should (load nospecial nil t)))
+ (files-tests--with-temp-non-special-and-file-name-handler (tmpfile nospecial)
+ (should-error (load nospecial nil t))))
+
+(ert-deftest files-tests-file-name-non-special-make-auto-save-file-name ()
+ (files-tests--with-temp-non-special (tmpfile nospecial)
+ (save-current-buffer
+ (should (equal (prog2 (set-buffer (find-file-noselect nospecial))
+ (make-auto-save-file-name)
+ (kill-buffer))
+ (prog2 (set-buffer (find-file-noselect tmpfile))
+ (make-auto-save-file-name)
+ (kill-buffer))))))
+ (files-tests--with-temp-non-special-and-file-name-handler (tmpfile nospecial)
+ (save-current-buffer
+ (should-not (equal (prog2 (set-buffer (find-file-noselect nospecial))
+ (make-auto-save-file-name)
+ (kill-buffer))
+ (prog2 (set-buffer (find-file-noselect tmpfile))
+ (make-auto-save-file-name)
+ (kill-buffer)))))))
+
+(ert-deftest files-test-auto-save-name-default ()
+ (with-temp-buffer
+ (let ((auto-save-file-name-transforms nil)
+ (name-start (if (memq system-type '(windows-nt ms-dos)) 2 nil)))
+ (setq buffer-file-name "/tmp/foo.txt")
+ (should (equal (substring (make-auto-save-file-name) name-start)
+ "/tmp/#foo.txt#")))))
+
+(ert-deftest files-test-auto-save-name-transform ()
+ (with-temp-buffer
+ (setq buffer-file-name "/tmp/foo.txt")
+ (let ((auto-save-file-name-transforms
+ '(("\\`/.*/\\([^/]+\\)\\'" "/var/tmp/\\1" nil)))
+ (name-start (if (memq system-type '(windows-nt ms-dos)) 2 nil)))
+ (should (equal (substring (make-auto-save-file-name) name-start)
+ "/var/tmp/#foo.txt#")))))
+
+(ert-deftest files-test-auto-save-name-unique ()
+ (with-temp-buffer
+ (setq buffer-file-name "/tmp/foo.txt")
+ (let ((auto-save-file-name-transforms
+ '(("\\`/.*/\\([^/]+\\)\\'" "/var/tmp/\\1" t)))
+ (name-start (if (memq system-type '(windows-nt ms-dos)) 2 nil)))
+ (should (equal (substring (make-auto-save-file-name) name-start)
+ "/var/tmp/#!tmp!foo.txt#")))
+ (let ((auto-save-file-name-transforms
+ '(("\\`/.*/\\([^/]+\\)\\'" "/var/tmp/\\1" sha1)))
+ (name-start (if (memq system-type '(windows-nt ms-dos)) 2 nil)))
+ (should (equal (substring (make-auto-save-file-name) name-start)
+ "/var/tmp/#b57c5a04f429a83305859d3350ecdab8315a9037#")))))
+
+(ert-deftest files-test-lock-name-default ()
+ (let ((lock-file-name-transforms nil)
+ (name-start (if (memq system-type '(windows-nt ms-dos)) 2 nil)))
+ (should (equal (substring (make-lock-file-name "/tmp/foo.txt") name-start)
+ "/tmp/.#foo.txt"))))
+
+(ert-deftest files-test-lock-name-unique ()
+ (let ((lock-file-name-transforms
+ '(("\\`/.*/\\([^/]+\\)\\'" "/var/tmp/\\1" t)))
+ (name-start (if (memq system-type '(windows-nt ms-dos)) 2 nil)))
+ (should (equal (substring (make-lock-file-name "/tmp/foo.txt") name-start)
+ "/var/tmp/.#!tmp!foo.txt")))
+ (let ((lock-file-name-transforms
+ '(("\\`/.*/\\([^/]+\\)\\'" "/var/tmp/\\1" sha1)))
+ (name-start (if (memq system-type '(windows-nt ms-dos)) 2 nil)))
+ (should (equal (substring (make-lock-file-name "/tmp/foo.txt") name-start)
+ "/var/tmp/.#b57c5a04f429a83305859d3350ecdab8315a9037"))))
+
+(ert-deftest files-tests-file-name-non-special-make-directory ()
+ (files-tests--with-temp-non-special (tmpdir nospecial-dir t)
+ (let ((default-directory nospecial-dir))
+ (make-directory "dir")
+ (should (file-directory-p "dir"))
+ (delete-directory "dir")))
+ (files-tests--with-temp-non-special-and-file-name-handler
+ (tmpdir nospecial-dir t)
+ (let ((default-directory nospecial-dir))
+ (should-error (make-directory "dir")))))
+
+(ert-deftest files-tests-file-name-non-special-make-directory-internal ()
+ (files-tests--with-temp-non-special (tmpdir nospecial-dir t)
+ (let ((default-directory nospecial-dir))
+ (make-directory-internal "dir")
+ (should (file-directory-p "dir"))
+ (delete-directory "dir")))
+ (files-tests--with-temp-non-special-and-file-name-handler
+ (tmpdir nospecial-dir t)
+ (let ((default-directory nospecial-dir))
+ (should-error (make-directory-internal "dir")))))
+
+(ert-deftest files-tests-file-name-non-special-make-nearby-temp-file ()
+ (let* ((default-directory (file-name-quote temporary-file-directory))
+ (near-tmpfile (make-nearby-temp-file "file")))
+ (should (file-exists-p near-tmpfile))
+ (delete-file near-tmpfile)))
+
+(ert-deftest files-tests-file-name-non-special-make-symbolic-link ()
+ (files-tests--with-temp-non-special (tmpdir nospecial-dir t)
+ (files-tests--with-temp-non-special (tmpfile nospecial)
+ (let* ((linkname (expand-file-name "link" tmpdir))
+ (may-symlink (ignore-errors (make-symbolic-link tmpfile linkname)
+ t)))
+ (when may-symlink
+ (should (file-symlink-p linkname))
+ (delete-file linkname)
+ (let ((linkname (expand-file-name "link" nospecial-dir)))
+ (make-symbolic-link tmpfile linkname)
+ (should (file-symlink-p linkname))
+ (delete-file linkname))))))
+ (files-tests--with-temp-non-special-and-file-name-handler
+ (tmpdir nospecial-dir t)
+ (files-tests--with-temp-non-special-and-file-name-handler
+ (tmpfile nospecial)
+ (let* ((linkname (expand-file-name "link" tmpdir))
+ (may-symlink (ignore-errors (make-symbolic-link tmpfile linkname)
+ t)))
+ (when may-symlink
+ (should (file-symlink-p linkname))
+ (delete-file linkname)
+ (let ((linkname (expand-file-name "link" nospecial-dir)))
+ (should-error (make-symbolic-link tmpfile linkname))))))))
+
+;; See `files-tests-file-name-non-special--subprocess'.
+;; (ert-deftest files-tests-file-name-non-special-process-file ())
+
+(ert-deftest files-tests-file-name-non-special-rename-file ()
+ (files-tests--with-temp-non-special (tmpfile nospecial)
+ (rename-file nospecial (files-tests--new-name nospecial "x"))
+ (rename-file (files-tests--new-name nospecial "x") nospecial)
+ (rename-file tmpfile (files-tests--new-name nospecial "x"))
+ (rename-file (files-tests--new-name nospecial "x") nospecial)
+ (rename-file nospecial (files-tests--new-name tmpfile "x"))
+ (rename-file (files-tests--new-name nospecial "x") nospecial))
+ (files-tests--with-temp-non-special-and-file-name-handler (tmpfile nospecial)
+ (should-error (rename-file nospecial (files-tests--new-name nospecial "x")))
+ (rename-file tmpfile (files-tests--new-name nospecial "x"))
+ (rename-file (files-tests--new-name nospecial "x") nospecial)
+ (rename-file nospecial (files-tests--new-name tmpfile "x"))
+ (should-error (rename-file (files-tests--new-name nospecial "x") nospecial))
+ (delete-file (files-tests--new-name tmpfile "x"))
+ (delete-file (files-tests--new-name nospecial "x"))))
+
+(ert-deftest files-tests-file-name-non-special-set-file-acl ()
+ (files-tests--with-temp-non-special (tmpfile nospecial)
+ (set-file-acl nospecial (file-acl nospecial)))
+ (files-tests--with-temp-non-special-and-file-name-handler (tmpfile nospecial)
+ (set-file-acl nospecial (file-acl nospecial))))
+
+(ert-deftest files-tests-file-name-non-special-set-file-modes ()
+ (files-tests--with-temp-non-special (tmpfile nospecial)
+ (set-file-modes nospecial (file-modes nospecial)))
+ (files-tests--with-temp-non-special-and-file-name-handler (tmpfile nospecial)
+ (should-error (set-file-modes nospecial (file-modes nospecial)))))
+
+(ert-deftest files-tests-file-name-non-special-set-file-selinux-context ()
+ (files-tests--with-temp-non-special (tmpfile nospecial)
+ (unless (equal (file-selinux-context tmpfile) '(nil nil nil nil))
+ (set-file-selinux-context nospecial (file-selinux-context nospecial))))
+ (files-tests--with-temp-non-special-and-file-name-handler (tmpfile nospecial)
+ (unless (equal (file-selinux-context tmpfile) '(nil nil nil nil))
+ (should-error
+ (set-file-selinux-context nospecial (file-selinux-context nospecial))))))
+
+(ert-deftest files-tests-file-name-non-special-set-file-times ()
+ (files-tests--with-temp-non-special (tmpfile nospecial)
+ (set-file-times nospecial nil 'nofollow))
+ (files-tests--with-temp-non-special-and-file-name-handler (tmpfile nospecial)
+ (should-error (set-file-times nospecial nil 'nofollow))))
+
+(ert-deftest files-tests-file-name-non-special-set-visited-file-modtime ()
+ (files-tests--with-temp-non-special (tmpfile nospecial)
+ (save-current-buffer
+ (set-buffer (find-file-noselect nospecial))
+ (set-visited-file-modtime)
+ (kill-buffer)))
+ (files-tests--with-temp-non-special-and-file-name-handler (tmpfile nospecial)
+ (save-current-buffer
+ (set-buffer (find-file-noselect nospecial))
+ (set-visited-file-modtime)
+ (kill-buffer))))
+
+(ert-deftest files-tests-file-name-non-special-shell-command ()
+ (files-tests--with-temp-non-special (tmpdir nospecial-dir t)
+ (with-temp-buffer
+ (let ((default-directory nospecial-dir))
+ (shell-command (concat (shell-quote-argument
+ (concat invocation-directory invocation-name))
+ " --version")
+ (current-buffer))
+ (goto-char (point-min))
+ (should (search-forward emacs-version nil t)))))
+ (files-tests--with-temp-non-special-and-file-name-handler
+ (tmpdir nospecial-dir t)
+ (with-temp-buffer
+ (let ((default-directory nospecial-dir))
+ (should-error
+ (shell-command (concat (shell-quote-argument
+ (concat invocation-directory invocation-name))
+ " --version")
+ (current-buffer)))))))
+
+(ert-deftest files-tests-file-name-non-special-start-file-process ()
+ (files-tests--with-temp-non-special (tmpdir nospecial-dir t)
+ (with-temp-buffer
+ (let ((default-directory nospecial-dir))
+ (let ((proc (start-file-process
+ "emacs" (current-buffer)
+ (concat invocation-directory invocation-name)
+ "--version")))
+ (accept-process-output proc)
+ (goto-char (point-min))
+ (should (search-forward emacs-version nil t))
+ ;; Don't stop the test run with a query, as the subprocess
+ ;; may or may not be dead by the time we reach here.
+ (set-process-query-on-exit-flag proc nil)
+ ;; On MS-Windows, wait for the process to die, since the OS
+ ;; will not let us delete a directory that is the cwd of a
+ ;; running process.
+ (when (eq system-type 'windows-nt)
+ (while (process-live-p proc)
+ (sleep-for 0.1)))))))
+ (files-tests--with-temp-non-special-and-file-name-handler
+ (tmpdir nospecial-dir t)
+ (with-temp-buffer
+ (let ((default-directory nospecial-dir))
+ (should-error (start-file-process
+ "emacs" (current-buffer)
+ (concat invocation-directory invocation-name)
+ "--version"))))))
+
+(ert-deftest files-tests-file-name-non-special-substitute-in-file-name ()
+ (files-tests--with-temp-non-special (tmpfile nospecial)
+ (let ((process-environment (cons "FOO=foo" process-environment))
+ (nospecial-foo (files-tests--new-name nospecial "$FOO")))
+ ;; The "/:" prevents substitution.
+ (equal (substitute-in-file-name nospecial-foo) nospecial-foo)))
+ (files-tests--with-temp-non-special-and-file-name-handler (tmpfile nospecial)
+ (let ((process-environment (cons "FOO=foo" process-environment))
+ (nospecial-foo (files-tests--new-name nospecial "$FOO")))
+ ;; The "/:" prevents substitution.
+ (equal (substitute-in-file-name nospecial-foo) nospecial-foo))))
+
+(ert-deftest files-tests-file-name-non-special-temporary-file-directory ()
+ (files-tests--with-temp-non-special (tmpdir nospecial-dir t)
+ (let ((default-directory nospecial-dir))
+ (equal (temporary-file-directory) temporary-file-directory)))
+ (files-tests--with-temp-non-special-and-file-name-handler
+ (tmpdir nospecial-dir t)
+ (let ((default-directory nospecial-dir))
+ (equal (temporary-file-directory) temporary-file-directory))))
+
+(ert-deftest files-tests-file-name-non-special-unhandled-file-name-directory ()
+ (files-tests--with-temp-non-special (tmpdir nospecial-dir t)
+ (equal (unhandled-file-name-directory nospecial-dir)
+ (file-name-as-directory tmpdir)))
+ (files-tests--with-temp-non-special-and-file-name-handler
+ (tmpdir nospecial-dir t)
+ (equal (unhandled-file-name-directory nospecial-dir)
+ (file-name-as-directory tmpdir))))
+
+(ert-deftest files-tests-file-name-non-special-vc-registered ()
+ (files-tests--with-temp-non-special (tmpfile nospecial)
+ (should (equal (vc-registered nospecial) (vc-registered tmpfile))))
+ (files-tests--with-temp-non-special-and-file-name-handler (tmpfile nospecial)
+ (should (equal (vc-registered nospecial) (vc-registered tmpfile)))))
+
+;; See test `files-tests-file-name-non-special--buffers'.
+;; (ert-deftest files-tests-file-name-non-special-verify-visited-file-modtime ())
+
+(ert-deftest files-tests-file-name-non-special-write-region ()
+ (files-tests--with-temp-non-special (tmpfile nospecial)
+ (with-temp-buffer
+ (write-region nil nil nospecial nil :visit)))
+ (files-tests--with-temp-non-special-and-file-name-handler (tmpfile nospecial)
+ (with-temp-buffer
+ (write-region nil nil nospecial nil :visit))))
+
+(ert-deftest files-tests-file-name-non-special-make-process ()
+ "Check that the ‘:file-handler’ argument of ‘make-process’
+works as expected if the default directory is quoted."
+ (let ((default-directory (file-name-quote invocation-directory))
+ (program (file-name-quote
+ (expand-file-name invocation-name invocation-directory))))
+ (should (processp (make-process :name "name"
+ :command (list program "--version")
+ :file-handler t)))))
+
+(ert-deftest files-tests-insert-directory-wildcard-in-dir-p ()
(let ((alist (list (cons "/home/user/*/.txt" (cons "/home/user/" "*/.txt"))
(cons "/home/user/.txt" nil)
(cons "/home/*/.txt" (cons "/home/" "*/.txt"))
@@ -344,29 +1263,65 @@ be invoked with the right arguments."
(cdr path-res)
(insert-directory-wildcard-in-dir-p (car path-res)))))))
-(ert-deftest files-tests--make-directory ()
- (let* ((dir (make-temp-file "files-mkdir-test" t))
- (dirname (file-name-as-directory dir))
- (file (concat dirname "file"))
- (subdir1 (concat dirname "subdir1"))
- (subdir2 (concat dirname "subdir2"))
- (a/b (concat dirname "a/b")))
- (write-region "" nil file)
- (should-error (make-directory "/"))
- (should-not (make-directory "/" t))
- (should-error (make-directory dir))
- (should-not (make-directory dir t))
- (should-error (make-directory dirname))
- (should-not (make-directory dirname t))
- (should-error (make-directory file))
- (should-error (make-directory file t))
- (should-not (make-directory subdir1))
- (should-not (make-directory subdir2 t))
- (should-error (make-directory a/b))
- (should-not (make-directory a/b t))
- (delete-directory dir 'recursive)))
-
-(ert-deftest files-test-no-file-write-contents ()
+(ert-deftest files-tests-make-directory ()
+ (ert-with-temp-directory dir
+ (let* ((dirname (file-name-as-directory dir))
+ (file (concat dirname "file"))
+ (subdir1 (concat dirname "subdir1"))
+ (subdir2 (concat dirname "subdir2"))
+ (a/b (concat dirname "a/b")))
+ (write-region "" nil file)
+ (should-error (make-directory "/"))
+ (should-not (make-directory "/" t))
+ (should-error (make-directory dir))
+ (should-not (make-directory dir t))
+ (should-error (make-directory dirname))
+ (should-not (make-directory dirname t))
+ (should-error (make-directory file))
+ (should-error (make-directory file t))
+ (should-not (make-directory subdir1))
+ (should-not (make-directory subdir2 t))
+ (should-error (make-directory a/b))
+ (should-not (make-directory a/b t))
+ (delete-directory dir 'recursive))))
+
+(ert-deftest files-tests-file-modes-symbolic-to-number ()
+ (let ((alist (list (cons "a=rwx" #o777)
+ (cons "o=t" #o1000)
+ (cons "o=xt" #o1001)
+ (cons "o=tx" #o1001) ; Order doesn't matter.
+ (cons "u=rwx,g=rx,o=rx" #o755)
+ (cons "u=rwx,g=,o=" #o700)
+ (cons "u=rwx" #o700) ; Empty permissions can be ignored.
+ (cons "u=rw,g=r,o=r" #o644)
+ (cons "u=rw,g=r,o=t" #o1640)
+ (cons "u=rw,g=r,o=xt" #o1641)
+ (cons "u=rwxs,g=rs,o=xt" #o7741)
+ (cons "u=rws,g=rs,o=t" #o7640)
+ (cons "u=rws,g=rs,o=r" #o6644)
+ (cons "a=r" #o444)
+ (cons "u=S" nil)
+ (cons "u=T" nil)
+ (cons "u=Z" nil))))
+ (dolist (x alist)
+ (if (cdr-safe x)
+ (should (equal (cdr x) (file-modes-symbolic-to-number (car x))))
+ (should-error (file-modes-symbolic-to-number (car x)))))))
+
+(ert-deftest files-tests-file-modes-number-to-symbolic ()
+ (let ((alist (list (cons #o755 "-rwxr-xr-x")
+ (cons #o700 "-rwx------")
+ (cons #o644 "-rw-r--r--")
+ (cons #o1640 "-rw-r----T")
+ (cons #o1641 "-rw-r----t")
+ (cons #o7741 "-rwsr-S--t")
+ (cons #o7640 "-rwSr-S--T")
+ (cons #o6644 "-rwSr-Sr--")
+ (cons #o444 "-r--r--r--"))))
+ (dolist (x alist)
+ (should (equal (cdr x) (file-modes-number-to-symbolic (car x)))))))
+
+(ert-deftest files-tests-no-file-write-contents ()
"Test that `write-contents-functions' permits saving a file.
Usually `basic-save-buffer' will prompt for a file name if the
current buffer has none. It should first call the functions in
@@ -375,7 +1330,8 @@ consider the buffer saved, without prompting for a file
name (Bug#28412)."
(let ((read-file-name-function
(lambda (&rest _ignore)
- (error "Prompting for file name"))))
+ (error "Prompting for file name")))
+ require-final-newline)
;; With contents function, and no file.
(with-temp-buffer
(setq write-contents-functions (lambda () t))
@@ -387,29 +1343,552 @@ name (Bug#28412)."
(set-buffer-modified-p t)
(should-error (save-buffer) :type 'error))
;; Then a buffer visiting a file: should save normally.
- (files-tests--with-temp-file temp-file-name
+ (ert-with-temp-file temp-file-name
(with-current-buffer (find-file-noselect temp-file-name)
(setq write-contents-functions nil)
(insert "p")
(should (null (save-buffer)))
(should (eq (buffer-size) 1))))))
-(ert-deftest files-tests--copy-directory ()
- (let* ((dir (make-temp-file "files-mkdir-test" t))
- (dirname (file-name-as-directory dir))
- (source (concat dirname "source"))
- (dest (concat dirname "dest/new/directory/"))
- (file (concat (file-name-as-directory source) "file"))
- (source2 (concat dirname "source2"))
- (dest2 (concat dirname "dest/new2")))
- (make-directory source)
- (write-region "" nil file)
- (copy-directory source dest t t t)
- (should (file-exists-p (concat dest "file")))
- (make-directory (concat (file-name-as-directory source2) "a") t)
- (copy-directory source2 dest2)
- (should (file-directory-p (concat (file-name-as-directory dest2) "a")))
- (delete-directory dir 'recursive)))
+(ert-deftest files-tests-copy-directory ()
+ (ert-with-temp-directory dir
+ (let* ((dirname (file-name-as-directory dir))
+ (source (concat dirname "source"))
+ (dest (concat dirname "dest/new/directory/"))
+ (file (concat (file-name-as-directory source) "file"))
+ (source2 (concat dirname "source2"))
+ (dest2 (concat dirname "dest/new2")))
+ (make-directory source)
+ (write-region "" nil file)
+ (copy-directory source dest t t t)
+ (should (file-exists-p (concat dest "file")))
+ (make-directory (concat (file-name-as-directory source2) "a") t)
+ (copy-directory source2 dest2)
+ (should (file-directory-p (concat (file-name-as-directory dest2) "a")))
+ (delete-directory dir 'recursive))))
+
+(ert-deftest files-tests-abbreviate-file-name-homedir ()
+ ;; Check homedir abbreviation.
+ (let* ((homedir temporary-file-directory)
+ (process-environment (cons (format "HOME=%s" homedir)
+ process-environment))
+ (abbreviated-home-dir nil))
+ (should (equal "~/foo/bar"
+ (abbreviate-file-name (concat homedir "foo/bar")))))
+ ;; Check that homedir abbreviation doesn't occur when homedir is just /.
+ (let* ((homedir "/")
+ (process-environment (cons (format "HOME=%s" homedir)
+ process-environment))
+ (abbreviated-home-dir nil))
+ (should (equal "/foo/bar"
+ (abbreviate-file-name (concat homedir "foo/bar"))))))
+
+(ert-deftest files-tests-abbreviate-file-name-directory-abbrev-alist ()
+ ;; Check `directory-abbrev-alist' abbreviation.
+ (let ((directory-abbrev-alist '(("\\`/nowhere/special" . "/nw/sp"))))
+ (should (equal "/nw/sp/here"
+ (abbreviate-file-name "/nowhere/special/here"))))
+ ;; Check homedir and `directory-abbrev-alist' abbreviation.
+ (let* ((homedir temporary-file-directory)
+ (process-environment (cons (format "HOME=%s" homedir)
+ process-environment))
+ (abbreviated-home-dir nil)
+ (directory-abbrev-alist
+ `((,(concat "\\`" (regexp-quote homedir) "nowhere/special")
+ . ,(concat homedir "nw/sp")))))
+ (should (equal "~/nw/sp/here"
+ (abbreviate-file-name
+ (concat homedir "nowhere/special/here"))))))
+
+(ert-deftest files-tests-abbreviated-home-dir ()
+ "Test that changing HOME does not confuse `abbreviate-file-name'.
+See <https://debbugs.gnu.org/19657#20>."
+ (let* ((homedir temporary-file-directory)
+ (process-environment (cons (format "HOME=%s" homedir)
+ process-environment))
+ (abbreviated-home-dir nil)
+ (testfile (expand-file-name "foo" homedir))
+ (old (file-truename (abbreviate-file-name testfile)))
+ (process-environment (cons (format "HOME=%s"
+ (expand-file-name "bar" homedir))
+ process-environment)))
+ (should (equal old (file-truename (abbreviate-file-name testfile))))))
+
+(ert-deftest files-tests-executable-find ()
+ "Test that `executable-find' works also with a relative or remote PATH.
+See <https://debbugs.gnu.org/35241>."
+ (ert-with-temp-file tmpfile
+ :suffix (car exec-suffixes)
+ (set-file-modes tmpfile #o755)
+ (let ((exec-path `(,temporary-file-directory)))
+ (should
+ (equal tmpfile
+ (executable-find (file-name-nondirectory tmpfile)))))
+ ;; An empty element of `exec-path' means `default-directory'.
+ (let ((default-directory temporary-file-directory)
+ (exec-path nil))
+ (should
+ (equal tmpfile
+ (executable-find (file-name-nondirectory tmpfile)))))
+ ;; The remote file name shall be quoted, and handled like a
+ ;; non-existing directory.
+ (let ((default-directory "/ssh::")
+ (exec-path (append exec-path `("." ,temporary-file-directory))))
+ (should
+ (equal tmpfile
+ (executable-find (file-name-nondirectory tmpfile)))))))
+
+;; Note: we call this test "...-zzdont..." so that it runs near the
+;; end, because otherwise the advice it adds to write-region doesn't
+;; get removed(??) and breaks the revert-file tests on MS-Windows.
+(ert-deftest files-tests-zzdont-rewrite-precious-files ()
+ "Test that `file-precious-flag' forces files to be saved by
+renaming only, rather than modified in-place."
+ (ert-with-temp-file temp-file-name
+ (let* ((advice (lambda (_start _end filename &rest _r)
+ (should-not (string= filename temp-file-name)))))
+ (unwind-protect
+ (with-current-buffer (find-file-noselect temp-file-name)
+ (advice-add #'write-region :before advice)
+ (setq-local file-precious-flag t)
+ (insert "foobar")
+ (should (null (save-buffer))))
+ (ignore-errors (advice-remove #'write-region advice))))))
+
+(ert-deftest files-test-file-size-human-readable ()
+ (should (equal (file-size-human-readable 13) "13"))
+ (should (equal (file-size-human-readable 13 'si) "13"))
+ (should (equal (file-size-human-readable 13 'iec) "13B"))
+ (should (equal (file-size-human-readable 10000) "9.8k"))
+ (should (equal (file-size-human-readable 10000 'si) "10k"))
+ (should (equal (file-size-human-readable 10000 'iec) "9.8KiB"))
+ (should (equal (file-size-human-readable 4294967296 nil) "4G"))
+ (should (equal (file-size-human-readable 4294967296 'si) "4.3G"))
+ (should (equal (file-size-human-readable 4294967296 'iec) "4GiB"))
+ (should (equal (file-size-human-readable 13 nil " ") "13"))
+ (should (equal (file-size-human-readable 13 'si " ") "13"))
+ (should (equal (file-size-human-readable 13 'iec " ") "13 B"))
+ (should (equal (file-size-human-readable 10000 nil " ") "9.8 k"))
+ (should (equal (file-size-human-readable 10000 'si " ") "10 k"))
+ (should (equal (file-size-human-readable 10000 'iec " ") "9.8 KiB"))
+ (should (equal (file-size-human-readable 4294967296 nil " ") "4 G"))
+ (should (equal (file-size-human-readable 4294967296 'si " ") "4.3 G"))
+ (should (equal (file-size-human-readable 4294967296 'iec " ") "4 GiB"))
+ (should (equal (file-size-human-readable 10000 nil " " "bit") "9.8 kbit"))
+ (should (equal (file-size-human-readable 10000 'si " " "bit") "10 kbit"))
+ (should (equal (file-size-human-readable 10000 'iec " " "bit") "9.8 Kibit"))
+
+ (should (equal (file-size-human-readable 2048) "2k"))
+ (should (equal (file-size-human-readable 2046) "2k"))
+ (should (equal (file-size-human-readable 2050) "2k"))
+ (should (equal (file-size-human-readable 1950) "1.9k"))
+ (should (equal (file-size-human-readable 2100) "2.1k"))
+
+ (should (equal (file-size-human-readable-iec 0) "0 B"))
+ (should (equal (file-size-human-readable-iec 1) "1 B"))
+ (should (equal (file-size-human-readable-iec 9621) "9.4 KiB"))
+ (should (equal (file-size-human-readable-iec 72528034765) "68 GiB")))
+
+(ert-deftest files-test-magic-mode-alist-re-baseline ()
+ "Test magic-mode-alist with RE, expected behavior for match."
+ (let ((magic-mode-alist '(("my-tag" . text-mode))))
+ (with-temp-buffer
+ (insert "my-tag")
+ (normal-mode)
+ (should (eq major-mode 'text-mode)))))
+
+(ert-deftest files-test-magic-mode-alist-re-no-match ()
+ "Test magic-mode-alist with RE, expected behavior for no match."
+ (let ((magic-mode-alist '(("my-tag" . text-mode))))
+ (with-temp-buffer
+ (insert "not-my-tag")
+ (normal-mode)
+ (should (not (eq major-mode 'text-mode))))))
+
+(ert-deftest files-test-magic-mode-alist-re-case-diff ()
+ "Test that regexps in magic-mode-alist are case-sensitive.
+See <https://debbugs.gnu.org/36401>."
+ (let ((case-fold-search t)
+ (magic-mode-alist '(("my-tag" . text-mode))))
+ (with-temp-buffer
+ (goto-char (point-min))
+ (insert "My-Tag")
+ (normal-mode)
+ (should (not (eq major-mode 'text-mode))))))
+
+(ert-deftest files-colon-path ()
+ (if (memq system-type '(windows-nt ms-dos))
+ (should (equal (parse-colon-path "x:/foo//bar/baz")
+ '("x:/foo//bar/baz/")))
+ (should (equal (parse-colon-path "/foo//bar/baz")
+ '("/foo//bar/baz/"))))
+ (should (equal (parse-colon-path (concat "." path-separator "/tmp"))
+ '("./" "/tmp/")))
+ (should (equal (parse-colon-path (concat "/foo" path-separator "///bar"))
+ (if (memq system-type '(windows-nt cygwin ms-dos))
+ '("/foo/" "//bar/")
+ '("/foo/" "/bar/")))))
+
+(ert-deftest files-test-magic-mode-alist-doctype ()
+ "Test that DOCTYPE and variants put files in mhtml-mode."
+ (with-temp-buffer
+ (goto-char (point-min))
+ (insert "<!DOCTYPE html>")
+ (normal-mode)
+ (should (eq major-mode 'mhtml-mode))
+ (erase-buffer)
+ (insert "<!doctype html>")
+ (normal-mode)
+ (should (eq major-mode 'mhtml-mode))))
+
+(defvar files-tests-lao "The Way that can be told of is not the eternal Way;
+The name that can be named is not the eternal name.
+The Nameless is the origin of Heaven and Earth;
+The Named is the mother of all things.
+Therefore let there always be non-being,
+ so we may see their subtlety,
+And let there always be being,
+ so we may see their outcome.
+The two are the same,
+But after they are produced,
+ they have different names.
+")
+
+(defvar files-tests-tzu "The Nameless is the origin of Heaven and Earth;
+The named is the mother of all things.
+
+Therefore let there always be non-being,
+ so we may see their subtlety,
+And let there always be being,
+ so we may see their outcome.
+The two are the same,
+But after they are produced,
+ they have different names.
+They both may be called deep and profound.
+Deeper and more profound,
+The door of all subtleties!
+")
+
+(ert-deftest files-tests-revert-buffer ()
+ "Test that revert-buffer is successful."
+ (ert-with-temp-file temp-file-name
+ (with-temp-buffer
+ (insert files-tests-lao)
+ (write-file temp-file-name)
+ (erase-buffer)
+ (insert files-tests-tzu)
+ (revert-buffer t t t)
+ (should (compare-strings files-tests-lao nil nil
+ (buffer-substring (point-min) (point-max))
+ nil nil)))))
+
+(ert-deftest files-tests-revert-buffer-with-fine-grain ()
+ "Test that revert-buffer-with-fine-grain is successful."
+ (ert-with-temp-file temp-file-name
+ (with-temp-buffer
+ (insert files-tests-lao)
+ (write-file temp-file-name)
+ (erase-buffer)
+ (insert files-tests-tzu)
+ (should (revert-buffer-with-fine-grain t t))
+ (should (compare-strings files-tests-lao nil nil
+ (buffer-substring (point-min) (point-max))
+ nil nil)))))
+
+(ert-deftest files-tests-file-name-with-extension-good ()
+ "Test that `file-name-with-extension' succeeds with reasonable input."
+ (should (string= (file-name-with-extension "Jack" "css") "Jack.css"))
+ (should (string= (file-name-with-extension "Jack" ".css") "Jack.css"))
+ (should (string= (file-name-with-extension "Jack.scss" "css") "Jack.css"))
+ (should (string= (file-name-with-extension "/path/to/Jack.md" "org") "/path/to/Jack.org")))
+
+(ert-deftest files-tests-file-name-with-extension-bad ()
+ "Test that `file-name-with-extension' fails on malformed input."
+ (should-error (file-name-with-extension nil nil))
+ (should-error (file-name-with-extension "Jack" nil))
+ (should-error (file-name-with-extension nil "css"))
+ (should-error (file-name-with-extension "" ""))
+ (should-error (file-name-with-extension "" "css"))
+ (should-error (file-name-with-extension "Jack" ""))
+ (should-error (file-name-with-extension "Jack" "."))
+ (should-error (file-name-with-extension "/is/a/directory/" "css")))
+
+(ert-deftest files-tests-file-name-base ()
+ (should (equal (file-name-base "") ""))
+ (should (equal (file-name-base "/foo/") ""))
+ (should (equal (file-name-base "/foo") "foo"))
+ (should (equal (file-name-base "/foo/bar") "bar"))
+ (should (equal (file-name-base "foo") "foo"))
+ (should (equal (file-name-base "foo/bar") "bar")))
+
+(ert-deftest files-test-dir-locals-auto-mode-alist ()
+ "Test an `auto-mode-alist' entry in `.dir-locals.el'"
+ (find-file (ert-resource-file "whatever.quux"))
+ (should (eq major-mode 'tcl-mode))
+ (find-file (ert-resource-file "auto-test.zot1"))
+ (should (eq major-mode 'fundamental-mode))
+ (find-file (ert-resource-file "auto-test.zot2"))
+ (should (eq major-mode 'fundamental-mode))
+ (find-file (ert-resource-file "auto-test.zot3"))
+ (should (eq major-mode 'fundamental-mode)))
+
+(defun files-tests--save-some-buffers (pred def-pred-bind exp-1 exp-2)
+ "Helper function to test `save-some-buffers'.
+
+This function creates two file-visiting buffers, BUF-1, BUF-2 in
+different directories at the same level, i.e., none of them is a
+subdir of the other; then it modifies both buffers; finally, it
+calls `save-some-buffers' from BUF-1 with first arg t, second
+arg PRED and `save-some-buffers-default-predicate' let-bound to
+DEF-PRED-BIND.
+
+EXP-1 and EXP-2 are the expected values of calling `buffer-modified-p'
+on BUF-1 and BUF-2 after the `save-some-buffers' call.
+
+The test is repeated with `save-some-buffers-default-predicate'
+let-bound to PRED and passing nil as second arg of
+`save-some-buffers'."
+ (ert-with-temp-directory dir
+ (let* ((file-1 (expand-file-name "subdir-1/file.foo" dir))
+ (file-2 (expand-file-name "subdir-2/file.bar" dir))
+ (inhibit-message t)
+ buf-1 buf-2)
+ (unwind-protect
+ (progn
+ (make-empty-file file-1 'parens)
+ (make-empty-file file-2 'parens)
+ (setq buf-1 (find-file file-1)
+ buf-2 (find-file file-2))
+ (dolist (buf (list buf-1 buf-2))
+ (with-current-buffer buf (insert "foobar\n")))
+ ;; Run the test.
+ (with-current-buffer buf-1
+ (let ((save-some-buffers-default-predicate def-pred-bind))
+ (save-some-buffers t pred))
+ (should (eq exp-1 (buffer-modified-p buf-1)))
+ (should (eq exp-2 (buffer-modified-p buf-2))))
+ ;; Set both buffers as modified to run another test.
+ (dolist (buf (list buf-1 buf-2))
+ (with-current-buffer buf (set-buffer-modified-p t)))
+ ;; The result of this test must be identical as the previous one.
+ (with-current-buffer buf-1
+ (let ((save-some-buffers-default-predicate (or pred def-pred-bind)))
+ (save-some-buffers t nil))
+ (should (eq exp-1 (buffer-modified-p buf-1)))
+ (should (eq exp-2 (buffer-modified-p buf-2)))))
+ ;; Clean up.
+ (dolist (buf (list buf-1 buf-2))
+ (with-current-buffer buf
+ (set-buffer-modified-p nil)
+ (kill-buffer buf)))))))
+
+(ert-deftest files-tests-save-some-buffers ()
+ "Test `save-some-buffers'.
+Test the 3 cases for the second argument PRED, i.e., nil, t, or
+predicate.
+The value of `save-some-buffers-default-predicate' is ignored unless
+PRED is nil."
+ (let* ((foo-file-p (lambda () (string-suffix-p ".foo" buffer-file-name)))
+ (bar-file-p (lambda () (string-suffix-p ".bar" buffer-file-name)))
+ (args-results `((nil nil nil nil)
+ (nil ,foo-file-p nil t)
+ (nil ,bar-file-p t nil)
+ (,foo-file-p nil nil t)
+ (,bar-file-p nil t nil)
+
+ (buffer-modified-p nil nil nil)
+ (t nil nil nil)
+ (t ,foo-file-p nil nil)
+
+ (,foo-file-p save-some-buffers-root nil t)
+ (nil save-some-buffers-root nil t)
+ (,bar-file-p save-some-buffers-root t nil)
+ (t save-some-buffers-root nil nil))))
+ (pcase-dolist (`(,pred ,def-pred-bind ,exp-1 ,exp-2) args-results)
+ (files-tests--save-some-buffers pred def-pred-bind exp-1 exp-2))))
+
+(defun files-tests--with-buffer-offer-save (buffers-offer fn-test args-results)
+ "Helper macro to test `save-some-buffers' and `save-buffers-kill-emacs'.
+
+This macro creates several non-file-visiting buffers in different
+directories at the same level, i.e., none of them is a subdir of the
+other. Then it modifies the buffers and sets their `buffer-offer-save'
+as specified by BUFFERS-OFFER, a list of elements (BUFFER OFFER-SAVE).
+Finally, it calls FN-TEST from the first buffer.
+
+FN-TEST is the function to test: either `save-some-buffers' or
+`save-buffers-kill-emacs'. This function is called with
+`save-some-buffers-default-predicate' let-bound to a value
+specified inside ARGS-RESULTS.
+
+During the call to FN-TEST,`read-event' is overridden with a function that
+just returns `n' and `kill-emacs' is overridden to do nothing.
+
+ARGS-RESULTS is a list of elements (FN-ARGS CALLERS-DIR EXPECTED), where
+FN-ARGS are the arguments for FN-TEST;
+CALLERS-DIR specifies the value to let-bind
+\`save-some-buffers-default-predicate';
+ EXPECTED is the expected result of the test."
+ (let* ((dir (make-temp-file "testdir" 'dir))
+ (inhibit-message t)
+ (use-dialog-box nil)
+ buffers)
+ (pcase-dolist (`(,bufsym ,offer-save) buffers-offer)
+ (let* ((buf (generate-new-buffer (symbol-name bufsym)))
+ (subdir (expand-file-name
+ (format "subdir-%s" (buffer-name buf))
+ dir)))
+ (make-directory subdir 'parens)
+ (push buf buffers)
+ (with-current-buffer buf
+ (cd subdir)
+ (setq buffer-offer-save offer-save)
+ (insert "foobar\n"))))
+ (setq buffers (nreverse buffers))
+ (let ((nb-saved-buffers 0))
+ (unwind-protect
+ (pcase-dolist (`(,fn-test-args ,callers-dir ,expected)
+ args-results)
+ (setq nb-saved-buffers 0)
+ (with-current-buffer (car buffers)
+ (cl-letf
+ (((symbol-function 'read-event)
+ ;; Increase counter and answer 'n' when prompted
+ ;; to save a buffer.
+ (lambda (&rest _) (cl-incf nb-saved-buffers) ?n))
+ ;; Do not kill Emacs.
+ ((symbol-function 'kill-emacs) #'ignore)
+ (save-some-buffers-default-predicate callers-dir))
+ (apply fn-test fn-test-args)
+ (should (equal nb-saved-buffers expected)))))
+ ;; Clean up.
+ (dolist (buf buffers)
+ (with-current-buffer buf
+ (set-buffer-modified-p nil)
+ (kill-buffer buf)))
+ (delete-directory dir 'recursive)))))
+
+(defmacro files-tests-with-all-permutations (permutation list &rest body)
+ "Execute BODY forms for all permutations of LIST.
+Execute the forms with the symbol PERMUTATION bound to the current
+permutation."
+ (declare (indent 2) (debug (symbol form body)))
+ (let ((vec (gensym "vec")))
+ `(let ((,vec (vconcat ,list)))
+ (cl-labels ((swap (,vec i j)
+ (let ((tmp (aref ,vec j)))
+ (aset ,vec j (aref ,vec i))
+ (aset ,vec i tmp)))
+ (permute (,vec l r)
+ (if (= l r)
+ (let ((,permutation (append ,vec nil)))
+ ,@body)
+ (cl-loop for idx from l below (1+ r) do
+ (swap ,vec idx l)
+ (permute ,vec (1+ l) r)
+ (swap ,vec idx l)))))
+ (permute ,vec 0 (1- (length ,vec)))))))
+
+(ert-deftest files-tests-buffer-offer-save ()
+ "Test `save-some-buffers' for non-file-visiting buffers.
+Check the behavior of `save-some-buffers' for non-file-visiting
+buffers under several values of `buffer-offer-save'.
+The value of `save-some-buffers-default-predicate' is ignored unless
+PRED is nil."
+ (let* ((buffers-offer-init '((buf-1 t) (buf-2 always) (buf-3 nil)))
+ (nb-might-save
+ (length
+ (cl-remove-if (lambda (l) (null (cadr l))) buffers-offer-init)))
+ (nb-always-save
+ (length
+ (cl-remove-if-not (lambda (l) (eq 'always (cadr l))) buffers-offer-init))))
+ (files-tests-with-all-permutations
+ buffers-offer
+ buffers-offer-init
+ (dolist (pred `(nil t))
+ (dolist (callers-dir `(nil save-some-buffers-root))
+ (let* ((head-offer (cadar buffers-offer))
+ (res (cond ((null pred)
+ (if (null callers-dir) nb-always-save (or (and head-offer 1) 0)))
+ (t
+ ;; Save any buffer with `buffer-offer-save' non-nil.
+ (if (eq pred t) nb-might-save
+ ;; Restrict to caller's dir.
+ (or (and head-offer 1) 0)))))
+ (args-res `(((nil ,pred) ,callers-dir ,res))))
+ (files-tests--with-buffer-offer-save
+ buffers-offer
+ #'save-some-buffers
+ args-res)))))))
+
+(ert-deftest files-tests-save-buffers-kill-emacs--asks-to-save-buffers ()
+ "Test that `save-buffers-kill-emacs' asks to save buffers as expected.
+Prompt users for any modified buffer with `buffer-offer-save' non-nil."
+ (let* ((buffers-offer-init '((buf-1 t) (buf-2 always) (buf-3 nil)))
+ (nb-might-save
+ (length
+ (cl-remove-if (lambda (l) (null (cadr l))) buffers-offer-init))))
+ (files-tests-with-all-permutations
+ buffers-offer
+ buffers-offer-init
+ (files-tests--with-buffer-offer-save
+ buffers-offer
+ #'save-buffers-kill-emacs
+ `((nil nil ,nb-might-save)
+ ;; `save-some-buffers-default-predicate' (i.e. the 2nd element) is ignored.
+ (nil save-some-buffers-root ,nb-might-save))))))
+
+(ert-deftest test-file-name-split ()
+ (should (equal (file-name-split "foo/bar") '("foo" "bar")))
+ (should (equal (file-name-split "/foo/bar") '("" "foo" "bar")))
+ (should (equal (file-name-split "/foo/bar/zot") '("" "foo" "bar" "zot")))
+ (should (equal (file-name-split "/foo/bar/") '("" "foo" "bar" "")))
+ (should (equal (file-name-split "foo/bar/") '("foo" "bar" ""))))
+
+(ert-deftest files-test-set-mode ()
+ (find-file (ert-resource-file "file-mode"))
+ (should (eq major-mode 'text-mode))
+ (emacs-lisp-mode)
+ ;; Check that the mode cookie doesn't override the explicit setting.
+ (should (eq major-mode 'emacs-lisp-mode)))
+
+(ert-deftest files-test-set-mode-multiple ()
+ (find-file (ert-resource-file "file-mode-multiple"))
+ (should (eq major-mode 'outline-mode)))
+
+(ert-deftest files-test-set-mode-prop-line ()
+ (find-file (ert-resource-file "file-mode-prop-line"))
+ (should (eq major-mode 'text-mode)))
+
+(ert-deftest files-load-elc-gz-file ()
+ (skip-unless (executable-find "gzip"))
+ (ert-with-temp-directory dir
+ (let* ((pref (expand-file-name "compile-utf8" dir))
+ (el (concat pref ".el")))
+ (copy-file (ert-resource-file "compile-utf8.el") el)
+ (push dir load-path)
+ (should (load pref t))
+ (should (fboundp 'foo))
+ (should (documentation 'foo))
+ (should (documentation 'bar))
+ (should (documentation 'zot))
+
+ (byte-compile-file el)
+ (fmakunbound 'foo)
+ (should (load (concat pref ".elc") t))
+ (should (fboundp 'foo))
+ (should (documentation 'foo))
+ (should (documentation 'bar))
+ (should (documentation 'zot))
+
+ (dired-compress-file (concat pref ".elc"))
+ (fmakunbound 'foo)
+ (should (load (concat pref ".elc.gz") t))
+ (should (fboundp 'foo))
+ ;; This fails due to bug#12598.
+ (should (documentation 'foo))
+ (should (documentation 'bar))
+ (should (documentation 'zot)))))
(provide 'files-tests)
;;; files-tests.el ends here
diff --git a/test/lisp/files-x-tests.el b/test/lisp/files-x-tests.el
index 21cb01c350c..7ee2f0c1a65 100644
--- a/test/lisp/files-x-tests.el
+++ b/test/lisp/files-x-tests.el
@@ -1,6 +1,6 @@
-;;; files-x-tests.el --- tests for files-x.el.
+;;; files-x-tests.el --- tests for files-x.el. -*- lexical-binding: t -*-
-;; Copyright (C) 2016-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2022 Free Software Foundation, Inc.
;; Author: Michael Albinus <michael.albinus@gmx.de>
@@ -35,6 +35,12 @@
'((remote-null-device . "/dev/null")))
(defconst files-x-test--variables4
'((remote-null-device . "null")))
+(defvar remote-null-device)
+(put 'remote-shell-file-name 'safe-local-variable #'identity)
+(put 'remote-shell-command-switch 'safe-local-variable #'identity)
+(put 'remote-shell-interactive-switch 'safe-local-variable #'identity)
+(put 'remote-shell-login-switch 'safe-local-variable #'identity)
+(put 'remote-null-device 'safe-local-variable #'identity)
(defconst files-x-test--application '(:application 'my-application))
(defconst files-x-test--another-application
@@ -101,15 +107,19 @@
(setq files-x-test--criteria
(append files-x-test--application files-x-test--protocol
files-x-test--user files-x-test--machine))
+
;; An empty variable list is accepted (but makes no sense).
(connection-local-set-profiles files-x-test--criteria)
(should-not (connection-local-get-profiles files-x-test--criteria))
+
+ ;; First test, all declared properties.
(connection-local-set-profiles
files-x-test--criteria 'remote-bash 'remote-ksh)
(should
(equal
(connection-local-get-profiles files-x-test--criteria)
'(remote-bash remote-ksh)))
+
;; Changing the order of properties doesn't matter.
(setq files-x-test--criteria
(append files-x-test--protocol files-x-test--application
@@ -118,12 +128,14 @@
(equal
(connection-local-get-profiles files-x-test--criteria)
'(remote-bash remote-ksh)))
- ;; A further call adds profiles.
+
+ ;; A further call adds profiles.
(connection-local-set-profiles files-x-test--criteria 'remote-nullfile)
(should
(equal
(connection-local-get-profiles files-x-test--criteria)
'(remote-bash remote-ksh remote-nullfile)))
+
;; Adding existing profiles doesn't matter.
(connection-local-set-profiles
files-x-test--criteria 'remote-bash 'remote-nullfile)
@@ -132,31 +144,38 @@
(connection-local-get-profiles files-x-test--criteria)
'(remote-bash remote-ksh remote-nullfile)))
- ;; Use a criteria without application.
- (setq files-x-test--criteria
- (append files-x-test--protocol
- files-x-test--user files-x-test--machine))
- (connection-local-set-profiles files-x-test--criteria 'remote-ksh)
- (should
- (equal
- (connection-local-get-profiles files-x-test--criteria)
- '(remote-ksh)))
- ;; An application not used in any registered criteria matches also this.
- (setq files-x-test--criteria
- (append files-x-test--another-application files-x-test--protocol
- files-x-test--user files-x-test--machine))
- (should
- (equal
- (connection-local-get-profiles files-x-test--criteria)
- '(remote-ksh)))
+ ;; Use different properties.
+ (dolist (criteria
+ `(;; All properties.
+ ,(append files-x-test--application files-x-test--protocol
+ files-x-test--user files-x-test--machine)
+ ;; Without :application.
+ ,(append files-x-test--protocol
+ files-x-test--user files-x-test--machine)
+ ;; Without :protocol.
+ ,(append files-x-test--application
+ files-x-test--user files-x-test--machine)
+ ;; Without :user.
+ ,(append files-x-test--application files-x-test--protocol
+ files-x-test--machine)
+ ;; Without :machine.
+ ,(append files-x-test--application files-x-test--protocol
+ files-x-test--user)
+ ;; No property at all.
+ nil))
+ (should
+ (equal
+ (connection-local-get-profiles criteria)
+ '(remote-bash remote-ksh remote-nullfile))))
;; Using a nil criteria also works. Duplicate profiles are trashed.
(connection-local-set-profiles
nil 'remote-bash 'remote-ksh 'remote-ksh 'remote-bash)
+ ;; This matches also the existing profiles from other criteria.
(should
(equal
(connection-local-get-profiles nil)
- '(remote-bash remote-ksh)))
+ '(remote-bash remote-ksh remote-nullfile)))
;; A criteria other than plist is wrong.
(should-error (connection-local-set-profiles 'dummy))))
@@ -235,7 +254,9 @@
;; declare same variables as in `remote-bash'.
(should
(equal connection-local-variables-alist
- (nreverse (copy-tree files-x-test--variables1))))
+ (append
+ (nreverse (copy-tree files-x-test--variables3))
+ (nreverse (copy-tree files-x-test--variables1)))))
;; The variables exist also as local variables.
(should (local-variable-p 'remote-shell-file-name))
;; The proper variable value is set.
@@ -253,7 +274,10 @@
(should-not (local-variable-p 'remote-shell-file-name))
(should-not (boundp 'remote-shell-file-name))))))
-(ert-deftest files-x-test-with-connection-local-profiles ()
+(defvar tramp-connection-local-default-shell-variables)
+(defvar tramp-connection-local-default-system-variables)
+
+(ert-deftest files-x-test-with-connection-local-variables ()
"Test setting connection-local variables."
(let (connection-local-profile-alist connection-local-criteria-alist)
@@ -288,46 +312,69 @@
(string-equal (symbol-value 'remote-null-device) "/dev/null"))
;; A candidate connection-local variable is not bound yet.
- (should-not (local-variable-p 'remote-shell-command-switch))
-
- ;; Use the macro.
- (with-connection-local-profiles '(remote-bash remote-ksh)
- ;; All connection-local variables are set. They apply in
- ;; reverse order in `connection-local-variables-alist'.
- ;; This variable keeps only the variables to be set inside
- ;; the macro.
- (should
- (equal connection-local-variables-alist
- (nreverse (copy-tree files-x-test--variables1))))
- ;; The variables exist also as local variables.
- (should (local-variable-p 'remote-shell-file-name))
- (should (local-variable-p 'remote-shell-command-switch))
- ;; The proper variable values are set. The settings from
- ;; `remote-bash' overwrite the same variables as in
- ;; `remote-ksh'.
- (should
- (string-equal (symbol-value 'remote-shell-file-name) "/bin/bash"))
- (should
- (string-equal (symbol-value 'remote-shell-command-switch) "-c")))
-
- ;; Everything is rewound. The old variable values are reset.
- (should
- (equal connection-local-variables-alist
- (append
- (nreverse (copy-tree files-x-test--variables3))
- (nreverse (copy-tree files-x-test--variables2)))))
- ;; The variables exist also as local variables.
- (should (local-variable-p 'remote-shell-file-name))
- (should (local-variable-p 'remote-null-device))
- ;; The proper variable values are set. The settings from
- ;; `remote-ksh' are back.
- (should
- (string-equal (symbol-value 'remote-shell-file-name) "/bin/ksh"))
- (should
- (string-equal (symbol-value 'remote-null-device) "/dev/null"))
+ (should-not (local-variable-p 'remote-shell-command-switch))))
- ;; The variable set temporarily is not unbound, again.
- (should-not (local-variable-p 'remote-shell-command-switch))))))
+ (with-temp-buffer
+ ;; Use the macro. We need a remote `default-directory'.
+ (let ((enable-connection-local-variables t)
+ (default-directory "/method:host:")
+ (remote-null-device "null"))
+ (should-not connection-local-variables-alist)
+ (should-not (local-variable-p 'remote-shell-file-name))
+ (should-not (local-variable-p 'remote-null-device))
+ (should-not (boundp 'remote-shell-file-name))
+ (should (string-equal (symbol-value 'remote-null-device) "null"))
+
+ (connection-local-set-profiles
+ files-x-test--application 'remote-bash)
+
+ (with-connection-local-variables
+ ;; All connection-local variables are set. They apply in
+ ;; reverse order in `connection-local-variables-alist'.
+ ;; Since we ha a remote default directory, Tramp's settings
+ ;; are appended as well.
+ (should
+ (equal
+ connection-local-variables-alist
+ (append
+ (nreverse (copy-tree files-x-test--variables3))
+ (nreverse (copy-tree files-x-test--variables2))
+ (nreverse
+ (copy-tree tramp-connection-local-default-shell-variables))
+ (nreverse
+ (copy-tree tramp-connection-local-default-system-variables)))))
+ ;; The variables exist also as local variables.
+ (should (local-variable-p 'remote-shell-file-name))
+ (should (local-variable-p 'remote-null-device))
+ ;; The proper variable values are set.
+ (should
+ (string-equal (symbol-value 'remote-shell-file-name) "/bin/ksh"))
+ (should
+ (string-equal (symbol-value 'remote-null-device) "/dev/null"))
+
+ ;; Run another instance of `with-connection-local-variables'
+ ;; with a different application.
+ (let ((connection-local-default-application (cadr files-x-test--application)))
+ (with-connection-local-variables
+ ;; The proper variable values are set.
+ (should
+ (string-equal (symbol-value 'remote-shell-file-name) "/bin/bash"))
+ (should
+ (string-equal (symbol-value 'remote-null-device) "/dev/null"))))
+ ;; The variable values are reset.
+ (should
+ (string-equal (symbol-value 'remote-shell-file-name) "/bin/ksh"))
+ (should
+ (string-equal (symbol-value 'remote-null-device) "/dev/null")))
+
+ ;; Everything is rewound. The old variable values are reset.
+ (should-not connection-local-variables-alist)
+ ;; The variables don't exist as local variables.
+ (should-not (local-variable-p 'remote-shell-file-name))
+ (should-not (local-variable-p 'remote-null-device))
+ ;; The variable values are reset.
+ (should-not (boundp 'remote-shell-file-name))
+ (should (string-equal (symbol-value 'remote-null-device) "null"))))))
(provide 'files-x-tests)
;;; files-x-tests.el ends here
diff --git a/test/lisp/find-cmd-tests.el b/test/lisp/find-cmd-tests.el
new file mode 100644
index 00000000000..853ac9e27b4
--- /dev/null
+++ b/test/lisp/find-cmd-tests.el
@@ -0,0 +1,45 @@
+;;; find-cmd-tests.el --- tests for find-cmd.el. -*- lexical-binding: t -*-
+
+;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'find-cmd)
+
+(ert-deftest find-cmd-test-find-cmd ()
+ (should
+ (string-match
+ (rx "find " (+ any)
+ " \\( \\( -name .svn -or -name .git -or -name .CVS \\)"
+ " -prune -or -true \\)"
+ " \\( \\( \\(" " -name \\*.pl -or -name \\*.pm -or -name \\*.t \\)"
+ " -or -mtime \\+1 \\) -and \\( -fstype nfs -or -fstype ufs \\) \\) ")
+ (find-cmd '(prune (name ".svn" ".git" ".CVS"))
+ '(and (or (name "*.pl" "*.pm" "*.t")
+ (mtime "+1"))
+ (fstype "nfs" "ufs"))))))
+
+(ert-deftest find-cmd-test-find-cmd/error-unknown-atom ()
+ (should-error (find-cmd '(unknown 123))))
+
+(ert-deftest find-cmd-test-find-cmd/error-wrong-argnum ()
+ (should-error (find-cmd '(name))))
+
+(provide 'find-cmd-tests)
+;;; find-cmd-tests.el ends here
diff --git a/test/lisp/font-lock-tests.el b/test/lisp/font-lock-tests.el
new file mode 100644
index 00000000000..acdfc5a63da
--- /dev/null
+++ b/test/lisp/font-lock-tests.el
@@ -0,0 +1,41 @@
+;;; font-lock-tests.el --- Test suite for font-lock. -*- lexical-binding: t -*-
+
+;; Copyright (C) 2019-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+(require 'ert)
+
+(ert-deftest font-lock-test-append-anonymous-face ()
+ "Ensure `font-lock-append-text-property' does not splice anonymous faces."
+ (with-temp-buffer
+ (insert "foo")
+ (add-text-properties 1 3 '(face italic))
+ (font-lock-append-text-property 1 3 'face '(:strike-through t))
+ (should (equal (get-text-property 1 'face (current-buffer))
+ '(italic (:strike-through t))))))
+
+(ert-deftest font-lock-test-prepend-anonymous-face ()
+ "Ensure `font-lock-prepend-text-property' does not splice anonymous faces."
+ (with-temp-buffer
+ (insert "foo")
+ (add-text-properties 1 3 '(face italic))
+ (font-lock-prepend-text-property 1 3 'face '(:strike-through t))
+ (should (equal (get-text-property 1 'face (current-buffer))
+ '((:strike-through t) italic)))))
+
+;; font-lock-tests.el ends here
diff --git a/test/lisp/format-spec-tests.el b/test/lisp/format-spec-tests.el
new file mode 100644
index 00000000000..4a3cc74c334
--- /dev/null
+++ b/test/lisp/format-spec-tests.el
@@ -0,0 +1,191 @@
+;;; format-spec-tests.el --- tests for format-spec.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2019-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'format-spec)
+
+(ert-deftest format-spec-make ()
+ "Test `format-spec-make'."
+ (should-not (format-spec-make))
+ (should-error (format-spec-make ?b))
+ (should (equal (format-spec-make ?b "b") '((?b . "b"))))
+ (should-error (format-spec-make ?b "b" ?a))
+ (should (equal (format-spec-make ?b "b" ?a 'a)
+ '((?b . "b")
+ (?a . a)))))
+
+(ert-deftest format-spec-parse-flags ()
+ "Test `format-spec--parse-flags'."
+ (should-not (format-spec--parse-flags nil))
+ (should-not (format-spec--parse-flags ""))
+ (should (equal (format-spec--parse-flags "-") '(:pad-right)))
+ (should (equal (format-spec--parse-flags " 0") '(:pad-zero)))
+ (should (equal (format-spec--parse-flags " -x0y< >^_z ")
+ '(:pad-right :pad-zero :chop-left :chop-right
+ :upcase :downcase))))
+
+(ert-deftest format-spec-do-flags ()
+ "Test `format-spec--do-flags'."
+ (should (equal (format-spec--do-flags "" () nil nil) ""))
+ (dolist (flag '(:pad-zero :pad-right :upcase :downcase
+ :chop-left :chop-right))
+ (should (equal (format-spec--do-flags "" (list flag) nil nil) "")))
+ (should (equal (format-spec--do-flags "FOOBAR" '(:downcase :chop-right) 5 2)
+ " fo"))
+ (should (equal (format-spec--do-flags
+ "foobar" '(:pad-zero :pad-right :upcase :chop-left) 5 2)
+ "AR000")))
+
+(ert-deftest format-spec-do-flags-truncate ()
+ "Test `format-spec--do-flags' truncation."
+ (let ((flags nil))
+ (should (equal (format-spec--do-flags "" flags nil 0) ""))
+ (should (equal (format-spec--do-flags "" flags nil 1) ""))
+ (should (equal (format-spec--do-flags "a" flags nil 0) ""))
+ (should (equal (format-spec--do-flags "a" flags nil 1) "a"))
+ (should (equal (format-spec--do-flags "a" flags nil 2) "a"))
+ (should (equal (format-spec--do-flags "asd" flags nil 0) ""))
+ (should (equal (format-spec--do-flags "asd" flags nil 1) "a")))
+ (let ((flags '(:chop-left)))
+ (should (equal (format-spec--do-flags "" flags nil 0) ""))
+ (should (equal (format-spec--do-flags "" flags nil 1) ""))
+ (should (equal (format-spec--do-flags "a" flags nil 0) ""))
+ (should (equal (format-spec--do-flags "a" flags nil 1) "a"))
+ (should (equal (format-spec--do-flags "a" flags nil 2) "a"))
+ (should (equal (format-spec--do-flags "asd" flags nil 0) ""))
+ (should (equal (format-spec--do-flags "asd" flags nil 1) "d"))))
+
+(ert-deftest format-spec-do-flags-pad ()
+ "Test `format-spec--do-flags' padding."
+ (let ((flags nil))
+ (should (equal (format-spec--do-flags "" flags 0 nil) ""))
+ (should (equal (format-spec--do-flags "" flags 1 nil) " "))
+ (should (equal (format-spec--do-flags "a" flags 0 nil) "a"))
+ (should (equal (format-spec--do-flags "a" flags 1 nil) "a"))
+ (should (equal (format-spec--do-flags "a" flags 2 nil) " a")))
+ (let ((flags '(:pad-zero)))
+ (should (equal (format-spec--do-flags "" flags 0 nil) ""))
+ (should (equal (format-spec--do-flags "" flags 1 nil) "0"))
+ (should (equal (format-spec--do-flags "a" flags 0 nil) "a"))
+ (should (equal (format-spec--do-flags "a" flags 1 nil) "a"))
+ (should (equal (format-spec--do-flags "a" flags 2 nil) "0a")))
+ (let ((flags '(:pad-right)))
+ (should (equal (format-spec--do-flags "" flags 0 nil) ""))
+ (should (equal (format-spec--do-flags "" flags 1 nil) " "))
+ (should (equal (format-spec--do-flags "a" flags 0 nil) "a"))
+ (should (equal (format-spec--do-flags "a" flags 1 nil) "a"))
+ (should (equal (format-spec--do-flags "a" flags 2 nil) "a ")))
+ (let ((flags '(:pad-right :pad-zero)))
+ (should (equal (format-spec--do-flags "" flags 0 nil) ""))
+ (should (equal (format-spec--do-flags "" flags 1 nil) "0"))
+ (should (equal (format-spec--do-flags "a" flags 0 nil) "a"))
+ (should (equal (format-spec--do-flags "a" flags 1 nil) "a"))
+ (should (equal (format-spec--do-flags "a" flags 2 nil) "a0"))))
+
+(ert-deftest format-spec-do-flags-chop ()
+ "Test `format-spec--do-flags' chopping."
+ (let ((flags '(:chop-left)))
+ (should (equal (format-spec--do-flags "a" flags 0 nil) ""))
+ (should (equal (format-spec--do-flags "a" flags 1 nil) "a"))
+ (should (equal (format-spec--do-flags "asd" flags 0 nil) ""))
+ (should (equal (format-spec--do-flags "asd" flags 1 nil) "d")))
+ (let ((flags '(:chop-right)))
+ (should (equal (format-spec--do-flags "a" flags 0 nil) ""))
+ (should (equal (format-spec--do-flags "a" flags 1 nil) "a"))
+ (should (equal (format-spec--do-flags "asd" flags 0 nil) ""))
+ (should (equal (format-spec--do-flags "asd" flags 1 nil) "a"))))
+
+(ert-deftest format-spec-do-flags-case ()
+ "Test `format-spec--do-flags' case fiddling."
+ (dolist (flag '(:pad-zero :pad-right :chop-left :chop-right))
+ (let ((flags (list flag)))
+ (should (equal (format-spec--do-flags "a" flags nil nil) "a"))
+ (should (equal (format-spec--do-flags "A" flags nil nil) "A")))
+ (let ((flags (list flag :downcase)))
+ (should (equal (format-spec--do-flags "a" flags nil nil) "a"))
+ (should (equal (format-spec--do-flags "A" flags nil nil) "a")))
+ (let ((flags (list flag :upcase)))
+ (should (equal (format-spec--do-flags "a" flags nil nil) "A"))
+ (should (equal (format-spec--do-flags "A" flags nil nil) "A")))))
+
+(ert-deftest format-spec ()
+ (should (equal (format-spec "" ()) ""))
+ (should (equal (format-spec "a" ()) "a"))
+ (should (equal (format-spec "b" '((?b . "bar"))) "b"))
+ (should (equal (format-spec "%%%b%%b%b%%" '((?b . "bar"))) "%bar%bbar%"))
+ (should (equal (format-spec "foo %b zot" `((?b . "bar")))
+ "foo bar zot"))
+ (should (equal (format-spec "foo %-10b zot" '((?b . "bar")))
+ "foo bar zot"))
+ (should (equal (format-spec "foo %10b zot" '((?b . "bar")))
+ "foo bar zot"))
+ (should (equal-including-properties
+ (format-spec (propertize "a" 'a 'b) '((?a . "foo")))
+ #("a" 0 1 (a b))))
+ (let ((fmt (concat (propertize "%a" 'a 'b)
+ (propertize "%%" 'c 'd)
+ "%b"
+ (propertize "%b" 'e 'f))))
+ (should (equal-including-properties
+ (format-spec fmt '((?b . "asd") (?a . "fgh")))
+ #("fgh%asdasd" 0 3 (a b) 3 4 (c d) 7 10 (e f))))))
+
+(ert-deftest format-spec-unknown ()
+ (should-error (format-spec "foo %b %z zot" '((?b . "bar"))))
+ (should-error (format-spec "foo %b %%%z zot" '((?b . "bar"))))
+ (should (equal (format-spec "foo %b %z zot" '((?b . "bar")) t)
+ "foo bar %z zot"))
+ (should (equal (format-spec "foo %4b %%%4z %%4 zot" '((?b . "bar")) t)
+ "foo bar %%%4z %%4 zot"))
+ (should (equal (format-spec "foo %4b %%%4z %%4 zot" '((?b . "bar")) 'ignore)
+ "foo bar %%4z %4 zot"))
+ (should (equal (format-spec "foo %4b %%%4z %%4 zot" '((?b . "bar")) 'delete)
+ "foo bar % %4 zot")))
+
+(ert-deftest format-spec-flags ()
+ (should (equal (format-spec "foo %10b zot" '((?b . "bar")))
+ "foo bar zot"))
+ (should (equal (format-spec "foo % 10b zot" '((?b . "bar")))
+ "foo bar zot"))
+ (should (equal (format-spec "foo %-010b zot" '((?b . "bar")))
+ "foo bar0000000 zot"))
+ (should (equal (format-spec "foo %0-10b zot" '((?b . "bar")))
+ "foo bar0000000 zot"))
+ (should (equal (format-spec "foo %^10b zot" '((?b . "bar")))
+ "foo BAR zot"))
+ (should (equal (format-spec "foo %_10b zot" '((?b . "BAR")))
+ "foo bar zot"))
+ (should (equal (format-spec "foo %<4b zot" '((?b . "longbar")))
+ "foo gbar zot"))
+ (should (equal (format-spec "foo %>4b zot" '((?b . "longbar")))
+ "foo long zot")))
+
+(ert-deftest format-spec-split ()
+ (should (equal (format-spec "foo %b bar" '((?b . "zot")) nil t)
+ '("foo " "zot" " bar")))
+ (should (equal (format-spec "%b bar" '((?b . "zot")) nil t)
+ '("zot" " bar")))
+ (should (equal (format-spec "%b" '((?b . "zot")) nil t)
+ '("zot")))
+ (should (equal (format-spec "foo %b" '((?b . "zot")) nil t)
+ '("foo " "zot"))))
+
+;;; format-spec-tests.el ends here
diff --git a/test/lisp/gnus/gnus-group-tests.el b/test/lisp/gnus/gnus-group-tests.el
new file mode 100644
index 00000000000..4ae5fea3eb7
--- /dev/null
+++ b/test/lisp/gnus/gnus-group-tests.el
@@ -0,0 +1,52 @@
+;;; gnus-group-tests.el --- Tests for gnus-group.el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;
+
+;;; Code:
+
+(require 'gnus-group)
+(require 'ert)
+
+(ert-deftest gnus-short-group-name ()
+ (map-apply
+ (lambda (input expected)
+ (should (string-equal (gnus-short-group-name input) expected)))
+ '(("nnimap+email@example.com:archives/2020/03" . "email@example:a/2/03")
+ ("nndiary+diary:birthdays" . "diary:birthdays")
+ ("nnimap+email@example.com:test" . "email@example:test")
+ ("nnimap+email@example.com:234" . "email@example:234")
+
+ ;; This is a very aggressive shortening of the left hand side.
+ ("nnimap+email@banana.salesman.example.com:234" . "email@banana:234")
+ ("nntp+some.where.edu:soc.motss" . "some:s.motss")
+ ("nntp+news.gmane.org:gmane.emacs.gnus.general" . "news:g.e.g.general")
+ ("nntp+news.gnus.org:gmane.text.docbook.apps" . "news:g.t.d.apps")
+
+ ;; nnimap groups.
+ ("nnimap+email@example.com:[Invoices]/Bananas" . "email@example:I/Bananas")
+ ("nnimap+email@banana.salesman.example.com:[Invoices]/Bananas"
+ . "email@banana:I/Bananas")
+
+ ;; The "n" from "nnspool" is perhaps not optimal.
+ ("nnspool+alt.binaries.pictures.furniture" . "n.b.p.furniture"))))
+
+;;; gnus-group-tests.el ends here
diff --git a/test/lisp/gnus/gnus-icalendar-tests.el b/test/lisp/gnus/gnus-icalendar-tests.el
new file mode 100644
index 00000000000..348ddf9f056
--- /dev/null
+++ b/test/lisp/gnus/gnus-icalendar-tests.el
@@ -0,0 +1,259 @@
+;;; gnus-icalendar-tests.el --- tests -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+;; Author: Jan Tatarik <jan.tatarik@gmail.com>
+;; Keywords:
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;
+
+;;; Code:
+
+(require 'ert)
+(require 'gnus-icalendar)
+
+
+(defun gnus-icalendar-tests--get-ical-event (ical-string &optional participant)
+ "Return gnus-icalendar event for ICAL-STRING."
+ (let (event)
+ (with-temp-buffer
+ (insert ical-string)
+ (setq event (gnus-icalendar-event-from-buffer (buffer-name) participant)))
+ event))
+
+(ert-deftest gnus-icalendar-parse ()
+ "test"
+ (let ((tz (getenv "TZ"))
+ (event (gnus-icalendar-tests--get-ical-event "\
+BEGIN:VCALENDAR
+PRODID:-//Google Inc//Google Calendar 70.9054//EN
+VERSION:2.0
+CALSCALE:GREGORIAN
+METHOD:REQUEST
+BEGIN:VTIMEZONE
+TZID:America/New_York
+X-LIC-LOCATION:America/New_York
+BEGIN:DAYLIGHT
+TZOFFSETFROM:-0500
+TZOFFSETTO:-0400
+TZNAME:EDT
+DTSTART:19700308T020000
+RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU
+END:DAYLIGHT
+BEGIN:STANDARD
+TZOFFSETFROM:-0400
+TZOFFSETTO:-0500
+TZNAME:EST
+DTSTART:19701101T020000
+RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU
+END:STANDARD
+END:VTIMEZONE
+BEGIN:VEVENT
+DTSTART;TZID=America/New_York:20201208T090000
+DTEND;TZID=America/New_York:20201208T100000
+DTSTAMP:20200728T182853Z
+ORGANIZER;CN=Company Events:mailto:anoncompany.com_3bm6fh805bme9uoeliqcle1sa
+ g@group.calendar.google.com
+UID:iipdt88slddpeu7hheuu09sfmd@google.com
+X-MICROSOFT-CDO-OWNERAPPTID:-362490173
+RECURRENCE-ID;TZID=America/New_York:20201208T091500
+CREATED:20200309T134939Z
+DESCRIPTION:In this meeting\\, we will cover topics from product and enginee
+ ring presentations and demos to new hire announcements to watching the late
+LAST-MODIFIED:20200728T182852Z
+LOCATION:New York-22-Town Hall Space (250) [Chrome Box]
+SEQUENCE:4
+STATUS:CONFIRMED
+SUMMARY:Townhall | All Company Meeting
+TRANSP:OPAQUE
+END:VEVENT
+END:VCALENDAR
+")))
+
+ (unwind-protect
+ (progn
+ ;; Use this form so as not to rely on system tz database.
+ ;; Eg hydra.nixos.org.
+ (setenv "TZ" "CET-1CEST,M3.5.0/2,M10.5.0/3")
+ (should (eq (eieio-object-class event) 'gnus-icalendar-event-request))
+ (should (not (gnus-icalendar-event:recurring-p event)))
+ (should (string= (gnus-icalendar-event:start event) "2020-12-08 15:00"))
+ (with-slots (organizer summary description location end-time uid rsvp participation-type) event
+ (should (string= organizer "anoncompany.com_3bm6fh805bme9uoeliqcle1sag@group.calendar.google.com"))
+ (should (string= summary "Townhall | All Company Meeting"))
+ (should (string= description "In this meeting, we will cover topics from product and engineering presentations and demos to new hire announcements to watching the late"))
+ (should (string= location "New York-22-Town Hall Space (250) [Chrome Box]"))
+ (should (string= (format-time-string "%Y-%m-%d %H:%M" end-time) "2020-12-08 16:00"))
+ (should (string= uid "iipdt88slddpeu7hheuu09sfmd@google.com"))
+ (should (not rsvp))
+ (should (eq participation-type 'non-participant))))
+ (setenv "TZ" tz))))
+
+(ert-deftest gnus-icalendary-byday ()
+ ""
+ (let ((tz (getenv "TZ"))
+ (event (gnus-icalendar-tests--get-ical-event "\
+BEGIN:VCALENDAR
+PRODID:Zimbra-Calendar-Provider
+VERSION:2.0
+METHOD:REQUEST
+BEGIN:VTIMEZONE
+TZID:America/New_York
+BEGIN:STANDARD
+DTSTART:16010101T020000
+TZOFFSETTO:-0500
+TZOFFSETFROM:-0400
+RRULE:FREQ=YEARLY;WKST=MO;INTERVAL=1;BYMONTH=11;BYDAY=1SU
+TZNAME:EST
+END:STANDARD
+BEGIN:DAYLIGHT
+DTSTART:16010101T020000
+TZOFFSETTO:-0400
+TZOFFSETFROM:-0500
+RRULE:FREQ=YEARLY;WKST=MO;INTERVAL=1;BYMONTH=3;BYDAY=2SU
+TZNAME:EDT
+END:DAYLIGHT
+END:VTIMEZONE
+BEGIN:VEVENT
+UID:903a5415-9067-4f63-b499-1b6205f49c88
+RRULE:FREQ=DAILY;UNTIL=20200825T035959Z;INTERVAL=1;BYDAY=MO,TU,WE,TH,FR
+SUMMARY:appointment every weekday\\, start jul 24\\, 2020\\, end aug 24\\, 2020
+ATTENDEE;CN=Mark Hershberger;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP
+ =TRUE:mailto:hexmode <at> gmail.com
+ORGANIZER;CN=Mark A. Hershberger:mailto:mah <at> nichework.com
+DTSTART;TZID=\"America/New_York\":20200724T090000
+DTEND;TZID=\"America/New_York\":20200724T093000
+STATUS:CONFIRMED
+CLASS:PUBLIC
+X-MICROSOFT-CDO-INTENDEDSTATUS:BUSY
+TRANSP:OPAQUE
+LAST-MODIFIED:20200719T150815Z
+DTSTAMP:20200719T150815Z
+SEQUENCE:0
+DESCRIPTION:The following is a new meeting request:
+BEGIN:VALARM
+ACTION:DISPLAY
+TRIGGER;RELATED=START:-PT5M
+DESCRIPTION:Reminder
+END:VALARM
+END:VEVENT
+END:VCALENDAR" (list "Mark Hershberger"))))
+
+ (unwind-protect
+ (progn
+ ;; Use this form so as not to rely on system tz database.
+ ;; Eg hydra.nixos.org.
+ (setenv "TZ" "CET-1CEST,M3.5.0/2,M10.5.0/3")
+ (should (eq (eieio-object-class event) 'gnus-icalendar-event-request))
+ (should (gnus-icalendar-event:recurring-p event))
+ (should (string= (gnus-icalendar-event:recurring-interval event) "1"))
+ (should (string= (gnus-icalendar-event:start event) "2020-07-24 15:00"))
+ (with-slots (organizer summary description location end-time uid rsvp participation-type) event
+ (should (string= organizer "mah <at> nichework.com"))
+ (should (string= summary "appointment every weekday, start jul 24, 2020, end aug 24, 2020"))
+ (should (string= description "The following is a new meeting request:"))
+ (should (null location))
+ (should (string= (format-time-string "%Y-%m-%d %H:%M" end-time) "2020-07-24 15:30"))
+ (should (string= uid "903a5415-9067-4f63-b499-1b6205f49c88"))
+ (should rsvp)
+ (should (eq participation-type 'required)))
+ (should (equal (gnus-icalendar-event:recurring-days event) '(1 2 3 4 5)))
+ (should (string= (gnus-icalendar-event:org-timestamp event) "<2020-07-24 15:00-15:30 +1w>
+<2020-07-27 15:00-15:30 +1w>
+<2020-07-28 15:00-15:30 +1w>
+<2020-07-29 15:00-15:30 +1w>
+<2020-07-30 15:00-15:30 +1w>")))
+ (setenv "TZ" tz))))
+
+(ert-deftest gnus-icalendary-weekly-byday ()
+ ""
+ (let ((tz (getenv "TZ"))
+ (event (gnus-icalendar-tests--get-ical-event "\
+BEGIN:VCALENDAR
+PRODID:-//Google Inc//Google Calendar 70.9054//EN
+VERSION:2.0
+CALSCALE:GREGORIAN
+METHOD:REQUEST
+BEGIN:VTIMEZONE
+TZID:Europe/Berlin
+X-LIC-LOCATION:Europe/Berlin
+BEGIN:DAYLIGHT
+TZOFFSETFROM:+0100
+TZOFFSETTO:+0200
+TZNAME:CEST
+DTSTART:19700329T020000
+RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU
+END:DAYLIGHT
+BEGIN:STANDARD
+TZOFFSETFROM:+0200
+TZOFFSETTO:+0100
+TZNAME:CET
+DTSTART:19701025T030000
+RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU
+END:STANDARD
+END:VTIMEZONE
+BEGIN:VEVENT
+DTSTART;TZID=Europe/Berlin:20200915T140000
+DTEND;TZID=Europe/Berlin:20200915T143000
+RRULE:FREQ=WEEKLY;BYDAY=FR,MO,TH,TU,WE
+DTSTAMP:20200915T120627Z
+ORGANIZER;CN=anon@anoncompany.com:mailto:anon@anoncompany.com
+UID:7b6g3m7iftuo90ei4ul00feqn_R20200915T120000@google.com
+ATTENDEE;CUTYPE=INDIVIDUAL;PARTSTAT=ACCEPTED;RSVP=TRUE
+ ;CN=participant@anoncompany.com;X-NUM-GUESTS=0:mailto:participant@anoncompany.com
+CREATED:20200325T095723Z
+DESCRIPTION:Coffee talk
+LAST-MODIFIED:20200915T120623Z
+LOCATION:
+SEQUENCE:0
+STATUS:CONFIRMED
+SUMMARY:Casual coffee talk
+TRANSP:OPAQUE
+END:VEVENT
+END:VCALENDAR" (list "participant@anoncompany.com"))))
+
+ (unwind-protect
+ (progn
+ ;; Use this form so as not to rely on system tz database.
+ ;; Eg hydra.nixos.org.
+ (setenv "TZ" "CET-1CEST,M3.5.0/2,M10.5.0/3")
+ (should (eq (eieio-object-class event) 'gnus-icalendar-event-request))
+ (should (gnus-icalendar-event:recurring-p event))
+ (should (string= (gnus-icalendar-event:recurring-interval event) "1"))
+ (should (string= (gnus-icalendar-event:start event) "2020-09-15 14:00"))
+ (with-slots (organizer summary description location end-time uid rsvp participation-type) event
+ (should (string= organizer "anon@anoncompany.com"))
+ (should (string= summary "Casual coffee talk"))
+ (should (string= description "Coffee talk"))
+ (should (string= location ""))
+ (should (string= (format-time-string "%Y-%m-%d %H:%M" end-time) "2020-09-15 14:30"))
+ (should (string= uid "7b6g3m7iftuo90ei4ul00feqn_R20200915T120000@google.com"))
+ (should rsvp)
+ (should (eq participation-type 'required)))
+ (should (equal (sort (gnus-icalendar-event:recurring-days event) #'<) '(1 2 3 4 5)))
+ (should (string= (gnus-icalendar-event:org-timestamp event) "<2020-09-15 14:00-14:30 +1w>
+<2020-09-16 14:00-14:30 +1w>
+<2020-09-17 14:00-14:30 +1w>
+<2020-09-18 14:00-14:30 +1w>
+<2020-09-21 14:00-14:30 +1w>")))
+ (setenv "TZ" tz))))
+
+(provide 'gnus-icalendar-tests)
+;;; gnus-icalendar-tests.el ends here
diff --git a/test/lisp/gnus/gnus-search-tests.el b/test/lisp/gnus/gnus-search-tests.el
new file mode 100644
index 00000000000..4a5def97d3c
--- /dev/null
+++ b/test/lisp/gnus/gnus-search-tests.el
@@ -0,0 +1,100 @@
+;;; gnus-search-tests.el --- Tests for Gnus' search routines -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2017, 2021-2022 Free Software Foundation, Inc.
+
+;; Author: Eric Abrahamsen <eric@ericabrahamsen.net>
+;; Keywords:
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Tests for the search parsing, search engines, and their
+;; transformations.
+
+;;; Code:
+
+(require 'ert)
+(require 'gnus-search)
+
+(ert-deftest gnus-s-parse ()
+ "Test basic structural parsing."
+ (let ((pairs
+ '(("string" . ("string"))
+ ("from:john" . ((from . "john")))
+ ("here and there" . ("here" and "there"))
+ ("here or there" . ((or "here" "there")))
+ ("here (there or elsewhere)" . ("here" ((or "there" "elsewhere"))))
+ ("here not there" . ("here" (not "there")))
+ ("from:boss or not vacation" . ((or (from . "boss") (not "vacation")))))))
+ (dolist (p pairs)
+ (should (equal (gnus-search-parse-query (car p)) (cdr p))))))
+
+(ert-deftest gnus-s-expand-keyword ()
+ "Test expansion of keywords"
+ (let ((gnus-search-expandable-keys
+ (default-value 'gnus-search-expandable-keys))
+ (pairs
+ '(("su" . "subject")
+ ("sin" . "since")
+ ("body" . "body")
+ ("list-id" . "list-id"))))
+ (dolist (p pairs)
+ (should (equal (gnus-search-query-expand-key (car p))
+ (cdr p))))
+ (should-error (gnus-search-query-expand-key "s")
+ :type 'gnus-search-parse-error)))
+
+(ert-deftest gnus-s-parse-date ()
+ "Test parsing of date expressions."
+ (let ((rel-date (encode-time 0 0 0 15 4 2017))
+ (pairs
+ '(("January" . (nil 1 nil))
+ ("2017" . (nil nil 2017))
+ ("15" . (15 nil nil))
+ ("January 15" . (15 1 nil))
+ ("tuesday" . (11 4 2017))
+ ("1d" . (14 4 2017))
+ ("1w" . (8 4 2017)))))
+ (dolist (p pairs)
+ (should (equal (gnus-search-query-parse-date (car p) rel-date)
+ (cdr p))))))
+
+(ert-deftest gnus-s-delimited-string ()
+ "Test proper functioning of `gnus-search-query-return-string'."
+ (with-temp-buffer
+ (insert "one\ntwo words\nthree \"words with quotes\"\n\"quotes at start\"\n/alternate \"quotes\"/\n(more bits)")
+ (goto-char (point-min))
+ (should (string= (gnus-search-query-return-string)
+ "one"))
+ (forward-line)
+ (should (string= (gnus-search-query-return-string)
+ "two"))
+ (forward-line)
+ (should (string= (gnus-search-query-return-string)
+ "three"))
+ (forward-line)
+ (should (string= (gnus-search-query-return-string "\"")
+ "\"quotes at start\""))
+ (forward-line)
+ (should (string= (gnus-search-query-return-string "/")
+ "/alternate \"quotes\"/"))
+ (forward-line)
+ (should (string= (gnus-search-query-return-string ")" t)
+ "more bits"))))
+
+(provide 'gnus-search-tests)
+;;; gnus-search-tests.el ends here
diff --git a/test/lisp/gnus/gnus-test-headers.el b/test/lisp/gnus/gnus-test-headers.el
new file mode 100644
index 00000000000..730c10f9818
--- /dev/null
+++ b/test/lisp/gnus/gnus-test-headers.el
@@ -0,0 +1,178 @@
+;;; gnus-test-headers.el --- Tests for Gnus header-related functions -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2018-2022 Free Software Foundation, Inc.
+
+;; Author: Eric Abrahamsen <eric@ericabrahamsen.net>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; The tests her are for
+
+;;; Code:
+
+(require 'ert)
+(require 'gnus-sum)
+
+(defconst gnus-headers-test-data
+ '([2 "Re: [Emacs-devel] Emacs move" "Dave Love <d.love@dl.ac.uk>"
+ "Thu, 14 Sep 2000 11:10:46 +0100"
+ "<200009141010.LAA26351@djlvig.dl.ac.uk>"
+ "<20000913175943.A26093@sparky.nisa.net>"
+ 1882 16 "nnmaildir mails:2"
+ ((To . "Jeff Bailey <jbailey@nisa.net>")
+ (Cc . "emacs-devel@gnu.org, cvs-hackers@gnu.org"))]
+ [3 "Re: [Emacs-devel] Emacs move" "Sam Steingold <sds@gnu.org>"
+ "14 Sep 2000 10:21:56 -0400" "<upum7xddn.fsf@xchange.com>"
+ "<20000913175943.A26093@sparky.nisa.net>"
+ 2991 50 "nnmaildir mails:3"
+ ((To . "Jeff Bailey <jbailey@nisa.net>")
+ (Cc . "emacs-devel@gnu.org, cvs-hackers@gnu.org"))]
+ [4 "Re: [Emacs-devel] Emacs move" "Jeff Bailey <jbailey@nisa.net>"
+ "Thu, 14 Sep 2000 09:14:47 -0700"
+ "<20000914091447.G4827@sparky.nisa.net>"
+ "<20000913175943.A26093@sparky.nisa.net> <upum7xddn.fsf@xchange.com>"
+ 1780 15 "nnmaildir mails:4"
+ ((To . "sds@gnu.org, Jeff Bailey <jbailey@nisa.net>")
+ (Cc . "emacs-devel@gnu.org, cvs-hackers@gnu.org"))]
+ [5 "Re: [Emacs-devel] Emacs move" "Dave Love <d.love@dl.ac.uk>"
+ "Thu, 14 Sep 2000 18:24:36 +0100"
+ "<200009141724.SAA26807@djlvig.dl.ac.uk>"
+ "<20000913175943.A26093@sparky.nisa.net>"
+ 1343 9 "nnmaildir mails:5"
+ ((To . "Jeff Bailey <jbailey@nisa.net>")
+ (Cc . "emacs-devel@gnu.org, cvs-hackers@gnu.org"))]
+ [6 "Re: [Emacs-devel] Emacs move" "Karl Fogel <kfogel@galois.collab.net>"
+ "14 Sep 2000 10:37:35 -0500" "<87em2nyog0.fsf@galois.collab.net>"
+ "<20000913175943.A26093@sparky.nisa.net> <200009141724.SAA26807@djlvig.dl.ac.uk>"
+ 3740 124 "nnmaildir mails:6"
+ ((To . "Dave Love <d.love@dl.ac.uk>")
+ (Cc . "Jeff Bailey <jbailey@nisa.net>, emacs-devel@gnu.org, cvs-hackers@gnu.org"))]
+ [7 "Re: [Emacs-devel] Emacs move" "Jeff Bailey <jbailey@nisa.net>"
+ "Thu, 14 Sep 2000 10:55:12 -0700"
+ "<20000914105512.A29291@sparky.nisa.net>"
+ "<20000913175943.A26093@sparky.nisa.net> <200009141724.SAA26807@djlvig.dl.ac.uk> <87em2nyog0.fsf@galois.collab.net>"
+ 1687 16 "nnmaildir mails:7"
+ ((To . "kfogel@red-bean.com, Dave Love <d.love@dl.ac.uk>")
+ (Cc . "Jeff Bailey <jbailey@nisa.net>, emacs-devel@gnu.org, cvs-hackers@gnu.org"))]
+ [8 "Re: [Emacs-devel] Emacs move" "John Wiegley <johnw@gnu.org>"
+ "Thu, 14 Sep 2000 12:19:01 -0700"
+ "<200009141919.MAA05085@localhost.localdomain>"
+ "<20000913175943.A26093@sparky.nisa.net>"
+ 1978 27 "nnmaildir mails:8"
+ ((To . "emacs-devel@gnu.org"))]
+ [9 "Re: [Emacs-devel] Emacs move"
+ "\"Robert J. Chassell\" <bob@rattlesnake.com>"
+ "Thu, 14 Sep 2000 07:33:15 -0400 (EDT)"
+ "<m13ZXGV-000BCgC@megalith.rattlesnake.com>"
+ "<20000913175943.A26093@sparky.nisa.net>"
+ 3046 72 "nnmaildir mails:9"
+ ((To . "jbailey@nisa.net")
+ (Cc . "emacs-devel@gnu.org, cvs-hackers@gnu.org"))]
+ [10 "Re: [Emacs-devel] Emacs move"
+ "wmperry@aventail.com (William M. Perry)"
+ "14 Sep 2000 09:10:25 -0500"
+ "<86g0n3f4j2.fsf@megalith.bp.aventail.com>"
+ "<20000913175943.A26093@sparky.nisa.net> <m13ZXGV-000BCgC@megalith.rattlesnake.com>"
+ 3104 44 "nnmaildir mails:10"
+ ((To . "bob@rattlesnake.com")
+ (Cc . "jbailey@nisa.net, emacs-devel@gnu.org, cvs-hackers@gnu.org"))]
+ [11 "Re: [Emacs-devel] Emacs move" "Gerd Moellmann <gerd@gnu.org>"
+ "Thu, 14 Sep 2000 21:51:05 +0200 (CEST)"
+ "<200009141951.VAA06005@gerd.segv.de>"
+ "<20000913175943.A26093@sparky.nisa.net> <m13ZXGV-000BCgC@megalith.rattlesnake.com> <86g0n3f4j2.fsf@megalith.bp.aventail.com>"
+ 1884 6 "nnmaildir mails:11"
+ ((To . "wmvperry@aventail.com")
+ (Cc . "bob@rattlesnake.com, jbailey@nisa.net, emacs-devel@gnu.org, cvs-hackers@gnu.org"))]
+ [12 "Re: [Emacs-devel] Emacs move" "Gerd Moellmann <gerd@gnu.org>"
+ "Thu, 14 Sep 2000 21:49:03 +0200 (CEST)"
+ "<200009141949.VAA05998@gerd.segv.de>"
+ "<20000913175943.A26093@sparky.nisa.net> <m13ZXGV-000BCgC@megalith.rattlesnake.com>"
+ 2408 24 "nnmaildir mails:12"
+ ((To . "bob@rattlesnake.com")
+ (Cc . "jbailey@nisa.net, emacs-devel@gnu.org, cvs-hackers@gnu.org"))]
+ [13 "Re: [Emacs-devel] Emacs move"
+ "\"Robert J. Chassell\" <bob@rattlesnake.com>"
+ "Thu, 14 Sep 2000 17:50:01 -0400 (EDT)"
+ "<m13ZgtN-000BD3C@megalith.rattlesnake.com>"
+ "<20000913175943.A26093@sparky.nisa.net> <m13ZXGV-000BCgC@megalith.rattlesnake.com> <200009141949.VAA05998@gerd.segv.de>"
+ 1968 23 "nnmaildir mails:13"
+ ((To . "gerd@gnu.org")
+ (Cc . "bob@rattlesnake.com, jbailey@nisa.net, emacs-devel@gnu.org, cvs-hackers@gnu.org"))]
+ [14 "Re: [Emacs-devel] Emacs move" "Richard Stallman <rms@gnu.org>"
+ "Fri, 15 Sep 2000 16:28:12 -0600 (MDT)"
+ "<200009152228.QAA20526@wijiji.santafe.edu>"
+ "<20000913175943.A26093@sparky.nisa.net> <m13ZXGV-000BCgC@megalith.rattlesnake.com>"
+ 1288 2 "nnmaildir mails:14"
+ ((To . "jbailey@nisa.net, emacs-devel@gnu.org, cvs-hackers@gnu.org"))]
+ [15 "[Emacs-devel] Emacs move" "Jeff Bailey <jbailey@nisa.net>"
+ "Wed, 13 Sep 2000 17:59:43 -0700"
+ "<20000913175943.A26093@sparky.nisa.net>" ""
+ 1661 26 "nnmaildir mails:15"
+ ((To . "emacs-devel@gnu.org")
+ (Cc . "cvs-hackers@gnu.org"))]
+ [16 "Re: [Emacs-devel] Emacs move" "Jeff Bailey <jbailey@nisa.net>"
+ "Fri, 15 Sep 2000 22:00:12 -0700"
+ "<20000915220012.A3923@sparky.nisa.net>"
+ "<20000913175943.A26093@sparky.nisa.net> <m13ZXGV-000BCgC@megalith.rattlesnake.com> <200009141949.VAA05998@gerd.segv.de> <m13ZgtN-000BD3C@megalith.rattlesnake.com>"
+ 2857 51 "nnmaildir mails:16"
+ ((To . "bob@rattlesnake.com, gerd@gnu.org")
+ (Cc . "jbailey@nisa.net, emacs-devel@gnu.org, cvs-hackers@gnu.org"))])
+ "A pile of headers with potential interdependencies.")
+
+(ert-deftest gnus-headers-make-dependency-table ()
+ (let ((table (gnus-make-hashtable 20))
+ (data (copy-sequence gnus-headers-test-data))
+ ret)
+ (dolist (h data)
+ ;; `gnus-dependencies-add-header' returns nil if it fails to add
+ ;; the header.
+ (should (gnus-dependencies-add-header h table nil)))
+ ;; Pick a value to test.
+ (setq ret (gethash "<m13ZXGV-000BCgC@megalith.rattlesnake.com>"
+ table))
+ ;; The message has three children.
+ (should (= 3 (length (cdr ret))))
+ ;; The first of those children has one child.
+ (should (= 1 (length (cdr (nth 1 ret)))))))
+
+(ert-deftest gnus-headers-loop-dependencies ()
+ "Intentionally create a reference loop."
+ (let ((table (gnus-make-hashtable 20))
+ (data (copy-sequence gnus-headers-test-data))
+ (parent-id "<200009141724.SAA26807@djlvig.dl.ac.uk>")
+ (child-id "<87em2nyog0.fsf@galois.collab.net>")
+ parent)
+ (dolist (h data)
+ (gnus-dependencies-add-header h table nil))
+
+ (setq parent (gethash parent-id table))
+
+ ;; Put the parent header in the child references of one of its own
+ ;; children. `gnus-thread-loop-p' only checks if there's a loop
+ ;; between parent and immediate child, not parent and random
+ ;; descendant. At least, near as I can tell that's the case.
+
+ (push (list (car parent)) (cdr (gethash child-id table)))
+
+ (let ((gnus-newsgroup-dependencies table))
+ (should
+ (= 1 ; 1 indicates an infloop.
+ (gnus-thread-loop-p (car parent) (cadr parent)))))))
+
+(provide 'gnus-test-headers)
+;;; gnus-test-headers.el ends here
diff --git a/test/lisp/gnus/gnus-tests.el b/test/lisp/gnus/gnus-tests.el
index c2a41d717cf..4c5a6a8191c 100644
--- a/test/lisp/gnus/gnus-tests.el
+++ b/test/lisp/gnus/gnus-tests.el
@@ -1,6 +1,6 @@
-;;; gnus-tests.el --- Wrapper for the Gnus tests
+;;; gnus-tests.el --- Wrapper for the Gnus tests -*- lexical-binding:t -*-
-;; Copyright (C) 2011-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2022 Free Software Foundation, Inc.
;; Author: Teodor Zlatanov <tzz@lifelogs.com>
@@ -26,8 +26,6 @@
;;; Code:
;; registry.el is required by gnus-registry.el but this way we're explicit.
-(eval-when-compile (require 'cl))
-
(require 'registry)
(require 'gnus-registry)
diff --git a/test/lisp/gnus/gnus-util-tests.el b/test/lisp/gnus/gnus-util-tests.el
new file mode 100644
index 00000000000..464567061f6
--- /dev/null
+++ b/test/lisp/gnus/gnus-util-tests.el
@@ -0,0 +1,135 @@
+;;; gnus-util-tests.el --- Selectived tests only. -*- lexical-binding:t -*-
+;; Copyright (C) 2015-2022 Free Software Foundation, Inc.
+
+;; Author: Jens Lechtenbörger <jens.lechtenboerger@fsfe.org>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'gnus-util)
+
+(ert-deftest gnus-string> ()
+ ;; Failure paths
+ (should-error (gnus-string> "" 1)
+ :type 'wrong-type-argument)
+ (should-error (gnus-string> "")
+ :type 'wrong-number-of-arguments)
+
+ ;; String tests
+ (should (gnus-string> "def" "abc"))
+ (should (gnus-string> 'def 'abc))
+ (should (gnus-string> "abc" "DEF"))
+ (should (gnus-string> "abc" 'DEF))
+ (should (gnus-string> "αβγ" "abc"))
+ (should (gnus-string> "אבג" "αβγ"))
+ (should (gnus-string> nil ""))
+ (should (gnus-string> "abc" ""))
+ (should (gnus-string> "abc" "ab"))
+ (should-not (gnus-string> "abc" "abc"))
+ (should-not (gnus-string> "abc" "def"))
+ (should-not (gnus-string> "DEF" "abc"))
+ (should-not (gnus-string> 'DEF "abc"))
+ (should-not (gnus-string> "123" "abc"))
+ (should-not (gnus-string> "" "")))
+
+(ert-deftest gnus-string< ()
+ ;; Failure paths
+ (should-error (gnus-string< "" 1)
+ :type 'wrong-type-argument)
+ (should-error (gnus-string< "")
+ :type 'wrong-number-of-arguments)
+
+ ;; String tests
+ (setq case-fold-search nil)
+ (should (gnus-string< "abc" "def"))
+ (should (gnus-string< 'abc 'def))
+ (should (gnus-string< "DEF" "abc"))
+ (should (gnus-string< "DEF" 'abc))
+ (should (gnus-string< "abc" "αβγ"))
+ (should (gnus-string< "αβγ" "אבג"))
+ (should (gnus-string< "" nil))
+ (should (gnus-string< "" "abc"))
+ (should (gnus-string< "ab" "abc"))
+ (should-not (gnus-string< "abc" "abc"))
+ (should-not (gnus-string< "def" "abc"))
+ (should-not (gnus-string< "abc" "DEF"))
+ (should-not (gnus-string< "abc" 'DEF))
+ (should-not (gnus-string< "abc" "123"))
+ (should-not (gnus-string< "" ""))
+
+ ;; gnus-string< checks case-fold-search
+ (setq case-fold-search t)
+ (should (gnus-string< "abc" "DEF"))
+ (should (gnus-string< "abc" 'GHI))
+ (should (gnus-string< 'abc "DEF"))
+ (should (gnus-string< 'GHI 'JKL))
+ (should (gnus-string< "abc" "ΑΒΓ"))
+ (should-not (gnus-string< "ABC" "abc"))
+ (should-not (gnus-string< "def" "ABC")))
+
+(ert-deftest gnus-subsetp ()
+ ;; False for non-lists.
+ (should-not (gnus-subsetp "1" "1"))
+ (should-not (gnus-subsetp "1" '("1")))
+ (should-not (gnus-subsetp '("1") "1"))
+
+ ;; Real tests.
+ (should (gnus-subsetp '() '()))
+ (should (gnus-subsetp '() '("1")))
+ (should (gnus-subsetp '("1") '("1")))
+ (should (gnus-subsetp '(42) '("1" 42)))
+ (should (gnus-subsetp '(42) '(42 "1")))
+ (should (gnus-subsetp '(42) '("1" 42 2)))
+ (should-not (gnus-subsetp '("1") '()))
+ (should-not (gnus-subsetp '("1") '(2)))
+ (should-not (gnus-subsetp '("1" 2) '(2)))
+ (should-not (gnus-subsetp '(2 "1") '(2)))
+ (should-not (gnus-subsetp '("1" 2) '(2 3)))
+
+ ;; Duplicates don't matter for sets.
+ (should (gnus-subsetp '("1" "1") '("1")))
+ (should (gnus-subsetp '("1" 2 "1") '(2 "1")))
+ (should (gnus-subsetp '("1" 2 "1") '(2 "1" "1" 2)))
+ (should-not (gnus-subsetp '("1" 2 "1" 3) '(2 "1" "1" 2))))
+
+(ert-deftest gnus-setdiff ()
+ ;; False for non-lists.
+ (should-not (gnus-setdiff "1" "1"))
+ (should-not (gnus-setdiff "1" '()))
+ (should-not (gnus-setdiff '() "1"))
+
+ ;; Real tests.
+ (should-not (gnus-setdiff '() '()))
+ (should-not (gnus-setdiff '() '("1")))
+ (should-not (gnus-setdiff '("1") '("1")))
+ (should (equal '("1") (gnus-setdiff '("1") '())))
+ (should (equal '("1") (gnus-setdiff '("1") '(2))))
+ (should (equal '("1") (gnus-setdiff '("1" 2) '(2))))
+ (should (equal '("1") (gnus-setdiff '("1" 2 3) '(3 2))))
+ (should (equal '("1") (gnus-setdiff '(2 "1" 3) '(3 2))))
+ (should (equal '("1") (gnus-setdiff '(2 3 "1") '(3 2))))
+ (should (equal '(2 "1") (gnus-setdiff '(2 3 "1") '(3))))
+
+ ;; Duplicates aren't touched for sets if they are not removed.
+ (should-not (gnus-setdiff '("1" "1") '("1")))
+ (should (equal '("1") (gnus-setdiff '(2 "1" 2) '(2))))
+ (should (equal '("1" "1") (gnus-setdiff '(2 "1" 2 "1") '(2)))))
+
+;;; gnus-util-tests.el ends here
diff --git a/test/lisp/gnus/message-tests.el b/test/lisp/gnus/message-tests.el
index f905ba3e263..a724428ecb4 100644
--- a/test/lisp/gnus/message-tests.el
+++ b/test/lisp/gnus/message-tests.el
@@ -1,6 +1,6 @@
-;;; message-mode-tests.el --- Tests for message-mode -*- lexical-binding: t; -*-
+;;; message-tests.el --- Tests for message-mode -*- lexical-binding: t; -*-
-;; Copyright (C) 2015-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2022 Free Software Foundation, Inc.
;; Author: João Távora <joaotavora@gmail.com>
@@ -29,6 +29,8 @@
(require 'ert)
(require 'ert-x)
+(require 'cl-lib)
+
(ert-deftest message-mode-propertize ()
(with-temp-buffer
(unwind-protect
@@ -45,14 +47,10 @@
(setq-local parse-sexp-lookup-properties t)
(backward-sexp)
(should (string= "here's an opener "
- (buffer-substring-no-properties
- (line-beginning-position)
- (point))))
+ (buffer-substring-no-properties (pos-bol) (point))))
(forward-sexp)
(should (string= "and here's a closer )"
- (buffer-substring-no-properties
- (line-beginning-position)
- (point)))))
+ (buffer-substring-no-properties (pos-bol) (point)))))
(set-buffer-modified-p nil))))
@@ -97,7 +95,90 @@
(should (string= stripped-was
(message-strip-subject-trailing-was with-was)))))))
+(ert-deftest message-all-recipients ()
+ (ert-with-test-buffer (:name "message")
+ (insert "To: Person 1 <p1@p1.org>, Person 2 <p2@p2.org>\n")
+ (insert "Cc: Person 3 <p3@p3.org>, Person 4 <p4@p4.org>\n")
+ (insert "Bcc: Person 5 <p5@p5.org>, Person 6 <p6@p6.org>\n")
+ (should (equal (message-all-recipients)
+ '(("Person 1" "p1@p1.org")
+ ("Person 2" "p2@p2.org")
+ ("Person 3" "p3@p3.org")
+ ("Person 4" "p4@p4.org")
+ ("Person 5" "p5@p5.org")
+ ("Person 6" "p6@p6.org"))))))
+
+(ert-deftest message-all-epg-keys-available-p ()
+ (skip-unless (epg-check-configuration (epg-find-configuration 'OpenPGP)))
+ (let ((person1 '("Person 1" "p1@p1.org"))
+ (person2 '("Person 2" "p2@p2.org"))
+ (person3 '("Person 3" "p3@p3.org"))
+ (recipients nil)
+ (keyring '("p1@p1.org" "p2@p2.org")))
+ (cl-letf (((symbol-function 'epg-list-keys)
+ (lambda (_ email) (cl-find email keyring :test #'string=)))
+ ((symbol-function 'message-all-recipients)
+ (lambda () recipients)))
+
+ (setq recipients (list))
+ (should (message-all-epg-keys-available-p))
+
+ (setq recipients (list person1))
+ (should (message-all-epg-keys-available-p))
+
+ (setq recipients (list person1 person2))
+ (should (message-all-epg-keys-available-p))
+
+ (setq recipients (list person3))
+ (should-not (message-all-epg-keys-available-p))
+
+ (setq recipients (list person1 person3))
+ (should-not (message-all-epg-keys-available-p))
+
+ (setq recipients (list person3 person1))
+ (should-not (message-all-epg-keys-available-p))
+
+ (setq recipients (list person1 person2 person3))
+ (should-not (message-all-epg-keys-available-p)))))
+
+(ert-deftest message-alter-repeat-address ()
+ (should (equal (message--alter-repeat-address
+ "Lars Ingebrigtsen <larsi@gnus.org>")
+ "Lars Ingebrigtsen <larsi@gnus.org>"))
+
+ (should (equal (message--alter-repeat-address
+ "\"larsi@gnus.org\" <larsi@gnus.org>")
+ "larsi@gnus.org")))
+
+(ert-deftest message-replace-header ()
+ (with-temp-buffer
+ (save-excursion
+ (insert "From: dang@gnus.org
+To: user1,
+ user2
+Cc: user3,
+ user4
+--text follows this line--
+Hello.
+"))
+ (save-excursion
+ (message-replace-header "From" "ding@gnus.org")
+ (should (cl-search "ding" (message-field-value "From"))))
+ (save-excursion
+ (message-replace-header "From" "dong@gnus.org" "To")
+ (should (cl-search "dong" (message-field-value "From")))
+ (should (re-search-forward "From:"))
+ (should-error (re-search-forward "To:"))
+ (should (re-search-forward "Cc:")))
+ (save-excursion
+ (message-replace-header "From" "dang@gnus.org" (split-string "To Cc"))
+ (should (cl-search "dang" (message-field-value "From")))
+ (should (re-search-forward "From:"))
+ (should-error (re-search-forward "To:"))
+ ;; That this isn't so is probably a bug from 1997.
+ ;; (should-error (re-search-forward "Cc:"))
+ )))
(provide 'message-mode-tests)
-;;; message-mode-tests.el ends here
+;;; message-tests.el ends here
diff --git a/test/lisp/gnus/mm-decode-resources/8bit-multipart.bin b/test/lisp/gnus/mm-decode-resources/8bit-multipart.bin
new file mode 100644
index 00000000000..0b193a27234
--- /dev/null
+++ b/test/lisp/gnus/mm-decode-resources/8bit-multipart.bin
@@ -0,0 +1,20 @@
+From: example <example@example.org>
+To: example <example@example.org>
+Content-Type: multipart/alternative; boundary="===============2877195075946974246=="
+Date: Thu, 29 Oct 2020 14:47:55 +0100
+MIME-Version: 1.0
+Subject: test
+
+--===============2877195075946974246==
+Content-Type: text/plain; charset="utf-8"
+Content-Transfer-Encoding: 8bit
+
+ääää
+
+--===============2877195075946974246==
+Content-Type: text/html; charset="utf-8"
+Content-Transfer-Encoding: 8bit
+
+<!doctype html><html><head><meta http-equiv="content-type" content="text/html; charset=UTF-8"></head><body>ääää</body></html>
+
+--===============2877195075946974246==--
diff --git a/test/lisp/gnus/mm-decode-resources/win1252-multipart.bin b/test/lisp/gnus/mm-decode-resources/win1252-multipart.bin
new file mode 100644
index 00000000000..d3c5026dcce
--- /dev/null
+++ b/test/lisp/gnus/mm-decode-resources/win1252-multipart.bin
@@ -0,0 +1,44 @@
+To: example <example@example.org>
+From: example <example@example.org>
+Date: Tue, 5 Jan 2021 10:30:34 +0100
+MIME-Version: 1.0
+Content-Type: multipart/mixed; boundary="------------FB569A4368539497CC91D1DC"
+Content-Language: fr
+Subject: test
+
+--------------FB569A4368539497CC91D1DC
+Content-Type: multipart/alternative;
+ boundary="------------61C81A7DC7592E4C6F856A85"
+
+
+--------------61C81A7DC7592E4C6F856A85
+Content-Type: text/plain; charset=windows-1252; format=flowed
+Content-Transfer-Encoding: 8bit
+
+dj rat
+
+--------------61C81A7DC7592E4C6F856A85
+Content-Type: text/html; charset=windows-1252
+Content-Transfer-Encoding: 8bit
+
+<html>
+ <head>
+ <meta http-equiv="content-type" content="text/html; charset=windows-1252">
+ </head>
+ <body>
+ dj rat
+ </body>
+</html>
+
+--------------61C81A7DC7592E4C6F856A85--
+
+--------------FB569A4368539497CC91D1DC
+Content-Type: text/plain; charset="us-ascii"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Content-Disposition: inline
+
+mailing list signature
+
+--------------FB569A4368539497CC91D1DC--
+
diff --git a/test/lisp/gnus/mm-decode-tests.el b/test/lisp/gnus/mm-decode-tests.el
new file mode 100644
index 00000000000..5f39a32b0de
--- /dev/null
+++ b/test/lisp/gnus/mm-decode-tests.el
@@ -0,0 +1,102 @@
+;;; mm-decode-tests.el --- -*- lexical-binding:t -*-
+
+;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'ert-x)
+(require 'mm-decode)
+
+(ert-deftest test-mm-dissect-buffer ()
+ (with-temp-buffer
+ (set-buffer-multibyte nil)
+ (insert-file-contents-literally (ert-resource-file "8bit-multipart.bin"))
+ (while (search-forward "\r\n" nil t)
+ (replace-match "\n"))
+ (let ((handle (mm-dissect-buffer)))
+ (should (equal (mm-handle-media-type handle) "multipart/alternative"))
+ ;; Skip multipart type.
+ (pop handle)
+ (let ((part (pop handle)))
+ (should (equal (mm-handle-media-type part) "text/plain"))
+ (should (eq (mm-handle-encoding part) '8bit))
+ (with-current-buffer (mm-handle-buffer part)
+ (should (equal (decode-coding-string
+ (buffer-string)
+ (intern (mail-content-type-get (mm-handle-type part)
+ 'charset)))
+ "ääää\n"))))
+ (let ((part (pop handle)))
+ (should (equal (mm-handle-media-type part) "text/html"))
+ (should (eq (mm-handle-encoding part) '8bit))
+ (with-current-buffer (mm-handle-buffer part)
+ (should (equal (decode-coding-string
+ (buffer-string)
+ (intern (mail-content-type-get (mm-handle-type part)
+ 'charset)))
+ "<!doctype html><html><head><meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\"></head><body>ääää</body></html>\n")))))))
+
+(ert-deftest test-mm-with-part-unibyte ()
+ (with-temp-buffer
+ (set-buffer-multibyte nil)
+ (insert-file-contents-literally (ert-resource-file "8bit-multipart.bin"))
+ (while (search-forward "\r\n" nil t)
+ (replace-match "\n"))
+ (let ((handle (mm-dissect-buffer)))
+ (pop handle)
+ (let ((part (pop handle)))
+ (should (equal (decode-coding-string
+ (mm-with-part part
+ (buffer-string))
+ (intern (mail-content-type-get (mm-handle-type part)
+ 'charset)))
+ "ääää\n"))))))
+
+(ert-deftest test-mm-dissect-buffer-win1252 ()
+ (with-temp-buffer
+ (set-buffer-multibyte nil)
+ (insert-file-contents-literally (ert-resource-file "win1252-multipart.bin"))
+ (let ((handle (mm-dissect-buffer)))
+ (should (equal (mm-handle-media-type handle) "multipart/mixed"))
+ ;; Skip multipart type.
+ (pop handle)
+ (setq handle (car handle))
+ (pop handle)
+ (let ((part (pop handle)))
+ (should (equal (mm-handle-media-type part) "text/plain"))
+ (should (eq (mm-handle-encoding part) '8bit))
+ (with-current-buffer (mm-handle-buffer part)
+ (should (equal (decode-coding-string
+ (buffer-string)
+ (intern (mail-content-type-get (mm-handle-type part)
+ 'charset)))
+ "déjà raté\n"))))
+ (let ((part (pop handle)))
+ (should (equal (mm-handle-media-type part) "text/html"))
+ (should (eq (mm-handle-encoding part) '8bit))
+ (with-current-buffer (mm-handle-buffer part)
+ (should (equal (decode-coding-string
+ (buffer-string)
+ (intern (mail-content-type-get (mm-handle-type part)
+ 'charset)))
+ "<html>\n <head>\n <meta http-equiv=\"content-type\" content=\"text/html; charset=windows-1252\">\n </head>\n <body>\n déjà raté\n </body>\n</html>\n")))))))
+
+;;; mm-decode-tests.el ends here
diff --git a/test/lisp/gnus/mml-sec-resources/.gpg-v21-migrated b/test/lisp/gnus/mml-sec-resources/.gpg-v21-migrated
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/test/lisp/gnus/mml-sec-resources/.gpg-v21-migrated
diff --git a/test/lisp/gnus/mml-sec-resources/gpg-agent.conf b/test/lisp/gnus/mml-sec-resources/gpg-agent.conf
new file mode 100644
index 00000000000..20192990caf
--- /dev/null
+++ b/test/lisp/gnus/mml-sec-resources/gpg-agent.conf
@@ -0,0 +1,5 @@
+# pinentry-program /usr/bin/pinentry-gtk-2
+
+# verbose
+# log-file /tmp/gpg-agent.log
+# debug-all
diff --git a/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/02089CDDC6DFE93B8EA10D9E876F983E61FEC476.key b/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/02089CDDC6DFE93B8EA10D9E876F983E61FEC476.key
new file mode 100644
index 00000000000..58fd0b5edbc
--- /dev/null
+++ b/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/02089CDDC6DFE93B8EA10D9E876F983E61FEC476.key
Binary files differ
diff --git a/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/171B444DE92BEF997229000D9784118A94EEC1C9.key b/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/171B444DE92BEF997229000D9784118A94EEC1C9.key
new file mode 100644
index 00000000000..62f4ab25a69
--- /dev/null
+++ b/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/171B444DE92BEF997229000D9784118A94EEC1C9.key
Binary files differ
diff --git a/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/19FFEBC04DF3E037E16F6A4474DCB7984406975D.key b/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/19FFEBC04DF3E037E16F6A4474DCB7984406975D.key
new file mode 100644
index 00000000000..2a8ce135fb2
--- /dev/null
+++ b/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/19FFEBC04DF3E037E16F6A4474DCB7984406975D.key
Binary files differ
diff --git a/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/1E36D27DF9DAB96302D35268DADC5CE73EF45A2A.key b/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/1E36D27DF9DAB96302D35268DADC5CE73EF45A2A.key
new file mode 100644
index 00000000000..9f8de71c5e2
--- /dev/null
+++ b/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/1E36D27DF9DAB96302D35268DADC5CE73EF45A2A.key
Binary files differ
diff --git a/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/293109315BE584AB2EFEFCFCAD64666221D8B36C.key b/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/293109315BE584AB2EFEFCFCAD64666221D8B36C.key
new file mode 100644
index 00000000000..6e4a4e548fd
--- /dev/null
+++ b/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/293109315BE584AB2EFEFCFCAD64666221D8B36C.key
Binary files differ
diff --git a/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/335689599E1C0F66D73ADCF51E03EE36C97D121F.key b/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/335689599E1C0F66D73ADCF51E03EE36C97D121F.key
new file mode 100644
index 00000000000..cff58edaa89
--- /dev/null
+++ b/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/335689599E1C0F66D73ADCF51E03EE36C97D121F.key
Binary files differ
diff --git a/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/40BF94E540E3726CB150A1ADF7C1B514444B3FA6.key b/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/40BF94E540E3726CB150A1ADF7C1B514444B3FA6.key
new file mode 100644
index 00000000000..14af8662f79
--- /dev/null
+++ b/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/40BF94E540E3726CB150A1ADF7C1B514444B3FA6.key
Binary files differ
diff --git a/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/515D4637EFC6C09DB1F78BE8C2F2A3D63E7756C3.key b/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/515D4637EFC6C09DB1F78BE8C2F2A3D63E7756C3.key
new file mode 100644
index 00000000000..207a7237d3a
--- /dev/null
+++ b/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/515D4637EFC6C09DB1F78BE8C2F2A3D63E7756C3.key
Binary files differ
diff --git a/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/5A11B1935C46D0B227A73978DCA1293A85604F1D.key b/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/5A11B1935C46D0B227A73978DCA1293A85604F1D.key
new file mode 100644
index 00000000000..85ca78da04d
--- /dev/null
+++ b/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/5A11B1935C46D0B227A73978DCA1293A85604F1D.key
Binary files differ
diff --git a/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/62643CEBC7AEBE6817577A34399483700D76BD64.key b/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/62643CEBC7AEBE6817577A34399483700D76BD64.key
new file mode 100644
index 00000000000..79f3cd2b841
--- /dev/null
+++ b/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/62643CEBC7AEBE6817577A34399483700D76BD64.key
Binary files differ
diff --git a/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/680D01F368916A0021C14E3453B27B3C5F900683.key b/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/680D01F368916A0021C14E3453B27B3C5F900683.key
new file mode 100644
index 00000000000..776ddf7e9e2
--- /dev/null
+++ b/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/680D01F368916A0021C14E3453B27B3C5F900683.key
Binary files differ
diff --git a/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/6DF2D9DF7AED06F0524BEB642DF0FB48EFDBDB93.key b/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/6DF2D9DF7AED06F0524BEB642DF0FB48EFDBDB93.key
new file mode 100644
index 00000000000..2b464f0ccbe
--- /dev/null
+++ b/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/6DF2D9DF7AED06F0524BEB642DF0FB48EFDBDB93.key
Binary files differ
diff --git a/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/78C17E134E86E691297F7B719B2F2CDF41976234.key b/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/78C17E134E86E691297F7B719B2F2CDF41976234.key
new file mode 100644
index 00000000000..28a07668b21
--- /dev/null
+++ b/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/78C17E134E86E691297F7B719B2F2CDF41976234.key
Binary files differ
diff --git a/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/7F714F4D9D9676638214991E96D45704E4FFC409.key b/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/7F714F4D9D9676638214991E96D45704E4FFC409.key
new file mode 100644
index 00000000000..137659693bd
--- /dev/null
+++ b/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/7F714F4D9D9676638214991E96D45704E4FFC409.key
Binary files differ
diff --git a/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/854752F5D8090CA36EFBDD79C72BDFF6FA2D1FF0.key b/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/854752F5D8090CA36EFBDD79C72BDFF6FA2D1FF0.key
new file mode 100644
index 00000000000..c99824ccd43
--- /dev/null
+++ b/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/854752F5D8090CA36EFBDD79C72BDFF6FA2D1FF0.key
Binary files differ
diff --git a/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/93FF37C268FDBF0767F5FFDC49409DDAC9388B2C.key b/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/93FF37C268FDBF0767F5FFDC49409DDAC9388B2C.key
new file mode 100644
index 00000000000..49c2dc58bd8
--- /dev/null
+++ b/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/93FF37C268FDBF0767F5FFDC49409DDAC9388B2C.key
Binary files differ
diff --git a/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/A3BA94EAE83509CC90DB1B77B54A51959D8DABEA.key b/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/A3BA94EAE83509CC90DB1B77B54A51959D8DABEA.key
new file mode 100644
index 00000000000..ca128408952
--- /dev/null
+++ b/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/A3BA94EAE83509CC90DB1B77B54A51959D8DABEA.key
Binary files differ
diff --git a/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/A73E9D01F0465B518E8E7D5AD529077AAC1603B4.key b/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/A73E9D01F0465B518E8E7D5AD529077AAC1603B4.key
new file mode 100644
index 00000000000..3f14b40927a
--- /dev/null
+++ b/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/A73E9D01F0465B518E8E7D5AD529077AAC1603B4.key
Binary files differ
diff --git a/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/AE6A24B17A8D0CAF9B7E000AA77F0B41D7BFFFCF.key b/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/AE6A24B17A8D0CAF9B7E000AA77F0B41D7BFFFCF.key
new file mode 100644
index 00000000000..06adc06c427
--- /dev/null
+++ b/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/AE6A24B17A8D0CAF9B7E000AA77F0B41D7BFFFCF.key
Binary files differ
diff --git a/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/C072AF82DCCCB9A7F1B85FFA10B802DC4ED16703.key b/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/C072AF82DCCCB9A7F1B85FFA10B802DC4ED16703.key
new file mode 100644
index 00000000000..cf9a60d233b
--- /dev/null
+++ b/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/C072AF82DCCCB9A7F1B85FFA10B802DC4ED16703.key
Binary files differ
diff --git a/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/C43E1A079B28DFAEBB39CBA01793BDE11EF4B490.key b/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/C43E1A079B28DFAEBB39CBA01793BDE11EF4B490.key
new file mode 100644
index 00000000000..0ed35172fe0
--- /dev/null
+++ b/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/C43E1A079B28DFAEBB39CBA01793BDE11EF4B490.key
Binary files differ
diff --git a/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/C67DAD345455EAD6D51368008FC3A53B8D195B5A.key b/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/C67DAD345455EAD6D51368008FC3A53B8D195B5A.key
new file mode 100644
index 00000000000..090059d9e81
--- /dev/null
+++ b/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/C67DAD345455EAD6D51368008FC3A53B8D195B5A.key
Binary files differ
diff --git a/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/CB5E00CE582C2645D2573FC16B2F14F85A7F47AA.key b/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/CB5E00CE582C2645D2573FC16B2F14F85A7F47AA.key
new file mode 100644
index 00000000000..9061f675121
--- /dev/null
+++ b/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/CB5E00CE582C2645D2573FC16B2F14F85A7F47AA.key
Binary files differ
diff --git a/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/CC68630A06B048F5A91136C162C7A3273E20DE6F.key b/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/CC68630A06B048F5A91136C162C7A3273E20DE6F.key
new file mode 100644
index 00000000000..89f6013100d
--- /dev/null
+++ b/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/CC68630A06B048F5A91136C162C7A3273E20DE6F.key
Binary files differ
diff --git a/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/E7E73903E1BF93481DE0E7C9769D6C31E1863CFF.key b/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/E7E73903E1BF93481DE0E7C9769D6C31E1863CFF.key
new file mode 100644
index 00000000000..41dac37574e
--- /dev/null
+++ b/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/E7E73903E1BF93481DE0E7C9769D6C31E1863CFF.key
Binary files differ
diff --git a/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/F0117468BE801ED4B81972E159A98FDD4814DCEC.key b/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/F0117468BE801ED4B81972E159A98FDD4814DCEC.key
new file mode 100644
index 00000000000..5df7b4a5953
--- /dev/null
+++ b/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/F0117468BE801ED4B81972E159A98FDD4814DCEC.key
Binary files differ
diff --git a/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/F4C5EFD5779BE892CAFD5B721D68DED677C9B151.key b/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/F4C5EFD5779BE892CAFD5B721D68DED677C9B151.key
new file mode 100644
index 00000000000..03daf80975b
--- /dev/null
+++ b/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/F4C5EFD5779BE892CAFD5B721D68DED677C9B151.key
Binary files differ
diff --git a/test/lisp/gnus/mml-sec-resources/pubring.gpg b/test/lisp/gnus/mml-sec-resources/pubring.gpg
new file mode 100644
index 00000000000..6bd169963df
--- /dev/null
+++ b/test/lisp/gnus/mml-sec-resources/pubring.gpg
Binary files differ
diff --git a/test/lisp/gnus/mml-sec-resources/pubring.kbx b/test/lisp/gnus/mml-sec-resources/pubring.kbx
new file mode 100644
index 00000000000..399a0414fd2
--- /dev/null
+++ b/test/lisp/gnus/mml-sec-resources/pubring.kbx
Binary files differ
diff --git a/test/lisp/gnus/mml-sec-resources/secring.gpg b/test/lisp/gnus/mml-sec-resources/secring.gpg
new file mode 100644
index 00000000000..b323c072c04
--- /dev/null
+++ b/test/lisp/gnus/mml-sec-resources/secring.gpg
Binary files differ
diff --git a/test/lisp/gnus/mml-sec-resources/trustdb.gpg b/test/lisp/gnus/mml-sec-resources/trustdb.gpg
new file mode 100644
index 00000000000..09ebd8db114
--- /dev/null
+++ b/test/lisp/gnus/mml-sec-resources/trustdb.gpg
Binary files differ
diff --git a/test/lisp/gnus/mml-sec-resources/trustlist.txt b/test/lisp/gnus/mml-sec-resources/trustlist.txt
new file mode 100644
index 00000000000..f886572d283
--- /dev/null
+++ b/test/lisp/gnus/mml-sec-resources/trustlist.txt
@@ -0,0 +1,26 @@
+# This is the list of trusted keys. Comment lines, like this one, as
+# well as empty lines are ignored. Lines have a length limit but this
+# is not a serious limitation as the format of the entries is fixed and
+# checked by gpg-agent. A non-comment line starts with optional white
+# space, followed by the SHA-1 fingerpint in hex, followed by a flag
+# which may be one of 'P', 'S' or '*' and optionally followed by a list of
+# other flags. The fingerprint may be prefixed with a '!' to mark the
+# key as not trusted. You should give the gpg-agent a HUP or run the
+# command "gpgconf --reload gpg-agent" after changing this file.
+
+
+# Include the default trust list
+include-default
+
+
+# CN=No Expiry
+D0:6A:A1:18:65:3C:C3:8E:9D:0C:AF:56:ED:7A:21:35:E1:58:21:77 S relax
+
+# CN=Second Key Pair
+0E:58:22:9B:80:EE:33:95:9F:F7:18:FE:EF:25:40:2B:47:9D:C6:E2 S relax
+
+# CN=No Expiry two UIDs
+D4:CA:78:E1:47:0B:9F:C2:AE:45:D7:84:64:9B:8C:E6:4E:BB:32:0C S relax
+
+# CN=Different subkeys
+4F:96:2A:B7:F4:76:61:6A:78:3D:72:AA:40:35:D5:9B:5F:88:E9:FC S relax
diff --git a/test/lisp/gnus/mml-sec-tests.el b/test/lisp/gnus/mml-sec-tests.el
new file mode 100644
index 00000000000..f308a617645
--- /dev/null
+++ b/test/lisp/gnus/mml-sec-tests.el
@@ -0,0 +1,900 @@
+;;; mml-sec-tests.el --- Tests mml-sec.el, see README-mml-secure.txt. -*- lexical-binding:t -*-
+
+;; Copyright (C) 2015, 2020-2022 Free Software Foundation, Inc.
+
+;; Author: Jens Lechtenbörger <jens.lechtenboerger@fsfe.org>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'ert-x)
+
+(require 'message)
+(require 'epa)
+(require 'epg)
+(require 'mml-sec)
+(require 'gnus-sum)
+
+(defvar with-smime nil
+ "If nil, exclude S/MIME from tests as passphrases need to entered manually.
+Mostly, the empty passphrase is used. However, the keys for
+ \"No Expiry two UIDs\" have the passphrase \"Passphrase\" (for OpenPGP as well
+ as S/MIME).")
+
+(defun test-conf ()
+ ;; Emacs doesn't have support for finding the name of the PGP agent
+ ;; on MacOS, so disable the checks.
+ (and (not (eq system-type 'darwin))
+ (ignore-errors (epg-find-configuration 'OpenPGP))))
+
+(defun enc-standards ()
+ (if with-smime '(enc-pgp enc-pgp-mime enc-smime)
+ '(enc-pgp enc-pgp-mime)))
+(defun enc-sign-standards ()
+ (if with-smime
+ '(enc-sign-pgp enc-sign-pgp-mime enc-sign-smime)
+ '(enc-sign-pgp enc-sign-pgp-mime)))
+(defun sign-standards ()
+ (if with-smime
+ '(sign-pgp sign-pgp-mime sign-smime)
+ '(sign-pgp sign-pgp-mime)))
+
+(defvar mml-smime-use)
+
+(defun mml-secure-test-fixture (body &optional interactive)
+ "Setup GnuPG home containing test keys and prepare environment for BODY.
+If optional INTERACTIVE is non-nil, allow questions to the user in case of
+key problems.
+This fixture temporarily unsets GPG_AGENT_INFO to enable passphrase tests,
+which will neither work with gpgsm nor GnuPG 2.1 any longer, I guess.
+Actually, I'm not sure why people would want to cache passwords in Emacs
+instead of gpg-agent."
+ (unwind-protect
+ (let ((agent-info (getenv "GPG_AGENT_INFO"))
+ (gpghome (getenv "GNUPGHOME")))
+ (condition-case error
+ (let ((epg-gpg-home-directory (ert-resource-directory))
+ (mml-smime-use 'epg)
+ ;; Create debug output in empty epg-debug-buffer.
+ (epg-debug t)
+ (epg-debug-buffer (get-buffer-create " *epg-test*"))
+ (mml-secure-fail-when-key-problem (not interactive)))
+ (with-current-buffer epg-debug-buffer
+ (erase-buffer))
+ ;; Unset GPG_AGENT_INFO to enable passphrase caching inside Emacs.
+ ;; Just for testing. Jens does not recommend this for daily use.
+ (setenv "GPG_AGENT_INFO")
+ ;; Set GNUPGHOME as gpg-agent started by gpgsm does
+ ;; not look in the proper places otherwise, see:
+ ;; https://bugs.gnupg.org/gnupg/issue2126
+ (setenv "GNUPGHOME" epg-gpg-home-directory)
+ (unwind-protect
+ (funcall body)
+ (mml-sec-test--kill-gpg-agent)))
+ (error
+ (setenv "GPG_AGENT_INFO" agent-info)
+ (setenv "GNUPGHOME" gpghome)
+ (signal (car error) (cdr error))))
+ (setenv "GPG_AGENT_INFO" agent-info)
+ (setenv "GNUPGHOME" gpghome))))
+
+(defun mml-secure-test-message-setup (method to from &optional text bcc)
+ "Setup a buffer with MML METHOD, TO, and FROM headers.
+Optionally, a message TEXT and BCC header can be passed."
+ (with-temp-buffer
+ (when bcc (insert (format "Bcc: %s\n" bcc)))
+ (insert (format "To: %s
+From: %s
+Subject: Test
+%s\n" to from mail-header-separator))
+ (if text
+ (insert (format "%s" text))
+ (spook))
+ (cond ((eq method 'enc-pgp-mime)
+ (mml-secure-message-encrypt-pgpmime 'nosig))
+ ((eq method 'enc-sign-pgp-mime)
+ (mml-secure-message-encrypt-pgpmime))
+ ((eq method 'enc-pgp) (mml-secure-message-encrypt-pgp 'nosig))
+ ((eq method 'enc-sign-pgp) (mml-secure-message-encrypt-pgp))
+ ((eq method 'enc-smime) (mml-secure-message-encrypt-smime 'nosig))
+ ((eq method 'enc-sign-smime) (mml-secure-message-encrypt-smime))
+ ((eq method 'sign-pgp-mime) (mml-secure-message-sign-pgpmime))
+ ((eq method 'sign-pgp) (mml-secure-message-sign-pgp))
+ ((eq method 'sign-smime) (mml-secure-message-sign-smime))
+ (t (error "Unknown method")))
+ (buffer-string)))
+
+(defun mml-secure-test-mail-fixture (method to from body2
+ &optional interactive)
+ "Setup buffer encrypted using METHOD for TO from FROM, call BODY2.
+Pass optional INTERACTIVE to mml-secure-test-fixture."
+ (mml-secure-test-fixture
+ (lambda ()
+ (let ((_context (if (memq method '(enc-smime enc-sign-smime sign-smime))
+ (epg-make-context 'CMS)
+ (epg-make-context 'OpenPGP)))
+ ;; Verify and decrypt by default.
+ (mm-verify-option 'known)
+ (mm-decrypt-option 'known)
+ (plaintext "The Magic Words are Squeamish Ossifrage"))
+ (with-temp-buffer
+ (insert (mml-secure-test-message-setup method to from plaintext))
+ (message-options-set-recipient)
+ (message-encode-message-body)
+ ;; Replace separator line with newline.
+ (goto-char (point-min))
+ (re-search-forward
+ (concat "^" (regexp-quote mail-header-separator) "\n"))
+ (replace-match "\n")
+ ;; The following treatment of handles, plainbuf, and multipart
+ ;; resulted from trial-and-error.
+ ;; Someone with more knowledge on how to decrypt messages and verify
+ ;; signatures might know more appropriate functions to invoke
+ ;; instead.
+ (let* ((handles (or (mm-dissect-buffer)
+ (mm-uu-dissect)))
+ (isplain (bufferp (car handles)))
+ (ismultipart (equal (car handles) "multipart/mixed"))
+ (plainbuf (if isplain
+ (car handles)
+ (if ismultipart
+ (car (cadadr handles))
+ (caadr handles))))
+ (decrypted
+ (with-current-buffer plainbuf (buffer-string)))
+ (gnus-info
+ (if isplain
+ nil
+ (if ismultipart
+ (or (mm-handle-multipart-ctl-parameter
+ (cadr handles) 'gnus-details)
+ (mm-handle-multipart-ctl-parameter
+ (cadr handles) 'gnus-info))
+ (mm-handle-multipart-ctl-parameter
+ handles 'gnus-info)))))
+ (funcall body2 gnus-info plaintext decrypted)))))
+ interactive))
+
+;; TODO If the variable BODY3 is renamed to BODY, an infinite recursion
+;; occurs. Emacs bug?
+(defun mml-secure-test-key-fixture (body3)
+ "Customize unique keys for sub@example.org and call BODY3.
+For OpenPGP, we have:
+- 1E6B FA97 3D9E 3103 B77F D399 C399 9CF1 268D BEA2
+ uid Different subkeys <sub@example.org>
+- 1463 2ECA B9E2 2736 9C8D D97B F7E7 9AB7 AE31 D471
+ uid Second Key Pair <sub@example.org>
+
+For S/MIME:
+ ID: 0x479DC6E2
+ Subject: /CN=Second Key Pair
+ aka: sub@example.org
+ fingerprint: 0E:58:22:9B:80:EE:33:95:9F:F7:18:FE:EF:25:40:2B:47:9D:C6:E2
+
+ ID: 0x5F88E9FC
+ Subject: /CN=Different subkeys
+ aka: sub@example.org
+ fingerprint: 4F:96:2A:B7:F4:76:61:6A:78:3D:72:AA:40:35:D5:9B:5F:88:E9:FC
+
+In both cases, the first key is customized for signing and encryption."
+ (mml-secure-test-fixture
+ (lambda ()
+ (let* ((mml-secure-key-preferences
+ '((OpenPGP (sign) (encrypt)) (CMS (sign) (encrypt))))
+ (pcontext (epg-make-context 'OpenPGP))
+ (pkey (epg-list-keys pcontext "C3999CF1268DBEA2"))
+ (scontext (epg-make-context 'CMS))
+ (skey (epg-list-keys scontext "0x479DC6E2")))
+ (mml-secure-cust-record-keys pcontext 'encrypt "sub@example.org" pkey)
+ (mml-secure-cust-record-keys pcontext 'sign "sub@example.org" pkey)
+ (mml-secure-cust-record-keys scontext 'encrypt "sub@example.org" skey)
+ (mml-secure-cust-record-keys scontext 'sign "sub@example.org" skey)
+ (funcall body3)))))
+
+(ert-deftest mml-secure-key-checks ()
+ "Test mml-secure-check-user-id and mml-secure-check-sub-key on sample keys."
+ (skip-unless (test-conf))
+ (mml-secure-test-fixture
+ (lambda ()
+ (let* ((context (epg-make-context 'OpenPGP))
+ (keys1 (epg-list-keys context "expired@example.org"))
+ (keys2 (epg-list-keys context "no-exp@example.org"))
+ (keys3 (epg-list-keys context "sub@example.org"))
+ (keys4 (epg-list-keys context "revoked-uid@example.org"))
+ (keys5 (epg-list-keys context "disabled@example.org"))
+ (keys6 (epg-list-keys context "sign@example.org"))
+ (keys7 (epg-list-keys context "jens.lechtenboerger@fsfe"))
+ )
+ (should (and (= 1 (length keys1)) (= 1 (length keys2))
+ (= 2 (length keys3))
+ (= 1 (length keys4)) (= 1 (length keys5))
+ ))
+ ;; key1 is expired
+ (should-not (mml-secure-check-user-id (car keys1) "expired@example.org"))
+ (should-not (mml-secure-check-sub-key context (car keys1) 'encrypt))
+ (should-not (mml-secure-check-sub-key context (car keys1) 'sign))
+
+ ;; key2 does not expire, but does not have the UID expired@example.org
+ (should-not (mml-secure-check-user-id (car keys2) "expired@example.org"))
+ (should (mml-secure-check-user-id (car keys2) "no-exp@example.org"))
+ (should (mml-secure-check-sub-key context (car keys2) 'encrypt))
+ (should (mml-secure-check-sub-key context (car keys2) 'sign))
+
+ ;; Two keys exist for sub@example.org.
+ (should (mml-secure-check-user-id (car keys3) "sub@example.org"))
+ (should (mml-secure-check-sub-key context (car keys3) 'encrypt))
+ (should (mml-secure-check-sub-key context (car keys3) 'sign))
+ (should (mml-secure-check-user-id (cadr keys3) "sub@example.org"))
+ (should (mml-secure-check-sub-key context (cadr keys3) 'encrypt))
+ (should (mml-secure-check-sub-key context (cadr keys3) 'sign))
+
+ ;; The UID revoked-uid@example.org is revoked. The key itself is
+ ;; usable, though (with the UID sub@example.org).
+ (should-not
+ (mml-secure-check-user-id (car keys4) "revoked-uid@example.org"))
+ (should (mml-secure-check-sub-key context (car keys4) 'encrypt))
+ (should (mml-secure-check-sub-key context (car keys4) 'sign))
+ (should (mml-secure-check-user-id (car keys4) "sub@example.org"))
+
+ ;; The next key is disabled and, thus, unusable.
+ (should (mml-secure-check-user-id (car keys5) "disabled@example.org"))
+ (should-not (mml-secure-check-sub-key context (car keys5) 'encrypt))
+ (should-not (mml-secure-check-sub-key context (car keys5) 'sign))
+
+ ;; The next key has multiple subkeys.
+ ;; 42466F0F is valid sign subkey, 501FFD98 is expired
+ (should (mml-secure-check-sub-key context (car keys6) 'sign "42466F0F"))
+ (should-not
+ (mml-secure-check-sub-key context (car keys6) 'sign "501FFD98"))
+ ;; DC7F66E7 is encrypt subkey
+ (should
+ (mml-secure-check-sub-key context (car keys6) 'encrypt "DC7F66E7"))
+ (should-not
+ (mml-secure-check-sub-key context (car keys6) 'sign "DC7F66E7"))
+ (should-not
+ (mml-secure-check-sub-key context (car keys6) 'encrypt "42466F0F"))
+
+ ;; The final key is just a public key.
+ (should (mml-secure-check-sub-key context (car keys7) 'encrypt))
+ (should-not (mml-secure-check-sub-key context (car keys7) 'sign))
+ ))))
+
+(ert-deftest mml-secure-find-usable-keys-1 ()
+ "Make sure that expired and disabled keys and revoked UIDs are not used."
+ (skip-unless (test-conf))
+ (mml-secure-test-fixture
+ (lambda ()
+ (let ((context (epg-make-context 'OpenPGP)))
+ (should-not
+ (mml-secure-find-usable-keys context "expired@example.org" 'encrypt))
+ (should-not
+ (mml-secure-find-usable-keys context "expired@example.org" 'sign))
+
+ (should-not
+ (mml-secure-find-usable-keys context "disabled@example.org" 'encrypt))
+ (should-not
+ (mml-secure-find-usable-keys context "disabled@example.org" 'sign))
+
+ (should-not
+ (mml-secure-find-usable-keys
+ context "<revoked-uid@example.org>" 'encrypt))
+ (should-not
+ (mml-secure-find-usable-keys
+ context "<revoked-uid@example.org>" 'sign))
+ ;; Same test without ankles. Will fail for Ma Gnus v0.14 and earlier.
+ (should-not
+ (mml-secure-find-usable-keys
+ context "revoked-uid@example.org" 'encrypt))
+
+ ;; Expired key should not be usable.
+ ;; Will fail for Ma Gnus v0.14 and earlier.
+ ;; sign@example.org has the expired subkey 0x501FFD98.
+ (should-not
+ (mml-secure-find-usable-keys context "0x501FFD98" 'sign))
+
+ (should
+ (mml-secure-find-usable-keys context "no-exp@example.org" 'encrypt))
+ (should
+ (mml-secure-find-usable-keys context "no-exp@example.org" 'sign))
+ ))))
+
+(ert-deftest mml-secure-find-usable-keys-2 ()
+ "Test different ways to search for keys."
+ (skip-unless (test-conf))
+ (mml-secure-test-fixture
+ (lambda ()
+ (let ((context (epg-make-context 'OpenPGP)))
+ ;; Plain substring search is not supported.
+ (should
+ (= 0 (length
+ (mml-secure-find-usable-keys context "No Expiry" 'encrypt))))
+ (should
+ (= 0 (length
+ (mml-secure-find-usable-keys context "No Expiry" 'sign))))
+
+ ;; Search for e-mail addresses works with and without ankle brackets.
+ (should
+ (= 1 (length (mml-secure-find-usable-keys
+ context "<no-exp@example.org>" 'encrypt))))
+ (should
+ (= 1 (length (mml-secure-find-usable-keys
+ context "<no-exp@example.org>" 'sign))))
+ (should
+ (= 1 (length (mml-secure-find-usable-keys
+ context "no-exp@example.org" 'encrypt))))
+ (should
+ (= 1 (length (mml-secure-find-usable-keys
+ context "no-exp@example.org" 'sign))))
+
+ ;; Use full UID string.
+ (should
+ (= 1 (length (mml-secure-find-usable-keys
+ context "No Expiry <no-exp@example.org>" 'encrypt))))
+ (should
+ (= 1 (length (mml-secure-find-usable-keys
+ context "No Expiry <no-exp@example.org>" 'sign))))
+
+ ;; If just the public key is present, only encryption is possible.
+ ;; Search works with key IDs, with and without prefix "0x".
+ (should
+ (= 1 (length (mml-secure-find-usable-keys
+ context "A142FD84" 'encrypt))))
+ (should
+ (= 1 (length (mml-secure-find-usable-keys
+ context "0xA142FD84" 'encrypt))))
+ (should
+ (= 0 (length (mml-secure-find-usable-keys
+ context "A142FD84" 'sign))))
+ (should
+ (= 0 (length (mml-secure-find-usable-keys
+ context "0xA142FD84" 'sign))))
+ ))))
+
+(ert-deftest mml-secure-select-preferred-keys-1 ()
+ "If only one key exists for an e-mail address, it is the preferred one."
+ (skip-unless (test-conf))
+ (mml-secure-test-fixture
+ (lambda ()
+ (let ((context (epg-make-context 'OpenPGP)))
+ (should (equal "832F3CC6518D37BC658261B802372A42CA6D40FB"
+ (mml-secure-fingerprint
+ (car (mml-secure-select-preferred-keys
+ context '("no-exp@example.org") 'encrypt)))))))))
+
+(ert-deftest mml-secure-select-preferred-keys-2 ()
+ "If multiple keys exists for an e-mail address, customization is necessary."
+ (skip-unless (test-conf))
+ (mml-secure-test-fixture
+ (lambda ()
+ (let* ((context (epg-make-context 'OpenPGP))
+ (mml-secure-key-preferences
+ '((OpenPGP (sign) (encrypt)) (CMS (sign) (encrypt))))
+ (pref (car (mml-secure-find-usable-keys
+ context "sub@example.org" 'encrypt))))
+ (should-error (mml-secure-select-preferred-keys
+ context '("sub@example.org") 'encrypt))
+ (mml-secure-cust-record-keys
+ context 'encrypt "sub@example.org" (list pref))
+ (should (mml-secure-select-preferred-keys
+ context '("sub@example.org") 'encrypt))
+ (should-error (mml-secure-select-preferred-keys
+ context '("sub@example.org") 'sign))
+ (should (mml-secure-select-preferred-keys
+ context '("sub@example.org") 'encrypt))
+ (should
+ (equal (list (mml-secure-fingerprint pref))
+ (mml-secure-cust-fpr-lookup context 'encrypt "sub@example.org")))
+ (should (mml-secure-cust-remove-keys context 'encrypt "sub@example.org"))
+ (should-error (mml-secure-select-preferred-keys
+ context '("sub@example.org") 'encrypt))))))
+
+(ert-deftest mml-secure-select-preferred-keys-3 ()
+ "Expired customized keys are removed if multiple keys are available."
+ (skip-unless (test-conf))
+ (mml-secure-test-fixture
+ (lambda ()
+ (let ((context (epg-make-context 'OpenPGP))
+ (mml-secure-key-preferences
+ '((OpenPGP (sign) (encrypt)) (CMS (sign) (encrypt)))))
+ ;; sub@example.org has two keys (268DBEA2, AE31D471).
+ ;; Normal preference works.
+ (mml-secure-cust-record-keys
+ context 'encrypt "sub@example.org" (epg-list-keys context "268DBEA2"))
+ (should (mml-secure-select-preferred-keys
+ context '("sub@example.org") 'encrypt))
+ (mml-secure-cust-remove-keys context 'encrypt "sub@example.org")
+
+ ;; Fake preference for expired (unrelated) key CE15FAE7,
+ ;; results in error (and automatic removal of outdated preference).
+ (mml-secure-cust-record-keys
+ context 'encrypt "sub@example.org" (epg-list-keys context "CE15FAE7"))
+ (should-error (mml-secure-select-preferred-keys
+ context '("sub@example.org") 'encrypt))
+ (should-not
+ (mml-secure-cust-remove-keys context 'encrypt "sub@example.org"))))))
+
+(ert-deftest mml-secure-select-preferred-keys-4 ()
+ "Multiple keys can be recorded per recipient or signature."
+ (skip-unless (test-conf))
+ (skip-unless (ignore-errors (epg-find-configuration 'CMS)))
+ (mml-secure-test-fixture
+ (lambda ()
+ (let ((pcontext (epg-make-context 'OpenPGP))
+ (scontext (epg-make-context 'CMS))
+ (pkeys '("1E6BFA973D9E3103B77FD399C3999CF1268DBEA2"
+ "14632ECAB9E227369C8DD97BF7E79AB7AE31D471"))
+ (skeys '("0x5F88E9FC" "0x479DC6E2"))
+ (mml-secure-key-preferences
+ '((OpenPGP (sign) (encrypt)) (CMS (sign) (encrypt)))))
+
+ ;; OpenPGP preferences via pcontext
+ (dolist (key pkeys nil)
+ (mml-secure-cust-record-keys
+ pcontext 'encrypt "sub@example.org" (epg-list-keys pcontext key))
+ (mml-secure-cust-record-keys
+ pcontext 'sign "sub@example.org" (epg-list-keys pcontext key 'secret)))
+ (let ((p-e-fprs (mml-secure-cust-fpr-lookup
+ pcontext 'encrypt "sub@example.org"))
+ (p-s-fprs (mml-secure-cust-fpr-lookup
+ pcontext 'sign "sub@example.org")))
+ (should (= 2 (length p-e-fprs)))
+ (should (= 2 (length p-s-fprs)))
+ (should (member "1E6BFA973D9E3103B77FD399C3999CF1268DBEA2" p-e-fprs))
+ (should (member "14632ECAB9E227369C8DD97BF7E79AB7AE31D471" p-e-fprs))
+ (should (member "1E6BFA973D9E3103B77FD399C3999CF1268DBEA2" p-s-fprs))
+ (should (member "14632ECAB9E227369C8DD97BF7E79AB7AE31D471" p-s-fprs)))
+ ;; Duplicate record does not change anything.
+ (mml-secure-cust-record-keys
+ pcontext 'encrypt "sub@example.org"
+ (epg-list-keys pcontext "1E6BFA973D9E3103B77FD399C3999CF1268DBEA2"))
+ (mml-secure-cust-record-keys
+ pcontext 'sign "sub@example.org"
+ (epg-list-keys pcontext "1E6BFA973D9E3103B77FD399C3999CF1268DBEA2"))
+ (let ((p-e-fprs (mml-secure-cust-fpr-lookup
+ pcontext 'encrypt "sub@example.org"))
+ (p-s-fprs (mml-secure-cust-fpr-lookup
+ pcontext 'sign "sub@example.org")))
+ (should (= 2 (length p-e-fprs)))
+ (should (= 2 (length p-s-fprs))))
+
+ ;; S/MIME preferences via scontext
+ (dolist (key skeys nil)
+ (mml-secure-cust-record-keys
+ scontext 'encrypt "sub@example.org"
+ (epg-list-keys scontext key))
+ (mml-secure-cust-record-keys
+ scontext 'sign "sub@example.org"
+ (epg-list-keys scontext key 'secret)))
+ (let ((s-e-fprs (mml-secure-cust-fpr-lookup
+ scontext 'encrypt "sub@example.org"))
+ (s-s-fprs (mml-secure-cust-fpr-lookup
+ scontext 'sign "sub@example.org")))
+ (should (= 2 (length s-e-fprs)))
+ (should (= 2 (length s-s-fprs))))
+ ))))
+
+(defun mml-secure-test-en-decrypt
+ (method to from
+ &optional checksig checkplain enc-keys expectfail interactive)
+ "Encrypt message using METHOD, addressed to TO, from FROM.
+If optional CHECKSIG is non-nil, it must be a number, and a signature check is
+performed; the number indicates how many signatures are expected.
+If optional CHECKPLAIN is non-nil, the expected plaintext should be obtained
+via decryption.
+If optional ENC-KEYS is non-nil, it is a list of pairs of encryption keys (for
+OpenPGP and S/SMIME) expected in `epg-debug-buffer'.
+If optional EXPECTFAIL is non-nil, a decryption failure is expected.
+Pass optional INTERACTIVE to mml-secure-test-mail-fixture."
+ (mml-secure-test-mail-fixture method to from
+ (lambda (gnus-info plaintext decrypted)
+ (if expectfail
+ (should-not (equal plaintext decrypted))
+ (when checkplain
+ (should (equal plaintext decrypted)))
+ (let ((protocol (if (memq method
+ '(enc-smime enc-sign-smime sign-smime))
+ 'CMS
+ 'OpenPGP)))
+ (when checksig
+ (let* ((context (epg-make-context protocol))
+ (signer-names (mml-secure-signer-names protocol from))
+ (signer-keys (mml-secure-signers context signer-names))
+ (signer-fprs (mapcar 'mml-secure-fingerprint signer-keys)))
+ (should (eq checksig (length signer-fprs)))
+ (if (eq checksig 0)
+ ;; First key in keyring
+ (should (string-match-p
+ (concat "Good signature from "
+ (if (eq protocol 'CMS)
+ "0E58229B80EE33959FF718FEEF25402B479DC6E2"
+ "02372A42CA6D40FB"))
+ gnus-info)))
+ (dolist (fpr signer-fprs nil)
+ ;; OpenPGP: "Good signature from 02372A42CA6D40FB No Expiry <no-exp@example.org> (trust undefined) created ..."
+ ;; S/MIME: "Good signature from D06AA118653CC38E9D0CAF56ED7A2135E1582177 /CN=No Expiry (trust full) ..."
+ (should (string-match-p
+ (concat "Good signature from "
+ (if (eq protocol 'CMS)
+ fpr
+ (substring fpr -16 nil)))
+ gnus-info)))))
+ (when enc-keys
+ (with-current-buffer epg-debug-buffer
+ (goto-char (point-min))
+ ;; The following regexp does not necessarily match at the
+ ;; start of the line as a path may or may not be present.
+ ;; Also note that gpg.* matches gpg2 and gpgsm as well.
+ (let* ((line (concat "gpg.*--encrypt.*$"))
+ (end (re-search-forward line))
+ (match (match-string 0)))
+ (should (and end match))
+ (dolist (pair enc-keys nil)
+ (let ((fpr (if (eq protocol 'OpenPGP)
+ (car pair)
+ (cdr pair))))
+ (should (string-match-p (concat "-r " fpr) match))))
+ (goto-char (point-max))
+ ))))))
+ interactive))
+
+(defvar mml-smime-cache-passphrase)
+(defvar mml2015-cache-passphrase)
+(defvar mml1991-cache-passphrase)
+
+(defun mml-secure-test-en-decrypt-with-passphrase
+ (method to from checksig jl-passphrase do-cache
+ &optional enc-keys expectfail)
+ "Call mml-secure-test-en-decrypt with changed passphrase caching.
+Args METHOD, TO, FROM, CHECKSIG are passed to mml-secure-test-en-decrypt.
+JL-PASSPHRASE is fixed as return value for `read-passwd',
+boolean DO-CACHE determines whether to cache the passphrase.
+If optional ENC-KEYS is non-nil, it is a list of encryption keys expected
+in `epg-debug-buffer'.
+If optional EXPECTFAIL is non-nil, a decryption failure is expected."
+ (let ((mml-secure-cache-passphrase do-cache)
+ (mml1991-cache-passphrase do-cache)
+ (mml2015-cache-passphrase do-cache)
+ (mml-smime-cache-passphrase do-cache)
+ )
+ (cl-letf (((symbol-function 'read-passwd)
+ (lambda (_prompt &optional _confirm _default) jl-passphrase)))
+ (mml-secure-test-en-decrypt method to from checksig t enc-keys expectfail)
+ )))
+
+(ert-deftest mml-secure-en-decrypt-1 ()
+ "Encrypt message; then decrypt and test for expected result.
+In this test, the single matching key is chosen automatically."
+ (skip-unless (test-conf))
+ (dolist (method (enc-standards) nil)
+ ;; no-exp@example.org with single encryption key
+ (mml-secure-test-en-decrypt
+ method "no-exp@example.org" "sub@example.org" nil t
+ (list (cons "02372A42CA6D40FB" "ED7A2135E1582177")))))
+
+(ert-deftest mml-secure-en-decrypt-2 ()
+ "Encrypt message; then decrypt and test for expected result.
+In this test, the encryption key needs to fixed among multiple ones."
+ (skip-unless (test-conf))
+ (skip-unless (ignore-errors (epg-find-configuration 'CMS)))
+ ;; sub@example.org with multiple candidate keys,
+ ;; fixture customizes preferred ones.
+ (mml-secure-test-key-fixture
+ (lambda ()
+ (dolist (method (enc-standards) nil)
+ (mml-secure-test-en-decrypt
+ method "sub@example.org" "no-exp@example.org" nil t
+ (list (cons "C3999CF1268DBEA2" "EF25402B479DC6E2")))))))
+
+(ert-deftest mml-secure-en-decrypt-3 ()
+ "Encrypt message; then decrypt and test for expected result.
+In this test, encrypt-to-self variables are set to t."
+ ;; Random failures with "wrong-type-argument stringp nil".
+ ;; Seems unlikely to be specific to hydra.nixos.org...
+ :tags (if (getenv "EMACS_HYDRA_CI") '(:unstable))
+ (skip-unless (test-conf))
+ (skip-unless (ignore-errors (epg-find-configuration 'CMS)))
+ ;; sub@example.org with multiple candidate keys,
+ ;; fixture customizes preferred ones.
+ (mml-secure-test-key-fixture
+ (lambda ()
+ (let ((mml-secure-openpgp-encrypt-to-self t)
+ (mml-secure-smime-encrypt-to-self t))
+ (dolist (method (enc-standards) nil)
+ (mml-secure-test-en-decrypt
+ method "sub@example.org" "no-exp@example.org" nil t
+ (list (cons "C3999CF1268DBEA2" "EF25402B479DC6E2")
+ (cons "02372A42CA6D40FB" "ED7A2135E1582177"))))))))
+
+(ert-deftest mml-secure-en-decrypt-4 ()
+ "Encrypt message; then decrypt and test for expected result.
+In this test, encrypt-to-self variables are set to lists."
+ (skip-unless (test-conf))
+ ;; Send from sub@example.org, which has two keys; encrypt to both.
+ (let ((mml-secure-openpgp-encrypt-to-self
+ '("C3999CF1268DBEA2" "F7E79AB7AE31D471"))
+ (mml-secure-smime-encrypt-to-self
+ '("EF25402B479DC6E2" "4035D59B5F88E9FC")))
+ (dolist (method (enc-standards) nil)
+ (mml-secure-test-en-decrypt
+ method "no-exp@example.org" "sub@example.org" nil t
+ (list (cons "C3999CF1268DBEA2" "EF25402B479DC6E2")
+ (cons "F7E79AB7AE31D471" "4035D59B5F88E9FC"))))))
+
+(ert-deftest mml-secure-en-decrypt-sign-1-1-single ()
+ "Sign and encrypt message; then decrypt and test for expected result.
+In this test, just multiple encryption and signing keys may be available."
+ :tags '(:unstable)
+ (skip-unless (test-conf))
+ (mml-secure-test-key-fixture
+ (lambda ()
+ (let ((mml-secure-openpgp-sign-with-sender t)
+ (mml-secure-smime-sign-with-sender t))
+ (dolist (method (enc-sign-standards) nil)
+ ;; no-exp with just one key
+ (mml-secure-test-en-decrypt
+ method "no-exp@example.org" "no-exp@example.org" 1 t)
+ ;; customized choice for encryption key
+ (mml-secure-test-en-decrypt
+ method "sub@example.org" "no-exp@example.org" 1 t)
+ ;; customized choice for signing key
+ (mml-secure-test-en-decrypt
+ method "no-exp@example.org" "sub@example.org" 1 t)
+ ;; customized choice for both keys
+ (mml-secure-test-en-decrypt
+ method "sub@example.org" "sub@example.org" 1 t)
+ )))))
+
+(ert-deftest mml-secure-en-decrypt-sign-1-2-double ()
+ "Sign and encrypt message; then decrypt and test for expected result.
+In this test, just multiple encryption and signing keys may be available."
+ :tags '(:unstable)
+ (skip-unless (test-conf))
+ (mml-secure-test-key-fixture
+ (lambda ()
+ (let ((mml-secure-openpgp-sign-with-sender t)
+ (mml-secure-smime-sign-with-sender t))
+ ;; Now use both keys to sign. The customized one via sign-with-sender,
+ ;; the other one via the following setting.
+ (let ((mml-secure-openpgp-signers '("F7E79AB7AE31D471"))
+ (mml-secure-smime-signers '("0x5F88E9FC")))
+ (dolist (method (enc-sign-standards) nil)
+ (mml-secure-test-en-decrypt
+ method "no-exp@example.org" "sub@example.org" 2 t)))))))
+
+(ert-deftest mml-secure-en-decrypt-sign-1-3-double ()
+ "Sign and encrypt message; then decrypt and test for expected result.
+In this test, just multiple encryption and signing keys may be available."
+ :tags '(:unstable)
+ (skip-unless (test-conf))
+ (mml-secure-test-key-fixture
+ (lambda ()
+ ;; Now use both keys for sub@example.org to sign an e-mail from
+ ;; a different address (without associated keys).
+ (let ((mml-secure-openpgp-sign-with-sender nil)
+ (mml-secure-smime-sign-with-sender nil)
+ (mml-secure-openpgp-signers
+ '("F7E79AB7AE31D471" "C3999CF1268DBEA2"))
+ (mml-secure-smime-signers '("0x5F88E9FC" "0x479DC6E2")))
+ (dolist (method (enc-sign-standards) nil)
+ (mml-secure-test-en-decrypt
+ method "no-exp@example.org" "no-keys@example.org" 2 t))))))
+
+(ert-deftest mml-secure-en-decrypt-sign-2 ()
+ "Sign and encrypt message; then decrypt and test for expected result.
+In this test, lists of encryption and signing keys are customized."
+ :tags '(:unstable)
+ (skip-unless (test-conf))
+ (mml-secure-test-key-fixture
+ (lambda ()
+ (let ((mml-secure-key-preferences
+ '((OpenPGP (sign) (encrypt)) (CMS (sign) (encrypt))))
+ (pcontext (epg-make-context 'OpenPGP))
+ (scontext (epg-make-context 'CMS))
+ (mml-secure-openpgp-sign-with-sender t)
+ (mml-secure-smime-sign-with-sender t))
+ (dolist (key '("F7E79AB7AE31D471" "C3999CF1268DBEA2") nil)
+ (mml-secure-cust-record-keys
+ pcontext 'encrypt "sub@example.org" (epg-list-keys pcontext key))
+ (mml-secure-cust-record-keys
+ pcontext 'sign "sub@example.org" (epg-list-keys pcontext key t)))
+ (dolist (key '("0x5F88E9FC" "0x479DC6E2") nil)
+ (mml-secure-cust-record-keys
+ scontext 'encrypt "sub@example.org" (epg-list-keys scontext key))
+ (mml-secure-cust-record-keys
+ scontext 'sign "sub@example.org" (epg-list-keys scontext key t)))
+ (dolist (method (enc-sign-standards) nil)
+ ;; customized choice for encryption key
+ (mml-secure-test-en-decrypt
+ method "sub@example.org" "no-exp@example.org" 1 t)
+ ;; customized choice for signing key
+ (mml-secure-test-en-decrypt
+ method "no-exp@example.org" "sub@example.org" 2 t)
+ ;; customized choice for both keys
+ (mml-secure-test-en-decrypt
+ method "sub@example.org" "sub@example.org" 2 t)
+ )))))
+
+(ert-deftest mml-secure-en-decrypt-sign-3 ()
+ "Sign and encrypt message; then decrypt and test for expected result.
+Use sign-with-sender and encrypt-to-self."
+ :tags '(:unstable)
+ (skip-unless (test-conf))
+ (mml-secure-test-key-fixture
+ (lambda ()
+ (let ((mml-secure-openpgp-sign-with-sender t)
+ (mml-secure-openpgp-encrypt-to-self t)
+ (mml-secure-smime-sign-with-sender t)
+ (mml-secure-smime-encrypt-to-self t))
+ (dolist (method (enc-sign-standards) nil)
+ (mml-secure-test-en-decrypt
+ method "sub@example.org" "no-exp@example.org" 1 t
+ (list (cons "C3999CF1268DBEA2" "EF25402B479DC6E2")
+ (cons "02372A42CA6D40FB" "ED7A2135E1582177"))))
+ ))))
+
+(ert-deftest mml-secure-sign-verify-1 ()
+ "Sign message with sender; then verify and test for expected result."
+ (skip-unless (test-conf))
+ (skip-unless (ignore-errors (epg-find-configuration 'CMS)))
+ (mml-secure-test-key-fixture
+ (lambda ()
+ (dolist (method (sign-standards) nil)
+ (let ((mml-secure-openpgp-sign-with-sender t)
+ (mml-secure-smime-sign-with-sender t))
+ ;; A single signing key for sender sub@example.org is customized
+ ;; in the fixture.
+ (mml-secure-test-en-decrypt
+ method "uid1@example.org" "sub@example.org" 1 nil)
+
+ ;; From sub@example.org, sign with two keys;
+ ;; sign-with-sender and one from signers-variable:
+ (let ((mml-secure-openpgp-signers '("02372A42CA6D40FB"))
+ (mml-secure-smime-signers
+ '("D06AA118653CC38E9D0CAF56ED7A2135E1582177")))
+ (mml-secure-test-en-decrypt
+ method "no-exp@example.org" "sub@example.org" 2 nil))
+ )))))
+
+(ert-deftest mml-secure-sign-verify-3 ()
+ "Try to sign message with expired OpenPGP subkey, which raises an error.
+With Ma Gnus v0.14 and earlier a signature would be created with a wrong key."
+ (skip-unless (test-conf))
+ (should-error
+ (mml-secure-test-key-fixture
+ (lambda ()
+ (let ((with-smime nil)
+ (mml-secure-openpgp-sign-with-sender nil)
+ (mml-secure-openpgp-signers '("501FFD98")))
+ (dolist (method (sign-standards) nil)
+ (mml-secure-test-en-decrypt
+ method "no-exp@example.org" "sign@example.org" 1 nil)
+ ))))))
+
+;; TODO Passphrase passing and caching in Emacs does not seem to work
+;; with gpgsm at all.
+;; Independently of caching settings, a pinentry dialogue is displayed.
+;; Thus, the following tests require the user to enter the correct gpgsm
+;; passphrases at the correct points in time. (Either empty string or
+;; "Passphrase".)
+(ert-deftest mml-secure-en-decrypt-passphrase-cache ()
+ "Encrypt message; then decrypt and test for expected result.
+In this test, a key is used that requires the passphrase \"Passphrase\".
+In the first decryption this passphrase is hardcoded, in the second one it
+ is taken from a cache."
+ (skip-unless (test-conf))
+ (ert-skip "Requires passphrase")
+ (mml-secure-test-key-fixture
+ (lambda ()
+ (dolist (method (enc-standards) nil)
+ (mml-secure-test-en-decrypt-with-passphrase
+ method "uid1@example.org" "sub@example.org" nil
+ ;; Beware! For passphrases copy-sequence is necessary, as they may
+ ;; be erased, which actually changes the function's code and causes
+ ;; multiple invocations to fail. I was surprised...
+ (copy-sequence "Passphrase") t)
+ (mml-secure-test-en-decrypt-with-passphrase
+ method "uid1@example.org" "sub@example.org" nil
+ (copy-sequence "Incorrect") t)))))
+
+(defun mml-secure-en-decrypt-passphrase-no-cache (method)
+ "Encrypt message with METHOD; then decrypt and test for expected result.
+In this test, a key is used that requires the passphrase \"Passphrase\".
+In the first decryption this passphrase is hardcoded, but caching disabled.
+So the second decryption fails."
+ (mml-secure-test-key-fixture
+ (lambda ()
+ (mml-secure-test-en-decrypt-with-passphrase
+ method "uid1@example.org" "sub@example.org" nil
+ (copy-sequence "Passphrase") nil)
+ (mml-secure-test-en-decrypt-with-passphrase
+ method "uid1@example.org" "sub@example.org" nil
+ (copy-sequence "Incorrect") nil nil t))))
+
+(ert-deftest mml-secure-en-decrypt-passphrase-no-cache-openpgp-todo ()
+ "Passphrase caching with OpenPGP only for GnuPG 1.x."
+ (skip-unless (test-conf))
+ (skip-unless (string< (cdr (assq 'version (epg-find-configuration 'OpenPGP)))
+ "2"))
+ (mml-secure-en-decrypt-passphrase-no-cache 'enc-pgp)
+ (mml-secure-en-decrypt-passphrase-no-cache 'enc-pgp-mime))
+
+(ert-deftest mml-secure-en-decrypt-passphrase-no-cache-smime-todo ()
+ "Passphrase caching does not work with S/MIME (and gpgsm)."
+ :expected-result :failed
+ (skip-unless (test-conf))
+ (if with-smime
+ (mml-secure-en-decrypt-passphrase-no-cache 'enc-smime)
+ (should nil)))
+
+
+;; Test truncation of question in y-or-n-p.
+(defun mml-secure-select-preferred-keys-todo ()
+ "Manual customization with truncated question."
+ (mml-secure-test-key-fixture
+ (lambda ()
+ (mml-secure-test-en-decrypt
+ 'enc-pgp-mime
+ "jens.lechtenboerger@informationelle-selbstbestimmung-im-internet.de"
+ "no-exp@example.org" nil t nil nil t))))
+
+(defun mml-secure-select-preferred-keys-ok ()
+ "Manual customization with entire question."
+ (mml-secure-test-fixture
+ (lambda ()
+ (mml-secure-select-preferred-keys
+ (epg-make-context 'OpenPGP)
+ '("jens.lechtenboerger@informationelle-selbstbestimmung-im-internet.de")
+ 'encrypt))
+ t))
+
+
+;; ERT entry points
+(defun mml-secure-run-tests ()
+ "Run all tests with defaults."
+ (ert-run-tests-batch))
+
+(defun mml-secure-run-tests-with-gpg2 ()
+ "Run all tests with gpg2 instead of gpg."
+ (let* ((epg-gpg-program "gpg2"); ~/local/gnupg-2.1.9/PLAY/inst/bin/gpg2
+ (gpg-version (cdr (assq 'version (epg-find-configuration 'OpenPGP))))
+ ;; Empty passphrases do not seem to work with gpgsm in 2.1.x:
+ ;; https://lists.gnupg.org/pipermail/gnupg-users/2015-October/054575.html
+ (with-smime (string< gpg-version "2.1")))
+ (ert-run-tests-batch)))
+
+(defun mml-secure-run-tests-without-smime ()
+ "Skip S/MIME tests (as they require manual passphrase entry)."
+ (let ((with-smime nil))
+ (ert-run-tests-batch)))
+
+(defun mml-sec-test--kill-gpg-agent ()
+ (dolist (pid (list-system-processes))
+ (let ((atts (process-attributes pid)))
+ (when (and (equal (cdr (assq 'user atts)) (user-login-name))
+ (or (equal (cdr (assq 'comm atts)) "gpg-agent")
+ (equal (cdr (assq 'comm atts)) "scdaemon"))
+ (string-match
+ (concat "homedir.*"
+ (regexp-quote (directory-file-name
+ (ert-resource-directory))))
+ (cdr (assq 'args atts))))
+ (call-process "kill" nil nil nil (format "%d" pid))))))
+
+;;; mml-sec-tests.el ends here
diff --git a/test/lisp/gnus/nnrss-tests.el b/test/lisp/gnus/nnrss-tests.el
new file mode 100644
index 00000000000..47d208cb160
--- /dev/null
+++ b/test/lisp/gnus/nnrss-tests.el
@@ -0,0 +1,45 @@
+;;; nnrss-tests.el --- tests for gnus/nnrss.el -*- lexical-binding:t -*-
+
+;; Copyright (C) 2019-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'nnrss)
+
+(ert-deftest test-nnrss-normalize ()
+ (should (equal (nnrss-normalize-date "2004-09-17T05:09:49.001+00:00")
+ "Fri, 17 Sep 2004 05:09:49 +0000")))
+
+(defconst test-nnrss-xml
+ '((rss
+ ((version . "2.0")
+ (xmlns:dc . "http://purl.org/dc/elements/1.1/"))
+ (channel
+ ((xmlns:content . "http://purl.org/rss/1.0/modules/content/"))))))
+
+(ert-deftest test-nnrss-namespace-top ()
+ (should (equal (nnrss-get-namespace-prefix
+ test-nnrss-xml "http://purl.org/dc/elements/1.1/")
+ "dc:")))
+(ert-deftest test-nnrss-namespace-inner ()
+ (should (equal (nnrss-get-namespace-prefix
+ test-nnrss-xml "http://purl.org/rss/1.0/modules/content/")
+ "content:")))
+
+;;; nnrss-tests.el ends here
diff --git a/test/lisp/help-fns-tests.el b/test/lisp/help-fns-tests.el
index 98e6b335b90..7ff7aa1ccd7 100644
--- a/test/lisp/help-fns-tests.el
+++ b/test/lisp/help-fns-tests.el
@@ -1,6 +1,6 @@
-;;; help-fns.el --- tests for help-fns.el
+;;; help-fns-tests.el --- tests for help-fns.el -*- lexical-binding: t -*-
-;; Copyright (C) 2014-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2022 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
@@ -24,8 +24,10 @@
;;; Code:
(require 'ert)
+(require 'help-fns)
+(require 'subr-x)
-(autoload 'help-fns-test--macro "help-fns" nil nil t)
+(autoload 'help-fns-test--macro "foo" nil nil t)
;;; Several tests for describe-function
@@ -56,31 +58,38 @@ Return first line of the output of (describe-function-1 FUNC)."
(should (string-match regexp result))))
(ert-deftest help-fns-test-lisp-macro ()
- (let ((regexp "a Lisp macro in .subr\.el")
+ (let ((regexp "a Lisp macro in .+subr\\.el")
(result (help-fns-tests--describe-function 'when)))
(should (string-match regexp result))))
(ert-deftest help-fns-test-lisp-defun ()
- (let ((regexp "a compiled Lisp function in .subr\.el")
+ (let ((regexp (if (featurep 'native-compile)
+ "a native-compiled Lisp function in .+subr\\.el"
+ "a byte-compiled Lisp function in .+subr\\.el"))
(result (help-fns-tests--describe-function 'last)))
(should (string-match regexp result))))
(ert-deftest help-fns-test-lisp-defsubst ()
- (let ((regexp "a compiled Lisp function in .subr\.el")
+ (let ((regexp "a byte-compiled Lisp function in .+subr\\.el")
(result (help-fns-tests--describe-function 'posn-window)))
(should (string-match regexp result))))
(ert-deftest help-fns-test-alias-to-defun ()
- (let ((regexp "an alias for .set-file-modes. in .subr\.el")
+ (let ((regexp "an alias for .set-file-modes. in .+subr\\.el")
(result (help-fns-tests--describe-function 'chmod)))
(should (string-match regexp result))))
(ert-deftest help-fns-test-bug23887 ()
"Test for https://debbugs.gnu.org/23887 ."
- (let ((regexp "an alias for .re-search-forward. in .subr\.el")
+ (let ((regexp "an alias for .re-search-forward. in .+subr\\.el")
(result (help-fns-tests--describe-function 'search-forward-regexp)))
(should (string-match regexp result))))
+(ert-deftest help-fns-test-dangling-alias ()
+ "Make sure we don't burp on bogus aliases."
+ (let ((f (make-symbol "bogus-alias")))
+ (define-obsolete-function-alias f 'help-fns-test--undefined-function "past")
+ (describe-symbol f)))
;;; Test describe-function over functions with funny names
(defun abc\\\[universal-argument\]b\`c\'d\\e\"f (x)
@@ -118,4 +127,64 @@ Return first line of the output of (describe-function-1 FUNC)."
(goto-char (point-min))
(should (looking-at "^font-lock-comment-face is "))))
-;;; help-fns.el ends here
+(defvar foo-test-map)
+(defvar help-fns-test--describe-keymap-foo)
+
+
+;;; Tests for describe-keymap
+(ert-deftest help-fns-test-find-keymap-name ()
+ (should (equal (help-fns-find-keymap-name lisp-mode-map) 'lisp-mode-map))
+ ;; Follow aliasing.
+ (unwind-protect
+ (progn
+ (defvaralias 'foo-test-map 'lisp-mode-map)
+ (should (equal (help-fns-find-keymap-name foo-test-map) 'lisp-mode-map)))
+ (makunbound 'foo-test-map)))
+
+(ert-deftest help-fns-test-describe-keymap/symbol ()
+ (describe-keymap 'minibuffer-local-must-match-map)
+ (with-current-buffer "*Help*"
+ (should (looking-at "^minibuffer-local-must-match-map is"))))
+
+(ert-deftest help-fns-test-describe-keymap/value ()
+ (describe-keymap minibuffer-local-must-match-map)
+ (with-current-buffer "*Help*"
+ (should (looking-at "\nKey"))))
+
+(ert-deftest help-fns-test-describe-keymap/not-keymap ()
+ (should-error (describe-keymap nil))
+ (should-error (describe-keymap emacs-version)))
+
+(ert-deftest help-fns-test-describe-keymap/let-bound ()
+ (let ((foobar minibuffer-local-must-match-map))
+ (describe-keymap foobar)
+ (with-current-buffer "*Help*"
+ (should (looking-at "\nKey")))))
+
+(ert-deftest help-fns-test-describe-keymap/dynamically-bound-no-file ()
+ (setq help-fns-test--describe-keymap-foo minibuffer-local-must-match-map)
+ (describe-keymap 'help-fns-test--describe-keymap-foo)
+ (with-current-buffer "*Help*"
+ (should (looking-at "^help-fns-test--describe-keymap-foo is"))))
+
+;;; Tests for find-lisp-object-file-name
+(ert-deftest help-fns-test-bug24697-function-search ()
+ (should-not (find-lisp-object-file-name 'tab-width 1)))
+
+(ert-deftest help-fns-test-bug24697-non-internal-variable ()
+ (let ((help-fns--test-var (make-symbol "help-fns--test-var")))
+ ;; simulate an internal variable
+ (put help-fns--test-var 'variable-documentation 1)
+ (should-not (find-lisp-object-file-name help-fns--test-var 'defface))
+ (should-not (find-lisp-object-file-name help-fns--test-var 1))))
+
+(ert-deftest help-fns--analyze-function-recursive ()
+ (defalias 'help-fns--a 'help-fns--b)
+ (should (equal (help-fns--analyze-function 'help-fns--a)
+ '(help-fns--a help-fns--b t help-fns--b)))
+ ;; Make a loop and see that it doesn't infloop.
+ (defalias 'help-fns--b 'help-fns--a)
+ (should (equal (help-fns--analyze-function 'help-fns--a)
+ '(help-fns--a help-fns--b t help-fns--b))))
+
+;;; help-fns-tests.el ends here
diff --git a/test/lisp/help-mode-tests.el b/test/lisp/help-mode-tests.el
new file mode 100644
index 00000000000..04241f31383
--- /dev/null
+++ b/test/lisp/help-mode-tests.el
@@ -0,0 +1,169 @@
+;;; help-mode-tests.el --- Tests for help-mode.el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+;; Author: Simen Heggestøyl <simenheg@gmail.com>
+;; Keywords:
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;
+
+;;; Code:
+
+(require 'ert)
+(require 'help-mode)
+(require 'pp)
+
+(ert-deftest help-mode-tests-help-buffer ()
+ (let ((help-xref-following nil))
+ (should (equal "*Help*" (help-buffer)))))
+
+(ert-deftest help-mode-tests-help-buffer-current-buffer ()
+ (with-temp-buffer
+ (help-mode)
+ (let ((help-xref-following t))
+ (should (equal (buffer-name (current-buffer))
+ (help-buffer))))))
+
+(ert-deftest help-mode-tests-make-xrefs ()
+ (with-temp-buffer
+ (insert "car is a built-in function in ‘C source code’.
+
+(car LIST)
+
+ Probably introduced at or before Emacs version 1.2.
+ This function does not change global state, including the match data.
+
+Return the car of LIST. If arg is nil, return nil.
+Error if arg is not nil and not a cons cell. See also ‘car-safe’.
+
+See Info node ‘(elisp)Cons Cells’ for a discussion of related basic
+Lisp concepts such as car, cdr, cons cell and list.")
+ (help-mode)
+ (help-make-xrefs)
+ (let ((car-safe-button (button-at 298)))
+ (should (eq (button-type car-safe-button) 'help-symbol))
+ (should (eq (button-get car-safe-button 'help-function)
+ #'describe-symbol)))
+ (let ((cons-cells-info-button (button-at 333)))
+ (should (eq (button-type cons-cells-info-button) 'help-info))
+ (should (eq (button-get cons-cells-info-button 'help-function)
+ #'info)))))
+
+(ert-deftest help-mode-tests-xref-button ()
+ (let* ((fmt "See also the function ‘%s’.")
+ ;; 1+ translates string index to buffer position.
+ (beg (1+ (string-search "%" fmt))))
+ (with-temp-buffer
+ (dolist (fn '(interactive \` = + - * / %))
+ (erase-buffer)
+ (insert (format fmt fn))
+ (goto-char (point-min))
+ (re-search-forward help-xref-symbol-regexp)
+ (help-xref-button 9 'help-function)
+ (should-not (button-at (1- beg)))
+ (should-not (button-at (+ beg (length (symbol-name fn)))))
+ (should (eq (button-type (button-at beg)) 'help-function))))))
+
+(ert-deftest help-mode-tests-insert-xref-button ()
+ (with-temp-buffer
+ (help-insert-xref-button "[back]" 'help-back)
+ (goto-char (point-min))
+ (should (eq (button-type (button-at (point))) 'help-back))
+ (help-insert-xref-button "[forward]" 'help-forward)
+ ;; The back button should stay unchanged.
+ (should (eq (button-type (button-at (point))) 'help-back))))
+
+(ert-deftest help-mode-tests-xref-on-pp ()
+ (with-temp-buffer
+ (insert (pp '(cons fill-column)))
+ (help-xref-on-pp (point-min) (point-max))
+ (goto-char (point-min))
+ (search-forward "co")
+ (should (eq (button-type (button-at (point))) 'help-function))
+ (search-forward "-")
+ (should (eq (button-type (button-at (point))) 'help-variable))))
+
+(ert-deftest help-mode-tests-xref-go-back ()
+ (let ((help-xref-stack
+ `((2 ,(lambda () (erase-buffer) (insert "bar"))))))
+ (with-temp-buffer
+ (insert "foo")
+ (help-xref-go-back (current-buffer))
+ (should (= (point) 2))
+ (should (equal (buffer-string) "bar")))))
+
+(ert-deftest help-mode-tests-xref-go-forward ()
+ (let ((help-xref-forward-stack
+ `((2 ,(lambda () (erase-buffer) (insert "bar"))))))
+ (with-temp-buffer
+ (insert "foo")
+ (help-xref-go-forward (current-buffer))
+ (should (= (point) 2))
+ (should (equal (buffer-string) "bar")))))
+
+(ert-deftest help-mode-tests-go-back ()
+ (let ((help-xref-stack
+ `((2 ,(lambda () (erase-buffer) (insert "bar"))))))
+ (with-temp-buffer
+ (insert "foo")
+ (help-go-back)
+ (should (= (point) 2))
+ (should (equal (buffer-string) "bar")))))
+
+(ert-deftest help-mode-tests-go-back-no-stack ()
+ (let ((help-xref-stack '()))
+ (should-error (help-go-back))))
+
+(ert-deftest help-mode-tests-go-forward ()
+ (let ((help-xref-forward-stack
+ `((2 ,(lambda () (erase-buffer) (insert "bar"))))))
+ (with-temp-buffer
+ (insert "foo")
+ (help-go-forward)
+ (should (= (point) 2))
+ (should (equal (buffer-string) "bar")))))
+
+(ert-deftest help-mode-tests-go-forward-no-stack ()
+ (let ((help-xref-forward-stack '()))
+ (should-error (help-go-forward))))
+
+(ert-deftest help-mode-tests-do-xref ()
+ (with-temp-buffer
+ (help-mode)
+ (help-do-xref 0 #'describe-symbol '(car))
+ (should (looking-at-p "car is a"))
+ (should (string-match-p "[back]" (buffer-string)))))
+
+(ert-deftest help-mode-tests-follow-symbol ()
+ (with-temp-buffer
+ (insert "car")
+ (help-mode)
+ (help-follow-symbol 0)
+ (should (looking-at-p "car is a"))
+ (should (string-match-p "[back]" (buffer-string)))))
+
+(ert-deftest help-mode-tests-follow-symbol-no-symbol ()
+ (with-temp-buffer
+ (insert "fXYEWnRHI0B9w6VJqQIw")
+ (help-mode)
+ (should-error (help-follow-symbol 0))))
+
+(provide 'help-mode-tests)
+;;; help-mode-tests.el ends here
diff --git a/test/lisp/help-tests.el b/test/lisp/help-tests.el
new file mode 100644
index 00000000000..0fcaacb6443
--- /dev/null
+++ b/test/lisp/help-tests.el
@@ -0,0 +1,486 @@
+;;; help-tests.el --- Tests for help.el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2019-2022 Free Software Foundation, Inc.
+
+;; Author: Juanma Barranquero <lekktu@gmail.com>
+;; Eli Zaretskii <eliz@gnu.org>
+;; Stefan Kangas <stefankangas@gmail.com>
+;; Keywords: help, internal
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(eval-when-compile (require 'cl-lib))
+(require 'text-property-search) ; for `text-property-search-forward'
+
+(ert-deftest help-split-fundoc-SECTION ()
+ "Test new optional arg SECTION."
+ (let* ((doc "Doc first line.\nDoc second line.")
+ (usg "\n\n(fn ARG1 &optional ARG2)")
+ (full (concat doc usg))
+ (usage "(t ARG1 &optional ARG2)"))
+ ;; Docstring has both usage and doc
+ (should (equal (help-split-fundoc full t nil) `(,usage . ,doc)))
+ (should (equal (help-split-fundoc full t t) `(,usage . ,doc)))
+ (should (equal (help-split-fundoc full t 'usage) usage))
+ (should (equal (help-split-fundoc full t 'doc) doc))
+ ;; Docstring has no usage, only doc
+ (should (equal (help-split-fundoc doc t nil) nil))
+ (should (equal (help-split-fundoc doc t t) `(nil . ,doc)))
+ (should (equal (help-split-fundoc doc t 'usage) nil))
+ (should (equal (help-split-fundoc doc t 'doc) doc))
+ ;; Docstring is only usage, no doc
+ (should (equal (help-split-fundoc usg t nil) `(,usage . nil)))
+ (should (equal (help-split-fundoc usg t t) `(,usage . nil)))
+ (should (equal (help-split-fundoc usg t 'usage) usage))
+ (should (equal (help-split-fundoc usg t 'doc) nil))
+ ;; Docstring is null
+ (should (equal (help-split-fundoc nil t nil) nil))
+ (should (equal (help-split-fundoc nil t t) '(nil)))
+ (should (equal (help-split-fundoc nil t 'usage) nil))
+ (should (equal (help-split-fundoc nil t 'doc) nil))))
+
+(ert-deftest help--key-description-fontified ()
+ (should (equal (help--key-description-fontified
+ (where-is-internal #'next-line nil t))
+ "C-n"))
+ (should-not (help--key-description-fontified nil)))
+
+
+;;; substitute-command-keys
+
+(defmacro with-substitute-command-keys-test (&rest body)
+ `(cl-flet* ((test
+ (lambda (orig result)
+ (should (equal (substitute-command-keys orig)
+ result))))
+ (test-re
+ (lambda (orig regexp)
+ (should (string-match (concat "\\`" regexp "\\'")
+ (substitute-command-keys orig))))))
+ ,@body))
+
+(ert-deftest help-tests-substitute-command-keys/no-change ()
+ (with-substitute-command-keys-test
+ (test "foo" "foo")
+ (test "\\invalid-escape" "\\invalid-escape")))
+
+(ert-deftest help-tests-substitute-command-keys/commands ()
+ (with-substitute-command-keys-test
+ (test "foo \\[goto-char]" "foo M-g c")
+ (test "\\[next-line]" "C-n")
+ (test "\\[next-line]\n\\[next-line]" "C-n\nC-n")
+ (test "\\[next-line]\\[previous-line]" "C-nC-p")
+ (test "\\[next-line]\\=\\[previous-line]" "C-n\\[previous-line]")
+ ;; Allow any style of quotes, since the terminal might not support
+ ;; UTF-8. Same thing is done below.
+ (test-re "\\[next-line]`foo'" "C-n[`'‘]foo['’]")
+ (test "\\[emacs-version]" "M-x emacs-version")
+ (test "\\[emacs-version]\\[next-line]" "M-x emacs-versionC-n")
+ (test-re "\\[emacs-version]`foo'" "M-x emacs-version[`'‘]foo['’]")))
+
+(ert-deftest help-tests-substitute-command-keys/literal-key-sequence ()
+ "Literal replacement."
+ (with-substitute-command-keys-test
+ (test "\\`C-m'" "C-m")
+ (test "\\`C-m'\\`C-j'" "C-mC-j")
+ (test "foo\\`C-m'bar\\`C-j'baz" "fooC-mbarC-jbaz")
+ (test "\\`M-x next-line'" "M-x next-line")
+ (test "\\`mouse-1'" "mouse-1")))
+
+(ert-deftest help-tests-substitute-command-keys/literal-key-sequence-ignore-invalid ()
+ "Ignore any invalid literal key sequence."
+ (with-substitute-command-keys-test
+ (test-re "ab\\`'cd" "ab\\\\[`'‘]['’]cd")
+ (test-re "\\`c-c'" "\\\\[`'‘]c-c['’]")
+ (test-re "\\`<foo bar baz>'" "\\\\[`'‘]<foo bar baz>['’]")))
+
+(ert-deftest help-tests-substitute-key-bindings/help-key-binding-face ()
+ (let ((A (substitute-command-keys "\\[next-line]"))
+ (B (substitute-command-keys "\\`f'")))
+ (should (eq (get-text-property 0 'face A) 'help-key-binding))
+ (should (eq (get-text-property 0 'face B) 'help-key-binding))))
+
+(ert-deftest help-tests-substitute-key-bindings/help-key-binding-no-face ()
+ (let ((A (substitute-command-keys "\\[next-line]" t))
+ (B (substitute-command-keys "\\`f'" t)))
+ (should (eq (get-text-property 0 'face A) nil))
+ (should (eq (get-text-property 0 'face B) nil))
+ (should (equal A "C-n"))
+ (should (equal B "f"))))
+
+(defvar-keymap help-tests--test-keymap
+ :doc "Just some keymap for testing."
+ "C-g" #'abort-minibuffers
+ "TAB" #'minibuffer-complete
+ "C-j" #'minibuffer-complete-and-exit
+ "RET" #'minibuffer-complete-and-exit
+ "SPC" #'minibuffer-complete-word
+ "?" #'minibuffer-completion-help
+ "C-<tab>" #'file-cache-minibuffer-complete
+ "<XF86Back>" #'previous-history-element
+ "<XF86Forward>" #'next-history-element
+ "<backtab>" #'minibuffer-complete
+ "<down>" #'next-line-or-history-element
+ "<next>" #'next-history-element
+ "<prior>" #'switch-to-completions
+ "<up>" #'previous-line-or-history-element
+ "M-v" #'switch-to-completions
+ "M-<" #'minibuffer-beginning-of-buffer
+ "M-n" #'next-history-element
+ "M-p" #'previous-history-element
+ "M-r" #'previous-matching-history-element
+ "M-s" #'next-matching-history-element
+ "M-g M-c" #'switch-to-completions)
+
+(ert-deftest help-tests-substitute-command-keys/keymaps ()
+ (with-substitute-command-keys-test
+ (test-re "\\{help-tests--test-keymap}"
+ "
+Key Binding
+-+
+C-g abort-minibuffers
+TAB minibuffer-complete
+C-j minibuffer-complete-and-exit
+RET minibuffer-complete-and-exit
+SPC minibuffer-complete-word
+\\? minibuffer-completion-help
+C-<tab> file-cache-minibuffer-complete
+<XF86Back> previous-history-element
+<XF86Forward> next-history-element
+<backtab> minibuffer-complete
+<down> next-line-or-history-element
+<next> next-history-element
+<prior> switch-to-completions
+<up> previous-line-or-history-element
+
+M-< minibuffer-beginning-of-buffer
+M-n next-history-element
+M-p previous-history-element
+M-r previous-matching-history-element
+M-s next-matching-history-element
+M-v switch-to-completions
+
+M-g M-c switch-to-completions
+")))
+
+(ert-deftest help-tests-substitute-command-keys/keymap-change ()
+ (with-substitute-command-keys-test
+ ;; Global binding should be found even if specifying a specific map
+ (test "\\<minibuffer-local-must-match-map>\\[abort-recursive-edit]" "C-]")
+ (test "\\<emacs-lisp-mode-map>\\[eval-defun]" "C-M-x")
+ ;; Specific map overrides advertised-binding
+ (test "\\<undo-repeat-map>\\[undo]" "u")
+ (test "\\[undo]" "C-x u")))
+
+(defvar-keymap help-tests-remap-map
+ :full t
+ "x" 'foo
+ "y" 'bar
+ "<remap> <foo>" 'bar)
+
+(ert-deftest help-tests-substitute-command-keys/remap ()
+ (should (equal (substitute-command-keys "\\<help-tests-remap-map>\\[foo]") "y"))
+ (should (equal (substitute-command-keys "\\<help-tests-remap-map>\\[bar]") "y")))
+
+(ert-deftest help-tests-substitute-command-keys/undefined-map ()
+ (with-substitute-command-keys-test
+ (test-re "\\{foobar-map}"
+ "\nUses keymap [`'‘]foobar-map['’], which is not currently defined.\n")))
+
+(ert-deftest help-tests-substitute-command-keys/quotes ()
+ (with-substitute-command-keys-test
+ (let ((text-quoting-style 'curve))
+ (test "quotes ‘like this’" "quotes ‘like this’")
+ (test "`x'" "‘x’")
+ (test "`" "‘")
+ (test "'" "’")
+ (test "\\`" "\\‘"))
+ (let ((text-quoting-style 'straight))
+ (test "quotes `like this'" "quotes 'like this'")
+ (test "`x'" "'x'")
+ (test "`" "'")
+ (test "'" "'")
+ (test "\\`" "\\'"))
+ (let ((text-quoting-style 'grave))
+ (test "quotes `like this'" "quotes `like this'")
+ (test "`x'" "`x'")
+ (test "`" "`")
+ (test "'" "'")
+ (test "\\`" "\\`"))))
+
+(ert-deftest help-tests-substitute-quotes ()
+ (let ((text-quoting-style 'curve))
+ (should (string= (substitute-quotes "quotes ‘like this’") "quotes ‘like this’"))
+ (should (string= (substitute-quotes "`x'") "‘x’"))
+ (should (string= (substitute-quotes "`") "‘"))
+ (should (string= (substitute-quotes "'") "’"))
+ (should (string= (substitute-quotes "\\`") "\\‘")))
+ (let ((text-quoting-style 'straight))
+ (should (string= (substitute-quotes "quotes `like this'") "quotes 'like this'"))
+ (should (string= (substitute-quotes "`x'") "'x'"))
+ (should (string= (substitute-quotes "`") "'"))
+ (should (string= (substitute-quotes "'") "'"))
+ (should (string= (substitute-quotes "\\`") "\\'")))
+ (let ((text-quoting-style 'grave))
+ (should (string= (substitute-quotes "quotes `like this'") "quotes `like this'"))
+ (should (string= (substitute-quotes "`x'") "`x'"))
+ (should (string= (substitute-quotes "`") "`"))
+ (should (string= (substitute-quotes "'") "'"))
+ (should (string= (substitute-quotes "\\`") "\\`"))))
+
+(ert-deftest help-tests-substitute-command-keys/literals ()
+ (with-substitute-command-keys-test
+ (test "foo \\=\\[goto-char]" "foo \\[goto-char]")
+ (test "foo \\=\\=" "foo \\=")
+ (test "\\=\\=" "\\=")
+ (test "\\=\\[" "\\[")
+ (let ((text-quoting-style 'curve))
+ (test "\\=`x\\='" "`x'"))
+ (let ((text-quoting-style 'straight))
+ (test "\\=`x\\='" "`x'"))
+ (let ((text-quoting-style 'grave))
+ (test "\\=`x\\='" "`x'"))))
+
+(ert-deftest help-tests-substitute-command-keys/no-change-2 ()
+ (with-substitute-command-keys-test
+ (test "\\[foobar" "\\[foobar")
+ (test "\\=" "\\=")))
+
+(ert-deftest help-tests-substitute-command-keys/multibyte ()
+ ;; Cannot use string= here, as that compares unibyte and multibyte
+ ;; strings not equal.
+ (should (compare-strings
+ (substitute-command-keys "\200 \\[goto-char]") nil nil
+ "\200 M-g c" nil nil)))
+
+(ert-deftest help-tests-substitute-command-keys/apropos ()
+ (save-window-excursion
+ (apropos "foo")
+ (switch-to-buffer "*Apropos*")
+ (goto-char (point-min))
+ (should (looking-at "Type RET on"))))
+
+(defvar-keymap help-tests-major-mode-map
+ :full t
+ "x" 'foo-original
+ "1" 'foo-range
+ "2" 'foo-range
+ "3" 'foo-range
+ "4" 'foo-range
+ "C-e" 'foo-something
+ "<f1>" 'foo-function-key1
+ "(" 'short-range
+ ")" 'short-range
+ "a" 'foo-other-range
+ "b" 'foo-other-range
+ "c" 'foo-other-range)
+
+(define-derived-mode help-tests-major-mode nil
+ "Major mode for testing shadowing.")
+
+(defvar-keymap help-tests-minor-mode-map
+ :full t
+ "x" 'foo-shadow
+ "C-e" 'foo-shadow)
+
+(define-minor-mode help-tests-minor-mode
+ "Minor mode for testing shadowing.")
+
+(ert-deftest help-tests-substitute-command-keys/add-key-face ()
+ (should (equal (substitute-command-keys "\\[next-line]")
+ (propertize "C-n"
+ 'face 'help-key-binding
+ 'font-lock-face 'help-key-binding))))
+
+(ert-deftest help-tests-substitute-command-keys/add-key-face-listing ()
+ (with-temp-buffer
+ (insert (substitute-command-keys "\\{help-tests-minor-mode-map}"))
+ (goto-char (point-min))
+ (text-property-search-forward 'face 'help-key-binding)
+ (should (looking-at "C-e"))
+ ;; Don't fontify trailing whitespace.
+ (should-not (get-text-property (+ (point) 3) 'face))
+ (text-property-search-forward 'face 'help-key-binding)
+ (should (looking-at "x"))
+ (should-not (get-text-property (+ (point) 1) 'face))))
+
+(ert-deftest help-tests-substitute-command-keys/test-mode ()
+ (with-substitute-command-keys-test
+ (with-temp-buffer
+ (help-tests-major-mode)
+ (test-re "\\{help-tests-major-mode-map}"
+ "
+Key Binding
+-+
+1 .. 4 foo-range
+a .. c foo-other-range
+
+C-e foo-something
+( .. ) short-range
+x foo-original
+<F1> foo-function-key1
+"))))
+
+(ert-deftest help-tests-substitute-command-keys/shadow ()
+ (with-substitute-command-keys-test
+ (with-temp-buffer
+ (help-tests-major-mode)
+ (help-tests-minor-mode)
+ (test-re "\\{help-tests-major-mode-map}"
+ "
+Key Binding
+-+
+1 .. 4 foo-range
+a .. c foo-other-range
+
+C-e foo-something
+ (this binding is currently shadowed)
+( .. ) short-range
+x foo-original
+ (this binding is currently shadowed)
+<F1> foo-function-key1
+"))))
+
+(ert-deftest help-tests-substitute-command-keys/command-remap ()
+ (with-substitute-command-keys-test
+ (let ((help-tests-major-mode-map (make-keymap))) ; Protect from changes.
+ (with-temp-buffer
+ (help-tests-major-mode)
+ (define-key help-tests-major-mode-map [remap foo] 'bar)
+ (test-re "\\{help-tests-major-mode-map}"
+ "
+Key Binding
+-+
+<remap> <foo> bar
+")))))
+
+(ert-deftest help-tests-describe-map-tree/no-menu-t ()
+ (with-temp-buffer
+ (let ((standard-output (current-buffer))
+ (map '(keymap . ((1 . foo)
+ (menu-bar keymap
+ (foo menu-item "Foo" foo
+ :enable mark-active
+ :help "Help text"))))))
+ (describe-map-tree map nil nil nil nil t nil nil nil)
+ (should (string-match "
+Key Binding
+-+
+C-a foo\n"
+ (buffer-string))))))
+
+(ert-deftest help-tests-describe-map-tree/no-menu-nil ()
+ (with-temp-buffer
+ (let ((standard-output (current-buffer))
+ (map '(keymap . ((1 . foo)
+ (menu-bar keymap
+ (foo menu-item "Foo" foo
+ :enable mark-active
+ :help "Help text"))))))
+ (describe-map-tree map nil nil nil nil nil nil nil nil)
+ (should (string-match "
+Key Binding
+-+
+C-a foo
+
+<menu-bar> <foo> foo\n"
+ (buffer-string))))))
+
+(ert-deftest help-tests-describe-map-tree/mention-shadow-t ()
+ (with-temp-buffer
+ (let ((standard-output (current-buffer))
+ (map '(keymap . ((1 . foo)
+ (2 . bar))))
+ (shadow-maps '((keymap . ((1 . baz))))))
+ (describe-map-tree map t shadow-maps nil nil t nil nil t)
+ (should (string-match "
+Key Binding
+-+
+C-a foo
+ (this binding is currently shadowed)
+C-b bar\n"
+ (buffer-string))))))
+
+(ert-deftest help-tests-describe-map-tree/mention-shadow-nil ()
+ (with-temp-buffer
+ (let ((standard-output (current-buffer))
+ (map '(keymap . ((1 . foo)
+ (2 . bar))))
+ (shadow-maps '((keymap . ((1 . baz))))))
+ (describe-map-tree map t shadow-maps nil nil t nil nil nil)
+ (should (string-match "
+Key Binding
+-+
+C-b bar\n"
+ (buffer-string))))))
+
+(ert-deftest help-tests-describe-map-tree/partial-t ()
+ (with-temp-buffer
+ (let ((standard-output (current-buffer))
+ (map '(keymap . ((1 . foo)
+ (2 . undefined)))))
+ (describe-map-tree map t nil nil nil nil nil nil nil)
+ (should (string-match "
+Key Binding
+-+
+C-a foo\n"
+ (buffer-string))))))
+
+(ert-deftest help-tests-describe-map-tree/partial-nil ()
+ (with-temp-buffer
+ (let ((standard-output (current-buffer))
+ (map '(keymap . ((1 . foo)
+ (2 . undefined)))))
+ (describe-map-tree map nil nil nil nil nil nil nil nil)
+ (should (string-match "
+Key Binding
+-+
+C-a foo
+C-b undefined\n"
+ (buffer-string))))))
+
+(defvar help-tests--was-in-buffer nil)
+
+(ert-deftest help-substitute-command-keys/menu-filter-in-correct-buffer ()
+ "Evaluate menu-filter in the original buffer. See Bug#39149."
+ (unwind-protect
+ (progn
+ (define-key global-map (kbd "C-c C-l r")
+ `(menu-item "2" identity
+ :filter ,(lambda (cmd)
+ (setq help-tests--was-in-buffer
+ (current-buffer))
+ cmd)))
+ (with-temp-buffer
+ (substitute-command-keys "\\[identity]")
+ (should (eq help-tests--was-in-buffer
+ (current-buffer)))))
+ (setq help-tests--was-in-buffer nil)
+ (define-key global-map (kbd "C-c C-l r") nil)
+ (define-key global-map (kbd "C-c C-l") nil)))
+
+(ert-deftest help-substitute-command-keys/preserves-text-properties ()
+ "Check that we preserve text properties (Bug#17052)."
+ (should (equal (substitute-command-keys
+ (propertize "foo \\[save-buffer]" 'face 'bold))
+ (propertize "foo C-x C-s" 'face 'bold))))
+
+(provide 'help-tests)
+
+;;; help-tests.el ends here
diff --git a/test/lisp/hfy-cmap-resources/rgb.txt b/test/lisp/hfy-cmap-resources/rgb.txt
new file mode 100644
index 00000000000..f8e369fae2a
--- /dev/null
+++ b/test/lisp/hfy-cmap-resources/rgb.txt
@@ -0,0 +1,4 @@
+# test comment
+255 250 250 snow
+248 248 255 ghost white
+248 248 255 GhostWhite
diff --git a/test/lisp/hfy-cmap-tests.el b/test/lisp/hfy-cmap-tests.el
new file mode 100644
index 00000000000..fa9c51df4c6
--- /dev/null
+++ b/test/lisp/hfy-cmap-tests.el
@@ -0,0 +1,55 @@
+;;; hfy-cmap-tests.el --- tests for hfy-cmap.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'ert-x)
+(require 'hfy-cmap)
+
+(defconst hfy-cmap-tests--data
+ (concat "255 250 250 snow\n"
+ "248 248 255 ghost white\n"
+ "248 248 255 GhostWhite\n"))
+
+(defconst hfy-cmap-tests--parsed
+ '(("GhostWhite" 248 248 255)
+ ("ghost white" 248 248 255)
+ ("snow" 255 250 250)))
+
+(ert-deftest test-hfy-cmap--parse-buffer ()
+ (with-temp-buffer
+ (insert hfy-cmap-tests--data)
+ (should (equal (hfy-cmap--parse-buffer (current-buffer))
+ hfy-cmap-tests--parsed))))
+
+(ert-deftest test-htmlfontify-load-rgb-file ()
+ :tags '(:expensive-test)
+ (let (hfy-rgb-txt-color-map)
+ (htmlfontify-load-rgb-file (ert-resource-file "rgb.txt"))
+ (should (equal hfy-rgb-txt-color-map
+ hfy-cmap-tests--parsed))))
+
+(ert-deftest test-htmlfontify-load-rgb-file/non-existent-file ()
+ (let (hfy-rgb-txt-color-map)
+ (htmlfontify-load-rgb-file "/non/existent/file")
+ (should-not hfy-rgb-txt-color-map)))
+
+(provide 'hfy-cmap-tests)
+;;; hfy-cmap-tests.el ends here
diff --git a/test/lisp/hi-lock-tests.el b/test/lisp/hi-lock-tests.el
index dfe583453ef..760b319a926 100644
--- a/test/lisp/hi-lock-tests.el
+++ b/test/lisp/hi-lock-tests.el
@@ -1,22 +1,24 @@
;;; hi-lock-tests.el --- Tests for hi-lock.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2017 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2022 Free Software Foundation, Inc.
;; Author: Tino Calancha <tino.calancha@gmail.com>
;; Keywords:
-;; This program is free software; you can redistribute it and/or modify
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
-;; This program is distributed in the hope that it will be useful,
+;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
-;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Code:
@@ -28,9 +30,9 @@
(let ((faces hi-lock-face-defaults))
(with-temp-buffer
(insert "a A b B\n")
- (cl-letf (((symbol-function 'completing-read)
- (lambda (prompt coll x y z hist defaults)
- (car defaults))))
+ (cl-letf (((symbol-function 'read-face-name)
+ (lambda (_prompt &optional defaults)
+ (intern (car defaults)))))
(dotimes (_ 2)
(let ((face (hi-lock-read-face-name)))
(hi-lock-set-pattern "a" face))))
@@ -40,13 +42,172 @@
(let ((faces hi-lock-face-defaults))
(with-temp-buffer
(insert "foo bar")
- (cl-letf (((symbol-function 'completing-read)
- (lambda (prompt coll x y z hist defaults)
- (car defaults))))
+ (cl-letf (((symbol-function 'read-face-name)
+ (lambda (_prompt &optional defaults)
+ (intern (car defaults)))))
(hi-lock-set-pattern "9999" (hi-lock-read-face-name)) ; No match
(hi-lock-set-pattern "foo" (hi-lock-read-face-name)))
;; Only one match, then we have used just 1 face
(should (equal hi-lock--unused-faces (cdr faces))))))
+(ert-deftest hi-lock-case-fold ()
+ "Test for case-sensitivity."
+ (let ((hi-lock-auto-select-face t))
+ (with-temp-buffer
+ (insert "a A b B\n")
+
+ (dotimes (_ 2) (highlight-regexp "[a]"))
+ (should (= (length (overlays-in (point-min) (point-max))) 2))
+ (unhighlight-regexp "[a]")
+ (should (= (length (overlays-in (point-min) (point-max))) 0))
+
+ (dotimes (_ 2) (highlight-regexp "[a]" nil nil "a"))
+ (should (= (length (overlays-in (point-min) (point-max))) 2))
+ (unhighlight-regexp "a")
+ (should (= (length (overlays-in (point-min) (point-max))) 0))
+
+ (dotimes (_ 2) (highlight-regexp "[A]" ))
+ (should (= (length (overlays-in (point-min) (point-max))) 1))
+ (unhighlight-regexp "[A]")
+ (should (= (length (overlays-in (point-min) (point-max))) 0))
+
+ (dotimes (_ 2) (highlight-regexp "[A]" nil nil "A"))
+ (should (= (length (overlays-in (point-min) (point-max))) 1))
+ (unhighlight-regexp "A")
+ (should (= (length (overlays-in (point-min) (point-max))) 0))
+
+ (let ((case-fold-search nil)) (dotimes (_ 2) (highlight-regexp "[a]")))
+ (should (= (length (overlays-in (point-min) (point-max))) 1))
+ (unhighlight-regexp "[a]")
+ (should (= (length (overlays-in (point-min) (point-max))) 0))
+
+ (dotimes (_ 2) (highlight-phrase "a a"))
+ (should (= (length (overlays-in (point-min) (point-max))) 1))
+ (unhighlight-regexp "a a")
+ (should (= (length (overlays-in (point-min) (point-max))) 0))
+
+ (let ((search-spaces-regexp search-whitespace-regexp)) (highlight-regexp "a a"))
+ (should (= (length (overlays-in (point-min) (point-max))) 1))
+ (cl-letf (((symbol-function 'completing-read)
+ (lambda (_prompt _coll
+ &optional _x _y _z _hist defaults _inherit)
+ (car defaults))))
+ (call-interactively 'unhighlight-regexp))
+ (should (= (length (overlays-in (point-min) (point-max))) 0))
+
+ (emacs-lisp-mode)
+ (setq font-lock-mode t)
+
+ (dotimes (_ 2) (highlight-regexp "[a]"))
+ (font-lock-ensure)
+ (should (memq 'hi-yellow (get-text-property 1 'face)))
+ (should (memq 'hi-yellow (get-text-property 3 'face)))
+ (let ((font-lock-fontified t)) (unhighlight-regexp "[a]"))
+ (should (null (get-text-property 3 'face)))
+
+ (dotimes (_ 2) (highlight-regexp "[a]" nil nil "a"))
+ (font-lock-ensure)
+ (should (memq 'hi-yellow (get-text-property 1 'face)))
+ (should (memq 'hi-yellow (get-text-property 3 'face)))
+ (let ((font-lock-fontified t)) (unhighlight-regexp "a"))
+ (should (null (get-text-property 3 'face)))
+
+ (dotimes (_ 2) (highlight-regexp "[A]" ))
+ (font-lock-ensure)
+ (should (null (get-text-property 1 'face)))
+ (should (memq 'hi-yellow (get-text-property 3 'face)))
+ (let ((font-lock-fontified t)) (unhighlight-regexp "[A]"))
+ (should (null (get-text-property 3 'face)))
+
+ (dotimes (_ 2) (highlight-regexp "[A]" nil nil "A"))
+ (font-lock-ensure)
+ (should (null (get-text-property 1 'face)))
+ (should (memq 'hi-yellow (get-text-property 3 'face)))
+ (let ((font-lock-fontified t)) (unhighlight-regexp "A"))
+ (should (null (get-text-property 3 'face)))
+
+ (let ((case-fold-search nil)) (dotimes (_ 2) (highlight-regexp "[a]")))
+ (font-lock-ensure)
+ (should (memq 'hi-yellow (get-text-property 1 'face)))
+ (should (null (get-text-property 3 'face)))
+ (let ((font-lock-fontified t)) (unhighlight-regexp "[a]"))
+ (should (null (get-text-property 1 'face)))
+
+ (dotimes (_ 2) (highlight-phrase "a a"))
+ (font-lock-ensure)
+ (should (memq 'hi-yellow (get-text-property 1 'face)))
+ (let ((font-lock-fontified t)) (unhighlight-regexp "a a"))
+ (should (null (get-text-property 1 'face)))
+
+ (let ((search-spaces-regexp search-whitespace-regexp)) (highlight-regexp "a a"))
+ (font-lock-ensure)
+ (should (memq 'hi-yellow (get-text-property 1 'face)))
+ (cl-letf (((symbol-function 'completing-read)
+ (lambda (_prompt _coll
+ &optional _x _y _z _hist defaults _inherit)
+ (car defaults)))
+ (font-lock-fontified t))
+ (call-interactively 'unhighlight-regexp))
+ (should (null (get-text-property 1 'face))))))
+
+(ert-deftest hi-lock-unhighlight ()
+ "Test for unhighlighting and `hi-lock--regexps-at-point'."
+ (let ((hi-lock-auto-select-face t))
+ (with-temp-buffer
+ (insert "aAbB\n")
+
+ (cl-letf (((symbol-function 'completing-read)
+ (lambda (_prompt _coll
+ &optional _x _y _z _hist defaults _inherit)
+ (car defaults))))
+
+ (highlight-regexp "a")
+ (highlight-regexp "b")
+ (should (= (length (overlays-in (point-min) (point-max))) 4))
+ ;; `hi-lock--regexps-at-point' should take regexp "a" at point 1,
+ ;; not the last regexp "b"
+ (goto-char 1)
+ (call-interactively 'unhighlight-regexp)
+ (should (= (length (overlays-in 1 3)) 0))
+ (should (= (length (overlays-in 3 5)) 2))
+ ;; Next call should unhighlight remaining regepxs
+ (call-interactively 'unhighlight-regexp)
+ (should (= (length (overlays-in 3 5)) 0))
+
+ ;; Test unhighlight all
+ (highlight-regexp "a")
+ (highlight-regexp "b")
+ (should (= (length (overlays-in (point-min) (point-max))) 4))
+ (unhighlight-regexp t)
+ (should (= (length (overlays-in (point-min) (point-max))) 0))
+
+ (emacs-lisp-mode)
+ (setq font-lock-mode t)
+
+ (highlight-regexp "a")
+ (highlight-regexp "b")
+ (font-lock-ensure)
+ (should (memq 'hi-yellow (get-text-property 1 'face)))
+ (should (memq 'hi-yellow (get-text-property 3 'face)))
+ ;; `hi-lock--regexps-at-point' should take regexp "a" at point 1,
+ ;; not the last regexp "b"
+ (goto-char 1)
+ (let ((font-lock-fontified t)) (call-interactively 'unhighlight-regexp))
+ (should (null (get-text-property 1 'face)))
+ (should (memq 'hi-yellow (get-text-property 3 'face)))
+ ;; Next call should unhighlight remaining regepxs
+ (let ((font-lock-fontified t)) (call-interactively 'unhighlight-regexp))
+ (should (null (get-text-property 3 'face)))
+
+ ;; Test unhighlight all
+ (highlight-regexp "a")
+ (highlight-regexp "b")
+ (font-lock-ensure)
+ (should (memq 'hi-yellow (get-text-property 1 'face)))
+ (should (memq 'hi-yellow (get-text-property 3 'face)))
+ (let ((font-lock-fontified t)) (unhighlight-regexp t))
+ (should (null (get-text-property 1 'face)))
+ (should (null (get-text-property 3 'face)))))))
+
(provide 'hi-lock-tests)
;;; hi-lock-tests.el ends here
diff --git a/test/lisp/hl-line-tests.el b/test/lisp/hl-line-tests.el
new file mode 100644
index 00000000000..888351addac
--- /dev/null
+++ b/test/lisp/hl-line-tests.el
@@ -0,0 +1,114 @@
+;;; hl-line-tests.el --- Test suite for hl-line. -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+(require 'ert)
+(require 'hl-line)
+
+(defsubst hl-line-tests-verify (_label on-p)
+ (if on-p
+ (cl-some (apply-partially #'eq hl-line-overlay)
+ (overlays-at (point)))
+ (not (cl-some (apply-partially #'eq hl-line-overlay)
+ (overlays-at (point))))))
+
+(ert-deftest hl-line-tests-sticky-across-frames ()
+ (skip-unless (display-graphic-p))
+ (customize-set-variable 'global-hl-line-sticky-flag t)
+ (call-interactively #'global-hl-line-mode)
+ (let ((first-frame (selected-frame))
+ (first-buffer "foo")
+ (second-buffer "bar")
+ second-frame)
+ (unwind-protect
+ (progn
+ (switch-to-buffer first-buffer)
+ (save-excursion
+ (insert (buffer-name)))
+ (run-hooks 'post-command-hook)
+ (should (hl-line-tests-verify 111 t))
+ (select-frame (setq second-frame (make-frame)))
+ (switch-to-buffer second-buffer)
+ (save-excursion
+ (insert (buffer-name)))
+ (run-hooks 'post-command-hook)
+ (should (hl-line-tests-verify 762 t))
+ (with-current-buffer first-buffer
+ (should (hl-line-tests-verify 534 t)))
+ (call-interactively #'global-hl-line-mode)
+ (should (hl-line-tests-verify 125 nil))
+ (with-current-buffer first-buffer
+ (should (hl-line-tests-verify 892 nil)))
+
+ ;; now do unsticky
+ (customize-set-variable 'hl-line-sticky-flag nil)
+ (call-interactively #'global-hl-line-mode)
+ (run-hooks 'post-command-hook)
+ (should (hl-line-tests-verify 467 t))
+ (with-current-buffer first-buffer
+ (should (hl-line-tests-verify 765 nil)))
+ (select-frame first-frame)
+ (should (equal (buffer-name) first-buffer))
+ (run-hooks 'post-command-hook)
+ (should (hl-line-tests-verify 423 t))
+ (with-current-buffer second-buffer
+ (should (hl-line-tests-verify 897 nil))))
+ (let (kill-buffer-query-functions)
+ (ignore-errors (kill-buffer first-buffer))
+ (ignore-errors (kill-buffer second-buffer))
+ (ignore-errors (delete-frame second-frame))))))
+
+(ert-deftest hl-line-tests-sticky ()
+ (customize-set-variable 'hl-line-sticky-flag t)
+ (let ((first-buffer "foo")
+ (second-buffer "bar"))
+ (unwind-protect
+ (progn
+ (switch-to-buffer first-buffer)
+ (hl-line-mode 1)
+ (save-excursion
+ (insert (buffer-name)))
+ (run-hooks 'post-command-hook)
+ (should (hl-line-tests-verify 123 t))
+ (switch-to-buffer second-buffer)
+ (hl-line-mode 1)
+ (save-excursion
+ (insert (buffer-name)))
+ (run-hooks 'post-command-hook)
+ (should (hl-line-tests-verify 56 t))
+ (with-current-buffer first-buffer
+ (should (hl-line-tests-verify 67 t)))
+
+ ;; now do unsticky
+ (customize-set-variable 'hl-line-sticky-flag nil)
+ (should (hl-line-tests-verify 234 t))
+ (with-current-buffer first-buffer
+ (should (hl-line-tests-verify 231 nil)))
+ (switch-to-buffer first-buffer)
+ (run-hooks 'post-command-hook)
+ (should (hl-line-tests-verify 257 t))
+ (with-current-buffer second-buffer
+ (should (hl-line-tests-verify 999 nil)))))
+ (let (kill-buffer-query-functions)
+ (ignore-errors (kill-buffer first-buffer))
+ (ignore-errors (kill-buffer second-buffer)))))
+
+(provide 'hl-line-tests)
+
+;;; hl-line-tests.el ends here
diff --git a/test/lisp/htmlfontify-tests.el b/test/lisp/htmlfontify-tests.el
index 0ad775d74a0..5c1f053066b 100644
--- a/test/lisp/htmlfontify-tests.el
+++ b/test/lisp/htmlfontify-tests.el
@@ -1,6 +1,6 @@
;;; htmlfontify-tests.el --- Test suite. -*- lexical-binding: t -*-
-;; Copyright (C) 2015-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2022 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -21,26 +21,17 @@
(require 'ert)
(require 'htmlfontify)
-(ert-deftest htmlfontify-autoload ()
- "Tests to see whether reftex-auc has been autoloaded"
- (should
- (fboundp 'htmlfontify-load-rgb-file))
- (should
- (autoloadp
- (symbol-function
- 'htmlfontify-load-rgb-file))))
-
(ert-deftest htmlfontify-bug25468 ()
"Tests that htmlfontify can be loaded even if no shell is
available (Bug#25468)."
(should (equal (let ((process-environment
(cons "SHELL=/does/not/exist" process-environment)))
(call-process
- (expand-file-name (invocation-name) (invocation-directory))
+ (expand-file-name invocation-name invocation-directory)
nil nil nil
"--quick" "--batch"
(concat "--load=" (locate-library "htmlfontify"))))
0)))
(provide 'htmlfontify-tests)
-;; htmlfontify-tests.el ends here
+;;; htmlfontify-tests.el ends here
diff --git a/test/lisp/ibuffer-tests.el b/test/lisp/ibuffer-tests.el
index 35605ca28dc..d54718e297a 100644
--- a/test/lisp/ibuffer-tests.el
+++ b/test/lisp/ibuffer-tests.el
@@ -1,6 +1,6 @@
;;; ibuffer-tests.el --- Test suite. -*- lexical-binding: t -*-
-;; Copyright (C) 2015-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2022 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -82,7 +82,7 @@
(test1 '((mode . org-mode)
(or (size-gt . 10000)
(and (not (starred-name))
- (directory . "\<org\>")))))
+ (directory . "<org>")))))
(test2 '((or (mode . emacs-lisp-mode) (file-extension . "elc?")
(and (starred-name) (name . "elisp"))
(mode . lisp-interaction-mode))))
@@ -132,7 +132,7 @@
(ibuffer-switch-to-saved-filter-groups "saved-filters")
(should (assoc "Elisp" (cdar ibuffer-saved-filter-groups))))
(setq ibuffer-saved-filter-groups orig-filters)
- (ibuffer-awhen (get-buffer "*Ibuffer*")
+ (when-let ((it (get-buffer "*Ibuffer*")))
(and (buffer-live-p it) (kill-buffer it))))))
@@ -312,8 +312,8 @@
(funcall create-non-file-buffer "ibuf-test-3.b" :size 50
:mode #'text-mode
:include-content "...but a multitude of drops?\n"))
- (dirA (with-current-buffer bufA default-directory))
- (dirB (with-current-buffer bufB default-directory)))
+ (dirA (regexp-quote (with-current-buffer bufA default-directory)))
+ (dirB (regexp-quote (with-current-buffer bufB default-directory))))
(should (ibuffer-included-in-filters-p
bufA '((basename . "ibuf-test-3"))))
(should (ibuffer-included-in-filters-p
@@ -785,7 +785,7 @@
(funcall tag
(funcall description
'starred-name)
- ": " "nil"))
+ "" ""))
(funcall tag
(funcall description 'directory)
": " "\\<org\\>")))))
@@ -806,7 +806,7 @@
(funcall tag "AND"
(funcall tag
(funcall description 'starred-name)
- ": " "nil")
+ "" "")
(funcall tag
(funcall description 'name)
": " "elisp"))
@@ -826,4 +826,4 @@
(should (equal (ibuffer-unary-operand '(not . a)) 'a)))
(provide 'ibuffer-tests)
-;; ibuffer-tests.el ends here
+;;; ibuffer-tests.el ends here
diff --git a/test/lisp/ido-tests.el b/test/lisp/ido-tests.el
index a325f49c58e..56ef6cde358 100644
--- a/test/lisp/ido-tests.el
+++ b/test/lisp/ido-tests.el
@@ -1,6 +1,6 @@
;;; ido-tests.el --- unit tests for ido.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2017 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2022 Free Software Foundation, Inc.
;; Author: Philipp Stephani <phst@google.com>
@@ -25,6 +25,8 @@
;;; Code:
+(require 'ido)
+
(ert-deftest ido-tests--other-window-frame ()
"Verifies that Bug#26360 is fixed."
(should-not ido-mode)
@@ -44,4 +46,9 @@
(should (commandp #'ido-display-buffer-other-frame)))
(ido-mode 0)))
+(ert-deftest ido-directory-too-big-p ()
+ (should-not (ido-directory-too-big-p "/some/dir/"))
+ (let ((ido-big-directories (cons (rx "me/di") ido-big-directories)))
+ (should (ido-directory-too-big-p "/some/dir/"))))
+
;;; ido-tests.el ends here
diff --git a/test/lisp/image-file-tests.el b/test/lisp/image-file-tests.el
new file mode 100644
index 00000000000..59af6ba909a
--- /dev/null
+++ b/test/lisp/image-file-tests.el
@@ -0,0 +1,44 @@
+;;; image-file-tests.el --- Test suite for image-files -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2019-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'image-file)
+
+(defconst image-file-tests-data-directory
+ (expand-file-name "data/image" (getenv "EMACS_TEST_DIRECTORY"))
+ "Directory containing image test data.")
+
+(ert-deftest insert-image-file ()
+ (skip-unless (image-type-available-p 'png))
+ (with-temp-buffer
+ (set-buffer-multibyte t)
+ (insert-image-file (expand-file-name "blank-100x200.png"
+ image-file-tests-data-directory))
+ (should (image--get-image)))
+ (with-temp-buffer
+ (set-buffer-multibyte nil)
+ (insert-image-file (expand-file-name "blank-100x200.png"
+ image-file-tests-data-directory))
+ (should (image--get-image))))
+
+;;; image-file-tests.el ends here
diff --git a/test/lisp/image-tests.el b/test/lisp/image-tests.el
new file mode 100644
index 00000000000..bc8c3636c3c
--- /dev/null
+++ b/test/lisp/image-tests.el
@@ -0,0 +1,156 @@
+;;; image-tests.el --- tests for image.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2019-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'image)
+(eval-when-compile
+ (require 'cl-lib))
+
+(defconst image-tests--emacs-images-directory
+ (expand-file-name "images" data-directory)
+ "Directory containing Emacs images.")
+
+(defconst image-tests--files
+ `((gif . ,(expand-file-name "test/data/image/black.gif"
+ source-directory))
+ (jpeg . ,(expand-file-name "test/data/image/black.jpg"
+ source-directory))
+ (pbm . ,(expand-file-name "splash.pbm"
+ image-tests--emacs-images-directory))
+ (png . ,(expand-file-name "splash.png"
+ image-tests--emacs-images-directory))
+ (svg . ,(expand-file-name "splash.svg"
+ image-tests--emacs-images-directory))
+ (tiff . ,(expand-file-name
+ "nextstep/GNUstep/Emacs.base/Resources/emacs.tiff"
+ source-directory))
+ (webp . ,(expand-file-name "test/data/image/black.webp"
+ source-directory))
+ (xbm . ,(expand-file-name "gnus/gnus.xbm"
+ image-tests--emacs-images-directory))
+ (xpm . ,(expand-file-name "splash.xpm"
+ image-tests--emacs-images-directory))))
+
+(ert-deftest image--set-property ()
+ "Test `image--set-property' behavior."
+ (let ((image (list 'image)))
+ ;; Add properties.
+ (setf (image-property image :scale) 1)
+ (should (equal image '(image :scale 1)))
+ (setf (image-property image :width) 8)
+ (should (equal image '(image :scale 1 :width 8)))
+ (setf (image-property image :height) 16)
+ (should (equal image '(image :scale 1 :width 8 :height 16)))
+ ;; Delete properties.
+ (setf (image-property image :type) nil)
+ (should (equal image '(image :scale 1 :width 8 :height 16)))
+ (setf (image-property image :scale) nil)
+ (should (equal image '(image :width 8 :height 16)))
+ (setf (image-property image :height) nil)
+ (should (equal image '(image :width 8)))
+ (setf (image-property image :width) nil)
+ (should (equal image '(image)))))
+
+(ert-deftest image-find-image ()
+ (should (listp (find-image '((:type xpm :file "undo.xpm")))))
+ (should (listp (find-image '((:type png :file "newsticker/rss-feed.png" :ascent center)))))
+ (should-not (find-image '((:type png :file "does-not-exist-foo-bar.png")))))
+
+(ert-deftest image-supported-file-p/built-in ()
+ ;; (skip-unless (image-type-available-p 'pbm)) ; Always built-in
+ (skip-unless (display-images-p)) ; (except in nox builds).
+ (should (eq (image-supported-file-p "foo.pbm") 'pbm)))
+
+(ert-deftest image-supported-file-p/optional ()
+ (if (image-type-available-p 'jpeg)
+ (should (eq (image-supported-file-p "foo.jpg") 'jpeg))
+ (should-not (image-supported-file-p "foo.jpg"))))
+
+(ert-deftest image-supported-file-p/unsupported-returns-nil ()
+ (should-not (image-supported-file-p "foo.some-unsupported-format")))
+
+(ert-deftest image-type-from-file-name ()
+ (with-suppressed-warnings ((obsolete image-type-from-file-name))
+ (should (eq (image-type-from-file-name "foo.jpg") 'jpeg))
+ (should (eq (image-type-from-file-name "foo.png") 'png))
+ (should (eq (image-type-from-file-name "foo.webp") 'webp))))
+
+(ert-deftest image-type/from-filename ()
+ ;; On emba, `image-types' and `image-load-path' do not exist.
+ (skip-unless (and (bound-and-true-p image-types)
+ (bound-and-true-p image-load-path)
+ (image-type-available-p 'jpeg)))
+ (should (eq (image-type "foo.jpg") 'jpeg)))
+
+(defun image-tests--type-from-file-header (type)
+ "Test image-type-from-file-header."
+ (should (eq (if (image-type-available-p type) type)
+ (image-type-from-file-header (cdr (assq type image-tests--files))))))
+
+(ert-deftest image-type-from-file-header-test/gif ()
+ (image-tests--type-from-file-header 'gif))
+
+(ert-deftest image-type-from-file-header-test/jpeg ()
+ (image-tests--type-from-file-header 'jpeg))
+
+(ert-deftest image-type-from-file-header-test/pbm ()
+ (image-tests--type-from-file-header 'pbm))
+
+(ert-deftest image-type-from-file-header-test/png ()
+ (image-tests--type-from-file-header 'png))
+
+(ert-deftest image-type-from-file-header-test/svg ()
+ (image-tests--type-from-file-header 'svg))
+
+(ert-deftest image-type-from-file-header-test/tiff ()
+ (image-tests--type-from-file-header 'tiff))
+
+(ert-deftest image-type-from-file-header-test/webp ()
+ (image-tests--type-from-file-header 'webp))
+
+(ert-deftest image-type-from-file-header-test/xbm ()
+ (image-tests--type-from-file-header 'xbm))
+
+(ert-deftest image-type-from-file-header-test/xpm ()
+ (image-tests--type-from-file-header 'xpm))
+
+(ert-deftest image-rotate ()
+ "Test `image-rotate'."
+ (cl-letf* ((image (list 'image))
+ ((symbol-function 'image--get-imagemagick-and-warn)
+ (lambda () image)))
+ (let ((current-prefix-arg '(4)))
+ (call-interactively #'image-rotate))
+ (should (equal image '(image :rotation 270.0)))
+ (call-interactively #'image-rotate)
+ (should (equal image '(image :rotation 0.0)))
+ (image-rotate)
+ (should (equal image '(image :rotation 90.0)))
+ (image-rotate 0)
+ (should (equal image '(image :rotation 90.0)))
+ (image-rotate 1)
+ (should (equal image '(image :rotation 91.0)))
+ (image-rotate 1234.5)
+ (should (equal image '(image :rotation 245.5)))
+ (image-rotate -154.5)
+ (should (equal image '(image :rotation 91.0)))))
+
+;;; image-tests.el ends here
diff --git a/test/lisp/image/exif-tests.el b/test/lisp/image/exif-tests.el
new file mode 100644
index 00000000000..d62eef4798d
--- /dev/null
+++ b/test/lisp/image/exif-tests.el
@@ -0,0 +1,49 @@
+;;; exif-tests.el --- tests for exif.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2019-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'exif)
+
+(defun test-image-file (name)
+ (expand-file-name
+ name (expand-file-name "data/image"
+ (or (getenv "EMACS_TEST_DIRECTORY")
+ "../../"))))
+
+(ert-deftest test-exif-parse ()
+ (let ((exif (exif-parse-file (test-image-file "black.jpg"))))
+ (should (equal (exif-field 'make exif) "Panasonic"))
+ (should (equal (exif-field 'orientation exif) 1))
+ (should (equal (exif-field 'x-resolution exif) '(180 . 1)))
+ (should (equal (exif-field 'date-time exif) "2019:09:21 16:22:13"))))
+
+(ert-deftest test-exif-parse-short ()
+ (let ((exif (exif-parse-file (test-image-file "black-short.jpg"))))
+ (should (equal (exif-field 'make exif) "thr"))
+ (should (equal (exif-field 'model exif) "four"))
+ (should (equal (exif-field 'software exif) "em"))
+ (should (equal (exif-field 'artist exif) "z"))))
+
+(ert-deftest test-exit-direct-ascii-value ()
+ (should (equal (exif--direct-ascii-value 28005 2 t) (string ?e ?m 0)))
+ (should (equal (exif--direct-ascii-value 28005 2 nil) (string ?m ?e 0))))
+
+;;; exif-tests.el ends here
diff --git a/test/lisp/image/gravatar-tests.el b/test/lisp/image/gravatar-tests.el
new file mode 100644
index 00000000000..3b3a0ad4643
--- /dev/null
+++ b/test/lisp/image/gravatar-tests.el
@@ -0,0 +1,77 @@
+;;; gravatar-tests.el --- tests for gravatar.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2019-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'gravatar)
+
+(ert-deftest gravatar-hash ()
+ "Test `gravatar-hash'."
+ (should (equal (gravatar-hash "") "d41d8cd98f00b204e9800998ecf8427e"))
+ (let ((hash "acbd18db4cc2f85cedef654fccc4a4d8"))
+ (should (equal (gravatar-hash "foo") hash))
+ (should (equal (gravatar-hash "foo ") hash))
+ (should (equal (gravatar-hash " foo") hash))
+ (should (equal (gravatar-hash " foo ") hash))))
+
+(ert-deftest gravatar-size ()
+ "Test query strings for `gravatar-size'."
+ (let ((gravatar-default-image nil)
+ (gravatar-force-default nil))
+ (let ((gravatar-size 2048))
+ (should (equal (gravatar--query-string) "r=g&s=2048")))
+ (let ((gravatar-size nil))
+ (should (equal (gravatar--query-string) "r=g")))))
+
+(ert-deftest gravatar-default-image ()
+ "Test query strings for `gravatar-default-image'."
+ (let ((gravatar-force-default nil)
+ (gravatar-size nil))
+ (let ((gravatar-default-image nil))
+ (should (equal (gravatar--query-string) "r=g")))
+ (let ((gravatar-default-image "404"))
+ (should (equal (gravatar--query-string) "r=g&d=404")))
+ (let ((gravatar-default-image "https://foo/bar.png"))
+ (should (equal (gravatar--query-string)
+ "r=g&d=https%3A%2F%2Ffoo%2Fbar.png")))))
+
+(ert-deftest gravatar-force-default ()
+ "Test query strings for `gravatar-force-default'."
+ (let ((gravatar-default-image nil)
+ (gravatar-size nil))
+ (let ((gravatar-force-default nil))
+ (should (equal (gravatar--query-string) "r=g")))
+ (let ((gravatar-force-default t))
+ (should (equal (gravatar--query-string) "r=g&f=y")))))
+
+(ert-deftest gravatar-build-url ()
+ "Test `gravatar-build-url'."
+ (let ((gravatar-default-image nil)
+ (gravatar-force-default nil)
+ (gravatar-size nil)
+ (gravatar-service 'gravatar)
+ url)
+ (gravatar-build-url "foo" (lambda (u) (setq url u)))
+ (while (not url)
+ (sleep-for 0.01))
+ (should (equal url "\
+https://www.gravatar.com/avatar/acbd18db4cc2f85cedef654fccc4a4d8?r=g"))))
+
+;;; gravatar-tests.el ends here
diff --git a/test/lisp/image/image-dired-tests.el b/test/lisp/image/image-dired-tests.el
new file mode 100644
index 00000000000..00df72487fd
--- /dev/null
+++ b/test/lisp/image/image-dired-tests.el
@@ -0,0 +1,37 @@
+;;; image-dired-tests.el --- Tests for image-dired.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'image-dired)
+
+(defun image-dired-test-image-file (name)
+ (expand-file-name
+ name (expand-file-name "data/image"
+ (or (getenv "EMACS_TEST_DIRECTORY")
+ "../"))))
+
+(ert-deftest image-dired-tests-get-exif-file-name ()
+ (skip-unless (image-type-available-p 'jpeg))
+ (let ((img (image-dired-test-image-file "black.jpg")))
+ (should (equal (image-dired-get-exif-file-name img)
+ "2019_09_21_16_22_13_black.jpg"))))
+
+;;; image-dired-tests.el ends here
diff --git a/test/lisp/image/image-dired-util-tests.el b/test/lisp/image/image-dired-util-tests.el
new file mode 100644
index 00000000000..39862fc6faa
--- /dev/null
+++ b/test/lisp/image/image-dired-util-tests.el
@@ -0,0 +1,54 @@
+;;; image-dired-util-tests.el --- Tests for image-dired.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'ert-x)
+(require 'image-dired)
+(require 'image-dired-util)
+(require 'xdg)
+
+(ert-deftest image-dired-thumb-name/standard ()
+ (let ((image-dired-thumbnail-storage 'standard))
+ (should (file-name-absolute-p (image-dired-thumb-name "foo.jpg")))
+ (should (string-search (xdg-cache-home)
+ (image-dired-thumb-name "foo.jpg")))
+ (should (string-match (rx (in "0-9a-f") ".png")
+ (image-dired-thumb-name "foo.jpg")))))
+
+(ert-deftest image-dired-thumb-name/image-dired ()
+ ;; Avoid trying to create `image-dired-dir'.
+ (ert-with-temp-directory dir
+ (let ((image-dired-dir dir)
+ (image-dired-thumbnail-storage 'image-dired))
+ (should (file-name-absolute-p (image-dired-thumb-name "foo.jpg")))
+ (should (equal (file-name-nondirectory
+ ;; The checksum is based on the directory name.
+ (image-dired-thumb-name "/some/path/foo.jpg"))
+ "foo_45fff7fcc4a0945679b7b11dec36a82d.thumb.jpg")))))
+
+(ert-deftest image-dired-thumb-name/per-directory ()
+ (let ((image-dired-thumbnail-storage 'per-directory))
+ (should (file-name-absolute-p (image-dired-thumb-name "foo.jpg")))
+ (should (equal (file-name-nondirectory
+ (image-dired-thumb-name "foo.jpg"))
+ "foo.thumb.jpg"))))
+
+;;; image-dired-util-tests.el ends here
diff --git a/test/lisp/imenu-tests.el b/test/lisp/imenu-tests.el
index aedc90e84b4..9667f0566c2 100644
--- a/test/lisp/imenu-tests.el
+++ b/test/lisp/imenu-tests.el
@@ -1,6 +1,6 @@
-;;; imenu-tests.el --- Test suite for imenu.
+;;; imenu-tests.el --- Test suite for imenu. -*- lexical-binding:t -*-
-;; Copyright (C) 2013-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2022 Free Software Foundation, Inc.
;; Author: Masatake YAMATO <yamato@redhat.com>
;; Keywords: tools convenience
@@ -50,24 +50,23 @@
(setq input (cdr input)))))
result))
-(defmacro imenu-simple-scan-deftest (name doc major-mode content expected-items)
+(defmacro imenu-simple-scan-deftest (name doc mode content expected-items)
"Generate an ert test for mode-own imenu expression.
Run `imenu-create-index-function' at the buffer which content is
-CONTENT with MAJOR-MODE. A generated test runs `imenu-create-index-function'
-at the buffer which content is CONTENT with MAJOR-MODE. Then it compares a list
-of strings which are picked up from the result with EXPECTED-ITEMS."
+CONTENT with major MODE. A generated test runs `imenu-create-index-function'
+at the buffer which content is CONTENT with major MODE. Then it compares a
+list of strings which are picked up from the result with EXPECTED-ITEMS."
(let ((xname (intern (concat "imenu-simple-scan-deftest-" (symbol-name name)))))
`(ert-deftest ,xname ()
- ,doc
+ ,doc
(with-temp-buffer
(insert ,content)
- (funcall ',major-mode)
+ (funcall #',mode)
(let ((result-items (sort (imenu-simple-scan-deftest-gather-strings-from-list
(funcall imenu-create-index-function))
#'string-lessp))
(expected-items (sort (copy-sequence ,expected-items) #'string-lessp)))
- (should (equal result-items expected-items))
- )))))
+ (should (equal result-items expected-items)))))))
(imenu-simple-scan-deftest sh "Test imenu expression for sh-mode." sh-mode "a()
{
diff --git a/test/lisp/info-tests.el b/test/lisp/info-tests.el
new file mode 100644
index 00000000000..11ac25555de
--- /dev/null
+++ b/test/lisp/info-tests.el
@@ -0,0 +1,39 @@
+;;; info-tests.el --- Tests for info.el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;
+
+;;; Code:
+
+(require 'info)
+(require 'ert)
+(require 'ert-x)
+
+(ert-deftest test-info-urls ()
+ (should (equal (Info-url-for-node "(emacs)Minibuffer")
+ "https://www.gnu.org/software/emacs/manual/html_node/emacs/Minibuffer.html"))
+ (should (equal (Info-url-for-node "(emacs)Minibuffer File")
+ "https://www.gnu.org/software/emacs/manual/html_node/emacs/Minibuffer-File.html"))
+ (should (equal (Info-url-for-node "(elisp)Backups and Auto-Saving")
+ "https://www.gnu.org/software/emacs/manual/html_node/elisp/Backups-and-Auto_002dSaving.html"))
+ (should-error (Info-url-for-node "(gnus)Minibuffer File")))
+
+;;; info-tests.el ends here
diff --git a/test/lisp/info-xref-tests.el b/test/lisp/info-xref-tests.el
index 0a2038a644e..117170ba338 100644
--- a/test/lisp/info-xref-tests.el
+++ b/test/lisp/info-xref-tests.el
@@ -1,6 +1,6 @@
-;;; info-xref.el --- tests for info-xref.el
+;;; info-xref-tests.el --- tests for info-xref.el -*- lexical-binding:t -*-
-;; Copyright (C) 2013-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2022 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -22,6 +22,7 @@
;;; Code:
(require 'ert)
+(require 'ert-x)
(require 'info-xref)
(defun info-xref-test-internal (body result)
@@ -96,15 +97,17 @@ text.
(ert-deftest info-xref-test-makeinfo ()
"Test that info-xref can parse basic makeinfo output."
(skip-unless (executable-find "makeinfo"))
- (let ((tempfile (make-temp-file "info-xref-test" nil ".texi"))
- (tempfile2 (make-temp-file "info-xref-test2" nil ".texi"))
- (errflag t))
- (unwind-protect
- (progn
- ;; tempfile contains xrefs to various things, including tempfile2.
- (info-xref-test-write-file
- tempfile
- (concat "\
+ (ert-with-temp-file tempfile
+ :suffix ".texi"
+ (ert-with-temp-file tempfile2
+ :suffix ".texi"
+ (let ((errflag t))
+ (unwind-protect
+ (progn
+ ;; tempfile contains xrefs to various things, including tempfile2.
+ (info-xref-test-write-file
+ tempfile
+ (concat "\
@xref{nodename,,,missing,Missing Manual}.
@xref{nodename,crossref,title,missing,Missing Manual}.
@@ -114,34 +117,51 @@ text.
@xref{Chapter One,Something}.
"
- (format "@xref{Chapter One,,,%s,Present Manual}.\n"
- (file-name-sans-extension (file-name-nondirectory
- tempfile2)))))
- ;; Something for tempfile to xref to.
- (info-xref-test-write-file tempfile2 "")
- (require 'info)
- (save-window-excursion
- (let ((Info-directory-list
- (list
- (or (file-name-directory tempfile) ".")))
- Info-additional-directory-list)
- (info-xref-check (format "%s.info" (file-name-sans-extension
- tempfile))))
- (should (equal (list info-xref-bad info-xref-good
- info-xref-unavail)
- '(0 1 2)))
- (setq errflag nil)
- ;; If there was an error, we can leave this around.
- (kill-buffer info-xref-output-buffer)))
- ;; Useful diagnostic in case of problems.
- (if errflag
- (with-temp-buffer
- (call-process "makeinfo" nil t nil "--version")
- (message "%s" (buffer-string))))
- (mapc 'delete-file (list tempfile tempfile2
- (format "%s.info" (file-name-sans-extension
- tempfile))
- (format "%s.info" (file-name-sans-extension
- tempfile2)))))))
-
-;;; info-xref.el ends here
+ (format "@xref{Chapter One,,,%s,Present Manual}.\n"
+ (file-name-sans-extension (file-name-nondirectory
+ tempfile2)))))
+ ;; Something for tempfile to xref to.
+ (info-xref-test-write-file tempfile2 "")
+ (require 'info)
+ (save-window-excursion
+ (let ((Info-directory-list
+ (list
+ (or (file-name-directory tempfile) ".")))
+ Info-additional-directory-list)
+ (info-xref-check (format "%s.info" (file-name-sans-extension
+ tempfile))))
+ (should (equal (list info-xref-bad info-xref-good
+ info-xref-unavail)
+ '(0 1 2)))
+ (setq errflag nil)
+ ;; If there was an error, we can leave this around.
+ (kill-buffer info-xref-output-buffer)))
+ ;; Useful diagnostic in case of problems.
+ (if errflag
+ (with-temp-buffer
+ (call-process "makeinfo" nil t nil "--version")
+ (message "%s" (buffer-string))))
+ (ignore-errors
+ (delete-file (format "%s.info" (file-name-sans-extension
+ tempfile))))
+ (ignore-errors
+ (delete-file (format "%s.info" (file-name-sans-extension
+ tempfile2)))))))))
+
+(ert-deftest info-xref-test-emacs-manuals ()
+ "Test that all internal links in the Emacs manuals work."
+ :tags '(:expensive-test)
+ (require 'info)
+ (let ((default-directory (car (Info-default-dirs)))
+ (Info-directory-list '(".")))
+ (skip-unless (file-readable-p "emacs.info"))
+ (info-xref-check-all)
+ (with-current-buffer info-xref-output-buffer
+ (goto-char (point-max))
+ (should (search-backward "done" nil t))
+ (should (string-match-p
+ " [0-9]\\{3,\\} good, 0 bad"
+ (buffer-substring-no-properties (pos-bol) (pos-eol)))))))
+
+
+;;; info-xref-tests.el ends here
diff --git a/test/lisp/international/ccl-tests.el b/test/lisp/international/ccl-tests.el
new file mode 100644
index 00000000000..cf472415c7a
--- /dev/null
+++ b/test/lisp/international/ccl-tests.el
@@ -0,0 +1,252 @@
+;;; ccl-tests.el --- unit tests for ccl.el -*- lexical-binding:t -*-
+
+;; Copyright (C) 2018-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'ccl)
+(require 'seq)
+
+
+(ert-deftest shift ()
+ (with-suppressed-warnings ((suspicious lsh))
+
+ ;; shift left +ve 5628 #x00000000000015fc
+ (should (= (ash 5628 8) 1440768)) ; #x000000000015fc00
+ (should (= (lsh 5628 8) 1440768)) ; #x000000000015fc00
+
+ ;; shift left -ve -5628 #x3fffffffffffea04
+ (should (= (ash -5628 8) -1440768)) ; #x3fffffffffea0400
+ (should (= (lsh -5628 8) -1440768)) ; #x3fffffffffea0400
+
+ ;; shift right +ve 5628 #x00000000000015fc
+ (should (= (ash 5628 -8) 21)) ; #x0000000000000015
+ (should (= (lsh 5628 -8) 21)) ; #x0000000000000015
+
+ ;; shift right -ve -5628 #x3fffffffffffea04
+ (should (= (ash -5628 -8) -22)) ; #x3fffffffffffffea
+ (should (= (lsh -5628 -8)
+ (ash (- -5628 (ash most-negative-fixnum 1)) -8)
+ (ash (logand (ash -5628 -1) most-positive-fixnum) -7)))))
+
+;; CCl program from `pgg-parse-crc24' in lisp/obsolete/pgg-parse.el
+(defconst prog-pgg-source
+ '(1
+ ((loop
+ (read r0) (r1 ^= r0) (r2 ^= 0)
+ (r5 = 0)
+ (loop
+ (r1 <<= 1)
+ (r1 += ((r2 >> 15) & 1))
+ (r2 <<= 1)
+ (if (r1 & 256)
+ ((r1 ^= 390) (r2 ^= 19707)))
+ (if (r5 < 7)
+ ((r5 += 1)
+ (repeat))))
+ (repeat)))))
+
+(defconst prog-pgg-code
+ [1 30 14 114744 114775 0 161 131127 1 148217 15 82167
+ 1 1848 131159 1 1595 5 256 114743 390 114775 19707
+ 1467 16 7 183 1 -5628 -7164 22])
+
+(defconst prog-pgg-dump
+"Out-buffer must be as large as in-buffer.
+Main-body:
+ 2:[read-register] read r0 (0 remaining)
+ 3:[set-assign-expr-register] r1 ^= r0
+ 4:[set-assign-expr-const] r2 ^= 0
+ 6:[set-short-const] r5 = 0
+ 7:[set-assign-expr-const] r1 <<= 1
+ 9:[set-expr-const] r7 = r2 >> 15
+ 11:[set-assign-expr-const] r7 &= 1
+ 13:[set-assign-expr-register] r1 += r7
+ 14:[set-assign-expr-const] r2 <<= 1
+ 16:[jump-cond-expr-const] if !(r1 & 256), jump to 23(+7)
+ 19:[set-assign-expr-const] r1 ^= 390
+ 21:[set-assign-expr-const] r2 ^= 19707
+ 23:[jump-cond-expr-const] if !(r5 < 7), jump to 29(+6)
+ 26:[set-assign-expr-const] r5 += 1
+ 28:[jump] jump to 7(-21)
+ 29:[jump] jump to 2(-27)
+At EOF:
+ 30:[end] end
+")
+
+(ert-deftest ccl-compile-pgg ()
+ (should (equal (ccl-compile prog-pgg-source) prog-pgg-code)))
+
+(ert-deftest ccl-dump-pgg ()
+ (with-temp-buffer
+ (ccl-dump prog-pgg-code)
+ (should (equal (buffer-string) prog-pgg-dump))))
+
+(defvar pgg-parse-crc24)
+(declare-function pgg-parse-crc24-string "pgg-parse" (string))
+
+(ert-deftest pgg-parse-crc24 ()
+ ;; Compiler
+ (require 'pgg)
+ (should (equal pgg-parse-crc24 prog-pgg-code))
+ ;; Interpreter
+ (should (equal (pgg-parse-crc24-string "foo") (concat [#x4f #xc2 #x55])))
+ (should (equal (pgg-parse-crc24-string "bar") (concat [#x51 #xd9 #x53])))
+ (should (equal (pgg-parse-crc24-string "baz") (concat [#xf0 #x58 #x6a]))))
+
+(ert-deftest pgg-parse-crc24-dump ()
+ ;; Disassembler
+ (require 'pgg)
+ (with-temp-buffer
+ (ccl-dump pgg-parse-crc24)
+ (should (equal (buffer-string) prog-pgg-dump))))
+
+;;----------------------------------------------------------------------------
+;; Program from 'midikbd-decoder in midi-kbd-0.2.el GNU ELPA package
+(defconst prog-midi-source
+ '(2
+ (loop
+ (loop
+ ;; central message receiver loop here.
+ ;; When it exits, the command to deal with is in r0
+ ;; Any arguments are in r1 and r2
+ ;; r3 contains: 0 if no arguments are accepted
+ ;; 1 if 1 argument can be accepted
+ ;; 2 if 2 arguments can be accepted
+ ;; 3 if the first of two arguments has been accepted
+ ;; Arguments are read into r1 and r2.
+ ;; r4 contains the current running status byte if any.
+ (read-if (r0 < #x80)
+ (branch r3
+ (repeat)
+ ((r1 = r0) (r0 = r4) (break))
+ ((r1 = r0) (r3 = 3) (repeat))
+ ((r2 = r0) (r3 = 2) (r0 = r4) (break))))
+ (if (r0 >= #xf8) ; real time message
+ (break))
+ (if (r0 < #xf0) ; channel command
+ ((r4 = r0)
+ (if ((r0 & #xe0) == #xc0)
+ ;; program change and channel pressure take only 1 argument
+ (r3 = 1)
+ (r3 = 2))
+ (repeat)))
+ ;; system common message, we swallow those for now
+ (r3 = 0)
+ (repeat))
+ (if ((r0 & #xf0) == #x90)
+ (if (r2 == 0) ; Some Midi devices use velocity 0
+ ; for switching notes off,
+ ; so translate into note-off
+ ; and fall through
+ (r0 -= #x10)
+ ((r0 &= #xf)
+ (write 0)
+ (write r0 r1 r2)
+ (repeat))))
+ (if ((r0 & #xf0) == #x80)
+ ((r0 &= #xf)
+ (write 1)
+ (write r0 r1 r2)
+ (repeat)))
+ (repeat))))
+
+(defconst prog-midi-code
+ [2 72 4893 16 128 1133 5 6 9 12 16 -2556 32 1024 6660 32 865
+ -4092 64 609 1024 4868 795 20 248 3844 3099 16 240 128 82169
+ 224 1275 18 192 353 260 609 -9468 97 -9980 82169 240 4091
+ 18 144 1371 18 0 16407 16 1796 81943 15 20 529 305 81 -14588
+ 82169 240 2555 18 128 81943 15 276 529 305 81 -17660 -17916 22])
+
+(defconst prog-midi-dump
+(concat "Out-buffer must be 2 times bigger than in-buffer.
+Main-body:
+ 2:[read-jump-cond-expr-const] read r0, if !(r0 < 128), jump to 22(+20)
+ 5:[branch] jump to array[r3] of length 4
+ 11 12 15 18 22 ""
+ 11:[jump] jump to 2(-9)
+ 12:[set-register] r1 = r0
+ 13:[set-register] r0 = r4
+ 14:[jump] jump to 41(+27)
+ 15:[set-register] r1 = r0
+ 16:[set-short-const] r3 = 3
+ 17:[jump] jump to 2(-15)
+ 18:[set-register] r2 = r0
+ 19:[set-short-const] r3 = 2
+ 20:[set-register] r0 = r4
+ 21:[jump] jump to 41(+20)
+ 22:[jump-cond-expr-const] if !(r0 >= 248), jump to 26(+4)
+ 25:[jump] jump to 41(+16)
+ 26:[jump-cond-expr-const] if !(r0 < 240), jump to 39(+13)
+ 29:[set-register] r4 = r0
+ 30:[set-expr-const] r7 = r0 & 224
+ 32:[jump-cond-expr-const] if !(r7 == 192), jump to 37(+5)
+ 35:[set-short-const] r3 = 1
+ 36:[jump] jump to 38(+2)
+ 37:[set-short-const] r3 = 2
+ 38:[jump] jump to 2(-36)
+ 39:[set-short-const] r3 = 0
+ 40:[jump] jump to 2(-38)
+ 41:[set-expr-const] r7 = r0 & 240
+ 43:[jump-cond-expr-const] if !(r7 == 144), jump to 59(+16)
+ 46:[jump-cond-expr-const] if !(r2 == 0), jump to 52(+6)
+ 49:[set-assign-expr-const] r0 -= 16
+ 51:[jump] jump to 59(+8)
+ 52:[set-assign-expr-const] r0 &= 15
+ 54:[write-const-string] write char \"\x00\"
+ 55:[write-register] write r0 (2 remaining)
+ 56:[write-register] write r1 (1 remaining)
+ 57:[write-register] write r2 (0 remaining)
+ 58:[jump] jump to 2(-56)
+ 59:[set-expr-const] r7 = r0 & 240
+ 61:[jump-cond-expr-const] if !(r7 == 128), jump to 71(+10)
+ 64:[set-assign-expr-const] r0 &= 15
+ 66:[write-const-string] write char \"\x01\"
+ 67:[write-register] write r0 (2 remaining)
+ 68:[write-register] write r1 (1 remaining)
+ 69:[write-register] write r2 (0 remaining)
+ 70:[jump] jump to 2(-68)
+ 71:[jump] jump to 2(-69)
+At EOF:
+ 72:[end] end
+"))
+
+(ert-deftest ccl-compile-midi ()
+ (should (equal (ccl-compile prog-midi-source) prog-midi-code)))
+
+(ert-deftest ccl-dump-midi ()
+ (with-temp-buffer
+ (ccl-dump prog-midi-code)
+ (should (equal (buffer-string) prog-midi-dump))))
+
+(ert-deftest ccl-hash-table ()
+ (let ((sym (gensym))
+ (table (make-hash-table :test 'eq)))
+ (puthash 16 17 table)
+ (puthash 17 16 table)
+ (define-translation-hash-table sym table)
+ (let* ((prog `(2
+ ((loop
+ (lookup-integer ,sym r0 r1)))))
+ (compiled (ccl-compile prog))
+ (registers [17 0 0 0 0 0 0 0]))
+ (ccl-execute compiled registers)
+ (should (equal registers [2 16 0 0 0 0 0 1])))))
+
+;;; ccl-tests.el ends here
diff --git a/test/lisp/international/mule-tests.el b/test/lisp/international/mule-tests.el
index 4265cec14af..94e864817f0 100644
--- a/test/lisp/international/mule-tests.el
+++ b/test/lisp/international/mule-tests.el
@@ -1,6 +1,6 @@
;;; mule-tests.el --- unit tests for mule.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2017 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2022 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -23,6 +23,8 @@
;;; Code:
+(require 'ert-x) ;For `ert-simulate-keys'.
+
(ert-deftest find-auto-coding--bug27391 ()
"Check that Bug#27391 is fixed."
(with-temp-buffer
@@ -36,4 +38,39 @@
(find-auto-coding "" (buffer-size)))
'(utf-8 . :coding)))))
+(ert-deftest mule-cmds-tests--encode-ebcdic ()
+ (should (equal (encode-coding-char ?a 'ebcdic-int) "\201"))
+ (should (not (multibyte-string-p (encode-coding-char ?a 'utf-8)))))
+
+(ert-deftest mule-cmds--test-universal-coding-system-argument ()
+ (should (equal "ccccccccccccccccab"
+ (let ((enable-recursive-minibuffers t))
+ (ert-simulate-keys
+ (kbd "C-x RET c u t f - 8 RET C-u C-u c a b RET")
+ (read-string "prompt:"))))))
+
+(ert-deftest mule-utf-7 ()
+ ;; utf-7 and utf-7-imap are not ASCII-compatible.
+ (should-not (coding-system-get 'utf-7 :ascii-compatible-p))
+ (should-not (coding-system-get 'utf-7-imap :ascii-compatible-p))
+ ;; Invariant ASCII subset.
+ (let ((s (apply #'string (append (number-sequence #x20 #x25)
+ (number-sequence #x27 #x7e)))))
+ (should (equal (encode-coding-string s 'utf-7-imap) s))
+ (should (equal (decode-coding-string s 'utf-7-imap) s)))
+ ;; Escaped ampersand.
+ (should (equal (encode-coding-string "a&bcd" 'utf-7-imap) "a&-bcd"))
+ (should (equal (decode-coding-string "a&-bcd" 'utf-7-imap) "a&bcd"))
+ ;; Ability to encode Unicode.
+ (should (equal (check-coding-systems-region "あ" nil '(utf-7-imap)) nil))
+ (should (equal (encode-coding-string "あ" 'utf-7-imap) "&MEI-"))
+ (should (equal (decode-coding-string "&MEI-" 'utf-7-imap) "あ")))
+
+(ert-deftest mule-hz ()
+ ;; The chinese-hz encoding is not ASCII compatible.
+ (should-not (coding-system-get 'chinese-hz :ascii-compatible-p)))
+
+;; Stop "Local Variables" above causing confusion when visiting this file.
+
+
;;; mule-tests.el ends here
diff --git a/test/lisp/international/mule-util-resources/utf-8.txt b/test/lisp/international/mule-util-resources/utf-8.txt
new file mode 100644
index 00000000000..385bbb4ba80
--- /dev/null
+++ b/test/lisp/international/mule-util-resources/utf-8.txt
@@ -0,0 +1,2 @@
+Thís is a test line 1.
+Line 2.
diff --git a/test/lisp/international/mule-util-tests.el b/test/lisp/international/mule-util-tests.el
index 01f40a227ca..cf29e0e290e 100644
--- a/test/lisp/international/mule-util-tests.el
+++ b/test/lisp/international/mule-util-tests.el
@@ -1,6 +1,6 @@
-;;; mule-util --- tests for international/mule-util.el
+;;; mule-util-tests.el --- tests for international/mule-util.el -*- lexical-binding:t -*-
-;; Copyright (C) 2002-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2022 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -22,6 +22,7 @@
;;; Code:
(require 'ert)
+(require 'ert-x)
(require 'mule-util)
(defconst mule-util-test-truncate-data
@@ -75,10 +76,50 @@
(eval
`(ert-deftest ,testname ()
,testdoc
- (should (equal (apply 'truncate-string-to-width ',(car testdata))
- ,(cdr testdata)))))))
+ (let ((truncate-string-ellipsis "..."))
+ (should (equal (apply 'truncate-string-to-width ',(car testdata))
+ ,(cdr testdata))))))))
(dotimes (i (length mule-util-test-truncate-data))
(mule-util-test-truncate-create i))
-;;; mule-util.el ends here
+(ert-deftest filepos/bufferpos-tests-utf-8 ()
+ (let ((coding-system-for-read 'utf-8-unix))
+ (with-temp-buffer
+ (insert-file-contents (ert-resource-file "utf-8.txt"))
+ (should (eq buffer-file-coding-system 'utf-8-unix))
+ ;; First line is "Thís is a test line 1.".
+ ;; Bytes start counting at 0; chars at 1.
+ (should (= (filepos-to-bufferpos 1 'exact) 2))
+ (should (= (bufferpos-to-filepos 2 'exact) 1))
+ ;; After non-ASCII.
+ (should (= (filepos-to-bufferpos 4 'exact) 4))
+ (should (= (bufferpos-to-filepos 4 'exact) 4)))))
+
+(ert-deftest filepos/bufferpos-tests-binary ()
+ (let ((coding-system-for-read 'binary))
+ (with-temp-buffer
+ (insert-file-contents (ert-resource-file "utf-8.txt"))
+ (should (eq buffer-file-coding-system 'no-conversion))
+ ;; First line is "Thís is a test line 1.".
+ ;; Bytes start counting at 0; chars at 1.
+ (should (= (filepos-to-bufferpos 1 'exact) 2))
+ (should (= (bufferpos-to-filepos 2 'exact) 1))
+ ;; After non-ASCII.
+ (should (= (filepos-to-bufferpos 4 'exact) 5))
+ (should (= (bufferpos-to-filepos 5 'exact) 4)))))
+
+(ert-deftest filepos/bufferpos-tests-undecided ()
+ (let ((coding-system-for-read 'binary))
+ (with-temp-buffer
+ (insert-file-contents (ert-resource-file "utf-8.txt"))
+ (setq buffer-file-coding-system 'undecided)
+ (should-error (filepos-to-bufferpos 1 'exact))
+ (should-error (bufferpos-to-filepos 2 'exact))
+ (should (= (filepos-to-bufferpos 1 'approximate) 2))
+ (should (= (bufferpos-to-filepos 2 'approximate) 1))
+ ;; After non-ASCII.
+ (should (= (filepos-to-bufferpos 4 'approximate) 5))
+ (should (= (bufferpos-to-filepos 5 'approximate) 4)))))
+
+;;; mule-util-tests.el ends here
diff --git a/test/lisp/international/textsec-tests.el b/test/lisp/international/textsec-tests.el
new file mode 100644
index 00000000000..6b0773dc407
--- /dev/null
+++ b/test/lisp/international/textsec-tests.el
@@ -0,0 +1,214 @@
+;;; textsec-tests.el --- Tests for textsec.el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;
+
+;;; Code:
+
+(require 'textsec)
+(require 'ert)
+(require 'ert-x)
+
+(ert-deftest test-scripts ()
+ (should (equal (textsec-scripts "Circle")
+ '((latin) (latin) (latin) (latin) (latin) (latin))))
+ (should (textsec-single-script-p "Circle"))
+
+ (should (equal (textsec-scripts "СігсӀе")
+ '((cyrillic) (cyrillic) (cyrillic)
+ (cyrillic) (cyrillic) (cyrillic))))
+ (should (textsec-single-script-p "СігсӀе"))
+
+ (should (equal (textsec-scripts "Сirсlе")
+ '((cyrillic) (latin) (latin) (cyrillic) (latin) (cyrillic))))
+ (should-not (textsec-single-script-p "Сirсlе"))
+
+ (should (equal (textsec-scripts "Circ1e")
+ '((latin) (latin) (latin) (latin) (common) (latin))))
+ (should (textsec-single-script-p "Circ1e"))
+
+ (should (equal (textsec-scripts "C𝗂𝗋𝖼𝗅𝖾")
+ '((latin) (common) (common) (common) (common) (common))))
+ (should (textsec-single-script-p "C𝗂𝗋𝖼𝗅𝖾"))
+
+ (should (equal (textsec-scripts "𝖢𝗂𝗋𝖼𝗅𝖾")
+ '((common) (common) (common) (common) (common) (common))))
+ (should (textsec-single-script-p "𝖢𝗂𝗋𝖼𝗅𝖾"))
+
+ (should (equal (textsec-scripts "〆切")
+ '((common han) (han))))
+ (should (textsec-single-script-p "〆切"))
+
+ (should (equal (textsec-scripts "ねガ")
+ '((hiragana) (katakana))))
+ (should (textsec-single-script-p "ねガ")))
+
+(ert-deftest test-minimal-scripts ()
+ (should (equal (textsec-covering-scripts "Circle")
+ '(latin)))
+ (should (equal (textsec-covering-scripts "Сirсlе")
+ '(cyrillic latin)))
+ (should (equal (textsec-covering-scripts "〆切")
+ '(han))))
+
+(ert-deftest test-restriction-level ()
+ (should (eq (textsec-restriction-level "foo")
+ 'ascii-only))
+ (should (eq (textsec-restriction-level "C𝗂𝗋𝖼𝗅𝖾")
+ 'single-script))
+ (should (eq (textsec-restriction-level "切foo")
+ 'highly-restrictive))
+ (should (eq (textsec-restriction-level "հfoo")
+ 'moderately-retrictive))
+ (should (eq (textsec-restriction-level "Сirсlе")
+ 'unrestricted)))
+
+(ert-deftest test-mixed-numbers ()
+ (should-not (textsec-mixed-numbers-p "foo"))
+ (should-not (textsec-mixed-numbers-p "8foo8"))
+ (should-not (textsec-mixed-numbers-p "foo20@foo.org"))
+ (should (textsec-mixed-numbers-p "8foo৪")))
+
+(ert-deftest test-resolved ()
+ (should (equal (textsec-resolved-script-set "ljeto")
+ '(latin)))
+ (should-not (textsec-resolved-script-set "Сirсlе")))
+
+(ert-deftest test-confusable ()
+ (should (equal (textsec-unconfuse-string "ljeto") "ljeto"))
+ (should (textsec-ascii-confusable-p "ljeto"))
+ (should-not (textsec-ascii-confusable-p "ljeto"))
+ (should (equal (textsec-unconfuse-string "~") "〜"))
+ (should-not (textsec-ascii-confusable-p "~"))
+
+ (should (textsec-single-script-confusable-p "ljeto" "ljeto"))
+ (should-not (textsec-single-script-confusable-p "paypal" "pаypаl"))
+ (should-not (textsec-single-script-confusable-p "scope""ѕсоре"))
+
+ (should-not (textsec-mixed-script-confusable-p "ljeto" "ljeto"))
+ (should (textsec-mixed-script-confusable-p "paypal" "pаypаl"))
+ (should (textsec-mixed-script-confusable-p "scope""ѕсоре"))
+
+ (should-not (textsec-whole-script-confusable-p "ljeto" "ljeto"))
+ (should-not (textsec-whole-script-confusable-p "paypal" "pаypаl"))
+ (should (textsec-whole-script-confusable-p "scope""ѕсоре")))
+
+(ert-deftest test-suspiction-domain ()
+ (should (textsec-domain-suspicious-p "foo/bar.org"))
+ (should-not (textsec-domain-suspicious-p "foo.org"))
+ (should (textsec-domain-suspicious-p "f\N{LEFT-TO-RIGHT ISOLATE}oo.org"))
+
+ (should (textsec-domain-suspicious-p "Сгсе.ru"))
+ (should-not (textsec-domain-suspicious-p "фСгсе.ru"))
+
+ (should-not (textsec-domain-suspicious-p
+ "21a:34aa:c782:3ad2:1bf8:73f8:141:66e8"))
+ (should (textsec-domain-suspicious-p
+ "21a:34aa:c782:3ad2:1bf8:73f8:141:66e8:66e8"))
+ (should-not (textsec-domain-suspicious-p
+ "[21a:34aa:c782:3ad2:1bf8:73f8:141:66e8]"))
+ (should (textsec-domain-suspicious-p
+ "[21a:34aa:c782:3ad2:1bf8:73f8:141:66e8"))
+ (should-not (textsec-domain-suspicious-p "138.25.106.12"))
+ (should-not (textsec-domain-suspicious-p "2001:db8::ff00:42:8329"))
+ (should-not (textsec-domain-suspicious-p "::ffff:129.55.2.201")))
+
+(ert-deftest test-suspicious-local ()
+ (should-not (textsec-local-address-suspicious-p "larsi"))
+ (should (textsec-local-address-suspicious-p ".larsi"))
+ (should (textsec-local-address-suspicious-p "larsi."))
+ (should-not (textsec-local-address-suspicious-p "la.rsi"))
+ (should (textsec-local-address-suspicious-p "lar..si"))
+
+ (should-not (textsec-local-address-suspicious-p "LÅRSI"))
+ (should (textsec-local-address-suspicious-p "LÅRSI"))
+
+ (should (textsec-local-address-suspicious-p "larsi8৪")))
+
+(ert-deftest test-suspicious-name ()
+ (should-not (textsec-name-suspicious-p "Lars Ingebrigtsen"))
+ (should (textsec-name-suspicious-p "LÅRS INGEBRIGTSEN"))
+ (should-not (textsec-name-suspicious-p "LÅRS INGEBRIGTSEN"))
+
+ (should (textsec-name-suspicious-p
+ "Lars Ingebrigtsen\N{LEFT-TO-RIGHT OVERRIDE}"))
+ (should (textsec-name-suspicious-p
+ "Lars Ingebrigtsen\N{LEFT-TO-RIGHT OVERRIDE}f"))
+ (should-not (textsec-name-suspicious-p
+ "Lars Ingebrigtsen\N{LEFT-TO-RIGHT MARK}"))
+ (should-not (textsec-name-suspicious-p "אבגד ⁧שונה⁩ מרגיל"))
+
+ (should (textsec-name-suspicious-p
+ "\N{COMBINING GRAVE ACCENT}\N{COMBINING GRAVE ACCENT}Lars Ingebrigtsen"))
+ (should-not (textsec-name-suspicious-p
+ "\N{COMBINING GRAVE ACCENT}\N{COMBINING ENCLOSING CIRCLE}Lars Ingebrigtsen"))
+ (should (textsec-name-suspicious-p
+ "\N{COMBINING GRAVE ACCENT}\N{COMBINING ENCLOSING CIRCLE}\N{COMBINING GRAVE ACCENT}\N{COMBINING ENCLOSING CIRCLE}\N{COMBINING GRAVE ACCENT}Lars Ingebrigtsen")))
+
+(ert-deftest test-suspicious-email ()
+ (should-not
+ (textsec-email-address-header-suspicious-p
+ "Lars Ingebrigtsen <larsi@gnus.org>"))
+ (should
+ (textsec-email-address-header-suspicious-p
+ "LÅrs Ingebrigtsen <larsi@gnus.org>"))
+ (should
+ (textsec-email-address-header-suspicious-p
+ "Lars Ingebrigtsen <.larsi@gnus.org>"))
+ (should
+ (textsec-email-address-header-suspicious-p
+ "Lars Ingebrigtsen <larsi@gn\N{LEFT-TO-RIGHT ISOLATE}us.org>"))
+
+ (should
+ (textsec-email-address-header-suspicious-p
+ "Lars Ingebrigtsen <larsi@\N{RIGHT-TO-LEFT OVERRIDE}gnus.org>"))
+
+ (should-not (textsec-email-address-header-suspicious-p
+ "דגבא <foo@bar.com>"))
+
+ (should (textsec-email-address-suspicious-p
+ "Bob_Norbolwits@GCSsafetyACE.com​")))
+
+(ert-deftest test-suspicious-url ()
+ (should-not (textsec-url-suspicious-p "http://example.ru/bar"))
+ (should (textsec-url-suspicious-p "http://Сгсе.ru/bar")))
+
+(ert-deftest test-suspicious-link ()
+ (should-not (textsec-link-suspicious-p
+ (cons "https://gnu.org/" "Hello")))
+ (should-not (textsec-link-suspicious-p
+ (cons "https://gnu.org/" "https://gnu.org/")))
+ (should-not (textsec-link-suspicious-p
+ (cons "https://gnu.org/" "https://www.gnu.org/")))
+ (should-not (textsec-link-suspicious-p
+ (cons "https://www.gnu.org/" "https://gnu.org/")))
+ (should (textsec-link-suspicious-p
+ (cons "https://www.gnu.org/" "https://org/")))
+ (should (textsec-link-suspicious-p
+ (cons "https://www.gnu.org/" "https://fsf.org/")))
+ (should (textsec-link-suspicious-p
+ (cons "https://www.gnu.org/" "http://fsf.org/")))
+
+ (should (textsec-link-suspicious-p
+ (cons "https://www.gn\N{LEFT-TO-RIGHT ISOLATE}u.org/"
+ "https://gn\N{LEFT-TO-RIGHT ISOLATE}u.org"))))
+
+;;; textsec-tests.el ends here
diff --git a/test/lisp/international/ucs-normalize-tests.el b/test/lisp/international/ucs-normalize-tests.el
index 94bf77633e1..9e359d5022f 100644
--- a/test/lisp/international/ucs-normalize-tests.el
+++ b/test/lisp/international/ucs-normalize-tests.el
@@ -1,6 +1,6 @@
-;;; ucs-normalize --- tests for international/ucs-normalize.el -*- lexical-binding: t -*-
+;;; ucs-normalize-tests.el --- tests for international/ucs-normalize.el -*- lexical-binding: t -*-
-;; Copyright (C) 2002-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2022 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -123,9 +123,9 @@ The following invariants must be true for all conformant implementations..."
(defsubst ucs-normalize-tests--rule2-holds-p (X)
"Check 2nd conformance rule.
-For every code point X assigned in this version of Unicode that is not specifically
-listed in Part 1, the following invariants must be true for all conformant
-implementations:
+For every code point X assigned in this version of Unicode that
+is not specifically listed in Part 1, the following invariants
+must be true for all conformant implementations:
X == toNFC(X) == toNFD(X) == toNFKC(X) == toNFKD(X)"
(and (ucs-normalize-tests--normalization-chareq-p NFC X X)
@@ -181,26 +181,43 @@ implementations:
(should-not (ucs-normalize-tests--rule1-failing-for-partX 0)))
(defconst ucs-normalize-tests--failing-lines-part1
- (list 15131 15132 15133 15134 15135 15136 15137 15138
- 15139
- 16149 16150 16151 16152 16153 16154 16155 16156
- 16157 16158 16159 16160 16161 16162 16163 16164
- 16165 16166 16167 16168 16169 16170 16171 16172
- 16173 16174 16175 16176 16177 16178 16179 16180
- 16181 16182 16183 16184 16185 16186 16187 16188
- 16189 16190 16191 16192 16193 16194 16195 16196
- 16197 16198 16199 16200 16201 16202 16203 16204
- 16205 16206 16207 16208 16209 16210 16211 16212
- 16213 16214 16215 16216 16217 16218 16219 16220
- 16221 16222 16223 16224 16225 16226 16227 16228
- 16229 16230 16231 16232 16233 16234 16235 16236
- 16237 16238 16239 16240 16241 16242 16243 16244
- 16245 16246 16247 16248 16249 16250 16251 16252
- 16253 16254 16255 16256 16257 16258 16259 16260
- 16261 16262 16263 16264 16265 16266 16267 16268
- 16269 16270 16271 16272 16273 16274 16275 16276
- 16277 16278 16279 16280 16281 16282 16283 16284
- 16285 16286 16287 16288 16289))
+ (list 2412 2413 2414 15133 15134 15135 15136 15137
+ 15138 15139 15140 15141 15142 15143 15144 15145
+ 15146 15147 15148 15149 15150 15151 15152 15153
+ 15154 15155 15156 15157 15158 15159 15160 15161
+ 15162 15163 15164 15165 15166 15167 15168 15169
+ 15170 15171 15172 15173 15174 15175 15176 15177
+ 15178 15179 15180 15181 15182 15183 15184 15185
+ 15186 15187 15188 15192 15193 15194 15195 15196
+ 15197 15198 15199 15200 15201 16211 16212 16213
+ 16214 16215 16216 16217 16218 16219 16220 16221
+ 16222 16223 16224 16225 16226 16227 16228 16229
+ 16230 16231 16232 16233 16234 16235 16236 16237
+ 16238 16239 16240 16241 16242 16243 16244 16245
+ 16246 16247 16248 16249 16250 16251 16252 16253
+ 16254 16255 16256 16257 16258 16259 16260 16261
+ 16262 16263 16264 16265 16266 16267 16268 16269
+ 16270 16271 16272 16273 16274 16275 16276 16277
+ 16278 16279 16280 16281 16282 16283 16284 16285
+ 16286 16287 16288 16289 16290 16291 16292 16293
+ 16294 16295 16296 16297 16298 16299 16300 16301
+ 16302 16303 16304 16305 16306 16307 16308 16309
+ 16310 16311 16312 16313 16314 16315 16316 16317
+ 16318 16319 16320 16321 16322 16323 16324 16325
+ 16326 16327 16328 16329 16330 16331 16332 16333
+ 16334 16335 16336 16337 16338 16339 16340 16341
+ 16342 16343 16344 16345 16346 16347 16348 16349
+ 16350 16351 16352 16353 16354 16355 16356 16357
+ 16358 16359 16360 16361 16362 16363 16364 16365
+ 16366 16367 16368 16369 16370 16371 16372 16373
+ 16374 16375 16376 16377 16378 16379 16380 16381
+ 16382 16383 16384 16385 16386 16387 16388 16389
+ 16390 16391 16392 16393 16394 16395 16396 16397
+ 16398 16399 16400 16401 16402 16403 16404 16405
+ 16406 16407 16408 16409 16410 16411 16412 16413
+ 16550 16551 16552 16553 16554 16555 16556 16557
+ 16488 16489 16490 16491 16492 16493 16494 16495
+ 16496 16497 16558 16559))
;; Keep a record of failures, for consulting afterwards (the ert
;; backtrace only shows a truncated version of these lists).
@@ -232,12 +249,13 @@ implementations:
(ert-deftest ucs-normalize-part1 ()
:tags '(:expensive-test)
+ (skip-unless (not (getenv "EMACS_HYDRA_CI"))) ; SLOW ~ 1800s
;; This takes a long time, so make sure we're compiled.
(dolist (fun '(ucs-normalize-tests--part1-rule2
ucs-normalize-tests--rule1-failing-for-partX
ucs-normalize-tests--rule1-holds-p
ucs-normalize-tests--rule2-holds-p))
- (or (byte-code-function-p (symbol-function fun))
+ (or (compiled-function-p (symbol-function fun))
(byte-compile fun)))
(let ((ucs-normalize-tests--chars-part1 (make-char-table 'ucs-normalize-tests t)))
(setq ucs-normalize-tests--part1-rule1-failed-lines
@@ -258,21 +276,88 @@ implementations:
ucs-normalize-tests--failing-lines-part1)))
(defconst ucs-normalize-tests--failing-lines-part2
- (list 17656 17658 18006 18007 18008 18009 18010 18011
- 18012 18340 18342 18344 18346 18348 18350 18352
- 18354 18356 18358 18360 18362 18364 18366 18368
- 18370 18372 18374 18376 18378 18380 18382 18384
- 18386 18388 18390 18392 18394 18396 18398 18400
- 18402 18404 18406 18408 18410 18412 18414 18416
- 18418 18420 18422 18424 18426 18428 18430 18432
- 18434 18436 18438 18440 18442 18444 18446 18448
- 18450 18518 18520 18522 18524 18526 18528 18530
- 18532 18534 18536 18538 18540 18542 18544 18546
- 18548 18550 18552 18554 18556 18558 18560 18562
- 18564 18566 18568 18570 18572 18574 18576 18578
- 18580 18582 18584 18586 18588 18590 18592 18594
- 18596 18598 18600 18602 18604 18606 18608 18610
- 18612 18614 18616 18618 18620))
+ (list 17087 17088 17089 17090 17091 17092 17093 17094
+ 17098 17099 17100 17101 17102 17103 17104 17105
+ 17106 17107 17108 17113 17114 17115 17116 17117
+ 17118 17119 17120 17125 17126 17127 17128 17129
+ 17130 17131 17132 17133 17134 17135 17136 17137
+ 17138 17139 17140 17141 17142 17143 17144 17145
+ 17146 17157 17158 17159 17160 17161 17162 17163
+ 17164 17185 17186 17187 17188 17189 17190 17197
+ 17198 17199 17200 17207 17208 17209 17210 17211
+ 17212 17213 17214 17219 17220 17221 17222 17275
+ 17276 17285 17286 17295 17296 17309 17310 17311
+ 17312 17313 17314 17315 17316 17317 17318 17319
+ 17320 17325 17326 17373 17374 17419 17420 17421
+ 17422 17433 17434 17439 17440 17465 17466 17473
+ 17474 17479 17480 17485 17486 17491 17492 17497
+ 17498 17499 17500 17501 17502 17505 17506 17507
+ 17508 17511 17512 17519 17520 17523 17524 17527
+ 17528 17531 17532 17551 17552 17555 17556 17599
+ 17600 17601 17602 17603 17604 17605 17607 17608
+ 17609 17610 17611 17612 17613 17615 17617 17619
+ 17621 17623 17625 17627 17629 17631 17632 17633
+ 17634 17635 17636 17637 17638 17639 17640 17669
+ 17670 17675 17676 17681 17682 17689 17690 17691
+ 17692 17693 17694 17707 17708 17713 17714 17715
+ 17716 17727 17728 17733 17734 17739 17740 17745
+ 17746 17749 17750 17753 17754 17759 17760 17767
+ 17768 17789 17790 17801 17802 17807 17808 17809
+ 17810 17811 17812 17813 17814 17815 17816 17821
+ 17822 17829 17830 17843 17844 17845 17846 17851
+ 17852 17861 17875 17876 17879 17880 17899 17900
+ 17097 17907 17908 17911 17912 17913 17914 17915
+ 17916 17917 17918 17919 17920 17921 17922 17927
+ 17928 17929 17930 17931 17932 17933 17935 17937
+ 17938 17939 17940 17941 17943 17945 17947 17949
+ 17951 17952 17953 17955 17957 17959 17961 17962
+ 17967 17968 17987 17988 17993 17994 18003 18004
+ 18005 18006 18007 18008 18009 18010 18011 18012
+ 18017 18018 18019 18020 18021 18022 18023 18024
+ 18041 18042 18049 18050 18053 18054 18055 18056
+ 18069 18070 18079 18080 18163 18164 18165 18166
+ 18171 18172 18175 18176 18211 18212 18219 18220
+ 18221 18222 18223 18224 18225 18226 18301 18302
+ 18389 18390 18391 18392 18393 18394 18397 18398
+ 18407 18408 18439 18440 18441 18442 18443 18444
+ 18445 18446 18447 18448 18449 18450 18451 18452
+ 18457 18458 18459 18460 18471 18472 18479 18480
+ 18485 18486 18499 18500 18501 18502 18509 18510
+ 18513 18514 18515 18516 18517 18518 18519 18520
+ 18521 18523 18524 18525 18527 18528 18531 18537
+ 18538 18539 18541 18543 18545 18547 18549 18550
+ 18551 18553 18554 18555 18557 18558 18559 18560
+ 18561 18562 18563 18564 18565 18566 18567 18569
+ 18571 18573 18575 18577 18579 18581 18583 18585
+ 18587 18589 18591 18593 18595 18596 18597 18599
+ 18601 18602 18603 18605 18606 18607 18609 18611
+ 18612 18613 18615 18617 18618 18619 18621 18622
+ 18623 18624 18625 18626 18627 18628 18629 18631
+ 18632 18633 18634 18635 18636 18637 18639 18641
+ 18643 18645 18647 18649 18651 18653 18655 18657
+ 18659 18661 18663 18664 18665 18667 18668 18669
+ 18670 18671 18673 18674 18675 18676 18677 18679
+ 18680 18681 18683 18685 18686 18687 18688 18689
+ 18690 18691 18692 18693 18694 18695 18696 18697
+ 18698 18699 18700 18701 18702 18703 18704 18705
+ 18706 18707 18708 18709 18710 18711 18712 18713
+ 18714 18715 18717 18719 18721 18722 18723 18724
+ 18725 18727 18729 18731 18733 18735 18737 18739
+ 18740 18741 18742 18743 18745 18747 18749 18751
+ 18753 18755 18757 18759 18761 18763 18765 18767
+ 18769 18771 18773 18775 18777 18779 18781 18783
+ 18785 18787 18789 18791 18793 18795 18797 18799
+ 18801 18803 18805 18807 18809 18811 18813 18815
+ 18817 18819 18821 18823 18825 18827 18829 18831
+ 18833 18835 18837 18839 18840 18841 18842 18843
+ 18844 18845 18846 18847 18848 18849 18850 18851
+ 18852 18853 18855 18857 18859 18861 18863 18865
+ 18866 18867 18869 18871 18873 18875 18877 18879
+ 18881 18883 18885 18887 18888 18889 18891 18893
+ 18895 18897 18899 18901 18903 18905 18907 18909
+ 18911 18913 18914 18915 18916 18917 18918 18919
+ 18920 18921 18923 18925 18927 18929 18931 18933
+ 18935 18937 18939 18941 18943 18945 18947 18948))
(ert-deftest ucs-normalize-part2 ()
:tags '(:expensive-test)
@@ -299,7 +384,7 @@ implementations:
(list " var var))
(dolist (linos (seq-partition newval 8))
(insert (mapconcat #'number-to-string linos " ") "\n"))
- (insert ")\)"))
+ (insert "))"))
(defun ucs-normalize-check-failing-lines ()
(interactive)
@@ -333,4 +418,15 @@ implementations:
(display-buffer (current-buffer)))
(message "No changes to failing lines needed"))))
+(ert-deftest ucs-normalize-save-match-data ()
+ "Verify that match data isn't clobbered (bug#41445)"
+ (string-match (rx (+ digit)) "a47b")
+ (should (equal (match-data t) '(1 3)))
+ (should (equal
+ (decode-coding-string
+ (encode-coding-string "Käsesoßenrührlöffel" 'utf-8-hfs)
+ 'utf-8-hfs)
+ "Käsesoßenrührlöffel"))
+ (should (equal (match-data t) '(1 3))))
+
;;; ucs-normalize-tests.el ends here
diff --git a/test/lisp/isearch-tests.el b/test/lisp/isearch-tests.el
index b2981c0cc08..8cb5e5e4542 100644
--- a/test/lisp/isearch-tests.el
+++ b/test/lisp/isearch-tests.el
@@ -1,21 +1,23 @@
;;; isearch-tests.el --- Tests for isearch.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2013-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2022 Free Software Foundation, Inc.
;; Author: Artur Malabarba <bruce.connor.am@gmail.com>
-;; This program is free software; you can redistribute it and/or modify
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
-;; This program is distributed in the hope that it will be useful,
+;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
-;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Code:
@@ -36,5 +38,85 @@
;; Bug #21091: let `isearch-done' work without `isearch-update'.
(isearch-done))
+
+;; Search functions.
+
+(defun isearch--test-search-within-boundaries (pairs)
+ (goto-char (point-min))
+ (let ((isearch-forward t)
+ (isearch-regexp nil))
+ (dolist (pos (append pairs nil))
+ (should (eq (cdr pos) (isearch-search-string "foo" nil t)))
+ (should (equal (match-string 0) "foo"))
+ (when (car pos) (should (eq (car pos) (match-beginning 0))))))
+
+ (goto-char (point-max))
+ (let ((isearch-forward nil)
+ (isearch-regexp nil))
+ (dolist (pos (append (reverse pairs) nil))
+ (should (eq (car pos) (isearch-search-string "foo" nil t)))
+ (should (equal (match-string 0) "foo"))
+ (when (cdr pos) (should (eq (cdr pos) (match-end 0))))))
+
+ (goto-char (point-min))
+ (let ((isearch-forward t)
+ (isearch-regexp t))
+ (dolist (pos (append pairs nil))
+ (should (eq (cdr pos) (isearch-search-string ".*" nil t)))
+ (should (equal (match-string 0) "foo"))
+ (when (car pos) (should (eq (car pos) (match-beginning 0))))))
+
+ (goto-char (point-min))
+ (let ((isearch-forward t)
+ (isearch-regexp t))
+ (dolist (pos (append pairs nil))
+ (should (eq (cdr pos) (isearch-search-string "^.*" nil t)))
+ (should (equal (match-string 0) "foo"))
+ (when (car pos) (should (eq (car pos) (match-beginning 0))))))
+
+ (goto-char (point-min))
+ (let ((isearch-forward t)
+ (isearch-regexp t))
+ (dolist (pos (append pairs nil))
+ (should (eq (cdr pos) (isearch-search-string ".*$" nil t)))
+ (should (equal (match-string 0) "foo"))
+ (when (car pos) (should (eq (car pos) (match-beginning 0))))))
+
+ (goto-char (point-max))
+ (let ((isearch-forward nil)
+ (isearch-regexp t))
+ (dolist (pos (append (reverse pairs) nil))
+ (should (eq (car pos) (isearch-search-string "^.*" nil t)))
+ (should (equal (match-string 0) "foo"))
+ (when (cdr pos) (should (eq (cdr pos) (match-end 0))))))
+
+ (goto-char (point-max))
+ (let ((isearch-forward nil)
+ (isearch-regexp t))
+ (dolist (pos (append (reverse pairs) nil))
+ (should (eq (car pos) (isearch-search-string "foo$" nil t)))
+ (should (equal (match-string 0) "foo"))
+ (when (cdr pos) (should (eq (cdr pos) (match-end 0)))))))
+
+(ert-deftest isearch--test-search-fun-in-text-property ()
+ (let* ((pairs '((4 . 7) (11 . 14) (21 . 24)))
+ (isearch-search-fun-function
+ (lambda () (isearch-search-fun-in-text-property nil 'dired-filename))))
+ (with-temp-buffer
+ (insert "foo" (propertize "foo" 'dired-filename t) "foo\n")
+ (insert (propertize "foo" 'dired-filename t) "foo\n")
+ (insert "foo" (propertize "foo" 'dired-filename t) "\n")
+ (isearch--test-search-within-boundaries pairs))))
+
+(ert-deftest isearch--test-search-fun-in-noncontiguous-region ()
+ (let* ((pairs '((4 . 7) (11 . 14) (21 . 24)))
+ (isearch-search-fun-function
+ (lambda () (isearch-search-fun-in-noncontiguous-region nil pairs))))
+ (with-temp-buffer
+ (insert "foofoofoo\n")
+ (insert "foofoo\n")
+ (insert "foofoo\n")
+ (isearch--test-search-within-boundaries pairs))))
+
(provide 'isearch-tests)
;;; isearch-tests.el ends here
diff --git a/test/lisp/jit-lock-tests.el b/test/lisp/jit-lock-tests.el
index 5847eac6998..190825d325e 100644
--- a/test/lisp/jit-lock-tests.el
+++ b/test/lisp/jit-lock-tests.el
@@ -1,6 +1,6 @@
-;;; jit-lock-tests.el --- tests for jit-lock
+;;; jit-lock-tests.el --- tests for jit-lock -*- lexical-binding:t -*-
-;; Copyright (C) 2016-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2022 Free Software Foundation, Inc.
;; Author: Dmitry Gutov <dgutov@yandex.ru>
@@ -58,3 +58,5 @@
(with-silent-modifications
(put-text-property (point-min) (point-max) 'fontified t))
(jit-lock-fontify-now (point-min) (point-max))))
+
+;;; jit-lock-tests.el ends here
diff --git a/test/lisp/json-tests.el b/test/lisp/json-tests.el
index fe5f466bd76..ab1f19fb6e7 100644
--- a/test/lisp/json-tests.el
+++ b/test/lisp/json-tests.el
@@ -1,31 +1,38 @@
-;;; json-tests.el --- Test suite for json.el
+;;; json-tests.el --- Test suite for json.el -*- lexical-binding:t -*-
-;; Copyright (C) 2015-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2022 Free Software Foundation, Inc.
;; Author: Dmitry Gutov <dgutov@yandex.ru>
-;; This program is free software; you can redistribute it and/or modify
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
-;; This program is distributed in the hope that it will be useful,
+;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
-;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Code:
(require 'ert)
(require 'json)
+(require 'map)
+(require 'seq)
+
+(eval-when-compile
+ (require 'cl-lib))
(defmacro json-tests--with-temp-buffer (content &rest body)
"Create a temporary buffer with CONTENT and evaluate BODY there.
Point is moved to beginning of the buffer."
- (declare (indent 1))
+ (declare (debug t) (indent 1))
`(with-temp-buffer
(insert ,content)
(goto-char (point-min))
@@ -33,66 +40,107 @@ Point is moved to beginning of the buffer."
;;; Utilities
-(ert-deftest test-json-join ()
- (should (equal (json-join '() ", ") ""))
- (should (equal (json-join '("a" "b" "c") ", ") "a, b, c")))
-
(ert-deftest test-json-alist-p ()
(should (json-alist-p '()))
- (should (json-alist-p '((a 1) (b 2) (c 3))))
- (should (json-alist-p '((:a 1) (:b 2) (:c 3))))
- (should (json-alist-p '(("a" 1) ("b" 2) ("c" 3))))
+ (should (json-alist-p '((()))))
+ (should (json-alist-p '((a))))
+ (should (json-alist-p '((a . 1))))
+ (should (json-alist-p '((a . 1) (b 2) (c))))
+ (should (json-alist-p '((:a) (:b 2) (:c . 3))))
+ (should (json-alist-p '(("a" . 1) ("b" 2) ("c"))))
+ (should-not (json-alist-p '(())))
+ (should-not (json-alist-p '(a)))
+ (should-not (json-alist-p '(a . 1)))
+ (should-not (json-alist-p '((a . 1) . [])))
+ (should-not (json-alist-p '((a . 1) [])))
(should-not (json-alist-p '(:a :b :c)))
(should-not (json-alist-p '(:a 1 :b 2 :c 3)))
- (should-not (json-alist-p '((:a 1) (:b 2) 3))))
+ (should-not (json-alist-p '((:a 1) (:b 2) 3)))
+ (should-not (json-alist-p '((:a 1) (:b 2) ())))
+ (should-not (json-alist-p '(((a) 1) (b 2) (c 3))))
+ (should-not (json-alist-p []))
+ (should-not (json-alist-p [(a . 1)]))
+ (should-not (json-alist-p #s(hash-table))))
(ert-deftest test-json-plist-p ()
(should (json-plist-p '()))
+ (should (json-plist-p '(:a 1)))
(should (json-plist-p '(:a 1 :b 2 :c 3)))
+ (should (json-plist-p '(:a :b)))
+ (should (json-plist-p '(:a :b :c :d)))
+ (should-not (json-plist-p '(a)))
+ (should-not (json-plist-p '(a 1)))
(should-not (json-plist-p '(a 1 b 2 c 3)))
(should-not (json-plist-p '("a" 1 "b" 2 "c" 3)))
+ (should-not (json-plist-p '(:a)))
(should-not (json-plist-p '(:a :b :c)))
- (should-not (json-plist-p '((:a 1) (:b 2) (:c 3)))))
+ (should-not (json-plist-p '(:a 1 :b 2 :c)))
+ (should-not (json-plist-p '((:a 1))))
+ (should-not (json-plist-p '((:a 1) (:b 2) (:c 3))))
+ (should-not (json-plist-p []))
+ (should-not (json-plist-p [:a 1]))
+ (should-not (json-plist-p #s(hash-table))))
-(ert-deftest test-json-plist-reverse ()
- (should (equal (json--plist-reverse '()) '()))
- (should (equal (json--plist-reverse '(:a 1)) '(:a 1)))
- (should (equal (json--plist-reverse '(:a 1 :b 2 :c 3))
+(ert-deftest test-json-plist-nreverse ()
+ (should (equal (json--plist-nreverse '()) '()))
+ (should (equal (json--plist-nreverse (list :a 1)) '(:a 1)))
+ (should (equal (json--plist-nreverse (list :a 1 :b 2)) '(:b 2 :a 1)))
+ (should (equal (json--plist-nreverse (list :a 1 :b 2 :c 3))
'(:c 3 :b 2 :a 1))))
-(ert-deftest test-json-plist-to-alist ()
- (should (equal (json--plist-to-alist '()) '()))
- (should (equal (json--plist-to-alist '(:a 1)) '((:a . 1))))
- (should (equal (json--plist-to-alist '(:a 1 :b 2 :c 3))
- '((:a . 1) (:b . 2) (:c . 3)))))
-
(ert-deftest test-json-advance ()
(json-tests--with-temp-buffer "{ \"a\": 1 }"
(json-advance 0)
- (should (= (point) (point-min)))
+ (should (bobp))
+ (json-advance)
+ (should (= (point) (1+ (point-min))))
+ (json-advance 0)
+ (should (= (point) (1+ (point-min))))
+ (json-advance 1)
+ (should (= (point) (+ (point-min) 2)))
(json-advance 3)
- (should (= (point) (+ (point-min) 3)))))
+ (should (= (point) (+ (point-min) 5)))))
(ert-deftest test-json-peek ()
(json-tests--with-temp-buffer ""
(should (zerop (json-peek))))
(json-tests--with-temp-buffer "{ \"a\": 1 }"
- (should (equal (json-peek) ?{))))
+ (should (= (json-peek) ?\{))
+ (goto-char (1- (point-max)))
+ (should (= (json-peek) ?\}))
+ (json-advance)
+ (should (zerop (json-peek)))))
(ert-deftest test-json-pop ()
(json-tests--with-temp-buffer ""
(should-error (json-pop) :type 'json-end-of-file))
(json-tests--with-temp-buffer "{ \"a\": 1 }"
- (should (equal (json-pop) ?{))
- (should (= (point) (+ (point-min) 1)))))
+ (should (= (json-pop) ?\{))
+ (should (= (point) (1+ (point-min))))
+ (goto-char (1- (point-max)))
+ (should (= (json-pop) ?\}))
+ (should-error (json-pop) :type 'json-end-of-file)))
(ert-deftest test-json-skip-whitespace ()
+ (json-tests--with-temp-buffer ""
+ (json-skip-whitespace)
+ (should (bobp))
+ (should (eobp)))
+ (json-tests--with-temp-buffer "{}"
+ (json-skip-whitespace)
+ (should (bobp))
+ (json-advance)
+ (json-skip-whitespace)
+ (should (= (point) (1+ (point-min))))
+ (json-advance)
+ (json-skip-whitespace)
+ (should (eobp)))
(json-tests--with-temp-buffer "\t\r\n\f\b { \"a\": 1 }"
(json-skip-whitespace)
- (should (equal (char-after) ?\f)))
+ (should (= (json-peek) ?\f)))
(json-tests--with-temp-buffer "\t\r\n\t { \"a\": 1 }"
(json-skip-whitespace)
- (should (equal (char-after) ?{))))
+ (should (= (json-peek) ?\{))))
;;; Paths
@@ -113,119 +161,381 @@ Point is moved to beginning of the buffer."
(ert-deftest test-json-path-to-position-no-match ()
(let* ((json-string "{\"foo\": {\"bar\": \"baz\"}}")
(matched-path (json-path-to-position 5 json-string)))
- (should (null matched-path))))
+ (should-not matched-path)))
;;; Keywords
(ert-deftest test-json-read-keyword ()
(json-tests--with-temp-buffer "true"
- (should (json-read-keyword "true")))
+ (should (eq (json-read-keyword "true") t))
+ (should (eobp)))
+ (json-tests--with-temp-buffer "true "
+ (should (eq (json-read-keyword "true") t))
+ (should (eobp)))
+ (json-tests--with-temp-buffer "true}"
+ (should (eq (json-read-keyword "true") t))
+ (should (= (point) (+ (point-min) 4))))
+ (json-tests--with-temp-buffer "true false"
+ (should (eq (json-read-keyword "true") t))
+ (should (= (point) (+ (point-min) 5))))
+ (json-tests--with-temp-buffer "true }"
+ (should (eq (json-read-keyword "true") t))
+ (should (= (point) (+ (point-min) 5))))
+ (json-tests--with-temp-buffer "true |"
+ (should (eq (json-read-keyword "true") t))
+ (should (= (point) (+ (point-min) 5))))
+ (json-tests--with-temp-buffer "false"
+ (let ((json-false 'false))
+ (should (eq (json-read-keyword "false") 'false)))
+ (should (eobp)))
+ (json-tests--with-temp-buffer "null"
+ (let ((json-null 'null))
+ (should (eq (json-read-keyword "null") 'null)))
+ (should (eobp))))
+
+(ert-deftest test-json-read-keyword-invalid ()
+ (json-tests--with-temp-buffer ""
+ (should (equal (should-error (json-read-keyword ""))
+ '(json-unknown-keyword "")))
+ (should (equal (should-error (json-read-keyword "true"))
+ '(json-unknown-keyword ()))))
(json-tests--with-temp-buffer "true"
- (should-error
- (json-read-keyword "false") :type 'json-unknown-keyword))
+ (should (equal (should-error (json-read-keyword "false"))
+ '(json-unknown-keyword "true"))))
(json-tests--with-temp-buffer "foo"
- (should-error
- (json-read-keyword "foo") :type 'json-unknown-keyword)))
+ (should (equal (should-error (json-read-keyword "foo"))
+ '(json-unknown-keyword "foo")))
+ (should (equal (should-error (json-read-keyword "bar"))
+ '(json-unknown-keyword "bar"))))
+ (json-tests--with-temp-buffer " true"
+ (should (equal (should-error (json-read-keyword "true"))
+ '(json-unknown-keyword ()))))
+ (json-tests--with-temp-buffer "truefalse"
+ (should (equal (should-error (json-read-keyword "true"))
+ '(json-unknown-keyword "truefalse"))))
+ (json-tests--with-temp-buffer "true|"
+ (should (equal (should-error (json-read-keyword "true"))
+ '(json-unknown-keyword "true")))))
(ert-deftest test-json-encode-keyword ()
(should (equal (json-encode-keyword t) "true"))
- (should (equal (json-encode-keyword json-false) "false"))
- (should (equal (json-encode-keyword json-null) "null")))
+ (let ((json-false 'false))
+ (should (equal (json-encode-keyword 'false) "false"))
+ (should (equal (json-encode-keyword json-false) "false")))
+ (let ((json-null 'null))
+ (should (equal (json-encode-keyword 'null) "null"))
+ (should (equal (json-encode-keyword json-null) "null"))))
;;; Numbers
-(ert-deftest test-json-read-number ()
- (json-tests--with-temp-buffer "3"
- (should (= (json-read-number) 3)))
- (json-tests--with-temp-buffer "-5"
- (should (= (json-read-number) -5)))
- (json-tests--with-temp-buffer "123.456"
- (should (= (json-read-number) 123.456)))
- (json-tests--with-temp-buffer "1e3"
- (should (= (json-read-number) 1e3)))
- (json-tests--with-temp-buffer "2e+3"
- (should (= (json-read-number) 2e3)))
- (json-tests--with-temp-buffer "3E3"
- (should (= (json-read-number) 3e3)))
- (json-tests--with-temp-buffer "1e-7"
- (should (= (json-read-number) 1e-7)))
- (json-tests--with-temp-buffer "abc"
- (should-error (json-read-number) :type 'json-number-format)))
+(ert-deftest test-json-read-integer ()
+ (json-tests--with-temp-buffer "0 "
+ (should (= (json-read-number) 0))
+ (should (eobp)))
+ (json-tests--with-temp-buffer "-0 "
+ (should (= (json-read-number) 0))
+ (should (eobp)))
+ (json-tests--with-temp-buffer "3 "
+ (should (= (json-read-number) 3))
+ (should (eobp)))
+ (json-tests--with-temp-buffer "-10 "
+ (should (= (json-read-number) -10))
+ (should (eobp)))
+ (json-tests--with-temp-buffer (format "%d " (1+ most-positive-fixnum))
+ (should (= (json-read-number) (1+ most-positive-fixnum)))
+ (should (eobp)))
+ (json-tests--with-temp-buffer (format "%d " (1- most-negative-fixnum))
+ (should (= (json-read-number) (1- most-negative-fixnum)))
+ (should (eobp))))
+
+(ert-deftest test-json-read-fraction ()
+ (json-tests--with-temp-buffer "0.0 "
+ (should (= (json-read-number) 0.0))
+ (should (eobp)))
+ (json-tests--with-temp-buffer "-0.0 "
+ (should (= (json-read-number) 0.0))
+ (should (eobp)))
+ (json-tests--with-temp-buffer "0.01 "
+ (should (= (json-read-number) 0.01))
+ (should (eobp)))
+ (json-tests--with-temp-buffer "-0.01 "
+ (should (= (json-read-number) -0.01))
+ (should (eobp)))
+ (json-tests--with-temp-buffer "123.456 "
+ (should (= (json-read-number) 123.456))
+ (should (eobp)))
+ (json-tests--with-temp-buffer "-123.456 "
+ (should (= (json-read-number) -123.456))
+ (should (eobp))))
+
+(ert-deftest test-json-read-exponent ()
+ (json-tests--with-temp-buffer "0e0 "
+ (should (= (json-read-number) 0e0))
+ (should (eobp)))
+ (json-tests--with-temp-buffer "-0E0 "
+ (should (= (json-read-number) 0e0))
+ (should (eobp)))
+ (json-tests--with-temp-buffer "-0E+0 "
+ (should (= (json-read-number) 0e0))
+ (should (eobp)))
+ (json-tests--with-temp-buffer "0e-0 "
+ (should (= (json-read-number) 0e0))
+ (should (eobp)))
+ (json-tests--with-temp-buffer "12e34 "
+ (should (= (json-read-number) 12e34))
+ (should (eobp)))
+ (json-tests--with-temp-buffer "-12E34 "
+ (should (= (json-read-number) -12e34))
+ (should (eobp)))
+ (json-tests--with-temp-buffer "-12E+34 "
+ (should (= (json-read-number) -12e34))
+ (should (eobp)))
+ (json-tests--with-temp-buffer "12e-34 "
+ (should (= (json-read-number) 12e-34))
+ (should (eobp))))
+
+(ert-deftest test-json-read-fraction-exponent ()
+ (json-tests--with-temp-buffer "0.0e0 "
+ (should (= (json-read-number) 0.0e0))
+ (should (eobp)))
+ (json-tests--with-temp-buffer "-0.0E0 "
+ (should (= (json-read-number) 0.0e0))
+ (should (eobp)))
+ (json-tests--with-temp-buffer "0.12E-0 "
+ (should (= (json-read-number) 0.12e0))
+ (should (eobp)))
+ (json-tests--with-temp-buffer "-12.34e+56 "
+ (should (= (json-read-number) -12.34e+56))
+ (should (eobp))))
+
+(ert-deftest test-json-read-number-invalid ()
+ (cl-flet ((read (str)
+ ;; Return error and point resulting from reading STR.
+ (json-tests--with-temp-buffer str
+ (cons (should-error (json-read-number)) (point)))))
+ ;; POS is where each of its STRINGS becomes invalid.
+ (pcase-dolist (`(,pos . ,strings)
+ '((1 "" "+" "-" "." "e" "e1" "abc" "++0" "++1"
+ "+0" "+0.0" "+12" "+12.34" "+12.34e56"
+ ".0" "+.0" "-.0" ".12" "+.12" "-.12"
+ ".e0" "+.e0" "-.e0" ".0e0" "+.0e0" "-.0e0")
+ (2 "01" "1ee1" "1e++1")
+ (3 "-01")
+ (4 "0.0.0" "1.1.1" "1e1e1")
+ (5 "-0.0.0" "-1.1.1")))
+ ;; Expected error and point.
+ (let ((res `((json-number-format ,pos) . ,pos)))
+ (dolist (str strings)
+ (should (equal (read str) res)))))))
(ert-deftest test-json-encode-number ()
- (should (equal (json-encode-number 3) "3"))
- (should (equal (json-encode-number -5) "-5"))
- (should (equal (json-encode-number 123.456) "123.456")))
+ (should (equal (json-encode 0) "0"))
+ (should (equal (json-encode -0) "0"))
+ (should (equal (json-encode 3) "3"))
+ (should (equal (json-encode -5) "-5"))
+ (should (equal (json-encode 123.456) "123.456"))
+ (let ((bignum (1+ most-positive-fixnum)))
+ (should (equal (json-encode bignum)
+ (number-to-string bignum)))))
-;; Strings
+;;; Strings
(ert-deftest test-json-read-escaped-char ()
(json-tests--with-temp-buffer "\\\""
- (should (equal (json-read-escaped-char) ?\"))))
+ (should (= (json-read-escaped-char) ?\"))
+ (should (eobp)))
+ (json-tests--with-temp-buffer "\\\\ "
+ (should (= (json-read-escaped-char) ?\\))
+ (should (= (point) (+ (point-min) 2))))
+ (json-tests--with-temp-buffer "\\b "
+ (should (= (json-read-escaped-char) ?\b))
+ (should (= (point) (+ (point-min) 2))))
+ (json-tests--with-temp-buffer "\\f "
+ (should (= (json-read-escaped-char) ?\f))
+ (should (= (point) (+ (point-min) 2))))
+ (json-tests--with-temp-buffer "\\n "
+ (should (= (json-read-escaped-char) ?\n))
+ (should (= (point) (+ (point-min) 2))))
+ (json-tests--with-temp-buffer "\\r "
+ (should (= (json-read-escaped-char) ?\r))
+ (should (= (point) (+ (point-min) 2))))
+ (json-tests--with-temp-buffer "\\t "
+ (should (= (json-read-escaped-char) ?\t))
+ (should (= (point) (+ (point-min) 2))))
+ (json-tests--with-temp-buffer "\\x "
+ (should (= (json-read-escaped-char) ?x))
+ (should (= (point) (+ (point-min) 2))))
+ (json-tests--with-temp-buffer "\\ud800\\uDC00 "
+ (should (= (json-read-escaped-char) #x10000))
+ (should (= (point) (+ (point-min) 12))))
+ (json-tests--with-temp-buffer "\\ud7ff\\udc00 "
+ (should (= (json-read-escaped-char) #xd7ff))
+ (should (= (point) (+ (point-min) 6))))
+ (json-tests--with-temp-buffer "\\uffff "
+ (should (= (json-read-escaped-char) #xffff))
+ (should (= (point) (+ (point-min) 6))))
+ (json-tests--with-temp-buffer "\\ufffff "
+ (should (= (json-read-escaped-char) #xffff))
+ (should (= (point) (+ (point-min) 6)))))
+
+(ert-deftest test-json-read-escaped-char-invalid ()
+ (json-tests--with-temp-buffer ""
+ (should-error (json-read-escaped-char)))
+ (json-tests--with-temp-buffer "\\"
+ (should-error (json-read-escaped-char) :type 'json-end-of-file))
+ (json-tests--with-temp-buffer "\\ufff "
+ (should (equal (should-error (json-read-escaped-char))
+ (list 'json-string-escape (+ (point-min) 2)))))
+ (json-tests--with-temp-buffer "\\ufffg "
+ (should (equal (should-error (json-read-escaped-char))
+ (list 'json-string-escape (+ (point-min) 2))))))
(ert-deftest test-json-read-string ()
+ (json-tests--with-temp-buffer ""
+ (should-error (json-read-string)))
(json-tests--with-temp-buffer "\"formfeed\f\""
- (should-error (json-read-string) :type 'json-string-format))
+ (should (equal (should-error (json-read-string))
+ '(json-string-format ?\f))))
+ (json-tests--with-temp-buffer "\"\""
+ (should (equal (json-read-string) "")))
(json-tests--with-temp-buffer "\"foo \\\"bar\\\"\""
(should (equal (json-read-string) "foo \"bar\"")))
(json-tests--with-temp-buffer "\"abcαβγ\""
(should (equal (json-read-string) "abcαβγ")))
(json-tests--with-temp-buffer "\"\\nasd\\u0444\\u044b\\u0432fgh\\t\""
(should (equal (json-read-string) "\nasdфывfgh\t")))
+ (json-tests--with-temp-buffer "\"abc\uFFFFαβγ𝔸𝐁𝖢\\\"\\\\\""
+ (should (equal (json-read-string) "abc\uFFFFαβγ𝔸𝐁𝖢\"\\")))
;; Bug#24784
(json-tests--with-temp-buffer "\"\\uD834\\uDD1E\""
(should (equal (json-read-string) "\U0001D11E")))
+ (json-tests--with-temp-buffer "f"
+ (should-error (json-read-string) :type 'json-end-of-file))
(json-tests--with-temp-buffer "foo"
- (should-error (json-read-string) :type 'json-string-format)))
+ (should-error (json-read-string) :type 'json-end-of-file)))
(ert-deftest test-json-encode-string ()
+ (should (equal (json-encode-string "") "\"\""))
+ (should (equal (json-encode-string "a") "\"a\""))
(should (equal (json-encode-string "foo") "\"foo\""))
(should (equal (json-encode-string "a\n\fb") "\"a\\n\\fb\""))
(should (equal (json-encode-string "\nasdфыв\u001f\u007ffgh\t")
- "\"\\nasdфыв\\u001f\u007ffgh\\t\"")))
+ "\"\\nasdфыв\\u001f\u007ffgh\\t\""))
+ ;; Bug#43549.
+ (should (equal (json-encode-string (propertize "foo" 'read-only t))
+ "\"foo\""))
+ (should (equal (json-encode-string "a\0b") "\"a\\u0000b\""))
+ (should (equal (json-encode-string "abc\uFFFFαβγ𝔸𝐁𝖢\"\\")
+ "\"abc\uFFFFαβγ𝔸𝐁𝖢\\\"\\\\\"")))
(ert-deftest test-json-encode-key ()
- (should (equal (json-encode-key "foo") "\"foo\""))
- (should (equal (json-encode-key 'foo) "\"foo\""))
- (should (equal (json-encode-key :foo) "\"foo\""))
- (should-error (json-encode-key 5) :type 'json-key-format)
- (should-error (json-encode-key ["foo"]) :type 'json-key-format)
- (should-error (json-encode-key '("foo")) :type 'json-key-format))
+ (with-suppressed-warnings ((obsolete json-encode-key))
+ (should (equal (json-encode-key '##) "\"\""))
+ (should (equal (json-encode-key :) "\"\""))
+ (should (equal (json-encode-key "") "\"\""))
+ (should (equal (json-encode-key 'a) "\"a\""))
+ (should (equal (json-encode-key :a) "\"a\""))
+ (should (equal (json-encode-key "a") "\"a\""))
+ (should (equal (json-encode-key t) "\"t\""))
+ (should (equal (json-encode-key :t) "\"t\""))
+ (should (equal (json-encode-key "t") "\"t\""))
+ (should (equal (json-encode-key nil) "\"nil\""))
+ (should (equal (json-encode-key :nil) "\"nil\""))
+ (should (equal (json-encode-key "nil") "\"nil\""))
+ (should (equal (json-encode-key ":a") "\":a\""))
+ (should (equal (json-encode-key ":t") "\":t\""))
+ (should (equal (json-encode-key ":nil") "\":nil\""))
+ (should (equal (should-error (json-encode-key 5))
+ '(json-key-format 5)))
+ (should (equal (should-error (json-encode-key ["foo"]))
+ '(json-key-format ["foo"])))
+ (should (equal (should-error (json-encode-key '("foo")))
+ '(json-key-format ("foo"))))))
;;; Objects
(ert-deftest test-json-new-object ()
(let ((json-object-type 'alist))
- (should (equal (json-new-object) '())))
+ (should-not (json-new-object)))
(let ((json-object-type 'plist))
- (should (equal (json-new-object) '())))
+ (should-not (json-new-object)))
(let* ((json-object-type 'hash-table)
(json-object (json-new-object)))
(should (hash-table-p json-object))
- (should (= (hash-table-count json-object) 0))))
+ (should (map-empty-p json-object))
+ (should (eq (hash-table-test json-object) #'equal))))
-(ert-deftest test-json-add-to-object ()
+(ert-deftest test-json-add-to-alist ()
(let* ((json-object-type 'alist)
- (json-key-type nil)
(obj (json-new-object)))
- (setq obj (json-add-to-object obj "a" 1))
- (setq obj (json-add-to-object obj "b" 2))
- (should (equal (assq 'a obj) '(a . 1)))
- (should (equal (assq 'b obj) '(b . 2))))
+ (let ((json-key-type nil))
+ (setq obj (json-add-to-object obj "a" 1))
+ (setq obj (json-add-to-object obj "b" 2))
+ (should (equal (assq 'a obj) '(a . 1)))
+ (should (equal (assq 'b obj) '(b . 2))))
+ (let ((json-key-type 'symbol))
+ (setq obj (json-add-to-object obj "c" 3))
+ (setq obj (json-add-to-object obj "d" 4))
+ (should (equal (assq 'c obj) '(c . 3)))
+ (should (equal (assq 'd obj) '(d . 4))))
+ (let ((json-key-type 'keyword))
+ (setq obj (json-add-to-object obj "e" 5))
+ (setq obj (json-add-to-object obj "f" 6))
+ (should (equal (assq :e obj) '(:e . 5)))
+ (should (equal (assq :f obj) '(:f . 6))))
+ (let ((json-key-type 'string))
+ (setq obj (json-add-to-object obj "g" 7))
+ (setq obj (json-add-to-object obj "h" 8))
+ (should (equal (assoc "g" obj) '("g" . 7)))
+ (should (equal (assoc "h" obj) '("h" . 8))))))
+
+(ert-deftest test-json-add-to-plist ()
(let* ((json-object-type 'plist)
- (json-key-type nil)
(obj (json-new-object)))
- (setq obj (json-add-to-object obj "a" 1))
- (setq obj (json-add-to-object obj "b" 2))
- (should (= (plist-get obj :a) 1))
- (should (= (plist-get obj :b) 2)))
+ (let ((json-key-type nil))
+ (setq obj (json-add-to-object obj "a" 1))
+ (setq obj (json-add-to-object obj "b" 2))
+ (should (= (plist-get obj :a) 1))
+ (should (= (plist-get obj :b) 2)))
+ (let ((json-key-type 'keyword))
+ (setq obj (json-add-to-object obj "c" 3))
+ (setq obj (json-add-to-object obj "d" 4))
+ (should (= (plist-get obj :c) 3))
+ (should (= (plist-get obj :d) 4)))
+ (let ((json-key-type 'symbol))
+ (setq obj (json-add-to-object obj "e" 5))
+ (setq obj (json-add-to-object obj "f" 6))
+ (should (= (plist-get obj 'e) 5))
+ (should (= (plist-get obj 'f) 6)))
+ (let ((json-key-type 'string))
+ (setq obj (json-add-to-object obj "g" 7))
+ (setq obj (json-add-to-object obj "h" 8))
+ (should (= (plist-get obj "g" #'equal) 7))
+ (should (= (plist-get obj "h" #'equal) 8)))))
+
+(ert-deftest test-json-add-to-hash-table ()
(let* ((json-object-type 'hash-table)
- (json-key-type nil)
(obj (json-new-object)))
- (setq obj (json-add-to-object obj "a" 1))
- (setq obj (json-add-to-object obj "b" 2))
- (should (= (gethash "a" obj) 1))
- (should (= (gethash "b" obj) 2))))
+ (let ((json-key-type nil))
+ (setq obj (json-add-to-object obj "a" 1))
+ (setq obj (json-add-to-object obj "b" 2))
+ (should (= (gethash "a" obj) 1))
+ (should (= (gethash "b" obj) 2)))
+ (let ((json-key-type 'string))
+ (setq obj (json-add-to-object obj "c" 3))
+ (setq obj (json-add-to-object obj "d" 4))
+ (should (= (gethash "c" obj) 3))
+ (should (= (gethash "d" obj) 4)))
+ (let ((json-key-type 'symbol))
+ (setq obj (json-add-to-object obj "e" 5))
+ (setq obj (json-add-to-object obj "f" 6))
+ (should (= (gethash 'e obj) 5))
+ (should (= (gethash 'f obj) 6)))
+ (let ((json-key-type 'keyword))
+ (setq obj (json-add-to-object obj "g" 7))
+ (setq obj (json-add-to-object obj "h" 8))
+ (should (= (gethash :g obj) 7))
+ (should (= (gethash :h obj) 8)))))
(ert-deftest test-json-read-object ()
(json-tests--with-temp-buffer "{ \"a\": 1, \"b\": 2 }"
@@ -238,91 +548,491 @@ Point is moved to beginning of the buffer."
(let* ((json-object-type 'hash-table)
(hash-table (json-read-object)))
(should (= (gethash "a" hash-table) 1))
- (should (= (gethash "b" hash-table) 2))))
+ (should (= (gethash "b" hash-table) 2)))))
+
+(ert-deftest test-json-read-object-empty ()
+ (json-tests--with-temp-buffer "{}"
+ (let ((json-object-type 'alist))
+ (should-not (save-excursion (json-read-object))))
+ (let ((json-object-type 'plist))
+ (should-not (save-excursion (json-read-object))))
+ (let* ((json-object-type 'hash-table)
+ (hash-table (json-read-object)))
+ (should (hash-table-p hash-table))
+ (should (map-empty-p hash-table)))))
+
+(ert-deftest test-json-read-object-invalid ()
+ (json-tests--with-temp-buffer "{ \"a\" 1, \"b\": 2 }"
+ (should (equal (should-error (json-read-object))
+ '(json-object-format ":" ?1))))
(json-tests--with-temp-buffer "{ \"a\": 1 \"b\": 2 }"
- (should-error (json-read-object) :type 'json-object-format)))
+ (should (equal (should-error (json-read-object))
+ '(json-object-format "," ?\")))))
+
+(ert-deftest test-json-read-object-function ()
+ (let* ((pre nil)
+ (post nil)
+ (keys '("b" "a"))
+ (json-pre-element-read-function
+ (lambda (key)
+ (setq pre 'pre)
+ (should (equal key (pop keys)))))
+ (json-post-element-read-function
+ (lambda () (setq post 'post))))
+ (json-tests--with-temp-buffer "{ \"b\": 2, \"a\": 1 }"
+ (json-read-object)
+ (should (eq pre 'pre))
+ (should (eq post 'post)))))
(ert-deftest test-json-encode-hash-table ()
- (let ((hash-table (make-hash-table))
- (json-encoding-object-sort-predicate 'string<)
+ (let ((json-encoding-object-sort-predicate nil)
(json-encoding-pretty-print nil))
- (puthash :a 1 hash-table)
- (puthash :b 2 hash-table)
- (puthash :c 3 hash-table)
- (should (equal (json-encode hash-table)
- "{\"a\":1,\"b\":2,\"c\":3}"))))
+ (should (equal (json-encode #s(hash-table)) "{}"))
+ (should (equal (json-encode #s(hash-table data (a 1))) "{\"a\":1}"))
+ (should (equal (json-encode #s(hash-table data (t 1))) "{\"t\":1}"))
+ (should (equal (json-encode #s(hash-table data (nil 1))) "{\"nil\":1}"))
+ (should (equal (json-encode #s(hash-table data (:a 1))) "{\"a\":1}"))
+ (should (equal (json-encode #s(hash-table data (:t 1))) "{\"t\":1}"))
+ (should (equal (json-encode #s(hash-table data (:nil 1))) "{\"nil\":1}"))
+ (should (equal (json-encode #s(hash-table test equal data ("a" 1)))
+ "{\"a\":1}"))
+ (should (equal (json-encode #s(hash-table test equal data ("t" 1)))
+ "{\"t\":1}"))
+ (should (equal (json-encode #s(hash-table test equal data ("nil" 1)))
+ "{\"nil\":1}"))
+ (should (equal (json-encode #s(hash-table test equal data (":a" 1)))
+ "{\":a\":1}"))
+ (should (equal (json-encode #s(hash-table test equal data (":t" 1)))
+ "{\":t\":1}"))
+ (should (equal (json-encode #s(hash-table test equal data (":nil" 1)))
+ "{\":nil\":1}"))
+ (should (member (json-encode #s(hash-table data (t 2 :nil 1)))
+ '("{\"nil\":1,\"t\":2}" "{\"t\":2,\"nil\":1}")))
+ (should (member (json-encode #s(hash-table test equal data (:t 2 ":t" 1)))
+ '("{\":t\":1,\"t\":2}" "{\"t\":2,\":t\":1}")))
+ (should (member (json-encode #s(hash-table data (b 2 a 1)))
+ '("{\"a\":1,\"b\":2}" "{\"b\":2,\"a\":1}")))
+ (should (member (json-encode #s(hash-table data (c 3 b 2 a 1)))
+ '("{\"a\":1,\"b\":2,\"c\":3}"
+ "{\"a\":1,\"c\":3,\"b\":2}"
+ "{\"b\":2,\"a\":1,\"c\":3}"
+ "{\"b\":2,\"c\":3,\"a\":1}"
+ "{\"c\":3,\"a\":1,\"b\":2}"
+ "{\"c\":3,\"b\":2,\"a\":1}")))))
-(ert-deftest json-encode-simple-alist ()
- (let ((json-encoding-pretty-print nil))
- (should (equal (json-encode '((a . 1) (b . 2)))
- "{\"a\":1,\"b\":2}"))))
+(ert-deftest test-json-encode-hash-table-pretty ()
+ (let ((json-encoding-object-sort-predicate nil)
+ (json-encoding-pretty-print t)
+ (json-encoding-default-indentation " ")
+ (json-encoding-lisp-style-closings nil))
+ (should (equal (json-encode #s(hash-table)) "{}"))
+ (should (equal (json-encode #s(hash-table data (a 1))) "{\n \"a\": 1\n}"))
+ (should (member (json-encode #s(hash-table data (b 2 a 1)))
+ '("{\n \"a\": 1,\n \"b\": 2\n}"
+ "{\n \"b\": 2,\n \"a\": 1\n}")))
+ (should (member (json-encode #s(hash-table data (c 3 b 2 a 1)))
+ '("{\n \"a\": 1,\n \"b\": 2,\n \"c\": 3\n}"
+ "{\n \"a\": 1,\n \"c\": 3,\n \"b\": 2\n}"
+ "{\n \"b\": 2,\n \"a\": 1,\n \"c\": 3\n}"
+ "{\n \"b\": 2,\n \"c\": 3,\n \"a\": 1\n}"
+ "{\n \"c\": 3,\n \"a\": 1,\n \"b\": 2\n}"
+ "{\n \"c\": 3,\n \"b\": 2,\n \"a\": 1\n}")))))
-(ert-deftest test-json-encode-plist ()
- (let ((plist '(:a 1 :b 2))
+(ert-deftest test-json-encode-hash-table-lisp-style ()
+ (let ((json-encoding-object-sort-predicate nil)
+ (json-encoding-pretty-print t)
+ (json-encoding-default-indentation " ")
+ (json-encoding-lisp-style-closings t))
+ (should (equal (json-encode #s(hash-table)) "{}"))
+ (should (equal (json-encode #s(hash-table data (a 1))) "{\n \"a\": 1}"))
+ (should (member (json-encode #s(hash-table data (b 2 a 1)))
+ '("{\n \"a\": 1,\n \"b\": 2}"
+ "{\n \"b\": 2,\n \"a\": 1}")))
+ (should (member (json-encode #s(hash-table data (c 3 b 2 a 1)))
+ '("{\n \"a\": 1,\n \"b\": 2,\n \"c\": 3}"
+ "{\n \"a\": 1,\n \"c\": 3,\n \"b\": 2}"
+ "{\n \"b\": 2,\n \"a\": 1,\n \"c\": 3}"
+ "{\n \"b\": 2,\n \"c\": 3,\n \"a\": 1}"
+ "{\n \"c\": 3,\n \"a\": 1,\n \"b\": 2}"
+ "{\n \"c\": 3,\n \"b\": 2,\n \"a\": 1}")))))
+
+(ert-deftest test-json-encode-hash-table-sort ()
+ (let ((json-encoding-object-sort-predicate #'string<)
+ (json-encoding-pretty-print nil))
+ (pcase-dolist (`(,in . ,out)
+ '((#s(hash-table) . "{}")
+ (#s(hash-table data (a 1)) . "{\"a\":1}")
+ (#s(hash-table data (b 2 a 1)) . "{\"a\":1,\"b\":2}")
+ (#s(hash-table data (c 3 b 2 a 1))
+ . "{\"a\":1,\"b\":2,\"c\":3}")))
+ (let ((copy (map-pairs in)))
+ (should (equal (json-encode in) out))
+ ;; Ensure sorting isn't destructive.
+ (should (seq-set-equal-p (map-pairs in) copy))))))
+
+(ert-deftest test-json-encode-alist ()
+ (let ((json-encoding-object-sort-predicate nil)
(json-encoding-pretty-print nil))
- (should (equal (json-encode plist) "{\"a\":1,\"b\":2}"))))
+ (should (equal (json-encode-alist ()) "{}"))
+ (should (equal (json-encode-alist '((a . 1) (t . 2) (nil . 3)))
+ "{\"a\":1,\"t\":2,\"nil\":3}"))
+ (should (equal (json-encode-alist '((:a . 1) (:t . 2) (:nil . 3)))
+ "{\"a\":1,\"t\":2,\"nil\":3}"))
+ (should (equal (json-encode-alist '(("a" . 1) ("t" . 2) ("nil" . 3)))
+ "{\"a\":1,\"t\":2,\"nil\":3}"))
+ (should (equal (json-encode-alist '((":a" . 1) (":t" . 2) (":nil" . 3)))
+ "{\":a\":1,\":t\":2,\":nil\":3}"))
+ (should (equal (json-encode-alist '((t . 1) (:nil . 2) (":nil" . 3)))
+ "{\"t\":1,\"nil\":2,\":nil\":3}"))
+ (should (equal (json-encode-alist '((b . 2) (a . 1))) "{\"b\":2,\"a\":1}"))
+ (should (equal (json-encode-alist '((c . 3) (b . 2) (a . 1)))
+ "{\"c\":3,\"b\":2,\"a\":1}"))))
+
+(ert-deftest test-json-encode-alist-pretty ()
+ (let ((json-encoding-object-sort-predicate nil)
+ (json-encoding-pretty-print t)
+ (json-encoding-default-indentation " ")
+ (json-encoding-lisp-style-closings nil))
+ (should (equal (json-encode-alist ()) "{}"))
+ (should (equal (json-encode-alist '((a . 1))) "{\n \"a\": 1\n}"))
+ (should (equal (json-encode-alist '((b . 2) (a . 1)))
+ "{\n \"b\": 2,\n \"a\": 1\n}"))
+ (should (equal (json-encode-alist '((c . 3) (b . 2) (a . 1)))
+ "{\n \"c\": 3,\n \"b\": 2,\n \"a\": 1\n}"))))
-(ert-deftest test-json-encode-plist-with-sort-predicate ()
- (let ((plist '(:c 3 :a 1 :b 2))
- (json-encoding-object-sort-predicate 'string<)
+(ert-deftest test-json-encode-alist-lisp-style ()
+ (let ((json-encoding-object-sort-predicate nil)
+ (json-encoding-pretty-print t)
+ (json-encoding-default-indentation " ")
+ (json-encoding-lisp-style-closings t))
+ (should (equal (json-encode-alist ()) "{}"))
+ (should (equal (json-encode-alist '((a . 1))) "{\n \"a\": 1}"))
+ (should (equal (json-encode-alist '((b . 2) (a . 1)))
+ "{\n \"b\": 2,\n \"a\": 1}"))
+ (should (equal (json-encode-alist '((c . 3) (b . 2) (a . 1)))
+ "{\n \"c\": 3,\n \"b\": 2,\n \"a\": 1}"))))
+
+(ert-deftest test-json-encode-alist-sort ()
+ (let ((json-encoding-object-sort-predicate #'string<)
(json-encoding-pretty-print nil))
- (should (equal (json-encode plist) "{\"a\":1,\"b\":2,\"c\":3}"))))
+ (pcase-dolist (`(,in . ,out)
+ '((() . "{}")
+ (((a . 1)) . "{\"a\":1}")
+ (((b . 2) (a . 1)) . "{\"a\":1,\"b\":2}")
+ (((c . 3) (b . 2) (a . 1))
+ . "{\"a\":1,\"b\":2,\"c\":3}")))
+ (let ((copy (copy-alist in)))
+ (should (equal (json-encode-alist in) out))
+ ;; Ensure sorting isn't destructive (bug#40693).
+ (should (equal in copy))))))
-(ert-deftest test-json-encode-alist-with-sort-predicate ()
- (let ((alist '((:c . 3) (:a . 1) (:b . 2)))
- (json-encoding-object-sort-predicate 'string<)
+(ert-deftest test-json-encode-plist ()
+ (let ((json-encoding-object-sort-predicate nil)
(json-encoding-pretty-print nil))
- (should (equal (json-encode alist) "{\"a\":1,\"b\":2,\"c\":3}"))))
+ (should (equal (json-encode-plist ()) "{}"))
+ (should (equal (json-encode-plist '(:a 1)) "{\"a\":1}"))
+ (should (equal (json-encode-plist '(:b 2 :a 1)) "{\"b\":2,\"a\":1}"))
+ (should (equal (json-encode-plist '(":d" 4 "c" 3 b 2 :a 1))
+ "{\":d\":4,\"c\":3,\"b\":2,\"a\":1}"))
+ (should (equal (json-encode-plist '(nil 2 t 1))
+ "{\"nil\":2,\"t\":1}"))
+ (should (equal (json-encode-plist '(:nil 2 :t 1))
+ "{\"nil\":2,\"t\":1}"))
+ (should (equal (json-encode-plist '(":nil" 4 "nil" 3 ":t" 2 "t" 1))
+ "{\":nil\":4,\"nil\":3,\":t\":2,\"t\":1}"))))
+
+(ert-deftest test-json-encode-plist-pretty ()
+ (let ((json-encoding-object-sort-predicate nil)
+ (json-encoding-pretty-print t)
+ (json-encoding-default-indentation " ")
+ (json-encoding-lisp-style-closings nil))
+ (should (equal (json-encode-plist ()) "{}"))
+ (should (equal (json-encode-plist '(:a 1)) "{\n \"a\": 1\n}"))
+ (should (equal (json-encode-plist '(:b 2 :a 1))
+ "{\n \"b\": 2,\n \"a\": 1\n}"))
+ (should (equal (json-encode-plist '(:c 3 :b 2 :a 1))
+ "{\n \"c\": 3,\n \"b\": 2,\n \"a\": 1\n}"))))
+
+(ert-deftest test-json-encode-plist-lisp-style ()
+ (let ((json-encoding-object-sort-predicate nil)
+ (json-encoding-pretty-print t)
+ (json-encoding-default-indentation " ")
+ (json-encoding-lisp-style-closings t))
+ (should (equal (json-encode-plist ()) "{}"))
+ (should (equal (json-encode-plist '(:a 1)) "{\n \"a\": 1}"))
+ (should (equal (json-encode-plist '(:b 2 :a 1))
+ "{\n \"b\": 2,\n \"a\": 1}"))
+ (should (equal (json-encode-plist '(:c 3 :b 2 :a 1))
+ "{\n \"c\": 3,\n \"b\": 2,\n \"a\": 1}"))))
+
+(ert-deftest test-json-encode-plist-sort ()
+ (let ((json-encoding-object-sort-predicate #'string<)
+ (json-encoding-pretty-print nil))
+ (pcase-dolist (`(,in . ,out)
+ '((() . "{}")
+ ((:a 1) . "{\"a\":1}")
+ ((:b 2 :a 1) . "{\"a\":1,\"b\":2}")
+ ((:c 3 :b 2 :a 1) . "{\"a\":1,\"b\":2,\"c\":3}")))
+ (let ((copy (copy-sequence in)))
+ (should (equal (json-encode-plist in) out))
+ ;; Ensure sorting isn't destructive.
+ (should (equal in copy))))))
(ert-deftest test-json-encode-list ()
- (let ((json-encoding-pretty-print nil))
- (should (equal (json-encode-list '(:a 1 :b 2))
- "{\"a\":1,\"b\":2}"))
- (should (equal (json-encode-list '((:a . 1) (:b . 2)))
- "{\"a\":1,\"b\":2}"))
- (should (equal (json-encode-list '(1 2 3 4)) "[1,2,3,4]"))))
+ "Test `json-encode-list' or its more moral equivalents."
+ (let ((json-encoding-object-sort-predicate nil)
+ (json-encoding-pretty-print nil))
+ ;; Trick `json-encode' into using `json--print-list'.
+ (let ((json-null (list nil)))
+ (should (equal (json-encode ()) "{}")))
+ (should (equal (json-encode '(a)) "[\"a\"]"))
+ (should (equal (json-encode '(:a)) "[\"a\"]"))
+ (should (equal (json-encode '("a")) "[\"a\"]"))
+ (should (equal (json-encode '(a 1)) "[\"a\",1]"))
+ (should (equal (json-encode '("a" 1)) "[\"a\",1]"))
+ (should (equal (json-encode '(:a 1)) "{\"a\":1}"))
+ (should (equal (json-encode '((a . 1))) "{\"a\":1}"))
+ (should (equal (json-encode '((:a . 1))) "{\"a\":1}"))
+ (should (equal (json-encode '(:b 2 :a)) "[\"b\",2,\"a\"]"))
+ (should (equal (json-encode '(4 3 2 1)) "[4,3,2,1]"))
+ (should (equal (json-encode '(b 2 a 1)) "[\"b\",2,\"a\",1]"))
+ (should (equal (json-encode '(:b 2 :a 1)) "{\"b\":2,\"a\":1}"))
+ (should (equal (json-encode '((b . 2) (a . 1))) "{\"b\":2,\"a\":1}"))
+ (should (equal (json-encode '((:b . 2) (:a . 1)))
+ "{\"b\":2,\"a\":1}"))
+ (should (equal (json-encode '((a) 1)) "[[\"a\"],1]"))
+ (should (equal (json-encode '((:a) 1)) "[[\"a\"],1]"))
+ (should (equal (json-encode '(("a") 1)) "[[\"a\"],1]"))
+ (should (equal (json-encode '((a 1) 2)) "[[\"a\",1],2]"))
+ (should (equal (json-encode '((:a 1) 2)) "[{\"a\":1},2]"))
+ (should (equal (json-encode '(((a . 1)) 2)) "[{\"a\":1},2]"))
+ (should (equal (json-encode '(:a 1 :b (2))) "{\"a\":1,\"b\":[2]}"))
+ (should (equal (json-encode '((a . 1) (b 2))) "{\"a\":1,\"b\":[2]}"))
+ (should-error (json-encode '(a . 1)) :type 'wrong-type-argument)
+ (should-error (json-encode '((a . 1) 2)) :type 'wrong-type-argument)
+ (with-suppressed-warnings ((obsolete json-encode-list))
+ (should (equal (should-error (json-encode-list []))
+ '(json-error [])))
+ (should (equal (should-error (json-encode-list [a]))
+ '(json-error [a]))))))
;;; Arrays
(ert-deftest test-json-read-array ()
(let ((json-array-type 'vector))
+ (json-tests--with-temp-buffer "[]"
+ (should (equal (json-read-array) [])))
+ (json-tests--with-temp-buffer "[ ]"
+ (should (equal (json-read-array) [])))
+ (json-tests--with-temp-buffer "[1]"
+ (should (equal (json-read-array) [1])))
(json-tests--with-temp-buffer "[1, 2, \"a\", \"b\"]"
(should (equal (json-read-array) [1 2 "a" "b"]))))
(let ((json-array-type 'list))
+ (json-tests--with-temp-buffer "[]"
+ (should-not (json-read-array)))
+ (json-tests--with-temp-buffer "[ ]"
+ (should-not (json-read-array)))
+ (json-tests--with-temp-buffer "[1]"
+ (should (equal (json-read-array) '(1))))
(json-tests--with-temp-buffer "[1, 2, \"a\", \"b\"]"
(should (equal (json-read-array) '(1 2 "a" "b")))))
(json-tests--with-temp-buffer "[1 2]"
- (should-error (json-read-array) :type 'json-error)))
+ (should (equal (should-error (json-read-array))
+ '(json-array-format "," ?2)))))
+
+(ert-deftest test-json-read-array-function ()
+ (let* ((pre nil)
+ (post nil)
+ (keys '(0 1))
+ (json-pre-element-read-function
+ (lambda (key)
+ (setq pre 'pre)
+ (should (equal key (pop keys)))))
+ (json-post-element-read-function
+ (lambda () (setq post 'post))))
+ (json-tests--with-temp-buffer "[1, 0]"
+ (json-read-array)
+ (should (eq pre 'pre))
+ (should (eq post 'post)))))
(ert-deftest test-json-encode-array ()
- (let ((json-encoding-pretty-print nil))
- (should (equal (json-encode-array [1 2 "a" "b"])
- "[1,2,\"a\",\"b\"]"))))
+ (let ((json-encoding-object-sort-predicate nil)
+ (json-encoding-pretty-print nil))
+ (should (equal (json-encode-array ()) "[]"))
+ (should (equal (json-encode-array []) "[]"))
+ (should (equal (json-encode-array '(1)) "[1]"))
+ (should (equal (json-encode-array '[1]) "[1]"))
+ (should (equal (json-encode-array '(2 1)) "[2,1]"))
+ (should (equal (json-encode-array '[2 1]) "[2,1]"))
+ (should (equal (json-encode-array '[:b a 2 1]) "[\"b\",\"a\",2,1]"))))
+
+(ert-deftest test-json-encode-array-pretty ()
+ (let ((json-encoding-object-sort-predicate nil)
+ (json-encoding-pretty-print t)
+ (json-encoding-default-indentation " ")
+ (json-encoding-lisp-style-closings nil))
+ (should (equal (json-encode-array ()) "[]"))
+ (should (equal (json-encode-array []) "[]"))
+ (should (equal (json-encode-array '(1)) "[\n 1\n]"))
+ (should (equal (json-encode-array '[1]) "[\n 1\n]"))
+ (should (equal (json-encode-array '(2 1)) "[\n 2,\n 1\n]"))
+ (should (equal (json-encode-array '[2 1]) "[\n 2,\n 1\n]"))
+ (should (equal (json-encode-array '[:b a 2 1])
+ "[\n \"b\",\n \"a\",\n 2,\n 1\n]"))))
+
+(ert-deftest test-json-encode-array-lisp-style ()
+ (let ((json-encoding-object-sort-predicate nil)
+ (json-encoding-pretty-print t)
+ (json-encoding-default-indentation " ")
+ (json-encoding-lisp-style-closings t))
+ (should (equal (json-encode-array ()) "[]"))
+ (should (equal (json-encode-array []) "[]"))
+ (should (equal (json-encode-array '(1)) "[\n 1]"))
+ (should (equal (json-encode-array '[1]) "[\n 1]"))
+ (should (equal (json-encode-array '(2 1)) "[\n 2,\n 1]"))
+ (should (equal (json-encode-array '[2 1]) "[\n 2,\n 1]"))
+ (should (equal (json-encode-array '[:b a 2 1])
+ "[\n \"b\",\n \"a\",\n 2,\n 1]"))))
;;; Reader
(ert-deftest test-json-read ()
- (json-tests--with-temp-buffer "{ \"a\": 1 }"
- ;; We don't care exactly what the return value is (that is tested
- ;; in `test-json-read-object'), but it should parse without error.
- (should (json-read)))
+ (pcase-dolist (`(,fn . ,contents)
+ '((json-read-string "\"\"" "\"a\"")
+ (json-read-array "[]" "[1]")
+ (json-read-object "{}" "{\"a\":1}")
+ (json-read-keyword "null" "false" "true")
+ (json-read-number
+ "-0" "0" "1" "2" "3" "4" "5" "6" "7" "8" "9")))
+ (dolist (content contents)
+ ;; Check that leading whitespace is skipped.
+ (dolist (str (list content (concat " " content)))
+ (cl-letf* ((called nil)
+ ((symbol-function fn)
+ (lambda (&rest _) (setq called t))))
+ (json-tests--with-temp-buffer str
+ ;; We don't care exactly what the return value is (that is
+ ;; tested elsewhere), but it should parse without error.
+ (should (json-read))
+ (should called)))))))
+
+(ert-deftest test-json-read-invalid ()
(json-tests--with-temp-buffer ""
(should-error (json-read) :type 'json-end-of-file))
- (json-tests--with-temp-buffer "xxx"
- (should-error (json-read) :type 'json-readtable-error)))
+ (json-tests--with-temp-buffer " "
+ (should-error (json-read) :type 'json-end-of-file))
+ (json-tests--with-temp-buffer "x"
+ (should (equal (should-error (json-read))
+ '(json-readtable-error ?x))))
+ (json-tests--with-temp-buffer " x"
+ (should (equal (should-error (json-read))
+ '(json-readtable-error ?x)))))
(ert-deftest test-json-read-from-string ()
- (let ((json-string "{ \"a\": 1 }"))
- (json-tests--with-temp-buffer json-string
- (should (equal (json-read-from-string json-string)
+ (dolist (str '("\"\"" "\"a\"" "[]" "[1]" "{}" "{\"a\":1}"
+ "null" "false" "true" "0" "123"))
+ (json-tests--with-temp-buffer str
+ (should (equal (json-read-from-string str)
(json-read))))))
-;;; JSON encoder
+;;; Encoder
(ert-deftest test-json-encode ()
+ (should (equal (json-encode t) "true"))
+ (let ((json-null 'null))
+ (should (equal (json-encode json-null) "null")))
+ (let ((json-false 'false))
+ (should (equal (json-encode json-false) "false")))
+ (should (equal (json-encode "") "\"\""))
(should (equal (json-encode "foo") "\"foo\""))
+ (should (equal (json-encode :) "\"\""))
+ (should (equal (json-encode :foo) "\"foo\""))
+ (should (equal (json-encode '(1)) "[1]"))
+ (should (equal (json-encode 'foo) "\"foo\""))
+ (should (equal (json-encode 0) "0"))
+ (should (equal (json-encode 123) "123"))
+ (let ((json-encoding-object-sort-predicate nil)
+ (json-encoding-pretty-print nil))
+ (should (equal (json-encode []) "[]"))
+ (should (equal (json-encode [1]) "[1]"))
+ (should (equal (json-encode #s(hash-table)) "{}"))
+ (should (equal (json-encode #s(hash-table data (a 1))) "{\"a\":1}")))
+ (with-temp-buffer
+ (should (equal (should-error (json-encode (current-buffer)))
+ (list 'json-error (current-buffer))))))
+
+;;; Pretty printing & minimizing
+
+(defun json-tests-equal-pretty-print (original &optional expected)
+ "Abort current test if pretty-printing ORIGINAL does not yield EXPECTED.
+
+Both ORIGINAL and EXPECTED should be strings. If EXPECTED is
+nil, ORIGINAL should stay unchanged by pretty-printing."
(with-temp-buffer
- (should-error (json-encode (current-buffer)) :type 'json-error)))
+ (insert original)
+ (json-pretty-print-buffer)
+ (should (equal (buffer-string) (or expected original)))))
+
+(ert-deftest test-json-pretty-print-string ()
+ (json-tests-equal-pretty-print "\"\"")
+ (json-tests-equal-pretty-print "\"foo\""))
+
+(ert-deftest test-json-pretty-print-atom ()
+ (json-tests-equal-pretty-print "true")
+ (json-tests-equal-pretty-print "false")
+ (json-tests-equal-pretty-print "null"))
+
+(ert-deftest test-json-pretty-print-number ()
+ (json-tests-equal-pretty-print "123")
+ (json-tests-equal-pretty-print "0.123"))
+
+(ert-deftest test-json-pretty-print-object ()
+ ;; Empty (regression test for bug#24252).
+ (json-tests-equal-pretty-print "{}")
+ ;; One pair.
+ (json-tests-equal-pretty-print
+ "{\"key\":1}"
+ "{\n \"key\": 1\n}")
+ ;; Two pairs.
+ (json-tests-equal-pretty-print
+ "{\"key1\":1,\"key2\":2}"
+ "{\n \"key1\": 1,\n \"key2\": 2\n}")
+ ;; Nested object.
+ (json-tests-equal-pretty-print
+ "{\"foo\":{\"key\":1}}"
+ "{\n \"foo\": {\n \"key\": 1\n }\n}")
+ ;; Nested array.
+ (json-tests-equal-pretty-print
+ "{\"key\":[1,2]}"
+ "{\n \"key\": [\n 1,\n 2\n ]\n}")
+ ;; Confusable keys (bug#24252, bug#42545).
+ (json-tests-equal-pretty-print
+ (concat "{\"t\":1,\"nil\":2,\":t\":3,\":nil\":4,"
+ "\"null\":5,\":json-null\":6,\":json-false\":7}")
+ (concat "{\n \"t\": 1,\n \"nil\": 2,\n \":t\": 3,\n \":nil\": 4,"
+ "\n \"null\": 5,\n \":json-null\": 6,\n \":json-false\": 7\n}")))
+
+(ert-deftest test-json-pretty-print-array ()
+ ;; Empty.
+ (json-tests-equal-pretty-print "[]")
+ ;; One item.
+ (json-tests-equal-pretty-print
+ "[1]"
+ "[\n 1\n]")
+ ;; Two items.
+ (json-tests-equal-pretty-print
+ "[1,2]"
+ "[\n 1,\n 2\n]")
+ ;; Nested object.
+ (json-tests-equal-pretty-print
+ "[{\"key\":1}]"
+ "[\n {\n \"key\": 1\n }\n]")
+ ;; Nested array.
+ (json-tests-equal-pretty-print
+ "[[1,2]]"
+ "[\n [\n 1,\n 2\n ]\n]"))
(provide 'json-tests)
+
;;; json-tests.el ends here
diff --git a/test/lisp/jsonrpc-tests.el b/test/lisp/jsonrpc-tests.el
new file mode 100644
index 00000000000..e02cb154235
--- /dev/null
+++ b/test/lisp/jsonrpc-tests.el
@@ -0,0 +1,255 @@
+;;; jsonrpc-tests.el --- tests for jsonrpc.el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2018-2022 Free Software Foundation, Inc.
+
+;; Author: João Távora <joaotavora@gmail.com>
+;; Keywords: tests
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; About "deferred" tests, `jsonrpc--test-client' has a flag that we
+;; test in its `jsonrpc-connection-ready-p' API method. It holds any
+;; `jsonrpc-request's and `jsonrpc-async-request's explicitly passed
+;; `:deferred'. After clearing the flag, the held requests are
+;; actually sent to the server in the next opportunity (when receiving
+;; or sending something to the server).
+
+;;; Code:
+
+(require 'ert)
+(require 'jsonrpc)
+(require 'eieio)
+
+(defclass jsonrpc--test-endpoint (jsonrpc-process-connection)
+ ((scp :accessor jsonrpc--shutdown-complete-p)))
+
+(defclass jsonrpc--test-client (jsonrpc--test-endpoint)
+ ((hold-deferred :initform t :accessor jsonrpc--hold-deferred)))
+
+(defun jsonrpc--call-with-emacsrpc-fixture (fn)
+ "Do work for `jsonrpc--with-emacsrpc-fixture'. Call FN."
+ (let* (listen-server endpoint)
+ (unwind-protect
+ (progn
+ (setq listen-server
+ (make-network-process
+ :name "Emacs RPC server" :server t :host "localhost"
+ :service (if (version<= emacs-version "26.1")
+ 44444
+ ;; 26.1 can automatically find ports if
+ ;; one passes 0 here.
+ 0)
+ :log (lambda (listen-server client _message)
+ (push
+ (make-instance
+ 'jsonrpc--test-endpoint
+ :name (process-name client)
+ :process client
+ :request-dispatcher
+ (lambda (_endpoint method params)
+ (unless (memq method '(+ - * / vconcat append
+ sit-for ignore))
+ (signal 'jsonrpc-error
+ '((jsonrpc-error-message
+ . "Sorry, this isn't allowed")
+ (jsonrpc-error-code . -32601))))
+ (apply method (append params nil)))
+ :on-shutdown
+ (lambda (conn)
+ (setf (jsonrpc--shutdown-complete-p conn) t)))
+ (process-get listen-server 'handlers)))))
+ (setq endpoint
+ (make-instance
+ 'jsonrpc--test-client
+ "Emacs RPC client"
+ :process
+ (open-network-stream "JSONRPC test tcp endpoint"
+ nil "localhost"
+ (process-contact listen-server
+ :service))
+ :on-shutdown
+ (lambda (conn)
+ (setf (jsonrpc--shutdown-complete-p conn) t))))
+ (funcall fn endpoint))
+ (unwind-protect
+ (when endpoint
+ (kill-buffer (jsonrpc--events-buffer endpoint))
+ (jsonrpc-shutdown endpoint))
+ (when listen-server
+ (cl-loop do (delete-process listen-server)
+ while (progn (accept-process-output nil 0.1)
+ (process-live-p listen-server))
+ do (jsonrpc--message
+ "test listen-server is still running, waiting"))
+ (cl-loop for handler in (process-get listen-server 'handlers)
+ do (ignore-errors (jsonrpc-shutdown handler)))
+ (mapc #'kill-buffer
+ (mapcar #'jsonrpc--events-buffer
+ (process-get listen-server 'handlers))))))))
+
+(cl-defmacro jsonrpc--with-emacsrpc-fixture ((endpoint-sym) &body body)
+ `(jsonrpc--call-with-emacsrpc-fixture (lambda (,endpoint-sym) ,@body)))
+
+(ert-deftest returns-3 ()
+ "A basic test for adding two numbers in our test RPC."
+ (jsonrpc--with-emacsrpc-fixture (conn)
+ (should (= 3 (jsonrpc-request conn '+ [1 2])))))
+
+(ert-deftest errors-with--32601 ()
+ "Errors with -32601"
+ (jsonrpc--with-emacsrpc-fixture (conn)
+ (condition-case err
+ (progn
+ (jsonrpc-request conn 'delete-directory "~/tmp")
+ (ert-fail "A `jsonrpc-error' should have been signaled!"))
+ (jsonrpc-error
+ (should (= -32601 (cdr (assoc 'jsonrpc-error-code (cdr err)))))))))
+
+(ert-deftest signals-an--32603-JSONRPC-error ()
+ "Signals an -32603 JSONRPC error."
+ (jsonrpc--with-emacsrpc-fixture (conn)
+ (condition-case err
+ (progn
+ (jsonrpc-request conn '+ ["a" 2])
+ (ert-fail "A `jsonrpc-error' should have been signaled!"))
+ (jsonrpc-error
+ (should (= -32603 (cdr (assoc 'jsonrpc-error-code (cdr err)))))))))
+
+(ert-deftest times-out ()
+ "Request for 3-sec sit-for with 1-sec timeout times out."
+ (jsonrpc--with-emacsrpc-fixture (conn)
+ (should-error
+ (jsonrpc-request conn 'sit-for [3] :timeout 1))))
+
+(ert-deftest doesnt-time-out ()
+ :tags '(:expensive-test)
+ "Request for 1-sec sit-for with 2-sec timeout succeeds."
+ (jsonrpc--with-emacsrpc-fixture (conn)
+ (jsonrpc-request conn 'sit-for [1] :timeout 2)))
+
+(ert-deftest stretching-it-but-works ()
+ "Vector of numbers or vector of vector of numbers are serialized."
+ (jsonrpc--with-emacsrpc-fixture (conn)
+ ;; (vconcat [1 2 3] [3 4 5]) => [1 2 3 3 4 5] which can be
+ ;; serialized.
+ (should (equal
+ [1 2 3 3 4 5]
+ (jsonrpc-request conn 'vconcat [[1 2 3] [3 4 5]])))))
+
+(ert-deftest json-el-cant-serialize-this ()
+ "Can't serialize a response that is half-vector/half-list."
+ (jsonrpc--with-emacsrpc-fixture (conn)
+ (should-error
+ ;; (append [1 2 3] [3 4 5]) => (1 2 3 . [3 4 5]), which can't be
+ ;; serialized
+ (jsonrpc-request conn 'append [[1 2 3] [3 4 5]]))))
+
+(cl-defmethod jsonrpc-connection-ready-p
+ ((conn jsonrpc--test-client) what)
+ (and (cl-call-next-method)
+ (or (not (string-match "deferred" what))
+ (not (jsonrpc--hold-deferred conn)))))
+
+(ert-deftest deferred-action-toolate ()
+ :tags '(:expensive-test)
+ "Deferred request fails because no one clears the flag."
+ (jsonrpc--with-emacsrpc-fixture (conn)
+ (should-error
+ (jsonrpc-request conn '+ [1 2]
+ :deferred "deferred-testing" :timeout 0.5)
+ :type 'jsonrpc-error)
+ (should
+ (= 3 (jsonrpc-request conn '+ [1 2]
+ :timeout 0.5)))))
+
+(ert-deftest deferred-action-intime ()
+ :tags '(:expensive-test)
+ "Deferred request barely makes it after event clears a flag."
+ ;; Send an async request, which returns immediately. However the
+ ;; success fun which sets the flag only runs after some time.
+ (jsonrpc--with-emacsrpc-fixture (conn)
+ (jsonrpc-async-request conn
+ 'sit-for [0.5]
+ :success-fn
+ (lambda (_result)
+ (setf (jsonrpc--hold-deferred conn) nil)))
+ ;; Now wait for an answer to this request, which should be sent as
+ ;; soon as the previous one is answered.
+ (should
+ (= 3 (jsonrpc-request conn '+ [1 2]
+ :deferred "deferred"
+ :timeout 1)))))
+
+(ert-deftest deferred-action-complex-tests ()
+ :tags '(:expensive-test)
+ "Test a more complex situation with deferred requests."
+ (jsonrpc--with-emacsrpc-fixture (conn)
+ (let (n-deferred-1
+ n-deferred-2
+ second-deferred-went-through-p)
+ ;; This returns immediately
+ (jsonrpc-async-request
+ conn
+ 'sit-for [0.1]
+ :success-fn
+ (lambda (_result)
+ ;; this only gets runs after the "first deferred" is stashed.
+ (setq n-deferred-1
+ (hash-table-count (jsonrpc--deferred-actions conn)))))
+ (should-error
+ ;; This stashes the request and waits. It will error because
+ ;; no-one clears the "hold deferred" flag.
+ (jsonrpc-request conn 'ignore ["first deferred"]
+ :deferred "first deferred"
+ :timeout 0.5)
+ :type 'jsonrpc-error)
+ ;; The error means the deferred actions stash is now empty
+ (should (zerop (hash-table-count (jsonrpc--deferred-actions conn))))
+ ;; Again, this returns immediately.
+ (jsonrpc-async-request
+ conn
+ 'sit-for [0.1]
+ :success-fn
+ (lambda (_result)
+ ;; This gets run while "third deferred" below is waiting for
+ ;; a reply. Notice that we clear the flag in time here.
+ (setq n-deferred-2 (hash-table-count (jsonrpc--deferred-actions conn)))
+ (setf (jsonrpc--hold-deferred conn) nil)))
+ ;; This again stashes a request and returns immediately.
+ (jsonrpc-async-request conn 'ignore ["second deferred"]
+ :deferred "second deferred"
+ :timeout 1
+ :success-fn
+ (lambda (_result)
+ (setq second-deferred-went-through-p t)))
+ ;; And this also stashes a request, but waits. Eventually the
+ ;; flag is cleared in time and both requests go through.
+ (jsonrpc-request conn 'ignore ["third deferred"]
+ :deferred "third deferred"
+ :timeout 1)
+ ;; Wait another 0.5 secs just in case the success handlers of
+ ;; one of these last two requests didn't quite have a chance to
+ ;; run (Emacs 25.2 apparently needs this).
+ (accept-process-output nil 0.5)
+ (should second-deferred-went-through-p)
+ (should (eq 1 n-deferred-1))
+ (should (eq 2 n-deferred-2))
+ (should (eq 0 (hash-table-count (jsonrpc--deferred-actions conn)))))))
+
+(provide 'jsonrpc-tests)
+;;; jsonrpc-tests.el ends here
diff --git a/test/lisp/kmacro-tests.el b/test/lisp/kmacro-tests.el
index a691ec84549..75d700070aa 100644
--- a/test/lisp/kmacro-tests.el
+++ b/test/lisp/kmacro-tests.el
@@ -1,6 +1,6 @@
;;; kmacro-tests.el --- Tests for kmacro.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2017 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2022 Free Software Foundation, Inc.
;; Author: Gemini Lasswell <gazally@runbox.com>
@@ -91,33 +91,30 @@ body in KEYS-AND-BODY."
,docstring ,@keys
(kmacro-tests-with-kmacro-clean-slate ,@body))))
-(defvar kmacro-tests-keymap
- (let ((map (make-sparse-keymap)))
- (dotimes (i 26)
- (define-key map (string (+ ?a i)) 'self-insert-command))
- (dotimes (i 10)
- (define-key map (string (+ ?0 i)) 'self-insert-command))
- ;; Define a few key sequences of different lengths.
- (dolist (item '(("\C-a" . beginning-of-line)
- ("\C-b" . backward-char)
- ("\C-e" . end-of-line)
- ("\C-f" . forward-char)
- ("\C-r" . isearch-backward)
- ("\C-u" . universal-argument)
- ("\C-w" . kill-region)
- ("\C-SPC" . set-mark-command)
- ("\M-w" . kill-ring-save)
- ("\M-x" . execute-extended-command)
- ("\C-cd" . downcase-word)
- ("\C-cxu" . upcase-word)
- ("\C-cxq" . quoted-insert)
- ("\C-cxi" . kmacro-insert-counter)
- ("\C-x\C-k" . kmacro-keymap)))
- (define-key map (car item) (cdr item)))
- map)
- "Keymap to use for testing keyboard macros.
+(defvar-keymap kmacro-tests-keymap
+ :doc "Keymap to use for testing keyboard macros.
This is used to obtain consistent results even if tests are run
-in an environment with rebound keys.")
+in an environment with rebound keys."
+ ;; Define a few key sequences of different lengths.
+ "C-a" 'beginning-of-line
+ "C-b" 'backward-char
+ "C-e" 'end-of-line
+ "C-f" 'forward-char
+ "C-r" 'isearch-backward
+ "C-u" 'universal-argument
+ "C-w" 'kill-region
+ "C-SPC" 'set-mark-command
+ "M-w" 'kill-ring-save
+ "M-x" 'execute-extended-command
+ "C-c d" 'downcase-word
+ "C-c x u" 'upcase-word
+ "C-c x q" 'quoted-insert
+ "C-c x i" 'kmacro-insert-counter
+ "C-x C-k" 'kmacro-keymap)
+(dotimes (i 26)
+ (keymap-set kmacro-tests-keymap (string (+ ?a i)) 'self-insert-command))
+(dotimes (i 10)
+ (keymap-set kmacro-tests-keymap (string (+ ?0 i)) 'self-insert-command))
(defvar kmacro-tests-events nil
"Input events used by the kmacro test in progress.")
@@ -248,7 +245,7 @@ cause the current test to fail."
(kmacro-tests-simulate-command '(kmacro-set-counter 1))
(kmacro-tests-should-insert "1"
(kmacro-tests-simulate-command '(kmacro-insert-counter nil)))
- ;; Using universal arg to to set counter should reset to starting value.
+ ;; Using universal arg to set counter should reset to starting value.
(kmacro-tests-simulate-command '(kmacro-set-counter (4)) '(4))
(kmacro-tests-should-insert "5"
(kmacro-tests-simulate-command '(kmacro-insert-counter nil))))
@@ -312,7 +309,6 @@ cause the current test to fail."
(kmacro-tests-deftest kmacro-tests-end-and-call-macro-mouse ()
"Commands to end and call macro work under various conditions.
This is a regression test for Bug#24992."
- (:expected-result :failed)
(cl-letf (((symbol-function #'mouse-set-point) #'ignore))
;; First, try it with no macro to record.
(setq kmacro-tests-macros '(""))
@@ -520,7 +516,7 @@ This is a regression test for: Bug#3412, Bug#11817."
(should (eq saved-binding (key-binding "\C-a")))))
(kmacro-tests-deftest kmacro-tests-name-or-bind-to-key-when-no-macro ()
- "Bind to key, symbol or register fails when when no macro exists."
+ "Bind to key, symbol or register fails when no macro exists."
(should-error (kmacro-bind-to-key nil))
(should-error (kmacro-name-last-macro 'kmacro-tests-symbol-for-test))
(should-error (kmacro-to-register)))
@@ -584,8 +580,10 @@ This is a regression test for: Bug#3412, Bug#11817."
;; Check the bound key and run it and verify correct counter
;; and format.
(should (equal (string-to-vector "\C-cxi")
- (car (kmacro-extract-lambda
- (key-binding "\C-x\C-kA")))))
+ (car (with-suppressed-warnings
+ ((obsolete kmacro-extract-lambda))
+ (kmacro-extract-lambda
+ (key-binding "\C-x\C-kA"))))))
(kmacro-tests-should-insert "<5>"
(funcall (key-binding "\C-x\C-kA")))))
@@ -609,7 +607,7 @@ This is a regression test for: Bug#3412, Bug#11817."
(dotimes (i 2)
(kmacro-tests-define-macro (make-vector (1+ i) (+ ?a i)))
(kmacro-name-last-macro 'kmacro-tests-symbol-for-test)
- (should (fboundp 'kmacro-tests-symbol-for-test)))
+ (should (commandp 'kmacro-tests-symbol-for-test)))
;; Now run the function bound to the symbol. Result should be the
;; second macro.
@@ -818,7 +816,6 @@ This is a regression for item 7 in Bug#24991."
(kmacro-tests-deftest kmacro-tests-step-edit-cleans-up-hook ()
"Step-editing properly cleans up `post-command-hook.' (Bug #18708)"
- (:expected-result :failed)
(let (post-command-hook)
(setq-local post-command-hook '(t))
(kmacro-tests-run-step-edit "x"
@@ -827,6 +824,15 @@ This is a regression for item 7 in Bug#24991."
:macro-result "x")
(kmacro-tests-simulate-command '(beginning-of-line))))
+(ert-deftest kmacro-tests--cl-print ()
+ (should (equal (cl-prin1-to-string
+ (kmacro [?a ?b backspace backspace]))
+ "#f(kmacro \"a b <backspace> <backspace>\")"))
+ (should (equal (cl-prin1-to-string
+ (with-suppressed-warnings ((obsolete kmacro-lambda-form))
+ (kmacro-lambda-form [?a ?b backspace backspace] 1 "%d")))
+ "#f(kmacro \"a b <backspace> <backspace>\" 1 \"%d\")")))
+
(cl-defun kmacro-tests-run-step-edit
(macro &key events sequences result macro-result)
"Set up and run a test of `kmacro-step-edit-macro'.
@@ -836,7 +842,7 @@ and `read-event' and `read-key-sequence' set up to return items from
EVENTS and SEQUENCES respectively. SEQUENCES may be nil, but
EVENTS should not be. EVENTS should be a list of symbols bound
in `kmacro-step-edit-map' or `query-replace' map, and this function
-will do the keymap lookup for you. SEQUENCES should contain
+will do the keymap lookup for you. SEQUENCES should contain
return values for `read-key-sequence'.
Before running the macro, the current buffer will be erased.
diff --git a/test/lisp/loadhist-resources/loadhist--bar.el b/test/lisp/loadhist-resources/loadhist--bar.el
new file mode 100644
index 00000000000..5c8914ed573
--- /dev/null
+++ b/test/lisp/loadhist-resources/loadhist--bar.el
@@ -0,0 +1,27 @@
+;;; loadhist--bar.el --- Dummy package for loadhist-tests -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(autoload 'loadhist--foo-inc "loadhist--foo")
+
+(defun loadhist--bar-dec (x) (1- x))
+
+(provide 'loadhist--bar)
+;;; loadhist--bar.el ends here
diff --git a/test/lisp/loadhist-resources/loadhist--foo.el b/test/lisp/loadhist-resources/loadhist--foo.el
new file mode 100644
index 00000000000..3574c220135
--- /dev/null
+++ b/test/lisp/loadhist-resources/loadhist--foo.el
@@ -0,0 +1,29 @@
+;;; loadhist--foo.el --- Dummy package for loadhist-tests -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(autoload 'loadhist--bar-dec "loadhist--bar")
+
+(defun loadhist--foo-inc (x) (1+ x))
+
+(provide 'loadhist--foo)
+;;; loadhist--foo.el ends here
diff --git a/test/lisp/loadhist-tests.el b/test/lisp/loadhist-tests.el
new file mode 100644
index 00000000000..ef5fc164d34
--- /dev/null
+++ b/test/lisp/loadhist-tests.el
@@ -0,0 +1,104 @@
+;;; loadhist-tests.el --- Tests for loadhist.el -*- lexical-binding:t -*-
+
+;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+;; Author: Stefan Kangas <stefankangas@gmail.com>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'loadhist)
+
+(ert-deftest loadhist-tests-feature-symbols ()
+ (should (equal (file-name-base (car (feature-symbols 'loadhist))) "loadhist"))
+ (should-not (feature-symbols 'non-existent-feature)))
+
+(ert-deftest loadhist-tests-feature-file ()
+ (should (equal (file-name-base (feature-file 'loadhist)) "loadhist"))
+ (should-error (feature-file 'non-existent-feature)))
+
+(ert-deftest loadhist-tests-file-loadhist-lookup ()
+ ;; This should probably be extended...
+ (should (listp (file-loadhist-lookup "loadhist"))))
+
+(ert-deftest loadhist-tests-file-provides ()
+ (should (eq (car (file-provides "loadhist")) 'loadhist)))
+
+(ert-deftest loadhist-tests-file-requires ()
+ (should-not (file-requires "loadhist")))
+
+(ert-deftest loadhist-tests-file-dependents ()
+ (require 'dired-x)
+ (let ((deps (file-dependents "dired")))
+ (should (member "dired-x" (mapcar #'file-name-base deps)))))
+
+(ert-deftest loadhist-tests-unload-feature ()
+ (require 'dired-x)
+ (should-error (unload-feature 'dired))
+ (unload-feature 'dired-x))
+
+(defvar loadhist--tests-dir (file-name-directory (macroexp-file-name)))
+
+(ert-deftest loadhist-tests-unload-feature-nested ()
+ (add-to-list 'load-path (expand-file-name
+ "loadhist-resources/"
+ loadhist--tests-dir))
+ (declare-function loadhist--foo-inc "loadhist--foo")
+ (declare-function loadhist--bar-dec "loadhist--dec")
+ (load "loadhist--foo" nil t)
+ (should (and (functionp 'loadhist--bar-dec) (functionp 'loadhist--foo-inc)))
+ (should (autoloadp (symbol-function 'loadhist--bar-dec)))
+ (load "loadhist--bar" nil t)
+ (should (and (functionp 'loadhist--bar-dec) (functionp 'loadhist--foo-inc)))
+ (should (not (autoloadp (symbol-function 'loadhist--bar-dec))))
+ (should (not (autoloadp (symbol-function 'loadhist--foo-inc))))
+ (should (equal (list 40 42)
+ (list (loadhist--bar-dec 41) (loadhist--foo-inc 41))))
+ (unload-feature 'loadhist--bar)
+ (should (and (functionp 'loadhist--bar-dec) (functionp 'loadhist--foo-inc)))
+ (should (autoloadp (symbol-function 'loadhist--bar-dec)))
+ (should (not (autoloadp (symbol-function 'loadhist--foo-inc))))
+ (unload-feature 'loadhist--foo)
+ (should (null (symbol-function 'loadhist--bar-dec)))
+ (should (null (symbol-function 'loadhist--foo-inc)))
+ (should (null (get 'loadhist--bar-dec 'function-history)))
+ (should (null (get 'loadhist--foo-inc 'function-history))))
+
+(ert-deftest loadhist-tests-unload-feature-notnested ()
+ (add-to-list 'load-path (expand-file-name
+ "loadhist-resources/"
+ loadhist--tests-dir))
+ (load "loadhist--foo" nil t)
+ (load "loadhist--bar" nil t)
+ (should (equal (list 40 42)
+ (list (loadhist--bar-dec 41) (loadhist--foo-inc 41))))
+ (unload-feature 'loadhist--foo)
+ (should (functionp 'loadhist--bar-dec))
+ (should (not (autoloadp (symbol-function 'loadhist--bar-dec))))
+ (should (let ((f (symbol-function 'loadhist--foo-inc)))
+ ;; Both choices seem acceptable.
+ (or (null f) (autoloadp f))))
+ (unload-feature 'loadhist--bar)
+ (should (null (symbol-function 'loadhist--bar-dec)))
+ (should (null (symbol-function 'loadhist--foo-inc)))
+ (should (null (get 'loadhist--bar-dec 'function-history)))
+ (should (null (get 'loadhist--foo-inc 'function-history))))
+
+;;; loadhist-tests.el ends here
diff --git a/test/lisp/lpr-tests.el b/test/lisp/lpr-tests.el
new file mode 100644
index 00000000000..8e8179446d6
--- /dev/null
+++ b/test/lisp/lpr-tests.el
@@ -0,0 +1,41 @@
+;;; lpr-tests.el --- Tests for lpr.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'lpr)
+
+(ert-deftest lpr-test-printify-region ()
+ (with-temp-buffer
+ (insert "foo\^@-\^h\^k\^n-\^_\177bar")
+ (printify-region (point-min) (point-max))
+ (should (equal (buffer-string) "foo\\^@-\\^H\\^K\\^N-\\^_\\7fbar"))))
+
+(ert-deftest lpr-test-lpr-eval-switch ()
+ (should (equal (lpr-eval-switch "foo") "foo"))
+ (should (equal (lpr-eval-switch (lambda () "foo")) "foo"))
+ (let ((v "foo"))
+ (should (equal (lpr-eval-switch v) "foo")))
+ (should (equal (lpr-eval-switch (list #'identity "foo")) "foo"))
+ (should (equal (lpr-eval-switch 1) nil)))
+
+;;; lpr-tests.el ends here
diff --git a/test/lisp/ls-lisp-tests.el b/test/lisp/ls-lisp-tests.el
index 8e419d59bf4..39843defc2e 100644
--- a/test/lisp/ls-lisp-tests.el
+++ b/test/lisp/ls-lisp-tests.el
@@ -1,6 +1,6 @@
;;; ls-lisp-tests.el --- tests for ls-lisp.el -*- lexical-binding: t-*-
-;; Copyright (C) 2017 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2022 Free Software Foundation, Inc.
;; Author: Tino Calancha <tino.calancha@gmail.com>
;; Keywords:
@@ -25,7 +25,9 @@
;;; Code:
(require 'ert)
+(require 'ert-x)
(require 'ls-lisp)
+(require 'dired)
(ert-deftest ls-lisp-unload ()
"Test for https://debbugs.gnu.org/xxxxx ."
@@ -52,28 +54,29 @@
(kill-buffer buf)
(setq buf (dired (nconc (list dir) files)))
(should (looking-at "src"))
- (next-line) ; File names must be aligned.
+ (with-suppressed-warnings ((interactive-only next-line))
+ (next-line)) ; File names must be aligned.
(should (looking-at "src")))
(when (buffer-live-p buf) (kill-buffer buf)))))
(ert-deftest ls-lisp-test-bug27631 ()
"Test for https://debbugs.gnu.org/27631 ."
- (let* ((dir (make-temp-file "bug27631" 'dir))
- (dir1 (expand-file-name "dir1" dir))
- (dir2 (expand-file-name "dir2" dir))
- (default-directory dir)
- ls-lisp-use-insert-directory-program buf)
- (unwind-protect
- (progn
- (make-directory dir1)
- (make-directory dir2)
- (with-temp-file (expand-file-name "a.txt" dir1))
- (with-temp-file (expand-file-name "b.txt" dir2))
- (setq buf (dired (expand-file-name "dir*/*.txt" dir)))
- (dired-toggle-marks)
- (should (cdr (dired-get-marked-files))))
- (delete-directory dir 'recursive)
- (when (buffer-live-p buf) (kill-buffer buf)))))
+ (ert-with-temp-directory dir
+ :suffix "bug27631"
+ (let* ((dir1 (expand-file-name "dir1" dir))
+ (dir2 (expand-file-name "dir2" dir))
+ (default-directory dir)
+ ls-lisp-use-insert-directory-program buf)
+ (unwind-protect
+ (progn
+ (make-directory dir1)
+ (make-directory dir2)
+ (with-temp-file (expand-file-name "a.txt" dir1))
+ (with-temp-file (expand-file-name "b.txt" dir2))
+ (setq buf (dired (expand-file-name "dir*/*.txt" dir)))
+ (dired-toggle-marks)
+ (should (cdr (dired-get-marked-files))))
+ (when (buffer-live-p buf) (kill-buffer buf))))))
(ert-deftest ls-lisp-test-bug27693 ()
"Test for https://debbugs.gnu.org/27693 ."
@@ -90,5 +93,44 @@
(should (looking-back "[[:space:]]" (1- (point)))))
(when (buffer-live-p buf) (kill-buffer buf)))))
+(ert-deftest ls-lisp-test-bug55787 ()
+ "Test proper sorting by version."
+ (let ((files1 (vector "34 klmn-300dpi.jpg"
+ "34 klmn-300dpi.png"
+ "054_xyz.jpg"
+ "054_xyz.png"
+ "91 opqrs.jpg"
+ "91 opqrs.png"
+ "0717-abcd.jpg"
+ "0717-abcd.png"
+ "1935 uv.jpg"
+ "1935 uv.png"
+ "FFFF_fghk.jpg"
+ "FFFF_fghk.png"
+ "hhhh.jpg"
+ "hhhh.png"))
+ (files2 (vector "01.0" "10" "010" "01.2")))
+ (should (equal (sort files1
+ (lambda (x y)
+ (ls-lisp-version-lessp x y)))
+ '["0717-abcd.jpg"
+ "0717-abcd.png"
+ "054_xyz.jpg"
+ "054_xyz.png"
+ "34 klmn-300dpi.jpg"
+ "34 klmn-300dpi.png"
+ "91 opqrs.jpg"
+ "91 opqrs.png"
+ "1935 uv.jpg"
+ "1935 uv.png"
+ "FFFF_fghk.jpg"
+ "FFFF_fghk.png"
+ "hhhh.jpg"
+ "hhhh.png"]))
+ (should (equal (sort files2
+ (lambda (x y)
+ (ls-lisp-version-lessp x y)))
+ '["01.0" "01.2" "010" "10"]))))
+
(provide 'ls-lisp-tests)
;;; ls-lisp-tests.el ends here
diff --git a/test/lisp/mail/flow-fill-tests.el b/test/lisp/mail/flow-fill-tests.el
new file mode 100644
index 00000000000..8436a9627a8
--- /dev/null
+++ b/test/lisp/mail/flow-fill-tests.el
@@ -0,0 +1,107 @@
+;;; flow-fill-tests.el --- Tests for flow-fill.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2019-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'flow-fill)
+
+(ert-deftest fill-flow-tests-fill-flowed-decode ()
+ (let ((input
+ (concat
+ "> Thou villainous ill-breeding spongy dizzy-eyed \n"
+ "> reeky elf-skinned pigeon-egg! \n"
+ ">> Thou artless swag-bellied milk-livered \n"
+ ">> dismal-dreaming idle-headed scut!\n"
+ ">>> Thou errant folly-fallen spleeny reeling-ripe \n"
+ ">>> unmuzzled ratsbane!\n"
+ ">>>> Henceforth, the coding style is to be strictly \n"
+ ">>>> enforced, including the use of only upper case.\n"
+ ">>>>> I've noticed a lack of adherence to \n"
+ ">>>>> the coding \n"
+ ">>>>> styles, of late.\n"
+ ">>>>>> Any complaints?\n"))
+ (output
+ (concat
+ "> Thou villainous ill-breeding spongy dizzy-eyed reeky elf-skinned\n"
+ "> pigeon-egg! \n"
+ ">> Thou artless swag-bellied milk-livered dismal-dreaming idle-headed\n"
+ ">> scut!\n"
+ ">>> Thou errant folly-fallen spleeny reeling-ripe unmuzzled ratsbane!\n"
+ ">>>> Henceforth, the coding style is to be strictly enforced,\n"
+ ">>>> including the use of only upper case.\n"
+ ">>>>> I've noticed a lack of adherence to the coding styles, of late.\n"
+ ">>>>>> Any complaints?\n"))
+ (fill-flowed-display-column 69))
+ (with-temp-buffer
+ (insert input)
+ (fill-flowed)
+ (message "foo")
+ (should (equal (buffer-string) output)))))
+
+(ert-deftest fill-flow-tests-fill-flowed-encode ()
+ (let ((input
+ (concat
+ "> Thou villainous ill-breeding spongy dizzy-eyed \n"
+ "> reeky elf-skinned pigeon-egg! \n"
+ ">> Thou artless swag-bellied milk-livered \n"
+ ">> dismal-dreaming idle-headed scut!\n"
+ ">>> Thou errant folly-fallen spleeny reeling-ripe \n"
+ ">>> unmuzzled ratsbane!\n"
+ ">>>> Henceforth, the coding style is to be strictly \n"
+ ">>>> enforced, including the use of only upper case.\n"
+ ">>>>> I've noticed a lack of adherence to the coding \n"
+ ">>>>> styles, of late.\n"
+ ">>>>>> Any complaints?\n"))
+ (output
+ (concat
+ "> Thou villainous ill-breeding spongy dizzy-eyed \n"
+ "> reeky elf-skinned pigeon-egg! \n"
+ ">> Thou artless swag-bellied milk-livered \n"
+ ">> dismal-dreaming idle-headed scut!\n"
+ ">>> Thou errant folly-fallen spleeny reeling-ripe \n"
+ ">>> unmuzzled ratsbane!\n"
+ ">>>> Henceforth, the coding style is to be strictly \n"
+ ">>>> enforced, including the use of only upper case.\n"
+ ">>>>> I've noticed a lack of adherence to the coding \n"
+ ">>>>> styles, of late.\n"
+ ">>>>>> Any complaints?\n"))
+ (fill-flowed-display-column 69))
+ (with-temp-buffer
+ (insert input)
+ (fill-flowed-encode)
+ (should (equal (buffer-string) output)))))
+
+(ert-deftest fill-flow-tests-fill-flowed-stuffed ()
+ (let ((input
+ (concat
+ " > From space-stuffed with a \n"
+ "continuation.\n"))
+ (output
+ "> From space-stuffed with a continuation.\n")
+ (fill-flowed-display-column 69))
+ (with-temp-buffer
+ (insert input)
+ (fill-flowed)
+ (should (equal (buffer-string) output)))))
+
+(provide 'flow-fill-tests)
+;;; flow-fill-tests.el ends here
diff --git a/test/lisp/mail/footnote-tests.el b/test/lisp/mail/footnote-tests.el
new file mode 100644
index 00000000000..f3a35e3dfc6
--- /dev/null
+++ b/test/lisp/mail/footnote-tests.el
@@ -0,0 +1,47 @@
+;;; footnote-tests.el --- Tests for footnote-mode -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2019-2022 Free Software Foundation, Inc.
+
+;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
+;; Keywords:
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'footnote)
+
+(ert-deftest footnote-tests-same-place ()
+ (with-temp-buffer
+ (footnote-mode 1)
+ (insert "hello world")
+ (beginning-of-line) (forward-word)
+ (footnote-add-footnote)
+ (insert "footnote")
+ (footnote-back-to-message)
+ (should (equal (buffer-substring (point-min) (point))
+ "hello[1]"))
+ (beginning-of-line) (forward-word)
+ (footnote-add-footnote)
+ (insert "other footnote")
+ (footnote-back-to-message)
+ (should (equal (buffer-substring (point-min) (point))
+ "hello[1]"))
+ (should (equal (buffer-substring (point-min) (pos-eol))
+ "hello[1][2] world"))))
+
+(provide 'footnote-tests)
+;;; footnote-tests.el ends here
diff --git a/test/lisp/mail/ietf-drums-date-tests.el b/test/lisp/mail/ietf-drums-date-tests.el
new file mode 100644
index 00000000000..781d72d3529
--- /dev/null
+++ b/test/lisp/mail/ietf-drums-date-tests.el
@@ -0,0 +1,172 @@
+;;; ietf-drums-date-tests.el --- Test suite for ietf-drums-date.el -*- lexical-binding:t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; Author: Bob Rogers <rogers@rgrjr.com>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'ietf-drums)
+(require 'ietf-drums-date)
+
+(ert-deftest ietf-drums-date-tests ()
+ "Test basic ietf-drums-parse-date-string functionality."
+
+ ;; Test tokenization.
+ (should (equal (ietf-drums-date--tokenize-string " ") '()))
+ (should (equal (ietf-drums-date--tokenize-string " a b") '("a" "b")))
+ (should (equal (ietf-drums-date--tokenize-string "a bbc dde")
+ '("a" "bbc" "dde")))
+ (should (equal (ietf-drums-date--tokenize-string " , a 27 b,, c 14:32 ")
+ '("a" 27 "b" "c" "14:32")))
+ ;; Some folding whitespace tests.
+ (should (equal (ietf-drums-date--tokenize-string " a b (end) c" t)
+ '("a" "b")))
+ (should (equal (ietf-drums-date--tokenize-string "(quux)a (foo (bar)) b(baz)")
+ '("a" "b")))
+ (should (equal (ietf-drums-date--tokenize-string "a b\\cde")
+ ;; Strictly incorrect, but strictly unnecessary syntax.
+ '("a" "b\\cde")))
+ (should (equal (ietf-drums-date--tokenize-string "a b\\ de")
+ '("a" "b\\ de")))
+ (should (equal (ietf-drums-date--tokenize-string "a \\de \\(f")
+ '("a" "\\de" "\\(f")))
+
+ ;; Start with some compatible RFC822 dates.
+ (dolist (case '(("Mon, 22 Feb 2016 19:35:42 +0100"
+ (42 35 19 22 2 2016 1 -1 3600))
+ ("22 Feb 2016 19:35:42 +0100"
+ (42 35 19 22 2 2016 nil -1 3600))
+ ("Mon, 22 February 2016 19:35:42 +0100"
+ (42 35 19 22 2 2016 1 -1 3600))
+ ("Mon, 22 feb 2016 19:35:42 +0100"
+ (42 35 19 22 2 2016 1 -1 3600))
+ ("Monday, 22 february 2016 19:35:42 +0100"
+ (42 35 19 22 2 2016 1 -1 3600))
+ ("Monday, 22 february 2016 19:35:42 PST"
+ (42 35 19 22 2 2016 1 nil -28800))
+ ("Friday, 21 Sep 2018 13:47:58 PDT"
+ (58 47 13 21 9 2018 5 t -25200))
+ ("Friday, 21 Sep 2018 13:47:58 EDT"
+ (58 47 13 21 9 2018 5 t -14400))
+ ("Mon, 22 Feb 2016 19:35:42"
+ (42 35 19 22 2 2016 1 -1 nil))
+ ("Friday, 21 Sep 2018 13:47:58"
+ (58 47 13 21 9 2018 5 -1 nil))))
+ (let* ((input (car case))
+ (parsed (cadr case)))
+ ;; The input should parse the same without RFC822.
+ (should (equal (ietf-drums-parse-date-string input) parsed))
+ (should (equal (ietf-drums-parse-date-string input nil t) parsed))
+ ;; Check the encoded date (the official output, though the
+ ;; decoded-time is easier to debug).
+ (should (time-equal-p (ietf-drums-parse-date input)
+ (encode-time parsed)))))
+
+ ;; Two-digit years are not allowed by the "modern" format.
+ (should (equal (ietf-drums-parse-date-string "22 Feb 16 19:35:42 +0100")
+ '(42 35 19 22 2 2016 nil -1 3600)))
+ (should (equal (ietf-drums-parse-date-string "22 Feb 16 19:35:42 +0100" nil t)
+ '(nil nil nil 22 2 nil nil -1 nil)))
+ (should (equal (should-error (ietf-drums-parse-date-string
+ "22 Feb 16 19:35:42 +0100" t t))
+ '(date-parse-error "Four-digit years are required" 16)))
+ (should (equal (ietf-drums-parse-date-string "22 Feb 96 19:35:42 +0100")
+ '(42 35 19 22 2 1996 nil -1 3600)))
+ (should (equal (ietf-drums-parse-date-string "22 Feb 96 19:35:42 +0100" nil t)
+ '(nil nil nil 22 2 nil nil -1 nil)))
+ (should (equal (should-error (ietf-drums-parse-date-string
+ "22 Feb 96 19:35:42 +0100" t t))
+ '(date-parse-error "Four-digit years are required" 96)))
+
+ ;; Try some dates with comments.
+ (should (equal (ietf-drums-parse-date-string
+ "22 Feb (today) 16 19:35:42 +0100")
+ '(42 35 19 22 2 2016 nil -1 3600)))
+ (should (equal (ietf-drums-parse-date-string
+ "22 Feb (today) 16 19:35:42 +0100" nil t)
+ '(nil nil nil 22 2 nil nil -1 nil)))
+ (should (equal (should-error (ietf-drums-parse-date-string
+ "22 Feb (today) 16 19:35:42 +0100" t t))
+ '(date-parse-error "Expected a year" nil)))
+ (should (equal (ietf-drums-parse-date-string
+ "22 Feb 96 (long ago) 19:35:42 +0100")
+ '(42 35 19 22 2 1996 nil -1 3600)))
+ (should (equal (ietf-drums-parse-date-string
+ "Friday, 21 Sep(comment \\) with \\( parens)18 19:35:42")
+ '(42 35 19 21 9 2018 5 -1 nil)))
+ (should (equal (ietf-drums-parse-date-string
+ "Friday, 21 Sep 18 19:35:42 (unterminated comment")
+ '(42 35 19 21 9 2018 5 -1 nil)))
+
+ ;; Test some RFC822 error cases
+ (dolist (test '(("33 1 2022" ("Slot out of range" day 33 1 31))
+ ("0 1 2022" ("Slot out of range" day 0 1 31))
+ ("1 1 2020 2021" ("Expected an alphabetic month" 1))
+ ("1 Jan 2020 2021" ("Expected a time" 2021))
+ ("1 Jan 2020 20:21 2000" ("Expected a timezone" 2000))
+ ("1 Jan 2020 20:21 +0200 33" ("Extra token(s)" 33))))
+ (should (equal (should-error (ietf-drums-parse-date-string (car test) t))
+ (cons 'date-parse-error (cadr test)))))
+
+ (dolist (test '(("22 Feb 196" nil ;; bad year
+ ("Four-digit years are required" 196))
+ ("22 Feb 16 19:35:24" t ;; two-digit year
+ ("Four-digit years are required" 16))
+ ("22 Feb 96 19:35:42" t ;; two-digit year
+ ("Four-digit years are required" 96))
+ ("2 Feb 2021 1996" nil
+ ("Expected a time" 1996))
+ ("22 Fub 1996" nil
+ ("Expected an alphabetic month" "fub"))
+ ("1 Jan 2020 30" nil
+ ("Expected a time" 30))
+ ("1 Jan 2020 16:47 15:15" nil
+ ("Expected a timezone" "15:15"))
+ ("1 Jan 2020 16:47 +0800 -0800" t
+ ("Extra token(s)" "-0800"))
+ ;; Range tests
+ ("32 Dec 2021" nil
+ ("Slot out of range" day 32 1 31))
+ ("0 Dec 2021" nil
+ ("Slot out of range" day 0 1 31))
+ ("3 13 2021" nil
+ ("Expected an alphabetic month" 13))
+ ("3 Dec 0000" t
+ ("Four-digit years are required" 0))
+ ("3 Dec 20021" nil
+ ("Slot out of range" year 20021 1 9999))
+ ("1 Jan 2020 24:21:14" nil
+ ("Slot out of range" hour "24:21:14" 0 23))
+ ("1 Jan 2020 14:60:21" nil
+ ("Slot out of range" minute "14:60:21" 0 59))
+ ("1 Jan 2020 14:21:61" nil
+ ("Slot out of range" second "14:21:61" 0 60))))
+ (should (equal (should-error
+ (ietf-drums-parse-date-string (car test) t (cadr test)))
+ (cons 'date-parse-error (caddr test)))))
+ (should (equal (ietf-drums-parse-date-string
+ "1 Jan 2020 14:21:60") ;; a leap second!
+ '(60 21 14 1 1 2020 nil -1 nil))))
+
+(provide 'ietf-drums-date-tests)
+
+;;; ietf-drums-date-tests.el ends here
diff --git a/test/lisp/mail/ietf-drums-tests.el b/test/lisp/mail/ietf-drums-tests.el
new file mode 100644
index 00000000000..b13937bf736
--- /dev/null
+++ b/test/lisp/mail/ietf-drums-tests.el
@@ -0,0 +1,178 @@
+;;; ietf-drums-tests.el --- Test suite for ietf-drums.el -*- lexical-binding:t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; Author: Bob Rogers <rogers@rgrjr.com>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'ietf-drums)
+
+(ert-deftest ietf-drums-tests ()
+ "Test ietf-drums functionality."
+
+ ;; ietf-drums-remove-comments
+ (should (equal (ietf-drums-remove-comments "random string") "random string"))
+ (should (equal (ietf-drums-remove-comments "random \"non comment\" string")
+ "random \"non comment\" string"))
+ (should (equal (ietf-drums-remove-comments "random (comment) string")
+ "random string"))
+ (should (equal (ietf-drums-remove-comments "random (comment) (string)")
+ "random "))
+ (should (equal (ietf-drums-remove-comments
+ "random (first) (second (and)) (third) not fourth")
+ "random not fourth"))
+ ;; Test some unterminated comments.
+ (should (equal (ietf-drums-remove-comments "test an (unterminated comment")
+ "test an "))
+ (should (equal (ietf-drums-remove-comments "test an \"unterminated quote")
+ ;; returns the string unchanged (and doesn't barf).
+ "test an \"unterminated quote"))
+ (should (equal (ietf-drums-remove-comments
+ ;; note that double-quote is not special.
+ "test (unterminated comments with \"quoted (\" )stuff")
+ "test "))
+
+ ;; ietf-drums-remove-whitespace
+ (should (equal (ietf-drums-remove-whitespace "random string")
+ "randomstring"))
+ (should (equal (ietf-drums-remove-whitespace "random (comment) string")
+ "random(comment)string"))
+ (should (equal (ietf-drums-remove-whitespace "random \"non comment\" string")
+ "random\"non comment\"string"))
+ (should (equal (ietf-drums-remove-whitespace "random (comment)\r\n(string)")
+ "random(comment)(string)"))
+ (should (equal (ietf-drums-remove-whitespace
+ "random (first) (second (and)) (third) not fourth")
+ "random(first)(second (and))(third)notfourth"))
+ ;; Test some unterminated comments and quotes.
+ (should (equal (ietf-drums-remove-whitespace
+ "random (first) (second (and)) (third unterminated")
+ "random(first)(second (and))(third unterminated"))
+ (should (equal (ietf-drums-remove-whitespace "random \"non terminated string")
+ "random\"non terminated string"))
+
+ ;; ietf-drums-strip
+ (should (equal (ietf-drums-strip "random string") "randomstring"))
+ (should (equal (ietf-drums-strip "random \"non comment\" string")
+ "random\"non comment\"string"))
+ (should (equal (ietf-drums-strip "random (comment) string")
+ "randomstring"))
+ (should (equal (ietf-drums-strip "random (comment) (string)")
+ "random"))
+ (should (equal (ietf-drums-strip
+ "random (first) (second (and)) (third) not fourth")
+ "randomnotfourth"))
+
+ ;; ietf-drums-strip-cte
+ (should (equal (ietf-drums-strip-cte "random \"non comment\" string")
+ ;; [the " " is still in there because it was quoted
+ ;; through the "strip". -- rgr, 5-Feb-22.]
+ "randomnon commentstring"))
+ (should (equal (ietf-drums-strip-cte "ran(d)do<m@>[s;t:r],,in=g")
+ "randomstring"))
+
+ ;; ietf-drums-quote-string
+ (should (equal (ietf-drums-quote-string "Bob") "Bob"))
+ (should (equal (ietf-drums-quote-string "Foo Bar") "\"Foo Bar\""))
+
+ ;; ietf-drums-get-comment
+ (should (equal (ietf-drums-get-comment "random string") nil))
+ (should (equal (ietf-drums-get-comment "random (comment) string") "comment"))
+ (should (equal (ietf-drums-get-comment "random \"non comment\" string") nil))
+ (should (equal (ietf-drums-get-comment "\"still (non) comment\" string")
+ nil))
+ (should (equal (ietf-drums-get-comment "random (comment)\r\nstring")
+ "comment"))
+ (should (equal (ietf-drums-get-comment "random (comment) (string)") "string"))
+ (should (equal (ietf-drums-get-comment
+ "random (first) (second (and)) (third) not fourth")
+ "third"))
+
+ ;; ietf-drums-make-address
+ (should (equal (ietf-drums-make-address "Bob Rogers" "rogers@rgrjr.com")
+ "\"Bob Rogers\" <rogers@rgrjr.com>"))
+ (should (equal (ietf-drums-make-address nil "rogers@rgrjr.com")
+ "rogers@rgrjr.com"))
+
+ ;; ietf-drums-parse-address
+ (should (equal (ietf-drums-parse-address "foo@example.com")
+ '("foo@example.com")))
+ (should (equal (ietf-drums-parse-address "<foo@example.com>")
+ '("foo@example.com")))
+ (should (equal (ietf-drums-parse-address "'foo' <foo@example.com>")
+ '("foo@example.com" . "'foo'")))
+ (should (equal (ietf-drums-parse-address "foo <foo@example.com>")
+ '("foo@example.com" . "foo")))
+ (should (equal (ietf-drums-parse-address "foo <foo@example.com> bar")
+ ;; [contrary to RFC2822, which wants the display-name
+ ;; before the address. -- rgr, 5-Feb-22.]
+ '("foo@example.com" . "foo bar")))
+ (should (equal (ietf-drums-parse-address " <foo@example.com> foo ")
+ ;; [ditto. -- rgr, 5-Feb-22.]
+ '("foo@example.com" . "foo")))
+ (should (equal (ietf-drums-parse-address "foo@example.com (foo)")
+ '("foo@example.com" . "foo")))
+ (should (equal (ietf-drums-parse-address "Bar Baz <barbaz@example.com>")
+ '("barbaz@example.com" . "Bar Baz")))
+ (should (equal (ietf-drums-parse-address "barbaz@example.com (Bar Baz)")
+ '("barbaz@example.com" . "Bar Baz")))
+ (should (equal (ietf-drums-parse-address
+ "Bar Baz (ignored) <barbaz@example.com>")
+ '("barbaz@example.com" . "Bar Baz")))
+ (should (equal (ietf-drums-parse-address "<barbaz@example.com> Bar Baz")
+ '("barbaz@example.com" . "Bar Baz")))
+ (should (equal (ietf-drums-parse-address
+ "(Bar Baz not ignored) barbaz@example.com")
+ ;; [not strictly RFC2822, which expects the name
+ ;; comment after the address. -- rgr, 5-Feb-22.]
+ '("barbaz@example.com" . "Bar Baz not ignored")))
+ (should (equal (ietf-drums-parse-address
+ "(ignored) <barbaz@example.com> (Bar Baz not ignored)")
+ '("barbaz@example.com" . "Bar Baz not ignored")))
+ (should (equal (ietf-drums-parse-address
+ "(ignored) barbaz@example.com (Bar Baz not ignored)")
+ '("barbaz@example.com" . "Bar Baz not ignored")))
+ ;; Test for RFC2047 token decoding.
+ (should (equal (ietf-drums-parse-address
+ "=?utf-8?B?0JfQtNGA0LDMgdCy0YHRgtCy0YPQudGC0LUh?= <foo@goo.ru>"
+ t)
+ '("foo@goo.ru" . "Здра́вствуйте!")))
+
+ ;; ietf-drums-parse-addresses
+ ;; Note that it's not worth getting too elaborate here, as the heavy
+ ;; lifting is all done by ietf-drums-parse-address.
+ (should (equal (ietf-drums-parse-addresses "foo@example.com")
+ '(("foo@example.com"))))
+ (should (equal (ietf-drums-parse-addresses
+ "foo@example.com, bar@example.com")
+ '(("foo@example.com") ("bar@example.com"))))
+ (should (equal (ietf-drums-parse-addresses
+ "foo@example.com, quux, bar@example.com")
+ '(("foo@example.com") ("bar@example.com"))))
+ (should (equal (ietf-drums-parse-addresses
+ "foo@example.com, Quux Dude <quux@noop.org>, bar@example.com")
+ '(("foo@example.com") ("quux@noop.org" . "Quux Dude")
+ ("bar@example.com")))))
+
+(provide 'ietf-drums-tests)
+
+;;; ietf-drums-tests.el ends here
diff --git a/test/lisp/mail/mail-extr-tests.el b/test/lisp/mail/mail-extr-tests.el
new file mode 100644
index 00000000000..a8f0c605cb0
--- /dev/null
+++ b/test/lisp/mail/mail-extr-tests.el
@@ -0,0 +1,41 @@
+;;; mail-extr-tests.el --- Tests for mail-extr.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'mail-extr)
+
+(defconst mail-extract-test-cases
+ '(("foo@example.org" . (nil "foo@example.org"))
+ ("J. Random Hacker <foo@example.org>" . ("J. Random Hacker" "foo@example.org"))
+ ("\"J. Random Hacker\" <foo@example.org>" . ("J. Random Hacker" "foo@example.org"))
+ ("Ååå Äää <foo@example.org>" . ("Ååå Äää" "foo@example.org"))))
+
+(ert-deftest mail-extract-address-components ()
+ (dolist (test mail-extract-test-cases)
+ (should (equal (mail-extract-address-components (car test)) (cdr test)))))
+
+(ert-deftest what-domain ()
+ (should (equal (what-domain "cu") "CU: Cuba")))
+
+(provide 'mail-extr-tests)
+;;; mail-extr-tests.el ends here
diff --git a/test/lisp/mail/mail-parse-tests.el b/test/lisp/mail/mail-parse-tests.el
new file mode 100644
index 00000000000..f5e6f1fb034
--- /dev/null
+++ b/test/lisp/mail/mail-parse-tests.el
@@ -0,0 +1,54 @@
+;;; mail-parse-tests.el --- tests for mail-parse.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'mail-parse)
+(require 'subr-x)
+
+(ert-deftest test-mail-header-parse-address-lax ()
+ (should (equal (mail-header-parse-address-lax
+ "Lars Ingebrigtsen <larsi@gnus.org>")
+ '("larsi@gnus.org" . "Lars Ingebrigtsen")))
+ (should (equal (mail-header-parse-address-lax
+ "Lars Ingebrigtsen larsi@gnus.org>")
+ '("larsi@gnus.org" . "Lars Ingebrigtsen")))
+ (should (equal (mail-header-parse-address-lax
+ "Lars Ingebrigtsen larsi@gnus.org")
+ '("larsi@gnus.org" . "Lars Ingebrigtsen")))
+ (should (equal (mail-header-parse-address-lax
+ "larsi@gnus.org (Lars Ingebrigtsen)")
+ '("larsi@gnus.org " . "Lars Ingebrigtsen")))
+ (should (equal (mail-header-parse-address-lax "larsi@gnus.org")
+ '("larsi@gnus.org")))
+ (should (equal (mail-header-parse-address-lax "foo")
+ nil)))
+
+(ert-deftest test-mail-header-parse-addresses-lax ()
+ (should (equal (mail-header-parse-addresses-lax
+ "Bob Weiner <rsw@gnu.org>, Mats Lidell <matsl@gnu.org>")
+ '(("rsw@gnu.org" . "Bob Weiner")
+ ("matsl@gnu.org" . "Mats Lidell")))))
+
+(provide 'mail-parse-tests)
+
+;;; mail-parse-tests.el ends here
diff --git a/test/lisp/mail/mail-utils-tests.el b/test/lisp/mail/mail-utils-tests.el
new file mode 100644
index 00000000000..29a9b9eeb96
--- /dev/null
+++ b/test/lisp/mail/mail-utils-tests.el
@@ -0,0 +1,105 @@
+;;; mail-utils-tests.el --- tests for mail-utils.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+;; Author: Stefan Kangas <stefankangas@gmail.com>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'sasl)
+(require 'mail-utils)
+
+(ert-deftest mail-utils-tests-mail-quote-printable ()
+ (should (equal (mail-quote-printable "abc") "abc"))
+ (should (equal (mail-quote-printable "åäö") "=E5=E4=F6"))
+ (should (equal (mail-quote-printable "åäö" t) "=?ISO-8859-1?Q?=E5=E4=F6?=")))
+
+(ert-deftest mail-utils-tests-mail-quote-printable-region ()
+ (with-temp-buffer
+ (insert "?=\"\"")
+ (mail-quote-printable-region (point-min) (point-max))
+ (should (equal (buffer-string) "=3F=3D=22=22")))
+ (with-temp-buffer
+ (insert "x")
+ (mail-quote-printable-region (point-min) (point-max) t)
+ (should (equal (buffer-string) "=?=?ISO-8859-1?Q?x"))))
+
+(ert-deftest mail-utils-tests-mail-unquote-printable ()
+ (should (equal (mail-unquote-printable "=E5=E4=F6") "åäö"))
+ (should (equal (mail-unquote-printable "=?ISO-8859-1?Q?=E5=E4=F6?=" t) "åäö")))
+
+(ert-deftest mail-utils-tests-mail-unquote-printable-region ()
+ (with-temp-buffer
+ (insert "=E5=E4=F6")
+ (mail-unquote-printable-region (point-min) (point-max))
+ (should (equal (buffer-string) "åäö")))
+ (with-temp-buffer
+ (insert "=?ISO-8859-1?Q?=E5=E4=F6?=")
+ (mail-unquote-printable-region (point-min) (point-max) t)
+ (should (equal (buffer-string) "åäö"))))
+
+(ert-deftest mail-utils-tests-mail-strip-quoted-names ()
+ (should (equal (mail-strip-quoted-names
+ "\"foo\" <foo@example.org>, bar@example.org")
+ "foo@example.org, bar@example.org")))
+
+(ert-deftest mail-utils-tests-mail-dont-reply-to ()
+ (let ((mail-dont-reply-to-names "foo@example.org"))
+ (should (equal (mail-dont-reply-to "foo@example.org, bar@example.org")
+ "bar@example.org"))))
+
+
+(ert-deftest mail-utils-tests-mail-fetch-field ()
+ (with-temp-buffer
+ (insert "Foo: bar\nBaz: zut")
+ (should (equal (mail-fetch-field "Foo") "bar"))))
+
+(ert-deftest mail-utils-tests-mail-parse-comma-list ()
+ (with-temp-buffer
+ (insert "foo@example.org,bar@example.org,baz@example.org")
+ (goto-char (point-min))
+ (should (equal (mail-parse-comma-list)
+ '("baz@example.org" "bar@example.org" "foo@example.org")))))
+
+(ert-deftest mail-utils-tests-mail-comma-list-regexp ()
+ (should (equal (mail-comma-list-regexp
+ "foo@example.org,bar@example.org,baz@example.org")
+ "foo@example.org\\|bar@example.org\\|baz@example.org")))
+
+(ert-deftest mail-utils-tests-mail-rfc822-time-zone ()
+ (with-suppressed-warnings ((obsolete mail-rfc822-time-zone))
+ (should (stringp (mail-rfc822-time-zone (current-time))))))
+
+(ert-deftest mail-utils-test-mail-rfc822-date/contains-year ()
+ (should (string-match (rx " 20" digit digit " ")
+ (mail-rfc822-date))))
+
+(ert-deftest mail-utils-test-mail-mbox-from ()
+ (with-temp-buffer
+ (insert "Subject: Hello
+From: jrh@example.org
+To: emacs-devel@gnu.org
+Date: Sun, 07 Feb 2021 22:46:37 -0500")
+ (should (equal (mail-mbox-from)
+ "From jrh@example.org Sun Feb 7 22:46:37 2021\n"))))
+
+(provide 'mail-utils-tests)
+;;; mail-utils-tests.el ends here
diff --git a/test/lisp/mail/qp-tests.el b/test/lisp/mail/qp-tests.el
new file mode 100644
index 00000000000..e8e58063b9c
--- /dev/null
+++ b/test/lisp/mail/qp-tests.el
@@ -0,0 +1,74 @@
+;;; qp-tests.el --- Tests for qp.el -*- lexical-binding:t; coding:utf-8 -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+;; Author: Stefan Kangas <stefankangas@gmail.com>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'qp)
+
+;; Quote by Antoine de Saint-Exupéry, Citadelle (1948)
+;; from https://en.wikipedia.org/wiki/Quoted-printable
+(defvar qp-tests-quote-qp
+ (concat "J'interdis aux marchands de vanter trop leurs marchandises. Car ils se font =\n"
+ "vite p=C3=A9dagogues et t'enseignent comme but ce qui n'est par essence qu'=\n"
+ "un moyen, et te trompant ainsi sur la route =C3=A0 suivre les voil=C3=A0 bi=\n"
+ "ent=C3=B4t qui te d=C3=A9gradent, car si leur musique est vulgaire ils te f=\n"
+ "abriquent pour te la vendre une =C3=A2me vulgaire."))
+(defvar qp-tests-quote-utf8
+ (concat "J'interdis aux marchands de vanter trop leurs marchandises. Car ils se font "
+ "vite pédagogues et t'enseignent comme but ce qui n'est par essence qu'"
+ "un moyen, et te trompant ainsi sur la route à suivre les voilà bi"
+ "entôt qui te dégradent, car si leur musique est vulgaire ils te f"
+ "abriquent pour te la vendre une âme vulgaire."))
+
+(ert-deftest qp-test--quoted-printable-decode-region ()
+ (with-temp-buffer
+ (insert qp-tests-quote-qp)
+ (encode-coding-region (point-min) (point-max) 'utf-8)
+ (quoted-printable-decode-region (point-min) (point-max) 'utf-8)
+ (should (equal (buffer-string) qp-tests-quote-utf8))))
+
+(ert-deftest qp-test--quoted-printable-decode-string ()
+ (should (equal (quoted-printable-decode-string "foo!") "foo!"))
+ (should (equal (quoted-printable-decode-string "=0C") "\^L"))
+ (should (equal (quoted-printable-decode-string "=3D") "="))
+ (should (equal (quoted-printable-decode-string "=A1Hola, se=F1or!?")
+ "\241Hola, se\361or!?")))
+
+(ert-deftest qp-test--quoted-printable-encode-region ()
+ (with-temp-buffer
+ (insert (make-string 26 ?=))
+ ;; (encode-coding-region (point-min) (point-max) 'utf-8)
+ (quoted-printable-encode-region (point-min) (point-max) t)
+ (should (equal (buffer-string)
+ (concat "=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D"
+ "=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=\n=3D")))))
+
+(ert-deftest qp-test--quoted-printable-encode-string ()
+ (should (equal (quoted-printable-encode-string "\241Hola, se\361or!?")
+ "=A1Hola, se=F1or!?"))
+ ;; Multibyte character.
+ (should-error (quoted-printable-encode-string "å")))
+
+(provide 'qp-tests)
+;;; qp-tests.el ends here
diff --git a/test/lisp/mail/rfc2045-tests.el b/test/lisp/mail/rfc2045-tests.el
new file mode 100644
index 00000000000..c65a0011c70
--- /dev/null
+++ b/test/lisp/mail/rfc2045-tests.el
@@ -0,0 +1,37 @@
+;;; rfc2045-tests.el --- Tests for rfc2045.el -*- lexical-binding:t -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+;; Author: Stefan Kangas <stefankangas@gmail.com>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'rfc2045)
+
+(ert-deftest rfc2045-test-encode-string ()
+ (should (equal (rfc2045-encode-string "foo" "bar") "foo=bar"))
+ (should (equal (rfc2045-encode-string "foo" "bar-baz") "foo=bar-baz"))
+ (should (equal (rfc2045-encode-string "foo" "bar baz") "foo=\"bar baz\""))
+ (should (equal (rfc2045-encode-string "foo" "bar\tbaz") "foo=\"bar\tbaz\""))
+ (should (equal (rfc2045-encode-string "foo" "bar\nbaz") "foo=\"bar\nbaz\"")))
+
+(provide 'rfc2045-tests)
+;;; rfc2045-tests.el ends here
diff --git a/test/lisp/mail/rfc2047-tests.el b/test/lisp/mail/rfc2047-tests.el
new file mode 100644
index 00000000000..6e50ce2f320
--- /dev/null
+++ b/test/lisp/mail/rfc2047-tests.el
@@ -0,0 +1,60 @@
+;;; rfc2047-tests.el --- tests for rfc2047.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2019-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'rfc2047)
+
+(defun test-rfc2047 (before after)
+ (with-temp-buffer
+ (insert before)
+ (goto-char (point-min))
+ (rfc2047-fold-field)
+ (should (equal (buffer-string) after))))
+
+(ert-deftest test-rfc2047-fold-short ()
+ (test-rfc2047
+ "Organization: Lots Of Short Words Here Lots Of Short Words Here Lots Of Short Words Here\n"
+
+ "Organization: Lots Of Short Words Here Lots Of Short Words Here Lots Of
+ Short Words Here
+"))
+
+(ert-deftest test-rfc2047-fold-encoded ()
+ (test-rfc2047
+ "Subject: This is =?utf-8?Q?=C3=A1?= long subject that's =?utf-8?Q?v=C3=A9ry?= long and =?utf-8?Q?ver=C3=BD?= encoded yes indeed it =?utf-8?Q?=C3=ADs?=\n"
+ "Subject: This is =?utf-8?Q?=C3=A1?= long subject that's
+ =?utf-8?Q?v=C3=A9ry?= long and =?utf-8?Q?ver=C3=BD?= encoded yes indeed it
+ =?utf-8?Q?=C3=ADs?=
+"))
+
+(ert-deftest test-rfc2047-fold-long ()
+ (test-rfc2047
+ "Organization: verylongverylongverylongverylongverylongverylongverylongverylongverylongword and then\n"
+ "Organization: verylongverylongverylongverylongverylongverylongverylongverylongverylongword
+ and then
+"))
+
+(ert-deftest test-rfc2047-fold-long-short ()
+ (test-rfc2047
+ "Organization: verylongverylongverylongverylongverylongverylongverylongverylongverylongword\n"
+ "Organization: verylongverylongverylongverylongverylongverylongverylongverylongverylongword\n"))
+
+;;; rfc2047-tests.el ends here
diff --git a/test/lisp/mail/rfc6068-tests.el b/test/lisp/mail/rfc6068-tests.el
new file mode 100644
index 00000000000..0efbb68cc2f
--- /dev/null
+++ b/test/lisp/mail/rfc6068-tests.el
@@ -0,0 +1,52 @@
+;;; rfc6068-tests.el --- Tests for rfc6068.el -*- lexical-binding:t -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'rfc6068)
+
+(ert-deftest rfc6068-unhexify-string ()
+ (should (equal (rfc6068-unhexify-string "hello%20there") "hello there"))
+ (should (equal (rfc6068-unhexify-string "caf%C3%A9") "café")))
+
+(ert-deftest rfc6068-parse-mailto-url ()
+ (should
+ (equal
+ (rfc6068-parse-mailto-url "mailto:foo@example.org?subject=Foo&bar=baz")
+ '(("To" . "foo@example.org") ("Subject" . "Foo") ("Bar" . "baz"))))
+ (should
+ (equal
+ (rfc6068-parse-mailto-url "mailto:foo@bar.com?to=bar@example.org")
+ '(("To" . "foo@bar.com, bar@example.org"))))
+ (should
+ (equal (rfc6068-parse-mailto-url "mailto:foo@bar.com?subject=bar%20baz")
+ '(("To" . "foo@bar.com") ("Subject" . "bar baz"))))
+ (should
+ (equal (rfc6068-parse-mailto-url "mailto:foo@bar.com?subject=bar%20baz&to=other@bar.com")
+ '(("Subject" . "bar baz") ("To" . "foo@bar.com, other@bar.com"))))
+ (should
+ (equal (rfc6068-parse-mailto-url "mailto:user@example.org?subject=caf%C3%A9&body=caf%C3%A9")
+ '(("To" . "user@example.org") ("Subject" . "café") ("Body" . "café")))))
+
+(provide 'rfc6068-tests)
+
+;;; rfc6068-tests.el ends here
diff --git a/test/lisp/mail/rfc822-tests.el b/test/lisp/mail/rfc822-tests.el
new file mode 100644
index 00000000000..ff29dac4277
--- /dev/null
+++ b/test/lisp/mail/rfc822-tests.el
@@ -0,0 +1,83 @@
+;;; rfc822-tests.el --- Tests for rfc822.el -*- lexical-binding:t -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'rfc822)
+
+(defmacro rfc822-tests-deftest (email desc &optional valid)
+ `(ert-deftest ,(intern (format "rfc822-email-%s-%s"
+ (if valid "valid" "invalid")
+ desc)) ()
+ (if ,valid
+ (should (equal (rfc822-addresses ,email) (list ,email)))
+ (let ((addresses (rfc822-addresses ,email)))
+ ;; `rfc822-addresses' returns a string if parsing fails.
+ (while (and (consp addresses)
+ (not (eq (string-to-char (car addresses)) ?\()))
+ (setq addresses (cdr addresses)))
+ ;; Found saved error.
+ (should (= (length addresses) 1))))))
+
+;;;; Valid emails
+
+(rfc822-tests-deftest "email@example.org" "email" t)
+(rfc822-tests-deftest "firstname.lastname@example.org" "dot-in-address" t)
+(rfc822-tests-deftest "email@subdomain.example.org" "dot-in-subdomain" t)
+(rfc822-tests-deftest "firstname+lastname@example.org" "contains-plus-sign" t)
+(rfc822-tests-deftest "email@123.123.123.123" "domain-valid-ip" t)
+(rfc822-tests-deftest "email@[123.123.123.123]" "domain-valid-ip-square-bracket" t)
+(rfc822-tests-deftest "\"email\"@example.org" "quotes-around-email" t)
+(rfc822-tests-deftest "1234567890@example.org" "digits-in-address" t)
+(rfc822-tests-deftest "email@example-one.com" "dash-in-domain-name" t)
+(rfc822-tests-deftest "_______@example.org" "underscore-in-address" t)
+(rfc822-tests-deftest "email@example.name" "dotname-tld" t)
+(rfc822-tests-deftest "email@example.co.jp" "dot-in-tld" t)
+(rfc822-tests-deftest "firstname-lastname@example.org" "dash-in-address" t)
+(rfc822-tests-deftest "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghiklm@example.org" "address-long" t)
+
+;;;; Invalid emails
+
+(rfc822-tests-deftest "#@%^%#$@#$@#.com" "garbage")
+(rfc822-tests-deftest "@example.org" "missing-username")
+(rfc822-tests-deftest "email@example@example.org" "two-at-signs")
+(rfc822-tests-deftest ".email@example.org" "address-leading-dot")
+(rfc822-tests-deftest "email.@example.org" "address-trailing-dot")
+(rfc822-tests-deftest "email..email@example.org" "address-multiple-dots")
+(rfc822-tests-deftest "email@example..org" "domain-multiple-dots")
+(rfc822-tests-deftest "email@example.org." "domain-trailing-dot")
+(rfc822-tests-deftest "email@.example.org" "domain-leading-dot")
+(rfc822-tests-deftest "test\\@test@example.org" "address-escaped-at-sign")
+
+;; FIXME: Should these fail?
+;; (rfc822-tests-deftest "plainaddress" "missing-at-sign-and-domain")
+;; (rfc822-tests-deftest "email@example.org (J. Random Hacker)" "text-following-email")
+;; (rfc822-tests-deftest "email@-example.org" "leading-dash-in-domain-is-invalid")
+;; (rfc822-tests-deftest "email@example-.org" "trailing-dash-in-domain-is-invalid")
+;; (rfc822-tests-deftest "あいうえお@example.org" "address-unicode-chars")
+;; (rfc822-tests-deftest "email.example.org" "missing-at")
+;; (rfc822-tests-deftest "email@111.222.333.44444" "invalid-IP-format")
+;; (rfc822-tests-deftest "email@domain" "missing-top-level-domain")
+;; (rfc822-tests-deftest "email@domain.web" ".web-is-not-a-valid-top-level-domain")
+
+(provide 'rfc822-tests)
+;;; rfc822-tests.el ends here
diff --git a/test/lisp/mail/rmail-tests.el b/test/lisp/mail/rmail-tests.el
index b0b86764226..44394cd52ed 100644
--- a/test/lisp/mail/rmail-tests.el
+++ b/test/lisp/mail/rmail-tests.el
@@ -1,6 +1,6 @@
;;; rmail-tests.el --- Test suite. -*- lexical-binding: t -*-
-;; Copyright (C) 2015-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2022 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -23,7 +23,7 @@
(ert-deftest rmail-autoload ()
- "Tests to see whether reftex-auc has been autoloaded"
+ "Test that `rmail-edit-current-message' has been autoloaded."
(should
(fboundp 'rmail-edit-current-message))
(should
@@ -32,4 +32,4 @@
'rmail-edit-current-message))))
(provide 'rmail-tests)
-;; rmail-tests.el ends here
+;;; rmail-tests.el ends here
diff --git a/test/manual/rmailmm.el b/test/lisp/mail/rmailmm-tests.el
index 8ec10d83e51..5d1ac6d6306 100644
--- a/test/manual/rmailmm.el
+++ b/test/lisp/mail/rmailmm-tests.el
@@ -1,6 +1,6 @@
-;;; rmailmm.el --- tests for mail/rmailmm.el
+;;; rmailmm-tests.el --- Tests for rmailmm.el -*- lexical-binding:t -*-
-;; Copyright (C) 2006-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2006-2022 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -19,27 +19,42 @@
;;; Commentary:
+;; Converted to ert from previous manual tests.
+
+;; FIXME: Some of these still lack a condition for success.
+
;;; Code:
+(require 'ert)
(require 'rmailmm)
-(defun rmailmm-test-handler ()
+(ert-deftest rmailmm-test-handler ()
"Test of a mail using no MIME parts at all."
(let ((mail "To: alex@gnu.org
Content-Type: text/plain; charset=koi8-r
Content-Transfer-Encoding: 8bit
MIME-Version: 1.0
-\372\304\322\301\327\323\324\327\325\312\324\305\41"))
- (switch-to-buffer (get-buffer-create "*test*"))
- (erase-buffer)
- (set-buffer-multibyte nil)
- (insert mail)
- (rmail-mime-show t)
- (set-buffer-multibyte t)))
+\372\304\322\301\327\323\324\327\325\312\324\305\41")
+ (correct "To: alex@gnu.org
+Content-Type: text/plain; charset=koi8-r
+Content-Transfer-Encoding: 8bit
+MIME-Version: 1.0
-(defun rmailmm-test-bulk-handler ()
+Здравствуйте!
+"))
+ (with-temp-buffer
+ (erase-buffer)
+ (set-buffer-multibyte nil)
+ (insert mail)
+ (rmail-mime-show t)
+ (set-buffer-multibyte t)
+ (should (equal (buffer-string) correct)))))
+
+;;;; FIXME: This doesn't seem to be working.
+(ert-deftest rmailmm-test-bulk-handler ()
"Test of a mail used as an example in RFC 2183."
+ :tags '(:unstable)
(let ((mail "Content-Type: image/jpeg
Content-Disposition: attachment; filename=genome.jpeg;
modification-date=\"Wed, 12 Feb 1997 16:29:51 -0500\";
@@ -54,13 +69,17 @@ WATQdRUvAK0Bnmshmtn79PpaLBbbOZkjKvRnjRZoRswOkG1wFchKew2g9wXVJVZL/m4+B+vv
UDwbgUEAUmk2Zyg101d6PhCDySgAvTvDgKiuOrc4dLxUb7UMnhGIexyI+d6U+ABuNAP4Simx
lgAAAABJRU5ErkJggg==
"))
- (switch-to-buffer (get-buffer-create "*test*"))
- (erase-buffer)
- (insert mail)
- (rmail-mime-show)))
-
-(defun rmailmm-test-multipart-handler ()
+ (with-temp-buffer
+ (erase-buffer)
+ (insert mail)
+ (rmail-mime-show)
+ ;; FIXME: What is the condition for success?
+ )))
+
+;; FIXME: Has no condition for success -- see below.
+(ert-deftest rmailmm-test-multipart-handler ()
"Test of a mail used as an example in RFC 2046."
+ :tags '(:unstable)
(let ((mail "From: Nathaniel Borenstein <nsb@bellcore.com>
To: Ned Freed <ned@innosoft.com>
Date: Sun, 21 Mar 1993 23:56:48 -0800 (PST)
@@ -88,6 +107,11 @@ This is the epilogue. It is also to be ignored."))
(switch-to-buffer (get-buffer-create "*test*"))
(erase-buffer)
(insert mail)
- (rmail-mime-show t)))
+ (rmail-mime-show t)
+ ;; FIXME: What is the condition for success?
+ (should nil) ; expected fail for now
+ ))
+
+(provide 'rmailmm-tests)
-;;; rmailmm.el ends here
+;;; rmailmm-tests.el ends here
diff --git a/test/lisp/mail/undigest-tests.el b/test/lisp/mail/undigest-tests.el
new file mode 100644
index 00000000000..d52c9f9c5ab
--- /dev/null
+++ b/test/lisp/mail/undigest-tests.el
@@ -0,0 +1,359 @@
+;;; undigest-tests.el --- Tests for undigest.el -*- lexical-binding:t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'ert-x)
+(require 'rmail)
+(require 'undigest)
+
+;;; Variables:
+;; Some digests for testing.
+(defvar rmail-rfc934-digest "From tester Fri Jan 24 00:00:00 2022
+From: Digester <digester@digester.com>
+To: Undigester <undigester@undigester.com>
+Date: ddd, dd mmm yy hh:mm:ss zzz
+Subject: Testing you
+
+Testing the undigester.
+
+------- Message sep
+
+From: NN1 <nn1@nn1.com>
+To: Digester <digester@digester.com>
+Date: ddd, dd mmm yy hh:mm:ss zzz
+Subject: Message one
+
+This is message one.
+
+------- Message sep
+
+From: NN2 <nn2@nn2.com>
+To: Digester <digester@digester.com>
+Date: ddd, dd mmm yy hh:mm:ss zzz
+Subject: Message two
+
+This is message two.
+"
+
+ "RFC 934 digest.")
+
+(defvar rmail-rfc1153-digest-strict "From tester Fri Jan 24 00:00:00 2022
+Date: ddd, dd mmm yy hh:mm:ss zzz
+From: Digester <digester@digester.com>
+To: Undigester <undigester@undigester.com>
+Date: ddd, dd mmm yy hh:mm:ss zzz
+Subject: Testing you
+
+Some mailing list information.
+
+Today's Topics:
+
+ 1. Message One Subject (Sender)
+ 2. Message Two Subject (Sender)
+
+----------------------------------------------------------------------
+
+Date: ddd, dd mmm yy hh:mm:ss zzz
+From: NN1 <nn1@nn1.com>
+Subject: Message One Subject
+
+This is message one.
+
+------------------------------
+
+Date: ddd, dd mmm yy hh:mm:ss zzz
+From: NN2 <nn2@nn2.com>
+Subject: Message Two Subject
+
+This is message two.
+
+------------------------------
+
+End of Digest.
+************************************
+"
+ "RFC 1153 strict style digest.")
+
+(defvar rmail-rfc1153-digest-less-strict "From tester Fri Jan 24 00:00:00 2022
+From: Digester <digester@digester.com>
+To: Undigester <undigester@undigester.com>
+Date: ddd, dd mmm yy hh:mm:ss zzz
+Subject: Testing you
+
+Some mailing list information.
+
+Today's Topics:
+
+ 1. Message One Subject (Sender)
+ 2. Message Two Subject (Sender)
+
+----------------------------------------------------------------------
+
+Date: ddd, dd mmm yy hh:mm:ss zzz
+From: NN1 <nn1@nn1.com>
+Subject: Message One Subject
+
+This is message one.
+
+------------------------------
+
+Date: ddd, dd mmm yy hh:mm:ss zzz
+From: NN2 <nn2@nn2.com>
+Subject: Message Two Subject
+
+This is message two.
+
+------------------------------
+
+Subject: Digest Footer
+
+End of Sbcl-help Digest, Vol 158, Issue 4
+*****************************************
+"
+ "RFC 1153 style digest, with a Subject header.")
+
+(defvar rmail-rfc1153-digest-sloppy "From tester Fri Jan 24 00:00:00 2022
+From: Digester <digester@digester.com>
+To: Undigester <undigester@undigester.com>
+Date: ddd, dd mmm yy hh:mm:ss zzz
+Subject: Testing you
+
+Some mailing list information.
+
+Today's Topics:
+
+ 1. Message One Subject (Sender)
+ 2. Message Two Subject (Sender)
+
+----------------------------------------------------------------------
+
+Date: ddd, dd mmm yy hh:mm:ss zzz
+From: NN1 <nn1@nn1.com>
+Subject: Message One Subject
+
+This is message one.
+
+------------------------------
+
+Date: ddd, dd mmm yy hh:mm:ss zzz
+From: NN2 <nn2@nn2.com>
+Subject: Message Two Subject
+
+This is message two.
+
+------------------------------
+
+Subject: Digest Footer
+
+______________________________________________
+Some blurb.
+
+End of Digest.
+************************************
+"
+ "RFC 1153 sloppy style digest.")
+
+(defvar rmail-rfc1521-mime-digest "From tester Fri Jan 24 00:00:00 2022
+From: Digester <digester@digester.com>
+To: Undigester <undigester@undigester.com>
+Date: ddd, dd mmm yy hh:mm:ss zzz
+Subject: Test digest
+MIME-Version: 1.0
+Content-Type: multipart/digest; boundary=\"----- =_aaaaaaaaaa0\"
+
+------- =_aaaaaaaaaa0
+Content-Type: message/rfc822
+
+From: NN1 <nn1@nn1.com>
+To: Digester <digester@digester.com>
+Date: ddd, dd mmm yy hh:mm:ss zzz
+Subject: Message one
+
+Message one.
+
+------- =_aaaaaaaaaa0
+
+From: NN2 <nn2@nn2.com>
+To: Digester <digester@digester.com>
+Date: ddd, dd mmm yy hh:mm:ss zzz
+Subject: Message two
+
+Message two.
+
+------- =_aaaaaaaaaa0
+"
+ "RFC 1521 style MIME digest.")
+
+(defvar rmail-multipart-mixed-digest
+ "From tester Fri Jan 24 00:00:00 2022
+From: Digester <digester@digester.com>
+To: Undigester <undigester@undigester.com>
+Date: ddd, dd mmm yy hh:mm:ss zzz
+Subject: Test digest
+Content-Type: multipart/mixed; boundary=\"===============2529375068597856000==\"
+MIME-Version: 1.0
+
+--===============2529375068597856000==
+Content-Type: text/plain;
+MIME-Version: 1.0
+Content-Description: Today's Topics
+
+Some message.
+
+--===============2529375068597856000==
+Content-Type: multipart/digest; boundary=\"===============6060050777038710134==\"
+MIME-Version: 1.0
+
+--===============6060050777038710134==
+Content-Type: message/rfc822
+MIME-Version: 1.0
+
+From: NN1 <nn1@nn1.com>
+To: Digester <digester@digester.com>
+Date: ddd, dd mmm yy hh:mm:ss zzz
+Subject: Message one
+
+Message one.
+
+--===============6060050777038710134==
+Content-Type: message/rfc822
+MIME-Version: 1.0
+
+From: NN2 <nn2@nn2.com>
+To: Digester <digester@digester.com>
+Date: ddd, dd mmm yy hh:mm:ss zzz
+Subject: Message two
+
+Message two.
+
+--===============6060050777038710134==--
+
+--===============2529375068597856000==
+Content-Type: text/plain;
+MIME-Version: 1.0
+Content-Description: Digest Footer
+
+The footer.
+
+--===============2529375068597856000==--"
+ "RFC 1521 digest inside a multipart/mixed message.")
+
+;;; Utils:
+(defun rmail-message-content (message)
+ "Return the content of the message numbered MESSAGE."
+ (rmail-show-message message)
+ (let ((beg (rmail-msgbeg rmail-current-message))
+ (end (rmail-msgend rmail-current-message)))
+ (with-current-buffer rmail-view-buffer
+ (save-excursion
+ (goto-char beg)
+ (search-forward "\n\n" end nil)
+ (buffer-substring-no-properties (match-end 0) end)))))
+
+;;; Tests:
+(ert-deftest rmail-undigest-test-rfc934-digest ()
+ "Test that we can undigest a RFC 934 digest."
+ (ert-with-temp-file file
+ :text rmail-rfc934-digest
+ ;; Rmail reads mbox files literally, so we must make sure the
+ ;; temporary mbox file has Unix-style EOLs.
+ :coding 'undecided-unix
+ (rmail file)
+ (undigestify-rmail-message)
+ (should (= rmail-total-messages 4))
+ (should (string= (rmail-message-content 2) "Testing the undigester.\n\n"))
+ (should (string= (rmail-message-content 3) "This is message one.\n\n"))
+ (should (string= (rmail-message-content 4) "This is message two.\n"))))
+
+(ert-deftest rmail-undigest-test-rfc1153-digest-strict ()
+ "Test that we can undigest a strict RFC 1153 digest."
+ :expected-result :failed
+ (ert-with-temp-file file
+ :text rmail-rfc1153-digest-strict
+ ;; Rmail reads mbox files literally, so we must make sure the
+ ;; temporary mbox file has Unix-style EOLs.
+ :coding 'undecided-unix
+ (rmail file)
+ (should
+ (ignore-errors
+ ;; This throws an error, because the Trailer is not recognized
+ ;; as a valid RFC 822 (or later) message.
+ (undigestify-rmail-message)
+ (should (string= (rmail-message-content 2) "Testing the undigester.\n\n"))
+ (should (string= (rmail-message-content 3) "This is message one.\n\n"))
+ (should (string= (rmail-message-content 4) "This is message two.\n"))
+ t))))
+
+(ert-deftest rmail-undigest-test-rfc1153-less-strict-digest ()
+ "Test that we can undigest a RFC 1153 with a Subject header in its footer."
+ (ert-with-temp-file file
+ :text rmail-rfc1153-digest-less-strict
+ ;; Rmail reads mbox files literally, so we must make sure the
+ ;; temporary mbox file has Unix-style EOLs.
+ :coding 'undecided-unix
+ (rmail file)
+ (undigestify-rmail-message)
+ (should (= rmail-total-messages 5))
+ (should (string= (rmail-message-content 3) "This is message one.\n\n"))
+ (should (string= (rmail-message-content 4) "This is message two.\n\n"))))
+
+(ert-deftest rmail-undigest-test-rfc1153-sloppy-digest ()
+ "Test that we can undigest a sloppy RFC 1153 digest."
+ (ert-with-temp-file file
+ :text rmail-rfc1153-digest-sloppy
+ ;; Rmail reads mbox files literally, so we must make sure the
+ ;; temporary mbox file has Unix-style EOLs.
+ :coding 'undecided-unix
+ (rmail file)
+ (undigestify-rmail-message)
+ (should (= rmail-total-messages 5))
+ (should (string= (rmail-message-content 3) "This is message one.\n\n"))
+ (should (string= (rmail-message-content 4) "This is message two.\n\n"))))
+
+;; This fails because `rmail-digest-parse-mime' combines the preamble with the
+;; first message of the digest. And then, it doesn't get rid of the last
+;; separator.
+(ert-deftest rmail-undigest-test-rfc1521-mime-digest ()
+ "Test that we can undigest a RFC 1521 MIME digest."
+ :expected-result :failed
+ (ert-with-temp-file file
+ :text rmail-rfc1521-mime-digest
+ ;; Rmail reads mbox files literally, so we must make sure the
+ ;; temporary mbox file has Unix-style EOLs.
+ :coding 'undecided-unix
+ (rmail file)
+ (undigestify-rmail-message)
+ (should (= rmail-total-messages 3))
+ (should (string= (rmail-message-content 2) "Message one.\n\n"))
+ (should (string= (rmail-message-content 3) "Message two.\n\n"))))
+
+(ert-deftest rmail-undigest-test-multipart-mixed-digest ()
+ "Test that we can undigest a digest inside a multipart/mixed digest."
+ (ert-with-temp-file file
+ :text rmail-multipart-mixed-digest
+ ;; Rmail reads mbox files literally, so we must make sure the
+ ;; temporary mbox file has Unix-style EOLs.
+ :coding 'undecided-unix
+ (rmail file)
+ (undigestify-rmail-message)
+ (should (= rmail-total-messages 4))
+ (should (string= (rmail-message-content 2) "Message one.\n\n"))
+ (should (string= (rmail-message-content 3) "Message two.\n\n"))))
diff --git a/test/lisp/mail/uudecode-resources/uudecoded.txt b/test/lisp/mail/uudecode-resources/uudecoded.txt
new file mode 100644
index 00000000000..a6f75519a17
--- /dev/null
+++ b/test/lisp/mail/uudecode-resources/uudecoded.txt
@@ -0,0 +1,16 @@
+This is a test file encoded with uuencode.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
diff --git a/test/lisp/mail/uudecode-resources/uuencoded.txt b/test/lisp/mail/uudecode-resources/uuencoded.txt
new file mode 100644
index 00000000000..1d2f888bea3
--- /dev/null
+++ b/test/lisp/mail/uudecode-resources/uuencoded.txt
@@ -0,0 +1,19 @@
+begin 644 uudecoded.txt
+M5&AI<R!I<R!A('1E<W0@9FEL92!E;F-O9&5D('=I=&@@=75E;F-O9&4N"@I4
+M:&ES(&9I;&4@:7,@<&%R="!O9B!'3E4@16UA8W,N"@I'3E4@16UA8W,@:7,@
+M9G)E92!S;V9T=V%R93H@>6]U(&-A;B!R961I<W1R:6)U=&4@:70@86YD+V]R
+M(&UO9&EF>0II="!U;F1E<B!T:&4@=&5R;7,@;V8@=&AE($=.52!'96YE<F%L
+M(%!U8FQI8R!,:6-E;G-E(&%S('!U8FQI<VAE9"!B>0IT:&4@1G)E92!3;V9T
+M=V%R92!&;W5N9&%T:6]N+"!E:71H97(@=F5R<VEO;B`S(&]F('1H92!,:6-E
+M;G-E+"!O<@HH870@>6]U<B!O<'1I;VXI(&%N>2!L871E<B!V97)S:6]N+@H*
+M1TY5($5M86-S(&ES(&1I<W1R:6)U=&5D(&EN('1H92!H;W!E('1H870@:70@
+M=VEL;"!B92!U<V5F=6PL"F)U="!7251(3U54($%.62!705)204Y463L@=VET
+M:&]U="!E=F5N('1H92!I;7!L:65D('=A<G)A;G1Y(&]F"DU%4D-(04Y404))
+M3$E462!O<B!&251.15-3($9/4B!!(%!!4E1)0U5,05(@4%524$]312X@(%-E
+M92!T:&4*1TY5($=E;F5R86P@4'5B;&EC($QI8V5N<V4@9F]R(&UO<F4@9&5T
+M86EL<RX*"EEO=2!S:&]U;&0@:&%V92!R96-E:79E9"!A(&-O<'D@;V8@=&AE
+M($=.52!'96YE<F%L(%!U8FQI8R!,:6-E;G-E"F%L;VYG('=I=&@@1TY5($5M
+M86-S+B`@268@;F]T+"!S964@/&AT='!S.B\O=W=W+F=N=2YO<F<O;&EC96YS
+&97,O/BX*
+`
+end
diff --git a/test/lisp/mail/uudecode-tests.el b/test/lisp/mail/uudecode-tests.el
new file mode 100644
index 00000000000..7946e99dbc9
--- /dev/null
+++ b/test/lisp/mail/uudecode-tests.el
@@ -0,0 +1,75 @@
+;;; uudecode-tests.el --- Tests for uudecode.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2019-2022 Free Software Foundation, Inc.
+
+;; Author: Stefan Kangas <stefankangas@gmail.com>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'ert-x)
+(require 'uudecode)
+
+(defun uudecode-tests-read-file (file)
+ "Read contents of FILE and return as string."
+ (with-temp-buffer
+ (insert-file-contents file)
+ (buffer-string)))
+
+(defvar uudecode-tests-encoded-str
+ (uudecode-tests-read-file (ert-resource-file "uuencoded.txt"))
+ "Uuencoded data for bookmark-tests.el.
+Same as `uudecode-tests-decoded-str' but uuencoded.")
+(defvar uudecode-tests-decoded-str
+ (uudecode-tests-read-file (ert-resource-file "uudecoded.txt"))
+ "Plain text data for bookmark-tests.el.
+Same as `uudecode-tests-encoded-str' but plain text.")
+
+(ert-deftest uudecode-tests-decode-region-internal ()
+ ;; Write to buffer
+ (with-temp-buffer
+ (insert uudecode-tests-encoded-str)
+ (uudecode-decode-region-internal (point-min) (point-max))
+ (should (equal (buffer-string) uudecode-tests-decoded-str)))
+ ;; Write to file
+ (with-temp-buffer
+ (ert-with-temp-file tmpfile
+ (insert uudecode-tests-encoded-str)
+ (uudecode-decode-region-internal (point-min) (point-max) tmpfile)
+ (should (equal (uudecode-tests-read-file tmpfile)
+ uudecode-tests-decoded-str)))))
+
+(ert-deftest uudecode-tests-decode-region-external ()
+ ;; Write to buffer
+ (when uudecode-use-external
+ (with-temp-buffer
+ (insert uudecode-tests-encoded-str)
+ (uudecode-decode-region-external (point-min) (point-max))
+ (should (equal (buffer-string) uudecode-tests-decoded-str)))
+ ;; Write to file
+ (with-temp-buffer
+ (ert-with-temp-file tmpfile
+ (insert uudecode-tests-encoded-str)
+ (uudecode-decode-region-external (point-min) (point-max) tmpfile)
+ (should (equal (uudecode-tests-read-file tmpfile)
+ uudecode-tests-decoded-str))))))
+
+(provide 'uudecode-tests)
+;;; uudecode-tests.el ends here
diff --git a/test/lisp/man-tests.el b/test/lisp/man-tests.el
index 9294994892d..82714f15668 100644
--- a/test/lisp/man-tests.el
+++ b/test/lisp/man-tests.el
@@ -1,6 +1,6 @@
-;;; man-tests.el --- Test suite for man.
+;;; man-tests.el --- Test suite for man. -*- lexical-binding:t -*-
-;; Copyright (C) 2013-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2022 Free Software Foundation, Inc.
;; Author: Wolfgang Jenkner <wjenkner@inode.at>
;; Keywords: help, internal, unix
@@ -24,6 +24,7 @@
(require 'ert)
(require 'man)
+(require 'seq)
(defconst man-tests-parse-man-k-tests
'(;; GNU/Linux: man-db-2.6.1
@@ -43,7 +44,7 @@ sinl [sin] (3) - sine function"
sin(3), sinf(3), sinl(3) - sine functions"
. (#("sin(3)" 0 6 (help-echo "sine functions")) #("sinf(3)" 0 7 (help-echo "sine functions")) #("sinl(3)" 0 7 (help-echo "sine functions"))))
;; SunOS, Solaris
- ;; http://docs.oracle.com/cd/E19455-01/805-6331/usradm-7/index.html
+ ;; https://docs.oracle.com/cd/E19455-01/805-6331/usradm-7/index.html
;; SunOS 4
("\
tset, reset (1) - establish or restore terminal characteristics"
@@ -60,7 +61,7 @@ cawf, nroff (1) - C version of the nroff-like, Amazingly Workable (text) Formatt
whatis (5) - database of online manual pages"
. (#("cawf(1)" 0 7 (help-echo "C version of the nroff-like, Amazingly Workable (text) Formatter")) #("nroff(1)" 0 8 (help-echo "C version of the nroff-like, Amazingly Workable (text) Formatter")) #("whatis(5)" 0 9 (help-echo "database of online manual pages"))))
;; HP-UX
- ;; http://docstore.mik.ua/manuals/hp-ux/en/B2355-60130/man.1.html
+ ;; https://docstore.mik.ua/manuals/hp-ux/en/B2355-60130/man.1.html
;; Assuming that the line break in the zgrep description was
;; introduced by the man page formatting.
("\
@@ -113,6 +114,53 @@ in the cdr of the element.")
(dolist (test man-tests-parse-man-k-tests)
(should (man-tests-parse-man-k-test-case test))))
+(defun man-tests-filter-strings (_buffer strings)
+ "Run `Man-bgproc-filter' on each of STRINGS.
+The formatted result will be inserted into BUFFER."
+ (let ((proc (start-process "dummy man-tests proc" (current-buffer) "cat")))
+ (set-process-query-on-exit-flag proc nil)
+ (dolist (str strings)
+ (Man-bgproc-filter proc str))))
+
+(ert-deftest man-bgproc-filter-buttonize-includes ()
+ ;; Test with abridged version of printf man page (Bug#36927).
+ (let ((str "\
+PRINTF(3) Linux Programmer's Manual PRINTF(3)
+
+NAME
+ printf, fprintf, dprintf, sprintf, snprintf, vprintf, vfprintf,
+
+SYNOPSIS
+ #include <stdio.h>
+
+ int printf(const char *format, ...);
+
+ #include <stdarg.h>
+
+ int vsprintf(char *str, const char *format, va_list ap);
+
+DESCRIPTION
+ The functions in the printf() family produce output according\n"))
+ (with-temp-buffer
+ (dolist (chunks
+ (list
+ ;; Test a few different kinds of chunking.
+ (list str)
+ (seq-mapcat (lambda (line)
+ (list line "\n"))
+ (split-string str "\n"))
+ (mapcar #'string str)))
+ (erase-buffer)
+ (man-tests-filter-strings (current-buffer) chunks)
+ (goto-char (point-min))
+ (ert-info ((format "%S" chunks) :prefix "Input: ")
+ (search-forward "#include <stdio.h>")
+ (let ((button (button-at (match-beginning 0))))
+ (should (and button (eq 'Man-xref-header-file (button-type button)))))
+ (search-forward "#include <stdarg.h>")
+ (let ((button (button-at (match-beginning 0))))
+ (should (and button (eq 'Man-xref-header-file (button-type button))))))))))
+
(provide 'man-tests)
;;; man-tests.el ends here
diff --git a/test/lisp/md4-tests.el b/test/lisp/md4-tests.el
index 42b13c9d2a1..d1f227cb90a 100644
--- a/test/lisp/md4-tests.el
+++ b/test/lisp/md4-tests.el
@@ -1,6 +1,6 @@
;;; md4-tests.el --- tests for md4.el -*- lexical-binding: t -*-
-;; Copyright (C) 2017 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2022 Free Software Foundation, Inc.
;; Author: Mark Oteiza <mvoteiza@udel.edu>
;; Maintainer: emacs-devel@gnu.org
@@ -29,7 +29,7 @@
(defun md4-tests-digest->hex (str)
"Print digest STR in hexadecimal."
- (mapconcat (lambda (x) (format "%02x" x)) str ""))
+ (mapconcat (lambda (x) (format "%02x" x)) str))
(ert-deftest md4-test-rfc1320 ()
"Verify the test suite results in RFC 1320.
diff --git a/test/lisp/mh-e/mh-limit-tests.el b/test/lisp/mh-e/mh-limit-tests.el
new file mode 100644
index 00000000000..5aedb890546
--- /dev/null
+++ b/test/lisp/mh-e/mh-limit-tests.el
@@ -0,0 +1,35 @@
+;;; mh-limit-tests.el --- tests for mh-limit.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'mh-limit)
+
+(ert-deftest mh-pick-args-list ()
+ "Test `mh-pick-args-list'."
+ (should (equal '() (mh-pick-args-list "")))
+ (should (equal '("-subject" "a") (mh-pick-args-list "-subject a")))
+ (should (equal '("-subject" "a") (mh-pick-args-list " -subject a ")))
+ (should (equal '("-subject" "a" "-from" "b")
+ (mh-pick-args-list "-subject a -from b")))
+ (should (equal '("-subject" "a b" "-from" "c d")
+ (mh-pick-args-list "-subject a b -from c d"))))
+
+;;; mh-limit-tests.el ends here
diff --git a/test/lisp/mh-e/mh-thread-tests.el b/test/lisp/mh-e/mh-thread-tests.el
new file mode 100644
index 00000000000..ea8d441e2d1
--- /dev/null
+++ b/test/lisp/mh-e/mh-thread-tests.el
@@ -0,0 +1,131 @@
+;;; mh-thread-tests.el --- tests for mh-thread.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'mh-thread)
+(eval-when-compile (require 'cl-lib))
+
+(defun mh-thread-tests-before-from ()
+ "Generate the fields of a scan line up to where the \"From\" field would start.
+The exact contents are not important, but the number of characters is."
+ (concat (make-string mh-cmd-note ?9)
+ (make-string mh-scan-cmd-note-width ?A)
+ (make-string mh-scan-destination-width ?t)
+ (make-string mh-scan-date-width ?/)
+ (make-string mh-scan-date-flag-width ?*)))
+
+;;; Tests of support routines
+
+(ert-deftest mh-thread-current-indentation-level ()
+ "Test that `mh-thread-current-indentation-level' identifies the level."
+ (with-temp-buffer
+ (insert (mh-thread-tests-before-from) "[Sender One] Subject of msg 1\n")
+ (insert (mh-thread-tests-before-from) " [Sender Two] Subject of msg 2\n")
+ (goto-char (point-min))
+ (should (equal 0 (mh-thread-current-indentation-level)))
+ (forward-line)
+ (should (equal 2 (mh-thread-current-indentation-level)))))
+
+(ert-deftest mh-thread-find-children ()
+ "Test `mh-thread-find-children'."
+ (let (expected-start expected-end)
+ (with-temp-buffer
+ (insert (mh-thread-tests-before-from) "[Sender One] line 1\n")
+ (setq expected-start (point))
+ (insert (mh-thread-tests-before-from) " [Sender Two] line 2\n")
+ (insert (mh-thread-tests-before-from) " [Sender Three] line 3\n")
+ (insert (mh-thread-tests-before-from) " [Sender Four] line 4\n")
+ (setq expected-end (1- (point)))
+ (insert (mh-thread-tests-before-from) " [Sender Five] line 5\n")
+ (goto-char (1+ expected-start))
+ (should (equal (list expected-start expected-end)
+ (mh-thread-find-children))))))
+
+(ert-deftest mh-thread-immediate-ancestor ()
+ "Test that `mh-thread-immediate-ancestor' moves to the correct message."
+ (with-temp-buffer
+ (insert (mh-thread-tests-before-from) "[Sender Other] line 1\n")
+ (insert (mh-thread-tests-before-from) "[Sender One] line 2\n")
+ (insert (mh-thread-tests-before-from) " [Sender Two] line 3\n")
+ (insert (mh-thread-tests-before-from) " [Sender Three] line 4\n")
+ (insert (mh-thread-tests-before-from) " [Sender Four] line 5\n")
+ (insert (mh-thread-tests-before-from) " [Sender Five] line 6\n")
+ (forward-line -1)
+ (should (equal (line-number-at-pos) 6))
+ (mh-thread-immediate-ancestor)
+ (should (equal (line-number-at-pos) 4)) ;skips over sibling
+ (mh-thread-immediate-ancestor)
+ (should (equal (line-number-at-pos) 3)) ;goes up only one level at a time
+ (mh-thread-immediate-ancestor)
+ (should (equal (line-number-at-pos) 2))
+ (mh-thread-immediate-ancestor)
+ (should (equal (line-number-at-pos) 2)))) ;no further motion at thread root
+
+;;; Tests of MH-Folder Commands
+
+(ert-deftest mh-thread-sibling-and-ancestor ()
+ "Test motion by `mh-thread-ancestor' and `mh-thread-next-sibling'."
+ (with-temp-buffer
+ (insert (mh-thread-tests-before-from) "[Sender Other] line 1\n")
+ (insert (mh-thread-tests-before-from) "[Sender One] line 2\n")
+ (insert (mh-thread-tests-before-from) " [Sender Two] line 3\n")
+ (insert (mh-thread-tests-before-from) " [Sender Three] line 4\n")
+ (insert (mh-thread-tests-before-from) " [Sender Four] line 5\n")
+ (insert (mh-thread-tests-before-from) " [Sender Five] line 6\n")
+ (forward-line -1)
+ (let ((mh-view-ops '(unthread))
+ (show-count 0))
+ (cl-letf (((symbol-function 'mh-maybe-show)
+ (lambda ()
+ (setq show-count (1+ show-count)))))
+ (should (equal (line-number-at-pos) 6))
+ ;; test mh-thread-ancestor
+ (mh-thread-ancestor)
+ (should (equal (line-number-at-pos) 4)) ;skips over sibling
+ (should (equal show-count 1))
+ (mh-thread-ancestor t)
+ (should (equal (line-number-at-pos) 2)) ;root flag skips to root
+ (should (equal show-count 2))
+ (mh-thread-ancestor)
+ (should (equal (line-number-at-pos) 2)) ;do not move from root
+ (should (equal show-count 2)) ;do not re-show at root
+ ;; test mh-thread-sibling
+ (mh-thread-next-sibling)
+ (should (equal (line-number-at-pos) 2)) ;no next sibling, no motion
+ (should (equal show-count 2)) ;no sibling, no show
+ (mh-thread-next-sibling t)
+ (should (equal (line-number-at-pos) 1))
+ (should (equal show-count 3))
+ (mh-thread-next-sibling t)
+ (should (equal (line-number-at-pos) 1)) ;no previous sibling
+ (should (equal show-count 3))
+ (goto-char (point-max))
+ (forward-line -1)
+ (should (equal (line-number-at-pos) 6))
+ (mh-thread-next-sibling t)
+ (should (equal (line-number-at-pos) 5))
+ (should (equal show-count 4))
+ (mh-thread-next-sibling t)
+ (should (equal (line-number-at-pos) 5)) ;no previous sibling
+ (should (equal show-count 4))
+ ))))
+
+;;; mh-thread-tests.el ends here
diff --git a/test/lisp/mh-e/mh-utils-tests.el b/test/lisp/mh-e/mh-utils-tests.el
new file mode 100644
index 00000000000..72ee2fc4745
--- /dev/null
+++ b/test/lisp/mh-e/mh-utils-tests.el
@@ -0,0 +1,551 @@
+;;; mh-utils-tests.el --- tests for mh-utils.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This test suite runs tests that use and depend on MH programs
+;; installed on the system.
+
+;; When running such tests, MH-E can use a particular MH variant
+;; installed on the system, or it can use the mocks provided here.
+;; (Setup is done by the `with-mh-test-env' macro.)
+
+;; By setting environment variable TEST_MH_PATH, you can select which of
+;; the installed MH variants to use, or ignore them all and use mocks.
+;; See also the script test-all-mh-variants.sh in this directory.
+
+;; 1. To run these tests against the default MH variant installed on
+;; this system:
+;; cd ../.. && make lisp/mh-e/mh-utils-tests
+
+;; 2. To run these tests against an MH variant installed in a
+;; specific directory, set TEST_MH_PATH, as in this example:
+;; cd ../.. && make lisp/mh-e/mh-utils-tests TEST_MH_PATH=/usr/local/nmh/bin
+
+;; 3. To search for and run these tests against all MH variants
+;; installed on this system:
+;; ./test-all-mh-variants.sh
+
+;; Setting the environment variable TEST_MH_DEBUG or the Lisp variable
+;; mh-test-utils-debug-mocks logs access to the file system during the test.
+
+;;; Code:
+
+(require 'ert)
+(require 'mh-utils)
+(eval-when-compile
+ (require 'cl-lib)
+ (require 'subr-x))
+
+(ert-deftest mh-quote-pick-expr ()
+ "Test `mh-quote-pick-expr'."
+ (should (equal nil (mh-quote-pick-expr nil)))
+ (should (equal '() (mh-quote-pick-expr '())))
+ (should (equal '("foo") (mh-quote-pick-expr '("foo"))))
+ (should (equal '("^\\[foo]?\\*+\\.\\$")
+ (mh-quote-pick-expr '("^[foo]?*+.$"))))
+ (should (equal '("^\\[foo]?\\*+\\.\\$" "bar" "baz\\$")
+ (mh-quote-pick-expr '("^[foo]?*+.$" "bar" "baz$")))))
+
+(ert-deftest mh-normalize-folder-name ()
+ "Test `mh-normalize-folder-name'."
+ (should (equal nil (mh-normalize-folder-name nil)))
+ (should (equal "+" (mh-normalize-folder-name "")))
+ (should (equal "" (mh-normalize-folder-name "" t)))
+ (should (equal nil (mh-normalize-folder-name "" nil nil t)))
+ (should (equal nil (mh-normalize-folder-name "+" nil nil t)))
+ (should (equal nil (mh-normalize-folder-name "+" t t t)))
+ (should (equal "+inbox" (mh-normalize-folder-name "inbox")))
+ (should (equal "+inbox" (mh-normalize-folder-name "+inbox")))
+ (should (equal "+inbox" (mh-normalize-folder-name "+inbox/")))
+ (should (equal "+inbox/" (mh-normalize-folder-name "+inbox/" t t t)))
+ (should (equal "+inbox/" (mh-normalize-folder-name "+inbox/" nil t)))
+ (should (equal "+news" (mh-normalize-folder-name "+inbox////../news")))
+ (should (equal "+news" (mh-normalize-folder-name "+inbox////../news/")))
+ (should (equal "+news/"
+ (mh-normalize-folder-name "+inbox////../news/" nil t)))
+ (should (equal "+inbox/news" (mh-normalize-folder-name "+inbox////./news"))))
+
+(ert-deftest mh-sub-folders-parse-no-folder ()
+ "Test `mh-sub-folders-parse' with no starting folder."
+ (let (others-position)
+ (with-temp-buffer
+ (insert "lines without has-string are ignored\n")
+ (insert "onespace has no messages.\n")
+ (insert "twospace has no messages.\n")
+ (insert " precedingblanks has no messages.\n")
+ (insert ".leadingdot has no messages.\n")
+ (insert "#leadinghash has no messages.\n")
+ (insert ",leadingcomma has no messages.\n")
+ (insert "withothers has no messages ; (others)")
+ (setq others-position (point))
+ (insert ".\n")
+ (insert "curf has no messages.\n")
+ (insert "curf+ has 123 messages.\n")
+ (insert "curf2+ has 17 messages.\n")
+ (insert "\ntotal after blank line is ignored has no messages.\n")
+ (should (equal
+ (mh-sub-folders-parse nil "curf+")
+ (list '("onespace") '("twospace") '("precedingblanks")
+ (cons "withothers" others-position)
+ '("curf") '("curf") '("curf2+")))))))
+
+(ert-deftest mh-sub-folders-parse-relative-folder ()
+ "Test `mh-sub-folders-parse' with folder."
+ (let (others-position)
+ (with-temp-buffer
+ (insert "testf+ has no messages.\n")
+ (insert "testf/sub1 has no messages.\n")
+ (insert "testf/sub2 has no messages ; (others)")
+ (setq others-position (point))
+ (insert ".\n")
+ (should (equal
+ (mh-sub-folders-parse "+testf" "testf+")
+ (list '("sub1") (cons "sub2" others-position)))))))
+
+(ert-deftest mh-sub-folders-parse-root-folder ()
+ "Test `mh-sub-folders-parse' with root folder."
+ (with-temp-buffer
+ (insert "/+ has no messages.\n")
+ (insert "/ has no messages.\n")
+ (insert "//nmh-style has no messages.\n")
+ (insert "/mu-style has no messages.\n")
+ (should (equal
+ (mh-sub-folders-parse "+/" "inbox+")
+ '(("") ("nmh-style") ("mu-style"))))))
+
+
+;; Folder names that are used by the following tests.
+(defvar mh-test-rel-folder "rela-folder")
+(defvar mh-test-abs-folder "/abso-folder")
+(defvar mh-test-no-such-folder "/testdir/none" "A folder that does not exist.")
+
+(defvar mh-test-utils-variants nil
+ "The value of `mh-variants' used for these tests.
+This variable allows setting `mh-variants' to a limited set for targeted
+testing. Its value can be different from the normal value when
+environment variable TEST_MH_PATH is set. By remembering the value, we
+can log the choice only once, which makes the batch log easier to read.")
+
+(defvar mh-test-variant-logged-already nil
+ "Whether `with-mh-test-env' has written the MH variant to the log.")
+
+(defvar mh-test-utils-debug-mocks (> (length (getenv "TEST_MH_DEBUG")) 0)
+ "Whether to log detailed behavior of mock functions.")
+
+(defvar mh-test-call-process-real (symbol-function 'call-process))
+(defvar mh-test-file-directory-p-real (symbol-function 'file-directory-p))
+
+;;; The macro with-mh-test-env wraps tests that touch the file system
+;;; and/or run programs.
+
+(defmacro with-mh-test-env (&rest body)
+ "Evaluate BODY with a test mail environment.
+Functions that touch the file system or run MH programs are either
+mocked out or pointed at a test tree. Uses `mh-test-utils-setup' to
+select which."
+ (declare (indent 0) (debug t))
+ `(cl-letf ((temp-home-dir nil)
+ ;; make local bindings for things we will modify for test env
+ (mh-user-path)
+ (mh-test-abs-folder)
+ ((symbol-function 'call-process))
+ ((symbol-function 'file-directory-p))
+ ;; the test always gets its own sub-folders cache
+ (mh-sub-folders-cache (make-hash-table :test #'equal))
+ ;; Allow envvar TEST_MH_PATH to control mh-variants.
+ (mh-variants mh-test-utils-variants)
+ ;; remember the original value
+ (original-mh-test-variant-logged mh-test-variant-logged-already)
+ (original-mh-path mh-path)
+ (original-mh-sys-path mh-sys-path)
+ (original-exec-path exec-path)
+ (original-mh-variant-in-use mh-variant-in-use)
+ (original-mh-progs mh-progs)
+ (original-mh-lib mh-lib)
+ (original-mh-lib-progs mh-lib-progs)
+ (original-mh-envvar (getenv "MH")))
+ (unwind-protect
+ (progn
+ (setq temp-home-dir (mh-test-utils-setup))
+ ,@body)
+ (unless noninteractive
+ ;; If interactive, forget that we logged the variant and
+ ;; restore any changes TEST_MH_PATH made.
+ (setq mh-test-variant-logged-already original-mh-test-variant-logged
+ mh-path original-mh-path
+ mh-sys-path original-mh-sys-path
+ exec-path original-exec-path
+ mh-variant-in-use original-mh-variant-in-use
+ mh-progs original-mh-progs
+ mh-lib original-mh-lib
+ mh-lib-progs original-mh-lib-progs))
+ (if temp-home-dir (delete-directory temp-home-dir t))
+ (setenv "MH" original-mh-envvar))))
+
+(defun mh-test-utils-setup ()
+ "Set dynamically bound variables needed by mock and/or variants.
+Call `mh-variant-set' to look through the directories named by
+environment variable `TEST_MH_PATH' (default: `mh-path' and `mh-sys-path')
+to find the MH variant to use, if any.
+Return the name of the root of the created directory tree, if any."
+ (when (getenv "TEST_MH_PATH")
+ ;; force mh-variants to use only TEST_MH_PATH
+ (setq mh-path (split-string (getenv "TEST_MH_PATH") path-separator t)
+ mh-sys-path nil
+ exec-path '("/bin" "/usr/bin")))
+ (unless mh-test-variant-logged-already
+ (mh-variant-set mh-variant)
+ (setq mh-test-utils-variants mh-variants)
+ (setq mh-test-variant-logged-already t))
+ (when (native-comp-available-p)
+ ;; As `call-process'' and `file-directory-p' will be redefined, the
+ ;; native compiler will invoke `call-process' to compile the
+ ;; respective trampolines. To avoid interference with the
+ ;; `call-process' mocking, we build these ahead of time.
+ (mapc #'comp-subr-trampoline-install '(call-process file-directory-p)))
+ (if mh-variant-in-use
+ (mh-test-utils-setup-with-variant)
+ (mh-test-utils-setup-with-mocks)))
+
+(defun mh-test-utils-setup-with-mocks ()
+ "Set dynamically bound variables so that MH programs are mocked out.
+The tests use this method if no configured MH variant is found."
+ (setq mh-user-path "/testdir/Mail/")
+ (mh-populate-sub-folders-cache "+")
+ (mh-populate-sub-folders-cache "+rela-folder")
+ (mh-populate-sub-folders-cache "+rela-folder/bar")
+ (mh-populate-sub-folders-cache "+rela-folder/foo")
+ (mh-populate-sub-folders-cache "+rela-folder/food")
+ (fset 'call-process #'mh-test-utils-mock-call-process)
+ (fset 'file-directory-p #'mh-test-utils-mock-file-directory-p)
+ ;; no temp directory created
+ nil)
+
+(defun mh-test-utils-mock-call-process (program
+ &optional _infile _destination _display
+ &rest args)
+ "A mocked version of `call-process' that calls no processes."
+ (let ((argument-responses
+ ;; assoc list of program arguments and lines to output.
+ '((("folder" "-fast") . ("rela-folder"))
+ (("folders" "-noheader" "-norecurse" "-nototal") .
+ ("rela-folder has no messages."))
+ (("folders" "-noheader" "-norecurse" "-nototal" "+rela-folder") .
+ ("rela-folder+ has no messages."
+ "rela-folder/bar has no messages."
+ "rela-folder/foo has no messages."
+ "rela-folder/food has no messages."))
+ (("folders" "-noheader" "-norecurse" "-nototal" "+rela-folder/foo") .
+ ("rela-folder/foo+ has no messages."))
+ (("folders" "-noheader" "-norecurse" "-nototal" "+") .
+ ("+ has no messages."))
+ (("folders" "-noheader" "-norecurse" "-nototal" "+/abso-folder") .
+ ("/abso-folder+ has no messages."
+ "/abso-folder/bar has no messages."
+ "/abso-folder/foo has no messages."
+ "/abso-folder/food has no messages."))
+ (("folders" "-noheader" "-norecurse" "-nototal" "+/") .
+ ("/+ has no messages ; (others)."
+ "/abso-folder has no messages ; (others)."
+ "/tmp has no messages ; (others)."))
+ ))
+ (arglist (cons (file-name-base program) args)))
+ (let ((response-list-cons (assoc arglist argument-responses)))
+ (cond (response-list-cons
+ (let ((response-list (cdr response-list-cons)))
+ (when mh-test-utils-debug-mocks
+ (message "call-process mock arglist %s" arglist)
+ (message " -> response %S" response-list))
+ (while response-list
+ (insert (car response-list) "\n")
+ (setq response-list (cdr response-list))))
+ 0)
+ (t
+ (message "call-process mock unexpected arglist %s" arglist)
+ 1)))))
+
+(defun mh-test-utils-mock-file-directory-p (filename)
+ "A mocked version of `file-directory-p' that does not access the file system."
+ (let ((directories '("" "/" "/tmp" "/abso-folder" "/abso-folder/foo"
+ "/testdir/Mail" "/testdir/Mail/rela-folder"
+ "/testdir/Mail/rela-folder/foo"
+ "rela-folder" "rela-folder/foo"))
+ (non-directories '("/abso-folder/fo" "rela-folder/fo"
+ "/testdir/Mail/rela-folder/fo"
+ "/testdir/Mail/nosuchfolder"
+ "/nosuchfolder" "nosuchfolder")))
+ (cond ((member (directory-file-name filename) directories)
+ (when mh-test-utils-debug-mocks
+ (message "file-directory-p mock: %S -> t" filename))
+ t)
+ ((member (directory-file-name filename) non-directories)
+ (when mh-test-utils-debug-mocks
+ (message "file-directory-p mock: %S -> nil" filename))
+ nil)
+ (t
+ (message "file-directory-p mock unexpected filename: %S" filename)
+ nil))))
+
+(defun mh-test-utils-setup-with-variant ()
+ "Create a temporary directory structure for actual MH programs to read.
+Return the name of the root of the created directory tree.
+Set dynamically bound variables so that MH programs may log.
+The tests use this method if a configured MH variant is found."
+ (let* ((temp-home-dir
+ (make-temp-file "emacs-mh-e-unit-test-" t))
+ (profile (expand-file-name
+ ".mh_profile" temp-home-dir))
+ (mail-dir (expand-file-name "Mail" temp-home-dir))
+ (rela-folder (expand-file-name
+ "rela-folder" mail-dir))
+ (abso-folder (expand-file-name
+ "abso-folder" temp-home-dir)))
+ (with-temp-file profile
+ (insert "Path: " mail-dir "\n" "Welcome: disable\n"))
+ (setenv "MH" profile)
+ (make-directory (expand-file-name "bar" rela-folder) t)
+ (make-directory (expand-file-name "foo" rela-folder) t)
+ (make-directory (expand-file-name "food" rela-folder) t)
+ (setq mh-user-path (file-name-as-directory mail-dir))
+ (make-directory (expand-file-name "bar" abso-folder) t)
+ (make-directory (expand-file-name "foo" abso-folder) t)
+ (make-directory (expand-file-name "food" abso-folder) t)
+ (setq mh-test-abs-folder abso-folder)
+ (fset 'call-process #'mh-test-utils-log-call-process)
+ (fset 'file-directory-p #'mh-test-utils-log-file-directory-p)
+ temp-home-dir))
+
+(defun mh-test-utils-log-call-process (program
+ &optional infile destination display
+ &rest args)
+ "A wrapper around `call-process' that can log the program args and output.
+Both args and output are written with `message' if `mh-test-utils-debug-mocks'
+is non-nil."
+ (let (process-output)
+ (when mh-test-utils-debug-mocks
+ (message "call-process arglist %s" (cons program args)))
+ (with-temp-buffer
+ (apply mh-test-call-process-real program infile destination display args)
+ (setq process-output (buffer-string)))
+ (when mh-test-utils-debug-mocks
+ (message " -> response:\n%s" process-output))
+ (insert process-output)))
+
+(defun mh-test-utils-log-file-directory-p (filename)
+ "A wrapper around `file-directory-p' that can log calls.
+Both FILENAME and the return value are written with `message'
+if `mh-test-utils-debug-mocks' is non-nil."
+ (let ((result (funcall mh-test-file-directory-p-real filename)))
+ (when mh-test-utils-debug-mocks
+ (message "file-directory-p: %S -> %s" filename result))
+ result))
+
+(defun mh-test-variant-handles-plus-slash (variant)
+ "Returns non-nil if this MH variant handles \"folders +/\".
+Mailutils 3.5, 3.7, and 3.13 are known not to."
+ (cond ((not (stringp variant))) ;our mock handles it
+ ((string-search "GNU Mailutils" variant)
+ (let ((mu-version (string-remove-prefix "GNU Mailutils " variant)))
+ (version<= "3.13.91" mu-version)))
+ (t))) ;no other known failures
+
+
+(ert-deftest mh-sub-folders-actual ()
+ "Test `mh-sub-folders-actual'."
+ ;; Note that mh-sub-folders-actual expects the folder to have
+ ;; already been normalized with
+ ;; (mh-normalize-folder-name folder nil nil t)
+ (with-mh-test-env
+ (should (member
+ mh-test-rel-folder
+ (mapcar (lambda (x) (car x)) (mh-sub-folders-actual nil))))
+ ;; Empty string and "+" not tested since mh-normalize-folder-name
+ ;; would change them to nil.
+ (should (member "foo"
+ (mapcar (lambda (x) (car x))
+ (mh-sub-folders-actual
+ (format "+%s" mh-test-rel-folder)))))
+ ;; Folder with trailing slash not tested since
+ ;; mh-normalize-folder-name would strip it.
+ (should (equal
+ nil
+ (mh-sub-folders-actual (format "+%s/foo" mh-test-rel-folder))))
+
+ (should (equal
+ (list (list "bar") (list "foo") (list "food"))
+ (mh-sub-folders-actual (format "+%s" mh-test-abs-folder))))
+
+ (when (mh-test-variant-handles-plus-slash mh-variant-in-use)
+ (should (member "tmp" (mapcar (lambda (x) (car x))
+ (mh-sub-folders-actual "+/")))))
+
+ ;; FIXME: mh-sub-folders-actual doesn't (yet) expect to be given a
+ ;; nonexistent folder.
+ ;; (should (equal nil
+ ;; (mh-sub-folders-actual "+nosuchfolder")))
+ ;; (should (equal nil
+ ;; (mh-sub-folders-actual "+/nosuchfolder")))
+ ))
+
+(ert-deftest mh-sub-folders ()
+ "Test `mh-sub-folders'."
+ (with-mh-test-env
+ (should (member mh-test-rel-folder
+ (mapcar (lambda (x) (car x)) (mh-sub-folders nil))))
+ (should (member mh-test-rel-folder
+ (mapcar (lambda (x) (car x)) (mh-sub-folders ""))))
+ (should-not (member mh-test-no-such-folder
+ (mapcar (lambda (x) (car x)) (mh-sub-folders "+"))))
+ (should (equal (list (list "bar") (list "foo") (list "food"))
+ (mh-sub-folders (format "+%s" mh-test-rel-folder))))
+ (should (equal (list (list "bar") (list "foo") (list "food"))
+ (mh-sub-folders (format "+%s/" mh-test-rel-folder))))
+ (should (equal nil
+ (mh-sub-folders (format "+%s/foo/" mh-test-rel-folder))))
+ (should (equal nil
+ (mh-sub-folders (format "+%s/foo" mh-test-rel-folder))))
+ (should (equal (list (list "bar") (list "foo") (list "food"))
+ (mh-sub-folders (format "+%s" mh-test-abs-folder))))
+ (when (mh-test-variant-handles-plus-slash mh-variant-in-use)
+ (should (member "tmp"
+ (mapcar (lambda (x) (car x)) (mh-sub-folders "+/")))))
+
+ ;; FIXME: mh-sub-folders doesn't (yet) expect to be given a
+ ;; nonexistent folder.
+ ;; (should (equal nil
+ ;; (mh-sub-folders "+nosuchfolder")))
+ ;; (should (equal nil
+ ;; (mh-sub-folders "+/nosuchfolder")))
+ ))
+
+
+(defmacro mh-test-folder-completion-1 (name
+ nil-expected t-expected lambda-expected)
+ "Helper for testing `mh-folder-completion-function'.
+Ask for completion on NAME three times, with three different
+values for the FLAG argument of `mh-folder-completion-function'.
+NIL-EXPECTED is the expected value with FLAG nil.
+T-EXPECTED is the expected value with FLAG t.
+LAMBDA-EXPECTED is the expected value with FLAG lambda."
+ (declare (debug t))
+ `(with-mh-test-env
+ (mh-test-folder-completion-2 ,nil-expected ;case "a"
+ (mh-folder-completion-function ,name nil nil))
+ (mh-test-folder-completion-2 ,t-expected ;case "b"
+ (mh-folder-completion-function ,name nil t))
+ (mh-test-folder-completion-2 ,lambda-expected ;case "c"
+ (mh-folder-completion-function ,name nil
+ 'lambda))))
+
+(defmacro mh-test-folder-completion-2 (expected actual)
+ "Inner helper for testing `mh-folder-completion-function'.
+ACTUAL should evaluate to either EXPECTED or to a list containing EXPECTED.
+ACTUAL may be evaluated twice, but this gives a clearer error on failure,
+and the `should' macro requires idempotent evaluation anyway."
+ (declare (debug t))
+ `(if (and (not (consp ,expected)) (consp ,actual))
+ (should (member ,expected ,actual))
+ (should (equal ,expected ,actual))))
+
+
+(ert-deftest mh-folder-completion-function-02-empty ()
+ "Test `mh-folder-completion-function' with empty name."
+ (mh-test-folder-completion-1 "" "+" (format "%s/" mh-test-rel-folder) nil))
+
+(ert-deftest mh-folder-completion-function-03-plus ()
+ "Test `mh-folder-completion-function' with `+'."
+ (mh-test-folder-completion-1 "+" "+" (format "%s/" mh-test-rel-folder) nil))
+
+(ert-deftest mh-folder-completion-function-04-rel-folder ()
+ "Test `mh-folder-completion-function' with `+rela-folder'."
+ (mh-test-folder-completion-1 (format "+%s" mh-test-rel-folder)
+ (format "+%s/" mh-test-rel-folder)
+ (list (format "%s/" mh-test-rel-folder))
+ t))
+
+(ert-deftest mh-folder-completion-function-05-rel-folder-slash ()
+ "Test `mh-folder-completion-function' with `+rela-folder/'."
+ (mh-test-folder-completion-1 (format "+%s/" mh-test-rel-folder)
+ (format "+%s/" mh-test-rel-folder)
+ (list "bar" "foo" "food")
+ t))
+
+(ert-deftest mh-folder-completion-function-06-rel-folder-slash-foo ()
+ "Test `mh-folder-completion-function' with `+rela-folder/foo'."
+ (mh-test-folder-completion-1 (format "+%s/foo" mh-test-rel-folder)
+ (format "+%s/foo" mh-test-rel-folder)
+ (list "foo" "food")
+ t)
+ (with-mh-test-env
+ (should (equal nil
+ (mh-folder-completion-function
+ (format "+%s/fo" mh-test-rel-folder) nil 'lambda)))))
+
+(ert-deftest mh-folder-completion-function-07-rel-folder-slash-foo-slash ()
+ "Test `mh-folder-completion-function' with `+rela-folder/foo/'."
+ (mh-test-folder-completion-1 (format "+%s/foo/" mh-test-rel-folder)
+ nil
+ nil
+ t))
+
+(ert-deftest mh-folder-completion-function-08-plus-slash ()
+ "Test `mh-folder-completion-function' with `+/'."
+ (with-mh-test-env
+ (skip-unless (mh-test-variant-handles-plus-slash mh-variant-in-use)))
+ (mh-test-folder-completion-1 "+/" "+/" "tmp/" t)
+ ;; case "bb"
+ (with-mh-test-env
+ (should (equal nil
+ (member (format "+%s/" mh-test-rel-folder)
+ (mh-folder-completion-function "+/" nil t))))))
+
+(ert-deftest mh-folder-completion-function-09-plus-slash-tmp ()
+ "Test `mh-folder-completion-function' with `+/tmp'."
+ (with-mh-test-env
+ (skip-unless (mh-test-variant-handles-plus-slash mh-variant-in-use)))
+ (mh-test-folder-completion-1 "+/tmp" "+/tmp/" "tmp/" t))
+
+(ert-deftest mh-folder-completion-function-10-plus-slash-abs-folder ()
+ "Test `mh-folder-completion-function' with `+/abso-folder'."
+ (mh-test-folder-completion-1 (format "+%s/" mh-test-abs-folder)
+ (format "+%s/" mh-test-abs-folder)
+ (list "bar" "foo" "food")
+ t))
+
+(ert-deftest mh-folder-completion-function-11-plus-slash-abs-folder-slash-foo ()
+ "Test `mh-folder-completion-function' with `+/abso-folder/foo'."
+ (mh-test-folder-completion-1 (format "+%s/foo" mh-test-abs-folder)
+ (format "+%s/foo" mh-test-abs-folder)
+ (list "foo" "food")
+ t)
+ (with-mh-test-env
+ (should (equal nil
+ (mh-folder-completion-function
+ (format "+%s/fo" mh-test-abs-folder) nil 'lambda)))))
+
+(ert-deftest mh-folder-completion-function-12-plus-nosuchfolder ()
+ "Test `mh-folder-completion-function' with `+nosuchfolder'."
+ (mh-test-folder-completion-1 "+nosuchfolder" nil nil nil))
+
+(ert-deftest mh-folder-completion-function-13-plus-slash-nosuchfolder ()
+ "Test `mh-folder-completion-function' with `+/nosuchfolder'."
+ (mh-test-folder-completion-1 "+/nosuchfolder" nil nil nil))
+
+;;; mh-utils-tests.el ends here
diff --git a/test/lisp/mh-e/mh-xface-tests.el b/test/lisp/mh-e/mh-xface-tests.el
new file mode 100644
index 00000000000..6c9c7ea1bf1
--- /dev/null
+++ b/test/lisp/mh-e/mh-xface-tests.el
@@ -0,0 +1,50 @@
+;;; mh-xface-tests.el --- tests for mh-xface.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'mh-xface)
+
+(ert-deftest mh-x-image-url-sane-p ()
+ "Test that `mh-x-image-url-sane-p' accepts a URL exactly if it is sane."
+ (should (equal (mh-x-image-url-sane-p (concat "http://"
+ (make-string 101 ?a)))
+ nil)) ;too long
+ (should (equal (mh-x-image-url-sane-p "http") nil)) ;too short
+ (should (equal (mh-x-image-url-sane-p "http:") t))
+ (should (equal (mh-x-image-url-sane-p "https") nil)) ;too short
+ (should (equal (mh-x-image-url-sane-p "https:") t))
+ (should (equal (mh-x-image-url-sane-p "https://www.example.com/me.png") t))
+ (should (equal (mh-x-image-url-sane-p "abcde:") nil)))
+
+(ert-deftest mh-x-image-url-cache-canonicalize ()
+ "Test `mh-x-image-url-cache-canonicalize'."
+ (should (equal (format "%s/%s" mh-x-image-cache-directory "%21foo%21bar.png")
+ (mh-x-image-url-cache-canonicalize "/foo/bar")))
+ (should (equal (format "%s/%s" mh-x-image-cache-directory
+ "http%3A%21%21domain.com%21foo%21bar.png")
+ (mh-x-image-url-cache-canonicalize
+ "http://domain.com/foo/bar")))
+ ;; All Windows invalid characters.
+ (should (equal (format "%s/%s" mh-x-image-cache-directory
+ "%21%3C%3E%3A%2A%3F%22%5C%7C%21bar.png")
+ (mh-x-image-url-cache-canonicalize "/<>:*?\"\\|/bar"))))
+
+;;; mh-xface-tests.el ends here
diff --git a/test/lisp/mh-e/test-all-mh-variants.sh b/test/lisp/mh-e/test-all-mh-variants.sh
new file mode 100755
index 00000000000..3789a5fdedc
--- /dev/null
+++ b/test/lisp/mh-e/test-all-mh-variants.sh
@@ -0,0 +1,102 @@
+#! /bin/bash
+# Run the mh-utils-tests against all MH variants found on this system.
+
+# Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+# This file is part of GNU Emacs.
+
+# GNU Emacs is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# GNU Emacs is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+# Commentary:
+
+# By default runs all tests; test names or Emacs-style regexps may be
+# given on the command line to run just those tests.
+#
+# Option -d turns on Emacs variable mh-test-utils-debug-mocks, which
+# causes the tests to output all interactions with the file system.
+
+# If you want to run the tests for only one MH variant, you don't need
+# to use this script, because "make" can do it. See the commentary at
+# the top of ./mh-utils-tests.el for the recipe.
+
+debug=
+if [[ "$1" = -* ]]; then
+ if [[ "$1" != -d ]]; then
+ echo "Usage: $(basename "$0") [-d] [test ...]" >&2
+ exit 2
+ fi
+ debug=t
+ shift
+fi
+
+shopt -s extglob
+ert_test_list=()
+for tst; do
+ # Guess the type the test spec
+ case $tst in
+ *[\[\].*+\\]*) # Regexp: put in string quotes
+ ert_test_list+=("\"$tst\"")
+ ;;
+ *) # Lisp expression, keyword, or symbol: use as is
+ ert_test_list+=("$tst")
+ ;;
+ esac
+done
+if [[ ${#ert_test_list[@]} -eq 0 ]]; then
+ # t means true for all tests, runs everything
+ ert_test_list=(t)
+fi
+
+# This script is 3 directories down in the Emacs source tree.
+cd "$(dirname "$0")"
+cd ../../..
+emacs=(src/emacs --batch -Q)
+
+# MH-E has a good list of directories where an MH variant might be installed,
+# so we look in each of those.
+read -r -a mh_sys_path \
+ < <("${emacs[@]}" -l mh-e --eval "(princ mh-sys-path)" | sed 's/[()]//g')
+
+have_done_mocked_variant=false
+declare -i tests_total=0 tests_passed=0
+
+for path in "${mh_sys_path[@]}"; do
+ if [[ ! -x "$path/mhparam" ]]; then
+ if [[ "$have_done_mocked_variant" = false ]]; then
+ have_done_mocked_variant=true
+ else
+ continue
+ fi
+ fi
+ echo "** Testing with PATH $path"
+ ((++tests_total))
+ TEST_MH_PATH=$path TEST_MH_DEBUG=$debug \
+ HOME=/nonexistent \
+ "${emacs[@]}" -l ert \
+ --eval "(setq load-prefer-newer t)" \
+ --eval "(load \"$PWD/test/lisp/mh-e/mh-utils-tests\" nil t)" \
+ --eval "(ert-run-tests-batch-and-exit '(or ${ert_test_list[*]}))" \
+ && ((++tests_passed))
+done
+
+if (( tests_total == 0 )); then
+ echo "NO tests run"
+ exit 1
+elif (( tests_total == tests_passed )); then
+ echo "All tested variants pass: $tests_passed/$tests_total"
+else
+ echo "Tested variants passing: $tests_passed/$tests_total," \
+ "FAILING: $((tests_total - tests_passed))/$tests_total"
+ exit 1
+fi
diff --git a/test/lisp/minibuffer-resources/data/minibuffer-test-cttq$tion b/test/lisp/minibuffer-resources/data/minibuffer-test-cttq$tion
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/test/lisp/minibuffer-resources/data/minibuffer-test-cttq$tion
diff --git a/test/lisp/minibuffer-resources/lisp/cedet/semantic-utest-c.test b/test/lisp/minibuffer-resources/lisp/cedet/semantic-utest-c.test
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/test/lisp/minibuffer-resources/lisp/cedet/semantic-utest-c.test
diff --git a/test/lisp/minibuffer-resources/lisp/cedet/semantic-utest.test b/test/lisp/minibuffer-resources/lisp/cedet/semantic-utest.test
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/test/lisp/minibuffer-resources/lisp/cedet/semantic-utest.test
diff --git a/test/lisp/minibuffer-tests.el b/test/lisp/minibuffer-tests.el
index c27b338f7f3..ec93c8f42a5 100644
--- a/test/lisp/minibuffer-tests.el
+++ b/test/lisp/minibuffer-tests.el
@@ -1,22 +1,24 @@
-;;; completion-tests.el --- Tests for completion functions -*- lexical-binding: t; -*-
+;;; minibuffer-tests.el --- Tests for completion functions -*- lexical-binding: t; -*-
-;; Copyright (C) 2013-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2022 Free Software Foundation, Inc.
;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
;; Keywords:
-;; This program is free software; you can redistribute it and/or modify
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
-;; This program is distributed in the hope that it will be useful,
+;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
-;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
@@ -24,6 +26,9 @@
;;; Code:
+(require 'ert)
+(require 'ert-x)
+
(eval-when-compile (require 'cl-lib))
(ert-deftest completion-test1 ()
@@ -42,5 +47,425 @@
(should (equal (buffer-string)
"test: "))))))
-(provide 'completion-tests)
-;;; completion-tests.el ends here
+(ert-deftest completion-table-with-predicate-test ()
+ (let ((full-collection
+ '("apple" ; Has A.
+ "beet" ; Has B.
+ "banana" ; Has A & B.
+ "cherry" ; Has neither.
+ ))
+ (no-A (lambda (x) (not (string-match-p "a" x))))
+ (no-B (lambda (x) (not (string-match-p "b" x)))))
+ (should
+ (member "cherry"
+ (completion-table-with-predicate
+ full-collection no-A t "" no-B t)))
+ (should-not
+ (member "banana"
+ (completion-table-with-predicate
+ full-collection no-A t "" no-B t)))
+ ;; "apple" should still match when strict is nil.
+ (should (eq t (try-completion
+ "apple"
+ (apply-partially
+ 'completion-table-with-predicate
+ full-collection no-A nil)
+ no-B)))
+ ;; "apple" should still match when strict is nil and pred2 is nil
+ ;; (Bug#27841).
+ (should (eq t (try-completion
+ "apple"
+ (apply-partially
+ 'completion-table-with-predicate
+ full-collection no-A nil))))))
+
+(ert-deftest completion-table-subvert-test ()
+ (let* ((origtable '("A-hello" "A-there"))
+ (subvtable (completion-table-subvert origtable "B" "A")))
+ (should (equal (try-completion "B-hel" subvtable)
+ "B-hello"))
+ (should (equal (all-completions "B-hel" subvtable) '("-hello")))
+ (should (test-completion "B-hello" subvtable))
+ (should (equal (completion-boundaries "B-hel" subvtable
+ nil "suffix")
+ '(1 . 6)))))
+
+(ert-deftest completion-table-test-quoting ()
+ (let ((process-environment
+ `("CTTQ1=ed" "CTTQ2=et/" ,@process-environment))
+ (default-directory (ert-resource-directory)))
+ (pcase-dolist (`(,input ,output)
+ '(
+ ;; Test that $ in files is properly $$ quoted.
+ ("data/m-cttq" "data/minibuffer-test-cttq$$tion")
+ ;; Test that $$ in input is properly unquoted.
+ ("data/m-cttq$$t" "data/minibuffer-test-cttq$$tion")
+ ;; Test that env-vars are preserved.
+ ("lisp/c${CTTQ1}et/se-u" "lisp/c${CTTQ1}et/semantic-utest")
+ ("lisp/ced${CTTQ2}se-u" "lisp/ced${CTTQ2}semantic-utest")
+ ;; Test that env-vars don't prevent partial-completion.
+ ;; FIXME: Ideally we'd like to keep the ${CTTQ}!
+ ("lis/c${CTTQ1}/se-u" "lisp/cedet/semantic-utest")
+ ))
+ (should (equal (completion-try-completion input
+ #'completion--file-name-table
+ nil (length input))
+ (cons output (length output)))))))
+
+(ert-deftest completion--insert-strings-faces ()
+ (with-temp-buffer
+ (completion--insert-strings
+ '(("completion1" "suffix1")))
+ (should (equal (get-text-property 12 'face) '(completions-annotations))))
+ (with-temp-buffer
+ (completion--insert-strings
+ '(("completion1" #("suffix1" 0 7 (face shadow)))))
+ (should (equal (get-text-property 12 'face) 'shadow)))
+ (with-temp-buffer
+ (completion--insert-strings
+ '(("completion1" "prefix1" "suffix1")))
+ (should (equal (get-text-property 19 'face) nil)))
+ (with-temp-buffer
+ (completion--insert-strings
+ '(("completion1" "prefix1" #("suffix1" 0 7 (face shadow)))))
+ (should (equal (get-text-property 19 'face) 'shadow))))
+
+(ert-deftest completion-pcm--optimize-pattern ()
+ (should (equal (completion-pcm--optimize-pattern '("buf" point "f"))
+ '("buf" point "f")))
+ (should (equal (completion-pcm--optimize-pattern '(any "" any))
+ '(any))))
+
+(defun test-completion-all-sorted-completions (base def history-var history-list)
+ (with-temp-buffer
+ (insert base)
+ (cl-letf (((symbol-function #'minibufferp) (lambda (&rest _) t)))
+ (let ((completion-styles '(basic))
+ (completion-category-defaults nil)
+ (completion-category-overrides nil)
+ (minibuffer-history-variable history-var)
+ (minibuffer-history history-list)
+ (minibuffer-default def)
+ (minibuffer-completion-table
+ (lambda (str pred action)
+ (pcase action
+ (`(boundaries . ,_) `(boundaries ,(length base) . 0))
+ (_ (complete-with-action
+ action
+ '("epsilon" "alpha" "gamma" "beta" "delta")
+ (substring str (length base)) pred))))))
+ (completion-all-sorted-completions)))))
+
+(ert-deftest completion-all-sorted-completions ()
+ ;; No base, disabled history, no default
+ (should (equal (test-completion-all-sorted-completions
+ "" nil t nil)
+ `("beta" "alpha" "delta" "gamma" "epsilon" . 0)))
+ ;; No base, disabled history, default string
+ (should (equal (test-completion-all-sorted-completions
+ "" "gamma" t nil)
+ `("gamma" "beta" "alpha" "delta" "epsilon" . 0)))
+ ;; No base, empty history, default string
+ (should (equal (test-completion-all-sorted-completions
+ "" "gamma" 'minibuffer-history nil)
+ `("gamma" "beta" "alpha" "delta" "epsilon" . 0)))
+ ;; No base, empty history, default list
+ (should (equal (test-completion-all-sorted-completions
+ "" '("gamma" "zeta") 'minibuffer-history nil)
+ `("gamma" "beta" "alpha" "delta" "epsilon" . 0)))
+ ;; No base, history, default string
+ (should (equal (test-completion-all-sorted-completions
+ "" "gamma" 'minibuffer-history '("other" "epsilon" "delta"))
+ `("gamma" "epsilon" "delta" "beta" "alpha" . 0)))
+ ;; Base, history, default string
+ (should (equal (test-completion-all-sorted-completions
+ "base/" "base/gamma" 'minibuffer-history
+ '("some/alpha" "base/epsilon" "base/delta"))
+ `("gamma" "epsilon" "delta" "beta" "alpha" . 5)))
+ ;; Base, history, default string
+ (should (equal (test-completion-all-sorted-completions
+ "base/" "gamma" 'minibuffer-history
+ '("some/alpha" "base/epsilon" "base/delta"))
+ `("epsilon" "delta" "beta" "alpha" "gamma" . 5))))
+
+(defun completion--pcm-score (comp)
+ "Get `completion-score' from COMP."
+ (get-text-property 0 'completion-score comp))
+
+(defun completion--pcm-first-difference-pos (comp)
+ "Get `completions-first-difference' from COMP."
+ (cl-loop for pos = (next-single-property-change 0 'face comp)
+ then (next-single-property-change pos 'face comp)
+ while pos
+ when (eq (get-text-property pos 'face comp)
+ 'completions-first-difference)
+ return pos))
+
+(ert-deftest completion-pcm-test-1 ()
+ ;; Point is at end, this does not match anything
+ (should (null
+ (completion-pcm-all-completions
+ "foo" '("hello" "world" "barfoobar") nil 3))))
+
+(ert-deftest completion-pcm-test-2 ()
+ ;; Point is at beginning, this matches "barfoobar"
+ (should (equal
+ (car (completion-pcm-all-completions
+ "foo" '("hello" "world" "barfoobar") nil 0))
+ "barfoobar")))
+
+(ert-deftest completion-pcm-test-3 ()
+ ;; Full match!
+ (should (eql
+ (completion--pcm-score
+ (car (completion-pcm-all-completions
+ "R" '("R" "hello") nil 1)))
+ 1.0)))
+
+(ert-deftest completion-pcm-test-4 ()
+ ;; One fourth of a match and no match due to point being at the end
+ (should (eql
+ (completion--pcm-score
+ (car (completion-pcm-all-completions
+ "RO" '("RaOb") nil 1)))
+ (/ 1.0 4.0)))
+ (should (null
+ (completion-pcm-all-completions
+ "RO" '("RaOb") nil 2))))
+
+(ert-deftest completion-pcm-test-5 ()
+ ;; Since point is at the beginning, there is nothing that can really
+ ;; be typed anymore
+ (should (null
+ (completion--pcm-first-difference-pos
+ (car (completion-pcm-all-completions
+ "f" '("few" "many") nil 0))))))
+
+(ert-deftest completion-pcm-test-6 ()
+ ;; Wildcards and delimiters work
+ (should (equal
+ (car (completion-pcm-all-completions
+ "li-pac*" '("list-packages") nil 7))
+ "list-packages"))
+ (should (null
+ (car (completion-pcm-all-completions
+ "li-pac*" '("do-not-list-packages") nil 7)))))
+
+(ert-deftest completion-substring-test-1 ()
+ ;; One third of a match!
+ (should (equal
+ (car (completion-substring-all-completions
+ "foo" '("hello" "world" "barfoobar") nil 3))
+ "barfoobar"))
+ (should (eql
+ (completion--pcm-score
+ (car (completion-substring-all-completions
+ "foo" '("hello" "world" "barfoobar") nil 3)))
+ (/ 1.0 3.0))))
+
+(ert-deftest completion-substring-test-2 ()
+ ;; Full match!
+ (should (eql
+ (completion--pcm-score
+ (car (completion-substring-all-completions
+ "R" '("R" "hello") nil 1)))
+ 1.0)))
+
+(ert-deftest completion-substring-test-3 ()
+ ;; Substring match
+ (should (equal
+ (car (completion-substring-all-completions
+ "custgroup" '("customize-group") nil 4))
+ "customize-group"))
+ (should (null
+ (car (completion-substring-all-completions
+ "custgroup" '("customize-group") nil 5)))))
+
+(ert-deftest completion-substring-test-4 ()
+ ;; `completions-first-difference' should be at the right place
+ (should (eql
+ (completion--pcm-first-difference-pos
+ (car (completion-substring-all-completions
+ "jab" '("dabjobstabby" "many") nil 1)))
+ 4))
+ (should (null
+ (completion--pcm-first-difference-pos
+ (car (completion-substring-all-completions
+ "jab" '("dabjabstabby" "many") nil 1)))))
+ (should (equal
+ (completion--pcm-first-difference-pos
+ (car (completion-substring-all-completions
+ "jab" '("dabjabstabby" "many") nil 3)))
+ 6)))
+
+(ert-deftest completion-flex-test-1 ()
+ ;; Fuzzy match
+ (should (equal
+ (car (completion-flex-all-completions
+ "foo" '("hello" "world" "fabrobazo") nil 3))
+ "fabrobazo")))
+
+(ert-deftest completion-flex-test-2 ()
+ ;; Full match!
+ (should (eql
+ (completion--pcm-score
+ (car (completion-flex-all-completions
+ "R" '("R" "hello") nil 1)))
+ 1.0)))
+
+(ert-deftest completion-flex-test-3 ()
+ ;; Another fuzzy match, but more of a "substring" one
+ (should (equal
+ (car (completion-flex-all-completions
+ "custgroup" '("customize-group-other-window") nil 4))
+ "customize-group-other-window"))
+ ;; `completions-first-difference' should be at the right place
+ (should (equal
+ (completion--pcm-first-difference-pos
+ (car (completion-flex-all-completions
+ "custgroup" '("customize-group-other-window") nil 4)))
+ 4))
+ (should (equal
+ (completion--pcm-first-difference-pos
+ (car (completion-flex-all-completions
+ "custgroup" '("customize-group-other-window") nil 9)))
+ 15)))
+
+
+(defmacro completing-read-with-minibuffer-setup (collection &rest body)
+ (declare (indent 1) (debug (collection body)))
+ `(catch 'result
+ (minibuffer-with-setup-hook
+ (lambda ()
+ (let ((redisplay-skip-initial-frame nil)
+ (executing-kbd-macro nil)) ; Don't skip redisplay
+ (throw 'result (progn . ,body))))
+ (let ((executing-kbd-macro t)) ; Force the real minibuffer
+ (completing-read "Prompt: " ,collection)))))
+
+(ert-deftest completion-auto-help-test ()
+ (let (messages)
+ (cl-letf* (((symbol-function 'minibuffer-message)
+ (lambda (message &rest args)
+ (push (apply #'format-message message args) messages))))
+ (let ((completion-auto-help nil))
+ (completing-read-with-minibuffer-setup
+ '("a" "ab" "ac")
+ (execute-kbd-macro (kbd "a TAB TAB"))
+ (should (equal (car messages) "Complete, but not unique"))
+ (should-not (get-buffer-window "*Completions*" 0))))
+ (let ((completion-auto-help t))
+ (completing-read-with-minibuffer-setup
+ '("a" "ab" "ac")
+ (execute-kbd-macro (kbd "a TAB TAB"))
+ (should (get-buffer-window "*Completions*" 0)))))))
+
+(ert-deftest completion-auto-select-test ()
+ (let ((completion-auto-select t))
+ (completing-read-with-minibuffer-setup
+ '("aa" "ab" "ac")
+ (execute-kbd-macro (kbd "a TAB"))
+ (should (and (get-buffer-window "*Completions*" 0)
+ (eq (current-buffer) (get-buffer "*Completions*"))))
+ (execute-kbd-macro (kbd "TAB TAB TAB"))
+ (should (and (get-buffer-window "*Completions*" 0)
+ (eq (current-buffer) (get-buffer " *Minibuf-1*"))))
+ (execute-kbd-macro (kbd "S-TAB"))
+ (should (and (get-buffer-window "*Completions*" 0)
+ (eq (current-buffer) (get-buffer "*Completions*"))))))
+ (let ((completion-auto-select 'second-tab))
+ (completing-read-with-minibuffer-setup
+ '("aa" "ab" "ac")
+ (execute-kbd-macro (kbd "a TAB"))
+ (should (and (get-buffer-window "*Completions*" 0)
+ (not (eq (current-buffer) (get-buffer "*Completions*")))))
+ (execute-kbd-macro (kbd "TAB TAB"))
+ (should (eq (current-buffer) (get-buffer "*Completions*"))))))
+
+(ert-deftest completion-auto-wrap-test ()
+ (let ((completion-auto-wrap nil))
+ (completing-read-with-minibuffer-setup
+ '("aa" "ab" "ac")
+ (insert "a")
+ (minibuffer-completion-help)
+ (switch-to-completions)
+ (should (equal "aa" (get-text-property (point) 'completion--string)))
+ (next-completion 2)
+ (should (equal "ac" (get-text-property (point) 'completion--string)))
+ ;; Fixed in bug#54374
+ (next-completion 5)
+ (should (equal "ac" (get-text-property (point) 'completion--string)))
+ (previous-completion 5)
+ (should (equal "aa" (get-text-property (point) 'completion--string)))))
+ (let ((completion-auto-wrap t))
+ (completing-read-with-minibuffer-setup
+ '("aa" "ab" "ac")
+ (insert "a")
+ (minibuffer-completion-help)
+ (switch-to-completions)
+ (should (equal "aa" (get-text-property (point) 'completion--string)))
+ (next-completion 2)
+ (should (equal "ac" (get-text-property (point) 'completion--string)))
+ (next-completion 1)
+ (should (equal "aa" (get-text-property (point) 'completion--string)))
+ (previous-completion 1)
+ (should (equal "ac" (get-text-property (point) 'completion--string))))))
+
+(ert-deftest completions-header-format-test ()
+ (let ((completion-show-help nil)
+ (completions-header-format nil))
+ (completing-read-with-minibuffer-setup
+ '("aa" "ab" "ac")
+ (insert "a")
+ (minibuffer-completion-help)
+ (switch-to-completions)
+ ;; Fixed in bug#55430
+ (should (equal "aa" (get-text-property (point) 'completion--string)))
+ (next-completion 2)
+ (should (equal "ac" (get-text-property (point) 'completion--string)))
+ (previous-completion 2)
+ (should (equal "aa" (get-text-property (point) 'completion--string)))
+ ;; Fixed in bug#54374
+ (previous-completion 1)
+ (should (equal "ac" (get-text-property (point) 'completion--string)))
+ (next-completion 1)
+ (should (equal "aa" (get-text-property (point) 'completion--string)))
+ ;; Fixed in bug#55430
+ (execute-kbd-macro (kbd "C-u RET"))
+ (should (equal (minibuffer-contents) "aa")))
+ (completing-read-with-minibuffer-setup
+ '("aa" "ab" "ac")
+ ;; Fixed in bug#55289
+ (execute-kbd-macro (kbd "a M-<up> M-<down>"))
+ (should (equal (minibuffer-contents) "aa")))))
+
+(ert-deftest completions-affixation-navigation-test ()
+ (let ((completion-extra-properties
+ '(:affixation-function
+ (lambda (completions)
+ (mapcar (lambda (c)
+ (list c "prefix " " suffix"))
+ completions)))))
+ (completing-read-with-minibuffer-setup
+ '("aa" "ab" "ac")
+ (insert "a")
+ (minibuffer-completion-help)
+ (switch-to-completions)
+ (should (equal 'highlight (get-text-property (point) 'mouse-face)))
+ (should (equal "aa" (get-text-property (point) 'completion--string)))
+ (let ((completion-auto-wrap t))
+ (next-completion 3))
+ (should (equal 'highlight (get-text-property (point) 'mouse-face)))
+ (should (equal "aa" (get-text-property (point) 'completion--string)))
+ (let ((completion-auto-wrap nil))
+ (next-completion 3))
+ (should (equal 'highlight (get-text-property (point) 'mouse-face)))
+ (should (equal "ac" (get-text-property (point) 'completion--string)))
+ ;; Fixed in bug#54374
+ (goto-char (1- (point-max)))
+ (should-not (equal 'highlight (get-text-property (point) 'mouse-face)))
+ (execute-kbd-macro (kbd "C-u RET"))
+ (should (equal (minibuffer-contents) "ac")))))
+
+(provide 'minibuffer-tests)
+;;; minibuffer-tests.el ends here
diff --git a/test/lisp/misc-tests.el b/test/lisp/misc-tests.el
new file mode 100644
index 00000000000..f84827ab025
--- /dev/null
+++ b/test/lisp/misc-tests.el
@@ -0,0 +1,138 @@
+;;; misc-tests.el --- Tests for misc.el -*- lexical-binding:t -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+;; Author: Stefan Kangas <stefankangas@gmail.com>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+
+(defmacro with-misc-test (original result &rest body)
+ (declare (indent 2))
+ `(with-temp-buffer
+ (insert ,original)
+ ,@body
+ (should (equal (buffer-string) ,result))))
+
+(ert-deftest misc-test-copy-from-above-command ()
+ (with-misc-test "abc\n" "abc\nabc"
+ (copy-from-above-command))
+ (with-misc-test "abc\n" "abc\nab"
+ (copy-from-above-command 2)))
+
+(ert-deftest misc-test-zap-up-to-char ()
+ (with-misc-test "abcde" "cde"
+ (goto-char (point-min))
+ (zap-up-to-char 1 ?c))
+ (with-misc-test "abcde abc123" "c123"
+ (goto-char (point-min))
+ (zap-up-to-char 2 ?c))
+ (let ((case-fold-search t))
+ (with-misc-test "abcdeCXYZ" "cdeCXYZ"
+ (goto-char (point-min))
+ (zap-up-to-char 1 ?C))
+ (with-misc-test "abcdeCXYZ" "CXYZ"
+ (goto-char (point-min))
+ (zap-up-to-char 1 ?C 'interactive))))
+
+(ert-deftest misc-test-upcase-char ()
+ (with-misc-test "abcde" "aBCDe"
+ (goto-char (1+ (point-min)))
+ (upcase-char 3)))
+
+(ert-deftest misc-test-forward-to-word ()
+ (with-temp-buffer
+ (insert " - abc")
+ (goto-char (point-min))
+ (forward-to-word 1)
+ (should (equal (point) 9)))
+ (with-temp-buffer
+ (insert "a b c")
+ (goto-char (point-min))
+ (forward-to-word 3)
+ (should (equal (point) 6))))
+
+(ert-deftest misc-test-backward-to-word ()
+ (with-temp-buffer
+ (insert "abc - ")
+ (backward-to-word 1)
+ (should (equal (point) 4)))
+ (with-temp-buffer
+ (insert "a b c")
+ (backward-to-word 3)
+ (should (equal (point) 1))))
+
+(ert-deftest misc--duplicate-line ()
+ ;; Duplicate a line (twice).
+ (with-temp-buffer
+ (insert "abc\ndefg\nh\n")
+ (goto-char 7)
+ (duplicate-line 2)
+ (should (equal (buffer-string) "abc\ndefg\ndefg\ndefg\nh\n"))
+ (should (equal (point) 7)))
+ ;; Duplicate a non-terminated line.
+ (with-temp-buffer
+ (insert "abc")
+ (goto-char 2)
+ (duplicate-line)
+ (should (equal (buffer-string) "abc\nabc\n"))
+ (should (equal (point) 2))))
+
+(require 'rect)
+
+(ert-deftest misc--duplicate-dwim ()
+ ;; Duplicate a line.
+ (with-temp-buffer
+ (insert "abc\ndefg\nh\n")
+ (goto-char 7)
+ (duplicate-dwim 2)
+ (should (equal (buffer-string) "abc\ndefg\ndefg\ndefg\nh\n"))
+ (should (equal (point) 7)))
+
+ ;; Duplicate a region.
+ (with-temp-buffer
+ (insert "abc\ndef\n")
+ (set-mark 2)
+ (goto-char 7)
+ (transient-mark-mode)
+ (should (use-region-p))
+ (duplicate-dwim)
+ (should (equal (buffer-string) "abc\ndebc\ndef\n"))
+ (should (equal (point) 7))
+ (should (region-active-p))
+ (should (equal (mark) 2)))
+
+ ;; Duplicate a rectangular region.
+ (with-temp-buffer
+ (insert "x\n>a\n>bcde\n>fg\nyz\n")
+ (goto-char 4)
+ (rectangle-mark-mode)
+ (goto-char 15)
+ (rectangle-forward-char 1)
+ (duplicate-dwim)
+ (should (equal (buffer-string) "x\n>a a \n>bcdbcde\n>fg fg \nyz\n"))
+ (should (equal (point) 24))
+ (should (region-active-p))
+ (should rectangle-mark-mode)
+ (should (equal (mark) 4))))
+
+(provide 'misc-tests)
+;;; misc-tests.el ends here
diff --git a/test/lisp/mouse-tests.el b/test/lisp/mouse-tests.el
index f8c91004ecc..03ecbc19858 100644
--- a/test/lisp/mouse-tests.el
+++ b/test/lisp/mouse-tests.el
@@ -1,6 +1,6 @@
;;; mouse-tests.el --- unit tests for mouse.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2016-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2022 Free Software Foundation, Inc.
;; Author: Philipp Stephani <phst@google.com>
@@ -25,27 +25,38 @@
;;; Code:
+(ert-deftest mouse-test-mouse-double-click-time ()
+ (let ((double-click-time 500))
+ (should (= (mouse-double-click-time) 500)))
+ (let ((double-click-time 0))
+ (should (= (mouse-double-click-time) 0)))
+ (let ((double-click-time -500))
+ (should (= (mouse-double-click-time) 0)))
+ (let ((double-click-time nil))
+ (should (= (mouse-double-click-time) 0)))
+ (let ((double-click-time t))
+ (should (numberp (mouse-double-click-time))))
+ (let ((double-click-time '(invalid)))
+ (should (= (mouse-double-click-time) 0))))
+
(ert-deftest bug23288-use-return-value ()
- "If ‘mouse-on-link-p’ returns a string, its first character is
-used."
- (cl-letf ((last-input-event '(down-mouse-1 nil 1))
- (unread-command-events '((mouse-1 nil 1)))
+ "If `mouse-on-link-p' returns a string, its first character is used."
+ (cl-letf ((unread-command-events '((down-mouse-1 nil 1) (mouse-1 nil 1)))
(mouse-1-click-follows-link t)
(mouse-1-click-in-non-selected-windows t)
((symbol-function 'mouse-on-link-p) (lambda (_pos) "abc")))
- (should-not (mouse--down-1-maybe-follows-link))
- (should (equal unread-command-events '(?a)))))
+ (should (eq 'down-mouse-1 (car-safe (aref (read-key-sequence "") 0))))
+ (should (eq ?a (aref (read-key-sequence "") 0)))))
(ert-deftest bug23288-translate-to-mouse-2 ()
- "If ‘mouse-on-link-p’ doesn’t return a string or vector,
-translate ‘mouse-1’ events into ‘mouse-2’ events."
- (cl-letf ((last-input-event '(down-mouse-1 nil 1))
- (unread-command-events '((mouse-1 nil 1)))
+ "If `mouse-on-link-p' doesn't return a string or vector,
+translate `mouse-1' events into `mouse-2' events."
+ (cl-letf ((unread-command-events '((down-mouse-1 nil 1) (mouse-1 nil 1)))
(mouse-1-click-follows-link t)
(mouse-1-click-in-non-selected-windows t)
((symbol-function 'mouse-on-link-p) (lambda (_pos) t)))
- (should-not (mouse--down-1-maybe-follows-link))
- (should (equal unread-command-events '((mouse-2 nil 1))))))
+ (should (eq 'down-mouse-1 (car-safe (aref (read-key-sequence "") 0))))
+ (should (eq 'mouse-2 (car-safe (aref (read-key-sequence "") 0))))))
(ert-deftest bug26816-mouse-frame-movement ()
"Mouse moves relative to frame."
@@ -55,5 +66,167 @@ translate ‘mouse-1’ events into ‘mouse-2’ events."
(should (equal (mouse-position)
(cons frame (cons 0 0))))))
+(ert-deftest context-menu-map-remove-consecutive-separators ()
+ "Check that `context-menu-map' removes consecutive separators."
+ ;; Both separators after the overall prompt string.
+ (let ((context-menu-functions
+ '((lambda (menu _click)
+ (define-key-after menu [foo-item] '(menu-item "Foo" identity))
+ (define-key-after menu [separator-1] menu-bar-separator)
+ (define-key-after menu [separator-2] menu-bar-separator)
+ (define-key-after menu [bar-item] '(menu-item "Bar" identity))
+ menu))))
+ (should (equal `(keymap
+ "Context Menu"
+ (foo-item menu-item "Foo" identity)
+ (separator-1 . ,menu-bar-separator)
+ (bar-item menu-item "Bar" identity))
+ (context-menu-map))))
+ ;; Both separators before the overall prompt string.
+ (let ((context-menu-functions
+ '((lambda (menu _click)
+ (define-key menu [bar-item] '(menu-item "Bar" identity))
+ (define-key menu [separator-2] menu-bar-separator)
+ (define-key menu [separator-1] menu-bar-separator)
+ (define-key menu [foo-item] '(menu-item "Foo" identity))
+ menu))))
+ (should (equal `(keymap
+ (foo-item menu-item "Foo" identity)
+ (separator-1 . ,menu-bar-separator)
+ (bar-item menu-item "Bar" identity)
+ "Context Menu")
+ (context-menu-map))))
+ ;; First separator before and second separator after the overall
+ ;; prompt string.
+ (let ((context-menu-functions
+ '((lambda (menu _click)
+ (define-key-after menu [separator-2] menu-bar-separator)
+ (define-key-after menu [bar-item] '(menu-item "Bar" identity))
+ (define-key menu [separator-1] menu-bar-separator)
+ (define-key menu [foo-item] '(menu-item "Foo" identity))
+ menu))))
+ (should (equal `(keymap
+ (foo-item menu-item "Foo" identity)
+ (separator-1 . ,menu-bar-separator)
+ "Context Menu"
+ (bar-item menu-item "Bar" identity))
+ (context-menu-map))))
+ ;; Three consecutive separators.
+ (let ((context-menu-functions
+ '((lambda (menu _click)
+ (define-key-after menu [foo-item] '(menu-item "Foo" identity))
+ (define-key-after menu [separator-1] menu-bar-separator)
+ (define-key-after menu [separator-2] menu-bar-separator)
+ (define-key-after menu [separator-3] menu-bar-separator)
+ (define-key-after menu [bar-item] '(menu-item "Bar" identity))
+ menu))))
+ (should (equal `(keymap
+ "Context Menu"
+ (foo-item menu-item "Foo" identity)
+ (separator-1 . ,menu-bar-separator)
+ (bar-item menu-item "Bar" identity))
+ (context-menu-map)))))
+
+(ert-deftest context-menu-map-remove-separators-at-beginning-or-end ()
+ "Check that `context-menu-map' removes separators at the
+beginning or end of the menu."
+ ;; Menus with only separators.
+ (let ((test-functions
+ '(;; Separator before the overall prompt string.
+ (lambda (menu _click)
+ (define-key menu [separator] menu-bar-separator)
+ menu)
+ ;; Separator after the overall prompt string.
+ (lambda (menu _click)
+ (define-key-after menu [separator] menu-bar-separator)
+ menu)
+ ;; Begin and end separators before the overall prompt string.
+ (lambda (menu _click)
+ (define-key menu [end-separator] menu-bar-separator)
+ (define-key menu [begin-separator] menu-bar-separator)
+ menu)
+ ;; Begin and end separators after the overall prompt string.
+ (lambda (menu _click)
+ (define-key-after menu [begin-separator] menu-bar-separator)
+ (define-key-after menu [end-separator] menu-bar-separator)
+ menu)
+ ;; Begin separator before and end separator after the
+ ;; overall prompt string.
+ (lambda (menu _click)
+ (define-key menu [begin-separator] menu-bar-separator)
+ (define-key-after menu [end-separator] menu-bar-separator)
+ menu))))
+ (dolist (fun test-functions)
+ (let ((context-menu-functions (list fun)))
+ (should (equal '(keymap "Context Menu")
+ (context-menu-map))))))
+ ;; Menus with separators at beginning and/or end with a menu-item
+ ;; before the prompt string.
+ (let ((test-functions
+ '(;; Separator before the overall prompt string and the menu-item.
+ (lambda (menu _click)
+ (define-key menu [foo-item] '(menu-item "Foo" identity))
+ (define-key menu [separator] menu-bar-separator)
+ menu)
+ ;; Separator before the overall prompt string, but after
+ ;; the menu-item.
+ (lambda (menu _click)
+ (define-key menu [separator] menu-bar-separator)
+ (define-key menu [foo-item] '(menu-item "Foo" identity))
+ menu)
+ ;; Separator at the end.
+ (lambda (menu _click)
+ (define-key menu [foo-item] '(menu-item "Foo" identity))
+ (define-key-after menu [separator] menu-bar-separator)
+ menu)
+ ;; Begin separator before and end separator after the
+ ;; overall prompt string.
+ (lambda (menu _click)
+ (define-key menu [foo-item] '(menu-item "Foo" identity))
+ (define-key menu [begin-separator] menu-bar-separator)
+ (define-key-after menu [end-separator] menu-bar-separator)
+ menu))))
+ (dolist (fun test-functions)
+ (let ((context-menu-functions (list fun)))
+ (should (equal '(keymap (foo-item menu-item "Foo" identity)
+ "Context Menu")
+ (context-menu-map))))))
+ ;; Menus with separators at beginning and/or end with a menu-item
+ ;; after the prompt string.
+ (let ((test-functions
+ '(;; Separator before the overall prompt string.
+ (lambda (menu _click)
+ (define-key menu [separator] menu-bar-separator)
+ (define-key-after menu [foo-item] '(menu-item "Foo" identity))
+ menu)
+ ;; Separator after the overall prompt string, but before
+ ;; the menu-item.
+ (lambda (menu _click)
+ (define-key-after menu [separator] menu-bar-separator)
+ (define-key-after menu [foo-item] '(menu-item "Foo" identity))
+ menu)
+ ;; Separator at the end.
+ (lambda (menu _click)
+ (define-key-after menu [foo-item] '(menu-item "Foo" identity))
+ (define-key-after menu [separator] menu-bar-separator)
+ menu)
+ ;; Begin and end separators after the overall prompt string.
+ (lambda (menu _click)
+ (define-key-after menu [begin-separator] menu-bar-separator)
+ (define-key-after menu [foo-item] '(menu-item "Foo" identity))
+ (define-key-after menu [end-separator] menu-bar-separator)
+ menu)
+ ;; Begin separator before and end separator after the
+ ;; overall prompt string.
+ (lambda (menu _click)
+ (define-key menu [begin-separator] menu-bar-separator)
+ (define-key-after menu [foo-item] '(menu-item "Foo" identity))
+ (define-key-after menu [end-separator] menu-bar-separator)
+ menu))))
+ (dolist (fun test-functions)
+ (let ((context-menu-functions (list fun)))
+ (should (equal '(keymap "Context Menu"
+ (foo-item menu-item "Foo" identity))
+ (context-menu-map)))))))
;;; mouse-tests.el ends here
diff --git a/test/lisp/mwheel-tests.el b/test/lisp/mwheel-tests.el
new file mode 100644
index 00000000000..947dfdbb5e8
--- /dev/null
+++ b/test/lisp/mwheel-tests.el
@@ -0,0 +1,46 @@
+;;; mwheel-tests.el --- tests for mwheel.el -*- lexical-binding:t -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'mwheel)
+
+(ert-deftest mwheel-test-enable/disable ()
+ (mouse-wheel-mode 1)
+ (should (eq (lookup-key (current-global-map) `[,mouse-wheel-up-event]) 'mwheel-scroll))
+ (mouse-wheel-mode -1)
+ (should (eq (lookup-key (current-global-map) `[,mouse-wheel-up-event]) nil)))
+
+(ert-deftest mwheel-test--create-scroll-keys ()
+ (should (equal (mouse-wheel--create-scroll-keys 10 'mouse-4)
+ '([mouse-4]
+ [left-margin mouse-4] [right-margin mouse-4]
+ [left-fringe mouse-4] [right-fringe mouse-4]
+ [vertical-scroll-bar mouse-4] [horizontal-scroll-bar mouse-4]
+ [mode-line mouse-4] [header-line mouse-4])))
+ ;; Don't bind modifiers outside of buffer area (e.g. for fringes).
+ (should (equal (mouse-wheel--create-scroll-keys '((shift) . 1) 'mouse-4)
+ '([(shift mouse-4)])))
+ (should (equal (mouse-wheel--create-scroll-keys '((control) . 9) 'mouse-7)
+ '([(control mouse-7)])))
+ (should (equal (mouse-wheel--create-scroll-keys '((meta) . 5) 'mouse-5)
+ '([(meta mouse-5)]))))
+
+;;; mwheel-tests.el ends here
diff --git a/test/lisp/net/browse-url-tests.el b/test/lisp/net/browse-url-tests.el
new file mode 100644
index 00000000000..1c993958b81
--- /dev/null
+++ b/test/lisp/net/browse-url-tests.el
@@ -0,0 +1,122 @@
+;;; browse-url-tests.el --- Tests for browse-url.el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+;; Author: Simen Heggestøyl <simenheg@gmail.com>
+;; Keywords:
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;
+
+;;; Code:
+
+(require 'browse-url)
+(require 'ert)
+(require 'ert-x)
+
+(ert-deftest browse-url-tests-browser-kind ()
+ (should (eq (browse-url--browser-kind #'browse-url-emacs "gnu.org")
+ 'internal))
+ (should
+ (eq (browse-url--browser-kind #'browse-url-firefox "gnu.org")
+ 'external)))
+
+(ert-deftest browse-url-tests-non-html-file-url-p ()
+ (should (browse-url--non-html-file-url-p "file://foo.txt"))
+ (should-not (browse-url--non-html-file-url-p "file://foo.html")))
+
+(ert-deftest browse-url-tests-select-handler-mailto ()
+ (should (eq (browse-url-select-handler "mailto:foo@bar.org")
+ 'browse-url--mailto))
+ (should (eq (browse-url-select-handler "mailto:foo@bar.org"
+ 'internal)
+ 'browse-url--mailto))
+ (should-not (browse-url-select-handler "mailto:foo@bar.org"
+ 'external)))
+
+(ert-deftest browse-url-tests-select-handler-man ()
+ (should (eq (browse-url-select-handler "man:ls") 'browse-url--man))
+ (should (eq (browse-url-select-handler "man:ls" 'internal)
+ 'browse-url--man))
+ (should-not (browse-url-select-handler "man:ls" 'external)))
+
+(ert-deftest browse-url-tests-select-handler-file ()
+ (should (eq (browse-url-select-handler "file://foo.txt")
+ 'browse-url-emacs))
+ (should (eq (browse-url-select-handler "file://foo.txt" 'internal)
+ 'browse-url-emacs))
+ (should-not (browse-url-select-handler "file://foo.txt" 'external)))
+
+(ert-deftest browse-url-tests-url-encode-chars ()
+ (should (equal (browse-url-url-encode-chars "foobar" "[ob]")
+ "f%6F%6F%62ar")))
+
+(ert-deftest browse-url-tests-encode-url ()
+ (should (equal (browse-url-encode-url "") ""))
+ (should (equal (browse-url-encode-url "a b c") "a%20b%20c"))
+ (should (equal (browse-url-encode-url "\"a\" \"b\"")
+ "%22a%22%20%22b%22"))
+ (should (equal (browse-url-encode-url "(a) (b)") "%28a%29%20%28b%29"))
+ (should (equal (browse-url-encode-url "a$ b$") "a$%20b$")))
+
+(ert-deftest browse-url-tests-url-at-point ()
+ (with-temp-buffer
+ (insert "gnu.org")
+ (should (equal (browse-url-url-at-point) "http://gnu.org"))))
+
+(ert-deftest browse-url-tests-file-url ()
+ (should (equal (browse-url-file-url "/foo") "file:///foo"))
+ (when (file-remote-p "/foo:")
+ (should (equal (browse-url-file-url "/foo:") "ftp://foo/")))
+ (when (file-remote-p "/ftp@foo:")
+ (should (equal (browse-url-file-url "/ftp@foo:") "ftp://foo/")))
+ (when (file-remote-p "/anonymous@foo:")
+ (should (equal (browse-url-file-url "/anonymous@foo:")
+ "ftp://foo/"))))
+
+(ert-deftest browse-url-tests-delete-temp-file ()
+ (ert-with-temp-file browse-url-temp-file-name
+ (browse-url-delete-temp-file)
+ (should-not (file-exists-p browse-url-temp-file-name)))
+ (ert-with-temp-file file
+ (browse-url-delete-temp-file file)
+ (should-not (file-exists-p file))))
+
+(ert-deftest browse-url-tests-add-buttons ()
+ (with-temp-buffer
+ (insert "Visit https://gnu.org")
+ (goto-char (point-min))
+ (browse-url-add-buttons)
+ (goto-char (- (point-max) 1))
+ (should (eq (get-text-property (point) 'face)
+ 'browse-url-button))
+ (should (get-text-property (point) 'browse-url-data))))
+
+(ert-deftest browse-url-tests-button-copy ()
+ (with-temp-buffer
+ (insert "Visit https://gnu.org")
+ (goto-char (point-min))
+ (browse-url-add-buttons)
+ (should-error (browse-url-button-copy))
+ (goto-char (- (point-max) 1))
+ (browse-url-button-copy)
+ (should (equal (car kill-ring) "https://gnu.org"))))
+
+(provide 'browse-url-tests)
+;;; browse-url-tests.el ends here
diff --git a/test/lisp/net/dbus-resources/org.gnu.Emacs.TestDBus.xml b/test/lisp/net/dbus-resources/org.gnu.Emacs.TestDBus.xml
new file mode 100644
index 00000000000..620f10510f2
--- /dev/null
+++ b/test/lisp/net/dbus-resources/org.gnu.Emacs.TestDBus.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0"?>
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node>
+ <interface name="org.freedesktop.DBus.Introspectable">
+ <method name="Introspect">
+ <arg name="xml" type="s" direction="out"/>
+ </method>
+ </interface>
+ <interface name="org.freedesktop.DBus.Properties">
+ <method name="Get">
+ <arg name="interface" type="s" direction="in"/>
+ <arg name="name" type="s" direction="in"/>
+ <arg name="value" type="v" direction="out"/>
+ </method>
+ <method name="Set">
+ <arg name="interface" type="s" direction="in"/>
+ <arg name="name" type="s" direction="in"/>
+ <arg name="value" type="v" direction="in"/>
+ </method>
+ <method name="GetAll">
+ <arg name="interface" type="s" direction="in"/>
+ <arg name="properties" type="a{sv}" direction="out"/>
+ </method>
+ <signal name="PropertiesChanged">
+ <arg name="interface" type="s"/>
+ <arg name="changed_properties" type="a{sv}"/>
+ <arg name="invalidated_properties" type="as"/>
+ </signal>
+ </interface>
+ <interface name="org.gnu.Emacs.TestDBus.Interface">
+ <method name="Connect">
+ <arg name="uuid" type="s" direction="in"/>
+ <arg name="mode" type="y" direction="in"/>
+ <arg name="options" type="a{sv}" direction="in"/>
+ <arg name="interface" type="s" direction="out"/>
+ </method>
+ <method name="DeprecatedMethod0">
+ <annotation name="org.freedesktop.DBus.Deprecated" value="true"/>
+ </method>
+ <method name="DeprecatedMethod1">
+ <annotation name="org.freedesktop.DBus.Deprecated" value="true"/>
+ </method>
+ <property name="Connected" type="b" access="read"/>
+ <property name="Player" type="o" access="read"/>
+ <annotation name="org.freedesktop.DBus.Deprecated" value="true"/>
+ </interface>
+ <node name="node0"/>
+ <node name="node1"/>
+</node>
diff --git a/test/lisp/net/dbus-tests.el b/test/lisp/net/dbus-tests.el
index cdae9cce456..76318429181 100644
--- a/test/lisp/net/dbus-tests.el
+++ b/test/lisp/net/dbus-tests.el
@@ -1,40 +1,52 @@
-;;; dbus-tests.el --- Tests of D-Bus integration into Emacs
+;;; dbus-tests.el --- Tests of D-Bus integration into Emacs -*- lexical-binding:t -*-
-;; Copyright (C) 2013-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2022 Free Software Foundation, Inc.
;; Author: Michael Albinus <michael.albinus@gmx.de>
-;; This program is free software: you can redistribute it and/or
-;; modify it under the terms of the GNU General Public License as
-;; published by the Free Software Foundation, either version 3 of the
-;; License, or (at your option) any later version.
-;;
-;; This program is distributed in the hope that it will be useful, but
-;; WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-;; General Public License for more details.
-;;
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
;; You should have received a copy of the GNU General Public License
-;; along with this program. If not, see `https://www.gnu.org/licenses/'.
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Code:
(require 'ert)
+(require 'ert-x)
(require 'dbus)
(defvar dbus-debug nil)
(declare-function dbus-get-unique-name "dbusbind.c" (bus))
-(defvar dbus--test-enabled-session-bus
+(defconst dbus--test-enabled-session-bus
(and (featurep 'dbusbind)
(dbus-ignore-errors (dbus-get-unique-name :session)))
"Check, whether we are registered at the session bus.")
-(defvar dbus--test-enabled-system-bus
+(defconst dbus--test-enabled-system-bus
(and (featurep 'dbusbind)
(dbus-ignore-errors (dbus-get-unique-name :system)))
"Check, whether we are registered at the system bus.")
+(defconst dbus--test-service "org.gnu.Emacs.TestDBus"
+ "Test service.")
+
+(defconst dbus--test-path "/org/gnu/Emacs/TestDBus"
+ "Test object path.")
+
+(defconst dbus--test-interface "org.gnu.Emacs.TestDBus.Interface"
+ "Test interface.")
+
(defun dbus--test-availability (bus)
"Test availability of D-Bus BUS."
(should (dbus-list-names bus))
@@ -54,6 +66,8 @@
(ert-deftest dbus-test01-type-conversion ()
"Check type conversion functions."
+ (skip-unless dbus--test-enabled-session-bus)
+
(let ((ustr "0123abc_xyz\x01\xff")
(mstr "Grüß Göttin"))
(should
@@ -82,31 +96,399 @@
(string-equal
(dbus-unescape-from-identifier (dbus-escape-as-identifier mstr)) mstr))))
+(ert-deftest dbus-test01-basic-types ()
+ "Check basic D-Bus type arguments."
+ (skip-unless dbus--test-enabled-session-bus)
+
+ ;; No argument or unknown keyword.
+ (should-error
+ (dbus-check-arguments :session dbus--test-service)
+ :type 'wrong-number-of-arguments)
+ (should-error
+ (dbus-check-arguments :session dbus--test-service :keyword)
+ :type 'wrong-type-argument)
+
+ ;; `:string'.
+ (should (dbus-check-arguments :session dbus--test-service "string"))
+ (should (dbus-check-arguments :session dbus--test-service :string "string"))
+ (should-error
+ (dbus-check-arguments :session dbus--test-service :string)
+ :type 'wrong-type-argument)
+ (should-error
+ (dbus-check-arguments :session dbus--test-service :string 0.5)
+ :type 'wrong-type-argument)
+
+ ;; `:object-path'.
+ (should
+ (dbus-check-arguments
+ :session dbus--test-service :object-path "/object/path"))
+ (should-error
+ (dbus-check-arguments :session dbus--test-service :object-path)
+ :type 'wrong-type-argument)
+ (should-error
+ (dbus-check-arguments :session dbus--test-service :object-path "string")
+ :type 'dbus-error)
+ (should-error
+ (dbus-check-arguments :session dbus--test-service :object-path 0.5)
+ :type 'wrong-type-argument)
+
+ ;; `:signature'.
+ (should (dbus-check-arguments :session dbus--test-service :signature "as"))
+ (should-error
+ (dbus-check-arguments :session dbus--test-service :signature)
+ :type 'wrong-type-argument)
+ ;; Raises an error on stderr.
+ (should-error
+ (dbus-check-arguments :session dbus--test-service :signature "string")
+ :type 'dbus-error)
+ (should-error
+ (dbus-check-arguments :session dbus--test-service :signature 0.5)
+ :type 'wrong-type-argument)
+
+ ;; `:boolean'.
+ (should (dbus-check-arguments :session dbus--test-service nil))
+ (should (dbus-check-arguments :session dbus--test-service t))
+ (should (dbus-check-arguments :session dbus--test-service :boolean nil))
+ (should (dbus-check-arguments :session dbus--test-service :boolean t))
+ (should (dbus-check-arguments :session dbus--test-service :boolean 'whatever))
+ (should-error
+ (dbus-check-arguments :session dbus--test-service :boolean)
+ :type 'wrong-type-argument)
+
+ ;; `:byte'.
+ (should (dbus-check-arguments :session dbus--test-service :byte 0))
+ ;; Only the least significant byte is taken into account.
+ (should
+ (dbus-check-arguments :session dbus--test-service :byte most-positive-fixnum))
+ (should-error
+ (dbus-check-arguments :session dbus--test-service :byte)
+ :type 'wrong-type-argument)
+ (should-error
+ (dbus-check-arguments :session dbus--test-service :byte -1)
+ :type 'wrong-type-argument)
+ (should-error
+ (dbus-check-arguments :session dbus--test-service :byte 0.5)
+ :type 'wrong-type-argument)
+ (should-error
+ (dbus-check-arguments :session dbus--test-service :byte "string")
+ :type 'wrong-type-argument)
+
+ ;; `:int16'.
+ (should (dbus-check-arguments :session dbus--test-service :int16 0))
+ (should (dbus-check-arguments :session dbus--test-service :int16 #x7fff))
+ (should (dbus-check-arguments :session dbus--test-service :int16 #x-8000))
+ (should-error
+ (dbus-check-arguments :session dbus--test-service :int16)
+ :type 'wrong-type-argument)
+ (should-error
+ (dbus-check-arguments :session dbus--test-service :int16 #x8000)
+ :type 'args-out-of-range)
+ (should-error
+ (dbus-check-arguments :session dbus--test-service :int16 #x-8001)
+ :type 'args-out-of-range)
+ (should-error
+ (dbus-check-arguments :session dbus--test-service :int16 0.5)
+ :type 'wrong-type-argument)
+ (should-error
+ (dbus-check-arguments :session dbus--test-service :int16 "string")
+ :type 'wrong-type-argument)
+
+ ;; `:uint16'.
+ (should (dbus-check-arguments :session dbus--test-service :uint16 0))
+ (should (dbus-check-arguments :session dbus--test-service :uint16 #xffff))
+ (should-error
+ (dbus-check-arguments :session dbus--test-service :uint16)
+ :type 'wrong-type-argument)
+ (should-error
+ (dbus-check-arguments :session dbus--test-service :uint16 #x10000)
+ :type 'args-out-of-range)
+ (should-error
+ (dbus-check-arguments :session dbus--test-service :uint16 -1)
+ :type 'wrong-type-argument)
+ (should-error
+ (dbus-check-arguments :session dbus--test-service :uint16 0.5)
+ :type 'wrong-type-argument)
+ (should-error
+ (dbus-check-arguments :session dbus--test-service :uint16 "string")
+ :type 'wrong-type-argument)
+
+ ;; `:int32'.
+ (should (dbus-check-arguments :session dbus--test-service :int32 0))
+ (should (dbus-check-arguments :session dbus--test-service :int32 #x7fffffff))
+ (should (dbus-check-arguments :session dbus--test-service :int32 #x-80000000))
+ (should-error
+ (dbus-check-arguments :session dbus--test-service :int32)
+ :type 'wrong-type-argument)
+ (should-error
+ (dbus-check-arguments :session dbus--test-service :int32 #x80000000)
+ :type 'args-out-of-range)
+ (should-error
+ (dbus-check-arguments :session dbus--test-service :int32 #x-80000001)
+ :type 'args-out-of-range)
+ (should-error
+ (dbus-check-arguments :session dbus--test-service :int32 0.5)
+ :type 'args-out-of-range)
+ (should-error
+ (dbus-check-arguments :session dbus--test-service :int32 "string")
+ :type 'wrong-type-argument)
+
+ ;; `:uint32'.
+ (should (dbus-check-arguments :session dbus--test-service 0))
+ (should (dbus-check-arguments :session dbus--test-service :uint32 0))
+ (should (dbus-check-arguments :session dbus--test-service :uint32 #xffffffff))
+ (should-error
+ (dbus-check-arguments :session dbus--test-service :uint32)
+ :type 'wrong-type-argument)
+ (should-error
+ (dbus-check-arguments :session dbus--test-service :uint32 #x100000000)
+ :type 'args-out-of-range)
+ (should-error
+ (dbus-check-arguments :session dbus--test-service :uint32 -1)
+ :type 'args-out-of-range)
+ (should-error
+ (dbus-check-arguments :session dbus--test-service :uint32 0.5)
+ :type 'args-out-of-range)
+ (should-error
+ (dbus-check-arguments :session dbus--test-service :uint32 "string")
+ :type 'wrong-type-argument)
+
+ ;; `:int64'.
+ (should (dbus-check-arguments :session dbus--test-service :int64 0))
+ (should
+ (dbus-check-arguments :session dbus--test-service :int64 #x7fffffffffffffff))
+ (should
+ (dbus-check-arguments :session dbus--test-service :int64 #x-8000000000000000))
+ (should-error
+ (dbus-check-arguments :session dbus--test-service :int64)
+ :type 'wrong-type-argument)
+ (should-error
+ (dbus-check-arguments :session dbus--test-service :int64 #x8000000000000000)
+ :type 'args-out-of-range)
+ (should-error
+ (dbus-check-arguments :session dbus--test-service :int64 #x-8000000000000001)
+ :type 'args-out-of-range)
+ (should-error
+ (dbus-check-arguments :session dbus--test-service :int64 0.5)
+ :type 'args-out-of-range)
+ (should-error
+ (dbus-check-arguments :session dbus--test-service :int64 "string")
+ :type 'wrong-type-argument)
+
+ ;; `:uint64'.
+ (should (dbus-check-arguments :session dbus--test-service :uint64 0))
+ (should
+ (dbus-check-arguments :session dbus--test-service :uint64 #xffffffffffffffff))
+ (should-error
+ (dbus-check-arguments :session dbus--test-service :uint64)
+ :type 'wrong-type-argument)
+ (should-error
+ (dbus-check-arguments :session dbus--test-service :uint64 #x10000000000000000)
+ :type 'args-out-of-range)
+ (should-error
+ (dbus-check-arguments :session dbus--test-service :uint64 -1)
+ :type 'args-out-of-range)
+ (should-error
+ (dbus-check-arguments :session dbus--test-service :uint64 0.5)
+ :type 'args-out-of-range)
+ (should-error
+ (dbus-check-arguments :session dbus--test-service :uint64 "string")
+ :type 'wrong-type-argument)
+
+ ;; `:double'.
+ (should (dbus-check-arguments :session dbus--test-service :double 0))
+ (should (dbus-check-arguments :session dbus--test-service :double 0.5))
+ (should (dbus-check-arguments :session dbus--test-service :double -0.5))
+ (should (dbus-check-arguments :session dbus--test-service :double -1))
+ ;; Shall both be supported?
+ (should (dbus-check-arguments :session dbus--test-service :double 1.0e+INF))
+ (should (dbus-check-arguments :session dbus--test-service :double 0.0e+NaN))
+ (should-error
+ (dbus-check-arguments :session dbus--test-service :double)
+ :type 'wrong-type-argument)
+ (should-error
+ (dbus-check-arguments :session dbus--test-service :double "string")
+ :type 'wrong-type-argument)
+
+ ;; `:unix-fd'. UNIX file descriptors are transferred out-of-band.
+ ;; We do not support this, and so we cannot do much testing here for
+ ;; `:unix-fd' being an argument (which is an index to the file
+ ;; descriptor in the array of file descriptors that accompany the
+ ;; D-Bus message). Mainly testing, that values out of `:uint32'
+ ;; type range fail.
+ (should (dbus-check-arguments :session dbus--test-service :unix-fd 0))
+ (should-error
+ (dbus-check-arguments :session dbus--test-service :unix-fd)
+ :type 'wrong-type-argument)
+ (should-error
+ (dbus-check-arguments :session dbus--test-service :unix-fd -1)
+ :type 'args-out-of-range)
+ (should-error
+ (dbus-check-arguments :session dbus--test-service :unix-fd 0.5)
+ :type 'args-out-of-range)
+ (should-error
+ (dbus-check-arguments :session dbus--test-service :unix-fd "string")
+ :type 'wrong-type-argument))
+
+(ert-deftest dbus-test01-compound-types ()
+ "Check basic D-Bus type arguments."
+ (skip-unless dbus--test-enabled-session-bus)
+
+ ;; `:array'. It contains several elements of the same type.
+ (should (dbus-check-arguments :session dbus--test-service '("string")))
+ (should (dbus-check-arguments :session dbus--test-service '(:array "string")))
+ (should
+ (dbus-check-arguments :session dbus--test-service '(:array :string "string")))
+ (should
+ (dbus-check-arguments
+ :session dbus--test-service '(:array :string "string1" "string2")))
+ (should
+ (dbus-check-arguments
+ :session dbus--test-service '(:array :signature "s" :signature "ao")))
+ ;; Empty array (of strings).
+ (should (dbus-check-arguments :session dbus--test-service '(:array)))
+ ;; Empty array (of object paths).
+ (should
+ (dbus-check-arguments :session dbus--test-service '(:array :signature "o")))
+ ;; Different element types.
+ (should-error
+ (dbus-check-arguments
+ :session dbus--test-service
+ '(:array :string "string" :object-path "/object/path"))
+ :type 'wrong-type-argument)
+ ;; Different variant types in array don't matter.
+ (should
+ (dbus-check-arguments
+ :session dbus--test-service
+ '(:array
+ (:variant :string "string1")
+ (:variant (:struct :string "string2" :object-path "/object/path")))))
+
+ ;; `:variant'. It contains exactly one element.
+ (should
+ (dbus-check-arguments
+ :session dbus--test-service '(:variant :string "string")))
+ (should
+ (dbus-check-arguments
+ :session dbus--test-service '(:variant (:array "string"))))
+ ;; Empty variant.
+ (should-error
+ (dbus-check-arguments :session dbus--test-service '(:variant))
+ :type 'wrong-type-argument)
+ ;; More than one element.
+ (should-error
+ (dbus-check-arguments
+ :session dbus--test-service
+ '(:variant :string "string" :object-path "/object/path"))
+ :type 'wrong-type-argument)
+
+ ;; `:dict-entry'. It must contain two elements; the first one must
+ ;; be of a basic type. It must be an element of an array.
+ (should
+ (dbus-check-arguments
+ :session dbus--test-service
+ '(:array (:dict-entry :string "string" :boolean nil))))
+ ;; This is an alternative syntax.
+ (should
+ (dbus-check-arguments
+ :session dbus--test-service
+ '(:array :dict-entry (:string "string" :boolean t))))
+ ;; Empty dict-entry.
+ (should-error
+ (dbus-check-arguments
+ :session dbus--test-service '(:array (:dict-entry)))
+ :type 'wrong-type-argument)
+ ;; One element.
+ (should-error
+ (dbus-check-arguments
+ :session dbus--test-service '(:array (:dict-entry :string "string")))
+ :type 'wrong-type-argument)
+ (should-error
+ (dbus-check-arguments
+ :session dbus--test-service
+ '(:array (:dict-entry :string "string" :boolean t :boolean t)))
+ :type 'wrong-type-argument)
+ ;; The first element ist not of a basic type.
+ (should-error
+ (dbus-check-arguments
+ :session dbus--test-service
+ '(:array (:dict-entry (:array :string "string") :boolean t)))
+ :type 'wrong-type-argument)
+ ;; It is not an element of an array.
+ (should-error
+ (dbus-check-arguments
+ :session dbus--test-service '(:dict-entry :string "string" :boolean t))
+ :type 'wrong-type-argument)
+ ;; Different dict entry types in array.
+ (should-error
+ (dbus-check-arguments
+ :session dbus--test-service
+ '(:array
+ (:dict-entry :string "string1" :boolean t)
+ (:dict-entry :string "string2" :object-path "/object/path")))
+ :type 'wrong-type-argument)
+
+ ;; `:struct'. There is no restriction what could be an element of a struct.
+ (should
+ (dbus-check-arguments
+ :session dbus--test-service
+ '(:struct
+ :string "string"
+ :object-path "/object/path"
+ (:variant (:array :unix-fd 1 :unix-fd 2 :unix-fd 3 :unix-fd 4)))))
+ ;; Empty struct.
+ (should-error
+ (dbus-check-arguments :session dbus--test-service '(:struct))
+ :type 'wrong-type-argument)
+ ;; Different struct types in array.
+ (should-error
+ (dbus-check-arguments
+ :session dbus--test-service
+ '(:array
+ (:struct :string "string1" :boolean t)
+ (:struct :object-path "/object/path")))
+ :type 'wrong-type-argument))
+
(defun dbus--test-register-service (bus)
"Check service registration at BUS."
;; Cleanup.
- (dbus-ignore-errors (dbus-unregister-service bus dbus-service-emacs))
+ (dbus-ignore-errors (dbus-unregister-service bus dbus--test-service))
;; Register an own service.
- (should (eq (dbus-register-service bus dbus-service-emacs) :primary-owner))
- (should (member dbus-service-emacs (dbus-list-known-names bus)))
- (should (eq (dbus-register-service bus dbus-service-emacs) :already-owner))
- (should (member dbus-service-emacs (dbus-list-known-names bus)))
+ (should (eq (dbus-register-service bus dbus--test-service) :primary-owner))
+ (should (member dbus--test-service (dbus-list-known-names bus)))
+ (should (eq (dbus-register-service bus dbus--test-service) :already-owner))
+ (should (member dbus--test-service (dbus-list-known-names bus)))
;; Unregister the service.
- (should (eq (dbus-unregister-service bus dbus-service-emacs) :released))
- (should-not (member dbus-service-emacs (dbus-list-known-names bus)))
- (should (eq (dbus-unregister-service bus dbus-service-emacs) :non-existent))
- (should-not (member dbus-service-emacs (dbus-list-known-names bus)))
+ (should (eq (dbus-unregister-service bus dbus--test-service) :released))
+ (should-not (member dbus--test-service (dbus-list-known-names bus)))
+ (should (eq (dbus-unregister-service bus dbus--test-service) :non-existent))
+ (should-not (member dbus--test-service (dbus-list-known-names bus)))
+
+ ;; A service name is a string, constructed of at least two words
+ ;; separated by ".".
+ (should
+ (equal
+ (butlast
+ (should-error (dbus-register-service bus "s")))
+ `(dbus-error ,dbus-error-invalid-args)))
;; `dbus-service-dbus' is reserved for the BUS itself.
- (should-error (dbus-register-service bus dbus-service-dbus))
- (should-error (dbus-unregister-service bus dbus-service-dbus)))
+ (should
+ (equal
+ (butlast
+ (should-error (dbus-register-service bus dbus-service-dbus)))
+ `(dbus-error ,dbus-error-invalid-args)))
+ (should
+ (equal
+ (butlast
+ (should-error (dbus-unregister-service bus dbus-service-dbus)))
+ `(dbus-error ,dbus-error-invalid-args))))
(ert-deftest dbus-test02-register-service-session ()
"Check service registration at `:session' bus."
(skip-unless (and dbus--test-enabled-session-bus
- (dbus-register-service :session dbus-service-emacs)))
+ (dbus-register-service :session dbus--test-service)))
(dbus--test-register-service :session)
(let ((service "org.freedesktop.Notifications"))
@@ -124,7 +506,7 @@
(ert-deftest dbus-test02-register-service-system ()
"Check service registration at `:system' bus."
(skip-unless (and dbus--test-enabled-system-bus
- (dbus-register-service :system dbus-service-emacs)))
+ (dbus-register-service :system dbus--test-service)))
(dbus--test-register-service :system))
(ert-deftest dbus-test02-register-service-own-bus ()
@@ -133,7 +515,7 @@ This includes initialization and closing the bus."
;; Start bus.
(let ((output
(ignore-errors
- (shell-command-to-string "dbus-launch --sh-syntax")))
+ (shell-command-to-string "env DISPLAY= dbus-launch --sh-syntax")))
bus pid)
(skip-unless (stringp output))
(when (string-match "DBUS_SESSION_BUS_ADDRESS='\\(.+\\)';" output)
@@ -148,7 +530,7 @@ This includes initialization and closing the bus."
(featurep 'dbusbind)
(dbus-init-bus bus)
(dbus-get-unique-name bus)
- (dbus-register-service bus dbus-service-emacs))))
+ (dbus-register-service bus dbus--test-service))))
;; Run the test.
(dbus--test-register-service bus))
@@ -159,25 +541,1475 @@ This includes initialization and closing the bus."
"Check `dbus-interface-peer' methods."
(skip-unless
(and dbus--test-enabled-session-bus
- (dbus-register-service :session dbus-service-emacs)
+ (dbus-register-service :session dbus--test-service)
;; "GetMachineId" is not implemented (yet). When it returns a
;; value, another D-Bus client like dbus-monitor is reacting
;; on `dbus-interface-peer'. We cannot test then.
(not
(dbus-ignore-errors
(dbus-call-method
- :session dbus-service-emacs dbus-path-dbus
+ :session dbus--test-service dbus-path-dbus
dbus-interface-peer "GetMachineId" :timeout 100)))))
- (should (dbus-ping :session dbus-service-emacs 100))
- (dbus-unregister-service :session dbus-service-emacs)
- (should-not (dbus-ping :session dbus-service-emacs 100)))
+ (should (dbus-ping :session dbus--test-service 100))
+ (dbus-unregister-service :session dbus--test-service)
+ (should-not (dbus-ping :session dbus--test-service 100)))
+
+(defun dbus--test-method-handler (&rest args)
+ "Method handler for `dbus-test04-register-method'."
+ (cond
+ ;; No argument.
+ ((null args)
+ :ignore)
+ ;; One argument.
+ ((= 1 (length args))
+ (car args))
+ ;; Two arguments.
+ ((= 2 (length args))
+ `(:error ,dbus-error-invalid-args
+ ,(format-message "Wrong arguments %s" args)))
+ ;; More than two arguments.
+ (t (signal 'dbus-error (cons "D-Bus signal" args)))))
+
+(ert-deftest dbus-test04-register-method ()
+ "Check method registration for an own service."
+ (skip-unless dbus--test-enabled-session-bus)
+ (dbus-ignore-errors (dbus-unregister-service :session dbus--test-service))
+
+ (unwind-protect
+ (let ((method1 "Method1")
+ (method2 "Method2")
+ (handler #'dbus--test-method-handler)
+ registered)
+
+ ;; The service is not registered yet.
+ (should
+ (equal
+ (butlast
+ (should-error
+ (dbus-call-method
+ :session dbus--test-service dbus--test-path
+ dbus--test-interface method1 :timeout 10 "foo")))
+ `(dbus-error ,dbus-error-service-unknown)))
+
+ ;; Register.
+ (should
+ (equal
+ (setq
+ registered
+ (dbus-register-method
+ :session dbus--test-service dbus--test-path
+ dbus--test-interface method1 handler))
+ `((:method :session ,dbus--test-interface ,method1)
+ (,dbus--test-service ,dbus--test-path ,handler))))
+ (should
+ (equal
+ (dbus-register-method
+ :session dbus--test-service dbus--test-path
+ dbus--test-interface method2 handler)
+ `((:method :session ,dbus--test-interface ,method2)
+ (,dbus--test-service ,dbus--test-path ,handler))))
+
+ ;; No argument, returns nil.
+ (should-not
+ (dbus-call-method
+ :session dbus--test-service dbus--test-path
+ dbus--test-interface method1))
+ ;; One argument, returns the argument.
+ (should
+ (string-equal
+ (dbus-call-method
+ :session dbus--test-service dbus--test-path
+ dbus--test-interface method1 "foo")
+ "foo"))
+ ;; Two arguments, D-Bus error activated as `(:error ...)' list.
+ (should
+ (equal
+ (should-error
+ (dbus-call-method
+ :session dbus--test-service dbus--test-path
+ dbus--test-interface method1 "foo" "bar"))
+ `(dbus-error ,dbus-error-invalid-args "Wrong arguments (foo bar)")))
+ ;; Three arguments, D-Bus error activated by `dbus-error'
+ ;; signal. On CentOS, it is not guaranteed which format the
+ ;; error message arises. (Bug#51369)
+ (should
+ (member
+ (should-error
+ (dbus-call-method
+ :session dbus--test-service dbus--test-path
+ dbus--test-interface method1 "foo" "bar" "baz"))
+ `((dbus-error "D-Bus signal" "foo" "bar" "baz")
+ (dbus-error
+ ,dbus-error-failed
+ "D-Bus error: \"D-Bus signal\", \"foo\", \"bar\", \"baz\""))))
+
+ ;; Unregister method.
+ (should (dbus-unregister-object registered))
+ (should-not (dbus-unregister-object registered))
+ (should
+ (equal
+ (butlast
+ (should-error
+ (dbus-call-method
+ :session dbus--test-service dbus--test-path
+ dbus--test-interface method1 :timeout 10 "foo")))
+ `(dbus-error ,dbus-error-no-reply))))
+
+ ;; Cleanup.
+ (dbus-unregister-service :session dbus--test-service)))
+
+(defun dbus--test-method-reentry-handler (&rest _args)
+ "Method handler for `dbus-test04-method-reentry'."
+ (dbus-get-all-managed-objects :session dbus--test-service dbus--test-path)
+ 42)
+
+(ert-deftest dbus-test04-method-reentry ()
+ "Check receiving method call while awaiting response.
+Ensure that incoming method calls are handled when call to `dbus-call-method'
+is in progress."
+ :tags '(:expensive-test)
+ ;; Simulate application registration. (Bug#43251)
+ (skip-unless dbus--test-enabled-session-bus)
+ (dbus-ignore-errors (dbus-unregister-service :session dbus--test-service))
+
+ (unwind-protect
+ (let ((method "Reentry"))
+ (should
+ (equal
+ (dbus-register-method
+ :session dbus--test-service dbus--test-path
+ dbus--test-interface method #'dbus--test-method-reentry-handler)
+ `((:method :session ,dbus--test-interface ,method)
+ (,dbus--test-service ,dbus--test-path
+ dbus--test-method-reentry-handler))))
+
+ (should
+ (=
+ (dbus-call-method
+ :session dbus--test-service dbus--test-path
+ dbus--test-interface method)
+ 42)))
+
+ ;; Cleanup.
+ (dbus-unregister-service :session dbus--test-service)))
+
+(ert-deftest dbus-test04-call-method-timeout ()
+ "Verify `dbus-call-method' request timeout."
+ :tags '(:expensive-test)
+ (skip-unless dbus--test-enabled-session-bus)
+ (dbus-ignore-errors (dbus-unregister-service :session dbus--test-service))
+ (dbus-register-service :session dbus--test-service)
+
+ (unwind-protect
+ (let ((start (current-time)))
+ ;; Test timeout override for method call.
+ (should-error
+ (dbus-call-method
+ :session dbus--test-service dbus--test-path
+ dbus-interface-introspectable "Introspect" :timeout 2500)
+ :type 'dbus-error)
+
+ (should
+ (< 2.4 (float-time (time-since start)) 2.7)))
+
+ ;; Cleanup.
+ (dbus-unregister-service :session dbus--test-service)))
+
+(defvar dbus--test-signal-received nil
+ "Received signal value in `dbus--test-signal-handler'.")
+
+(defun dbus--test-signal-handler (&rest args)
+ "Signal handler for `dbus-test*-signal' and `dbus-test08-register-monitor'."
+ (setq dbus--test-signal-received args))
+
+(defun dbus--test-timeout-handler (&rest _ignore)
+ "Timeout handler, reporting a failed test."
+ (ert-fail (format "`%s' timed out" (ert-test-name (ert-running-test)))))
+
+(ert-deftest dbus-test05-register-signal ()
+ "Check signal registration for an own service."
+ (skip-unless dbus--test-enabled-session-bus)
+ (dbus-ignore-errors (dbus-unregister-service :session dbus--test-service))
+
+ (unwind-protect
+ (let ((member "Member")
+ (handler #'dbus--test-signal-handler)
+ registered)
+
+ ;; Register signal handler.
+ (should
+ (equal
+ (setq
+ registered
+ (dbus-register-signal
+ :session dbus--test-service dbus--test-path
+ dbus--test-interface member handler))
+ `((:signal :session ,dbus--test-interface ,member)
+ (,dbus--test-service ,dbus--test-path ,handler))))
+
+ ;; Send one argument, basic type.
+ (setq dbus--test-signal-received nil)
+ (dbus-send-signal
+ :session dbus--test-service dbus--test-path
+ dbus--test-interface member "foo")
+ (with-timeout (1 (dbus--test-timeout-handler))
+ (while (null dbus--test-signal-received)
+ (read-event nil nil 0.1)))
+ (should (equal dbus--test-signal-received '("foo")))
+
+ ;; Send two arguments, compound types.
+ (setq dbus--test-signal-received nil)
+ (dbus-send-signal
+ :session dbus--test-service dbus--test-path
+ dbus--test-interface member
+ '(:array :byte 1 :byte 2 :byte 3) '(:variant :string "bar"))
+ (with-timeout (1 (dbus--test-timeout-handler))
+ (while (null dbus--test-signal-received)
+ (read-event nil nil 0.1)))
+ (should (equal dbus--test-signal-received '((1 2 3) ("bar"))))
+
+ ;; Unregister signal.
+ (should (dbus-unregister-object registered))
+ (should-not (dbus-unregister-object registered)))
+
+ ;; Cleanup.
+ (dbus-unregister-service :session dbus--test-service)))
+
+(ert-deftest dbus-test06-register-property ()
+ "Check property registration for an own service."
+ (skip-unless dbus--test-enabled-session-bus)
+ (dbus-ignore-errors (dbus-unregister-service :session dbus--test-service))
+
+ (unwind-protect
+ (let ((property1 "Property1")
+ (property2 "Property2")
+ (property3 "Property3")
+ (property4 "Property4")
+ registered)
+
+ ;; `:read' property.
+ (should
+ (equal
+ (setq
+ registered
+ (dbus-register-property
+ :session dbus--test-service dbus--test-path
+ dbus--test-interface property1 :read "foo"))
+ `((:property :session ,dbus--test-interface ,property1)
+ (,dbus--test-service ,dbus--test-path))))
+ (should
+ (string-equal
+ (dbus-get-property
+ :session dbus--test-service dbus--test-path
+ dbus--test-interface property1)
+ "foo"))
+ ;; Due to `:read' access type, we don't get a proper reply
+ ;; from `dbus-set-property'.
+ (should
+ (equal
+ (butlast
+ (should-error
+ (dbus-set-property
+ :session dbus--test-service dbus--test-path
+ dbus--test-interface property1 "foofoo")))
+ `(dbus-error ,dbus-error-property-read-only)))
+ (should
+ (string-equal
+ (dbus-get-property
+ :session dbus--test-service dbus--test-path
+ dbus--test-interface property1)
+ "foo"))
+
+ ;; `:write' property.
+ (should
+ (equal
+ (dbus-register-property
+ :session dbus--test-service dbus--test-path
+ dbus--test-interface property2 :write "bar")
+ `((:property :session ,dbus--test-interface ,property2)
+ (,dbus--test-service ,dbus--test-path))))
+ ;; Due to `:write' access type, we don't get a proper reply
+ ;; from `dbus-get-property'.
+ (should
+ (equal
+ (butlast
+ (should-error
+ (dbus-get-property
+ :session dbus--test-service dbus--test-path
+ dbus--test-interface property2)))
+ `(dbus-error ,dbus-error-access-denied)))
+ (should
+ (string-equal
+ (dbus-set-property
+ :session dbus--test-service dbus--test-path
+ dbus--test-interface property2 "barbar")
+ "barbar"))
+ ;; Still `:write' access type.
+ (should
+ (equal
+ (butlast
+ (should-error
+ (dbus-get-property
+ :session dbus--test-service dbus--test-path
+ dbus--test-interface property2)))
+ `(dbus-error ,dbus-error-access-denied)))
+
+ ;; `:readwrite' property, typed value (Bug#43252).
+ (should
+ (equal
+ (dbus-register-property
+ :session dbus--test-service dbus--test-path
+ dbus--test-interface property3 :readwrite :object-path "/baz")
+ `((:property :session ,dbus--test-interface ,property3)
+ (,dbus--test-service ,dbus--test-path))))
+ (should
+ (string-equal
+ (dbus-get-property
+ :session dbus--test-service dbus--test-path
+ dbus--test-interface property3)
+ "/baz"))
+ (should
+ (string-equal
+ (dbus-set-property
+ :session dbus--test-service dbus--test-path
+ dbus--test-interface property3 :object-path "/baz/baz")
+ "/baz/baz"))
+ (should
+ (string-equal
+ (dbus-get-property
+ :session dbus--test-service dbus--test-path
+ dbus--test-interface property3)
+ "/baz/baz"))
+
+ ;; Not registered property.
+ (should
+ (equal
+ (butlast
+ (should-error
+ (dbus-get-property
+ :session dbus--test-service dbus--test-path
+ dbus--test-interface property4)))
+ `(dbus-error ,dbus-error-unknown-property)))
+ (should
+ (equal
+ (butlast
+ (should-error
+ (dbus-set-property
+ :session dbus--test-service dbus--test-path
+ dbus--test-interface property4 "foobarbaz")))
+ `(dbus-error ,dbus-error-unknown-property)))
+
+ ;; `dbus-get-all-properties'. We cannot retrieve a value for
+ ;; the property with `:write' access type.
+ (let ((result
+ (dbus-get-all-properties
+ :session dbus--test-service dbus--test-path
+ dbus--test-interface)))
+ (should (string-equal (cdr (assoc property1 result)) "foo"))
+ (should (string-equal (cdr (assoc property3 result)) "/baz/baz"))
+ (should-not (assoc property2 result)))
+
+ ;; `dbus-get-all-managed-objects'. We cannot retrieve a value for
+ ;; the property with `:write' access type.
+ (let ((result
+ (dbus-get-all-managed-objects
+ :session dbus--test-service dbus--test-path)))
+ (should (setq result (cadr (assoc dbus--test-path result))))
+ (should (setq result (cadr (assoc dbus--test-interface result))))
+ (should (string-equal (cdr (assoc property1 result)) "foo"))
+ (should (string-equal (cdr (assoc property3 result)) "/baz/baz"))
+ (should-not (assoc property2 result)))
+
+ ;; Unregister property.
+ (should (dbus-unregister-object registered))
+ (should-not (dbus-unregister-object registered))
+ (should
+ (equal
+ (butlast
+ (should-error
+ (dbus-get-property
+ :session dbus--test-service dbus--test-path
+ dbus--test-interface property1)))
+ `(dbus-error ,dbus-error-unknown-property))))
+
+ ;; Cleanup.
+ (dbus-unregister-service :session dbus--test-service)))
+
+;; The following test is inspired by Bug#43146.
+(ert-deftest dbus-test06-register-property-several-paths ()
+ "Check property registration for an own service at several paths."
+ (skip-unless dbus--test-enabled-session-bus)
+ (dbus-ignore-errors (dbus-unregister-service :session dbus--test-service))
+
+ (unwind-protect
+ (let ((property1 "Property1")
+ (property2 "Property2")
+ (property3 "Property3"))
+
+ ;; First path.
+ (should
+ (equal
+ (dbus-register-property
+ :session dbus--test-service dbus--test-path
+ dbus--test-interface property1 :readwrite "foo")
+ `((:property :session ,dbus--test-interface ,property1)
+ (,dbus--test-service ,dbus--test-path))))
+ (should
+ (equal
+ (dbus-register-property
+ :session dbus--test-service dbus--test-path
+ dbus--test-interface property2 :readwrite "bar")
+ `((:property :session ,dbus--test-interface ,property2)
+ (,dbus--test-service ,dbus--test-path))))
+ (should
+ (string-equal
+ (dbus-get-property
+ :session dbus--test-service dbus--test-path
+ dbus--test-interface property1)
+ "foo"))
+ (should
+ (string-equal
+ (dbus-get-property
+ :session dbus--test-service dbus--test-path
+ dbus--test-interface property2)
+ "bar"))
+
+ (should
+ (string-equal
+ (dbus-set-property
+ :session dbus--test-service dbus--test-path
+ dbus--test-interface property1 "foofoo")
+ "foofoo"))
+ (should
+ (string-equal
+ (dbus-set-property
+ :session dbus--test-service dbus--test-path
+ dbus--test-interface property2 "barbar")
+ "barbar"))
+ (should
+ (string-equal
+ (dbus-get-property
+ :session dbus--test-service dbus--test-path
+ dbus--test-interface property1)
+ "foofoo"))
+ (should
+ (string-equal
+ (dbus-get-property
+ :session dbus--test-service dbus--test-path
+ dbus--test-interface property2)
+ "barbar"))
+
+ ;; Second path.
+ (should
+ (equal
+ (dbus-register-property
+ :session dbus--test-service (concat dbus--test-path dbus--test-path)
+ dbus--test-interface property2 :readwrite "foo")
+ `((:property :session ,dbus--test-interface ,property2)
+ (,dbus--test-service ,(concat dbus--test-path dbus--test-path)))))
+ (should
+ (equal
+ (dbus-register-property
+ :session dbus--test-service (concat dbus--test-path dbus--test-path)
+ dbus--test-interface property3 :readwrite "bar")
+ `((:property :session ,dbus--test-interface ,property3)
+ (,dbus--test-service ,(concat dbus--test-path dbus--test-path)))))
+ (should
+ (string-equal
+ (dbus-get-property
+ :session dbus--test-service (concat dbus--test-path dbus--test-path)
+ dbus--test-interface property2)
+ "foo"))
+ (should
+ (string-equal
+ (dbus-get-property
+ :session dbus--test-service (concat dbus--test-path dbus--test-path)
+ dbus--test-interface property3)
+ "bar"))
+
+ (should
+ (string-equal
+ (dbus-set-property
+ :session dbus--test-service (concat dbus--test-path dbus--test-path)
+ dbus--test-interface property2 "foofoo")
+ "foofoo"))
+ (should
+ (string-equal
+ (dbus-set-property
+ :session dbus--test-service (concat dbus--test-path dbus--test-path)
+ dbus--test-interface property3 "barbar")
+ "barbar"))
+ (should
+ (string-equal
+ (dbus-get-property
+ :session dbus--test-service (concat dbus--test-path dbus--test-path)
+ dbus--test-interface property2)
+ "foofoo"))
+ (should
+ (string-equal
+ (dbus-get-property
+ :session dbus--test-service (concat dbus--test-path dbus--test-path)
+ dbus--test-interface property3)
+ "barbar"))
+
+ ;; Everything is still fine, tested with `dbus-get-all-properties'.
+ (let ((result
+ (dbus-get-all-properties
+ :session dbus--test-service dbus--test-path
+ dbus--test-interface)))
+ (should (string-equal (cdr (assoc property1 result)) "foofoo"))
+ (should (string-equal (cdr (assoc property2 result)) "barbar"))
+ (should-not (assoc property3 result)))
+
+ (let ((result
+ (dbus-get-all-properties
+ :session dbus--test-service
+ (concat dbus--test-path dbus--test-path) dbus--test-interface)))
+ (should (string-equal (cdr (assoc property2 result)) "foofoo"))
+ (should (string-equal (cdr (assoc property3 result)) "barbar"))
+ (should-not (assoc property1 result)))
+
+ ;; Final check with `dbus-get-all-managed-objects'.
+ (let ((result
+ (dbus-get-all-managed-objects :session dbus--test-service "/"))
+ result1)
+ (should (setq result1 (cadr (assoc dbus--test-path result))))
+ (should (setq result1 (cadr (assoc dbus--test-interface result1))))
+ (should (string-equal (cdr (assoc property1 result1)) "foofoo"))
+ (should (string-equal (cdr (assoc property2 result1)) "barbar"))
+ (should-not (assoc property3 result1))
+
+ (should
+ (setq
+ result1
+ (cadr (assoc (concat dbus--test-path dbus--test-path) result))))
+ (should (setq result1 (cadr (assoc dbus--test-interface result1))))
+ (should (string-equal (cdr (assoc property2 result1)) "foofoo"))
+ (should (string-equal (cdr (assoc property3 result1)) "barbar"))
+ (should-not (assoc property1 result1))))
+
+ ;; Cleanup.
+ (dbus-unregister-service :session dbus--test-service)))
+
+(ert-deftest dbus-test06-register-property-emits-signal ()
+ "Check property registration for an own service, including signalling."
+ (skip-unless dbus--test-enabled-session-bus)
+ (dbus-ignore-errors (dbus-unregister-service :session dbus--test-service))
+
+ (unwind-protect
+ (let ((property "Property")
+ (handler #'dbus--test-signal-handler))
+
+ ;; Register signal handler.
+ (should
+ (equal
+ (dbus-register-signal
+ :session dbus--test-service dbus--test-path
+ dbus-interface-properties "PropertiesChanged" handler)
+ `((:signal :session ,dbus-interface-properties "PropertiesChanged")
+ (,dbus--test-service ,dbus--test-path ,handler))))
+
+ ;; Register property.
+ (setq dbus--test-signal-received nil)
+ (should
+ (equal
+ (dbus-register-property
+ :session dbus--test-service dbus--test-path
+ dbus--test-interface property :readwrite "foo" 'emits-signal)
+ `((:property :session ,dbus--test-interface ,property)
+ (,dbus--test-service ,dbus--test-path))))
+ (with-timeout (1 (dbus--test-timeout-handler))
+ (while (null dbus--test-signal-received)
+ (read-event nil nil 0.1)))
+ ;; It returns three arguments, "interface" (a string),
+ ;; "changed_properties" (an array of dict entries) and
+ ;; "invalidated_properties" (an array of strings).
+ (should
+ (equal dbus--test-signal-received
+ `(,dbus--test-interface ((,property ("foo"))) ())))
+
+ (should
+ (equal
+ (dbus-get-property
+ :session dbus--test-service dbus--test-path
+ dbus--test-interface property)
+ "foo"))
+
+ ;; Set property. The new value shall be signalled.
+ (setq dbus--test-signal-received nil)
+ (should
+ (equal
+ (dbus-set-property
+ :session dbus--test-service dbus--test-path
+ dbus--test-interface property
+ '(:array :byte 1 :byte 2 :byte 3))
+ '(1 2 3)))
+ (with-timeout (1 (dbus--test-timeout-handler))
+ (while (null dbus--test-signal-received)
+ (read-event nil nil 0.1)))
+ (should
+ (equal
+ dbus--test-signal-received
+ `(,dbus--test-interface ((,property ((1 2 3)))) ())))
+
+ (should
+ (equal
+ (dbus-get-property
+ :session dbus--test-service dbus--test-path
+ dbus--test-interface property)
+ '(1 2 3))))
+
+ ;; Cleanup.
+ (dbus-unregister-service :session dbus--test-service)))
+
+(defsubst dbus--test-run-property-test (selector name value expected)
+ "Generate a property test: register, set, get, getall sequence.
+This is a helper function for the macro `dbus--test-property'.
+The argument SELECTOR indicates whether the test should expand to
+`dbus-register-property' (if SELECTOR is `register') or
+`dbus-set-property' (if SELECTOR is `set').
+The argument NAME is the property name.
+The argument VALUE is the value to register or set.
+The argument EXPECTED is a transformed VALUE representing the
+form `dbus-get-property' should return."
+ (cond
+ ((eq selector 'register)
+ (should
+ (equal
+ (dbus-register-property
+ :session dbus--test-service dbus--test-path dbus--test-interface name
+ :readwrite value)
+ `((:property :session ,dbus--test-interface ,name)
+ (,dbus--test-service ,dbus--test-path)))))
+
+ ((eq selector 'set)
+ (should
+ (equal
+ (dbus-set-property
+ :session dbus--test-service dbus--test-path dbus--test-interface name
+ value)
+ expected)))
+
+ (t (signal 'wrong-type-argument "Selector should be 'register or 'set.")))
+
+ (should
+ (equal
+ (dbus-get-property
+ :session dbus--test-service dbus--test-path dbus--test-interface name)
+ expected))
+
+ (let ((result
+ (dbus-get-all-properties
+ :session dbus--test-service dbus--test-path dbus--test-interface)))
+ (should (equal (cdr (assoc name result)) expected)))
+
+ (let ((result
+ (dbus-get-all-managed-objects :session dbus--test-service "/"))
+ result1)
+ (should (setq result1 (cadr (assoc dbus--test-path result))))
+ (should (setq result1 (cadr (assoc dbus--test-interface result1))))
+ (should (equal (cdr (assoc name result1)) expected))))
+
+(defsubst dbus--test-property (name &rest value-list)
+ "Test a D-Bus property named by string argument NAME.
+The argument VALUE-LIST is a sequence of pairs, where each pair
+represents a value form and an expected returned value form. The
+first pair in VALUES is used for `dbus-register-property'.
+Subsequent pairs of the list are tested with `dbus-set-property'."
+ (let ((values (car value-list)))
+ (dbus--test-run-property-test
+ 'register name (car values) (cdr values)))
+ (dolist (values (cdr value-list))
+ (dbus--test-run-property-test
+ 'set name (car values) (cdr values))))
+
+(ert-deftest dbus-test06-property-types ()
+ "Check property access and mutation for an own service."
+ (skip-unless dbus--test-enabled-session-bus)
+ (dbus-ignore-errors (dbus-unregister-service :session dbus--test-service))
+ (dbus-register-service :session dbus--test-service)
+
+ (unwind-protect
+ (progn
+ (dbus--test-property
+ "ByteArray"
+ '((:array :byte 1 :byte 2 :byte 3) . (1 2 3))
+ '((:array :byte 4 :byte 5 :byte 6) . (4 5 6)))
+
+ (dbus--test-property
+ "StringArray"
+ '((:array "one" "two" :string "three") . ("one" "two" "three"))
+ '((:array :string "four" :string "five" "six") . ("four" "five" "six")))
+
+ (dbus--test-property
+ "ObjectArray"
+ '((:array
+ :object-path "/node00"
+ :object-path "/node01"
+ :object-path "/node0/node02")
+ . ("/node00" "/node01" "/node0/node02"))
+ '((:array
+ :object-path "/node10"
+ :object-path "/node11"
+ :object-path "/node0/node12")
+ . ("/node10" "/node11" "/node0/node12")))
+
+ (dbus--test-property
+ "Dictionary"
+ '((:array
+ :dict-entry (:string "four" (:variant :string "value of four"))
+ :dict-entry ("five" (:variant :object-path "/node0"))
+ :dict-entry ("six" (:variant (:array :byte 4 :byte 5 :byte 6))))
+ . (("four"
+ ("value of four"))
+ ("five"
+ ("/node0"))
+ ("six"
+ ((4 5 6)))))
+ '((:array
+ :dict-entry
+ (:string "key0" (:variant (:array :byte 7 :byte 8 :byte 9)))
+ :dict-entry ("key1" (:variant :string "value"))
+ :dict-entry ("key2" (:variant :object-path "/node0/node1")))
+ . (("key0"
+ ((7 8 9)))
+ ("key1"
+ ("value"))
+ ("key2"
+ ("/node0/node1")))))
+
+ (dbus--test-property ; Syntax emphasizing :dict compound type.
+ "Dictionary"
+ '((:array
+ (:dict-entry :string "seven" (:variant :string "value of seven"))
+ (:dict-entry "eight" (:variant :object-path "/node8"))
+ (:dict-entry "nine" (:variant (:array :byte 9 :byte 27 :byte 81))))
+ . (("seven"
+ ("value of seven"))
+ ("eight"
+ ("/node8"))
+ ("nine"
+ ((9 27 81)))))
+ '((:array
+ (:dict-entry
+ :string "key4" (:variant (:array :byte 7 :byte 49 :byte 125)))
+ (:dict-entry "key5" (:variant :string "obsolete"))
+ (:dict-entry "key6" (:variant :object-path "/node6/node7")))
+ . (("key4"
+ ((7 49 125)))
+ ("key5"
+ ("obsolete"))
+ ("key6"
+ ("/node6/node7")))))
+
+ (dbus--test-property
+ "ByteDictionary"
+ '((:array
+ (:dict-entry :byte 8 (:variant :string "byte-eight"))
+ (:dict-entry :byte 16 (:variant :object-path "/byte/sixteen"))
+ (:dict-entry :byte 48 (:variant (:array :byte 8 :byte 9 :byte 10))))
+ . (( 8 ("byte-eight"))
+ (16 ("/byte/sixteen"))
+ (48 ((8 9 10))))))
+
+ (dbus--test-property
+ "Variant"
+ '((:variant "Variant string") . ("Variant string"))
+ '((:variant :byte 42) . (42))
+ '((:variant :uint32 1000000) . (1000000))
+ '((:variant :object-path "/variant/path") . ("/variant/path"))
+ '((:variant :signature "a{sa{sv}}") . ("a{sa{sv}}"))
+ '((:variant
+ (:struct
+ 42 "string" (:object-path "/structure/path") (:variant "last")))
+ . ((42 "string" ("/structure/path") ("last")))))
+
+ ;; Test that :read prevents writes.
+ (should
+ (equal
+ (dbus-register-property
+ :session dbus--test-service dbus--test-path dbus--test-interface
+ "StringArray" :read '(:array "one" "two" :string "three"))
+ `((:property :session ,dbus--test-interface "StringArray")
+ (,dbus--test-service ,dbus--test-path))))
+
+ (should-error ; Cannot set property with :read access.
+ (dbus-set-property
+ :session dbus--test-service dbus--test-path dbus--test-interface
+ "StringArray" '(:array "seven" "eight" :string "nine"))
+ :type 'dbus-error)
+
+ (should ; Property value preserved on error.
+ (equal
+ (dbus-get-property
+ :session dbus--test-service dbus--test-path dbus--test-interface
+ "StringArray")
+ '("one" "two" "three")))
+
+ ;; Test mismatched types in array.
+ (should-error
+ (dbus-register-property
+ :session dbus--test-service dbus--test-path dbus--test-interface
+ "MixedArray" :readwrite
+ '(:array
+ :object-path "/node00"
+ :string "/node01"
+ :object-path "/node0/node02"))
+ :type 'wrong-type-argument)
+
+ ;; Test in-range integer values.
+ (should
+ (equal
+ (dbus-register-property
+ :session dbus--test-service dbus--test-path dbus--test-interface
+ "ByteValue" :readwrite :byte 255)
+ `((:property :session ,dbus--test-interface "ByteValue")
+ (,dbus--test-service ,dbus--test-path))))
+
+ (should
+ (=
+ (dbus-get-property
+ :session dbus--test-service dbus--test-path dbus--test-interface
+ "ByteValue")
+ 255))
+
+ (should
+ (equal
+ (dbus-register-property
+ :session dbus--test-service dbus--test-path dbus--test-interface
+ "ShortValue" :readwrite :int16 32767)
+ `((:property :session ,dbus--test-interface "ShortValue")
+ (,dbus--test-service ,dbus--test-path))))
+
+ (should
+ (=
+ (dbus-get-property
+ :session dbus--test-service dbus--test-path dbus--test-interface
+ "ShortValue")
+ 32767))
+
+ (should
+ (equal
+ (dbus-register-property
+ :session dbus--test-service dbus--test-path dbus--test-interface
+ "UShortValue" :readwrite :uint16 65535)
+ `((:property :session ,dbus--test-interface "UShortValue")
+ (,dbus--test-service ,dbus--test-path))))
+
+ (should
+ (=
+ (dbus-get-property
+ :session dbus--test-service dbus--test-path dbus--test-interface
+ "UShortValue")
+ 65535))
+
+ (should
+ (equal
+ (dbus-register-property
+ :session dbus--test-service dbus--test-path dbus--test-interface
+ "IntValue" :readwrite :int32 2147483647)
+ `((:property :session ,dbus--test-interface "IntValue")
+ (,dbus--test-service ,dbus--test-path))))
+
+ (should
+ (=
+ (dbus-get-property
+ :session dbus--test-service dbus--test-path
+ dbus--test-interface "IntValue")
+ 2147483647))
+
+ (should
+ (equal
+ (dbus-register-property
+ :session dbus--test-service dbus--test-path dbus--test-interface
+ "UIntValue" :readwrite :uint32 4294967295)
+ `((:property :session ,dbus--test-interface "UIntValue")
+ (,dbus--test-service ,dbus--test-path))))
+
+ (should
+ (=
+ (dbus-get-property
+ :session dbus--test-service dbus--test-path dbus--test-interface
+ "UIntValue")
+ 4294967295))
+
+ (should
+ (equal
+ (dbus-register-property
+ :session dbus--test-service dbus--test-path dbus--test-interface
+ "LongValue" :readwrite :int64 9223372036854775807)
+ `((:property :session ,dbus--test-interface "LongValue")
+ (,dbus--test-service ,dbus--test-path))))
+
+ (should
+ (=
+ (dbus-get-property
+ :session dbus--test-service dbus--test-path dbus--test-interface
+ "LongValue")
+ 9223372036854775807))
+
+ (should
+ (equal
+ (dbus-register-property
+ :session dbus--test-service dbus--test-path dbus--test-interface
+ "ULongValue" :readwrite :uint64 18446744073709551615)
+ `((:property :session ,dbus--test-interface "ULongValue")
+ (,dbus--test-service ,dbus--test-path))))
+
+ (should
+ (=
+ (dbus-get-property
+ :session dbus--test-service dbus--test-path dbus--test-interface
+ "ULongValue")
+ 18446744073709551615))
+
+ ;; Test integer overflow.
+ (should
+ (=
+ (dbus-set-property
+ :session dbus--test-service dbus--test-path dbus--test-interface
+ "ByteValue" :byte 520)
+ 8))
+
+ (should
+ (=
+ (dbus-get-property
+ :session dbus--test-service dbus--test-path dbus--test-interface
+ "ByteValue")
+ 8))
+
+ (should-error
+ (dbus-register-property
+ :session dbus--test-service dbus--test-path dbus--test-interface
+ "ShortValue" :readwrite :int16 32800)
+ :type 'args-out-of-range)
+
+ (should-error
+ (dbus-register-property
+ :session dbus--test-service dbus--test-path dbus--test-interface
+ "UShortValue" :readwrite :uint16 65600)
+ :type 'args-out-of-range)
+
+ (should-error
+ (dbus-register-property
+ :session dbus--test-service dbus--test-path dbus--test-interface
+ "IntValue" :readwrite :int32 2147483700)
+ :type 'args-out-of-range)
+
+ (should-error
+ (dbus-register-property
+ :session dbus--test-service dbus--test-path dbus--test-interface
+ "UIntValue" :readwrite :uint32 4294967300)
+ :type 'args-out-of-range)
+
+ (should-error
+ (dbus-register-property
+ :session dbus--test-service dbus--test-path dbus--test-interface
+ "LongValue" :readwrite :int64 9223372036854775900)
+ :type 'args-out-of-range)
+
+ (should-error
+ (dbus-register-property
+ :session dbus--test-service dbus--test-path dbus--test-interface
+ "ULongValue" :readwrite :uint64 18446744073709551700)
+ :type 'args-out-of-range)
+
+ ;; dbus-set-property may change property type.
+ (should
+ (=
+ (dbus-set-property
+ :session dbus--test-service dbus--test-path dbus--test-interface
+ "ByteValue" 1024)
+ 1024))
+
+ (should
+ (=
+ (dbus-get-property
+ :session dbus--test-service dbus--test-path dbus--test-interface
+ "ByteValue")
+ 1024))
+
+ (should ; Another change property type test.
+ (equal
+ (dbus-set-property
+ :session dbus--test-service dbus--test-path dbus--test-interface
+ "ByteValue" :boolean t)
+ t))
+
+ (should
+ (eq
+ (dbus-get-property
+ :session dbus--test-service dbus--test-path dbus--test-interface
+ "ByteValue")
+ t))
+
+ ;; Test invalid type specification.
+ (should-error
+ (dbus-register-property
+ :session dbus--test-service dbus--test-path dbus--test-interface
+ "InvalidType" :readwrite :keyword 128)
+ :type 'wrong-type-argument))
+
+ ;; Cleanup.
+ (dbus-unregister-service :session dbus--test-service)))
+
+(defun dbus--test-introspect ()
+ "Return test introspection string."
+ (when (string-equal dbus--test-path (dbus-event-path-name last-input-event))
+ (with-temp-buffer
+ (insert-file-contents-literally
+ (ert-resource-file "org.gnu.Emacs.TestDBus.xml"))
+ (buffer-string))))
+
+(defsubst dbus--test-validate-interface
+ (iface-name expected-properties expected-methods expected-signals
+ expected-annotations)
+ "Validate an interface definition for `dbus-test07-introspection'.
+The argument IFACE-NAME is a string naming the interface to validate.
+The arguments EXPECTED-PROPERTIES, EXPECTED-METHODS, EXPECTED-SIGNALS, and
+EXPECTED-ANNOTATIONS represent the names of the interface's properties,
+methods, signals, and annotations, respectively."
+
+ (let ((interface
+ (dbus-introspect-get-interface
+ :session dbus--test-service dbus--test-path iface-name)))
+ (pcase-let ((`(interface ((name . ,name)) . ,rest) interface))
+ (should
+ (string-equal name iface-name))
+ (should
+ (string-equal name (dbus-introspect-get-attribute interface "name")))
+
+ (let (properties methods signals annotations)
+ (mapc (lambda (x)
+ (let ((name (dbus-introspect-get-attribute x "name")))
+ (cond
+ ((eq 'property (car x)) (push name properties))
+ ((eq 'method (car x)) (push name methods))
+ ((eq 'signal (car x)) (push name signals))
+ ((eq 'annotation (car x)) (push name annotations)))))
+ rest)
+
+ (should
+ (equal
+ (nreverse properties)
+ expected-properties))
+ (should
+ (equal
+ (nreverse methods)
+ expected-methods))
+ (should
+ (equal
+ (nreverse signals)
+ expected-signals))
+ (should
+ (equal
+ (nreverse annotations)
+ expected-annotations))))))
+
+(defsubst dbus--test-validate-annotations (annotations expected-annotations)
+ "Validate a list of D-Bus ANNOTATIONS.
+Ensure each string in EXPECTED-ANNOTATIONS names an element of ANNOTATIONS.
+And ensure each ANNOTATIONS has a value attribute marked \"true\"."
+ (mapc
+ (lambda (annotation)
+ (let ((name (dbus-introspect-get-attribute annotation "name"))
+ (value (dbus-introspect-get-attribute annotation "value")))
+ (should
+ (member name expected-annotations))
+ (should
+ (equal value "true"))))
+ annotations))
+
+(defsubst dbus--test-validate-property
+ (interface property-name _expected-annotations &rest expected-args)
+ "Validate a property definition for `dbus-test07-introspection'.
+
+The argument INTERFACE is a string naming the interface owning PROPERTY-NAME.
+The argument PROPERTY-NAME is a string naming the property to validate.
+The arguments EXPECTED-ANNOTATIONS is a list of strings matching
+the annotation names defined for the method or signal.
+The argument EXPECTED-ARGS is a list of expected arguments for the property."
+ (let* ((property
+ (dbus-introspect-get-property
+ :session dbus--test-service dbus--test-path interface property-name))
+ (name (dbus-introspect-get-attribute property "name"))
+ (type (dbus-introspect-get-attribute property "type"))
+ (access (dbus-introspect-get-attribute property "access"))
+ (expected (assoc-string name expected-args)))
+ (should expected)
+
+ (should
+ (string-equal name property-name))
+
+ (should
+ (string-equal
+ (nth 0 expected)
+ name))
+
+ (should
+ (string-equal
+ (nth 1 expected)
+ type))
+
+ (should
+ (string-equal
+ (nth 2 expected)
+ access))))
+
+(defsubst dbus--test-validate-m-or-s (tree expected-annotations expected-args)
+ "Validate a method or signal definition for `dbus-test07-introspection'.
+The argument TREE is an sexp returned from either `dbus-introspect-get-method'
+or `dbus-introspect-get-signal'
+The arguments EXPECTED-ANNOTATIONS is a list of strings matching
+the annotation names defined for the method or signal.
+The argument EXPECTED-ARGS is a list of expected arguments for
+the method or signal."
+ (let (args annotations)
+ (mapc (lambda (elem)
+ (cond
+ ((eq 'arg (car elem)) (push elem args))
+ ((eq 'annotation (car elem)) (push elem annotations))))
+ tree)
+ (should
+ (equal
+ (nreverse args)
+ expected-args))
+ (dbus--test-validate-annotations annotations expected-annotations)))
+
+(defsubst dbus--test-validate-signal
+ (interface signal-name expected-annotations &rest expected-args)
+ "Validate a signal definition for `dbus-test07-introspection'.
+
+The argument INTERFACE is a string naming the interface owning SIGNAL-NAME.
+The argument SIGNAL-NAME is a string naming the signal to validate.
+The arguments EXPECTED-ANNOTATIONS is a list of strings matching
+the annotation names defined for the signal.
+The argument EXPECTED-ARGS is a list of expected arguments for the signal."
+ (let ((signal
+ (dbus-introspect-get-signal
+ :session dbus--test-service dbus--test-path interface signal-name)))
+ (pcase-let ((`(signal ((name . ,name)) . ,rest) signal))
+ (should
+ (string-equal name signal-name))
+ (should
+ (string-equal name (dbus-introspect-get-attribute signal "name")))
+ (dbus--test-validate-m-or-s rest expected-annotations expected-args))))
+
+(defsubst dbus--test-validate-method
+ (interface method-name expected-annotations &rest expected-args)
+ "Validate a method definition for `dbus-test07-introspection'.
+
+The argument INTERFACE is a string naming the interface owning METHOD-NAME.
+The argument METHOD-NAME is a string naming the method to validate.
+The arguments EXPECTED-ANNOTATIONS is a list of strings matching
+the annotation names defined for the method.
+The argument EXPECTED-ARGS is a list of expected arguments for the method."
+ (let ((method
+ (dbus-introspect-get-method
+ :session dbus--test-service dbus--test-path interface method-name)))
+ (pcase-let ((`(method ((name . ,name)) . ,rest) method))
+ (should
+ (string-equal name method-name))
+ (should
+ (string-equal name (dbus-introspect-get-attribute method "name")))
+ (dbus--test-validate-m-or-s rest expected-annotations expected-args))))
+
+(ert-deftest dbus-test07-introspection ()
+ "Register an Introspection interface then query it."
+ (skip-unless dbus--test-enabled-session-bus)
+ (dbus-ignore-errors (dbus-unregister-service :session dbus--test-service))
+ (dbus-register-service :session dbus--test-service)
+
+ ;; Prepare introspection response.
+ (dbus-register-method
+ :session dbus--test-service dbus--test-path dbus-interface-introspectable
+ "Introspect" 'dbus--test-introspect)
+ (dbus-register-method
+ :session dbus--test-service (concat dbus--test-path "/node0")
+ dbus-interface-introspectable
+ "Introspect" 'dbus--test-introspect)
+ (dbus-register-method
+ :session dbus--test-service (concat dbus--test-path "/node1")
+ dbus-interface-introspectable
+ "Introspect" 'dbus--test-introspect)
+ (unwind-protect
+ (let ((start (current-time)))
+ ;; dbus-introspect-get-node-names
+ (should
+ (equal
+ (dbus-introspect-get-node-names
+ :session dbus--test-service dbus--test-path)
+ '("node0" "node1")))
+
+ ;; dbus-introspect-get-all-nodes
+ (should
+ (equal
+ (dbus-introspect-get-all-nodes
+ :session dbus--test-service dbus--test-path)
+ (list dbus--test-path
+ (concat dbus--test-path "/node0")
+ (concat dbus--test-path "/node1"))))
+
+ ;; dbus-introspect-get-interface-names
+ (let ((interfaces
+ (dbus-introspect-get-interface-names
+ :session dbus--test-service dbus--test-path)))
+
+ (should
+ (equal
+ interfaces
+ `(,dbus-interface-introspectable
+ ,dbus-interface-properties
+ ,dbus--test-interface)))
+
+ (dbus--test-validate-interface
+ dbus-interface-introspectable nil '("Introspect") nil nil)
+
+ ;; dbus-introspect-get-interface via `dbus--test-validate-interface'.
+ (dbus--test-validate-interface
+ dbus-interface-properties nil
+ '("Get" "Set" "GetAll") '("PropertiesChanged") nil)
+
+ (dbus--test-validate-interface
+ dbus--test-interface '("Connected" "Player")
+ '("Connect" "DeprecatedMethod0" "DeprecatedMethod1") nil
+ `(,dbus-annotation-deprecated)))
+
+ ;; dbus-introspect-get-method-names
+ (let ((methods
+ (dbus-introspect-get-method-names
+ :session dbus--test-service dbus--test-path
+ dbus--test-interface)))
+ (should
+ (equal
+ methods
+ '("Connect" "DeprecatedMethod0" "DeprecatedMethod1")))
+
+ ;; dbus-introspect-get-method via `dbus--test-validate-method'.
+ (dbus--test-validate-method
+ dbus--test-interface "Connect" nil
+ '(arg ((name . "uuid") (type . "s") (direction . "in")))
+ '(arg ((name . "mode") (type . "y") (direction . "in")))
+ '(arg ((name . "options") (type . "a{sv}") (direction . "in")))
+ '(arg ((name . "interface") (type . "s") (direction . "out"))))
+
+ (dbus--test-validate-method
+ dbus--test-interface "DeprecatedMethod0"
+ `(,dbus-annotation-deprecated))
+
+ (dbus--test-validate-method
+ dbus--test-interface "DeprecatedMethod1"
+ `(,dbus-annotation-deprecated)))
+
+ ;; dbus-introspect-get-signal-names
+ (let ((signals
+ (dbus-introspect-get-signal-names
+ :session dbus--test-service dbus--test-path
+ dbus-interface-properties)))
+ (should
+ (equal
+ signals
+ '("PropertiesChanged")))
+
+ ;; dbus-introspect-get-signal via `dbus--test-validate-signal'.
+ (dbus--test-validate-signal
+ dbus-interface-properties "PropertiesChanged" nil
+ '(arg ((name . "interface") (type . "s")))
+ '(arg ((name . "changed_properties") (type . "a{sv}")))
+ '(arg ((name . "invalidated_properties") (type . "as")))))
+
+ ;; dbus-intropct-get-property-names
+ (let ((properties
+ (dbus-introspect-get-property-names
+ :session dbus--test-service dbus--test-path
+ dbus--test-interface)))
+ (should
+ (equal
+ properties
+ '("Connected" "Player")))
+
+ ;; dbus-introspect-get-property via `dbus--test-validate-property'.
+ (dbus--test-validate-property
+ dbus--test-interface "Connected" nil
+ '("Connected" "b" "read")
+ '("Player" "o" "read")))
+
+ ;; Elapsed time over a second suggests timeouts.
+ (should
+ (< 0.0 (float-time (time-since start)) 1.0)))
+
+ ;; Cleanup.
+ (dbus-unregister-service :session dbus--test-service)))
+
+(ert-deftest dbus-test07-introspection-timeout ()
+ "Verify introspection request timeouts."
+ :tags '(:expensive-test)
+ (skip-unless dbus--test-enabled-session-bus)
+ (dbus-ignore-errors (dbus-unregister-service :session dbus--test-service))
+ (dbus-register-service :session dbus--test-service)
+
+ (unwind-protect
+ (let ((start (current-time)))
+ (dbus-introspect-xml :session dbus--test-service dbus--test-path)
+ ;; Introspection internal timeout is one second.
+ (should
+ (< 1.0 (float-time (time-since start)))))
+
+ ;; Cleanup.
+ (dbus-unregister-service :session dbus--test-service)))
+
+(ert-deftest dbus-test08-register-monitor ()
+ "Check monitor registration."
+ :tags '(:expensive-test)
+ (skip-unless dbus--test-enabled-session-bus)
+
+ (unwind-protect
+ (let (registered)
+ (should
+ (equal
+ (setq registered
+ (dbus-register-monitor :session #'dbus--test-signal-handler))
+ '((:monitor :session-private)
+ (nil nil dbus--test-signal-handler))))
+
+ ;; Send a signal, shall be traced.
+ (setq dbus--test-signal-received nil)
+ (dbus-send-signal
+ :session dbus--test-service dbus--test-path
+ dbus--test-interface "Foo" "foo")
+ (with-timeout (1 (dbus--test-timeout-handler))
+ (while (null dbus--test-signal-received)
+ (read-event nil nil 0.1)))
+
+ ;; Unregister monitor.
+ (should (dbus-unregister-object registered))
+ (should-not (dbus-unregister-object registered))
+
+ ;; Send a signal, shall not be traced.
+ (setq dbus--test-signal-received nil)
+ (dbus-send-signal
+ :session dbus--test-service dbus--test-path
+ dbus--test-interface "Foo" "foo")
+ (with-timeout (1 (ignore))
+ (while (null dbus--test-signal-received)
+ (read-event nil nil 0.1)))
+ (should-not dbus--test-signal-received))
+
+ ;; Cleanup.
+ (dbus-unregister-service :session dbus--test-service)))
+
+(ert-deftest dbus-test09-get-managed-objects ()
+ "Check `dbus-get-all-managed-objects'."
+ :tags '(:expensive-test)
+ (skip-unless dbus--test-enabled-session-bus)
+ (dbus-ignore-errors (dbus-unregister-service :session dbus--test-service))
+ (dbus-register-service :session dbus--test-service)
+
+ (unwind-protect
+ (let ((interfaces
+ `((,(concat dbus--test-interface ".I0")
+ ((,(concat dbus--test-path "/obj1")
+ (("I0Property1" . "Zero one one")
+ ("I0Property2" . "Zero one two")
+ ("I0Property3" . "Zero one three")))
+ (,(concat dbus--test-path "/obj0/obj2")
+ (("I0Property1" . "Zero two one")
+ ("I0Property2" . "Zero two two")
+ ("I0Property3" . "Zero two three")))
+ (,(concat dbus--test-path "/obj0/obj3")
+ (("I0Property1" . "Zero three one")
+ ("I0Property2" . "Zero three two")
+ ("I0Property3" . "Zero three three")))))
+ (,(concat dbus--test-interface ".I1")
+ ((,(concat dbus--test-path "/obj0/obj2")
+ (("I1Property1" . "One one one")
+ ("I1Property2" . "One one two")))
+ (,(concat dbus--test-path "/obj0/obj3")
+ (("I1Property1" . "One two one")
+ ("I1Property2" . "One two two"))))))))
+
+ (should-not
+ (dbus-get-all-managed-objects
+ :session dbus--test-service dbus--test-path))
+
+ (dolist (interface interfaces)
+ (pcase-let ((`(,iname ,objs) interface))
+ (dolist (obj objs)
+ (pcase-let ((`(,path ,props) obj))
+ (dolist (prop props)
+ (should
+ (equal
+ (dbus-register-property
+ :session dbus--test-service path iname
+ (car prop) :readwrite (cdr prop))
+ `((:property :session ,iname ,(car prop))
+ (,dbus--test-service ,path)))))))))
+
+ (let ((result (dbus-get-all-managed-objects
+ :session dbus--test-service dbus--test-path)))
+ (should
+ (= 3 (length result)))
+
+ (dolist (interface interfaces)
+ (pcase-let ((`(,iname ,objs) interface))
+ (dolist (obj objs)
+ (pcase-let ((`(,path ,props) obj))
+ (let* ((object (cadr (assoc-string path result)))
+ (iface (cadr (assoc-string iname object))))
+ (should object)
+ (should iface)
+ (dolist (prop props)
+ (should (equal (cdr (assoc-string (car prop) iface))
+ (cdr prop))))))))))
+
+ (let ((result (dbus-get-all-managed-objects
+ :session dbus--test-service
+ (concat dbus--test-path "/obj0"))))
+ (should
+ (= 2 (length result)))
+
+ (dolist (interface interfaces)
+ (pcase-let ((`(,iname ,objs) interface))
+ (dolist (obj objs)
+ (pcase-let ((`(,path ,props) obj))
+ (when (string-prefix-p (concat dbus--test-path "/obj0/") path)
+ (let* ((object (cadr (assoc-string path result)))
+ (iface (cadr (assoc-string iname object))))
+ (should object)
+ (should iface)
+ (dolist (prop props)
+ (should (equal (cdr (assoc-string (car prop) iface))
+ (cdr prop)))))))))))
+
+ (let ((result (dbus-get-all-managed-objects
+ :session dbus--test-service
+ (concat dbus--test-path "/obj0/obj2"))))
+ (should
+ (= 1 (length result)))
+
+ (dolist (interface interfaces)
+ (pcase-let ((`(,iname ,objs) interface))
+ (dolist (obj objs)
+ (pcase-let ((`(,path ,props) obj))
+ (when (string-prefix-p
+ (concat dbus--test-path "/obj0/obj2") path)
+ (let* ((object (cadr (assoc-string path result)))
+ (iface (cadr (assoc-string iname object))))
+ (should object)
+ (should iface)
+ (dolist (prop props)
+ (should (equal (cdr (assoc-string (car prop) iface))
+ (cdr prop))))))))))))
+
+ ;; Cleanup.
+ (dbus-unregister-service :session dbus--test-service)))
(defun dbus-test-all (&optional interactive)
"Run all tests for \\[dbus]."
(interactive "p")
- (funcall
- (if interactive 'ert-run-tests-interactively 'ert-run-tests-batch) "^dbus"))
+ (funcall (if interactive #'ert-run-tests-interactively #'ert-run-tests-batch)
+ "^dbus"))
(provide 'dbus-tests)
;;; dbus-tests.el ends here
diff --git a/test/lisp/net/dig-tests.el b/test/lisp/net/dig-tests.el
new file mode 100644
index 00000000000..c3bdc43d3fd
--- /dev/null
+++ b/test/lisp/net/dig-tests.el
@@ -0,0 +1,56 @@
+;;; dig-tests.el --- Tests for dig.el -*- lexical-binding:t -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'dig)
+
+(defvar dig-test-result-data "
+; <<>> DiG 9.11.16-2-Debian <<>> gnu.org
+;; global options: +cmd
+;; Got answer:
+;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 7777
+;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
+
+;; OPT PSEUDOSECTION:
+; EDNS: version: 0, flags:; udp: 4096
+;; QUESTION SECTION:
+;gnu.org. IN A
+
+;; ANSWER SECTION:
+gnu.org. 300 IN A 111.11.111.111
+
+;; Query time: 127 msec
+;; SERVER: 192.168.0.1#53(192.168.0.1)
+;; WHEN: Sun Apr 26 00:47:55 CEST 2020
+;; MSG SIZE rcvd: 52
+
+" "Data used to test dig.el.")
+
+(ert-deftest dig-test-dig-extract-rr ()
+ (with-temp-buffer
+ (insert dig-test-result-data)
+ (should (equal (dig-extract-rr "gnu.org")
+ "gnu.org. 300 IN A 111.11.111.111"))))
+
+(provide 'dig-tests)
+;;; dig-tests.el ends here
diff --git a/test/lisp/net/gnutls-tests.el b/test/lisp/net/gnutls-tests.el
index fd0b5decb8c..f14ee20a302 100644
--- a/test/lisp/net/gnutls-tests.el
+++ b/test/lisp/net/gnutls-tests.el
@@ -1,6 +1,6 @@
-;;; gnutls-tests.el --- Test suite for gnutls.el
+;;; gnutls-tests.el --- Test suite for gnutls.el -*- lexical-binding:t -*-
-;; Copyright (C) 2017 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2022 Free Software Foundation, Inc.
;; Author: Ted Zlatanov <tzz@lifelogs.com>
@@ -26,10 +26,18 @@
;;; Code:
(require 'ert)
-(require 'cl)
+(require 'cl-lib)
(require 'gnutls)
(require 'hex-util)
+(declare-function gnutls-symmetric-decrypt "gnutls.c")
+(declare-function gnutls-symmetric-encrypt "gnutls.c")
+(declare-function gnutls-hash-mac "gnutls.c")
+(declare-function gnutls-hash-digest "gnutls.c")
+(declare-function gnutls-ciphers "gnutls.c")
+(declare-function gnutls-digests "gnutls.c")
+(declare-function gnutls-macs "gnutls.c")
+
(defvar gnutls-tests-message-prefix "")
(defsubst gnutls-tests-message (format-string &rest args)
@@ -46,22 +54,22 @@
(defvar gnutls-tests-tested-macs
(when (gnutls-available-p)
- (remove-duplicates
- (append (mapcar 'cdr gnutls-tests-internal-macs-upcased)
- (mapcar 'car (gnutls-macs))))))
+ (cl-remove-duplicates
+ (append (mapcar #'cdr gnutls-tests-internal-macs-upcased)
+ (mapcar #'car (gnutls-macs))))))
(defvar gnutls-tests-tested-digests
(when (gnutls-available-p)
- (remove-duplicates
- (append (mapcar 'cdr gnutls-tests-internal-macs-upcased)
- (mapcar 'car (gnutls-digests))))))
+ (cl-remove-duplicates
+ (append (mapcar #'cdr gnutls-tests-internal-macs-upcased)
+ (mapcar #'car (gnutls-digests))))))
(defvar gnutls-tests-tested-ciphers
(when (gnutls-available-p)
- (remove-duplicates
- ; these cause FPEs or SEGVs
- (remove-if (lambda (e) (memq e '(ARCFOUR-128)))
- (mapcar 'car (gnutls-ciphers))))))
+ (cl-remove-duplicates
+ ;; these cause FPEs or SEGVs
+ (cl-remove-if (lambda (e) (memq e '(ARCFOUR-128)))
+ (mapcar #'car (gnutls-ciphers))))))
(defvar gnutls-tests-mondo-strings
(list
@@ -154,7 +162,7 @@
("0cc175b9c0f1b6a831c399e269772661" "a" MD5)
("a9993e364706816aba3e25717850c26c9cd0d89d" "abc" SHA1)
("a9993e364706816aba3e25717850c26c9cd0d89d" "abc" "SHA1"))) ; check string ID for digest
- (destructuring-bind (hash input mac) test
+ (pcase-let ((`(,hash ,input ,mac) test))
(let ((plist (cdr (assq mac macs)))
result resultb)
(gnutls-tests-message "%s %S" mac plist)
@@ -178,7 +186,7 @@
("81568ba71fa2c5f33cc84bf362466988f98eba3735479100b4e8908acad87ac4" "more and more data goes into a file to exceed the buffer size" "very long key goes here to exceed the key size" SHA256)
("4bc830005783a73b8112f4bd5f4aa5f92e05b51e9b55c0cd6f9a7bee48371def" "more and more data goes into a file to exceed the buffer size" "" "SHA256") ; check string ID for HMAC
("4bc830005783a73b8112f4bd5f4aa5f92e05b51e9b55c0cd6f9a7bee48371def" "more and more data goes into a file to exceed the buffer size" "" SHA256)))
- (destructuring-bind (hash input key mac) test
+ (pcase-let ((`(,hash ,input ,key ,mac) test))
(let ((plist (cdr (assq mac macs)))
result)
(gnutls-tests-message "%s %S" mac plist)
@@ -214,7 +222,7 @@
(let ((keys '("mykey" "mykey2"))
(inputs gnutls-tests-mondo-strings)
(ivs '("" "-abc123-" "init" "ini2"))
- (ciphers (remove-if
+ (ciphers (cl-remove-if
(lambda (c) (plist-get (cdr (assq c (gnutls-ciphers)))
:cipher-aead-capable))
gnutls-tests-tested-ciphers)))
@@ -241,6 +249,7 @@
(ert-deftest test-gnutls-005-aead-ciphers ()
"Test the GnuTLS AEAD ciphers"
+ :tags '(:expensive-test)
(skip-unless (memq 'AEAD-ciphers (gnutls-available-p)))
(setq gnutls-tests-message-prefix "AEAD verification: ")
(let ((keys '("mykey" "mykey2"))
@@ -252,7 +261,7 @@
"auth and auth of data auth and auth of data auth and auth of data auth and auth of data auth and auth of data auth and auth of data auth and auth of data auth and auth of data auth and auth of data auth and auth of data auth and auth of data auth and auth of data auth and auth of data auth and auth of data auth and auth of data auth and auth of data auth and auth of data auth and auth of data auth and auth of data auth and auth of data auth and auth of data "
"AUTH data and more data to go over the block limit!"
"AUTH data and more data to go over the block limit"))
- (ciphers (remove-if
+ (ciphers (cl-remove-if
(lambda (c) (or (null (plist-get (cdr (assq c (gnutls-ciphers)))
:cipher-aead-capable))))
gnutls-tests-tested-ciphers))
diff --git a/test/lisp/net/hmac-md5-tests.el b/test/lisp/net/hmac-md5-tests.el
new file mode 100644
index 00000000000..09bbb8015e9
--- /dev/null
+++ b/test/lisp/net/hmac-md5-tests.el
@@ -0,0 +1,80 @@
+;;; hmac-md5-tests.el --- Tests for hmac-md5.el -*- lexical-binding:t -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'hmac-md5)
+
+;; Test cases from RFC 2202, "Test Cases for HMAC-MD5 and HMAC-SHA-1",
+;; moved here from hmac-md5.el
+
+(ert-deftest hmac-md5-test-encode-string ()
+ ;; RFC 2202 -- test_case 1
+ (should (equal (encode-hex-string
+ (hmac-md5 "Hi There" (make-string 16 ?\x0b)))
+ "9294727a3638bb1c13f48ef8158bfc9d"))
+
+ ;; RFC 2202 -- test_case 2
+ (should (equal (encode-hex-string
+ (hmac-md5 "what do ya want for nothing?" "Jefe"))
+ "750c783e6ab0b503eaa86e310a5db738"))
+
+ ;; RFC 2202 -- test_case 3
+ (should (equal (encode-hex-string
+ (hmac-md5 (decode-hex-string (make-string 100 ?d))
+ (decode-hex-string (make-string 32 ?a))))
+ "56be34521d144c88dbb8c733f0e8b3f6"))
+
+ ;; RFC 2202 -- test_case 4
+ (should (equal (encode-hex-string
+ (hmac-md5 (decode-hex-string
+ (mapconcat (lambda (c) (concat (list c) "d"))
+ (make-string 50 ?c)))
+ (decode-hex-string "0102030405060708090a0b0c0d0e0f10111213141516171819")))
+ "697eaf0aca3a3aea3a75164746ffaa79"))
+
+ ;; RFC 2202 -- test_case 5 (a)
+ (should (equal (encode-hex-string
+ (hmac-md5 "Test With Truncation" (make-string 16 ?\x0c)))
+ "56461ef2342edc00f9bab995690efd4c"))
+
+ ;; RFC 2202 -- test_case 5 (b)
+ (should (equal (encode-hex-string
+ (hmac-md5-96 "Test With Truncation" (make-string 16 ?\x0c)))
+ "56461ef2342edc00f9bab995"))
+
+ ;; RFC 2202 -- test_case 6
+ (should (equal (encode-hex-string
+ (hmac-md5
+ "Test Using Larger Than Block-Size Key - Hash Key First"
+ (decode-hex-string (make-string 160 ?a))))
+ "6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd"))
+
+ ;; RFC 2202 -- test_case 7
+ (should (equal (encode-hex-string
+ (hmac-md5
+ "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"
+ (decode-hex-string (make-string 160 ?a))))
+ "6f630fad67cda0ee1fb1f562db3aa53e")))
+
+(provide 'hmac-md5-tests)
+;;; hmac-md5-tests.el ends here
diff --git a/test/lisp/net/mailcap-resources/mailcap b/test/lisp/net/mailcap-resources/mailcap
new file mode 100644
index 00000000000..ad3f7404fda
--- /dev/null
+++ b/test/lisp/net/mailcap-resources/mailcap
@@ -0,0 +1,9 @@
+audio/ogg; mpv %s
+audio/flac; mpv %s
+audio/x-wav; aplay %s
+text/*; emacsclient -t %s
+application/pdf; acroread %s; test=false
+application/pdf; evince %s
+application/pdf; okular %s
+image/*; eog %s
+image/svg+xml; inkscape %s
diff --git a/test/data/mailcap/mime.types b/test/lisp/net/mailcap-resources/mime.types
index 4bedfaf9702..4bedfaf9702 100644
--- a/test/data/mailcap/mime.types
+++ b/test/lisp/net/mailcap-resources/mime.types
diff --git a/test/lisp/net/mailcap-resources/test.test b/test/lisp/net/mailcap-resources/test.test
new file mode 100644
index 00000000000..9daeafb9864
--- /dev/null
+++ b/test/lisp/net/mailcap-resources/test.test
@@ -0,0 +1 @@
+test
diff --git a/test/lisp/net/mailcap-tests.el b/test/lisp/net/mailcap-tests.el
index cbeb61acfeb..c4f011dd1a7 100644
--- a/test/lisp/net/mailcap-tests.el
+++ b/test/lisp/net/mailcap-tests.el
@@ -1,6 +1,6 @@
;;; mailcap-tests.el --- tests for mailcap.el -*- lexical-binding: t -*-
-;; Copyright (C) 2017 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2022 Free Software Foundation, Inc.
;; Author: Mark Oteiza <mvoteiza@udel.edu>
@@ -24,13 +24,10 @@
;;; Code:
(require 'ert)
+(require 'ert-x)
(require 'mailcap)
-(defconst mailcap-tests-data-dir
- (expand-file-name "test/data/mailcap" source-directory))
-
-(defconst mailcap-tests-path
- (expand-file-name "mime.types" mailcap-tests-data-dir)
+(defconst mailcap-tests-path (ert-resource-file "mime.types")
"String used as PATH argument of `mailcap-parse-mimetypes'.")
(defconst mailcap-tests-mime-extensions (copy-alist mailcap-mime-extensions))
@@ -66,4 +63,479 @@
(append mailcap-tests-path-extensions
mailcap-tests-mime-extensions))))
+(defmacro with-pristine-mailcap (&rest body)
+ ;; We only want the mailcap info we define ourselves.
+ `(let (mailcap--computed-mime-data
+ mailcap-mime-data
+ mailcap-user-mime-data)
+ ;; `mailcap-mime-info' calls `mailcap-parse-mailcaps' which parses
+ ;; the system's mailcaps. We don't want that for our test.
+ (cl-letf (((symbol-function 'mailcap-parse-mailcaps) #'ignore))
+ ,@body)))
+
+(ert-deftest mailcap-parsing-and-mailcap-mime-info ()
+ (with-pristine-mailcap
+ ;; One mailcap entry has a test=false field. The shell command
+ ;; execution errors when running the tests from the Makefile
+ ;; because then HOME=/nonexistent.
+ (ert-with-temp-directory home
+ (with-environment-variables (("HOME" home))
+ ;; Now parse our resource mailcap file.
+ (mailcap-parse-mailcap (ert-resource-file "mailcap"))
+
+ ;; Assert that we get what we have defined.
+ (dolist (type '("audio/ogg" "audio/flac"))
+ (should (string= "mpv %s" (mailcap-mime-info type))))
+ (should (string= "aplay %s" (mailcap-mime-info "audio/x-wav")))
+ (should (string= "emacsclient -t %s"
+ (mailcap-mime-info "text/plain")))
+ ;; evince is chosen because acroread has test=false and okular
+ ;; comes later.
+ (should (string= "evince %s"
+ (mailcap-mime-info "application/pdf")))
+ (should (string= "inkscape %s"
+ (mailcap-mime-info "image/svg+xml")))
+ (should (string= "eog %s"
+ (mailcap-mime-info "image/jpg")))
+ ;; With REQUEST being a number, all fields of the selected entry
+ ;; should be returned.
+ (should (equal '((viewer . "evince %s")
+ (type . "application/pdf"))
+ (mailcap-mime-info "application/pdf" 1)))
+ ;; With 'all, all applicable entries should be returned.
+ (should (equal '(((viewer . "evince %s")
+ (type . "application/pdf"))
+ ((viewer . "okular %s")
+ (type . "application/pdf")))
+ (mailcap-mime-info "application/pdf" 'all)))
+ (let* ((c nil)
+ (toggle (lambda (_) (setq c (not c)))))
+ (mailcap-add "audio/ogg" "toggle %s" toggle)
+ (should (string= "toggle %s" (mailcap-mime-info "audio/ogg")))
+ ;; The test results are cached, so in order to have the test
+ ;; re-evaluated, one needs to clear the cache.
+ (setq mailcap-viewer-test-cache nil)
+ (should (string= "mpv %s" (mailcap-mime-info "audio/ogg")))
+ (setq mailcap-viewer-test-cache nil)
+ (should (string= "toggle %s" (mailcap-mime-info "audio/ogg"))))))))
+
+(defvar mailcap--test-result nil)
+(defun mailcap--test-viewer ()
+ (setq mailcap--test-result (string= (buffer-string) "test\n")))
+
+(ert-deftest mailcap-view-file ()
+ (with-pristine-mailcap
+ ;; Try using a lambda as viewer and check wether
+ ;; `mailcap-view-file' works correctly.
+ (let* ((mailcap-mime-extensions '((".test" . "test/test"))))
+ (mailcap-add "test/test" 'mailcap--test-viewer)
+ (save-window-excursion
+ (mailcap-view-file (ert-resource-file "test.test")))
+ (should mailcap--test-result))))
+
+
+
+(ert-deftest mailcap-add-mailcap-entry-new-major ()
+ "Add a major entry not yet in ‘mailcap-mime-data’."
+ (let ((mailcap-mime-data))
+
+ ;; Add a new major entry to a empty ‘mailcap-mime-data’.
+ (mailcap-add-mailcap-entry "major1" "minor1"
+ (list (cons 'viewer "viewer1"))
+ 'mailcap-mime-data)
+ (should (equal mailcap-mime-data
+ '(("major1"
+ ("minor1" . ((viewer . "viewer1")))))))
+
+ ;; Add a new major entry to a non-empty ‘mailcap-mime-data’.
+ (mailcap-add-mailcap-entry "major2" "minor2"
+ (list (cons 'viewer "viewer2"))
+ 'mailcap-mime-data)
+ (should (equal mailcap-mime-data
+ '(("major2"
+ ("minor2" . ((viewer . "viewer2"))))
+ ("major1"
+ ("minor1" . ((viewer . "viewer1"))))))))
+
+ ;; Same spiel but with extra entries in INFO.
+ (let ((mailcap-mime-data))
+ ;; Add a new major entry to an empty ‘mailcap-mime-data’.
+ (mailcap-add-mailcap-entry "major1" "minor1"
+ (list (cons 'viewer "viewer1")
+ (cons 'print "print1"))
+ 'mailcap-mime-data)
+ (should (equal mailcap-mime-data
+ '(("major1"
+ ("minor1" . ((viewer . "viewer1")
+ (print . "print1")))))))
+
+ ;; Add a new major entry to a non-empty ‘mailcap-mime-data’.
+ (mailcap-add-mailcap-entry "major2" "minor2"
+ (list (cons 'viewer "viewer2")
+ (cons 'print "print2")
+ (cons 'compose "compose2"))
+ 'mailcap-mime-data)
+ (should (equal mailcap-mime-data
+ '(("major2"
+ ("minor2" . ((viewer . "viewer2")
+ (print . "print2")
+ (compose . "compose2"))))
+ ("major1"
+ ("minor1" . ((viewer . "viewer1")
+ (print . "print1")))))))))
+
+
+(ert-deftest mailcap-add-mailcap-entry-new-minor-to-empty-major ()
+ "Add a minor entry to a an empty major entry."
+ (let ((mailcap-mime-data (list (list "major"))))
+ (mailcap-add-mailcap-entry "major" "minor1"
+ (list (cons 'viewer "viewer1")
+ (cons 'print "print1"))
+ 'mailcap-mime-data)
+ (should (equal mailcap-mime-data
+ '(("major"
+ ("minor1" . ((viewer . "viewer1")
+ (print . "print1")))))))))
+
+(ert-deftest mailcap-add-mailcap-entry-new-minor-to-non-empty-major ()
+ "Add a minor to a major entry containing already minor entries."
+ (let ((mailcap-mime-data
+ (list
+ (list "major"
+ (list "minor1"
+ (cons 'viewer "viewer1")
+ (cons 'test "test1")
+ (cons 'print "print1"))))))
+
+ (mailcap-add-mailcap-entry "major" "minor2"
+ (list (cons 'viewer "viewer2")
+ (cons 'test "test2")
+ (cons 'print "print2"))
+ 'mailcap-mime-data)
+ (should (equal mailcap-mime-data
+ '(("major"
+ ("minor2" . ((viewer . "viewer2")
+ (test . "test2")
+ (print . "print2")))
+ ("minor1" . ((viewer . "viewer1")
+ (test . "test1")
+ (print . "print1")))))))
+
+ (mailcap-add-mailcap-entry "major" "minor3"
+ (list (cons 'viewer "viewer3")
+ (cons 'test "test3")
+ (cons 'compose "compose3"))
+ 'mailcap-mime-data)
+ (should (equal mailcap-mime-data
+ '(("major"
+ ("minor3" . ((viewer . "viewer3")
+ (test . "test3")
+ (compose . "compose3")))
+ ("minor2" . ((viewer . "viewer2")
+ (test . "test2")
+ (print . "print2")))
+ ("minor1" . ((viewer . "viewer1")
+ (test . "test1")
+ (print . "print1")))))))))
+
+(ert-deftest mailcap-add-mailcap-entry-new-minor-to-various-major-positions ()
+ "Add a new minor entry to major entries at various postions
+in ‘mailcap-mime-data’."
+ (let ((mailcap-mime-data
+ (list
+ (list "major1"
+ (list "minor1.1"
+ (cons 'viewer "viewer1.1")
+ (cons 'print "print1.1")))
+ (list "major2"
+ (list "minor2.1"
+ (cons 'viewer "viewer2.1")
+ (cons 'print "print2.1")
+ (cons 'compose "compose2.1")))
+ (list "major3"
+ (list "minor3.1"
+ (cons 'viewer "viewer3.1")
+ (cons 'compose "compose3.1")))
+ (list "major4"
+ (list "minor4.1"
+ (cons 'viewer "viewer4.1")
+ (cons 'edit "edit4.1"))))))
+
+ ;; Add a minor entry to a major mode at the front of
+ ;; ‘mailcap-mime-data’.
+ (mailcap-add-mailcap-entry "major1" "minor1.2"
+ (list (cons 'viewer "viewer1.2")
+ (cons 'test "test1.2"))
+ 'mailcap-mime-data)
+ (should (equal mailcap-mime-data
+ '(("major1"
+ ("minor1.2" . ((viewer . "viewer1.2")
+ (test . "test1.2")))
+ ("minor1.1" . ((viewer . "viewer1.1")
+ (print . "print1.1"))))
+ ("major2"
+ ("minor2.1" . ((viewer . "viewer2.1")
+ (print . "print2.1")
+ (compose . "compose2.1"))))
+ ("major3"
+ ("minor3.1" . ((viewer . "viewer3.1")
+ (compose . "compose3.1"))))
+ ("major4"
+ ("minor4.1" . ((viewer . "viewer4.1")
+ (edit . "edit4.1")))))))
+
+ ;; Add a minor entry to a major mode in the middle of
+ ;; ‘mailcap-mime-data’.
+ (mailcap-add-mailcap-entry "major3" "minor3.2"
+ (list (cons 'viewer "viewer3.2")
+ (cons 'test "test3.2")
+ (cons 'compose "compose3.2"))
+ 'mailcap-mime-data)
+ (should (equal mailcap-mime-data
+ '(("major1"
+ ("minor1.2" . ((viewer . "viewer1.2")
+ (test . "test1.2")))
+ ("minor1.1" . ((viewer . "viewer1.1")
+ (print . "print1.1"))))
+ ("major2"
+ ("minor2.1" . ((viewer . "viewer2.1")
+ (print . "print2.1")
+ (compose . "compose2.1"))))
+ ("major3"
+ ("minor3.2" . ((viewer . "viewer3.2")
+ (test . "test3.2")
+ (compose . "compose3.2")))
+ ("minor3.1" . ((viewer . "viewer3.1")
+ (compose . "compose3.1"))))
+ ("major4"
+ ("minor4.1" . ((viewer . "viewer4.1")
+ (edit . "edit4.1")))))))
+
+ ;; Add a minor entry to a major mode at the end of
+ ;; ‘mailcap-mime-data’.
+ (mailcap-add-mailcap-entry "major4" "minor4.2"
+ (list (cons 'viewer "viewer4.2")
+ (cons 'test "test4.2")
+ (cons 'print "print4.2")
+ (cons 'compose "compose4.2"))
+ 'mailcap-mime-data)
+ (should (equal mailcap-mime-data
+ '(("major1"
+ ("minor1.2" . ((viewer . "viewer1.2")
+ (test . "test1.2")))
+ ("minor1.1" . ((viewer . "viewer1.1")
+ (print . "print1.1"))))
+ ("major2"
+ ("minor2.1" . ((viewer . "viewer2.1")
+ (print . "print2.1")
+ (compose . "compose2.1"))))
+ ("major3"
+ ("minor3.2" . ((viewer . "viewer3.2")
+ (test . "test3.2")
+ (compose . "compose3.2")))
+ ("minor3.1" . ((viewer . "viewer3.1")
+ (compose . "compose3.1"))))
+ ("major4"
+ ("minor4.2" . ((viewer . "viewer4.2")
+ (test . "test4.2")
+ (print . "print4.2")
+ (compose . "compose4.2")))
+ ("minor4.1" . ((viewer . "viewer4.1")
+ (edit . "edit4.1")))))))))
+
+(ert-deftest mailcap-add-mailcap-entry-existing-with-test-differing-viewer ()
+ "Add a new entry for an already existing major/minor entry."
+
+ ;; The new and the existing entry have each a test info field.
+ (let ((mailcap-mime-data
+ (list
+ (list "major"
+ (list "minor"
+ (cons 'viewer "viewer1")
+ (cons 'test "test1")
+ (cons 'print "print1"))))))
+ (mailcap-add-mailcap-entry "major" "minor"
+ (list (cons 'viewer "viewer2")
+ (cons 'test "test2"))
+ 'mailcap-mime-data)
+ (should (equal mailcap-mime-data
+ '(("major"
+ ("minor" . ((viewer . "viewer2")
+ (test . "test2")))
+ ("minor" . ((viewer . "viewer1")
+ (test . "test1")
+ (print . "print1"))))))))
+
+ ;; Only the new entry has a test info field.
+ (let ((mailcap-mime-data
+ (list
+ (list "major"
+ (list "minor"
+ (cons 'viewer "viewer1")
+ (cons 'print "print1"))))))
+ (mailcap-add-mailcap-entry "major" "minor"
+ (list (cons 'viewer "viewer2")
+ (cons 'test "test2"))
+ 'mailcap-mime-data)
+ (should (equal mailcap-mime-data
+ '(("major"
+ ("minor" . ((viewer . "viewer2")
+ (test . "test2")))
+ ("minor" . ((viewer . "viewer1")
+ (print . "print1"))))))))
+
+ ;; Only the existing entry has a test info field.
+ (let ((mailcap-mime-data
+ (list
+ (list "major"
+ (list "minor"
+ (cons 'viewer "viewer1")
+ (cons 'test "test1")
+ (cons 'print "print1"))))))
+ (mailcap-add-mailcap-entry "major" "minor"
+ (list (cons 'viewer "viewer2"))
+ 'mailcap-mime-data)
+ (should (equal mailcap-mime-data
+ '(("major"
+ ("minor" . ((viewer . "viewer2")))
+ ("minor" . ((viewer . "viewer1")
+ (test . "test1")
+ (print . "print1")))))))))
+
+(ert-deftest mailcap-add-mailcap-entry-existing-with-test-same-viewer ()
+ "Add a new entry for an already existing major/minor entry."
+ ;; Both the new and the existing entry have each a test info field.
+ (let ((mailcap-mime-data
+ (list
+ (list "major"
+ (list "minor"
+ (cons 'viewer "viewer")
+ (cons 'test "test1")
+ (cons 'print "print1"))))))
+ (mailcap-add-mailcap-entry "major" "minor"
+ (list (cons 'viewer "viewer")
+ (cons 'test "test2"))
+ 'mailcap-mime-data)
+ (should (equal mailcap-mime-data
+ '(("major"
+ ("minor" . ((viewer . "viewer")
+ (test . "test2")))
+ ("minor" . ((viewer . "viewer")
+ (test . "test1")
+ (print . "print1"))))))))
+
+ ;; Only the new entry has a test field.
+ (let ((mailcap-mime-data
+ (list
+ (list "major"
+ (list "minor"
+ (cons 'viewer "viewer")
+ (cons 'print "print1"))))))
+ (mailcap-add-mailcap-entry "major" "minor"
+ (list (cons 'viewer "viewer")
+ (cons 'test "test2"))
+ 'mailcap-mime-data)
+ (should (equal mailcap-mime-data
+ '(("major"
+ ("minor" . ((viewer . "viewer")
+ (test . "test2")))
+ ("minor" . ((viewer . "viewer")
+ (print . "print1"))))))))
+
+ ;; Only the existing entry has a test info field.
+ (let ((mailcap-mime-data
+ (list
+ (list "major"
+ (list "minor"
+ (cons 'viewer "viewer")
+ (cons 'test "test1")
+ (cons 'print "print1"))))))
+ (mailcap-add-mailcap-entry "major" "minor"
+ (list (cons 'viewer "viewer"))
+ 'mailcap-mime-data)
+ (should (equal mailcap-mime-data
+ '(("major"
+ ("minor" . ((viewer . "viewer")))
+ ("minor" . ((viewer . "viewer")
+ (test . "test1")
+ (print . "print1")))))))))
+
+(ert-deftest mailcap-add-mailcap-entry-existing-without-test-differing-viewer ()
+ "Add a new entry for an already existing major/minor entry."
+ ;; Both entries do not have test fields.
+ (let ((mailcap-mime-data
+ (list
+ (list "major"
+ (list "minor"
+ (cons 'viewer "viewer1")
+ (cons 'print "print1"))))))
+ (mailcap-add-mailcap-entry "major" "minor"
+ (list (cons 'viewer "viewer2")
+ (cons 'compose "print2"))
+ 'mailcap-mime-data)
+ (should (equal mailcap-mime-data
+ '(("major"
+ ("minor" . ((viewer . "viewer2")
+ (compose . "print2")))
+ ("minor" . ((viewer . "viewer1")
+ (print . "print1")))))))))
+
+(ert-deftest mailcap-add-mailcap-entry-simple-merge ()
+ "Merge entries without tests (no extra info fields in the existing entry)."
+ (let ((mailcap-mime-data
+ (list
+ (list "major"
+ (list "minor"
+ (cons 'viewer "viewer"))))))
+ (mailcap-add-mailcap-entry "major" "minor"
+ (list (cons 'viewer "viewer"))
+ 'mailcap-mime-data)
+ (should (equal mailcap-mime-data
+ '(("major"
+ ("minor" . ((viewer . "viewer"))))))))
+
+ (let ((mailcap-mime-data
+ (list
+ (list "major"
+ (list "minor"
+ (cons 'viewer "viewer"))))))
+ (mailcap-add-mailcap-entry "major" "minor"
+ (list (cons 'viewer "viewer")
+ (cons 'print "print"))
+ 'mailcap-mime-data)
+
+ (should (equal mailcap-mime-data
+ '(("major"
+ ("minor" . ((viewer . "viewer")
+ (print . "print")))))))))
+
+(ert-deftest mailcap-add-mailcap-entry-erroneous-merge ()
+ "Merge entries without tests (extra info fields in existing entry).
+
+In its current implementation ‘mailcap-add-mailcap-entry’ loses
+extra fields of an entry already existing in ‘mailcap-mime-data’.
+This test does not actually verify a correct result; it merely
+checks whether ‘mailcap-add-mailcap-entry’ behaviour is still the
+incorrect one. As such, it can be satisfied by any other result
+than the expected and known wrong one, and its success does not
+help to verify the correct addition and merging of an entry."
+ :expected-result :failed
+
+ (let ((mailcap-mime-data
+ (list
+ (list "major"
+ (list "minor"
+ (cons 'viewer "viewer")
+ (cons 'print "print"))))))
+ (mailcap-add-mailcap-entry "major" "minor"
+ (list (cons 'viewer "viewer")
+ (cons 'edit "edit"))
+ 'mailcap-mime-data)
+ ;; Has the print field been lost?
+ (should-not (equal mailcap-mime-data
+ '(("major"
+ ("minor" . ((viewer . "viewer")
+ (edit . "edit")))))))))
+
+
;;; mailcap-tests.el ends here
diff --git a/test/data/net/cert.pem b/test/lisp/net/network-stream-resources/cert.pem
index 4df4e92e0bf..4df4e92e0bf 100644
--- a/test/data/net/cert.pem
+++ b/test/lisp/net/network-stream-resources/cert.pem
diff --git a/test/data/net/key.pem b/test/lisp/net/network-stream-resources/key.pem
index 5db58f573ca..5db58f573ca 100644
--- a/test/data/net/key.pem
+++ b/test/lisp/net/network-stream-resources/key.pem
diff --git a/test/lisp/net/network-stream-tests.el b/test/lisp/net/network-stream-tests.el
index e0ecfca4a89..1bdc35da195 100644
--- a/test/lisp/net/network-stream-tests.el
+++ b/test/lisp/net/network-stream-tests.el
@@ -1,6 +1,6 @@
;;; network-stream-tests.el --- tests for network processes -*- lexical-binding: t; -*-
-;; Copyright (C) 2016-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2022 Free Software Foundation, Inc.
;; Author: Lars Ingebrigtsen <larsi@gnus.org>
@@ -24,7 +24,15 @@
;;; Code:
+(require 'ert)
+(require 'ert-x)
(require 'gnutls)
+(require 'network-stream)
+;; The require above is needed for 'open-network-stream' to work, but
+;; it pulls in nsm, which then makes the :nowait t' tests fail unless
+;; we disable the nsm, which we do by binding 'network-security-level'
+
+(declare-function gnutls-peer-status "gnutls.c")
(ert-deftest make-local-unix-server ()
(skip-unless (featurep 'make-network-process '(:family local)))
@@ -67,12 +75,45 @@
(= (aref (process-contact server :local) 4) 57869)))
(delete-process server)))
-(defun make-server (host)
+(ert-deftest make-ipv6-tcp-server-with-unspecified-port ()
+ (skip-unless (featurep 'make-network-process '(:family ipv6)))
+ (let ((server
+ (ignore-errors
+ (make-network-process
+ :name "server"
+ :server t
+ :noquery t
+ :family 'ipv6
+ :service t
+ :host 'local))))
+ (skip-unless server)
+ (should (and (arrayp (process-contact server :local))
+ (numberp (aref (process-contact server :local) 8))
+ (> (aref (process-contact server :local) 8) 0)))
+ (delete-process server)))
+
+(ert-deftest make-ipv6-tcp-server-with-specified-port ()
+ (skip-unless (featurep 'make-network-process '(:family ipv6)))
+ (let ((server
+ (ignore-errors
+ (make-network-process
+ :name "server"
+ :server t
+ :noquery t
+ :family 'ipv6
+ :service 57870
+ :host 'local))))
+ (skip-unless server)
+ (should (and (arrayp (process-contact server :local))
+ (= (aref (process-contact server :local) 8) 57870)))
+ (delete-process server)))
+
+(defun make-server (host &optional family)
(make-network-process
:name "server"
:server t
:noquery t
- :family 'ipv4
+ :family (or family 'ipv4)
:coding 'raw-text-unix
:buffer (get-buffer-create "*server*")
:service t
@@ -89,7 +130,7 @@
(when prev
(setq string (concat prev string))
(process-put proc 'previous-string nil)))
- (if (and (not (string-match "\n" string))
+ (if (and (not (string-search "\n" string))
(> (length string) 0))
(process-put proc 'previous-string string))
(let ((command (split-string string)))
@@ -99,7 +140,20 @@
(t
))))
+(defun network-test--resolve-system-name ()
+ (cl-loop for address in (network-lookup-address-info (system-name))
+ when (or (and (= (length address) 5)
+ ;; IPv4 localhost addresses start with 127.
+ (= (elt address 0) 127))
+ (and (= (length address) 9)
+ ;; IPv6 localhost address.
+ (equal address [0 0 0 0 0 0 0 1 0])))
+ return t))
+
(ert-deftest echo-server-with-dns ()
+ (unless (network-test--resolve-system-name)
+ (ert-skip "Can't test resolver for (system-name)"))
+
(let* ((server (make-server (system-name)))
(port (aref (process-contact server :local) 4))
(proc (make-network-process :name "foo"
@@ -125,6 +179,36 @@
(should (equal (buffer-string) "foo\n")))
(delete-process server)))
+(ert-deftest echo-server-with-local-ipv4 ()
+ (let* ((server (make-server 'local 'ipv4))
+ (port (aref (process-contact server :local) 4))
+ (proc (make-network-process :name "foo"
+ :buffer (generate-new-buffer "*foo*")
+ :host 'local
+ :family 'ipv4
+ :service port)))
+ (with-current-buffer (process-buffer proc)
+ (process-send-string proc "echo foo")
+ (sleep-for 0.1)
+ (should (equal (buffer-string) "foo\n")))
+ (delete-process server)))
+
+(ert-deftest echo-server-with-local-ipv6 ()
+ (skip-unless (featurep 'make-network-process '(:family ipv6)))
+ (let ((server (ignore-errors (make-server 'local 'ipv6))))
+ (skip-unless server)
+ (let* ((port (aref (process-contact server :local) 8))
+ (proc (make-network-process :name "foo"
+ :buffer (generate-new-buffer "*foo*")
+ :host 'local
+ :family 'ipv6
+ :service port)))
+ (with-current-buffer (process-buffer proc)
+ (process-send-string proc "echo foo")
+ (sleep-for 0.1)
+ (should (equal (buffer-string) "foo\n")))
+ (delete-process server))))
+
(ert-deftest echo-server-with-ip ()
(let* ((server (make-server 'local))
(port (aref (process-contact server :local) 4))
@@ -159,16 +243,13 @@
(should (equal (buffer-string) "foo\n")))
(delete-process server)))
-(defconst network-stream-tests--datadir
- (expand-file-name "test/data/net" source-directory))
-
(defun make-tls-server (port)
(start-process "gnutls" (generate-new-buffer "*tls*")
"gnutls-serv" "--http"
"--x509keyfile"
- (concat network-stream-tests--datadir "/key.pem")
+ (ert-resource-file "key.pem")
"--x509certfile"
- (concat network-stream-tests--datadir "/cert.pem")
+ (ert-resource-file "cert.pem")
"--port" (format "%s" port)))
(ert-deftest connect-to-tls-ipv4-wait ()
@@ -214,6 +295,7 @@
(skip-unless (gnutls-available-p))
(let ((server (make-tls-server 44331))
(times 0)
+ (network-security-level 'low)
proc status)
(unwind-protect
(progn
@@ -227,6 +309,7 @@
:name "bar"
:buffer (generate-new-buffer "*foo*")
:nowait t
+ :family 'ipv4
:tls-parameters
(cons 'gnutls-x509pki
(gnutls-boot-parameters
@@ -257,6 +340,7 @@
(skip-unless (featurep 'make-network-process '(:family ipv6)))
(let ((server (make-tls-server 44333))
(times 0)
+ (network-security-level 'low)
proc status)
(unwind-protect
(progn
@@ -294,4 +378,417 @@
(setq issuer (split-string issuer ","))
(should (equal (nth 3 issuer) "O=Emacs Test Servicess LLC")))))
+(ert-deftest open-network-stream-tls-wait ()
+ (skip-unless (executable-find "gnutls-serv"))
+ (skip-unless (gnutls-available-p))
+ (let ((server (make-tls-server 44334))
+ (times 0)
+ (network-security-level 'low)
+ proc status)
+ (unwind-protect
+ (progn
+ (sleep-for 1)
+ (with-current-buffer (process-buffer server)
+ (message "gnutls-serv: %s" (buffer-string)))
+
+ ;; It takes a while for gnutls-serv to start.
+ (while (and (null (ignore-errors
+ (setq proc (open-network-stream
+ "bar"
+ (generate-new-buffer "*foo*")
+ "localhost"
+ 44334
+ :type 'tls
+ :nowait nil))))
+ (< (setq times (1+ times)) 10))
+ (sit-for 0.1))
+ (should proc)
+ (skip-unless (not (eq (process-status proc) 'connect))))
+ (if (process-live-p server) (delete-process server)))
+ (setq status (gnutls-peer-status proc))
+ (should (consp status))
+ (delete-process proc)
+ ;; This sleep-for is needed for the native MS-Windows build. If
+ ;; it is removed, the next test mysteriously fails because the
+ ;; initial part of the echo is not received.
+ (sleep-for 0.1)
+ (let ((issuer (plist-get (plist-get status :certificate) :issuer)))
+ (should (stringp issuer))
+ (setq issuer (split-string issuer ","))
+ (should (equal (nth 3 issuer) "O=Emacs Test Servicess LLC")))))
+
+(ert-deftest open-network-stream-tls-nowait ()
+ (skip-unless (executable-find "gnutls-serv"))
+ (skip-unless (gnutls-available-p))
+ (let ((server (make-tls-server 44335))
+ (times 0)
+ (network-security-level 'low)
+ proc status)
+ (unwind-protect
+ (progn
+ (sleep-for 1)
+ (with-current-buffer (process-buffer server)
+ (message "gnutls-serv: %s" (buffer-string)))
+
+ ;; It takes a while for gnutls-serv to start.
+ (while (and (null (ignore-errors
+ (setq proc (open-network-stream
+ "bar"
+ (generate-new-buffer "*foo*")
+ "localhost"
+ 44335
+ :type 'tls
+ :nowait t))))
+ (< (setq times (1+ times)) 10))
+ (sit-for 0.1))
+ (should proc)
+ (setq times 0)
+ (while (and (eq (process-status proc) 'connect)
+ (< (setq times (1+ times)) 10))
+ (sit-for 0.1))
+ (skip-unless (not (eq (process-status proc) 'connect))))
+ (if (process-live-p server) (delete-process server)))
+ (setq status (gnutls-peer-status proc))
+ (should (consp status))
+ (delete-process proc)
+ ;; This sleep-for is needed for the native MS-Windows build. If
+ ;; it is removed, the next test mysteriously fails because the
+ ;; initial part of the echo is not received.
+ (sleep-for 0.1)
+ (let ((issuer (plist-get (plist-get status :certificate) :issuer)))
+ (should (stringp issuer))
+ (setq issuer (split-string issuer ","))
+ (should (equal (nth 3 issuer) "O=Emacs Test Servicess LLC")))))
+
+(ert-deftest open-network-stream-tls ()
+ (skip-unless (executable-find "gnutls-serv"))
+ (skip-unless (gnutls-available-p))
+ (let ((server (make-tls-server 44336))
+ (times 0)
+ (network-security-level 'low)
+ proc status)
+ (unwind-protect
+ (progn
+ (sleep-for 1)
+ (with-current-buffer (process-buffer server)
+ (message "gnutls-serv: %s" (buffer-string)))
+
+ ;; It takes a while for gnutls-serv to start.
+ (while (and (null (ignore-errors
+ (setq proc (open-network-stream
+ "bar"
+ (generate-new-buffer "*foo*")
+ "localhost"
+ 44336
+ :type 'tls))))
+ (< (setq times (1+ times)) 10))
+ (sit-for 0.1))
+ (should proc)
+ (skip-unless (not (eq (process-status proc) 'connect))))
+ (if (process-live-p server) (delete-process server)))
+ (setq status (gnutls-peer-status proc))
+ (should (consp status))
+ (delete-process proc)
+ ;; This sleep-for is needed for the native MS-Windows build. If
+ ;; it is removed, the next test mysteriously fails because the
+ ;; initial part of the echo is not received.
+ (sleep-for 0.1)
+ (let ((issuer (plist-get (plist-get status :certificate) :issuer)))
+ (should (stringp issuer))
+ (setq issuer (split-string issuer ","))
+ (should (equal (nth 3 issuer) "O=Emacs Test Servicess LLC")))))
+
+(ert-deftest open-network-stream-tls-nocert ()
+ (skip-unless (executable-find "gnutls-serv"))
+ (skip-unless (gnutls-available-p))
+ (let ((server (make-tls-server 44337))
+ (times 0)
+ (network-security-level 'low)
+ proc status)
+ (unwind-protect
+ (progn
+ (sleep-for 1)
+ (with-current-buffer (process-buffer server)
+ (message "gnutls-serv: %s" (buffer-string)))
+
+ ;; It takes a while for gnutls-serv to start.
+ (while (and (null (ignore-errors
+ (setq proc (open-network-stream
+ "bar"
+ (generate-new-buffer "*foo*")
+ "localhost"
+ 44337
+ :type 'tls
+ :client-certificate nil))))
+ (< (setq times (1+ times)) 10))
+ (sit-for 0.1))
+ (should proc)
+ (skip-unless (not (eq (process-status proc) 'connect))))
+ (if (process-live-p server) (delete-process server)))
+ (setq status (gnutls-peer-status proc))
+ (should (consp status))
+ (delete-process proc)
+ ;; This sleep-for is needed for the native MS-Windows build. If
+ ;; it is removed, the next test mysteriously fails because the
+ ;; initial part of the echo is not received.
+ (sleep-for 0.1)
+ (let ((issuer (plist-get (plist-get status :certificate) :issuer)))
+ (should (stringp issuer))
+ (setq issuer (split-string issuer ","))
+ (should (equal (nth 3 issuer) "O=Emacs Test Servicess LLC")))))
+
+(ert-deftest open-gnutls-stream-new-api-default ()
+ (skip-unless (executable-find "gnutls-serv"))
+ (skip-unless (gnutls-available-p))
+ (let ((server (make-tls-server 44665))
+ (times 0)
+ proc status)
+ (unwind-protect
+ (progn
+ (sleep-for 1)
+ (with-current-buffer (process-buffer server)
+ (message "gnutls-serv: %s" (buffer-string)))
+
+ ;; It takes a while for gnutls-serv to start.
+ (while (and (null (ignore-errors
+ (setq proc (open-gnutls-stream
+ "bar"
+ (generate-new-buffer "*foo*")
+ "localhost"
+ 44665))))
+ (< (setq times (1+ times)) 10))
+ (sit-for 0.1))
+ (should proc)
+ (if (process-live-p server) (delete-process server)))
+ (setq status (gnutls-peer-status proc))
+ (should (consp status))
+ (delete-process proc)
+ ;; This sleep-for is needed for the native MS-Windows build. If
+ ;; it is removed, the next test mysteriously fails because the
+ ;; initial part of the echo is not received.
+ (sleep-for 0.1)
+ (let ((issuer (plist-get (plist-get status :certificate) :issuer)))
+ (should (stringp issuer))
+ (setq issuer (split-string issuer ","))
+ (should (equal (nth 3 issuer) "O=Emacs Test Servicess LLC"))))))
+
+(ert-deftest open-gnutls-stream-new-api-wait ()
+ (skip-unless (executable-find "gnutls-serv"))
+ (skip-unless (gnutls-available-p))
+ (let ((server (make-tls-server 44666))
+ (times 0)
+ proc status)
+ (unwind-protect
+ (progn
+ (sleep-for 1)
+ (with-current-buffer (process-buffer server)
+ (message "gnutls-serv: %s" (buffer-string)))
+
+ ;; It takes a while for gnutls-serv to start.
+ (while (and (null (ignore-errors
+ (setq proc (open-gnutls-stream
+ "bar"
+ (generate-new-buffer "*foo*")
+ "localhost"
+ 44666
+ (list :nowait nil)))))
+ (< (setq times (1+ times)) 10))
+ (sit-for 0.1))
+ (should proc)
+ (if (process-live-p server) (delete-process server)))
+ (setq status (gnutls-peer-status proc))
+ (should (consp status))
+ (delete-process proc)
+ ;; This sleep-for is needed for the native MS-Windows build. If
+ ;; it is removed, the next test mysteriously fails because the
+ ;; initial part of the echo is not received.
+ (sleep-for 0.1)
+ (let ((issuer (plist-get (plist-get status :certificate) :issuer)))
+ (should (stringp issuer))
+ (setq issuer (split-string issuer ","))
+ (should (equal (nth 3 issuer) "O=Emacs Test Servicess LLC"))))))
+
+(ert-deftest open-gnutls-stream-old-api-wait ()
+ (skip-unless (executable-find "gnutls-serv"))
+ (skip-unless (gnutls-available-p))
+ (let ((server (make-tls-server 44667))
+ (times 0)
+ (nowait nil) ; Workaround Bug#47080
+ proc status)
+ (unwind-protect
+ (progn
+ (sleep-for 1)
+ (with-current-buffer (process-buffer server)
+ (message "gnutls-serv: %s" (buffer-string)))
+
+ ;; It takes a while for gnutls-serv to start.
+ (while (and (null (ignore-errors
+ (setq proc (open-gnutls-stream
+ "bar"
+ (generate-new-buffer "*foo*")
+ "localhost"
+ 44667
+ nowait))))
+ (< (setq times (1+ times)) 10))
+ (sit-for 0.1))
+ (should proc)
+ (if (process-live-p server) (delete-process server)))
+ (setq status (gnutls-peer-status proc))
+ (should (consp status))
+ (delete-process proc)
+ ;; This sleep-for is needed for the native MS-Windows build. If
+ ;; it is removed, the next test mysteriously fails because the
+ ;; initial part of the echo is not received.
+ (sleep-for 0.1)
+ (let ((issuer (plist-get (plist-get status :certificate) :issuer)))
+ (should (stringp issuer))
+ (setq issuer (split-string issuer ","))
+ (should (equal (nth 3 issuer) "O=Emacs Test Servicess LLC"))))))
+
+(ert-deftest open-gnutls-stream-new-api-nowait ()
+ (skip-unless (executable-find "gnutls-serv"))
+ (skip-unless (gnutls-available-p))
+ (let ((server (make-tls-server 44668))
+ (times 0)
+ (network-security-level 'low)
+ proc status)
+ (unwind-protect
+ (progn
+ (sleep-for 1)
+ (with-current-buffer (process-buffer server)
+ (message "gnutls-serv: %s" (buffer-string)))
+
+ ;; It takes a while for gnutls-serv to start.
+ (while (and (null (ignore-errors
+ (setq proc (open-gnutls-stream
+ "bar"
+ (generate-new-buffer "*foo*")
+ "localhost"
+ 44668
+ (list :nowait t)))))
+ (< (setq times (1+ times)) 10))
+ (sit-for 0.1))
+ (should proc)
+ (setq times 0)
+ (while (and (eq (process-status proc) 'connect)
+ (< (setq times (1+ times)) 10))
+ (sit-for 0.1))
+ (skip-unless (not (eq (process-status proc) 'connect))))
+ (if (process-live-p server) (delete-process server)))
+ (setq status (gnutls-peer-status proc))
+ (should (consp status))
+ (delete-process proc)
+ (let ((issuer (plist-get (plist-get status :certificate) :issuer)))
+ (should (stringp issuer))
+ (setq issuer (split-string issuer ","))
+ (should (equal (nth 3 issuer) "O=Emacs Test Servicess LLC")))))
+
+(ert-deftest open-gnutls-stream-old-api-nowait ()
+ (skip-unless (executable-find "gnutls-serv"))
+ (skip-unless (gnutls-available-p))
+ (let ((server (make-tls-server 44669))
+ (times 0)
+ (network-security-level 'low)
+ (nowait t)
+ proc status)
+ (unwind-protect
+ (progn
+ (sleep-for 1)
+ (with-current-buffer (process-buffer server)
+ (message "gnutls-serv: %s" (buffer-string)))
+
+ ;; It takes a while for gnutls-serv to start.
+ (while (and (null (ignore-errors
+ (setq proc (open-gnutls-stream
+ "bar"
+ (generate-new-buffer "*foo*")
+ "localhost"
+ 44669
+ nowait))))
+ (< (setq times (1+ times)) 10))
+ (sit-for 0.1))
+ (should proc)
+ (setq times 0)
+ (while (and (eq (process-status proc) 'connect)
+ (< (setq times (1+ times)) 10))
+ (sit-for 0.1))
+ (skip-unless (not (eq (process-status proc) 'connect))))
+ (if (process-live-p server) (delete-process server)))
+ (setq status (gnutls-peer-status proc))
+ (should (consp status))
+ (delete-process proc)
+ (let ((issuer (plist-get (plist-get status :certificate) :issuer)))
+ (should (stringp issuer))
+ (setq issuer (split-string issuer ","))
+ (should (equal (nth 3 issuer) "O=Emacs Test Servicess LLC")))))
+
+(ert-deftest open-gnutls-stream-new-api-errors ()
+ (skip-unless (gnutls-available-p))
+ (should-error
+ (open-gnutls-stream
+ "bar"
+ (generate-new-buffer "*foo*")
+ "localhost"
+ 44777
+ (list t)))
+ (should-error
+ (open-gnutls-stream
+ "bar"
+ (generate-new-buffer "*foo*")
+ "localhost"
+ 44777
+ (vector :nowait t))))
+
+(ert-deftest check-network-process-coding-system-bind ()
+ "Check that binding coding-system-for-{read,write} works."
+ (let* ((coding-system-for-read 'binary)
+ (coding-system-for-write 'utf-8-unix)
+ (server
+ (make-network-process
+ :name "server"
+ :server t
+ :noquery t
+ :family 'ipv4
+ :service t
+ :host 'local))
+ (coding (process-coding-system server)))
+ (should (eq (car coding) 'binary))
+ (should (eq (cdr coding) 'utf-8-unix))
+ (delete-process server)))
+
+(ert-deftest check-network-process-coding-system-no-override ()
+ "Check that coding-system-for-{read,write} is not overridden by :coding nil."
+ (let* ((coding-system-for-read 'binary)
+ (coding-system-for-write 'utf-8-unix)
+ (server
+ (make-network-process
+ :name "server"
+ :server t
+ :noquery t
+ :family 'ipv4
+ :service t
+ :coding nil
+ :host 'local))
+ (coding (process-coding-system server)))
+ (should (eq (car coding) 'binary))
+ (should (eq (cdr coding) 'utf-8-unix))
+ (delete-process server)))
+
+(ert-deftest check-network-process-coding-system-override ()
+ "Check that :coding non-nil overrides coding-system-for-{read,write}."
+ (let* ((coding-system-for-read 'binary)
+ (coding-system-for-write 'utf-8-unix)
+ (server
+ (make-network-process
+ :name "server"
+ :server t
+ :noquery t
+ :family 'ipv4
+ :service t
+ :coding 'georgian-academy
+ :host 'local))
+ (coding (process-coding-system server)))
+ (should (eq (car coding) 'georgian-academy))
+ (should (eq (cdr coding) 'georgian-academy))
+ (delete-process server)))
;;; network-stream-tests.el ends here
diff --git a/test/lisp/net/newsticker-tests.el b/test/lisp/net/newsticker-tests.el
index def7c2aebce..2dc92566a61 100644
--- a/test/lisp/net/newsticker-tests.el
+++ b/test/lisp/net/newsticker-tests.el
@@ -1,6 +1,6 @@
-;;; newsticker-testsuite.el --- Test suite for newsticker.
+;;; newsticker-tests.el --- Test suite for newsticker. -*- lexical-binding:t -*-
-;; Copyright (C) 2003-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2022 Free Software Foundation, Inc.
;; Author: Ulf Jasper <ulf.jasper@web.de>
;; Keywords: News, RSS, Atom
diff --git a/test/lisp/net/nsm-tests.el b/test/lisp/net/nsm-tests.el
new file mode 100644
index 00000000000..e0536320cc9
--- /dev/null
+++ b/test/lisp/net/nsm-tests.el
@@ -0,0 +1,79 @@
+;;; nsm-tests.el --- tests for network security manager -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2019-2022 Free Software Foundation, Inc.
+
+;; Author: Robert Pluim <rpluim@gmail.com>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+
+;;; Code:
+
+(require 'nsm)
+(eval-when-compile (require 'cl-lib))
+
+(ert-deftest nsm-check-local-subnet-ipv4 ()
+ "Check that nsm can be avoided for local subnets."
+ (let ((local-ip '[172 26 128 160 0])
+ (mask '[255 255 255 0 0])
+
+ (wrong-length-mask '[255 255 255])
+ (wrong-mask '[255 255 255 255 0])
+ (remote-ip-yes '[172 26 128 161 0])
+ (remote-ip-no '[172 26 129 161 0]))
+
+ (should (eq t (nsm-network-same-subnet local-ip mask remote-ip-yes)))
+ (should (eq nil (nsm-network-same-subnet local-ip mask remote-ip-no)))
+ (should-error (nsm-network-same-subnet local-ip wrong-length-mask remote-ip-yes))
+ (should (eq nil (nsm-network-same-subnet local-ip wrong-mask remote-ip-yes)))
+ (should (eq t (nsm-should-check "google.com")))
+ (should (eq t (nsm-should-check "127.0.0.1")))
+ (should (eq t (nsm-should-check "localhost")))
+ (let ((nsm-trust-local-network t))
+ (should (eq t (nsm-should-check "google.com")))
+ (should (eq nil (nsm-should-check "127.0.0.1")))
+ (should (eq nil (nsm-should-check "localhost"))))))
+
+;; This will need updating when IANA assign more IPv6 global ranges.
+(defun ipv6-is-available ()
+ (and (featurep 'make-network-process '(:family ipv6))
+ (cl-rassoc-if
+ (lambda (elt)
+ (and (eq 9 (length elt))
+ (= (logand (aref elt 0) #xe000) #x2000)))
+ (network-interface-list))))
+
+(ert-deftest nsm-check-local-subnet-ipv6 ()
+ (skip-unless (ipv6-is-available))
+ (let ((local-ip '[123 456 789 11 172 26 128 160 0])
+ (mask '[255 255 255 255 255 255 255 0 0])
+
+ (wrong-length-mask '[255 255 255 255 255 255 255])
+ (wrong-mask '[255 255 255 255 255 255 255 255 0])
+ (remote-ip-yes '[123 456 789 11 172 26 128 161 0])
+ (remote-ip-no '[123 456 789 11 172 26 129 161 0]))
+ (should (eq t (nsm-network-same-subnet local-ip mask remote-ip-yes)))
+ (should (eq nil (nsm-network-same-subnet local-ip mask remote-ip-no)))
+ (should-error (nsm-network-same-subnet local-ip wrong-length-mask remote-ip-yes))
+ (should (eq nil (nsm-network-same-subnet local-ip wrong-mask remote-ip-yes))))
+ (should (eq t (nsm-should-check "::1")))
+ (let ((nsm-trust-local-network t))
+ (should (eq nil (nsm-should-check "::1")))))
+
+
+;;; nsm-tests.el ends here
diff --git a/test/lisp/net/ntlm-resources/authinfo b/test/lisp/net/ntlm-resources/authinfo
new file mode 100644
index 00000000000..698391e9313
--- /dev/null
+++ b/test/lisp/net/ntlm-resources/authinfo
@@ -0,0 +1 @@
+machine localhost port http user ntlm password ntlm
diff --git a/test/lisp/net/ntlm-tests.el b/test/lisp/net/ntlm-tests.el
new file mode 100644
index 00000000000..a02d97f19a8
--- /dev/null
+++ b/test/lisp/net/ntlm-tests.el
@@ -0,0 +1,427 @@
+;;; ntlm-tests.el --- tests for ntlm.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Run this with `NTLM_TESTS_VERBOSE=1' to get verbose debugging.
+
+;;; Code:
+
+(require 'ert)
+(require 'ert-x)
+(require 'ntlm)
+
+(defsubst ntlm-tests-message (format-string &rest arguments)
+ "Print a message conditional on an environment variable being set.
+FORMAT-STRING and ARGUMENTS are passed to the message function."
+ (when (getenv "NTLM_TESTS_VERBOSE")
+ (apply #'message (concat "ntlm-tests: " format-string) arguments)))
+
+
+;; This is the Lisp bignum implementation of `ntlm--time-to-timestamp',
+;; for reference.
+
+(defun ntlm-tests--time-to-timestamp (time)
+ "Convert TIME to an NTLMv2 timestamp.
+Return a unibyte string representing the number of tenths of a
+microsecond since January 1, 1601 as a 64-bit little-endian
+signed integer. TIME must be on the form (HIGH LOW USEC PSEC)."
+ (let* ((s (+ (ash (nth 0 time) 16) (nth 1 time)))
+ (us (nth 2 time))
+ (ps (nth 3 time))
+ (tenths-of-us-since-jan-1-1601
+ (+ (* s 10000000) (* us 10) (/ ps 100000)
+ ;; tenths of microseconds between 1601-01-01 and 1970-01-01
+ 116444736000000000)))
+ (apply #'unibyte-string
+ (mapcar (lambda (i)
+ (logand (ash tenths-of-us-since-jan-1-1601 (* i -8))
+ #xff))
+ (number-sequence 0 7)))))
+
+(ert-deftest ntlm-time-to-timestamp ()
+ ;; Verify poor man's bignums in implementation that can run on Emacs < 27.1.
+ (let ((time '(24471 63910 412962 0)))
+ (should (equal (ntlm--time-to-timestamp time)
+ (ntlm-tests--time-to-timestamp time))))
+ (let ((time '(397431 65535 999999 999999)))
+ (should (equal (ntlm--time-to-timestamp time)
+ (ntlm-tests--time-to-timestamp time)))))
+
+(defvar ntlm-tests--username-oem "ntlm"
+ "The username for NTLM authentication tests, in OEM string encoding.")
+(defvar ntlm-tests--username-unicode
+ (ntlm-ascii2unicode ntlm-tests--username-oem
+ (length ntlm-tests--username-oem))
+ "The username for NTLM authentication tests, in Unicode string encoding.")
+
+(defvar ntlm-tests--password "ntlm"
+ "The password used for NTLM authentication tests.")
+
+(defvar ntlm-tests--client-supports-unicode nil
+ "Non-nil if client supports Unicode strings.
+If client only supports OEM strings, nil.")
+
+(defvar ntlm-tests--challenge nil "The global random challenge.")
+
+(defun ntlm-server-build-type-2 ()
+ "Return an NTLM Type 2 message as a string.
+This string will be returned from the NTLM server to the NTLM client."
+ (let ((target (if ntlm-tests--client-supports-unicode
+ (ntlm-ascii2unicode "DOMAIN" (length "DOMAIN"))
+ "DOMAIN"))
+ (target-information ntlm-tests--password)
+ ;; Flag byte 1 flags.
+ (_negotiate-unicode 1)
+ (negotiate-oem 2)
+ (request-target 4)
+ ;; Flag byte 2 flags.
+ (negotiate-ntlm 2)
+ (_negotiate-local-call 4)
+ (_negotiate-always-sign 8)
+ ;; Flag byte 3 flags.
+ (_target-type-domain 1)
+ (_target-type-server 2)
+ (target-type-share 4)
+ (_negotiate-ntlm2-key 8)
+ (negotiate-target-information 128)
+ ;; Flag byte 4 flags, unused.
+ (_negotiate-128 32)
+ (_negotiate-56 128))
+ (concat
+ ;; Signature.
+ "NTLMSSP" (unibyte-string 0)
+ ;; Type 2.
+ (unibyte-string 2 0 0 0)
+ ;; Target length
+ (unibyte-string (length target) 0)
+ ;; Target allocated space.
+ (unibyte-string (length target) 0)
+ ;; Target offset.
+ (unibyte-string 48 0 0 0)
+ ;; Flags.
+ ;; Flag byte 1.
+ ;; Tell the client that this test server only supports OEM
+ ;; strings. This test server will handle Unicode strings
+ ;; anyway though.
+ (unibyte-string (logior negotiate-oem request-target))
+ ;; Flag byte 2.
+ (unibyte-string negotiate-ntlm)
+ ;; Flag byte 3.
+ (unibyte-string (logior negotiate-target-information target-type-share))
+ ;; Flag byte 4. Not sure what 2 means here.
+ (unibyte-string 2)
+ ;; Challenge. Set this to (unibyte-string 1 2 3 4 5 6 7 8)
+ ;; instead of (ntlm-generate-nonce) to hold constant for
+ ;; debugging.
+ (setq ntlm-tests--challenge (ntlm-generate-nonce))
+ ;; Context.
+ (make-string 8 0)
+ (unibyte-string (length target-information) 0)
+ (unibyte-string (length target-information) 0)
+ (unibyte-string 54 0 0 0)
+ target
+ target-information)))
+
+(defun ntlm-server-hash (challenge blob username password)
+ "Hash CHALLENGE, BLOB, USERNAME and PASSWORD for a Type 3 check."
+ (hmac-md5 (concat challenge blob)
+ (hmac-md5 (concat
+ (upcase
+ ;; This calculation always uses
+ ;; Unicode username, even when the
+ ;; server only supports OEM strings.
+ (ntlm-ascii2unicode username (length username))) "")
+ (cadr (ntlm-get-password-hashes password)))))
+
+(defun ntlm-server-check-authorization (authorization-string)
+ "Return t if AUTHORIZATION-STRING correctly authenticates the user."
+ (let* ((binary (base64-decode-string
+ (caddr (split-string authorization-string " "))))
+ (_lm-response-length (md4-unpack-int16 (substring binary 12 14)))
+ (_lm-response-offset
+ (cdr (md4-unpack-int32 (substring binary 16 20))))
+ (ntlm-response-length (md4-unpack-int16 (substring binary 20 22)))
+ (ntlm-response-offset
+ (cdr (md4-unpack-int32 (substring binary 24 28))))
+ (ntlm-hash
+ (substring binary ntlm-response-offset (+ ntlm-response-offset 16)))
+ (username-length (md4-unpack-int16 (substring binary 36 38)))
+ (username-offset (cdr (md4-unpack-int32 (substring binary 40 44))))
+ (username (substring binary username-offset
+ (+ username-offset username-length))))
+ (if (equal ntlm-response-length 24)
+ (let* ((expected
+ (ntlm-smb-owf-encrypt
+ (cadr (ntlm-get-password-hashes ntlm-tests--password))
+ ntlm-tests--challenge))
+ (received (substring binary ntlm-response-offset
+ (+ ntlm-response-offset
+ ntlm-response-length))))
+ (ntlm-tests-message "Got NTLMv1 response:")
+ (ntlm-tests-message "Expected hash: ===%S===" expected)
+ (ntlm-tests-message "Got hash: ===%S===" received)
+ (ntlm-tests-message "Expected username: ===%S==="
+ ntlm-tests--username-oem)
+ (ntlm-tests-message "Got username: ===%S===" username)
+ (and (or (equal username ntlm-tests--username-oem)
+ (equal username ntlm-tests--username-unicode))
+ (equal expected received)))
+ (let* ((ntlm-response-blob
+ (substring binary (+ ntlm-response-offset 16)
+ (+ (+ ntlm-response-offset 16)
+ (- ntlm-response-length 16))))
+ (_ntlm-timestamp (substring ntlm-response-blob 8 16))
+ (_ntlm-nonce (substring ntlm-response-blob 16 24))
+ (_target-length (md4-unpack-int16 (substring binary 28 30)))
+ (_target-offset
+ (cdr (md4-unpack-int32 (substring binary 32 36))))
+ (_workstation-length (md4-unpack-int16 (substring binary 44 46)))
+ (_workstation-offset
+ (cdr (md4-unpack-int32 (substring binary 48 52)))))
+ (cond
+ ;; This test server claims to only support OEM strings,
+ ;; but also checks Unicode strings.
+ ((or (equal username ntlm-tests--username-oem)
+ (equal username ntlm-tests--username-unicode))
+ (let* ((password ntlm-tests--password)
+ (ntlm-hash-from-type-3 (ntlm-server-hash
+ ntlm-tests--challenge
+ ntlm-response-blob
+ ;; Always -oem since
+ ;; `ntlm-server-hash'
+ ;; always converts it to
+ ;; Unicode.
+ ntlm-tests--username-oem
+ password)))
+ (ntlm-tests-message "Got NTLMv2 response:")
+ (ntlm-tests-message "Expected hash: ==%S==" ntlm-hash)
+ (ntlm-tests-message "Got hash: ==%S==" ntlm-hash-from-type-3)
+ (ntlm-tests-message "Expected username: ===%S==="
+ ntlm-tests--username-oem)
+ (ntlm-tests-message " or username: ===%S==="
+ ntlm-tests--username-unicode)
+ (ntlm-tests-message "Got username: ===%S===" username)
+ (equal ntlm-hash ntlm-hash-from-type-3)))
+ (t
+ nil))))))
+
+(require 'eieio)
+(require 'cl-lib)
+
+;; Silence some byte-compiler warnings that occur when
+;; web-server/web-server.el is not found.
+(eval-when-compile (cl-pushnew 'headers eieio--known-slot-names)
+ (cl-pushnew 'process eieio--known-slot-names))
+(declare-function ws-send nil)
+(declare-function ws-parse-request nil)
+(declare-function ws-start nil)
+(declare-function ws-stop-all nil)
+
+(eval-and-compile
+ (push (expand-file-name "../elpa/packages/web-server/" source-directory)
+ load-path)
+ (require 'web-server nil t)
+ (push (expand-file-name "../elpa/packages/url-http-ntlm/" source-directory)
+ load-path)
+ (require 'url-http-ntlm nil t))
+
+(defun ntlm-server-do-token (request _process)
+ "Process an NTLM client's REQUEST.
+PROCESS is unused."
+ (with-slots (process headers) request
+ (let* ((header-alist (cdr headers))
+ (authorization-header (assoc ':AUTHORIZATION header-alist))
+ (authorization-string (cdr authorization-header)))
+ (if (and (stringp authorization-string)
+ (string-match "NTLM " authorization-string))
+ (let* ((challenge (substring authorization-string (match-end 0)))
+ (binary (base64-decode-string challenge))
+ (type (aref binary 8))
+ ;; Flag byte 1 flags.
+ (negotiate-unicode 1)
+ (negotiate-oem 2)
+ (flags-byte-1 (aref binary 12))
+ (client-supports-unicode
+ (not (zerop (logand flags-byte-1 negotiate-unicode))))
+ (client-supports-oem
+ (not (zerop (logand flags-byte-1 negotiate-oem))))
+ (connection-header (assoc ':CONNECTION header-alist))
+ (_keep-alive
+ (when connection-header (cdr connection-header)))
+ (response
+ (cl-case type
+ (1
+ ;; Return Type 2 message.
+ (when (and (not client-supports-unicode)
+ (not client-supports-oem))
+ (warn (concat
+ "Weird client supports neither Unicode"
+ " nor OEM strings, using OEM.")))
+ (setq ntlm-tests--client-supports-unicode
+ client-supports-unicode)
+ (concat
+ "HTTP/1.1 401 Unauthorized\r\n"
+ "WWW-Authenticate: NTLM "
+ (base64-encode-string
+ (ntlm-server-build-type-2) t) "\r\n"
+ "WWW-Authenticate: Negotiate\r\n"
+ "WWW-Authenticate: Basic realm=\"domain\"\r\n"
+ "Content-Length: 0\r\n\r\n"))
+ (3
+ (if (ntlm-server-check-authorization
+ authorization-string)
+ "HTTP/1.1 200 OK\r\n\r\nAuthenticated.\r\n"
+ (progn
+ (if process
+ (set-process-filter process nil)
+ (error "Type 3 message found first?"))
+ (concat "HTTP/1.1 401 Unauthorized\r\n\r\n"
+ "Access Denied.\r\n")))))))
+ (if response
+ (ws-send process response)
+ (when process
+ (set-process-filter process nil)))
+ (when (equal type 3)
+ (set-process-filter process nil)
+ (process-send-eof process)))
+ (progn
+ ;; Did not get NTLM anything.
+ (set-process-filter process nil)
+ (process-send-eof process)
+ (concat "HTTP/1.1 401 Unauthorized\r\n\r\n"
+ "Access Denied.\r\n"))))))
+
+(defun ntlm-server-filter (process string)
+ "Read from PROCESS a STRING and treat it as a request from an NTLM client."
+ (let ((request (make-instance 'ws-request
+ :process process :pending string)))
+ (if (ws-parse-request request)
+ (ntlm-server-do-token request process)
+ (error "Failed to parse request"))))
+
+(defun ntlm-server-handler (request)
+ "Handle an HTTP REQUEST."
+ (with-slots (process headers) request
+ (let* ((header-alist (cdr headers))
+ (authorization-header (assoc ':AUTHORIZATION header-alist))
+ (connection-header (assoc ':CONNECTION header-alist))
+ (keep-alive (when connection-header (cdr connection-header)))
+ (response (concat
+ "HTTP/1.1 401 Unauthorized\r\n"
+ "WWW-Authenticate: Negotiate\r\n"
+ "WWW-Authenticate: NTLM\r\n"
+ "WWW-Authenticate: Basic realm=\"domain\"\r\n"
+ "Content-Length: 0\r\n\r\n")))
+ (if (null authorization-header)
+ ;; Tell client to use NTLM. Firefox will create a new
+ ;; connection.
+ (progn
+ (process-send-string process response)
+ (process-send-eof process))
+ (progn
+ (ntlm-server-do-token request nil)
+ (set-process-filter process #'ntlm-server-filter)
+ (if (equal (upcase keep-alive) "KEEP-ALIVE")
+ :keep-alive
+ (error "NTLM server expects keep-alive connection header")))))))
+
+(defun ntlm-server-start ()
+ "Start an NTLM server on port 8080 for testing."
+ (ws-start 'ntlm-server-handler 8080))
+
+(defun ntlm-server-stop ()
+ "Stop the NTLM server."
+ (ws-stop-all))
+
+(defvar ntlm-tests--result-buffer nil "Final NTLM result buffer.")
+
+(require 'url)
+
+(defun ntlm-tests--url-retrieve-internal-around (original &rest arguments)
+ "Save the result buffer from a `url-retrieve-internal' to a global variable.
+ORIGINAL is the original `url-retrieve-internal' function and
+ARGUMENTS are passed to it."
+ (setq ntlm-tests--result-buffer (apply original arguments)))
+
+(defun ntlm-tests--authenticate ()
+ "Authenticate using credentials from the authinfo resource file."
+ (setq ntlm-tests--result-buffer nil)
+ (let ((auth-sources (list (ert-resource-file "authinfo")))
+ (auth-source-do-cache nil)
+ (auth-source-debug (when (getenv "NTLM_TESTS_VERBOSE") 'trivia)))
+ (ntlm-tests-message "Using auth-sources: %S" auth-sources)
+ (url-retrieve-synchronously "http://localhost:8080"))
+ (sleep-for 0.1)
+ (ntlm-tests-message "Results are in: %S" ntlm-tests--result-buffer)
+ (with-current-buffer ntlm-tests--result-buffer
+ (buffer-string)))
+
+(defun ntlm-tests--start-server-authenticate-stop-server ()
+ "Start an NTLM server, authenticate against it, then stop the server."
+ (advice-add #'url-retrieve-internal
+ :around #'ntlm-tests--url-retrieve-internal-around)
+ (ntlm-server-stop)
+ (ntlm-server-start)
+ (let ((result (ntlm-tests--authenticate)))
+ (advice-remove #'url-retrieve-internal
+ #'ntlm-tests--url-retrieve-internal-around)
+ (ntlm-server-stop)
+ result))
+
+(defvar ntlm-tests--successful-result
+ (concat "HTTP/1.1 200 OK\n\nAuthenticated." (unibyte-string 13) "\n")
+ "Expected result of successful NTLM authentication.")
+
+(require 'find-func)
+(defun ntlm-tests--ensure-ws-parse-ntlm-support ()
+ "Ensure NTLM special-case in `ws-parse'."
+ (let* ((hit (find-function-search-for-symbol
+ 'ws-parse nil (locate-file "web-server.el" load-path)))
+ (buffer (car hit))
+ (position (cdr hit)))
+ (with-current-buffer buffer
+ (goto-char position)
+ (search-forward-regexp
+ ":NTLM" (save-excursion (forward-sexp) (point)) t))))
+
+(require 'lisp-mnt)
+(defvar ntlm-tests--dependencies-present
+ (and (featurep 'url-http-ntlm)
+ (version<= "2.0.4"
+ (lm-version (locate-file "url-http-ntlm.el" load-path)))
+ (featurep 'web-server)
+ (ntlm-tests--ensure-ws-parse-ntlm-support))
+ "Non-nil if GNU ELPA test dependencies were loaded.")
+
+(ert-deftest ntlm-authentication ()
+ "Check ntlm.el's implementation of NTLM authentication over HTTP."
+ (skip-unless ntlm-tests--dependencies-present)
+ (should (equal (ntlm-tests--start-server-authenticate-stop-server)
+ ntlm-tests--successful-result)))
+
+(ert-deftest ntlm-authentication-old-compatibility-level ()
+ (skip-unless ntlm-tests--dependencies-present)
+ (setq ntlm-compatibility-level 0)
+ (should (equal (ntlm-tests--start-server-authenticate-stop-server)
+ ntlm-tests--successful-result)))
+
+(provide 'ntlm-tests)
+
+;;; ntlm-tests.el ends here
diff --git a/test/lisp/net/puny-resources/IdnaTestV2.txt b/test/lisp/net/puny-resources/IdnaTestV2.txt
new file mode 100644
index 00000000000..ed2f32e129f
--- /dev/null
+++ b/test/lisp/net/puny-resources/IdnaTestV2.txt
@@ -0,0 +1,6344 @@
+# IdnaTestV2.txt
+# Date: 2021-08-17, 19:34:01 GMT
+# © 2021 Unicode®, Inc.
+# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries.
+# For terms of use, see http://www.unicode.org/terms_of_use.html
+#
+# Unicode IDNA Compatible Preprocessing for UTS #46
+# Version: 14.0.0
+#
+# For documentation and usage, see http://www.unicode.org/reports/tr46
+#
+# Test cases for verifying UTS #46 conformance.
+#
+# FORMAT:
+#
+# This file is in UTF-8, where characters may be escaped using the \uXXXX or \x{XXXX}
+# convention where they could otherwise have a confusing display.
+# These characters include control codes and combining marks.
+#
+# Columns (c1, c2,...) are separated by semicolons.
+# Leading and trailing spaces and tabs in each column are ignored.
+# Comments are indicated with hash marks.
+#
+# Column 1: source - The source string to be tested
+# Column 2: toUnicode - The result of applying toUnicode to the source,
+# with Transitional_Processing=false.
+# A blank value means the same as the source value.
+# Column 3: toUnicodeStatus - A set of status codes, each corresponding to a particular test.
+# A blank value means [] (no errors).
+# Column 4: toAsciiN - The result of applying toASCII to the source,
+# with Transitional_Processing=false.
+# A blank value means the same as the toUnicode value.
+# Column 5: toAsciiNStatus - A set of status codes, each corresponding to a particular test.
+# A blank value means the same as the toUnicodeStatus value.
+# An explicit [] means no errors.
+# Column 6: toAsciiT - The result of applying toASCII to the source,
+# with Transitional_Processing=true.
+# A blank value means the same as the toAsciiN value.
+# Column 7: toAsciiTStatus - A set of status codes, each corresponding to a particular test.
+# A blank value means the same as the toAsciiNStatus value.
+# An explicit [] means no errors.
+#
+# The line comments currently show visible characters that have been escaped.
+#
+# CONFORMANCE:
+#
+# To test for conformance to UTS #46, an implementation will perform the toUnicode, toAsciiN, and
+# toAsciiT operations on the source string, then verify the resulting strings and relevant status
+# values.
+#
+# If the implementation converts illegal code points into U+FFFD (as per
+# https://www.unicode.org/reports/tr46/#Processing) then the string comparisons need to
+# account for that by treating U+FFFD in the actual value as a wildcard when comparing to the
+# expected value in the test file.
+#
+# A status in toUnicode, toAsciiN or toAsciiT is indicated by a value in square brackets,
+# such as "[B5 B6]". In such a case, the contents is a list of status codes based on the step
+# numbers in UTS #46 and IDNA2008, with the following formats.
+#
+# Pn for Section 4 Processing step n
+# Vn for 4.1 Validity Criteria step n
+# U1 for UseSTD3ASCIIRules
+# An for 4.2 ToASCII step n
+# Bn for Bidi (in IDNA2008)
+# Cn for ContextJ (in IDNA2008)
+# Xn for toUnicode issues (see below)
+#
+# Thus C1 = Appendix A.1. ZERO WIDTH NON-JOINER, and C2 = Appendix A.2. ZERO WIDTH JOINER.
+# (The CONTEXTO tests are optional for client software, and not tested here.)
+#
+# Implementations that allow values of particular input flags to be false would ignore
+# the corresponding status codes listed in the table below when testing for errors.
+#
+# VerifyDnsLength: P4
+# CheckHyphens: V2, V3
+# CheckBidi: V8
+# CheckJoiners: V7
+# UseSTD3ASCIIRules: U1
+#
+# Implementations may be more strict than the default settings for UTS #46.
+# In particular, an implementation conformant to IDNA2008 would disallow the input for lines
+# marked with NV8.
+#
+# Implementations need only record that there is an error: they need not reproduce the
+# precise status codes (after removing the ignored status values).
+#
+# Compatibility errors
+#
+# The special error codes X3 and X4_2 are now returned where a toASCII error code
+# was formerly being generated in toUnicode due to an empty label.
+#
+# A3 was being generated in the following cases (in addition to its normal usage).
+# • an empty label in toUnicode. In this case, it is replaced by X3.
+#
+# A4_2 was being generated in the following case (in addition to its normal usage).
+# • an empty label in V8 (CheckBidi). In this case, it is being replaced by X4_2.
+# ============================================================================================
+fass.de; ; ; ; ; ; # fass.de
+faß.de; ; ; xn--fa-hia.de; ; fass.de; # faß.de
+Faß.de; faß.de; ; xn--fa-hia.de; ; fass.de; # faß.de
+xn--fa-hia.de; faß.de; ; xn--fa-hia.de; ; ; # faß.de
+
+# BIDI TESTS
+
+àא; ; [B5, B6]; xn--0ca24w; ; ; # àא
+àא; àא; [B5, B6]; xn--0ca24w; ; ; # àא
+Àא; àא; [B5, B6]; xn--0ca24w; ; ; # àא
+Àא; àא; [B5, B6]; xn--0ca24w; ; ; # àא
+xn--0ca24w; àא; [B5, B6]; xn--0ca24w; ; ; # àא
+0à.א; ; [B1]; xn--0-sfa.xn--4db; ; ; # 0à.א
+0à.א; 0à.א; [B1]; xn--0-sfa.xn--4db; ; ; # 0à.א
+0À.א; 0à.א; [B1]; xn--0-sfa.xn--4db; ; ; # 0à.א
+0À.א; 0à.א; [B1]; xn--0-sfa.xn--4db; ; ; # 0à.א
+xn--0-sfa.xn--4db; 0à.א; [B1]; xn--0-sfa.xn--4db; ; ; # 0à.א
+à.א̈; ; ; xn--0ca.xn--ssa73l; ; ; # à.א̈
+à.א̈; à.א̈; ; xn--0ca.xn--ssa73l; ; ; # à.א̈
+À.א̈; à.א̈; ; xn--0ca.xn--ssa73l; ; ; # à.א̈
+À.א̈; à.א̈; ; xn--0ca.xn--ssa73l; ; ; # à.א̈
+xn--0ca.xn--ssa73l; à.א̈; ; xn--0ca.xn--ssa73l; ; ; # à.א̈
+à.א0٠א; ; [B4]; xn--0ca.xn--0-zhcb98c; ; ; # à.א0٠א
+à.א0٠א; à.א0٠א; [B4]; xn--0ca.xn--0-zhcb98c; ; ; # à.א0٠א
+À.א0٠א; à.א0٠א; [B4]; xn--0ca.xn--0-zhcb98c; ; ; # à.א0٠א
+À.א0٠א; à.א0٠א; [B4]; xn--0ca.xn--0-zhcb98c; ; ; # à.א0٠א
+xn--0ca.xn--0-zhcb98c; à.א0٠א; [B4]; xn--0ca.xn--0-zhcb98c; ; ; # à.א0٠א
+̈.א; ; [B1, B3, B6, V5]; xn--ssa.xn--4db; ; ; # ̈.א
+xn--ssa.xn--4db; ̈.א; [B1, B3, B6, V5]; xn--ssa.xn--4db; ; ; # ̈.א
+à.א0٠; ; [B4]; xn--0ca.xn--0-zhc74b; ; ; # à.א0٠
+à.א0٠; à.א0٠; [B4]; xn--0ca.xn--0-zhc74b; ; ; # à.א0٠
+À.א0٠; à.א0٠; [B4]; xn--0ca.xn--0-zhc74b; ; ; # à.א0٠
+À.א0٠; à.א0٠; [B4]; xn--0ca.xn--0-zhc74b; ; ; # à.א0٠
+xn--0ca.xn--0-zhc74b; à.א0٠; [B4]; xn--0ca.xn--0-zhc74b; ; ; # à.א0٠
+àˇ.א; ; [B6]; xn--0ca88g.xn--4db; ; ; # àˇ.א
+àˇ.א; àˇ.א; [B6]; xn--0ca88g.xn--4db; ; ; # àˇ.א
+Àˇ.א; àˇ.א; [B6]; xn--0ca88g.xn--4db; ; ; # àˇ.א
+Àˇ.א; àˇ.א; [B6]; xn--0ca88g.xn--4db; ; ; # àˇ.א
+xn--0ca88g.xn--4db; àˇ.א; [B6]; xn--0ca88g.xn--4db; ; ; # àˇ.א
+à̈.א; ; ; xn--0ca81i.xn--4db; ; ; # à̈.א
+à̈.א; à̈.א; ; xn--0ca81i.xn--4db; ; ; # à̈.א
+À̈.א; à̈.א; ; xn--0ca81i.xn--4db; ; ; # à̈.א
+À̈.א; à̈.א; ; xn--0ca81i.xn--4db; ; ; # à̈.א
+xn--0ca81i.xn--4db; à̈.א; ; xn--0ca81i.xn--4db; ; ; # à̈.א
+
+# CONTEXT TESTS
+
+a‌b; ; [C1]; xn--ab-j1t; ; ab; [] # ab
+A‌B; a‌b; [C1]; xn--ab-j1t; ; ab; [] # ab
+A‌b; a‌b; [C1]; xn--ab-j1t; ; ab; [] # ab
+ab; ; ; ; ; ; # ab
+xn--ab-j1t; a‌b; [C1]; xn--ab-j1t; ; ; # ab
+a्‌b; ; ; xn--ab-fsf604u; ; xn--ab-fsf; # a्b
+A्‌B; a्‌b; ; xn--ab-fsf604u; ; xn--ab-fsf; # a्b
+A्‌b; a्‌b; ; xn--ab-fsf604u; ; xn--ab-fsf; # a्b
+xn--ab-fsf; a्b; ; xn--ab-fsf; ; ; # a्b
+a्b; ; ; xn--ab-fsf; ; ; # a्b
+A्B; a्b; ; xn--ab-fsf; ; ; # a्b
+A्b; a्b; ; xn--ab-fsf; ; ; # a्b
+xn--ab-fsf604u; a्‌b; ; xn--ab-fsf604u; ; ; # a्b
+̈‌̈بb; ; [B1, C1, V5]; xn--b-bcba413a2w8b; ; xn--b-bcba413a; [B1, V5] # ̈̈بb
+̈‌̈بB; ̈‌̈بb; [B1, C1, V5]; xn--b-bcba413a2w8b; ; xn--b-bcba413a; [B1, V5] # ̈̈بb
+xn--b-bcba413a; ̈̈بb; [B1, V5]; xn--b-bcba413a; ; ; # ̈̈بb
+xn--b-bcba413a2w8b; ̈‌̈بb; [B1, C1, V5]; xn--b-bcba413a2w8b; ; ; # ̈̈بb
+aب̈‌̈; ; [B5, B6, C1]; xn--a-ccba213a5w8b; ; xn--a-ccba213a; [B5, B6] # aب̈̈
+Aب̈‌̈; aب̈‌̈; [B5, B6, C1]; xn--a-ccba213a5w8b; ; xn--a-ccba213a; [B5, B6] # aب̈̈
+xn--a-ccba213a; aب̈̈; [B5, B6]; xn--a-ccba213a; ; ; # aب̈̈
+xn--a-ccba213a5w8b; aب̈‌̈; [B5, B6, C1]; xn--a-ccba213a5w8b; ; ; # aب̈̈
+aب̈‌̈بb; ; [B5]; xn--ab-uuba211bca8057b; ; xn--ab-uuba211bca; # aب̈̈بb
+Aب̈‌̈بB; aب̈‌̈بb; [B5]; xn--ab-uuba211bca8057b; ; xn--ab-uuba211bca; # aب̈̈بb
+Aب̈‌̈بb; aب̈‌̈بb; [B5]; xn--ab-uuba211bca8057b; ; xn--ab-uuba211bca; # aب̈̈بb
+xn--ab-uuba211bca; aب̈̈بb; [B5]; xn--ab-uuba211bca; ; ; # aب̈̈بb
+xn--ab-uuba211bca8057b; aب̈‌̈بb; [B5]; xn--ab-uuba211bca8057b; ; ; # aب̈̈بb
+a‍b; ; [C2]; xn--ab-m1t; ; ab; [] # ab
+A‍B; a‍b; [C2]; xn--ab-m1t; ; ab; [] # ab
+A‍b; a‍b; [C2]; xn--ab-m1t; ; ab; [] # ab
+xn--ab-m1t; a‍b; [C2]; xn--ab-m1t; ; ; # ab
+a्‍b; ; ; xn--ab-fsf014u; ; xn--ab-fsf; # a्b
+A्‍B; a्‍b; ; xn--ab-fsf014u; ; xn--ab-fsf; # a्b
+A्‍b; a्‍b; ; xn--ab-fsf014u; ; xn--ab-fsf; # a्b
+xn--ab-fsf014u; a्‍b; ; xn--ab-fsf014u; ; ; # a्b
+̈‍̈بb; ; [B1, C2, V5]; xn--b-bcba413a7w8b; ; xn--b-bcba413a; [B1, V5] # ̈̈بb
+̈‍̈بB; ̈‍̈بb; [B1, C2, V5]; xn--b-bcba413a7w8b; ; xn--b-bcba413a; [B1, V5] # ̈̈بb
+xn--b-bcba413a7w8b; ̈‍̈بb; [B1, C2, V5]; xn--b-bcba413a7w8b; ; ; # ̈̈بb
+aب̈‍̈; ; [B5, B6, C2]; xn--a-ccba213abx8b; ; xn--a-ccba213a; [B5, B6] # aب̈̈
+Aب̈‍̈; aب̈‍̈; [B5, B6, C2]; xn--a-ccba213abx8b; ; xn--a-ccba213a; [B5, B6] # aب̈̈
+xn--a-ccba213abx8b; aب̈‍̈; [B5, B6, C2]; xn--a-ccba213abx8b; ; ; # aب̈̈
+aب̈‍̈بb; ; [B5, C2]; xn--ab-uuba211bca5157b; ; xn--ab-uuba211bca; [B5] # aب̈̈بb
+Aب̈‍̈بB; aب̈‍̈بb; [B5, C2]; xn--ab-uuba211bca5157b; ; xn--ab-uuba211bca; [B5] # aب̈̈بb
+Aب̈‍̈بb; aب̈‍̈بb; [B5, C2]; xn--ab-uuba211bca5157b; ; xn--ab-uuba211bca; [B5] # aب̈̈بb
+xn--ab-uuba211bca5157b; aب̈‍̈بb; [B5, C2]; xn--ab-uuba211bca5157b; ; ; # aب̈̈بb
+
+# SELECTED TESTS
+
+¡; ; ; xn--7a; ; ; # ¡
+xn--7a; ¡; ; xn--7a; ; ; # ¡
+᧚; ; ; xn--pkf; ; ; # ᧚
+xn--pkf; ᧚; ; xn--pkf; ; ; # ᧚
+。; .; [X4_2]; ; [A4_2]; ; # .
+.; ; [X4_2]; ; [A4_2]; ; # .
+ꭠ; ; ; xn--3y9a; ; ; # ꭠ
+xn--3y9a; ꭠ; ; xn--3y9a; ; ; # ꭠ
+1234567890ä1234567890123456789012345678901234567890123456; ; ; xn--12345678901234567890123456789012345678901234567890123456-fxe; [A4_2]; ; # 1234567890ä1234567890123456789012345678901234567890123456
+1234567890ä1234567890123456789012345678901234567890123456; 1234567890ä1234567890123456789012345678901234567890123456; ; xn--12345678901234567890123456789012345678901234567890123456-fxe; [A4_2]; ; # 1234567890ä1234567890123456789012345678901234567890123456
+1234567890Ä1234567890123456789012345678901234567890123456; 1234567890ä1234567890123456789012345678901234567890123456; ; xn--12345678901234567890123456789012345678901234567890123456-fxe; [A4_2]; ; # 1234567890ä1234567890123456789012345678901234567890123456
+1234567890Ä1234567890123456789012345678901234567890123456; 1234567890ä1234567890123456789012345678901234567890123456; ; xn--12345678901234567890123456789012345678901234567890123456-fxe; [A4_2]; ; # 1234567890ä1234567890123456789012345678901234567890123456
+xn--12345678901234567890123456789012345678901234567890123456-fxe; 1234567890ä1234567890123456789012345678901234567890123456; ; xn--12345678901234567890123456789012345678901234567890123456-fxe; [A4_2]; ; # 1234567890ä1234567890123456789012345678901234567890123456
+www.eXample.cOm; www.example.com; ; ; ; ; # www.example.com
+Bücher.de; bücher.de; ; xn--bcher-kva.de; ; ; # bücher.de
+Bücher.de; bücher.de; ; xn--bcher-kva.de; ; ; # bücher.de
+bücher.de; bücher.de; ; xn--bcher-kva.de; ; ; # bücher.de
+bücher.de; ; ; xn--bcher-kva.de; ; ; # bücher.de
+BÜCHER.DE; bücher.de; ; xn--bcher-kva.de; ; ; # bücher.de
+BÜCHER.DE; bücher.de; ; xn--bcher-kva.de; ; ; # bücher.de
+xn--bcher-kva.de; bücher.de; ; xn--bcher-kva.de; ; ; # bücher.de
+ÖBB; öbb; ; xn--bb-eka; ; ; # öbb
+ÖBB; öbb; ; xn--bb-eka; ; ; # öbb
+öbb; öbb; ; xn--bb-eka; ; ; # öbb
+öbb; ; ; xn--bb-eka; ; ; # öbb
+Öbb; öbb; ; xn--bb-eka; ; ; # öbb
+Öbb; öbb; ; xn--bb-eka; ; ; # öbb
+xn--bb-eka; öbb; ; xn--bb-eka; ; ; # öbb
+βόλος.com; ; ; xn--nxasmm1c.com; ; xn--nxasmq6b.com; # βόλος.com
+βόλος.com; βόλος.com; ; xn--nxasmm1c.com; ; xn--nxasmq6b.com; # βόλος.com
+ΒΌΛΟΣ.COM; βόλοσ.com; ; xn--nxasmq6b.com; ; ; # βόλοσ.com
+ΒΌΛΟΣ.COM; βόλοσ.com; ; xn--nxasmq6b.com; ; ; # βόλοσ.com
+βόλοσ.com; ; ; xn--nxasmq6b.com; ; ; # βόλοσ.com
+βόλοσ.com; βόλοσ.com; ; xn--nxasmq6b.com; ; ; # βόλοσ.com
+Βόλοσ.com; βόλοσ.com; ; xn--nxasmq6b.com; ; ; # βόλοσ.com
+Βόλοσ.com; βόλοσ.com; ; xn--nxasmq6b.com; ; ; # βόλοσ.com
+xn--nxasmq6b.com; βόλοσ.com; ; xn--nxasmq6b.com; ; ; # βόλοσ.com
+Βόλος.com; βόλος.com; ; xn--nxasmm1c.com; ; xn--nxasmq6b.com; # βόλος.com
+Βόλος.com; βόλος.com; ; xn--nxasmm1c.com; ; xn--nxasmq6b.com; # βόλος.com
+xn--nxasmm1c.com; βόλος.com; ; xn--nxasmm1c.com; ; ; # βόλος.com
+xn--nxasmm1c; βόλος; ; xn--nxasmm1c; ; ; # βόλος
+βόλος; ; ; xn--nxasmm1c; ; xn--nxasmq6b; # βόλος
+βόλος; βόλος; ; xn--nxasmm1c; ; xn--nxasmq6b; # βόλος
+ΒΌΛΟΣ; βόλοσ; ; xn--nxasmq6b; ; ; # βόλοσ
+ΒΌΛΟΣ; βόλοσ; ; xn--nxasmq6b; ; ; # βόλοσ
+βόλοσ; ; ; xn--nxasmq6b; ; ; # βόλοσ
+βόλοσ; βόλοσ; ; xn--nxasmq6b; ; ; # βόλοσ
+Βόλοσ; βόλοσ; ; xn--nxasmq6b; ; ; # βόλοσ
+Βόλοσ; βόλοσ; ; xn--nxasmq6b; ; ; # βόλοσ
+xn--nxasmq6b; βόλοσ; ; xn--nxasmq6b; ; ; # βόλοσ
+Βόλος; βόλος; ; xn--nxasmm1c; ; xn--nxasmq6b; # βόλος
+Βόλος; βόλος; ; xn--nxasmm1c; ; xn--nxasmq6b; # βόλος
+www.ශ්‍රී.com; ; ; www.xn--10cl1a0b660p.com; ; www.xn--10cl1a0b.com; # www.ශ්රී.com
+WWW.ශ්‍රී.COM; www.ශ්‍රී.com; ; www.xn--10cl1a0b660p.com; ; www.xn--10cl1a0b.com; # www.ශ්රී.com
+Www.ශ්‍රී.com; www.ශ්‍රී.com; ; www.xn--10cl1a0b660p.com; ; www.xn--10cl1a0b.com; # www.ශ්රී.com
+www.xn--10cl1a0b.com; www.ශ්රී.com; ; www.xn--10cl1a0b.com; ; ; # www.ශ්රී.com
+www.ශ්රී.com; ; ; www.xn--10cl1a0b.com; ; ; # www.ශ්රී.com
+WWW.ශ්රී.COM; www.ශ්රී.com; ; www.xn--10cl1a0b.com; ; ; # www.ශ්රී.com
+Www.ශ්රී.com; www.ශ්රී.com; ; www.xn--10cl1a0b.com; ; ; # www.ශ්රී.com
+www.xn--10cl1a0b660p.com; www.ශ්‍රී.com; ; www.xn--10cl1a0b660p.com; ; ; # www.ශ්රී.com
+نامه‌ای; ; ; xn--mgba3gch31f060k; ; xn--mgba3gch31f; # نامهای
+xn--mgba3gch31f; نامهای; ; xn--mgba3gch31f; ; ; # نامهای
+نامهای; ; ; xn--mgba3gch31f; ; ; # نامهای
+xn--mgba3gch31f060k; نامه‌ای; ; xn--mgba3gch31f060k; ; ; # نامهای
+xn--mgba3gch31f060k.com; نامه‌ای.com; ; xn--mgba3gch31f060k.com; ; ; # نامهای.com
+نامه‌ای.com; ; ; xn--mgba3gch31f060k.com; ; xn--mgba3gch31f.com; # نامهای.com
+نامه‌ای.COM; نامه‌ای.com; ; xn--mgba3gch31f060k.com; ; xn--mgba3gch31f.com; # نامهای.com
+xn--mgba3gch31f.com; نامهای.com; ; xn--mgba3gch31f.com; ; ; # نامهای.com
+نامهای.com; ; ; xn--mgba3gch31f.com; ; ; # نامهای.com
+نامهای.COM; نامهای.com; ; xn--mgba3gch31f.com; ; ; # نامهای.com
+a.b.c。d。; a.b.c.d.; ; ; ; ; # a.b.c.d.
+a.b.c。d。; a.b.c.d.; ; ; ; ; # a.b.c.d.
+A.B.C。D。; a.b.c.d.; ; ; ; ; # a.b.c.d.
+A.b.c。D。; a.b.c.d.; ; ; ; ; # a.b.c.d.
+a.b.c.d.; ; ; ; ; ; # a.b.c.d.
+A.B.C。D。; a.b.c.d.; ; ; ; ; # a.b.c.d.
+A.b.c。D。; a.b.c.d.; ; ; ; ; # a.b.c.d.
+Ü.xn--tda; ü.ü; ; xn--tda.xn--tda; ; ; # ü.ü
+Ü.xn--tda; ü.ü; ; xn--tda.xn--tda; ; ; # ü.ü
+ü.xn--tda; ü.ü; ; xn--tda.xn--tda; ; ; # ü.ü
+ü.xn--tda; ü.ü; ; xn--tda.xn--tda; ; ; # ü.ü
+Ü.XN--TDA; ü.ü; ; xn--tda.xn--tda; ; ; # ü.ü
+Ü.XN--TDA; ü.ü; ; xn--tda.xn--tda; ; ; # ü.ü
+Ü.xn--Tda; ü.ü; ; xn--tda.xn--tda; ; ; # ü.ü
+Ü.xn--Tda; ü.ü; ; xn--tda.xn--tda; ; ; # ü.ü
+xn--tda.xn--tda; ü.ü; ; xn--tda.xn--tda; ; ; # ü.ü
+ü.ü; ; ; xn--tda.xn--tda; ; ; # ü.ü
+ü.ü; ü.ü; ; xn--tda.xn--tda; ; ; # ü.ü
+Ü.Ü; ü.ü; ; xn--tda.xn--tda; ; ; # ü.ü
+Ü.Ü; ü.ü; ; xn--tda.xn--tda; ; ; # ü.ü
+Ü.ü; ü.ü; ; xn--tda.xn--tda; ; ; # ü.ü
+Ü.ü; ü.ü; ; xn--tda.xn--tda; ; ; # ü.ü
+xn--u-ccb; ü; [V1]; xn--u-ccb; ; ; # ü
+a⒈com; ; [P1, V6]; xn--acom-0w1b; ; ; # a⒈com
+a1.com; ; ; ; ; ; # a1.com
+A⒈COM; a⒈com; [P1, V6]; xn--acom-0w1b; ; ; # a⒈com
+A⒈Com; a⒈com; [P1, V6]; xn--acom-0w1b; ; ; # a⒈com
+xn--acom-0w1b; a⒈com; [V6]; xn--acom-0w1b; ; ; # a⒈com
+xn--a-ecp.ru; a⒈.ru; [V6]; xn--a-ecp.ru; ; ; # a⒈.ru
+xn--0.pt; ; [P4]; ; ; ; # xn--0.pt
+xn--a.pt; €.pt; [V6]; xn--a.pt; ; ; # .pt
+xn--a-Ä.pt; xn--a-ä.pt; [P4]; xn--xn--a--gua.pt; ; ; # xn--a-ä.pt
+xn--a-Ä.pt; xn--a-ä.pt; [P4]; xn--xn--a--gua.pt; ; ; # xn--a-ä.pt
+xn--a-ä.pt; xn--a-ä.pt; [P4]; xn--xn--a--gua.pt; ; ; # xn--a-ä.pt
+xn--a-ä.pt; ; [P4]; xn--xn--a--gua.pt; ; ; # xn--a-ä.pt
+XN--A-Ä.PT; xn--a-ä.pt; [P4]; xn--xn--a--gua.pt; ; ; # xn--a-ä.pt
+XN--A-Ä.PT; xn--a-ä.pt; [P4]; xn--xn--a--gua.pt; ; ; # xn--a-ä.pt
+Xn--A-Ä.pt; xn--a-ä.pt; [P4]; xn--xn--a--gua.pt; ; ; # xn--a-ä.pt
+Xn--A-Ä.pt; xn--a-ä.pt; [P4]; xn--xn--a--gua.pt; ; ; # xn--a-ä.pt
+xn--xn--a--gua.pt; xn--a-ä.pt; [V2]; xn--xn--a--gua.pt; ; ; # xn--a-ä.pt
+日本語。JP; 日本語.jp; ; xn--wgv71a119e.jp; ; ; # 日本語.jp
+日本語。JP; 日本語.jp; ; xn--wgv71a119e.jp; ; ; # 日本語.jp
+日本語。jp; 日本語.jp; ; xn--wgv71a119e.jp; ; ; # 日本語.jp
+日本語。Jp; 日本語.jp; ; xn--wgv71a119e.jp; ; ; # 日本語.jp
+xn--wgv71a119e.jp; 日本語.jp; ; xn--wgv71a119e.jp; ; ; # 日本語.jp
+日本語.jp; ; ; xn--wgv71a119e.jp; ; ; # 日本語.jp
+日本語.JP; 日本語.jp; ; xn--wgv71a119e.jp; ; ; # 日本語.jp
+日本語.Jp; 日本語.jp; ; xn--wgv71a119e.jp; ; ; # 日本語.jp
+日本語。jp; 日本語.jp; ; xn--wgv71a119e.jp; ; ; # 日本語.jp
+日本語。Jp; 日本語.jp; ; xn--wgv71a119e.jp; ; ; # 日本語.jp
+☕; ; ; xn--53h; ; ; # ☕
+xn--53h; ☕; ; xn--53h; ; ; # ☕
+1.aß‌‍b‌‍cßßßßdςσßßßßßßßßeßßßßßßßßßßxßßßßßßßßßßyßßßßßßßß̂ßz; ; [C1, C2]; 1.xn--abcdexyz-qyacaaabaaaaaaabaaaaaaaaabaaaaaaaaabaaaaaaaa010ze2isb1140zba8cc; [C1, C2, A4_2]; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa; [A4_2] # 1.aßbcßßßßdςσßßßßßßßßeßßßßßßßßßßxßßßßßßßßßßyßßßßßßßß̂ßz
+1.ASS‌‍B‌‍CSSSSSSSSDΣΣSSSSSSSSSSSSSSSSESSSSSSSSSSSSSSSSSSSSXSSSSSSSSSSSSSSSSSSSSYSSSSSSSSSSSSSSSŜSSZ; 1.ass‌‍b‌‍cssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz; [C1, C2]; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa69989dba9gc; [C1, C2, A4_2]; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa; [A4_2] # 1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz
+1.ASS‌‍B‌‍CSSSSSSSSDΣΣSSSSSSSSSSSSSSSSESSSSSSSSSSSSSSSSSSSSXSSSSSSSSSSSSSSSSSSSSYSSSSSSSSSSSSSSSŜSSZ; 1.ass‌‍b‌‍cssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz; [C1, C2]; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa69989dba9gc; [C1, C2, A4_2]; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa; [A4_2] # 1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz
+1.ass‌‍b‌‍cssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz; ; [C1, C2]; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa69989dba9gc; [C1, C2, A4_2]; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa; [A4_2] # 1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz
+1.ass‌‍b‌‍cssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz; 1.ass‌‍b‌‍cssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz; [C1, C2]; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa69989dba9gc; [C1, C2, A4_2]; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa; [A4_2] # 1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz
+1.Ass‌‍b‌‍cssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz; 1.ass‌‍b‌‍cssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz; [C1, C2]; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa69989dba9gc; [C1, C2, A4_2]; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa; [A4_2] # 1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz
+1.Ass‌‍b‌‍cssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz; 1.ass‌‍b‌‍cssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz; [C1, C2]; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa69989dba9gc; [C1, C2, A4_2]; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa; [A4_2] # 1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz
+1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa; 1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz; ; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa; [A4_2]; ; # 1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz
+1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz; ; ; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa; [A4_2]; ; # 1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz
+1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz; 1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz; ; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa; [A4_2]; ; # 1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz
+1.ASSBCSSSSSSSSDΣΣSSSSSSSSSSSSSSSSESSSSSSSSSSSSSSSSSSSSXSSSSSSSSSSSSSSSSSSSSYSSSSSSSSSSSSSSSŜSSZ; 1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz; ; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa; [A4_2]; ; # 1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz
+1.ASSBCSSSSSSSSDΣΣSSSSSSSSSSSSSSSSESSSSSSSSSSSSSSSSSSSSXSSSSSSSSSSSSSSSSSSSSYSSSSSSSSSSSSSSSŜSSZ; 1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz; ; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa; [A4_2]; ; # 1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz
+1.Assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz; 1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz; ; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa; [A4_2]; ; # 1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz
+1.Assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz; 1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz; ; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa; [A4_2]; ; # 1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz
+1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa69989dba9gc; 1.ass‌‍b‌‍cssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz; [C1, C2]; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa69989dba9gc; [C1, C2, A4_2]; ; # 1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz
+1.Aß‌‍b‌‍cßßßßdςσßßßßßßßßeßßßßßßßßßßxßßßßßßßßßßyßßßßßßßß̂ßz; 1.aß‌‍b‌‍cßßßßdςσßßßßßßßßeßßßßßßßßßßxßßßßßßßßßßyßßßßßßßß̂ßz; [C1, C2]; 1.xn--abcdexyz-qyacaaabaaaaaaabaaaaaaaaabaaaaaaaaabaaaaaaaa010ze2isb1140zba8cc; [C1, C2, A4_2]; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa; [A4_2] # 1.aßbcßßßßdςσßßßßßßßßeßßßßßßßßßßxßßßßßßßßßßyßßßßßßßß̂ßz
+1.xn--abcdexyz-qyacaaabaaaaaaabaaaaaaaaabaaaaaaaaabaaaaaaaa010ze2isb1140zba8cc; 1.aß‌‍b‌‍cßßßßdςσßßßßßßßßeßßßßßßßßßßxßßßßßßßßßßyßßßßßßßß̂ßz; [C1, C2]; 1.xn--abcdexyz-qyacaaabaaaaaaabaaaaaaaaabaaaaaaaaabaaaaaaaa010ze2isb1140zba8cc; [C1, C2, A4_2]; ; # 1.aßbcßßßßdςσßßßßßßßßeßßßßßßßßßßxßßßßßßßßßßyßßßßßßßß̂ßz
+‌x‍n‌-‍-bß; ; [C1, C2]; xn--xn--b-pqa5796ccahd; ; xn--bss; [] # xn--bß
+‌X‍N‌-‍-BSS; ‌x‍n‌-‍-bss; [C1, C2]; xn--xn--bss-7z6ccid; ; xn--bss; [] # xn--bss
+‌x‍n‌-‍-bss; ; [C1, C2]; xn--xn--bss-7z6ccid; ; xn--bss; [] # xn--bss
+‌X‍n‌-‍-Bss; ‌x‍n‌-‍-bss; [C1, C2]; xn--xn--bss-7z6ccid; ; xn--bss; [] # xn--bss
+xn--bss; 夙; ; xn--bss; ; ; # 夙
+夙; ; ; xn--bss; ; ; # 夙
+xn--xn--bss-7z6ccid; ‌x‍n‌-‍-bss; [C1, C2]; xn--xn--bss-7z6ccid; ; ; # xn--bss
+‌X‍n‌-‍-Bß; ‌x‍n‌-‍-bß; [C1, C2]; xn--xn--b-pqa5796ccahd; ; xn--bss; [] # xn--bß
+xn--xn--b-pqa5796ccahd; ‌x‍n‌-‍-bß; [C1, C2]; xn--xn--b-pqa5796ccahd; ; ; # xn--bß
+ˣ͏ℕ​﹣­-᠌ℬ︀ſ⁤𝔰󠇯ffl; 夡夞夜夙; ; xn--bssffl; ; ; # 夡夞夜夙
+x͏N​-­-᠌B︀s⁤s󠇯ffl; 夡夞夜夙; ; xn--bssffl; ; ; # 夡夞夜夙
+x͏n​-­-᠌b︀s⁤s󠇯ffl; 夡夞夜夙; ; xn--bssffl; ; ; # 夡夞夜夙
+X͏N​-­-᠌B︀S⁤S󠇯FFL; 夡夞夜夙; ; xn--bssffl; ; ; # 夡夞夜夙
+X͏n​-­-᠌B︀s⁤s󠇯ffl; 夡夞夜夙; ; xn--bssffl; ; ; # 夡夞夜夙
+xn--bssffl; 夡夞夜夙; ; xn--bssffl; ; ; # 夡夞夜夙
+夡夞夜夙; ; ; xn--bssffl; ; ; # 夡夞夜夙
+ˣ͏ℕ​﹣­-᠌ℬ︀S⁤𝔰󠇯FFL; 夡夞夜夙; ; xn--bssffl; ; ; # 夡夞夜夙
+x͏N​-­-᠌B︀S⁤s󠇯FFL; 夡夞夜夙; ; xn--bssffl; ; ; # 夡夞夜夙
+ˣ͏ℕ​﹣­-᠌ℬ︀s⁤𝔰󠇯ffl; 夡夞夜夙; ; xn--bssffl; ; ; # 夡夞夜夙
+123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901; ; ; ; ; ; # 123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901
+123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901.; ; ; ; ; ; # 123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901.
+123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789012; ; ; ; [A4_1]; ; # 123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789012
+123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901234.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890; ; ; ; [A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901234.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890
+123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901234.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890.; ; ; ; [A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901234.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890.
+123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901234.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901; ; ; ; [A4_1, A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901234.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901
+ä1234567890123456789012345678901234567890123456789012345; ; ; xn--1234567890123456789012345678901234567890123456789012345-9te; ; ; # ä1234567890123456789012345678901234567890123456789012345
+ä1234567890123456789012345678901234567890123456789012345; ä1234567890123456789012345678901234567890123456789012345; ; xn--1234567890123456789012345678901234567890123456789012345-9te; ; ; # ä1234567890123456789012345678901234567890123456789012345
+Ä1234567890123456789012345678901234567890123456789012345; ä1234567890123456789012345678901234567890123456789012345; ; xn--1234567890123456789012345678901234567890123456789012345-9te; ; ; # ä1234567890123456789012345678901234567890123456789012345
+Ä1234567890123456789012345678901234567890123456789012345; ä1234567890123456789012345678901234567890123456789012345; ; xn--1234567890123456789012345678901234567890123456789012345-9te; ; ; # ä1234567890123456789012345678901234567890123456789012345
+xn--1234567890123456789012345678901234567890123456789012345-9te; ä1234567890123456789012345678901234567890123456789012345; ; xn--1234567890123456789012345678901234567890123456789012345-9te; ; ; # ä1234567890123456789012345678901234567890123456789012345
+123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901; ; ; 123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901; ; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901
+123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901; ; 123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901; ; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901
+123456789012345678901234567890123456789012345678901234567890123.1234567890Ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901; ; 123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901; ; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901
+123456789012345678901234567890123456789012345678901234567890123.1234567890Ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901; ; 123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901; ; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901
+123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901; ; 123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901; ; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901
+123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901.; ; ; 123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901.; ; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901.
+123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901.; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901.; ; 123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901.; ; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901.
+123456789012345678901234567890123456789012345678901234567890123.1234567890Ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901.; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901.; ; 123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901.; ; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901.
+123456789012345678901234567890123456789012345678901234567890123.1234567890Ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901.; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901.; ; 123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901.; ; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901.
+123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901.; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901.; ; 123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901.; ; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901.
+123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789012; ; ; 123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789012; [A4_1]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789012
+123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789012; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789012; ; 123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789012; [A4_1]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789012
+123456789012345678901234567890123456789012345678901234567890123.1234567890Ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789012; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789012; ; 123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789012; [A4_1]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789012
+123456789012345678901234567890123456789012345678901234567890123.1234567890Ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789012; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789012; ; 123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789012; [A4_1]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789012
+123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789012; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789012; ; 123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789012; [A4_1]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789012
+123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890; ; ; 123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890; [A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890
+123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890; ; 123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890; [A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890
+123456789012345678901234567890123456789012345678901234567890123.1234567890Ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890; ; 123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890; [A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890
+123456789012345678901234567890123456789012345678901234567890123.1234567890Ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890; ; 123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890; [A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890
+123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890; ; 123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890; [A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890
+123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890.; ; ; 123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890.; [A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890.
+123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890.; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890.; ; 123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890.; [A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890.
+123456789012345678901234567890123456789012345678901234567890123.1234567890Ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890.; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890.; ; 123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890.; [A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890.
+123456789012345678901234567890123456789012345678901234567890123.1234567890Ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890.; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890.; ; 123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890.; [A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890.
+123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890.; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890.; ; 123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890.; [A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890.
+123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901; ; ; 123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901; [A4_1, A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901
+123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901; ; 123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901; [A4_1, A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901
+123456789012345678901234567890123456789012345678901234567890123.1234567890Ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901; ; 123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901; [A4_1, A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901
+123456789012345678901234567890123456789012345678901234567890123.1234567890Ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901; ; 123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901; [A4_1, A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901
+123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901; ; 123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901; [A4_1, A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901
+a.b..-q--a-.e; ; [V2, V3, X4_2]; ; [V2, V3, A4_2]; ; # a.b..-q--a-.e
+a.b..-q--ä-.e; ; [V2, V3, X4_2]; a.b..xn---q----jra.e; [V2, V3, A4_2]; ; # a.b..-q--ä-.e
+a.b..-q--ä-.e; a.b..-q--ä-.e; [V2, V3, X4_2]; a.b..xn---q----jra.e; [V2, V3, A4_2]; ; # a.b..-q--ä-.e
+A.B..-Q--Ä-.E; a.b..-q--ä-.e; [V2, V3, X4_2]; a.b..xn---q----jra.e; [V2, V3, A4_2]; ; # a.b..-q--ä-.e
+A.B..-Q--Ä-.E; a.b..-q--ä-.e; [V2, V3, X4_2]; a.b..xn---q----jra.e; [V2, V3, A4_2]; ; # a.b..-q--ä-.e
+A.b..-Q--Ä-.E; a.b..-q--ä-.e; [V2, V3, X4_2]; a.b..xn---q----jra.e; [V2, V3, A4_2]; ; # a.b..-q--ä-.e
+A.b..-Q--Ä-.E; a.b..-q--ä-.e; [V2, V3, X4_2]; a.b..xn---q----jra.e; [V2, V3, A4_2]; ; # a.b..-q--ä-.e
+a.b..xn---q----jra.e; a.b..-q--ä-.e; [V2, V3, X4_2]; a.b..xn---q----jra.e; [V2, V3, A4_2]; ; # a.b..-q--ä-.e
+a..c; ; [X4_2]; ; [A4_2]; ; # a..c
+a.-b.; ; [V3]; ; ; ; # a.-b.
+a.b-.c; ; [V3]; ; ; ; # a.b-.c
+a.-.c; ; [V3]; ; ; ; # a.-.c
+a.bc--de.f; ; [V2]; ; ; ; # a.bc--de.f
+ä.­.c; ä..c; [X4_2]; xn--4ca..c; [A4_2]; ; # ä..c
+ä.­.c; ä..c; [X4_2]; xn--4ca..c; [A4_2]; ; # ä..c
+Ä.­.C; ä..c; [X4_2]; xn--4ca..c; [A4_2]; ; # ä..c
+Ä.­.C; ä..c; [X4_2]; xn--4ca..c; [A4_2]; ; # ä..c
+xn--4ca..c; ä..c; [X4_2]; xn--4ca..c; [A4_2]; ; # ä..c
+ä.-b.; ; [V3]; xn--4ca.-b.; ; ; # ä.-b.
+ä.-b.; ä.-b.; [V3]; xn--4ca.-b.; ; ; # ä.-b.
+Ä.-B.; ä.-b.; [V3]; xn--4ca.-b.; ; ; # ä.-b.
+Ä.-B.; ä.-b.; [V3]; xn--4ca.-b.; ; ; # ä.-b.
+xn--4ca.-b.; ä.-b.; [V3]; xn--4ca.-b.; ; ; # ä.-b.
+ä.b-.c; ; [V3]; xn--4ca.b-.c; ; ; # ä.b-.c
+ä.b-.c; ä.b-.c; [V3]; xn--4ca.b-.c; ; ; # ä.b-.c
+Ä.B-.C; ä.b-.c; [V3]; xn--4ca.b-.c; ; ; # ä.b-.c
+Ä.B-.C; ä.b-.c; [V3]; xn--4ca.b-.c; ; ; # ä.b-.c
+Ä.b-.C; ä.b-.c; [V3]; xn--4ca.b-.c; ; ; # ä.b-.c
+Ä.b-.C; ä.b-.c; [V3]; xn--4ca.b-.c; ; ; # ä.b-.c
+xn--4ca.b-.c; ä.b-.c; [V3]; xn--4ca.b-.c; ; ; # ä.b-.c
+ä.-.c; ; [V3]; xn--4ca.-.c; ; ; # ä.-.c
+ä.-.c; ä.-.c; [V3]; xn--4ca.-.c; ; ; # ä.-.c
+Ä.-.C; ä.-.c; [V3]; xn--4ca.-.c; ; ; # ä.-.c
+Ä.-.C; ä.-.c; [V3]; xn--4ca.-.c; ; ; # ä.-.c
+xn--4ca.-.c; ä.-.c; [V3]; xn--4ca.-.c; ; ; # ä.-.c
+ä.bc--de.f; ; [V2]; xn--4ca.bc--de.f; ; ; # ä.bc--de.f
+ä.bc--de.f; ä.bc--de.f; [V2]; xn--4ca.bc--de.f; ; ; # ä.bc--de.f
+Ä.BC--DE.F; ä.bc--de.f; [V2]; xn--4ca.bc--de.f; ; ; # ä.bc--de.f
+Ä.BC--DE.F; ä.bc--de.f; [V2]; xn--4ca.bc--de.f; ; ; # ä.bc--de.f
+Ä.bc--De.f; ä.bc--de.f; [V2]; xn--4ca.bc--de.f; ; ; # ä.bc--de.f
+Ä.bc--De.f; ä.bc--de.f; [V2]; xn--4ca.bc--de.f; ; ; # ä.bc--de.f
+xn--4ca.bc--de.f; ä.bc--de.f; [V2]; xn--4ca.bc--de.f; ; ; # ä.bc--de.f
+a.b.̈c.d; ; [V5]; a.b.xn--c-bcb.d; ; ; # a.b.̈c.d
+A.B.̈C.D; a.b.̈c.d; [V5]; a.b.xn--c-bcb.d; ; ; # a.b.̈c.d
+A.b.̈c.d; a.b.̈c.d; [V5]; a.b.xn--c-bcb.d; ; ; # a.b.̈c.d
+a.b.xn--c-bcb.d; a.b.̈c.d; [V5]; a.b.xn--c-bcb.d; ; ; # a.b.̈c.d
+A0; a0; ; ; ; ; # a0
+0A; 0a; ; ; ; ; # 0a
+0A.א; 0a.א; [B1]; 0a.xn--4db; ; ; # 0a.א
+0a.א; ; [B1]; 0a.xn--4db; ; ; # 0a.א
+0a.xn--4db; 0a.א; [B1]; 0a.xn--4db; ; ; # 0a.א
+c.xn--0-eha.xn--4db; c.0ü.א; [B1]; c.xn--0-eha.xn--4db; ; ; # c.0ü.א
+b-.א; ; [B6, V3]; b-.xn--4db; ; ; # b-.א
+B-.א; b-.א; [B6, V3]; b-.xn--4db; ; ; # b-.א
+b-.xn--4db; b-.א; [B6, V3]; b-.xn--4db; ; ; # b-.א
+d.xn----dha.xn--4db; d.ü-.א; [B6, V3]; d.xn----dha.xn--4db; ; ; # d.ü-.א
+aא; ; [B5, B6]; xn--a-0hc; ; ; # aא
+Aא; aא; [B5, B6]; xn--a-0hc; ; ; # aא
+xn--a-0hc; aא; [B5, B6]; xn--a-0hc; ; ; # aא
+אׇ; ; ; xn--vdbr; ; ; # אׇ
+xn--vdbr; אׇ; ; xn--vdbr; ; ; # אׇ
+א9ׇ; ; ; xn--9-ihcz; ; ; # א9ׇ
+xn--9-ihcz; א9ׇ; ; xn--9-ihcz; ; ; # א9ׇ
+אaׇ; ; [B2, B3]; xn--a-ihcz; ; ; # אaׇ
+אAׇ; אaׇ; [B2, B3]; xn--a-ihcz; ; ; # אaׇ
+xn--a-ihcz; אaׇ; [B2, B3]; xn--a-ihcz; ; ; # אaׇ
+את; ; ; xn--4db6c; ; ; # את
+xn--4db6c; את; ; xn--4db6c; ; ; # את
+א׳ת; ; ; xn--4db6c0a; ; ; # א׳ת
+xn--4db6c0a; א׳ת; ; xn--4db6c0a; ; ; # א׳ת
+aאTz; aאtz; [B5]; xn--atz-qpe; ; ; # aאtz
+aאtz; ; [B5]; xn--atz-qpe; ; ; # aאtz
+AאTZ; aאtz; [B5]; xn--atz-qpe; ; ; # aאtz
+Aאtz; aאtz; [B5]; xn--atz-qpe; ; ; # aאtz
+xn--atz-qpe; aאtz; [B5]; xn--atz-qpe; ; ; # aאtz
+אTת; אtת; [B2]; xn--t-zhc3f; ; ; # אtת
+אtת; ; [B2]; xn--t-zhc3f; ; ; # אtת
+xn--t-zhc3f; אtת; [B2]; xn--t-zhc3f; ; ; # אtת
+א7ת; ; ; xn--7-zhc3f; ; ; # א7ת
+xn--7-zhc3f; א7ת; ; xn--7-zhc3f; ; ; # א7ת
+א٧ת; ; ; xn--4db6c6t; ; ; # א٧ת
+xn--4db6c6t; א٧ת; ; xn--4db6c6t; ; ; # א٧ת
+a7٧z; ; [B5]; xn--a7z-06e; ; ; # a7٧z
+A7٧Z; a7٧z; [B5]; xn--a7z-06e; ; ; # a7٧z
+A7٧z; a7٧z; [B5]; xn--a7z-06e; ; ; # a7٧z
+xn--a7z-06e; a7٧z; [B5]; xn--a7z-06e; ; ; # a7٧z
+א7٧ת; ; [B4]; xn--7-zhc3fty; ; ; # א7٧ת
+xn--7-zhc3fty; א7٧ת; [B4]; xn--7-zhc3fty; ; ; # א7٧ת
+ஹ்‍; ; ; xn--dmc4b194h; ; xn--dmc4b; # ஹ்
+xn--dmc4b; ஹ்; ; xn--dmc4b; ; ; # ஹ்
+ஹ்; ; ; xn--dmc4b; ; ; # ஹ்
+xn--dmc4b194h; ஹ்‍; ; xn--dmc4b194h; ; ; # ஹ்
+ஹ‍; ; [C2]; xn--dmc225h; ; xn--dmc; [] # ஹ
+xn--dmc; ஹ; ; xn--dmc; ; ; # ஹ
+ஹ; ; ; xn--dmc; ; ; # ஹ
+xn--dmc225h; ஹ‍; [C2]; xn--dmc225h; ; ; # ஹ
+‍; ; [C2]; xn--1ug; ; ; [A4_2] #
+; ; [X4_2]; ; [A4_2]; ; #
+xn--1ug; ‍; [C2]; xn--1ug; ; ; #
+ஹ்‌; ; ; xn--dmc4by94h; ; xn--dmc4b; # ஹ்
+xn--dmc4by94h; ஹ்‌; ; xn--dmc4by94h; ; ; # ஹ்
+ஹ‌; ; [C1]; xn--dmc025h; ; xn--dmc; [] # ஹ
+xn--dmc025h; ஹ‌; [C1]; xn--dmc025h; ; ; # ஹ
+‌; ; [C1]; xn--0ug; ; ; [A4_2] #
+xn--0ug; ‌; [C1]; xn--0ug; ; ; #
+لٰ‌ۭۯ; ; ; xn--ghb2gxqia7523a; ; xn--ghb2gxqia; # لٰۭۯ
+xn--ghb2gxqia; لٰۭۯ; ; xn--ghb2gxqia; ; ; # لٰۭۯ
+لٰۭۯ; ; ; xn--ghb2gxqia; ; ; # لٰۭۯ
+xn--ghb2gxqia7523a; لٰ‌ۭۯ; ; xn--ghb2gxqia7523a; ; ; # لٰۭۯ
+لٰ‌ۯ; ; ; xn--ghb2g3qq34f; ; xn--ghb2g3q; # لٰۯ
+xn--ghb2g3q; لٰۯ; ; xn--ghb2g3q; ; ; # لٰۯ
+لٰۯ; ; ; xn--ghb2g3q; ; ; # لٰۯ
+xn--ghb2g3qq34f; لٰ‌ۯ; ; xn--ghb2g3qq34f; ; ; # لٰۯ
+ل‌ۭۯ; ; ; xn--ghb25aga828w; ; xn--ghb25aga; # لۭۯ
+xn--ghb25aga; لۭۯ; ; xn--ghb25aga; ; ; # لۭۯ
+لۭۯ; ; ; xn--ghb25aga; ; ; # لۭۯ
+xn--ghb25aga828w; ل‌ۭۯ; ; xn--ghb25aga828w; ; ; # لۭۯ
+ل‌ۯ; ; ; xn--ghb65a953d; ; xn--ghb65a; # لۯ
+xn--ghb65a; لۯ; ; xn--ghb65a; ; ; # لۯ
+لۯ; ; ; xn--ghb65a; ; ; # لۯ
+xn--ghb65a953d; ل‌ۯ; ; xn--ghb65a953d; ; ; # لۯ
+لٰ‌ۭ; ; [B3, C1]; xn--ghb2gxqy34f; ; xn--ghb2gxq; [] # لٰۭ
+xn--ghb2gxq; لٰۭ; ; xn--ghb2gxq; ; ; # لٰۭ
+لٰۭ; ; ; xn--ghb2gxq; ; ; # لٰۭ
+xn--ghb2gxqy34f; لٰ‌ۭ; [B3, C1]; xn--ghb2gxqy34f; ; ; # لٰۭ
+ۯ‌ۯ; ; [C1]; xn--cmba004q; ; xn--cmba; [] # ۯۯ
+xn--cmba; ۯۯ; ; xn--cmba; ; ; # ۯۯ
+ۯۯ; ; ; xn--cmba; ; ; # ۯۯ
+xn--cmba004q; ۯ‌ۯ; [C1]; xn--cmba004q; ; ; # ۯۯ
+ل‌; ; [B3, C1]; xn--ghb413k; ; xn--ghb; [] # ل
+xn--ghb; ل; ; xn--ghb; ; ; # ل
+ل; ; ; xn--ghb; ; ; # ل
+xn--ghb413k; ل‌; [B3, C1]; xn--ghb413k; ; ; # ل
+a。。b; a..b; [X4_2]; ; [A4_2]; ; # a..b
+A。。B; a..b; [X4_2]; ; [A4_2]; ; # a..b
+a..b; ; [X4_2]; ; [A4_2]; ; # a..b
+‍。。ڹ‌; ‍..ڹ‌; [B1, B3, C1, C2, X4_2]; xn--1ug..xn--skb080k; [B1, B3, C1, C2, A4_2]; ..xn--skb; [A4_2] # ..ڹ
+..xn--skb; ..ڹ; [X4_2]; ..xn--skb; [A4_2]; ; # ..ڹ
+xn--1ug..xn--skb080k; ‍..ڹ‌; [B1, B3, C1, C2, X4_2]; xn--1ug..xn--skb080k; [B1, B3, C1, C2, A4_2]; ; # ..ڹ
+א0٠; ; [B4]; xn--0-zhc74b; ; ; # א0٠
+xn--0-zhc74b; א0٠; [B4]; xn--0-zhc74b; ; ; # א0٠
+$; ; [P1, V6]; ; ; ; # $
+
+# RANDOMIZED TESTS
+
+c.0ü.א; ; [B1]; c.xn--0-eha.xn--4db; ; ; # c.0ü.א
+c.0ü.א; c.0ü.א; [B1]; c.xn--0-eha.xn--4db; ; ; # c.0ü.א
+C.0Ü.א; c.0ü.א; [B1]; c.xn--0-eha.xn--4db; ; ; # c.0ü.א
+C.0Ü.א; c.0ü.א; [B1]; c.xn--0-eha.xn--4db; ; ; # c.0ü.א
+C.0ü.א; c.0ü.א; [B1]; c.xn--0-eha.xn--4db; ; ; # c.0ü.א
+C.0ü.א; c.0ü.א; [B1]; c.xn--0-eha.xn--4db; ; ; # c.0ü.א
+⒕∝ٟ򓤦.-󠄯; ⒕∝ٟ򓤦.-; [P1, V3, V6]; xn--7hb713lfwbi1311b.-; ; ; # ⒕∝ٟ.-
+14.∝ٟ򓤦.-󠄯; 14.∝ٟ򓤦.-; [P1, V3, V6]; 14.xn--7hb713l3v90n.-; ; ; # 14.∝ٟ.-
+14.xn--7hb713l3v90n.-; 14.∝ٟ򓤦.-; [V3, V6]; 14.xn--7hb713l3v90n.-; ; ; # 14.∝ٟ.-
+xn--7hb713lfwbi1311b.-; ⒕∝ٟ򓤦.-; [V3, V6]; xn--7hb713lfwbi1311b.-; ; ; # ⒕∝ٟ.-
+ꡣ.ߏ; ; ; xn--8c9a.xn--qsb; ; ; # ꡣ.ߏ
+xn--8c9a.xn--qsb; ꡣ.ߏ; ; xn--8c9a.xn--qsb; ; ; # ꡣ.ߏ
+≯؃。-; ≯؃.-; [B1, P1, V3, V6]; xn--lfb566l.-; ; ; # ≯.-
+≯؃。-; ≯؃.-; [B1, P1, V3, V6]; xn--lfb566l.-; ; ; # ≯.-
+≯؃。-; ≯؃.-; [B1, P1, V3, V6]; xn--lfb566l.-; ; ; # ≯.-
+≯؃。-; ≯؃.-; [B1, P1, V3, V6]; xn--lfb566l.-; ; ; # ≯.-
+xn--lfb566l.-; ≯؃.-; [B1, V3, V6]; xn--lfb566l.-; ; ; # ≯.-
+⾛𐹧⾕.ᅟ󠗰ςႭ; 走𐹧谷.ᅟ󠗰ςႭ; [B5, P1, V6]; xn--6g3a1x434z.xn--3xa827dhpae6345i; ; xn--6g3a1x434z.xn--4xa627dhpae6345i; # 走𐹧谷.ςႭ
+走𐹧谷.ᅟ󠗰ςႭ; ; [B5, P1, V6]; xn--6g3a1x434z.xn--3xa827dhpae6345i; ; xn--6g3a1x434z.xn--4xa627dhpae6345i; # 走𐹧谷.ςႭ
+走𐹧谷.ᅟ󠗰ςⴍ; ; [B5, P1, V6]; xn--6g3a1x434z.xn--3xa380eotvh7453a; ; xn--6g3a1x434z.xn--4xa180eotvh7453a; # 走𐹧谷.ςⴍ
+走𐹧谷.ᅟ󠗰ΣႭ; 走𐹧谷.ᅟ󠗰σႭ; [B5, P1, V6]; xn--6g3a1x434z.xn--4xa627dhpae6345i; ; ; # 走𐹧谷.σႭ
+走𐹧谷.ᅟ󠗰σⴍ; ; [B5, P1, V6]; xn--6g3a1x434z.xn--4xa180eotvh7453a; ; ; # 走𐹧谷.σⴍ
+走𐹧谷.ᅟ󠗰Σⴍ; 走𐹧谷.ᅟ󠗰σⴍ; [B5, P1, V6]; xn--6g3a1x434z.xn--4xa180eotvh7453a; ; ; # 走𐹧谷.σⴍ
+xn--6g3a1x434z.xn--4xa180eotvh7453a; 走𐹧谷.ᅟ󠗰σⴍ; [B5, V6]; xn--6g3a1x434z.xn--4xa180eotvh7453a; ; ; # 走𐹧谷.σⴍ
+xn--6g3a1x434z.xn--4xa627dhpae6345i; 走𐹧谷.ᅟ󠗰σႭ; [B5, V6]; xn--6g3a1x434z.xn--4xa627dhpae6345i; ; ; # 走𐹧谷.σႭ
+xn--6g3a1x434z.xn--3xa380eotvh7453a; 走𐹧谷.ᅟ󠗰ςⴍ; [B5, V6]; xn--6g3a1x434z.xn--3xa380eotvh7453a; ; ; # 走𐹧谷.ςⴍ
+xn--6g3a1x434z.xn--3xa827dhpae6345i; 走𐹧谷.ᅟ󠗰ςႭ; [B5, V6]; xn--6g3a1x434z.xn--3xa827dhpae6345i; ; ; # 走𐹧谷.ςႭ
+⾛𐹧⾕.ᅟ󠗰ςⴍ; 走𐹧谷.ᅟ󠗰ςⴍ; [B5, P1, V6]; xn--6g3a1x434z.xn--3xa380eotvh7453a; ; xn--6g3a1x434z.xn--4xa180eotvh7453a; # 走𐹧谷.ςⴍ
+⾛𐹧⾕.ᅟ󠗰ΣႭ; 走𐹧谷.ᅟ󠗰σႭ; [B5, P1, V6]; xn--6g3a1x434z.xn--4xa627dhpae6345i; ; ; # 走𐹧谷.σႭ
+⾛𐹧⾕.ᅟ󠗰σⴍ; 走𐹧谷.ᅟ󠗰σⴍ; [B5, P1, V6]; xn--6g3a1x434z.xn--4xa180eotvh7453a; ; ; # 走𐹧谷.σⴍ
+⾛𐹧⾕.ᅟ󠗰Σⴍ; 走𐹧谷.ᅟ󠗰σⴍ; [B5, P1, V6]; xn--6g3a1x434z.xn--4xa180eotvh7453a; ; ; # 走𐹧谷.σⴍ
+‍≠ᢙ≯.솣-ᡴႠ; ; [C2, P1, V6]; xn--jbf929a90b0b.xn----6zg521d196p; ; xn--jbf911clb.xn----6zg521d196p; [P1, V6] # ≠ᢙ≯.솣-ᡴႠ
+‍≠ᢙ≯.솣-ᡴႠ; ‍≠ᢙ≯.솣-ᡴႠ; [C2, P1, V6]; xn--jbf929a90b0b.xn----6zg521d196p; ; xn--jbf911clb.xn----6zg521d196p; [P1, V6] # ≠ᢙ≯.솣-ᡴႠ
+‍≠ᢙ≯.솣-ᡴⴀ; ‍≠ᢙ≯.솣-ᡴⴀ; [C2, P1, V6]; xn--jbf929a90b0b.xn----p9j493ivi4l; ; xn--jbf911clb.xn----p9j493ivi4l; [P1, V6] # ≠ᢙ≯.솣-ᡴⴀ
+‍≠ᢙ≯.솣-ᡴⴀ; ; [C2, P1, V6]; xn--jbf929a90b0b.xn----p9j493ivi4l; ; xn--jbf911clb.xn----p9j493ivi4l; [P1, V6] # ≠ᢙ≯.솣-ᡴⴀ
+xn--jbf911clb.xn----p9j493ivi4l; ≠ᢙ≯.솣-ᡴⴀ; [V6]; xn--jbf911clb.xn----p9j493ivi4l; ; ; # ≠ᢙ≯.솣-ᡴⴀ
+xn--jbf929a90b0b.xn----p9j493ivi4l; ‍≠ᢙ≯.솣-ᡴⴀ; [C2, V6]; xn--jbf929a90b0b.xn----p9j493ivi4l; ; ; # ≠ᢙ≯.솣-ᡴⴀ
+xn--jbf911clb.xn----6zg521d196p; ≠ᢙ≯.솣-ᡴႠ; [V6]; xn--jbf911clb.xn----6zg521d196p; ; ; # ≠ᢙ≯.솣-ᡴႠ
+xn--jbf929a90b0b.xn----6zg521d196p; ‍≠ᢙ≯.솣-ᡴႠ; [C2, V6]; xn--jbf929a90b0b.xn----6zg521d196p; ; ; # ≠ᢙ≯.솣-ᡴႠ
+񯞜.𐿇ྡྷݽ؀; 񯞜.𐿇ྡྷݽ؀; [P1, V6]; xn--gw68a.xn--ifb57ev2psc6027m; ; ; # .𐿇ྡྷݽ
+񯞜.𐿇ྡྷݽ؀; 񯞜.𐿇ྡྷݽ؀; [P1, V6]; xn--gw68a.xn--ifb57ev2psc6027m; ; ; # .𐿇ྡྷݽ
+񯞜.𐿇ྡྷݽ؀; ; [P1, V6]; xn--gw68a.xn--ifb57ev2psc6027m; ; ; # .𐿇ྡྷݽ
+xn--gw68a.xn--ifb57ev2psc6027m; 񯞜.𐿇ྡྷݽ؀; [V6]; xn--gw68a.xn--ifb57ev2psc6027m; ; ; # .𐿇ྡྷݽ
+𣳔̃.𑓂; ; [V5]; xn--nsa95820a.xn--wz1d; ; ; # 𣳔̃.𑓂
+xn--nsa95820a.xn--wz1d; 𣳔̃.𑓂; [V5]; xn--nsa95820a.xn--wz1d; ; ; # 𣳔̃.𑓂
+𞤀𞥅񘐱。󠄌Ⴣꡥ; 𞤢𞥅񘐱.Ⴣꡥ; [B2, B3, P1, V6]; xn--9d6hgcy3556a.xn--7nd0578e; ; ; # 𞤢𞥅.Ⴣꡥ
+𞤢𞥅񘐱。󠄌ⴣꡥ; 𞤢𞥅񘐱.ⴣꡥ; [B2, B3, P1, V6]; xn--9d6hgcy3556a.xn--rlju750b; ; ; # 𞤢𞥅.ⴣꡥ
+xn--9d6hgcy3556a.xn--rlju750b; 𞤢𞥅񘐱.ⴣꡥ; [B2, B3, V6]; xn--9d6hgcy3556a.xn--rlju750b; ; ; # 𞤢𞥅.ⴣꡥ
+xn--9d6hgcy3556a.xn--7nd0578e; 𞤢𞥅񘐱.Ⴣꡥ; [B2, B3, V6]; xn--9d6hgcy3556a.xn--7nd0578e; ; ; # 𞤢𞥅.Ⴣꡥ
+𞤀𞥅񘐱。󠄌ⴣꡥ; 𞤢𞥅񘐱.ⴣꡥ; [B2, B3, P1, V6]; xn--9d6hgcy3556a.xn--rlju750b; ; ; # 𞤢𞥅.ⴣꡥ
+࣢𑁿ς𖬱。󠅡렧; ࣢𑁿ς𖬱.렧; [B1, P1, V6]; xn--3xa73xp48ys2xc.xn--kn2b; ; xn--4xa53xp48ys2xc.xn--kn2b; # 𑁿ς𖬱.렧
+࣢𑁿ς𖬱。󠅡렧; ࣢𑁿ς𖬱.렧; [B1, P1, V6]; xn--3xa73xp48ys2xc.xn--kn2b; ; xn--4xa53xp48ys2xc.xn--kn2b; # 𑁿ς𖬱.렧
+࣢𑁿Σ𖬱。󠅡렧; ࣢𑁿σ𖬱.렧; [B1, P1, V6]; xn--4xa53xp48ys2xc.xn--kn2b; ; ; # 𑁿σ𖬱.렧
+࣢𑁿Σ𖬱。󠅡렧; ࣢𑁿σ𖬱.렧; [B1, P1, V6]; xn--4xa53xp48ys2xc.xn--kn2b; ; ; # 𑁿σ𖬱.렧
+࣢𑁿σ𖬱。󠅡렧; ࣢𑁿σ𖬱.렧; [B1, P1, V6]; xn--4xa53xp48ys2xc.xn--kn2b; ; ; # 𑁿σ𖬱.렧
+࣢𑁿σ𖬱。󠅡렧; ࣢𑁿σ𖬱.렧; [B1, P1, V6]; xn--4xa53xp48ys2xc.xn--kn2b; ; ; # 𑁿σ𖬱.렧
+xn--4xa53xp48ys2xc.xn--kn2b; ࣢𑁿σ𖬱.렧; [B1, V6]; xn--4xa53xp48ys2xc.xn--kn2b; ; ; # 𑁿σ𖬱.렧
+xn--3xa73xp48ys2xc.xn--kn2b; ࣢𑁿ς𖬱.렧; [B1, V6]; xn--3xa73xp48ys2xc.xn--kn2b; ; ; # 𑁿ς𖬱.렧
+-‍。𞤍‌‍⒈; -‍.𞤯‌‍⒈; [B1, C1, C2, P1, V3, V6]; xn----ugn.xn--0ugc555aiv51d; ; -.xn--tsh3666n; [B1, P1, V3, V6] # -.𞤯⒈
+-‍。𞤍‌‍1.; -‍.𞤯‌‍1.; [B1, C1, C2, V3]; xn----ugn.xn--1-rgnd61297b.; ; -.xn--1-0i8r.; [B1, V3] # -.𞤯1.
+-‍。𞤯‌‍1.; -‍.𞤯‌‍1.; [B1, C1, C2, V3]; xn----ugn.xn--1-rgnd61297b.; ; -.xn--1-0i8r.; [B1, V3] # -.𞤯1.
+-.xn--1-0i8r.; -.𞤯1.; [B1, V3]; -.xn--1-0i8r.; ; ; # -.𞤯1.
+xn----ugn.xn--1-rgnd61297b.; -‍.𞤯‌‍1.; [B1, C1, C2, V3]; xn----ugn.xn--1-rgnd61297b.; ; ; # -.𞤯1.
+-‍。𞤯‌‍⒈; -‍.𞤯‌‍⒈; [B1, C1, C2, P1, V3, V6]; xn----ugn.xn--0ugc555aiv51d; ; -.xn--tsh3666n; [B1, P1, V3, V6] # -.𞤯⒈
+-.xn--tsh3666n; -.𞤯⒈; [B1, V3, V6]; -.xn--tsh3666n; ; ; # -.𞤯⒈
+xn----ugn.xn--0ugc555aiv51d; -‍.𞤯‌‍⒈; [B1, C1, C2, V3, V6]; xn----ugn.xn--0ugc555aiv51d; ; ; # -.𞤯⒈
+‌򅎭.Ⴒ𑇀; ; [C1, P1, V6]; xn--0ug15083f.xn--qnd6272k; ; xn--bn95b.xn--qnd6272k; [P1, V6] # .Ⴒ𑇀
+‌򅎭.ⴒ𑇀; ; [C1, P1, V6]; xn--0ug15083f.xn--9kj2034e; ; xn--bn95b.xn--9kj2034e; [P1, V6] # .ⴒ𑇀
+xn--bn95b.xn--9kj2034e; 򅎭.ⴒ𑇀; [V6]; xn--bn95b.xn--9kj2034e; ; ; # .ⴒ𑇀
+xn--0ug15083f.xn--9kj2034e; ‌򅎭.ⴒ𑇀; [C1, V6]; xn--0ug15083f.xn--9kj2034e; ; ; # .ⴒ𑇀
+xn--bn95b.xn--qnd6272k; 򅎭.Ⴒ𑇀; [V6]; xn--bn95b.xn--qnd6272k; ; ; # .Ⴒ𑇀
+xn--0ug15083f.xn--qnd6272k; ‌򅎭.Ⴒ𑇀; [C1, V6]; xn--0ug15083f.xn--qnd6272k; ; ; # .Ⴒ𑇀
+繱𑖿‍.8︒; 繱𑖿‍.8︒; [P1, V6]; xn--1ug6928ac48e.xn--8-o89h; ; xn--gl0as212a.xn--8-o89h; # 繱𑖿.8︒
+繱𑖿‍.8。; 繱𑖿‍.8.; ; xn--1ug6928ac48e.8.; ; xn--gl0as212a.8.; # 繱𑖿.8.
+xn--gl0as212a.8.; 繱𑖿.8.; ; xn--gl0as212a.8.; ; ; # 繱𑖿.8.
+繱𑖿.8.; ; ; xn--gl0as212a.8.; ; ; # 繱𑖿.8.
+xn--1ug6928ac48e.8.; 繱𑖿‍.8.; ; xn--1ug6928ac48e.8.; ; ; # 繱𑖿.8.
+繱𑖿‍.8.; ; ; xn--1ug6928ac48e.8.; ; xn--gl0as212a.8.; # 繱𑖿.8.
+xn--gl0as212a.xn--8-o89h; 繱𑖿.8︒; [V6]; xn--gl0as212a.xn--8-o89h; ; ; # 繱𑖿.8︒
+xn--1ug6928ac48e.xn--8-o89h; 繱𑖿‍.8︒; [V6]; xn--1ug6928ac48e.xn--8-o89h; ; ; # 繱𑖿.8︒
+󠆾.𞀈; .𞀈; [V5, X4_2]; .xn--ph4h; [V5, A4_2]; ; # .𞀈
+󠆾.𞀈; .𞀈; [V5, X4_2]; .xn--ph4h; [V5, A4_2]; ; # .𞀈
+.xn--ph4h; .𞀈; [V5, X4_2]; .xn--ph4h; [V5, A4_2]; ; # .𞀈
+ß۫。‍; ß۫.‍; [C2]; xn--zca012a.xn--1ug; ; xn--ss-59d.; [] # ß۫.
+SS۫。‍; ss۫.‍; [C2]; xn--ss-59d.xn--1ug; ; xn--ss-59d.; [] # ss۫.
+ss۫。‍; ss۫.‍; [C2]; xn--ss-59d.xn--1ug; ; xn--ss-59d.; [] # ss۫.
+Ss۫。‍; ss۫.‍; [C2]; xn--ss-59d.xn--1ug; ; xn--ss-59d.; [] # ss۫.
+xn--ss-59d.; ss۫.; ; xn--ss-59d.; ; ; # ss۫.
+ss۫.; ; ; xn--ss-59d.; ; ; # ss۫.
+SS۫.; ss۫.; ; xn--ss-59d.; ; ; # ss۫.
+Ss۫.; ss۫.; ; xn--ss-59d.; ; ; # ss۫.
+xn--ss-59d.xn--1ug; ss۫.‍; [C2]; xn--ss-59d.xn--1ug; ; ; # ss۫.
+xn--zca012a.xn--1ug; ß۫.‍; [C2]; xn--zca012a.xn--1ug; ; ; # ß۫.
+󠐵‌⒈.󠎇; 󠐵‌⒈.󠎇; [C1, P1, V6]; xn--0ug88o47900b.xn--tv36e; ; xn--tshz2001k.xn--tv36e; [P1, V6] # ⒈.
+󠐵‌1..󠎇; ; [C1, P1, V6, X4_2]; xn--1-rgn37671n..xn--tv36e; [C1, P1, V6, A4_2]; xn--1-bs31m..xn--tv36e; [P1, V6, A4_2] # 1..
+xn--1-bs31m..xn--tv36e; 󠐵1..󠎇; [V6, X4_2]; xn--1-bs31m..xn--tv36e; [V6, A4_2]; ; # 1..
+xn--1-rgn37671n..xn--tv36e; 󠐵‌1..󠎇; [C1, V6, X4_2]; xn--1-rgn37671n..xn--tv36e; [C1, V6, A4_2]; ; # 1..
+xn--tshz2001k.xn--tv36e; 󠐵⒈.󠎇; [V6]; xn--tshz2001k.xn--tv36e; ; ; # ⒈.
+xn--0ug88o47900b.xn--tv36e; 󠐵‌⒈.󠎇; [C1, V6]; xn--0ug88o47900b.xn--tv36e; ; ; # ⒈.
+󟈣ٟꪲß。󌓧; 󟈣ٟꪲß.󌓧; [P1, V6]; xn--zca92z0t7n5w96j.xn--bb79d; ; xn--ss-3xd2839nncy1m.xn--bb79d; # ٟꪲß.
+󟈣ٟꪲSS。󌓧; 󟈣ٟꪲss.󌓧; [P1, V6]; xn--ss-3xd2839nncy1m.xn--bb79d; ; ; # ٟꪲss.
+󟈣ٟꪲss。󌓧; 󟈣ٟꪲss.󌓧; [P1, V6]; xn--ss-3xd2839nncy1m.xn--bb79d; ; ; # ٟꪲss.
+󟈣ٟꪲSs。󌓧; 󟈣ٟꪲss.󌓧; [P1, V6]; xn--ss-3xd2839nncy1m.xn--bb79d; ; ; # ٟꪲss.
+xn--ss-3xd2839nncy1m.xn--bb79d; 󟈣ٟꪲss.󌓧; [V6]; xn--ss-3xd2839nncy1m.xn--bb79d; ; ; # ٟꪲss.
+xn--zca92z0t7n5w96j.xn--bb79d; 󟈣ٟꪲß.󌓧; [V6]; xn--zca92z0t7n5w96j.xn--bb79d; ; ; # ٟꪲß.
+ݴ‌𞤿。𽘐䉜‍񿤼; ݴ‌𞤿.𽘐䉜‍񿤼; [C1, C2, P1, V6]; xn--4pb607jjt73a.xn--1ug236ke314donv1a; ; xn--4pb2977v.xn--z0nt555ukbnv; [P1, V6] # ݴ𞤿.䉜
+ݴ‌𞤝。𽘐䉜‍񿤼; ݴ‌𞤿.𽘐䉜‍񿤼; [C1, C2, P1, V6]; xn--4pb607jjt73a.xn--1ug236ke314donv1a; ; xn--4pb2977v.xn--z0nt555ukbnv; [P1, V6] # ݴ𞤿.䉜
+xn--4pb2977v.xn--z0nt555ukbnv; ݴ𞤿.𽘐䉜񿤼; [V6]; xn--4pb2977v.xn--z0nt555ukbnv; ; ; # ݴ𞤿.䉜
+xn--4pb607jjt73a.xn--1ug236ke314donv1a; ݴ‌𞤿.𽘐䉜‍񿤼; [C1, C2, V6]; xn--4pb607jjt73a.xn--1ug236ke314donv1a; ; ; # ݴ𞤿.䉜
+򔭜ςᡱ⒈.≮𑄳‍𐮍; ; [B1, P1, V6]; xn--3xa407hkzinr77u.xn--1ug85gn777ahze; ; xn--4xa207hkzinr77u.xn--gdh5392g6sd; # ςᡱ⒈.≮𑄳𐮍
+򔭜ςᡱ⒈.≮𑄳‍𐮍; 򔭜ςᡱ⒈.≮𑄳‍𐮍; [B1, P1, V6]; xn--3xa407hkzinr77u.xn--1ug85gn777ahze; ; xn--4xa207hkzinr77u.xn--gdh5392g6sd; # ςᡱ⒈.≮𑄳𐮍
+򔭜ςᡱ1..≮𑄳‍𐮍; ; [B1, P1, V6, X4_2]; xn--1-xmb999meq63t..xn--1ug85gn777ahze; [B1, P1, V6, A4_2]; xn--1-zmb699meq63t..xn--gdh5392g6sd; # ςᡱ1..≮𑄳𐮍
+򔭜ςᡱ1..≮𑄳‍𐮍; 򔭜ςᡱ1..≮𑄳‍𐮍; [B1, P1, V6, X4_2]; xn--1-xmb999meq63t..xn--1ug85gn777ahze; [B1, P1, V6, A4_2]; xn--1-zmb699meq63t..xn--gdh5392g6sd; # ςᡱ1..≮𑄳𐮍
+򔭜Σᡱ1..≮𑄳‍𐮍; 򔭜σᡱ1..≮𑄳‍𐮍; [B1, P1, V6, X4_2]; xn--1-zmb699meq63t..xn--1ug85gn777ahze; [B1, P1, V6, A4_2]; xn--1-zmb699meq63t..xn--gdh5392g6sd; # σᡱ1..≮𑄳𐮍
+򔭜Σᡱ1..≮𑄳‍𐮍; 򔭜σᡱ1..≮𑄳‍𐮍; [B1, P1, V6, X4_2]; xn--1-zmb699meq63t..xn--1ug85gn777ahze; [B1, P1, V6, A4_2]; xn--1-zmb699meq63t..xn--gdh5392g6sd; # σᡱ1..≮𑄳𐮍
+򔭜σᡱ1..≮𑄳‍𐮍; ; [B1, P1, V6, X4_2]; xn--1-zmb699meq63t..xn--1ug85gn777ahze; [B1, P1, V6, A4_2]; xn--1-zmb699meq63t..xn--gdh5392g6sd; # σᡱ1..≮𑄳𐮍
+򔭜σᡱ1..≮𑄳‍𐮍; 򔭜σᡱ1..≮𑄳‍𐮍; [B1, P1, V6, X4_2]; xn--1-zmb699meq63t..xn--1ug85gn777ahze; [B1, P1, V6, A4_2]; xn--1-zmb699meq63t..xn--gdh5392g6sd; # σᡱ1..≮𑄳𐮍
+xn--1-zmb699meq63t..xn--gdh5392g6sd; 򔭜σᡱ1..≮𑄳𐮍; [B1, V6, X4_2]; xn--1-zmb699meq63t..xn--gdh5392g6sd; [B1, V6, A4_2]; ; # σᡱ1..≮𑄳𐮍
+xn--1-zmb699meq63t..xn--1ug85gn777ahze; 򔭜σᡱ1..≮𑄳‍𐮍; [B1, V6, X4_2]; xn--1-zmb699meq63t..xn--1ug85gn777ahze; [B1, V6, A4_2]; ; # σᡱ1..≮𑄳𐮍
+xn--1-xmb999meq63t..xn--1ug85gn777ahze; 򔭜ςᡱ1..≮𑄳‍𐮍; [B1, V6, X4_2]; xn--1-xmb999meq63t..xn--1ug85gn777ahze; [B1, V6, A4_2]; ; # ςᡱ1..≮𑄳𐮍
+򔭜Σᡱ⒈.≮𑄳‍𐮍; 򔭜σᡱ⒈.≮𑄳‍𐮍; [B1, P1, V6]; xn--4xa207hkzinr77u.xn--1ug85gn777ahze; ; xn--4xa207hkzinr77u.xn--gdh5392g6sd; # σᡱ⒈.≮𑄳𐮍
+򔭜Σᡱ⒈.≮𑄳‍𐮍; 򔭜σᡱ⒈.≮𑄳‍𐮍; [B1, P1, V6]; xn--4xa207hkzinr77u.xn--1ug85gn777ahze; ; xn--4xa207hkzinr77u.xn--gdh5392g6sd; # σᡱ⒈.≮𑄳𐮍
+򔭜σᡱ⒈.≮𑄳‍𐮍; ; [B1, P1, V6]; xn--4xa207hkzinr77u.xn--1ug85gn777ahze; ; xn--4xa207hkzinr77u.xn--gdh5392g6sd; # σᡱ⒈.≮𑄳𐮍
+򔭜σᡱ⒈.≮𑄳‍𐮍; 򔭜σᡱ⒈.≮𑄳‍𐮍; [B1, P1, V6]; xn--4xa207hkzinr77u.xn--1ug85gn777ahze; ; xn--4xa207hkzinr77u.xn--gdh5392g6sd; # σᡱ⒈.≮𑄳𐮍
+xn--4xa207hkzinr77u.xn--gdh5392g6sd; 򔭜σᡱ⒈.≮𑄳𐮍; [B1, V6]; xn--4xa207hkzinr77u.xn--gdh5392g6sd; ; ; # σᡱ⒈.≮𑄳𐮍
+xn--4xa207hkzinr77u.xn--1ug85gn777ahze; 򔭜σᡱ⒈.≮𑄳‍𐮍; [B1, V6]; xn--4xa207hkzinr77u.xn--1ug85gn777ahze; ; ; # σᡱ⒈.≮𑄳𐮍
+xn--3xa407hkzinr77u.xn--1ug85gn777ahze; 򔭜ςᡱ⒈.≮𑄳‍𐮍; [B1, V6]; xn--3xa407hkzinr77u.xn--1ug85gn777ahze; ; ; # ςᡱ⒈.≮𑄳𐮍
+ㅤ्Ⴀ័.᠋; ㅤ्Ⴀ័.; [P1, V6]; xn--n3b468azngju2a.; ; ; # ्Ⴀ័.
+ᅠ्Ⴀ័.᠋; ᅠ्Ⴀ័.; [P1, V6]; xn--n3b468aoqa89r.; ; ; # ्Ⴀ័.
+ᅠ्ⴀ័.᠋; ᅠ्ⴀ័.; [P1, V6]; xn--n3b742bkqf4ty.; ; ; # ्ⴀ័.
+xn--n3b742bkqf4ty.; ᅠ्ⴀ័.; [V6]; xn--n3b742bkqf4ty.; ; ; # ्ⴀ័.
+xn--n3b468aoqa89r.; ᅠ्Ⴀ័.; [V6]; xn--n3b468aoqa89r.; ; ; # ्Ⴀ័.
+ㅤ्ⴀ័.᠋; ㅤ्ⴀ័.; [P1, V6]; xn--n3b445e53po6d.; ; ; # ्ⴀ័.
+xn--n3b445e53po6d.; ㅤ्ⴀ័.; [V6]; xn--n3b445e53po6d.; ; ; # ्ⴀ័.
+xn--n3b468azngju2a.; ㅤ्Ⴀ័.; [V6]; xn--n3b468azngju2a.; ; ; # ्Ⴀ័.
+❣‍.্𑰽ؒꤩ; ❣‍.্𑰽ؒꤩ; [C2, V5]; xn--1ugy10a.xn--0fb32q3w7q2g4d; ; xn--pei.xn--0fb32q3w7q2g4d; [V5] # ❣.্𑰽ؒꤩ
+❣‍.্𑰽ؒꤩ; ; [C2, V5]; xn--1ugy10a.xn--0fb32q3w7q2g4d; ; xn--pei.xn--0fb32q3w7q2g4d; [V5] # ❣.্𑰽ؒꤩ
+xn--pei.xn--0fb32q3w7q2g4d; ❣.্𑰽ؒꤩ; [V5]; xn--pei.xn--0fb32q3w7q2g4d; ; ; # ❣.্𑰽ؒꤩ
+xn--1ugy10a.xn--0fb32q3w7q2g4d; ❣‍.্𑰽ؒꤩ; [C2, V5]; xn--1ugy10a.xn--0fb32q3w7q2g4d; ; ; # ❣.্𑰽ؒꤩ
+≮𐳺𐹄.≯񪮸ꡅ; ; [B1, P1, V6]; xn--gdh7943gk2a.xn--hdh1383c5e36c; ; ; # ≮𐳺.≯ꡅ
+≮𐳺𐹄.≯񪮸ꡅ; ≮𐳺𐹄.≯񪮸ꡅ; [B1, P1, V6]; xn--gdh7943gk2a.xn--hdh1383c5e36c; ; ; # ≮𐳺.≯ꡅ
+xn--gdh7943gk2a.xn--hdh1383c5e36c; ≮𐳺𐹄.≯񪮸ꡅ; [B1, V6]; xn--gdh7943gk2a.xn--hdh1383c5e36c; ; ; # ≮𐳺.≯ꡅ
+ೌ𐧅𐳏󠲺。್ᠦ; ೌ𐧅𐳏󠲺.್ᠦ; [B1, P1, V5, V6]; xn--7tc6360ky5bn2732c.xn--8tc429c; ; ; # ೌ𐧅𐳏.್ᠦ
+ೌ𐧅𐳏󠲺。್ᠦ; ೌ𐧅𐳏󠲺.್ᠦ; [B1, P1, V5, V6]; xn--7tc6360ky5bn2732c.xn--8tc429c; ; ; # ೌ𐧅𐳏.್ᠦ
+ೌ𐧅𐲏󠲺。್ᠦ; ೌ𐧅𐳏󠲺.್ᠦ; [B1, P1, V5, V6]; xn--7tc6360ky5bn2732c.xn--8tc429c; ; ; # ೌ𐧅𐳏.್ᠦ
+xn--7tc6360ky5bn2732c.xn--8tc429c; ೌ𐧅𐳏󠲺.್ᠦ; [B1, V5, V6]; xn--7tc6360ky5bn2732c.xn--8tc429c; ; ; # ೌ𐧅𐳏.್ᠦ
+ೌ𐧅𐲏󠲺。್ᠦ; ೌ𐧅𐳏󠲺.್ᠦ; [B1, P1, V5, V6]; xn--7tc6360ky5bn2732c.xn--8tc429c; ; ; # ೌ𐧅𐳏.್ᠦ
+͉。𧡫; ͉.𧡫; [V5]; xn--nua.xn--bc6k; ; ; # ͉.𧡫
+xn--nua.xn--bc6k; ͉.𧡫; [V5]; xn--nua.xn--bc6k; ; ; # ͉.𧡫
+𑰿󠅦.ᅠ; 𑰿.ᅠ; [P1, V5, V6]; xn--ok3d.xn--psd; ; ; # 𑰿.
+𑰿󠅦.ᅠ; 𑰿.ᅠ; [P1, V5, V6]; xn--ok3d.xn--psd; ; ; # 𑰿.
+xn--ok3d.xn--psd; 𑰿.ᅠ; [V5, V6]; xn--ok3d.xn--psd; ; ; # 𑰿.
+-𞤆‍。󸼄𞳒; -𞤨‍.󸼄𞳒; [B1, B5, B6, C2, P1, V3, V6]; xn----ugnx367r.xn--846h96596c; ; xn----ni8r.xn--846h96596c; [B1, B5, B6, P1, V3, V6] # -𞤨.
+-𞤨‍。󸼄𞳒; -𞤨‍.󸼄𞳒; [B1, B5, B6, C2, P1, V3, V6]; xn----ugnx367r.xn--846h96596c; ; xn----ni8r.xn--846h96596c; [B1, B5, B6, P1, V3, V6] # -𞤨.
+xn----ni8r.xn--846h96596c; -𞤨.󸼄𞳒; [B1, B5, B6, V3, V6]; xn----ni8r.xn--846h96596c; ; ; # -𞤨.
+xn----ugnx367r.xn--846h96596c; -𞤨‍.󸼄𞳒; [B1, B5, B6, C2, V3, V6]; xn----ugnx367r.xn--846h96596c; ; ; # -𞤨.
+ꡏ󠇶≯𳾽。᷽⾇滸𐹰; ꡏ󠇶≯𳾽.᷽舛滸𐹰; [B1, P1, V5, V6]; xn--hdh7483cu6twwki8e.xn--yfg0765a58l0n6k; ; ; # ꡏ≯.᷽舛滸𐹰
+ꡏ󠇶≯𳾽。᷽⾇滸𐹰; ꡏ󠇶≯𳾽.᷽舛滸𐹰; [B1, P1, V5, V6]; xn--hdh7483cu6twwki8e.xn--yfg0765a58l0n6k; ; ; # ꡏ≯.᷽舛滸𐹰
+ꡏ󠇶≯𳾽。᷽舛滸𐹰; ꡏ󠇶≯𳾽.᷽舛滸𐹰; [B1, P1, V5, V6]; xn--hdh7483cu6twwki8e.xn--yfg0765a58l0n6k; ; ; # ꡏ≯.᷽舛滸𐹰
+ꡏ󠇶≯𳾽。᷽舛滸𐹰; ꡏ󠇶≯𳾽.᷽舛滸𐹰; [B1, P1, V5, V6]; xn--hdh7483cu6twwki8e.xn--yfg0765a58l0n6k; ; ; # ꡏ≯.᷽舛滸𐹰
+xn--hdh7483cu6twwki8e.xn--yfg0765a58l0n6k; ꡏ󠇶≯𳾽.᷽舛滸𐹰; [B1, V5, V6]; xn--hdh7483cu6twwki8e.xn--yfg0765a58l0n6k; ; ; # ꡏ≯.᷽舛滸𐹰
+蔏。𑰺; 蔏.𑰺; [V5]; xn--uy1a.xn--jk3d; ; ; # 蔏.𑰺
+蔏。𑰺; 蔏.𑰺; [V5]; xn--uy1a.xn--jk3d; ; ; # 蔏.𑰺
+xn--uy1a.xn--jk3d; 蔏.𑰺; [V5]; xn--uy1a.xn--jk3d; ; ; # 蔏.𑰺
+𝟿𐮋。󠄊; 9𐮋.; [B1]; xn--9-rv5i.; ; ; # 9𐮋.
+9𐮋。󠄊; 9𐮋.; [B1]; xn--9-rv5i.; ; ; # 9𐮋.
+xn--9-rv5i.; 9𐮋.; [B1]; xn--9-rv5i.; ; ; # 9𐮋.
+󟇇-䟖F。ߋ⒈٢; 󟇇-䟖f.ߋ⒈٢; [B4, P1, V6]; xn---f-mz8b08788k.xn--bib53ev44d; ; ; # -䟖f.ߋ⒈٢
+󟇇-䟖F。ߋ1.٢; 󟇇-䟖f.ߋ1.٢; [B1, P1, V6]; xn---f-mz8b08788k.xn--1-ybd.xn--bib; ; ; # -䟖f.ߋ1.٢
+󟇇-䟖f。ߋ1.٢; 󟇇-䟖f.ߋ1.٢; [B1, P1, V6]; xn---f-mz8b08788k.xn--1-ybd.xn--bib; ; ; # -䟖f.ߋ1.٢
+xn---f-mz8b08788k.xn--1-ybd.xn--bib; 󟇇-䟖f.ߋ1.٢; [B1, V6]; xn---f-mz8b08788k.xn--1-ybd.xn--bib; ; ; # -䟖f.ߋ1.٢
+󟇇-䟖f。ߋ⒈٢; 󟇇-䟖f.ߋ⒈٢; [B4, P1, V6]; xn---f-mz8b08788k.xn--bib53ev44d; ; ; # -䟖f.ߋ⒈٢
+xn---f-mz8b08788k.xn--bib53ev44d; 󟇇-䟖f.ߋ⒈٢; [B4, V6]; xn---f-mz8b08788k.xn--bib53ev44d; ; ; # -䟖f.ߋ⒈٢
+‌。𐹺; ‌.𐹺; [B1, C1]; xn--0ug.xn--yo0d; ; .xn--yo0d; [B1, A4_2] # .𐹺
+‌。𐹺; ‌.𐹺; [B1, C1]; xn--0ug.xn--yo0d; ; .xn--yo0d; [B1, A4_2] # .𐹺
+.xn--yo0d; .𐹺; [B1, X4_2]; .xn--yo0d; [B1, A4_2]; ; # .𐹺
+xn--0ug.xn--yo0d; ‌.𐹺; [B1, C1]; xn--0ug.xn--yo0d; ; ; # .𐹺
+𐡆.≯‌-𞥀; ; [B1, C1, P1, V6]; xn--le9c.xn----rgn40iy359e; ; xn--le9c.xn----ogo9956r; [B1, P1, V6] # 𐡆.≯-𞥀
+𐡆.≯‌-𞥀; 𐡆.≯‌-𞥀; [B1, C1, P1, V6]; xn--le9c.xn----rgn40iy359e; ; xn--le9c.xn----ogo9956r; [B1, P1, V6] # 𐡆.≯-𞥀
+𐡆.≯‌-𞤞; 𐡆.≯‌-𞥀; [B1, C1, P1, V6]; xn--le9c.xn----rgn40iy359e; ; xn--le9c.xn----ogo9956r; [B1, P1, V6] # 𐡆.≯-𞥀
+𐡆.≯‌-𞤞; 𐡆.≯‌-𞥀; [B1, C1, P1, V6]; xn--le9c.xn----rgn40iy359e; ; xn--le9c.xn----ogo9956r; [B1, P1, V6] # 𐡆.≯-𞥀
+xn--le9c.xn----ogo9956r; 𐡆.≯-𞥀; [B1, V6]; xn--le9c.xn----ogo9956r; ; ; # 𐡆.≯-𞥀
+xn--le9c.xn----rgn40iy359e; 𐡆.≯‌-𞥀; [B1, C1, V6]; xn--le9c.xn----rgn40iy359e; ; ; # 𐡆.≯-𞥀
+󠁀-。≠ﳗ; 󠁀-.≠هج; [B1, P1, V3, V6]; xn----f411m.xn--rgb7c611j; ; ; # -.≠هج
+󠁀-。≠ﳗ; 󠁀-.≠هج; [B1, P1, V3, V6]; xn----f411m.xn--rgb7c611j; ; ; # -.≠هج
+󠁀-。≠هج; 󠁀-.≠هج; [B1, P1, V3, V6]; xn----f411m.xn--rgb7c611j; ; ; # -.≠هج
+󠁀-。≠هج; 󠁀-.≠هج; [B1, P1, V3, V6]; xn----f411m.xn--rgb7c611j; ; ; # -.≠هج
+xn----f411m.xn--rgb7c611j; 󠁀-.≠هج; [B1, V3, V6]; xn----f411m.xn--rgb7c611j; ; ; # -.≠هج
+񻬹𑈵。‍𞨶; 񻬹𑈵.‍𞨶; [B1, C2, P1, V6]; xn--8g1d12120a.xn--1ug6651p; ; xn--8g1d12120a.xn--5l6h; [P1, V6] # 𑈵.
+xn--8g1d12120a.xn--5l6h; 񻬹𑈵.𞨶; [V6]; xn--8g1d12120a.xn--5l6h; ; ; # 𑈵.
+xn--8g1d12120a.xn--1ug6651p; 񻬹𑈵.‍𞨶; [B1, C2, V6]; xn--8g1d12120a.xn--1ug6651p; ; ; # 𑈵.
+𑋧꧀2。㧉򒖄; 𑋧꧀2.㧉򒖄; [P1, V5, V6]; xn--2-5z4eu89y.xn--97l02706d; ; ; # 𑋧꧀2.㧉
+𑋧꧀2。㧉򒖄; 𑋧꧀2.㧉򒖄; [P1, V5, V6]; xn--2-5z4eu89y.xn--97l02706d; ; ; # 𑋧꧀2.㧉
+xn--2-5z4eu89y.xn--97l02706d; 𑋧꧀2.㧉򒖄; [V5, V6]; xn--2-5z4eu89y.xn--97l02706d; ; ; # 𑋧꧀2.㧉
+‌𽬄𐹴𞩥。≯6; ‌𽬄𐹴𞩥.≯6; [B1, C1, P1, V6]; xn--0ug7105gf5wfxepq.xn--6-ogo; ; xn--so0du768aim9m.xn--6-ogo; [B1, B5, B6, P1, V6] # 𐹴.≯6
+‌𽬄𐹴𞩥。≯6; ‌𽬄𐹴𞩥.≯6; [B1, C1, P1, V6]; xn--0ug7105gf5wfxepq.xn--6-ogo; ; xn--so0du768aim9m.xn--6-ogo; [B1, B5, B6, P1, V6] # 𐹴.≯6
+xn--so0du768aim9m.xn--6-ogo; 𽬄𐹴𞩥.≯6; [B1, B5, B6, V6]; xn--so0du768aim9m.xn--6-ogo; ; ; # 𐹴.≯6
+xn--0ug7105gf5wfxepq.xn--6-ogo; ‌𽬄𐹴𞩥.≯6; [B1, C1, V6]; xn--0ug7105gf5wfxepq.xn--6-ogo; ; ; # 𐹴.≯6
+𑁿.𐹦𻞵-‍; 𑁿.𐹦𻞵-‍; [B1, B3, B6, C2, P1, V5, V6]; xn--q30d.xn----ugn1088hfsxv; ; xn--q30d.xn----i26i1299n; [B1, B3, B6, P1, V3, V5, V6] # 𑁿.𐹦-
+𑁿.𐹦𻞵-‍; ; [B1, B3, B6, C2, P1, V5, V6]; xn--q30d.xn----ugn1088hfsxv; ; xn--q30d.xn----i26i1299n; [B1, B3, B6, P1, V3, V5, V6] # 𑁿.𐹦-
+xn--q30d.xn----i26i1299n; 𑁿.𐹦𻞵-; [B1, B3, B6, V3, V5, V6]; xn--q30d.xn----i26i1299n; ; ; # 𑁿.𐹦-
+xn--q30d.xn----ugn1088hfsxv; 𑁿.𐹦𻞵-‍; [B1, B3, B6, C2, V5, V6]; xn--q30d.xn----ugn1088hfsxv; ; ; # 𑁿.𐹦-
+⤸ς𺱀。ᅠ; ⤸ς𺱀.ᅠ; [P1, V6]; xn--3xa392qmp03d.xn--cl7c; ; xn--4xa192qmp03d.xn--cl7c; # ⤸ς.
+⤸ς𺱀。ᅠ; ⤸ς𺱀.ᅠ; [P1, V6]; xn--3xa392qmp03d.xn--psd; ; xn--4xa192qmp03d.xn--psd; # ⤸ς.
+⤸Σ𺱀。ᅠ; ⤸σ𺱀.ᅠ; [P1, V6]; xn--4xa192qmp03d.xn--psd; ; ; # ⤸σ.
+⤸σ𺱀。ᅠ; ⤸σ𺱀.ᅠ; [P1, V6]; xn--4xa192qmp03d.xn--psd; ; ; # ⤸σ.
+xn--4xa192qmp03d.xn--psd; ⤸σ𺱀.ᅠ; [V6]; xn--4xa192qmp03d.xn--psd; ; ; # ⤸σ.
+xn--3xa392qmp03d.xn--psd; ⤸ς𺱀.ᅠ; [V6]; xn--3xa392qmp03d.xn--psd; ; ; # ⤸ς.
+⤸Σ𺱀。ᅠ; ⤸σ𺱀.ᅠ; [P1, V6]; xn--4xa192qmp03d.xn--cl7c; ; ; # ⤸σ.
+⤸σ𺱀。ᅠ; ⤸σ𺱀.ᅠ; [P1, V6]; xn--4xa192qmp03d.xn--cl7c; ; ; # ⤸σ.
+xn--4xa192qmp03d.xn--cl7c; ⤸σ𺱀.ᅠ; [V6]; xn--4xa192qmp03d.xn--cl7c; ; ; # ⤸σ.
+xn--3xa392qmp03d.xn--cl7c; ⤸ς𺱀.ᅠ; [V6]; xn--3xa392qmp03d.xn--cl7c; ; ; # ⤸ς.
+ݥဵ𐫔ە.𐦬𑋪Ⴃ; ; [B2, B3, P1, V6]; xn--llb10as9tqp5y.xn--bnd9168j21f; ; ; # ݥဵ𐫔ە.𐦬𑋪Ⴃ
+ݥဵ𐫔ە.𐦬𑋪ⴃ; ; [B2, B3]; xn--llb10as9tqp5y.xn--ukj7371e21f; ; ; # ݥဵ𐫔ە.𐦬𑋪ⴃ
+xn--llb10as9tqp5y.xn--ukj7371e21f; ݥဵ𐫔ە.𐦬𑋪ⴃ; [B2, B3]; xn--llb10as9tqp5y.xn--ukj7371e21f; ; ; # ݥဵ𐫔ە.𐦬𑋪ⴃ
+xn--llb10as9tqp5y.xn--bnd9168j21f; ݥဵ𐫔ە.𐦬𑋪Ⴃ; [B2, B3, V6]; xn--llb10as9tqp5y.xn--bnd9168j21f; ; ; # ݥဵ𐫔ە.𐦬𑋪Ⴃ
+١᭄-킼.᮪ؖ٬≯; ; [B1, B5, B6, P1, V5, V6]; xn----9pc551nk39n.xn--4fb6o571degg; ; ; # ١᭄-킼.᮪ؖ٬≯
+١᭄-킼.᮪ؖ٬≯; ١᭄-킼.᮪ؖ٬≯; [B1, B5, B6, P1, V5, V6]; xn----9pc551nk39n.xn--4fb6o571degg; ; ; # ١᭄-킼.᮪ؖ٬≯
+xn----9pc551nk39n.xn--4fb6o571degg; ١᭄-킼.᮪ؖ٬≯; [B1, B5, B6, V5, V6]; xn----9pc551nk39n.xn--4fb6o571degg; ; ; # ١᭄-킼.᮪ؖ٬≯
+-。ۂ؄򅖡𑓂; -.ۂ؄򅖡𑓂; [B1, B2, B3, P1, V3, V6]; -.xn--mfb39a7208dzgs3d; ; ; # -.ۂ𑓂
+-。ۂ؄򅖡𑓂; -.ۂ؄򅖡𑓂; [B1, B2, B3, P1, V3, V6]; -.xn--mfb39a7208dzgs3d; ; ; # -.ۂ𑓂
+-.xn--mfb39a7208dzgs3d; -.ۂ؄򅖡𑓂; [B1, B2, B3, V3, V6]; -.xn--mfb39a7208dzgs3d; ; ; # -.ۂ𑓂
+‍󯑖󠁐.ֽ𙮰ꡝ𐋡; ‍󯑖󠁐.ֽ𙮰ꡝ𐋡; [C2, P1, V5, V6]; xn--1ug66101lt8me.xn--ldb8734fg0qcyzzg; ; xn--b726ey18m.xn--ldb8734fg0qcyzzg; [P1, V5, V6] # .ֽꡝ𐋡
+‍󯑖󠁐.ֽ𙮰ꡝ𐋡; ; [C2, P1, V5, V6]; xn--1ug66101lt8me.xn--ldb8734fg0qcyzzg; ; xn--b726ey18m.xn--ldb8734fg0qcyzzg; [P1, V5, V6] # .ֽꡝ𐋡
+xn--b726ey18m.xn--ldb8734fg0qcyzzg; 󯑖󠁐.ֽ𙮰ꡝ𐋡; [V5, V6]; xn--b726ey18m.xn--ldb8734fg0qcyzzg; ; ; # .ֽꡝ𐋡
+xn--1ug66101lt8me.xn--ldb8734fg0qcyzzg; ‍󯑖󠁐.ֽ𙮰ꡝ𐋡; [C2, V5, V6]; xn--1ug66101lt8me.xn--ldb8734fg0qcyzzg; ; ; # .ֽꡝ𐋡
+︒􃈵ς񀠇。𐮈; ︒􃈵ς񀠇.𐮈; [B1, P1, V6]; xn--3xa3729jwz5t7gl5f.xn--f29c; ; xn--4xa1729jwz5t7gl5f.xn--f29c; # ︒ς.𐮈
+。􃈵ς񀠇。𐮈; .􃈵ς񀠇.𐮈; [P1, V6, X4_2]; .xn--3xa88573c7n64d.xn--f29c; [P1, V6, A4_2]; .xn--4xa68573c7n64d.xn--f29c; # .ς.𐮈
+。􃈵Σ񀠇。𐮈; .􃈵σ񀠇.𐮈; [P1, V6, X4_2]; .xn--4xa68573c7n64d.xn--f29c; [P1, V6, A4_2]; ; # .σ.𐮈
+。􃈵σ񀠇。𐮈; .􃈵σ񀠇.𐮈; [P1, V6, X4_2]; .xn--4xa68573c7n64d.xn--f29c; [P1, V6, A4_2]; ; # .σ.𐮈
+.xn--4xa68573c7n64d.xn--f29c; .􃈵σ񀠇.𐮈; [V6, X4_2]; .xn--4xa68573c7n64d.xn--f29c; [V6, A4_2]; ; # .σ.𐮈
+.xn--3xa88573c7n64d.xn--f29c; .􃈵ς񀠇.𐮈; [V6, X4_2]; .xn--3xa88573c7n64d.xn--f29c; [V6, A4_2]; ; # .ς.𐮈
+︒􃈵Σ񀠇。𐮈; ︒􃈵σ񀠇.𐮈; [B1, P1, V6]; xn--4xa1729jwz5t7gl5f.xn--f29c; ; ; # ︒σ.𐮈
+︒􃈵σ񀠇。𐮈; ︒􃈵σ񀠇.𐮈; [B1, P1, V6]; xn--4xa1729jwz5t7gl5f.xn--f29c; ; ; # ︒σ.𐮈
+xn--4xa1729jwz5t7gl5f.xn--f29c; ︒􃈵σ񀠇.𐮈; [B1, V6]; xn--4xa1729jwz5t7gl5f.xn--f29c; ; ; # ︒σ.𐮈
+xn--3xa3729jwz5t7gl5f.xn--f29c; ︒􃈵ς񀠇.𐮈; [B1, V6]; xn--3xa3729jwz5t7gl5f.xn--f29c; ; ; # ︒ς.𐮈
+ߙ.ۮ󆾃≯󠅲; ߙ.ۮ󆾃≯; [B2, B3, P1, V6]; xn--0sb.xn--bmb691l0524t; ; ; # ߙ.ۮ≯
+ߙ.ۮ󆾃≯󠅲; ߙ.ۮ󆾃≯; [B2, B3, P1, V6]; xn--0sb.xn--bmb691l0524t; ; ; # ߙ.ۮ≯
+ߙ.ۮ󆾃≯󠅲; ߙ.ۮ󆾃≯; [B2, B3, P1, V6]; xn--0sb.xn--bmb691l0524t; ; ; # ߙ.ۮ≯
+ߙ.ۮ󆾃≯󠅲; ߙ.ۮ󆾃≯; [B2, B3, P1, V6]; xn--0sb.xn--bmb691l0524t; ; ; # ߙ.ۮ≯
+xn--0sb.xn--bmb691l0524t; ߙ.ۮ󆾃≯; [B2, B3, V6]; xn--0sb.xn--bmb691l0524t; ; ; # ߙ.ۮ≯
+ᩳ󚙸.𐭍; ; [B1, P1, V5, V6]; xn--2of22352n.xn--q09c; ; ; # ᩳ.𐭍
+xn--2of22352n.xn--q09c; ᩳ󚙸.𐭍; [B1, V5, V6]; xn--2of22352n.xn--q09c; ; ; # ᩳ.𐭍
+⒉󠊓≠。Ⴟ⬣Ⴈ; ⒉󠊓≠.Ⴟ⬣Ⴈ; [P1, V6]; xn--1ch07f91401d.xn--gnd9b297j; ; ; # ⒉≠.Ⴟ⬣Ⴈ
+⒉󠊓≠。Ⴟ⬣Ⴈ; ⒉󠊓≠.Ⴟ⬣Ⴈ; [P1, V6]; xn--1ch07f91401d.xn--gnd9b297j; ; ; # ⒉≠.Ⴟ⬣Ⴈ
+2.󠊓≠。Ⴟ⬣Ⴈ; 2.󠊓≠.Ⴟ⬣Ⴈ; [P1, V6]; 2.xn--1chz4101l.xn--gnd9b297j; ; ; # 2.≠.Ⴟ⬣Ⴈ
+2.󠊓≠。Ⴟ⬣Ⴈ; 2.󠊓≠.Ⴟ⬣Ⴈ; [P1, V6]; 2.xn--1chz4101l.xn--gnd9b297j; ; ; # 2.≠.Ⴟ⬣Ⴈ
+2.󠊓≠。ⴟ⬣ⴈ; 2.󠊓≠.ⴟ⬣ⴈ; [P1, V6]; 2.xn--1chz4101l.xn--45iz7d6b; ; ; # 2.≠.ⴟ⬣ⴈ
+2.󠊓≠。ⴟ⬣ⴈ; 2.󠊓≠.ⴟ⬣ⴈ; [P1, V6]; 2.xn--1chz4101l.xn--45iz7d6b; ; ; # 2.≠.ⴟ⬣ⴈ
+2.xn--1chz4101l.xn--45iz7d6b; 2.󠊓≠.ⴟ⬣ⴈ; [V6]; 2.xn--1chz4101l.xn--45iz7d6b; ; ; # 2.≠.ⴟ⬣ⴈ
+2.xn--1chz4101l.xn--gnd9b297j; 2.󠊓≠.Ⴟ⬣Ⴈ; [V6]; 2.xn--1chz4101l.xn--gnd9b297j; ; ; # 2.≠.Ⴟ⬣Ⴈ
+⒉󠊓≠。ⴟ⬣ⴈ; ⒉󠊓≠.ⴟ⬣ⴈ; [P1, V6]; xn--1ch07f91401d.xn--45iz7d6b; ; ; # ⒉≠.ⴟ⬣ⴈ
+⒉󠊓≠。ⴟ⬣ⴈ; ⒉󠊓≠.ⴟ⬣ⴈ; [P1, V6]; xn--1ch07f91401d.xn--45iz7d6b; ; ; # ⒉≠.ⴟ⬣ⴈ
+xn--1ch07f91401d.xn--45iz7d6b; ⒉󠊓≠.ⴟ⬣ⴈ; [V6]; xn--1ch07f91401d.xn--45iz7d6b; ; ; # ⒉≠.ⴟ⬣ⴈ
+xn--1ch07f91401d.xn--gnd9b297j; ⒉󠊓≠.Ⴟ⬣Ⴈ; [V6]; xn--1ch07f91401d.xn--gnd9b297j; ; ; # ⒉≠.Ⴟ⬣Ⴈ
+-󠉱ྸჅ。-𐹽ݴ𞣑; -󠉱ྸჅ.-𐹽ݴ𞣑; [B1, P1, V3, V6]; xn----xmg12fm2555h.xn----05c4213ryr0g; ; ; # -ྸჅ.-𐹽ݴ𞣑
+-󠉱ྸⴥ。-𐹽ݴ𞣑; -󠉱ྸⴥ.-𐹽ݴ𞣑; [B1, P1, V3, V6]; xn----xmg317tgv352a.xn----05c4213ryr0g; ; ; # -ྸⴥ.-𐹽ݴ𞣑
+xn----xmg317tgv352a.xn----05c4213ryr0g; -󠉱ྸⴥ.-𐹽ݴ𞣑; [B1, V3, V6]; xn----xmg317tgv352a.xn----05c4213ryr0g; ; ; # -ྸⴥ.-𐹽ݴ𞣑
+xn----xmg12fm2555h.xn----05c4213ryr0g; -󠉱ྸჅ.-𐹽ݴ𞣑; [B1, V3, V6]; xn----xmg12fm2555h.xn----05c4213ryr0g; ; ; # -ྸჅ.-𐹽ݴ𞣑
+ٙ。𑄴︒اߝ; ٙ.𑄴︒اߝ; [B1, B3, B6, P1, V5, V6]; xn--1hb.xn--mgb09fp820c08pa; ; ; # ٙ.𑄴︒اߝ
+ٙ。𑄴。اߝ; ٙ.𑄴.اߝ; [B1, B3, B6, V5]; xn--1hb.xn--w80d.xn--mgb09f; ; ; # ٙ.𑄴.اߝ
+xn--1hb.xn--w80d.xn--mgb09f; ٙ.𑄴.اߝ; [B1, B3, B6, V5]; xn--1hb.xn--w80d.xn--mgb09f; ; ; # ٙ.𑄴.اߝ
+xn--1hb.xn--mgb09fp820c08pa; ٙ.𑄴︒اߝ; [B1, B3, B6, V5, V6]; xn--1hb.xn--mgb09fp820c08pa; ; ; # ٙ.𑄴︒اߝ
+Ⴙظ.󠆓‍; Ⴙظ.‍; [B1, B5, B6, C2, P1, V6]; xn--3gb194c.xn--1ug; ; xn--3gb194c.; [B5, B6, P1, V6] # Ⴙظ.
+ⴙظ.󠆓‍; ⴙظ.‍; [B1, B5, B6, C2]; xn--3gb910r.xn--1ug; ; xn--3gb910r.; [B5, B6] # ⴙظ.
+xn--3gb910r.; ⴙظ.; [B5, B6]; xn--3gb910r.; ; ; # ⴙظ.
+xn--3gb910r.xn--1ug; ⴙظ.‍; [B1, B5, B6, C2]; xn--3gb910r.xn--1ug; ; ; # ⴙظ.
+xn--3gb194c.; Ⴙظ.; [B5, B6, V6]; xn--3gb194c.; ; ; # Ⴙظ.
+xn--3gb194c.xn--1ug; Ⴙظ.‍; [B1, B5, B6, C2, V6]; xn--3gb194c.xn--1ug; ; ; # Ⴙظ.
+󠆸。₆0𐺧ݖ; .60𐺧ݖ; [B1, X4_2]; .xn--60-cke9470y; [B1, A4_2]; ; # .60𐺧ݖ
+󠆸。60𐺧ݖ; .60𐺧ݖ; [B1, X4_2]; .xn--60-cke9470y; [B1, A4_2]; ; # .60𐺧ݖ
+.xn--60-cke9470y; .60𐺧ݖ; [B1, X4_2]; .xn--60-cke9470y; [B1, A4_2]; ; # .60𐺧ݖ
+6ࡏ。-𑈴; 6ࡏ.-𑈴; [B1, V3]; xn--6-jjd.xn----6n8i; ; ; # 6ࡏ.-𑈴
+6ࡏ。-𑈴; 6ࡏ.-𑈴; [B1, V3]; xn--6-jjd.xn----6n8i; ; ; # 6ࡏ.-𑈴
+xn--6-jjd.xn----6n8i; 6ࡏ.-𑈴; [B1, V3]; xn--6-jjd.xn----6n8i; ; ; # 6ࡏ.-𑈴
+‍񋌿𐹰。્ς𞰎ࣖ; ‍񋌿𐹰.્ς𞰎ࣖ; [B1, C2, P1, V5, V6]; xn--1ugx105gq26y.xn--3xa41xcwbfz15g; ; xn--oo0d1330n.xn--4xa21xcwbfz15g; [B1, B5, B6, P1, V5, V6] # 𐹰.્ςࣖ
+‍񋌿𐹰。્ς𞰎ࣖ; ‍񋌿𐹰.્ς𞰎ࣖ; [B1, C2, P1, V5, V6]; xn--1ugx105gq26y.xn--3xa41xcwbfz15g; ; xn--oo0d1330n.xn--4xa21xcwbfz15g; [B1, B5, B6, P1, V5, V6] # 𐹰.્ςࣖ
+‍񋌿𐹰。્Σ𞰎ࣖ; ‍񋌿𐹰.્σ𞰎ࣖ; [B1, C2, P1, V5, V6]; xn--1ugx105gq26y.xn--4xa21xcwbfz15g; ; xn--oo0d1330n.xn--4xa21xcwbfz15g; [B1, B5, B6, P1, V5, V6] # 𐹰.્σࣖ
+‍񋌿𐹰。્σ𞰎ࣖ; ‍񋌿𐹰.્σ𞰎ࣖ; [B1, C2, P1, V5, V6]; xn--1ugx105gq26y.xn--4xa21xcwbfz15g; ; xn--oo0d1330n.xn--4xa21xcwbfz15g; [B1, B5, B6, P1, V5, V6] # 𐹰.્σࣖ
+xn--oo0d1330n.xn--4xa21xcwbfz15g; 񋌿𐹰.્σ𞰎ࣖ; [B1, B5, B6, V5, V6]; xn--oo0d1330n.xn--4xa21xcwbfz15g; ; ; # 𐹰.્σࣖ
+xn--1ugx105gq26y.xn--4xa21xcwbfz15g; ‍񋌿𐹰.્σ𞰎ࣖ; [B1, C2, V5, V6]; xn--1ugx105gq26y.xn--4xa21xcwbfz15g; ; ; # 𐹰.્σࣖ
+xn--1ugx105gq26y.xn--3xa41xcwbfz15g; ‍񋌿𐹰.્ς𞰎ࣖ; [B1, C2, V5, V6]; xn--1ugx105gq26y.xn--3xa41xcwbfz15g; ; ; # 𐹰.્ςࣖ
+‍񋌿𐹰。્Σ𞰎ࣖ; ‍񋌿𐹰.્σ𞰎ࣖ; [B1, C2, P1, V5, V6]; xn--1ugx105gq26y.xn--4xa21xcwbfz15g; ; xn--oo0d1330n.xn--4xa21xcwbfz15g; [B1, B5, B6, P1, V5, V6] # 𐹰.્σࣖ
+‍񋌿𐹰。્σ𞰎ࣖ; ‍񋌿𐹰.્σ𞰎ࣖ; [B1, C2, P1, V5, V6]; xn--1ugx105gq26y.xn--4xa21xcwbfz15g; ; xn--oo0d1330n.xn--4xa21xcwbfz15g; [B1, B5, B6, P1, V5, V6] # 𐹰.્σࣖ
+⒈񟄜Ⴓ⒪.්򘘶ࢋ𐹢; ⒈񟄜Ⴓ⒪.්򘘶ࢋ𐹢; [B1, P1, V5, V6]; xn--rnd762h7cx3027d.xn--3xb99xpx1yoes3e; ; ; # ⒈Ⴓ⒪.්ࢋ𐹢
+1.񟄜Ⴓ(o).්򘘶ࢋ𐹢; ; [B1, B6, P1, V5, V6]; 1.xn--(o)-7sn88849j.xn--3xb99xpx1yoes3e; ; ; # 1.Ⴓ(o).්ࢋ𐹢
+1.񟄜ⴓ(o).්򘘶ࢋ𐹢; ; [B1, B6, P1, V5, V6]; 1.xn--(o)-ej1bu5389e.xn--3xb99xpx1yoes3e; ; ; # 1.ⴓ(o).්ࢋ𐹢
+1.񟄜Ⴓ(O).්򘘶ࢋ𐹢; 1.񟄜Ⴓ(o).්򘘶ࢋ𐹢; [B1, B6, P1, V5, V6]; 1.xn--(o)-7sn88849j.xn--3xb99xpx1yoes3e; ; ; # 1.Ⴓ(o).්ࢋ𐹢
+1.xn--(o)-7sn88849j.xn--3xb99xpx1yoes3e; 1.񟄜Ⴓ(o).්򘘶ࢋ𐹢; [B1, B6, P1, V5, V6]; 1.xn--(o)-7sn88849j.xn--3xb99xpx1yoes3e; ; ; # 1.Ⴓ(o).්ࢋ𐹢
+1.xn--(o)-ej1bu5389e.xn--3xb99xpx1yoes3e; 1.񟄜ⴓ(o).්򘘶ࢋ𐹢; [B1, B6, P1, V5, V6]; 1.xn--(o)-ej1bu5389e.xn--3xb99xpx1yoes3e; ; ; # 1.ⴓ(o).්ࢋ𐹢
+⒈񟄜ⴓ⒪.්򘘶ࢋ𐹢; ⒈񟄜ⴓ⒪.්򘘶ࢋ𐹢; [B1, P1, V5, V6]; xn--tsh0ds63atl31n.xn--3xb99xpx1yoes3e; ; ; # ⒈ⴓ⒪.්ࢋ𐹢
+xn--tsh0ds63atl31n.xn--3xb99xpx1yoes3e; ⒈񟄜ⴓ⒪.්򘘶ࢋ𐹢; [B1, V5, V6]; xn--tsh0ds63atl31n.xn--3xb99xpx1yoes3e; ; ; # ⒈ⴓ⒪.්ࢋ𐹢
+xn--rnd762h7cx3027d.xn--3xb99xpx1yoes3e; ⒈񟄜Ⴓ⒪.්򘘶ࢋ𐹢; [B1, V5, V6]; xn--rnd762h7cx3027d.xn--3xb99xpx1yoes3e; ; ; # ⒈Ⴓ⒪.්ࢋ𐹢
+𞤷.𐮐𞢁𐹠ؤ; ; ; xn--ve6h.xn--jgb1694kz0b2176a; ; ; # 𞤷.𐮐𞢁𐹠ؤ
+𞤷.𐮐𞢁𐹠ؤ; 𞤷.𐮐𞢁𐹠ؤ; ; xn--ve6h.xn--jgb1694kz0b2176a; ; ; # 𞤷.𐮐𞢁𐹠ؤ
+𞤕.𐮐𞢁𐹠ؤ; 𞤷.𐮐𞢁𐹠ؤ; ; xn--ve6h.xn--jgb1694kz0b2176a; ; ; # 𞤷.𐮐𞢁𐹠ؤ
+𞤕.𐮐𞢁𐹠ؤ; 𞤷.𐮐𞢁𐹠ؤ; ; xn--ve6h.xn--jgb1694kz0b2176a; ; ; # 𞤷.𐮐𞢁𐹠ؤ
+xn--ve6h.xn--jgb1694kz0b2176a; 𞤷.𐮐𞢁𐹠ؤ; ; xn--ve6h.xn--jgb1694kz0b2176a; ; ; # 𞤷.𐮐𞢁𐹠ؤ
+𐲈-。𑄳񢌻; 𐳈-.𑄳񢌻; [B1, B3, P1, V3, V5, V6]; xn----ue6i.xn--v80d6662t; ; ; # 𐳈-.𑄳
+𐲈-。𑄳񢌻; 𐳈-.𑄳񢌻; [B1, B3, P1, V3, V5, V6]; xn----ue6i.xn--v80d6662t; ; ; # 𐳈-.𑄳
+𐳈-。𑄳񢌻; 𐳈-.𑄳񢌻; [B1, B3, P1, V3, V5, V6]; xn----ue6i.xn--v80d6662t; ; ; # 𐳈-.𑄳
+xn----ue6i.xn--v80d6662t; 𐳈-.𑄳񢌻; [B1, B3, V3, V5, V6]; xn----ue6i.xn--v80d6662t; ; ; # 𐳈-.𑄳
+𐳈-。𑄳񢌻; 𐳈-.𑄳񢌻; [B1, B3, P1, V3, V5, V6]; xn----ue6i.xn--v80d6662t; ; ; # 𐳈-.𑄳
+-󠉖ꡧ.󠊂񇆃🄉; -󠉖ꡧ.󠊂񇆃🄉; [P1, V3, V6]; xn----hg4ei0361g.xn--207ht163h7m94c; ; ; # -ꡧ.🄉
+-󠉖ꡧ.󠊂񇆃8,; ; [P1, V3, V6]; xn----hg4ei0361g.xn--8,-k362evu488a; ; ; # -ꡧ.8,
+xn----hg4ei0361g.xn--8,-k362evu488a; -󠉖ꡧ.󠊂񇆃8,; [P1, V3, V6]; xn----hg4ei0361g.xn--8,-k362evu488a; ; ; # -ꡧ.8,
+xn----hg4ei0361g.xn--207ht163h7m94c; -󠉖ꡧ.󠊂񇆃🄉; [V3, V6]; xn----hg4ei0361g.xn--207ht163h7m94c; ; ; # -ꡧ.🄉
+󠾛󠈴臯𧔤.ݨ𝟝; 󠾛󠈴臯𧔤.ݨ5; [B1, P1, V6]; xn--zb1at733hm579ddhla.xn--5-b5c; ; ; # 臯𧔤.ݨ5
+󠾛󠈴臯𧔤.ݨ5; ; [B1, P1, V6]; xn--zb1at733hm579ddhla.xn--5-b5c; ; ; # 臯𧔤.ݨ5
+xn--zb1at733hm579ddhla.xn--5-b5c; 󠾛󠈴臯𧔤.ݨ5; [B1, V6]; xn--zb1at733hm579ddhla.xn--5-b5c; ; ; # 臯𧔤.ݨ5
+≮𐹣.𝨿; ≮𐹣.𝨿; [B1, B3, B6, P1, V5, V6]; xn--gdh1504g.xn--e92h; ; ; # ≮𐹣.𝨿
+≮𐹣.𝨿; ≮𐹣.𝨿; [B1, B3, B6, P1, V5, V6]; xn--gdh1504g.xn--e92h; ; ; # ≮𐹣.𝨿
+≮𐹣.𝨿; ; [B1, B3, B6, P1, V5, V6]; xn--gdh1504g.xn--e92h; ; ; # ≮𐹣.𝨿
+≮𐹣.𝨿; ≮𐹣.𝨿; [B1, B3, B6, P1, V5, V6]; xn--gdh1504g.xn--e92h; ; ; # ≮𐹣.𝨿
+xn--gdh1504g.xn--e92h; ≮𐹣.𝨿; [B1, B3, B6, V5, V6]; xn--gdh1504g.xn--e92h; ; ; # ≮𐹣.𝨿
+𐹯ᯛ੍。脥; 𐹯ᯛ੍.脥; [B1]; xn--ybc101g3m1p.xn--740a; ; ; # 𐹯ᯛ੍.脥
+𐹯ᯛ੍。脥; 𐹯ᯛ੍.脥; [B1]; xn--ybc101g3m1p.xn--740a; ; ; # 𐹯ᯛ੍.脥
+xn--ybc101g3m1p.xn--740a; 𐹯ᯛ੍.脥; [B1]; xn--ybc101g3m1p.xn--740a; ; ; # 𐹯ᯛ੍.脥
+᭄ᅟ𞷿򃀍.-; ; [B1, B5, P1, V3, V5, V6]; xn--osd971cpx70btgt8b.-; ; ; # ᭄.-
+xn--osd971cpx70btgt8b.-; ᭄ᅟ𞷿򃀍.-; [B1, B5, V3, V5, V6]; xn--osd971cpx70btgt8b.-; ; ; # ᭄.-
+‌。͔; ‌.͔; [C1, V5]; xn--0ug.xn--yua; ; .xn--yua; [V5, A4_2] # .͔
+‌。͔; ‌.͔; [C1, V5]; xn--0ug.xn--yua; ; .xn--yua; [V5, A4_2] # .͔
+.xn--yua; .͔; [V5, X4_2]; .xn--yua; [V5, A4_2]; ; # .͔
+xn--0ug.xn--yua; ‌.͔; [C1, V5]; xn--0ug.xn--yua; ; ; # .͔
+𞤥󠅮.ᡄႮ; 𞤥.ᡄႮ; [P1, V6]; xn--de6h.xn--mnd799a; ; ; # 𞤥.ᡄႮ
+𞤥󠅮.ᡄႮ; 𞤥.ᡄႮ; [P1, V6]; xn--de6h.xn--mnd799a; ; ; # 𞤥.ᡄႮ
+𞤥󠅮.ᡄⴎ; 𞤥.ᡄⴎ; ; xn--de6h.xn--37e857h; ; ; # 𞤥.ᡄⴎ
+𞤃󠅮.ᡄႮ; 𞤥.ᡄႮ; [P1, V6]; xn--de6h.xn--mnd799a; ; ; # 𞤥.ᡄႮ
+𞤃󠅮.ᡄⴎ; 𞤥.ᡄⴎ; ; xn--de6h.xn--37e857h; ; ; # 𞤥.ᡄⴎ
+xn--de6h.xn--37e857h; 𞤥.ᡄⴎ; ; xn--de6h.xn--37e857h; ; ; # 𞤥.ᡄⴎ
+𞤥.ᡄⴎ; ; ; xn--de6h.xn--37e857h; ; ; # 𞤥.ᡄⴎ
+𞤃.ᡄႮ; 𞤥.ᡄႮ; [P1, V6]; xn--de6h.xn--mnd799a; ; ; # 𞤥.ᡄႮ
+𞤃.ᡄⴎ; 𞤥.ᡄⴎ; ; xn--de6h.xn--37e857h; ; ; # 𞤥.ᡄⴎ
+xn--de6h.xn--mnd799a; 𞤥.ᡄႮ; [V6]; xn--de6h.xn--mnd799a; ; ; # 𞤥.ᡄႮ
+𞤥󠅮.ᡄⴎ; 𞤥.ᡄⴎ; ; xn--de6h.xn--37e857h; ; ; # 𞤥.ᡄⴎ
+𞤃󠅮.ᡄႮ; 𞤥.ᡄႮ; [P1, V6]; xn--de6h.xn--mnd799a; ; ; # 𞤥.ᡄႮ
+𞤃󠅮.ᡄⴎ; 𞤥.ᡄⴎ; ; xn--de6h.xn--37e857h; ; ; # 𞤥.ᡄⴎ
+𞤥.ᡄႮ; ; [P1, V6]; xn--de6h.xn--mnd799a; ; ; # 𞤥.ᡄႮ
+𞤧𝨨Ξ.𪺏㛨❸; 𞤧𝨨ξ.𪺏㛨❸; [B2, B3, B6]; xn--zxa5691vboja.xn--bfi293ci119b; ; ; # 𞤧𝨨ξ.𪺏㛨❸
+𞤧𝨨Ξ.𪺏㛨❸; 𞤧𝨨ξ.𪺏㛨❸; [B2, B3, B6]; xn--zxa5691vboja.xn--bfi293ci119b; ; ; # 𞤧𝨨ξ.𪺏㛨❸
+𞤧𝨨ξ.𪺏㛨❸; ; [B2, B3, B6]; xn--zxa5691vboja.xn--bfi293ci119b; ; ; # 𞤧𝨨ξ.𪺏㛨❸
+𞤅𝨨Ξ.𪺏㛨❸; 𞤧𝨨ξ.𪺏㛨❸; [B2, B3, B6]; xn--zxa5691vboja.xn--bfi293ci119b; ; ; # 𞤧𝨨ξ.𪺏㛨❸
+𞤅𝨨ξ.𪺏㛨❸; 𞤧𝨨ξ.𪺏㛨❸; [B2, B3, B6]; xn--zxa5691vboja.xn--bfi293ci119b; ; ; # 𞤧𝨨ξ.𪺏㛨❸
+xn--zxa5691vboja.xn--bfi293ci119b; 𞤧𝨨ξ.𪺏㛨❸; [B2, B3, B6]; xn--zxa5691vboja.xn--bfi293ci119b; ; ; # 𞤧𝨨ξ.𪺏㛨❸
+𞤧𝨨ξ.𪺏㛨❸; 𞤧𝨨ξ.𪺏㛨❸; [B2, B3, B6]; xn--zxa5691vboja.xn--bfi293ci119b; ; ; # 𞤧𝨨ξ.𪺏㛨❸
+𞤅𝨨Ξ.𪺏㛨❸; 𞤧𝨨ξ.𪺏㛨❸; [B2, B3, B6]; xn--zxa5691vboja.xn--bfi293ci119b; ; ; # 𞤧𝨨ξ.𪺏㛨❸
+𞤅𝨨ξ.𪺏㛨❸; 𞤧𝨨ξ.𪺏㛨❸; [B2, B3, B6]; xn--zxa5691vboja.xn--bfi293ci119b; ; ; # 𞤧𝨨ξ.𪺏㛨❸
+᠆몆‌-。Ⴛ𐦅︒; ᠆몆‌-.Ⴛ𐦅︒; [B1, B5, B6, C1, P1, V3, V6]; xn----e3j425bsk1o.xn--znd2362jhgh; ; xn----e3j6620g.xn--znd2362jhgh; [B1, B5, B6, P1, V3, V6] # ᠆몆-.Ⴛ𐦅︒
+᠆몆‌-。Ⴛ𐦅︒; ᠆몆‌-.Ⴛ𐦅︒; [B1, B5, B6, C1, P1, V3, V6]; xn----e3j425bsk1o.xn--znd2362jhgh; ; xn----e3j6620g.xn--znd2362jhgh; [B1, B5, B6, P1, V3, V6] # ᠆몆-.Ⴛ𐦅︒
+᠆몆‌-。Ⴛ𐦅。; ᠆몆‌-.Ⴛ𐦅.; [B1, B5, B6, C1, P1, V3, V6]; xn----e3j425bsk1o.xn--znd4948j.; ; xn----e3j6620g.xn--znd4948j.; [B1, B5, B6, P1, V3, V6] # ᠆몆-.Ⴛ𐦅.
+᠆몆‌-。Ⴛ𐦅。; ᠆몆‌-.Ⴛ𐦅.; [B1, B5, B6, C1, P1, V3, V6]; xn----e3j425bsk1o.xn--znd4948j.; ; xn----e3j6620g.xn--znd4948j.; [B1, B5, B6, P1, V3, V6] # ᠆몆-.Ⴛ𐦅.
+᠆몆‌-。ⴛ𐦅。; ᠆몆‌-.ⴛ𐦅.; [B1, B5, B6, C1, P1, V3, V6]; xn----e3j425bsk1o.xn--jlju661e.; ; xn----e3j6620g.xn--jlju661e.; [B1, B5, B6, P1, V3, V6] # ᠆몆-.ⴛ𐦅.
+᠆몆‌-。ⴛ𐦅。; ᠆몆‌-.ⴛ𐦅.; [B1, B5, B6, C1, P1, V3, V6]; xn----e3j425bsk1o.xn--jlju661e.; ; xn----e3j6620g.xn--jlju661e.; [B1, B5, B6, P1, V3, V6] # ᠆몆-.ⴛ𐦅.
+xn----e3j6620g.xn--jlju661e.; ᠆몆-.ⴛ𐦅.; [B1, B5, B6, V3, V6]; xn----e3j6620g.xn--jlju661e.; ; ; # ᠆몆-.ⴛ𐦅.
+xn----e3j425bsk1o.xn--jlju661e.; ᠆몆‌-.ⴛ𐦅.; [B1, B5, B6, C1, V3, V6]; xn----e3j425bsk1o.xn--jlju661e.; ; ; # ᠆몆-.ⴛ𐦅.
+xn----e3j6620g.xn--znd4948j.; ᠆몆-.Ⴛ𐦅.; [B1, B5, B6, V3, V6]; xn----e3j6620g.xn--znd4948j.; ; ; # ᠆몆-.Ⴛ𐦅.
+xn----e3j425bsk1o.xn--znd4948j.; ᠆몆‌-.Ⴛ𐦅.; [B1, B5, B6, C1, V3, V6]; xn----e3j425bsk1o.xn--znd4948j.; ; ; # ᠆몆-.Ⴛ𐦅.
+᠆몆‌-。ⴛ𐦅︒; ᠆몆‌-.ⴛ𐦅︒; [B1, B5, B6, C1, P1, V3, V6]; xn----e3j425bsk1o.xn--jlj4997dhgh; ; xn----e3j6620g.xn--jlj4997dhgh; [B1, B5, B6, P1, V3, V6] # ᠆몆-.ⴛ𐦅︒
+᠆몆‌-。ⴛ𐦅︒; ᠆몆‌-.ⴛ𐦅︒; [B1, B5, B6, C1, P1, V3, V6]; xn----e3j425bsk1o.xn--jlj4997dhgh; ; xn----e3j6620g.xn--jlj4997dhgh; [B1, B5, B6, P1, V3, V6] # ᠆몆-.ⴛ𐦅︒
+xn----e3j6620g.xn--jlj4997dhgh; ᠆몆-.ⴛ𐦅︒; [B1, B5, B6, V3, V6]; xn----e3j6620g.xn--jlj4997dhgh; ; ; # ᠆몆-.ⴛ𐦅︒
+xn----e3j425bsk1o.xn--jlj4997dhgh; ᠆몆‌-.ⴛ𐦅︒; [B1, B5, B6, C1, V3, V6]; xn----e3j425bsk1o.xn--jlj4997dhgh; ; ; # ᠆몆-.ⴛ𐦅︒
+xn----e3j6620g.xn--znd2362jhgh; ᠆몆-.Ⴛ𐦅︒; [B1, B5, B6, V3, V6]; xn----e3j6620g.xn--znd2362jhgh; ; ; # ᠆몆-.Ⴛ𐦅︒
+xn----e3j425bsk1o.xn--znd2362jhgh; ᠆몆‌-.Ⴛ𐦅︒; [B1, B5, B6, C1, V3, V6]; xn----e3j425bsk1o.xn--znd2362jhgh; ; ; # ᠆몆-.Ⴛ𐦅︒
+󠾳.︒⥱‌𐹬; ; [B1, C1, P1, V6]; xn--uf66e.xn--0ugz28axl3pqxna; ; xn--uf66e.xn--qtiz073e3ik; [B1, P1, V6] # .︒⥱𐹬
+󠾳.。⥱‌𐹬; 󠾳..⥱‌𐹬; [B1, C1, P1, V6, X4_2]; xn--uf66e..xn--0ugz28as66q; [B1, C1, P1, V6, A4_2]; xn--uf66e..xn--qti2829e; [B1, P1, V6, A4_2] # ..⥱𐹬
+xn--uf66e..xn--qti2829e; 󠾳..⥱𐹬; [B1, V6, X4_2]; xn--uf66e..xn--qti2829e; [B1, V6, A4_2]; ; # ..⥱𐹬
+xn--uf66e..xn--0ugz28as66q; 󠾳..⥱‌𐹬; [B1, C1, V6, X4_2]; xn--uf66e..xn--0ugz28as66q; [B1, C1, V6, A4_2]; ; # ..⥱𐹬
+xn--uf66e.xn--qtiz073e3ik; 󠾳.︒⥱𐹬; [B1, V6]; xn--uf66e.xn--qtiz073e3ik; ; ; # .︒⥱𐹬
+xn--uf66e.xn--0ugz28axl3pqxna; 󠾳.︒⥱‌𐹬; [B1, C1, V6]; xn--uf66e.xn--0ugz28axl3pqxna; ; ; # .︒⥱𐹬
+𐯖.𐹠Ⴑ񚇜𐫊; ; [B1, P1, V6]; xn--n49c.xn--pnd4619jwicl862o; ; ; # .𐹠Ⴑ𐫊
+𐯖.𐹠ⴑ񚇜𐫊; ; [B1, P1, V6]; xn--n49c.xn--8kj8702ewicl862o; ; ; # .𐹠ⴑ𐫊
+xn--n49c.xn--8kj8702ewicl862o; 𐯖.𐹠ⴑ񚇜𐫊; [B1, V6]; xn--n49c.xn--8kj8702ewicl862o; ; ; # .𐹠ⴑ𐫊
+xn--n49c.xn--pnd4619jwicl862o; 𐯖.𐹠Ⴑ񚇜𐫊; [B1, V6]; xn--n49c.xn--pnd4619jwicl862o; ; ; # .𐹠Ⴑ𐫊
+ྤ񱤯.𝟭Ⴛ; ྤ񱤯.1Ⴛ; [P1, V5, V6]; xn--0fd40533g.xn--1-q1g; ; ; # ྤ.1Ⴛ
+ྤ񱤯.1Ⴛ; ; [P1, V5, V6]; xn--0fd40533g.xn--1-q1g; ; ; # ྤ.1Ⴛ
+ྤ񱤯.1ⴛ; ; [P1, V5, V6]; xn--0fd40533g.xn--1-tws; ; ; # ྤ.1ⴛ
+xn--0fd40533g.xn--1-tws; ྤ񱤯.1ⴛ; [V5, V6]; xn--0fd40533g.xn--1-tws; ; ; # ྤ.1ⴛ
+xn--0fd40533g.xn--1-q1g; ྤ񱤯.1Ⴛ; [V5, V6]; xn--0fd40533g.xn--1-q1g; ; ; # ྤ.1Ⴛ
+ྤ񱤯.𝟭ⴛ; ྤ񱤯.1ⴛ; [P1, V5, V6]; xn--0fd40533g.xn--1-tws; ; ; # ྤ.1ⴛ
+-ࠦ齀。릿𐸋; -ࠦ齀.릿𐸋; [B1, B5, B6, P1, V3, V6]; xn----6gd0617i.xn--7y2bm55m; ; ; # -ࠦ齀.릿
+-ࠦ齀。릿𐸋; -ࠦ齀.릿𐸋; [B1, B5, B6, P1, V3, V6]; xn----6gd0617i.xn--7y2bm55m; ; ; # -ࠦ齀.릿
+xn----6gd0617i.xn--7y2bm55m; -ࠦ齀.릿𐸋; [B1, B5, B6, V3, V6]; xn----6gd0617i.xn--7y2bm55m; ; ; # -ࠦ齀.릿
+󠔊ܜ鹝꾗。񾵐‍‍⏃; 󠔊ܜ鹝꾗.񾵐‍‍⏃; [B1, B6, C2, P1, V6]; xn--mnb6558e91kyq533a.xn--1uga46zs309y; ; xn--mnb6558e91kyq533a.xn--6mh27269e; [B1, B6, P1, V6] # ܜ鹝꾗.⏃
+󠔊ܜ鹝꾗。񾵐‍‍⏃; 󠔊ܜ鹝꾗.񾵐‍‍⏃; [B1, B6, C2, P1, V6]; xn--mnb6558e91kyq533a.xn--1uga46zs309y; ; xn--mnb6558e91kyq533a.xn--6mh27269e; [B1, B6, P1, V6] # ܜ鹝꾗.⏃
+xn--mnb6558e91kyq533a.xn--6mh27269e; 󠔊ܜ鹝꾗.񾵐⏃; [B1, B6, V6]; xn--mnb6558e91kyq533a.xn--6mh27269e; ; ; # ܜ鹝꾗.⏃
+xn--mnb6558e91kyq533a.xn--1uga46zs309y; 󠔊ܜ鹝꾗.񾵐‍‍⏃; [B1, B6, C2, V6]; xn--mnb6558e91kyq533a.xn--1uga46zs309y; ; ; # ܜ鹝꾗.⏃
+≮.-܈--; ≮.-܈--; [B1, P1, V2, V3, V6]; xn--gdh.xn------eqf; ; ; # ≮.-܈--
+≮.-܈--; ≮.-܈--; [B1, P1, V2, V3, V6]; xn--gdh.xn------eqf; ; ; # ≮.-܈--
+≮.-܈--; ; [B1, P1, V2, V3, V6]; xn--gdh.xn------eqf; ; ; # ≮.-܈--
+≮.-܈--; ≮.-܈--; [B1, P1, V2, V3, V6]; xn--gdh.xn------eqf; ; ; # ≮.-܈--
+xn--gdh.xn------eqf; ≮.-܈--; [B1, V2, V3, V6]; xn--gdh.xn------eqf; ; ; # ≮.-܈--
+𐹸󠋳。‍ς𝟩; 𐹸󠋳.‍ς7; [B1, C2, P1, V6]; xn--wo0di5177c.xn--7-xmb248s; ; xn--wo0di5177c.xn--7-zmb; [B1, P1, V6] # 𐹸.ς7
+𐹸󠋳。‍ς7; 𐹸󠋳.‍ς7; [B1, C2, P1, V6]; xn--wo0di5177c.xn--7-xmb248s; ; xn--wo0di5177c.xn--7-zmb; [B1, P1, V6] # 𐹸.ς7
+𐹸󠋳。‍Σ7; 𐹸󠋳.‍σ7; [B1, C2, P1, V6]; xn--wo0di5177c.xn--7-zmb938s; ; xn--wo0di5177c.xn--7-zmb; [B1, P1, V6] # 𐹸.σ7
+𐹸󠋳。‍σ7; 𐹸󠋳.‍σ7; [B1, C2, P1, V6]; xn--wo0di5177c.xn--7-zmb938s; ; xn--wo0di5177c.xn--7-zmb; [B1, P1, V6] # 𐹸.σ7
+xn--wo0di5177c.xn--7-zmb; 𐹸󠋳.σ7; [B1, V6]; xn--wo0di5177c.xn--7-zmb; ; ; # 𐹸.σ7
+xn--wo0di5177c.xn--7-zmb938s; 𐹸󠋳.‍σ7; [B1, C2, V6]; xn--wo0di5177c.xn--7-zmb938s; ; ; # 𐹸.σ7
+xn--wo0di5177c.xn--7-xmb248s; 𐹸󠋳.‍ς7; [B1, C2, V6]; xn--wo0di5177c.xn--7-xmb248s; ; ; # 𐹸.ς7
+𐹸󠋳。‍Σ𝟩; 𐹸󠋳.‍σ7; [B1, C2, P1, V6]; xn--wo0di5177c.xn--7-zmb938s; ; xn--wo0di5177c.xn--7-zmb; [B1, P1, V6] # 𐹸.σ7
+𐹸󠋳。‍σ𝟩; 𐹸󠋳.‍σ7; [B1, C2, P1, V6]; xn--wo0di5177c.xn--7-zmb938s; ; xn--wo0di5177c.xn--7-zmb; [B1, P1, V6] # 𐹸.σ7
+ς򅜌8.𞭤; ς򅜌8.𞭤; [P1, V6]; xn--8-xmb44974n.xn--su6h; ; xn--8-zmb14974n.xn--su6h; # ς8.
+ς򅜌8.𞭤; ; [P1, V6]; xn--8-xmb44974n.xn--su6h; ; xn--8-zmb14974n.xn--su6h; # ς8.
+Σ򅜌8.𞭤; σ򅜌8.𞭤; [P1, V6]; xn--8-zmb14974n.xn--su6h; ; ; # σ8.
+σ򅜌8.𞭤; ; [P1, V6]; xn--8-zmb14974n.xn--su6h; ; ; # σ8.
+xn--8-zmb14974n.xn--su6h; σ򅜌8.𞭤; [V6]; xn--8-zmb14974n.xn--su6h; ; ; # σ8.
+xn--8-xmb44974n.xn--su6h; ς򅜌8.𞭤; [V6]; xn--8-xmb44974n.xn--su6h; ; ; # ς8.
+Σ򅜌8.𞭤; σ򅜌8.𞭤; [P1, V6]; xn--8-zmb14974n.xn--su6h; ; ; # σ8.
+σ򅜌8.𞭤; σ򅜌8.𞭤; [P1, V6]; xn--8-zmb14974n.xn--su6h; ; ; # σ8.
+‌ᡑ🄀ڄ.-𐫄𑲤; ‌ᡑ🄀ڄ.-𐫄𑲤; [B1, C1, P1, V3, V6]; xn--9ib722gvtfi563c.xn----ek5i065b; ; xn--9ib722gbw95a.xn----ek5i065b; [B1, B5, B6, P1, V3, V6] # ᡑ🄀ڄ.-𐫄𑲤
+‌ᡑ0.ڄ.-𐫄𑲤; ; [B1, C1, V3]; xn--0-o7j263b.xn--9ib.xn----ek5i065b; ; xn--0-o7j.xn--9ib.xn----ek5i065b; [B1, V3] # ᡑ0.ڄ.-𐫄𑲤
+xn--0-o7j.xn--9ib.xn----ek5i065b; ᡑ0.ڄ.-𐫄𑲤; [B1, V3]; xn--0-o7j.xn--9ib.xn----ek5i065b; ; ; # ᡑ0.ڄ.-𐫄𑲤
+xn--0-o7j263b.xn--9ib.xn----ek5i065b; ‌ᡑ0.ڄ.-𐫄𑲤; [B1, C1, V3]; xn--0-o7j263b.xn--9ib.xn----ek5i065b; ; ; # ᡑ0.ڄ.-𐫄𑲤
+xn--9ib722gbw95a.xn----ek5i065b; ᡑ🄀ڄ.-𐫄𑲤; [B1, B5, B6, V3, V6]; xn--9ib722gbw95a.xn----ek5i065b; ; ; # ᡑ🄀ڄ.-𐫄𑲤
+xn--9ib722gvtfi563c.xn----ek5i065b; ‌ᡑ🄀ڄ.-𐫄𑲤; [B1, C1, V3, V6]; xn--9ib722gvtfi563c.xn----ek5i065b; ; ; # ᡑ🄀ڄ.-𐫄𑲤
+𖠍。𐪿넯򞵲; 𖠍.𐪿넯򞵲; [B2, B3, P1, V6]; xn--4e9e.xn--l60bj21opd57g; ; ; # 𖠍.넯
+𖠍。𐪿넯򞵲; 𖠍.𐪿넯򞵲; [B2, B3, P1, V6]; xn--4e9e.xn--l60bj21opd57g; ; ; # 𖠍.넯
+xn--4e9e.xn--l60bj21opd57g; 𖠍.𐪿넯򞵲; [B2, B3, V6]; xn--4e9e.xn--l60bj21opd57g; ; ; # 𖠍.넯
+᠇Ⴘ。؃Ⴈ𝆊; ᠇Ⴘ.؃Ⴈ𝆊; [B1, P1, V6]; xn--wnd558a.xn--lfb465c1v87a; ; ; # ᠇Ⴘ.Ⴈ𝆊
+᠇ⴘ。؃ⴈ𝆊; ᠇ⴘ.؃ⴈ𝆊; [B1, P1, V6]; xn--d6e009h.xn--lfb290rfu3z; ; ; # ᠇ⴘ.ⴈ𝆊
+xn--d6e009h.xn--lfb290rfu3z; ᠇ⴘ.؃ⴈ𝆊; [B1, V6]; xn--d6e009h.xn--lfb290rfu3z; ; ; # ᠇ⴘ.ⴈ𝆊
+xn--wnd558a.xn--lfb465c1v87a; ᠇Ⴘ.؃Ⴈ𝆊; [B1, V6]; xn--wnd558a.xn--lfb465c1v87a; ; ; # ᠇Ⴘ.Ⴈ𝆊
+⒚󠋑𞤰。牣٧Ⴜᣥ; ⒚󠋑𞤰.牣٧Ⴜᣥ; [B1, B5, P1, V6]; xn--cthy466n29j3e.xn--gib404ccxgh00h; ; ; # ⒚𞤰.牣٧Ⴜᣥ
+19.󠋑𞤰。牣٧Ⴜᣥ; 19.󠋑𞤰.牣٧Ⴜᣥ; [B1, B5, P1, V6]; 19.xn--oe6h75760c.xn--gib404ccxgh00h; ; ; # 19.𞤰.牣٧Ⴜᣥ
+19.󠋑𞤰。牣٧ⴜᣥ; 19.󠋑𞤰.牣٧ⴜᣥ; [B1, B5, P1, V6]; 19.xn--oe6h75760c.xn--gib285gtxo2l9d; ; ; # 19.𞤰.牣٧ⴜᣥ
+19.󠋑𞤎。牣٧Ⴜᣥ; 19.󠋑𞤰.牣٧Ⴜᣥ; [B1, B5, P1, V6]; 19.xn--oe6h75760c.xn--gib404ccxgh00h; ; ; # 19.𞤰.牣٧Ⴜᣥ
+19.󠋑𞤎。牣٧ⴜᣥ; 19.󠋑𞤰.牣٧ⴜᣥ; [B1, B5, P1, V6]; 19.xn--oe6h75760c.xn--gib285gtxo2l9d; ; ; # 19.𞤰.牣٧ⴜᣥ
+19.xn--oe6h75760c.xn--gib285gtxo2l9d; 19.󠋑𞤰.牣٧ⴜᣥ; [B1, B5, V6]; 19.xn--oe6h75760c.xn--gib285gtxo2l9d; ; ; # 19.𞤰.牣٧ⴜᣥ
+19.xn--oe6h75760c.xn--gib404ccxgh00h; 19.󠋑𞤰.牣٧Ⴜᣥ; [B1, B5, V6]; 19.xn--oe6h75760c.xn--gib404ccxgh00h; ; ; # 19.𞤰.牣٧Ⴜᣥ
+⒚󠋑𞤰。牣٧ⴜᣥ; ⒚󠋑𞤰.牣٧ⴜᣥ; [B1, B5, P1, V6]; xn--cthy466n29j3e.xn--gib285gtxo2l9d; ; ; # ⒚𞤰.牣٧ⴜᣥ
+⒚󠋑𞤎。牣٧Ⴜᣥ; ⒚󠋑𞤰.牣٧Ⴜᣥ; [B1, B5, P1, V6]; xn--cthy466n29j3e.xn--gib404ccxgh00h; ; ; # ⒚𞤰.牣٧Ⴜᣥ
+⒚󠋑𞤎。牣٧ⴜᣥ; ⒚󠋑𞤰.牣٧ⴜᣥ; [B1, B5, P1, V6]; xn--cthy466n29j3e.xn--gib285gtxo2l9d; ; ; # ⒚𞤰.牣٧ⴜᣥ
+xn--cthy466n29j3e.xn--gib285gtxo2l9d; ⒚󠋑𞤰.牣٧ⴜᣥ; [B1, B5, V6]; xn--cthy466n29j3e.xn--gib285gtxo2l9d; ; ; # ⒚𞤰.牣٧ⴜᣥ
+xn--cthy466n29j3e.xn--gib404ccxgh00h; ⒚󠋑𞤰.牣٧Ⴜᣥ; [B1, B5, V6]; xn--cthy466n29j3e.xn--gib404ccxgh00h; ; ; # ⒚𞤰.牣٧Ⴜᣥ
+-𐋱𐰽⒈.Ⴓ; ; [B1, P1, V3, V6]; xn----ecp0206g90h.xn--rnd; ; ; # -𐋱𐰽⒈.Ⴓ
+-𐋱𐰽1..Ⴓ; ; [B1, P1, V3, V6, X4_2]; xn---1-895nq11a..xn--rnd; [B1, P1, V3, V6, A4_2]; ; # -𐋱𐰽1..Ⴓ
+-𐋱𐰽1..ⴓ; ; [B1, V3, X4_2]; xn---1-895nq11a..xn--blj; [B1, V3, A4_2]; ; # -𐋱𐰽1..ⴓ
+xn---1-895nq11a..xn--blj; -𐋱𐰽1..ⴓ; [B1, V3, X4_2]; xn---1-895nq11a..xn--blj; [B1, V3, A4_2]; ; # -𐋱𐰽1..ⴓ
+xn---1-895nq11a..xn--rnd; -𐋱𐰽1..Ⴓ; [B1, V3, V6, X4_2]; xn---1-895nq11a..xn--rnd; [B1, V3, V6, A4_2]; ; # -𐋱𐰽1..Ⴓ
+-𐋱𐰽⒈.ⴓ; ; [B1, P1, V3, V6]; xn----ecp0206g90h.xn--blj; ; ; # -𐋱𐰽⒈.ⴓ
+xn----ecp0206g90h.xn--blj; -𐋱𐰽⒈.ⴓ; [B1, V3, V6]; xn----ecp0206g90h.xn--blj; ; ; # -𐋱𐰽⒈.ⴓ
+xn----ecp0206g90h.xn--rnd; -𐋱𐰽⒈.Ⴓ; [B1, V3, V6]; xn----ecp0206g90h.xn--rnd; ; ; # -𐋱𐰽⒈.Ⴓ
+‌긃.榶-; ; [C1, V3]; xn--0ug3307c.xn----d87b; ; xn--ej0b.xn----d87b; [V3] # 긃.榶-
+‌긃.榶-; ‌긃.榶-; [C1, V3]; xn--0ug3307c.xn----d87b; ; xn--ej0b.xn----d87b; [V3] # 긃.榶-
+xn--ej0b.xn----d87b; 긃.榶-; [V3]; xn--ej0b.xn----d87b; ; ; # 긃.榶-
+xn--0ug3307c.xn----d87b; ‌긃.榶-; [C1, V3]; xn--0ug3307c.xn----d87b; ; ; # 긃.榶-
+뉓泓𜵽.্‍; ; [P1, V5, V6]; xn--lwwp69lqs7m.xn--b7b605i; ; xn--lwwp69lqs7m.xn--b7b; # 뉓泓.্
+뉓泓𜵽.্‍; 뉓泓𜵽.্‍; [P1, V5, V6]; xn--lwwp69lqs7m.xn--b7b605i; ; xn--lwwp69lqs7m.xn--b7b; # 뉓泓.্
+xn--lwwp69lqs7m.xn--b7b; 뉓泓𜵽.্; [V5, V6]; xn--lwwp69lqs7m.xn--b7b; ; ; # 뉓泓.্
+xn--lwwp69lqs7m.xn--b7b605i; 뉓泓𜵽.্‍; [V5, V6]; xn--lwwp69lqs7m.xn--b7b605i; ; ; # 뉓泓.্
+‍𐹴ß。ິ⭵񪅌; ‍𐹴ß.ິ⭵񪅌; [B1, C2, P1, V5, V6]; xn--zca770nip7n.xn--57c638l8774i; ; xn--ss-ti3o.xn--57c638l8774i; [B1, P1, V5, V6] # 𐹴ß.ິ
+‍𐹴ß。ິ⭵񪅌; ‍𐹴ß.ິ⭵񪅌; [B1, C2, P1, V5, V6]; xn--zca770nip7n.xn--57c638l8774i; ; xn--ss-ti3o.xn--57c638l8774i; [B1, P1, V5, V6] # 𐹴ß.ິ
+‍𐹴SS。ິ⭵񪅌; ‍𐹴ss.ິ⭵񪅌; [B1, C2, P1, V5, V6]; xn--ss-l1t5169j.xn--57c638l8774i; ; xn--ss-ti3o.xn--57c638l8774i; [B1, P1, V5, V6] # 𐹴ss.ິ
+‍𐹴ss。ິ⭵񪅌; ‍𐹴ss.ິ⭵񪅌; [B1, C2, P1, V5, V6]; xn--ss-l1t5169j.xn--57c638l8774i; ; xn--ss-ti3o.xn--57c638l8774i; [B1, P1, V5, V6] # 𐹴ss.ິ
+‍𐹴Ss。ິ⭵񪅌; ‍𐹴ss.ິ⭵񪅌; [B1, C2, P1, V5, V6]; xn--ss-l1t5169j.xn--57c638l8774i; ; xn--ss-ti3o.xn--57c638l8774i; [B1, P1, V5, V6] # 𐹴ss.ິ
+xn--ss-ti3o.xn--57c638l8774i; 𐹴ss.ິ⭵񪅌; [B1, V5, V6]; xn--ss-ti3o.xn--57c638l8774i; ; ; # 𐹴ss.ິ
+xn--ss-l1t5169j.xn--57c638l8774i; ‍𐹴ss.ິ⭵񪅌; [B1, C2, V5, V6]; xn--ss-l1t5169j.xn--57c638l8774i; ; ; # 𐹴ss.ິ
+xn--zca770nip7n.xn--57c638l8774i; ‍𐹴ß.ິ⭵񪅌; [B1, C2, V5, V6]; xn--zca770nip7n.xn--57c638l8774i; ; ; # 𐹴ß.ິ
+‍𐹴SS。ິ⭵񪅌; ‍𐹴ss.ິ⭵񪅌; [B1, C2, P1, V5, V6]; xn--ss-l1t5169j.xn--57c638l8774i; ; xn--ss-ti3o.xn--57c638l8774i; [B1, P1, V5, V6] # 𐹴ss.ິ
+‍𐹴ss。ິ⭵񪅌; ‍𐹴ss.ິ⭵񪅌; [B1, C2, P1, V5, V6]; xn--ss-l1t5169j.xn--57c638l8774i; ; xn--ss-ti3o.xn--57c638l8774i; [B1, P1, V5, V6] # 𐹴ss.ິ
+‍𐹴Ss。ິ⭵񪅌; ‍𐹴ss.ິ⭵񪅌; [B1, C2, P1, V5, V6]; xn--ss-l1t5169j.xn--57c638l8774i; ; xn--ss-ti3o.xn--57c638l8774i; [B1, P1, V5, V6] # 𐹴ss.ິ
+᭄.᮪-≮≠; ᭄.᮪-≮≠; [P1, V5, V6]; xn--1uf.xn----nmlz65aub; ; ; # ᭄.᮪-≮≠
+᭄.᮪-≮≠; ᭄.᮪-≮≠; [P1, V5, V6]; xn--1uf.xn----nmlz65aub; ; ; # ᭄.᮪-≮≠
+᭄.᮪-≮≠; ; [P1, V5, V6]; xn--1uf.xn----nmlz65aub; ; ; # ᭄.᮪-≮≠
+᭄.᮪-≮≠; ᭄.᮪-≮≠; [P1, V5, V6]; xn--1uf.xn----nmlz65aub; ; ; # ᭄.᮪-≮≠
+xn--1uf.xn----nmlz65aub; ᭄.᮪-≮≠; [V5, V6]; xn--1uf.xn----nmlz65aub; ; ; # ᭄.᮪-≮≠
+᯳Ⴑᅟ.𑄴Ⅎ; ᯳Ⴑᅟ.𑄴Ⅎ; [P1, V5, V6]; xn--pnd26a55x.xn--f3g7465g; ; ; # ᯳Ⴑ.𑄴Ⅎ
+᯳Ⴑᅟ.𑄴Ⅎ; ; [P1, V5, V6]; xn--pnd26a55x.xn--f3g7465g; ; ; # ᯳Ⴑ.𑄴Ⅎ
+᯳ⴑᅟ.𑄴ⅎ; ; [P1, V5, V6]; xn--osd925cvyn.xn--73g3065g; ; ; # ᯳ⴑ.𑄴ⅎ
+᯳Ⴑᅟ.𑄴ⅎ; ; [P1, V5, V6]; xn--pnd26a55x.xn--73g3065g; ; ; # ᯳Ⴑ.𑄴ⅎ
+xn--pnd26a55x.xn--73g3065g; ᯳Ⴑᅟ.𑄴ⅎ; [V5, V6]; xn--pnd26a55x.xn--73g3065g; ; ; # ᯳Ⴑ.𑄴ⅎ
+xn--osd925cvyn.xn--73g3065g; ᯳ⴑᅟ.𑄴ⅎ; [V5, V6]; xn--osd925cvyn.xn--73g3065g; ; ; # ᯳ⴑ.𑄴ⅎ
+xn--pnd26a55x.xn--f3g7465g; ᯳Ⴑᅟ.𑄴Ⅎ; [V5, V6]; xn--pnd26a55x.xn--f3g7465g; ; ; # ᯳Ⴑ.𑄴Ⅎ
+᯳ⴑᅟ.𑄴ⅎ; ᯳ⴑᅟ.𑄴ⅎ; [P1, V5, V6]; xn--osd925cvyn.xn--73g3065g; ; ; # ᯳ⴑ.𑄴ⅎ
+᯳Ⴑᅟ.𑄴ⅎ; ᯳Ⴑᅟ.𑄴ⅎ; [P1, V5, V6]; xn--pnd26a55x.xn--73g3065g; ; ; # ᯳Ⴑ.𑄴ⅎ
+𜉆。Ⴃ𐴣𐹹똯; 𜉆.Ⴃ𐴣𐹹똯; [B5, P1, V6]; xn--187g.xn--bnd4785f8r8bdeb; ; ; # .Ⴃ𐴣𐹹똯
+𜉆。Ⴃ𐴣𐹹똯; 𜉆.Ⴃ𐴣𐹹똯; [B5, P1, V6]; xn--187g.xn--bnd4785f8r8bdeb; ; ; # .Ⴃ𐴣𐹹똯
+𜉆。ⴃ𐴣𐹹똯; 𜉆.ⴃ𐴣𐹹똯; [B5, P1, V6]; xn--187g.xn--ukjy205b8rscdeb; ; ; # .ⴃ𐴣𐹹똯
+𜉆。ⴃ𐴣𐹹똯; 𜉆.ⴃ𐴣𐹹똯; [B5, P1, V6]; xn--187g.xn--ukjy205b8rscdeb; ; ; # .ⴃ𐴣𐹹똯
+xn--187g.xn--ukjy205b8rscdeb; 𜉆.ⴃ𐴣𐹹똯; [B5, V6]; xn--187g.xn--ukjy205b8rscdeb; ; ; # .ⴃ𐴣𐹹똯
+xn--187g.xn--bnd4785f8r8bdeb; 𜉆.Ⴃ𐴣𐹹똯; [B5, V6]; xn--187g.xn--bnd4785f8r8bdeb; ; ; # .Ⴃ𐴣𐹹똯
+𐫀。⳻󠙾󠄷ㅤ; 𐫀.⳻󠙾ㅤ; [B1, P1, V6]; xn--pw9c.xn--mkj83l4v899a; ; ; # 𐫀.⳻
+𐫀。⳻󠙾󠄷ᅠ; 𐫀.⳻󠙾ᅠ; [B1, P1, V6]; xn--pw9c.xn--psd742lxt32w; ; ; # 𐫀.⳻
+xn--pw9c.xn--psd742lxt32w; 𐫀.⳻󠙾ᅠ; [B1, V6]; xn--pw9c.xn--psd742lxt32w; ; ; # 𐫀.⳻
+xn--pw9c.xn--mkj83l4v899a; 𐫀.⳻󠙾ㅤ; [B1, V6]; xn--pw9c.xn--mkj83l4v899a; ; ; # 𐫀.⳻
+ޚ⾇.ܞ-𐋰; ޚ舛.ܞ-𐋰; [B2, B3]; xn--7qb6383d.xn----20c3154q; ; ; # ޚ舛.ܞ-𐋰
+ޚ舛.ܞ-𐋰; ; [B2, B3]; xn--7qb6383d.xn----20c3154q; ; ; # ޚ舛.ܞ-𐋰
+xn--7qb6383d.xn----20c3154q; ޚ舛.ܞ-𐋰; [B2, B3]; xn--7qb6383d.xn----20c3154q; ; ; # ޚ舛.ܞ-𐋰
+Ⴉ猕󹛫≮.︒; Ⴉ猕󹛫≮.︒; [P1, V6]; xn--hnd212gz32d54x5r.xn--y86c; ; ; # Ⴉ猕≮.︒
+Ⴉ猕󹛫≮.︒; Ⴉ猕󹛫≮.︒; [P1, V6]; xn--hnd212gz32d54x5r.xn--y86c; ; ; # Ⴉ猕≮.︒
+Ⴉ猕󹛫≮.。; Ⴉ猕󹛫≮..; [P1, V6, X4_2]; xn--hnd212gz32d54x5r..; [P1, V6, A4_2]; ; # Ⴉ猕≮..
+Ⴉ猕󹛫≮.。; Ⴉ猕󹛫≮..; [P1, V6, X4_2]; xn--hnd212gz32d54x5r..; [P1, V6, A4_2]; ; # Ⴉ猕≮..
+ⴉ猕󹛫≮.。; ⴉ猕󹛫≮..; [P1, V6, X4_2]; xn--gdh892bbz0d5438s..; [P1, V6, A4_2]; ; # ⴉ猕≮..
+ⴉ猕󹛫≮.。; ⴉ猕󹛫≮..; [P1, V6, X4_2]; xn--gdh892bbz0d5438s..; [P1, V6, A4_2]; ; # ⴉ猕≮..
+xn--gdh892bbz0d5438s..; ⴉ猕󹛫≮..; [V6, X4_2]; xn--gdh892bbz0d5438s..; [V6, A4_2]; ; # ⴉ猕≮..
+xn--hnd212gz32d54x5r..; Ⴉ猕󹛫≮..; [V6, X4_2]; xn--hnd212gz32d54x5r..; [V6, A4_2]; ; # Ⴉ猕≮..
+ⴉ猕󹛫≮.︒; ⴉ猕󹛫≮.︒; [P1, V6]; xn--gdh892bbz0d5438s.xn--y86c; ; ; # ⴉ猕≮.︒
+ⴉ猕󹛫≮.︒; ⴉ猕󹛫≮.︒; [P1, V6]; xn--gdh892bbz0d5438s.xn--y86c; ; ; # ⴉ猕≮.︒
+xn--gdh892bbz0d5438s.xn--y86c; ⴉ猕󹛫≮.︒; [V6]; xn--gdh892bbz0d5438s.xn--y86c; ; ; # ⴉ猕≮.︒
+xn--hnd212gz32d54x5r.xn--y86c; Ⴉ猕󹛫≮.︒; [V6]; xn--hnd212gz32d54x5r.xn--y86c; ; ; # Ⴉ猕≮.︒
+🏮。ث鳳ߢ󠅉; 🏮.ث鳳ߢ; [B1, B2]; xn--8m8h.xn--qgb29f6z90a; ; ; # 🏮.ث鳳ߢ
+🏮。ث鳳ߢ󠅉; 🏮.ث鳳ߢ; [B1, B2]; xn--8m8h.xn--qgb29f6z90a; ; ; # 🏮.ث鳳ߢ
+xn--8m8h.xn--qgb29f6z90a; 🏮.ث鳳ߢ; [B1, B2]; xn--8m8h.xn--qgb29f6z90a; ; ; # 🏮.ث鳳ߢ
+‍𐹶。ß; ‍𐹶.ß; [B1, C2]; xn--1ug9105g.xn--zca; ; xn--uo0d.ss; [B1] # 𐹶.ß
+‍𐹶。SS; ‍𐹶.ss; [B1, C2]; xn--1ug9105g.ss; ; xn--uo0d.ss; [B1] # 𐹶.ss
+‍𐹶。ss; ‍𐹶.ss; [B1, C2]; xn--1ug9105g.ss; ; xn--uo0d.ss; [B1] # 𐹶.ss
+‍𐹶。Ss; ‍𐹶.ss; [B1, C2]; xn--1ug9105g.ss; ; xn--uo0d.ss; [B1] # 𐹶.ss
+xn--uo0d.ss; 𐹶.ss; [B1]; xn--uo0d.ss; ; ; # 𐹶.ss
+xn--1ug9105g.ss; ‍𐹶.ss; [B1, C2]; xn--1ug9105g.ss; ; ; # 𐹶.ss
+xn--1ug9105g.xn--zca; ‍𐹶.ß; [B1, C2]; xn--1ug9105g.xn--zca; ; ; # 𐹶.ß
+Å둄-.‌; å둄-.‌; [C1, V3]; xn----1fa1788k.xn--0ug; ; xn----1fa1788k.; [V3] # å둄-.
+Å둄-.‌; å둄-.‌; [C1, V3]; xn----1fa1788k.xn--0ug; ; xn----1fa1788k.; [V3] # å둄-.
+Å둄-.‌; å둄-.‌; [C1, V3]; xn----1fa1788k.xn--0ug; ; xn----1fa1788k.; [V3] # å둄-.
+Å둄-.‌; å둄-.‌; [C1, V3]; xn----1fa1788k.xn--0ug; ; xn----1fa1788k.; [V3] # å둄-.
+å둄-.‌; å둄-.‌; [C1, V3]; xn----1fa1788k.xn--0ug; ; xn----1fa1788k.; [V3] # å둄-.
+å둄-.‌; ; [C1, V3]; xn----1fa1788k.xn--0ug; ; xn----1fa1788k.; [V3] # å둄-.
+xn----1fa1788k.; å둄-.; [V3]; xn----1fa1788k.; ; ; # å둄-.
+xn----1fa1788k.xn--0ug; å둄-.‌; [C1, V3]; xn----1fa1788k.xn--0ug; ; ; # å둄-.
+å둄-.‌; å둄-.‌; [C1, V3]; xn----1fa1788k.xn--0ug; ; xn----1fa1788k.; [V3] # å둄-.
+å둄-.‌; å둄-.‌; [C1, V3]; xn----1fa1788k.xn--0ug; ; xn----1fa1788k.; [V3] # å둄-.
+゙򬎑ᷗ𞤀.򱲢-॓; ゙򬎑ᷗ𞤢.򱲢-॓; [B1, B6, P1, V5, V6]; xn--veg121fwg63altj9d.xn----eyd92688s; ; ; # ゙ᷗ𞤢.-॓
+゙򬎑ᷗ𞤢.򱲢-॓; ; [B1, B6, P1, V5, V6]; xn--veg121fwg63altj9d.xn----eyd92688s; ; ; # ゙ᷗ𞤢.-॓
+xn--veg121fwg63altj9d.xn----eyd92688s; ゙򬎑ᷗ𞤢.򱲢-॓; [B1, B6, V5, V6]; xn--veg121fwg63altj9d.xn----eyd92688s; ; ; # ゙ᷗ𞤢.-॓
+ς.ß񴱄۝⵿; ; [B5, B6, P1, V6]; xn--3xa.xn--zca281az71b8x73m; ; xn--4xa.xn--ss-y8d4760biv60n; # ς.ß⵿
+Σ.SS񴱄۝⵿; σ.ss񴱄۝⵿; [B5, B6, P1, V6]; xn--4xa.xn--ss-y8d4760biv60n; ; ; # σ.ss⵿
+σ.ss񴱄۝⵿; ; [B5, B6, P1, V6]; xn--4xa.xn--ss-y8d4760biv60n; ; ; # σ.ss⵿
+Σ.ss񴱄۝⵿; σ.ss񴱄۝⵿; [B5, B6, P1, V6]; xn--4xa.xn--ss-y8d4760biv60n; ; ; # σ.ss⵿
+xn--4xa.xn--ss-y8d4760biv60n; σ.ss񴱄۝⵿; [B5, B6, V6]; xn--4xa.xn--ss-y8d4760biv60n; ; ; # σ.ss⵿
+Σ.ß񴱄۝⵿; σ.ß񴱄۝⵿; [B5, B6, P1, V6]; xn--4xa.xn--zca281az71b8x73m; ; xn--4xa.xn--ss-y8d4760biv60n; # σ.ß⵿
+σ.ß񴱄۝⵿; ; [B5, B6, P1, V6]; xn--4xa.xn--zca281az71b8x73m; ; xn--4xa.xn--ss-y8d4760biv60n; # σ.ß⵿
+xn--4xa.xn--zca281az71b8x73m; σ.ß񴱄۝⵿; [B5, B6, V6]; xn--4xa.xn--zca281az71b8x73m; ; ; # σ.ß⵿
+xn--3xa.xn--zca281az71b8x73m; ς.ß񴱄۝⵿; [B5, B6, V6]; xn--3xa.xn--zca281az71b8x73m; ; ; # ς.ß⵿
+ꡀ𞀟。٫֙; ꡀ𞀟.٫֙; [B1]; xn--8b9a1720d.xn--kcb33b; ; ; # ꡀ𞀟.٫֙
+ꡀ𞀟。٫֙; ꡀ𞀟.٫֙; [B1]; xn--8b9a1720d.xn--kcb33b; ; ; # ꡀ𞀟.٫֙
+xn--8b9a1720d.xn--kcb33b; ꡀ𞀟.٫֙; [B1]; xn--8b9a1720d.xn--kcb33b; ; ; # ꡀ𞀟.٫֙
+򈛉‌ࢩ。⧅񘘡-𐭡; 򈛉‌ࢩ.⧅񘘡-𐭡; [B1, B5, B6, C1, P1, V6]; xn--yyb780jll63m.xn----zir1232guu71b; ; xn--yyb56242i.xn----zir1232guu71b; [B1, B5, B6, P1, V6] # ࢩ.⧅-𐭡
+򈛉‌ࢩ。⧅񘘡-𐭡; 򈛉‌ࢩ.⧅񘘡-𐭡; [B1, B5, B6, C1, P1, V6]; xn--yyb780jll63m.xn----zir1232guu71b; ; xn--yyb56242i.xn----zir1232guu71b; [B1, B5, B6, P1, V6] # ࢩ.⧅-𐭡
+xn--yyb56242i.xn----zir1232guu71b; 򈛉ࢩ.⧅񘘡-𐭡; [B1, B5, B6, V6]; xn--yyb56242i.xn----zir1232guu71b; ; ; # ࢩ.⧅-𐭡
+xn--yyb780jll63m.xn----zir1232guu71b; 򈛉‌ࢩ.⧅񘘡-𐭡; [B1, B5, B6, C1, V6]; xn--yyb780jll63m.xn----zir1232guu71b; ; ; # ࢩ.⧅-𐭡
+룱‍𰍨‌。𝨖︒; 룱‍𰍨‌.𝨖︒; [C1, C2, P1, V5, V6]; xn--0ugb3358ili2v.xn--y86cl899a; ; xn--ct2b0738h.xn--y86cl899a; [P1, V5, V6] # 룱𰍨.𝨖︒
+룱‍𰍨‌。𝨖︒; 룱‍𰍨‌.𝨖︒; [C1, C2, P1, V5, V6]; xn--0ugb3358ili2v.xn--y86cl899a; ; xn--ct2b0738h.xn--y86cl899a; [P1, V5, V6] # 룱𰍨.𝨖︒
+룱‍𰍨‌。𝨖。; 룱‍𰍨‌.𝨖.; [C1, C2, V5]; xn--0ugb3358ili2v.xn--772h.; ; xn--ct2b0738h.xn--772h.; [V5] # 룱𰍨.𝨖.
+룱‍𰍨‌。𝨖。; 룱‍𰍨‌.𝨖.; [C1, C2, V5]; xn--0ugb3358ili2v.xn--772h.; ; xn--ct2b0738h.xn--772h.; [V5] # 룱𰍨.𝨖.
+xn--ct2b0738h.xn--772h.; 룱𰍨.𝨖.; [V5]; xn--ct2b0738h.xn--772h.; ; ; # 룱𰍨.𝨖.
+xn--0ugb3358ili2v.xn--772h.; 룱‍𰍨‌.𝨖.; [C1, C2, V5]; xn--0ugb3358ili2v.xn--772h.; ; ; # 룱𰍨.𝨖.
+xn--ct2b0738h.xn--y86cl899a; 룱𰍨.𝨖︒; [V5, V6]; xn--ct2b0738h.xn--y86cl899a; ; ; # 룱𰍨.𝨖︒
+xn--0ugb3358ili2v.xn--y86cl899a; 룱‍𰍨‌.𝨖︒; [C1, C2, V5, V6]; xn--0ugb3358ili2v.xn--y86cl899a; ; ; # 룱𰍨.𝨖︒
+🄄.᳜⒈ß; 🄄.᳜⒈ß; [P1, V5, V6]; xn--x07h.xn--zca344lmif; ; xn--x07h.xn--ss-k1r094b; # 🄄.᳜⒈ß
+3,.᳜1.ß; ; [P1, V5, V6]; 3,.xn--1-43l.xn--zca; ; 3,.xn--1-43l.ss; # 3,.᳜1.ß
+3,.᳜1.SS; 3,.᳜1.ss; [P1, V5, V6]; 3,.xn--1-43l.ss; ; ; # 3,.᳜1.ss
+3,.᳜1.ss; ; [P1, V5, V6]; 3,.xn--1-43l.ss; ; ; # 3,.᳜1.ss
+3,.᳜1.Ss; 3,.᳜1.ss; [P1, V5, V6]; 3,.xn--1-43l.ss; ; ; # 3,.᳜1.ss
+3,.xn--1-43l.ss; 3,.᳜1.ss; [P1, V5, V6]; 3,.xn--1-43l.ss; ; ; # 3,.᳜1.ss
+3,.xn--1-43l.xn--zca; 3,.᳜1.ß; [P1, V5, V6]; 3,.xn--1-43l.xn--zca; ; ; # 3,.᳜1.ß
+🄄.᳜⒈SS; 🄄.᳜⒈ss; [P1, V5, V6]; xn--x07h.xn--ss-k1r094b; ; ; # 🄄.᳜⒈ss
+🄄.᳜⒈ss; 🄄.᳜⒈ss; [P1, V5, V6]; xn--x07h.xn--ss-k1r094b; ; ; # 🄄.᳜⒈ss
+🄄.᳜⒈Ss; 🄄.᳜⒈ss; [P1, V5, V6]; xn--x07h.xn--ss-k1r094b; ; ; # 🄄.᳜⒈ss
+xn--x07h.xn--ss-k1r094b; 🄄.᳜⒈ss; [V5, V6]; xn--x07h.xn--ss-k1r094b; ; ; # 🄄.᳜⒈ss
+xn--x07h.xn--zca344lmif; 🄄.᳜⒈ß; [V5, V6]; xn--x07h.xn--zca344lmif; ; ; # 🄄.᳜⒈ß
+񇌍⵿。𞼓򡄨𑐺; 񇌍⵿.𞼓򡄨𑐺; [B2, B3, P1, V6]; xn--eoj16016a.xn--0v1d3848a3lr0d; ; ; # ⵿.𑐺
+񇌍⵿。𞼓򡄨𑐺; 񇌍⵿.𞼓򡄨𑐺; [B2, B3, P1, V6]; xn--eoj16016a.xn--0v1d3848a3lr0d; ; ; # ⵿.𑐺
+xn--eoj16016a.xn--0v1d3848a3lr0d; 񇌍⵿.𞼓򡄨𑐺; [B2, B3, V6]; xn--eoj16016a.xn--0v1d3848a3lr0d; ; ; # ⵿.𑐺
+်्᷽.≠‍㇛; ်्᷽.≠‍㇛; [C2, P1, V5, V6]; xn--n3b956a9zm.xn--1ug63gz5w; ; xn--n3b956a9zm.xn--1ch912d; [P1, V5, V6] # ်्᷽.≠㇛
+်्᷽.≠‍㇛; ်्᷽.≠‍㇛; [C2, P1, V5, V6]; xn--n3b956a9zm.xn--1ug63gz5w; ; xn--n3b956a9zm.xn--1ch912d; [P1, V5, V6] # ်्᷽.≠㇛
+်्᷽.≠‍㇛; ်्᷽.≠‍㇛; [C2, P1, V5, V6]; xn--n3b956a9zm.xn--1ug63gz5w; ; xn--n3b956a9zm.xn--1ch912d; [P1, V5, V6] # ်्᷽.≠㇛
+်्᷽.≠‍㇛; ; [C2, P1, V5, V6]; xn--n3b956a9zm.xn--1ug63gz5w; ; xn--n3b956a9zm.xn--1ch912d; [P1, V5, V6] # ်्᷽.≠㇛
+်्᷽.≠‍㇛; ်्᷽.≠‍㇛; [C2, P1, V5, V6]; xn--n3b956a9zm.xn--1ug63gz5w; ; xn--n3b956a9zm.xn--1ch912d; [P1, V5, V6] # ်्᷽.≠㇛
+xn--n3b956a9zm.xn--1ch912d; ်्᷽.≠㇛; [V5, V6]; xn--n3b956a9zm.xn--1ch912d; ; ; # ်्᷽.≠㇛
+xn--n3b956a9zm.xn--1ug63gz5w; ်्᷽.≠‍㇛; [C2, V5, V6]; xn--n3b956a9zm.xn--1ug63gz5w; ; ; # ်्᷽.≠㇛
+Ⴁ𐋨娤.‍̼٢𑖿; ; [B1, C2, P1, V6]; xn--8md2578ag21g.xn--9ta62ngt6aou8t; ; xn--8md2578ag21g.xn--9ta62nrv36a; [B1, P1, V5, V6] # Ⴁ𐋨娤.̼٢𑖿
+ⴁ𐋨娤.‍̼٢𑖿; ; [B1, C2]; xn--skjw75lg29h.xn--9ta62ngt6aou8t; ; xn--skjw75lg29h.xn--9ta62nrv36a; [B1, V5] # ⴁ𐋨娤.̼٢𑖿
+xn--skjw75lg29h.xn--9ta62nrv36a; ⴁ𐋨娤.̼٢𑖿; [B1, V5]; xn--skjw75lg29h.xn--9ta62nrv36a; ; ; # ⴁ𐋨娤.̼٢𑖿
+xn--skjw75lg29h.xn--9ta62ngt6aou8t; ⴁ𐋨娤.‍̼٢𑖿; [B1, C2]; xn--skjw75lg29h.xn--9ta62ngt6aou8t; ; ; # ⴁ𐋨娤.̼٢𑖿
+xn--8md2578ag21g.xn--9ta62nrv36a; Ⴁ𐋨娤.̼٢𑖿; [B1, V5, V6]; xn--8md2578ag21g.xn--9ta62nrv36a; ; ; # Ⴁ𐋨娤.̼٢𑖿
+xn--8md2578ag21g.xn--9ta62ngt6aou8t; Ⴁ𐋨娤.‍̼٢𑖿; [B1, C2, V6]; xn--8md2578ag21g.xn--9ta62ngt6aou8t; ; ; # Ⴁ𐋨娤.̼٢𑖿
+🄀Ⴄ٩ࠠ。⒈ྶß; 🄀Ⴄ٩ࠠ.⒈ྶß; [B1, P1, V6]; xn--iib29f26o6n43c.xn--zca117e3vp; ; xn--iib29f26o6n43c.xn--ss-1sj588o; # 🄀Ⴄ٩ࠠ.⒈ྶß
+0.Ⴄ٩ࠠ。1.ྶß; 0.Ⴄ٩ࠠ.1.ྶß; [B1, B5, B6, P1, V5, V6]; 0.xn--iib29f26o.1.xn--zca117e; ; 0.xn--iib29f26o.1.xn--ss-1sj; # 0.Ⴄ٩ࠠ.1.ྶß
+0.ⴄ٩ࠠ。1.ྶß; 0.ⴄ٩ࠠ.1.ྶß; [B1, B5, B6, V5]; 0.xn--iib29fp25e.1.xn--zca117e; ; 0.xn--iib29fp25e.1.xn--ss-1sj; # 0.ⴄ٩ࠠ.1.ྶß
+0.Ⴄ٩ࠠ。1.ྶSS; 0.Ⴄ٩ࠠ.1.ྶss; [B1, B5, B6, P1, V5, V6]; 0.xn--iib29f26o.1.xn--ss-1sj; ; ; # 0.Ⴄ٩ࠠ.1.ྶss
+0.ⴄ٩ࠠ。1.ྶss; 0.ⴄ٩ࠠ.1.ྶss; [B1, B5, B6, V5]; 0.xn--iib29fp25e.1.xn--ss-1sj; ; ; # 0.ⴄ٩ࠠ.1.ྶss
+0.Ⴄ٩ࠠ。1.ྶSs; 0.Ⴄ٩ࠠ.1.ྶss; [B1, B5, B6, P1, V5, V6]; 0.xn--iib29f26o.1.xn--ss-1sj; ; ; # 0.Ⴄ٩ࠠ.1.ྶss
+0.xn--iib29f26o.1.xn--ss-1sj; 0.Ⴄ٩ࠠ.1.ྶss; [B1, B5, B6, V5, V6]; 0.xn--iib29f26o.1.xn--ss-1sj; ; ; # 0.Ⴄ٩ࠠ.1.ྶss
+0.xn--iib29fp25e.1.xn--ss-1sj; 0.ⴄ٩ࠠ.1.ྶss; [B1, B5, B6, V5]; 0.xn--iib29fp25e.1.xn--ss-1sj; ; ; # 0.ⴄ٩ࠠ.1.ྶss
+0.xn--iib29fp25e.1.xn--zca117e; 0.ⴄ٩ࠠ.1.ྶß; [B1, B5, B6, V5]; 0.xn--iib29fp25e.1.xn--zca117e; ; ; # 0.ⴄ٩ࠠ.1.ྶß
+0.xn--iib29f26o.1.xn--zca117e; 0.Ⴄ٩ࠠ.1.ྶß; [B1, B5, B6, V5, V6]; 0.xn--iib29f26o.1.xn--zca117e; ; ; # 0.Ⴄ٩ࠠ.1.ྶß
+🄀ⴄ٩ࠠ。⒈ྶß; 🄀ⴄ٩ࠠ.⒈ྶß; [B1, P1, V6]; xn--iib29fp25e0219a.xn--zca117e3vp; ; xn--iib29fp25e0219a.xn--ss-1sj588o; # 🄀ⴄ٩ࠠ.⒈ྶß
+🄀Ⴄ٩ࠠ。⒈ྶSS; 🄀Ⴄ٩ࠠ.⒈ྶss; [B1, P1, V6]; xn--iib29f26o6n43c.xn--ss-1sj588o; ; ; # 🄀Ⴄ٩ࠠ.⒈ྶss
+🄀ⴄ٩ࠠ。⒈ྶss; 🄀ⴄ٩ࠠ.⒈ྶss; [B1, P1, V6]; xn--iib29fp25e0219a.xn--ss-1sj588o; ; ; # 🄀ⴄ٩ࠠ.⒈ྶss
+🄀Ⴄ٩ࠠ。⒈ྶSs; 🄀Ⴄ٩ࠠ.⒈ྶss; [B1, P1, V6]; xn--iib29f26o6n43c.xn--ss-1sj588o; ; ; # 🄀Ⴄ٩ࠠ.⒈ྶss
+xn--iib29f26o6n43c.xn--ss-1sj588o; 🄀Ⴄ٩ࠠ.⒈ྶss; [B1, V6]; xn--iib29f26o6n43c.xn--ss-1sj588o; ; ; # 🄀Ⴄ٩ࠠ.⒈ྶss
+xn--iib29fp25e0219a.xn--ss-1sj588o; 🄀ⴄ٩ࠠ.⒈ྶss; [B1, V6]; xn--iib29fp25e0219a.xn--ss-1sj588o; ; ; # 🄀ⴄ٩ࠠ.⒈ྶss
+xn--iib29fp25e0219a.xn--zca117e3vp; 🄀ⴄ٩ࠠ.⒈ྶß; [B1, V6]; xn--iib29fp25e0219a.xn--zca117e3vp; ; ; # 🄀ⴄ٩ࠠ.⒈ྶß
+xn--iib29f26o6n43c.xn--zca117e3vp; 🄀Ⴄ٩ࠠ.⒈ྶß; [B1, V6]; xn--iib29f26o6n43c.xn--zca117e3vp; ; ; # 🄀Ⴄ٩ࠠ.⒈ྶß
+≠.‌-٫; ; [B1, C1, P1, V6]; xn--1ch.xn----vqc597q; ; xn--1ch.xn----vqc; [B1, P1, V3, V6] # ≠.-٫
+≠.‌-٫; ≠.‌-٫; [B1, C1, P1, V6]; xn--1ch.xn----vqc597q; ; xn--1ch.xn----vqc; [B1, P1, V3, V6] # ≠.-٫
+xn--1ch.xn----vqc; ≠.-٫; [B1, V3, V6]; xn--1ch.xn----vqc; ; ; # ≠.-٫
+xn--1ch.xn----vqc597q; ≠.‌-٫; [B1, C1, V6]; xn--1ch.xn----vqc597q; ; ; # ≠.-٫
+٠۱。󠳶𞠁٥; ٠۱.󠳶𞠁٥; [B1, P1, V6]; xn--8hb40a.xn--eib7967vner3e; ; ; # ٠۱.𞠁٥
+٠۱。󠳶𞠁٥; ٠۱.󠳶𞠁٥; [B1, P1, V6]; xn--8hb40a.xn--eib7967vner3e; ; ; # ٠۱.𞠁٥
+xn--8hb40a.xn--eib7967vner3e; ٠۱.󠳶𞠁٥; [B1, V6]; xn--8hb40a.xn--eib7967vner3e; ; ; # ٠۱.𞠁٥
+‌٣⒖。󱅉𽷛᯳; ‌٣⒖.󱅉𽷛᯳; [B1, C1, P1, V6]; xn--cib152kwgd.xn--1zf13512buy41d; ; xn--cib675m.xn--1zf13512buy41d; [B1, P1, V6] # ٣⒖.᯳
+‌٣15.。󱅉𽷛᯳; ‌٣15..󱅉𽷛᯳; [B1, C1, P1, V6, X4_2]; xn--15-gyd983x..xn--1zf13512buy41d; [B1, C1, P1, V6, A4_2]; xn--15-gyd..xn--1zf13512buy41d; [B1, P1, V6, A4_2] # ٣15..᯳
+xn--15-gyd..xn--1zf13512buy41d; ٣15..󱅉𽷛᯳; [B1, V6, X4_2]; xn--15-gyd..xn--1zf13512buy41d; [B1, V6, A4_2]; ; # ٣15..᯳
+xn--15-gyd983x..xn--1zf13512buy41d; ‌٣15..󱅉𽷛᯳; [B1, C1, V6, X4_2]; xn--15-gyd983x..xn--1zf13512buy41d; [B1, C1, V6, A4_2]; ; # ٣15..᯳
+xn--cib675m.xn--1zf13512buy41d; ٣⒖.󱅉𽷛᯳; [B1, V6]; xn--cib675m.xn--1zf13512buy41d; ; ; # ٣⒖.᯳
+xn--cib152kwgd.xn--1zf13512buy41d; ‌٣⒖.󱅉𽷛᯳; [B1, C1, V6]; xn--cib152kwgd.xn--1zf13512buy41d; ; ; # ٣⒖.᯳
+᯳.-逋񳦭󙙮; ; [P1, V3, V5, V6]; xn--1zf.xn----483d46987byr50b; ; ; # ᯳.-逋
+xn--1zf.xn----483d46987byr50b; ᯳.-逋񳦭󙙮; [V3, V5, V6]; xn--1zf.xn----483d46987byr50b; ; ; # ᯳.-逋
+ݖ。ㅤ‍ς; ݖ.ㅤ‍ς; [C2, P1, V6]; xn--9ob.xn--3xa995lq2l; ; xn--9ob.xn--4xa574u; [P1, V6] # ݖ.ς
+ݖ。ᅠ‍ς; ݖ.ᅠ‍ς; [C2, P1, V6]; xn--9ob.xn--3xa580ebol; ; xn--9ob.xn--4xa380e; [P1, V6] # ݖ.ς
+ݖ。ᅠ‍Σ; ݖ.ᅠ‍σ; [C2, P1, V6]; xn--9ob.xn--4xa380ebol; ; xn--9ob.xn--4xa380e; [P1, V6] # ݖ.σ
+ݖ。ᅠ‍σ; ݖ.ᅠ‍σ; [C2, P1, V6]; xn--9ob.xn--4xa380ebol; ; xn--9ob.xn--4xa380e; [P1, V6] # ݖ.σ
+xn--9ob.xn--4xa380e; ݖ.ᅠσ; [V6]; xn--9ob.xn--4xa380e; ; ; # ݖ.σ
+xn--9ob.xn--4xa380ebol; ݖ.ᅠ‍σ; [C2, V6]; xn--9ob.xn--4xa380ebol; ; ; # ݖ.σ
+xn--9ob.xn--3xa580ebol; ݖ.ᅠ‍ς; [C2, V6]; xn--9ob.xn--3xa580ebol; ; ; # ݖ.ς
+ݖ。ㅤ‍Σ; ݖ.ㅤ‍σ; [C2, P1, V6]; xn--9ob.xn--4xa795lq2l; ; xn--9ob.xn--4xa574u; [P1, V6] # ݖ.σ
+ݖ。ㅤ‍σ; ݖ.ㅤ‍σ; [C2, P1, V6]; xn--9ob.xn--4xa795lq2l; ; xn--9ob.xn--4xa574u; [P1, V6] # ݖ.σ
+xn--9ob.xn--4xa574u; ݖ.ㅤσ; [V6]; xn--9ob.xn--4xa574u; ; ; # ݖ.σ
+xn--9ob.xn--4xa795lq2l; ݖ.ㅤ‍σ; [C2, V6]; xn--9ob.xn--4xa795lq2l; ; ; # ݖ.σ
+xn--9ob.xn--3xa995lq2l; ݖ.ㅤ‍ς; [C2, V6]; xn--9ob.xn--3xa995lq2l; ; ; # ݖ.ς
+ᡆႣ。󞢧̕‍‍; ᡆႣ.󞢧̕‍‍; [C2, P1, V6]; xn--bnd320b.xn--5sa649la993427a; ; xn--bnd320b.xn--5sa98523p; [P1, V6] # ᡆႣ.̕
+ᡆႣ。󞢧̕‍‍; ᡆႣ.󞢧̕‍‍; [C2, P1, V6]; xn--bnd320b.xn--5sa649la993427a; ; xn--bnd320b.xn--5sa98523p; [P1, V6] # ᡆႣ.̕
+ᡆⴃ。󞢧̕‍‍; ᡆⴃ.󞢧̕‍‍; [C2, P1, V6]; xn--57e237h.xn--5sa649la993427a; ; xn--57e237h.xn--5sa98523p; [P1, V6] # ᡆⴃ.̕
+xn--57e237h.xn--5sa98523p; ᡆⴃ.󞢧̕; [V6]; xn--57e237h.xn--5sa98523p; ; ; # ᡆⴃ.̕
+xn--57e237h.xn--5sa649la993427a; ᡆⴃ.󞢧̕‍‍; [C2, V6]; xn--57e237h.xn--5sa649la993427a; ; ; # ᡆⴃ.̕
+xn--bnd320b.xn--5sa98523p; ᡆႣ.󞢧̕; [V6]; xn--bnd320b.xn--5sa98523p; ; ; # ᡆႣ.̕
+xn--bnd320b.xn--5sa649la993427a; ᡆႣ.󞢧̕‍‍; [C2, V6]; xn--bnd320b.xn--5sa649la993427a; ; ; # ᡆႣ.̕
+ᡆⴃ。󞢧̕‍‍; ᡆⴃ.󞢧̕‍‍; [C2, P1, V6]; xn--57e237h.xn--5sa649la993427a; ; xn--57e237h.xn--5sa98523p; [P1, V6] # ᡆⴃ.̕
+㭄‍ࡏ𑚵.ς𐮮‌‍; 㭄‍ࡏ𑚵.ς𐮮‌‍; [B5, B6, C1, C2]; xn--ewb962jfitku4r.xn--3xa895lda6932v; ; xn--ewb302xhu1l.xn--4xa0426k; [B5, B6] # 㭄ࡏ𑚵.ς𐮮
+㭄‍ࡏ𑚵.ς𐮮‌‍; ; [B5, B6, C1, C2]; xn--ewb962jfitku4r.xn--3xa895lda6932v; ; xn--ewb302xhu1l.xn--4xa0426k; [B5, B6] # 㭄ࡏ𑚵.ς𐮮
+㭄‍ࡏ𑚵.Σ𐮮‌‍; 㭄‍ࡏ𑚵.σ𐮮‌‍; [B5, B6, C1, C2]; xn--ewb962jfitku4r.xn--4xa695lda6932v; ; xn--ewb302xhu1l.xn--4xa0426k; [B5, B6] # 㭄ࡏ𑚵.σ𐮮
+㭄‍ࡏ𑚵.σ𐮮‌‍; ; [B5, B6, C1, C2]; xn--ewb962jfitku4r.xn--4xa695lda6932v; ; xn--ewb302xhu1l.xn--4xa0426k; [B5, B6] # 㭄ࡏ𑚵.σ𐮮
+xn--ewb302xhu1l.xn--4xa0426k; 㭄ࡏ𑚵.σ𐮮; [B5, B6]; xn--ewb302xhu1l.xn--4xa0426k; ; ; # 㭄ࡏ𑚵.σ𐮮
+xn--ewb962jfitku4r.xn--4xa695lda6932v; 㭄‍ࡏ𑚵.σ𐮮‌‍; [B5, B6, C1, C2]; xn--ewb962jfitku4r.xn--4xa695lda6932v; ; ; # 㭄ࡏ𑚵.σ𐮮
+xn--ewb962jfitku4r.xn--3xa895lda6932v; 㭄‍ࡏ𑚵.ς𐮮‌‍; [B5, B6, C1, C2]; xn--ewb962jfitku4r.xn--3xa895lda6932v; ; ; # 㭄ࡏ𑚵.ς𐮮
+㭄‍ࡏ𑚵.Σ𐮮‌‍; 㭄‍ࡏ𑚵.σ𐮮‌‍; [B5, B6, C1, C2]; xn--ewb962jfitku4r.xn--4xa695lda6932v; ; xn--ewb302xhu1l.xn--4xa0426k; [B5, B6] # 㭄ࡏ𑚵.σ𐮮
+㭄‍ࡏ𑚵.σ𐮮‌‍; 㭄‍ࡏ𑚵.σ𐮮‌‍; [B5, B6, C1, C2]; xn--ewb962jfitku4r.xn--4xa695lda6932v; ; xn--ewb302xhu1l.xn--4xa0426k; [B5, B6] # 㭄ࡏ𑚵.σ𐮮
+឵。𞯸ꡀ🄋; ឵.𞯸ꡀ🄋; [B1, B2, B3, B6, P1, V5, V6]; xn--03e.xn--8b9ar252dngd; ; ; # .ꡀ🄋
+xn--03e.xn--8b9ar252dngd; ឵.𞯸ꡀ🄋; [B1, B2, B3, B6, V5, V6]; xn--03e.xn--8b9ar252dngd; ; ; # .ꡀ🄋
+󐪺暑.⾑٨; 󐪺暑.襾٨; [B5, B6, P1, V6]; xn--tlvq3513e.xn--hib9228d; ; ; # 暑.襾٨
+󐪺暑.襾٨; ; [B5, B6, P1, V6]; xn--tlvq3513e.xn--hib9228d; ; ; # 暑.襾٨
+xn--tlvq3513e.xn--hib9228d; 󐪺暑.襾٨; [B5, B6, V6]; xn--tlvq3513e.xn--hib9228d; ; ; # 暑.襾٨
+󠄚≯ꡢ。࢑᷿; ≯ꡢ.࢑᷿; [B1, P1, V6]; xn--hdh7783c.xn--9xb680i; ; ; # ≯ꡢ.᷿
+󠄚≯ꡢ。࢑᷿; ≯ꡢ.࢑᷿; [B1, P1, V6]; xn--hdh7783c.xn--9xb680i; ; ; # ≯ꡢ.᷿
+xn--hdh7783c.xn--9xb680i; ≯ꡢ.࢑᷿; [B1, V6]; xn--hdh7783c.xn--9xb680i; ; ; # ≯ꡢ.᷿
+ﷃ𮁱୍𐨿.󐧤Ⴗ; كمم𮁱୍𐨿.󐧤Ⴗ; [B2, B3, P1, V6]; xn--fhbea662czx68a2tju.xn--vnd55511o; ; ; # كمم𮁱୍𐨿.Ⴗ
+كمم𮁱୍𐨿.󐧤Ⴗ; ; [B2, B3, P1, V6]; xn--fhbea662czx68a2tju.xn--vnd55511o; ; ; # كمم𮁱୍𐨿.Ⴗ
+كمم𮁱୍𐨿.󐧤ⴗ; ; [B2, B3, P1, V6]; xn--fhbea662czx68a2tju.xn--fljz2846h; ; ; # كمم𮁱୍𐨿.ⴗ
+xn--fhbea662czx68a2tju.xn--fljz2846h; كمم𮁱୍𐨿.󐧤ⴗ; [B2, B3, V6]; xn--fhbea662czx68a2tju.xn--fljz2846h; ; ; # كمم𮁱୍𐨿.ⴗ
+xn--fhbea662czx68a2tju.xn--vnd55511o; كمم𮁱୍𐨿.󐧤Ⴗ; [B2, B3, V6]; xn--fhbea662czx68a2tju.xn--vnd55511o; ; ; # كمم𮁱୍𐨿.Ⴗ
+ﷃ𮁱୍𐨿.󐧤ⴗ; كمم𮁱୍𐨿.󐧤ⴗ; [B2, B3, P1, V6]; xn--fhbea662czx68a2tju.xn--fljz2846h; ; ; # كمم𮁱୍𐨿.ⴗ
+𞀨。᭄򡛨𞎇; 𞀨.᭄򡛨𞎇; [P1, V5, V6]; xn--mi4h.xn--1uf6843smg20c; ; ; # 𞀨.᭄
+𞀨。᭄򡛨𞎇; 𞀨.᭄򡛨𞎇; [P1, V5, V6]; xn--mi4h.xn--1uf6843smg20c; ; ; # 𞀨.᭄
+xn--mi4h.xn--1uf6843smg20c; 𞀨.᭄򡛨𞎇; [V5, V6]; xn--mi4h.xn--1uf6843smg20c; ; ; # 𞀨.᭄
+󠣼‌.𐺰‌ᡟ; 󠣼‌.𐺰‌ᡟ; [B1, B2, B3, C1, P1, V6]; xn--0ug18531l.xn--v8e340bp21t; ; xn--q046e.xn--v8e7227j; [B1, B2, B3, P1, V6] # .𐺰ᡟ
+󠣼‌.𐺰‌ᡟ; ; [B1, B2, B3, C1, P1, V6]; xn--0ug18531l.xn--v8e340bp21t; ; xn--q046e.xn--v8e7227j; [B1, B2, B3, P1, V6] # .𐺰ᡟ
+xn--q046e.xn--v8e7227j; 󠣼.𐺰ᡟ; [B1, B2, B3, V6]; xn--q046e.xn--v8e7227j; ; ; # .𐺰ᡟ
+xn--0ug18531l.xn--v8e340bp21t; 󠣼‌.𐺰‌ᡟ; [B1, B2, B3, C1, V6]; xn--0ug18531l.xn--v8e340bp21t; ; ; # .𐺰ᡟ
+ᢛ󨅟ß.ጧ; ; [P1, V6]; xn--zca562jc642x.xn--p5d; ; xn--ss-7dp66033t.xn--p5d; # ᢛß.ጧ
+ᢛ󨅟SS.ጧ; ᢛ󨅟ss.ጧ; [P1, V6]; xn--ss-7dp66033t.xn--p5d; ; ; # ᢛss.ጧ
+ᢛ󨅟ss.ጧ; ; [P1, V6]; xn--ss-7dp66033t.xn--p5d; ; ; # ᢛss.ጧ
+ᢛ󨅟Ss.ጧ; ᢛ󨅟ss.ጧ; [P1, V6]; xn--ss-7dp66033t.xn--p5d; ; ; # ᢛss.ጧ
+xn--ss-7dp66033t.xn--p5d; ᢛ󨅟ss.ጧ; [V6]; xn--ss-7dp66033t.xn--p5d; ; ; # ᢛss.ጧ
+xn--zca562jc642x.xn--p5d; ᢛ󨅟ß.ጧ; [V6]; xn--zca562jc642x.xn--p5d; ; ; # ᢛß.ጧ
+⮒‌.񒚗‌; ; [C1, P1, V6]; xn--0ugx66b.xn--0ugz2871c; ; xn--b9i.xn--5p9y; [P1, V6] # ⮒.
+xn--b9i.xn--5p9y; ⮒.񒚗; [V6]; xn--b9i.xn--5p9y; ; ; # ⮒.
+xn--0ugx66b.xn--0ugz2871c; ⮒‌.񒚗‌; [C1, V6]; xn--0ugx66b.xn--0ugz2871c; ; ; # ⮒.
+𞤂񹞁𐹯。Ⴜ; 𞤤񹞁𐹯.Ⴜ; [B2, P1, V6]; xn--no0dr648a51o3b.xn--0nd; ; ; # 𞤤𐹯.Ⴜ
+𞤤񹞁𐹯。ⴜ; 𞤤񹞁𐹯.ⴜ; [B2, P1, V6]; xn--no0dr648a51o3b.xn--klj; ; ; # 𞤤𐹯.ⴜ
+xn--no0dr648a51o3b.xn--klj; 𞤤񹞁𐹯.ⴜ; [B2, V6]; xn--no0dr648a51o3b.xn--klj; ; ; # 𞤤𐹯.ⴜ
+xn--no0dr648a51o3b.xn--0nd; 𞤤񹞁𐹯.Ⴜ; [B2, V6]; xn--no0dr648a51o3b.xn--0nd; ; ; # 𞤤𐹯.Ⴜ
+𞤂񹞁𐹯。ⴜ; 𞤤񹞁𐹯.ⴜ; [B2, P1, V6]; xn--no0dr648a51o3b.xn--klj; ; ; # 𞤤𐹯.ⴜ
+𐹵⮣‌𑄰。񷴿ﲷ; 𐹵⮣‌𑄰.񷴿ضم; [B1, B5, B6, C1, P1, V6]; xn--0ug586bcj8p7jc.xn--1gb4a66004i; ; xn--s9i5458e7yb.xn--1gb4a66004i; [B1, B5, B6, P1, V6] # 𐹵⮣𑄰.ضم
+𐹵⮣‌𑄰。񷴿ضم; 𐹵⮣‌𑄰.񷴿ضم; [B1, B5, B6, C1, P1, V6]; xn--0ug586bcj8p7jc.xn--1gb4a66004i; ; xn--s9i5458e7yb.xn--1gb4a66004i; [B1, B5, B6, P1, V6] # 𐹵⮣𑄰.ضم
+xn--s9i5458e7yb.xn--1gb4a66004i; 𐹵⮣𑄰.񷴿ضم; [B1, B5, B6, V6]; xn--s9i5458e7yb.xn--1gb4a66004i; ; ; # 𐹵⮣𑄰.ضم
+xn--0ug586bcj8p7jc.xn--1gb4a66004i; 𐹵⮣‌𑄰.񷴿ضم; [B1, B5, B6, C1, V6]; xn--0ug586bcj8p7jc.xn--1gb4a66004i; ; ; # 𐹵⮣𑄰.ضم
+Ⴒ。デß𞤵్; Ⴒ.デß𞤵్; [B5, B6, P1, V6]; xn--qnd.xn--zca669cmr3a0f28a; ; xn--qnd.xn--ss-9nh3648ahh20b; # Ⴒ.デß𞤵్
+Ⴒ。デß𞤵్; Ⴒ.デß𞤵్; [B5, B6, P1, V6]; xn--qnd.xn--zca669cmr3a0f28a; ; xn--qnd.xn--ss-9nh3648ahh20b; # Ⴒ.デß𞤵్
+ⴒ。デß𞤵్; ⴒ.デß𞤵్; [B5, B6]; xn--9kj.xn--zca669cmr3a0f28a; ; xn--9kj.xn--ss-9nh3648ahh20b; # ⴒ.デß𞤵్
+ⴒ。デß𞤵్; ⴒ.デß𞤵్; [B5, B6]; xn--9kj.xn--zca669cmr3a0f28a; ; xn--9kj.xn--ss-9nh3648ahh20b; # ⴒ.デß𞤵్
+Ⴒ。デSS𞤓్; Ⴒ.デss𞤵్; [B5, B6, P1, V6]; xn--qnd.xn--ss-9nh3648ahh20b; ; ; # Ⴒ.デss𞤵్
+Ⴒ。デSS𞤓్; Ⴒ.デss𞤵్; [B5, B6, P1, V6]; xn--qnd.xn--ss-9nh3648ahh20b; ; ; # Ⴒ.デss𞤵్
+ⴒ。デss𞤵్; ⴒ.デss𞤵్; [B5, B6]; xn--9kj.xn--ss-9nh3648ahh20b; ; ; # ⴒ.デss𞤵్
+ⴒ。デss𞤵్; ⴒ.デss𞤵్; [B5, B6]; xn--9kj.xn--ss-9nh3648ahh20b; ; ; # ⴒ.デss𞤵్
+Ⴒ。デSs𞤵్; Ⴒ.デss𞤵్; [B5, B6, P1, V6]; xn--qnd.xn--ss-9nh3648ahh20b; ; ; # Ⴒ.デss𞤵్
+Ⴒ。デSs𞤵్; Ⴒ.デss𞤵్; [B5, B6, P1, V6]; xn--qnd.xn--ss-9nh3648ahh20b; ; ; # Ⴒ.デss𞤵్
+xn--qnd.xn--ss-9nh3648ahh20b; Ⴒ.デss𞤵్; [B5, B6, V6]; xn--qnd.xn--ss-9nh3648ahh20b; ; ; # Ⴒ.デss𞤵్
+xn--9kj.xn--ss-9nh3648ahh20b; ⴒ.デss𞤵్; [B5, B6]; xn--9kj.xn--ss-9nh3648ahh20b; ; ; # ⴒ.デss𞤵్
+xn--9kj.xn--zca669cmr3a0f28a; ⴒ.デß𞤵్; [B5, B6]; xn--9kj.xn--zca669cmr3a0f28a; ; ; # ⴒ.デß𞤵్
+xn--qnd.xn--zca669cmr3a0f28a; Ⴒ.デß𞤵్; [B5, B6, V6]; xn--qnd.xn--zca669cmr3a0f28a; ; ; # Ⴒ.デß𞤵్
+Ⴒ。デSS𞤵్; Ⴒ.デss𞤵్; [B5, B6, P1, V6]; xn--qnd.xn--ss-9nh3648ahh20b; ; ; # Ⴒ.デss𞤵్
+Ⴒ。デSS𞤵్; Ⴒ.デss𞤵్; [B5, B6, P1, V6]; xn--qnd.xn--ss-9nh3648ahh20b; ; ; # Ⴒ.デss𞤵్
+𑁿്.7-ߒ; 𑁿്.7-ߒ; [B1, B3, B6, V5]; xn--wxc1283k.xn--7--yue; ; ; # 𑁿്.7-ߒ
+𑁿്.7-ߒ; ; [B1, B3, B6, V5]; xn--wxc1283k.xn--7--yue; ; ; # 𑁿്.7-ߒ
+xn--wxc1283k.xn--7--yue; 𑁿്.7-ߒ; [B1, B3, B6, V5]; xn--wxc1283k.xn--7--yue; ; ; # 𑁿്.7-ߒ
+≯𑜫󠭇.᜴񒞤𑍬ᢧ; ; [P1, V5, V6]; xn--hdhx157g68o0g.xn--c0e65eu616c34o7a; ; ; # ≯𑜫.᜴𑍬ᢧ
+≯𑜫󠭇.᜴񒞤𑍬ᢧ; ≯𑜫󠭇.᜴񒞤𑍬ᢧ; [P1, V5, V6]; xn--hdhx157g68o0g.xn--c0e65eu616c34o7a; ; ; # ≯𑜫.᜴𑍬ᢧ
+xn--hdhx157g68o0g.xn--c0e65eu616c34o7a; ≯𑜫󠭇.᜴񒞤𑍬ᢧ; [V5, V6]; xn--hdhx157g68o0g.xn--c0e65eu616c34o7a; ; ; # ≯𑜫.᜴𑍬ᢧ
+ᷛ򎐙Ⴗ쏔。ށ; ᷛ򎐙Ⴗ쏔.ށ; [B1, P1, V5, V6]; xn--vnd148d733ky6n9e.xn--iqb; ; ; # ᷛႷ쏔.ށ
+ᷛ򎐙Ⴗ쏔。ށ; ᷛ򎐙Ⴗ쏔.ށ; [B1, P1, V5, V6]; xn--vnd148d733ky6n9e.xn--iqb; ; ; # ᷛႷ쏔.ށ
+ᷛ򎐙ⴗ쏔。ށ; ᷛ򎐙ⴗ쏔.ށ; [B1, P1, V5, V6]; xn--zegy26dw47iy6w2f.xn--iqb; ; ; # ᷛⴗ쏔.ށ
+ᷛ򎐙ⴗ쏔。ށ; ᷛ򎐙ⴗ쏔.ށ; [B1, P1, V5, V6]; xn--zegy26dw47iy6w2f.xn--iqb; ; ; # ᷛⴗ쏔.ށ
+xn--zegy26dw47iy6w2f.xn--iqb; ᷛ򎐙ⴗ쏔.ށ; [B1, V5, V6]; xn--zegy26dw47iy6w2f.xn--iqb; ; ; # ᷛⴗ쏔.ށ
+xn--vnd148d733ky6n9e.xn--iqb; ᷛ򎐙Ⴗ쏔.ށ; [B1, V5, V6]; xn--vnd148d733ky6n9e.xn--iqb; ; ; # ᷛႷ쏔.ށ
+ß。𐋳Ⴌྸ; ß.𐋳Ⴌྸ; [P1, V6]; xn--zca.xn--lgd10cu829c; ; ss.xn--lgd10cu829c; # ß.𐋳Ⴌྸ
+ß。𐋳Ⴌྸ; ß.𐋳Ⴌྸ; [P1, V6]; xn--zca.xn--lgd10cu829c; ; ss.xn--lgd10cu829c; # ß.𐋳Ⴌྸ
+ß。𐋳ⴌྸ; ß.𐋳ⴌྸ; ; xn--zca.xn--lgd921mvv0m; ; ss.xn--lgd921mvv0m; # ß.𐋳ⴌྸ
+SS。𐋳Ⴌྸ; ss.𐋳Ⴌྸ; [P1, V6]; ss.xn--lgd10cu829c; ; ; # ss.𐋳Ⴌྸ
+ss。𐋳ⴌྸ; ss.𐋳ⴌྸ; ; ss.xn--lgd921mvv0m; ; ; # ss.𐋳ⴌྸ
+Ss。𐋳Ⴌྸ; ss.𐋳Ⴌྸ; [P1, V6]; ss.xn--lgd10cu829c; ; ; # ss.𐋳Ⴌྸ
+ss.xn--lgd10cu829c; ss.𐋳Ⴌྸ; [V6]; ss.xn--lgd10cu829c; ; ; # ss.𐋳Ⴌྸ
+ss.xn--lgd921mvv0m; ss.𐋳ⴌྸ; ; ss.xn--lgd921mvv0m; ; ; # ss.𐋳ⴌྸ
+ss.𐋳ⴌྸ; ; ; ss.xn--lgd921mvv0m; ; ; # ss.𐋳ⴌྸ
+SS.𐋳Ⴌྸ; ss.𐋳Ⴌྸ; [P1, V6]; ss.xn--lgd10cu829c; ; ; # ss.𐋳Ⴌྸ
+Ss.𐋳Ⴌྸ; ss.𐋳Ⴌྸ; [P1, V6]; ss.xn--lgd10cu829c; ; ; # ss.𐋳Ⴌྸ
+xn--zca.xn--lgd921mvv0m; ß.𐋳ⴌྸ; ; xn--zca.xn--lgd921mvv0m; ; ; # ß.𐋳ⴌྸ
+ß.𐋳ⴌྸ; ; ; xn--zca.xn--lgd921mvv0m; ; ss.xn--lgd921mvv0m; # ß.𐋳ⴌྸ
+xn--zca.xn--lgd10cu829c; ß.𐋳Ⴌྸ; [V6]; xn--zca.xn--lgd10cu829c; ; ; # ß.𐋳Ⴌྸ
+ß。𐋳ⴌྸ; ß.𐋳ⴌྸ; ; xn--zca.xn--lgd921mvv0m; ; ss.xn--lgd921mvv0m; # ß.𐋳ⴌྸ
+SS。𐋳Ⴌྸ; ss.𐋳Ⴌྸ; [P1, V6]; ss.xn--lgd10cu829c; ; ; # ss.𐋳Ⴌྸ
+ss。𐋳ⴌྸ; ss.𐋳ⴌྸ; ; ss.xn--lgd921mvv0m; ; ; # ss.𐋳ⴌྸ
+Ss。𐋳Ⴌྸ; ss.𐋳Ⴌྸ; [P1, V6]; ss.xn--lgd10cu829c; ; ; # ss.𐋳Ⴌྸ
+-ڞ𐶡.‌⾝্; -ڞ𐶡.‌身্; [B1, C1, P1, V3, V6]; xn----stc7013r.xn--b7b305imj2f; ; xn----stc7013r.xn--b7b1419d; [B1, P1, V3, V6] # -ڞ.身্
+-ڞ𐶡.‌身্; ; [B1, C1, P1, V3, V6]; xn----stc7013r.xn--b7b305imj2f; ; xn----stc7013r.xn--b7b1419d; [B1, P1, V3, V6] # -ڞ.身্
+xn----stc7013r.xn--b7b1419d; -ڞ𐶡.身্; [B1, V3, V6]; xn----stc7013r.xn--b7b1419d; ; ; # -ڞ.身্
+xn----stc7013r.xn--b7b305imj2f; -ڞ𐶡.‌身্; [B1, C1, V3, V6]; xn----stc7013r.xn--b7b305imj2f; ; ; # -ڞ.身্
+😮ݤ𑈵𞀖.💅‍; 😮ݤ𑈵𞀖.💅‍; [B1, C2]; xn--opb4277kuc7elqsa.xn--1ug5265p; ; xn--opb4277kuc7elqsa.xn--kr8h; [B1] # 😮ݤ𑈵𞀖.💅
+😮ݤ𑈵𞀖.💅‍; ; [B1, C2]; xn--opb4277kuc7elqsa.xn--1ug5265p; ; xn--opb4277kuc7elqsa.xn--kr8h; [B1] # 😮ݤ𑈵𞀖.💅
+xn--opb4277kuc7elqsa.xn--kr8h; 😮ݤ𑈵𞀖.💅; [B1]; xn--opb4277kuc7elqsa.xn--kr8h; ; ; # 😮ݤ𑈵𞀖.💅
+xn--opb4277kuc7elqsa.xn--1ug5265p; 😮ݤ𑈵𞀖.💅‍; [B1, C2]; xn--opb4277kuc7elqsa.xn--1ug5265p; ; ; # 😮ݤ𑈵𞀖.💅
+ࣲ‍꙳ܒ.ᢏ‌󠍄; ; [B1, B6, C1, C2, P1, V5, V6]; xn--cnb37g904be26j.xn--89e849ax9363a; ; xn--cnb37gdy00a.xn--89e02253p; [B1, B6, P1, V5, V6] # ࣲ꙳ܒ.ᢏ
+xn--cnb37gdy00a.xn--89e02253p; ࣲ꙳ܒ.ᢏ󠍄; [B1, B6, V5, V6]; xn--cnb37gdy00a.xn--89e02253p; ; ; # ࣲ꙳ܒ.ᢏ
+xn--cnb37g904be26j.xn--89e849ax9363a; ࣲ‍꙳ܒ.ᢏ‌󠍄; [B1, B6, C1, C2, V5, V6]; xn--cnb37g904be26j.xn--89e849ax9363a; ; ; # ࣲ꙳ܒ.ᢏ
+Ⴑ.ڿ𞯓ᠲ; Ⴑ.ڿ𞯓ᠲ; [B2, B3, P1, V6]; xn--pnd.xn--ykb840gd555a; ; ; # Ⴑ.ڿᠲ
+Ⴑ.ڿ𞯓ᠲ; ; [B2, B3, P1, V6]; xn--pnd.xn--ykb840gd555a; ; ; # Ⴑ.ڿᠲ
+ⴑ.ڿ𞯓ᠲ; ; [B2, B3, P1, V6]; xn--8kj.xn--ykb840gd555a; ; ; # ⴑ.ڿᠲ
+xn--8kj.xn--ykb840gd555a; ⴑ.ڿ𞯓ᠲ; [B2, B3, V6]; xn--8kj.xn--ykb840gd555a; ; ; # ⴑ.ڿᠲ
+xn--pnd.xn--ykb840gd555a; Ⴑ.ڿ𞯓ᠲ; [B2, B3, V6]; xn--pnd.xn--ykb840gd555a; ; ; # Ⴑ.ڿᠲ
+ⴑ.ڿ𞯓ᠲ; ⴑ.ڿ𞯓ᠲ; [B2, B3, P1, V6]; xn--8kj.xn--ykb840gd555a; ; ; # ⴑ.ڿᠲ
+ᩚ𛦝్。𚝬𝟵; ᩚ𛦝్.𚝬9; [P1, V5, V6]; xn--lqc703ebm93a.xn--9-000p; ; ; # ᩚ్.9
+ᩚ𛦝్。𚝬9; ᩚ𛦝్.𚝬9; [P1, V5, V6]; xn--lqc703ebm93a.xn--9-000p; ; ; # ᩚ్.9
+xn--lqc703ebm93a.xn--9-000p; ᩚ𛦝్.𚝬9; [V5, V6]; xn--lqc703ebm93a.xn--9-000p; ; ; # ᩚ్.9
+‌ڠ𿺆𝟗。Ⴣ꒘ﳐ񐘖; ‌ڠ𿺆9.Ⴣ꒘مخ񐘖; [B1, B5, C1, P1, V6]; xn--9-vtc736qts91g.xn--tgb9bz61cfn8mw3t2c; ; xn--9-vtc42319e.xn--tgb9bz61cfn8mw3t2c; [B2, B5, P1, V6] # ڠ9.Ⴣ꒘مخ
+‌ڠ𿺆9。Ⴣ꒘مخ񐘖; ‌ڠ𿺆9.Ⴣ꒘مخ񐘖; [B1, B5, C1, P1, V6]; xn--9-vtc736qts91g.xn--tgb9bz61cfn8mw3t2c; ; xn--9-vtc42319e.xn--tgb9bz61cfn8mw3t2c; [B2, B5, P1, V6] # ڠ9.Ⴣ꒘مخ
+‌ڠ𿺆9。ⴣ꒘مخ񐘖; ‌ڠ𿺆9.ⴣ꒘مخ񐘖; [B1, B5, C1, P1, V6]; xn--9-vtc736qts91g.xn--tgb9bz87p833hw316c; ; xn--9-vtc42319e.xn--tgb9bz87p833hw316c; [B2, B5, P1, V6] # ڠ9.ⴣ꒘مخ
+xn--9-vtc42319e.xn--tgb9bz87p833hw316c; ڠ𿺆9.ⴣ꒘مخ񐘖; [B2, B5, V6]; xn--9-vtc42319e.xn--tgb9bz87p833hw316c; ; ; # ڠ9.ⴣ꒘مخ
+xn--9-vtc736qts91g.xn--tgb9bz87p833hw316c; ‌ڠ𿺆9.ⴣ꒘مخ񐘖; [B1, B5, C1, V6]; xn--9-vtc736qts91g.xn--tgb9bz87p833hw316c; ; ; # ڠ9.ⴣ꒘مخ
+xn--9-vtc42319e.xn--tgb9bz61cfn8mw3t2c; ڠ𿺆9.Ⴣ꒘مخ񐘖; [B2, B5, V6]; xn--9-vtc42319e.xn--tgb9bz61cfn8mw3t2c; ; ; # ڠ9.Ⴣ꒘مخ
+xn--9-vtc736qts91g.xn--tgb9bz61cfn8mw3t2c; ‌ڠ𿺆9.Ⴣ꒘مخ񐘖; [B1, B5, C1, V6]; xn--9-vtc736qts91g.xn--tgb9bz61cfn8mw3t2c; ; ; # ڠ9.Ⴣ꒘مخ
+‌ڠ𿺆𝟗。ⴣ꒘ﳐ񐘖; ‌ڠ𿺆9.ⴣ꒘مخ񐘖; [B1, B5, C1, P1, V6]; xn--9-vtc736qts91g.xn--tgb9bz87p833hw316c; ; xn--9-vtc42319e.xn--tgb9bz87p833hw316c; [B2, B5, P1, V6] # ڠ9.ⴣ꒘مخ
+ᡖ。̟񗛨ஂ-; ᡖ.̟񗛨ஂ-; [P1, V3, V5, V6]; xn--m8e.xn----mdb555dkk71m; ; ; # ᡖ.̟ஂ-
+ᡖ。̟񗛨ஂ-; ᡖ.̟񗛨ஂ-; [P1, V3, V5, V6]; xn--m8e.xn----mdb555dkk71m; ; ; # ᡖ.̟ஂ-
+xn--m8e.xn----mdb555dkk71m; ᡖ.̟񗛨ஂ-; [V3, V5, V6]; xn--m8e.xn----mdb555dkk71m; ; ; # ᡖ.̟ஂ-
+𞠠浘。絧𞀀; 𞠠浘.絧𞀀; [B2, B3]; xn--e0wp491f.xn--ud0a3573e; ; ; # 𞠠浘.絧𞀀
+xn--e0wp491f.xn--ud0a3573e; 𞠠浘.絧𞀀; [B2, B3]; xn--e0wp491f.xn--ud0a3573e; ; ; # 𞠠浘.絧𞀀
+֖Ⴋ.𝟳≯︒︊; ֖Ⴋ.7≯︒; [P1, V5, V6]; xn--hcb887c.xn--7-pgoy530h; ; ; # ֖Ⴋ.7≯︒
+֖Ⴋ.𝟳≯︒︊; ֖Ⴋ.7≯︒; [P1, V5, V6]; xn--hcb887c.xn--7-pgoy530h; ; ; # ֖Ⴋ.7≯︒
+֖Ⴋ.7≯。︊; ֖Ⴋ.7≯.; [P1, V5, V6]; xn--hcb887c.xn--7-pgo.; ; ; # ֖Ⴋ.7≯.
+֖Ⴋ.7≯。︊; ֖Ⴋ.7≯.; [P1, V5, V6]; xn--hcb887c.xn--7-pgo.; ; ; # ֖Ⴋ.7≯.
+֖ⴋ.7≯。︊; ֖ⴋ.7≯.; [P1, V5, V6]; xn--hcb613r.xn--7-pgo.; ; ; # ֖ⴋ.7≯.
+֖ⴋ.7≯。︊; ֖ⴋ.7≯.; [P1, V5, V6]; xn--hcb613r.xn--7-pgo.; ; ; # ֖ⴋ.7≯.
+xn--hcb613r.xn--7-pgo.; ֖ⴋ.7≯.; [V5, V6]; xn--hcb613r.xn--7-pgo.; ; ; # ֖ⴋ.7≯.
+xn--hcb887c.xn--7-pgo.; ֖Ⴋ.7≯.; [V5, V6]; xn--hcb887c.xn--7-pgo.; ; ; # ֖Ⴋ.7≯.
+֖ⴋ.𝟳≯︒︊; ֖ⴋ.7≯︒; [P1, V5, V6]; xn--hcb613r.xn--7-pgoy530h; ; ; # ֖ⴋ.7≯︒
+֖ⴋ.𝟳≯︒︊; ֖ⴋ.7≯︒; [P1, V5, V6]; xn--hcb613r.xn--7-pgoy530h; ; ; # ֖ⴋ.7≯︒
+xn--hcb613r.xn--7-pgoy530h; ֖ⴋ.7≯︒; [V5, V6]; xn--hcb613r.xn--7-pgoy530h; ; ; # ֖ⴋ.7≯︒
+xn--hcb887c.xn--7-pgoy530h; ֖Ⴋ.7≯︒; [V5, V6]; xn--hcb887c.xn--7-pgoy530h; ; ; # ֖Ⴋ.7≯︒
+‍F𑓂。󠺨︒ݾ𐹢; ‍f𑓂.󠺨︒ݾ𐹢; [B1, C2, P1, V6]; xn--f-tgn9761i.xn--fqb1637j8hky9452a; ; xn--f-kq9i.xn--fqb1637j8hky9452a; [B1, P1, V6] # f𑓂.︒ݾ𐹢
+‍F𑓂。󠺨。ݾ𐹢; ‍f𑓂.󠺨.ݾ𐹢; [B1, C2, P1, V6]; xn--f-tgn9761i.xn--7656e.xn--fqb4175k; ; xn--f-kq9i.xn--7656e.xn--fqb4175k; [B1, P1, V6] # f𑓂..ݾ𐹢
+‍f𑓂。󠺨。ݾ𐹢; ‍f𑓂.󠺨.ݾ𐹢; [B1, C2, P1, V6]; xn--f-tgn9761i.xn--7656e.xn--fqb4175k; ; xn--f-kq9i.xn--7656e.xn--fqb4175k; [B1, P1, V6] # f𑓂..ݾ𐹢
+xn--f-kq9i.xn--7656e.xn--fqb4175k; f𑓂.󠺨.ݾ𐹢; [B1, V6]; xn--f-kq9i.xn--7656e.xn--fqb4175k; ; ; # f𑓂..ݾ𐹢
+xn--f-tgn9761i.xn--7656e.xn--fqb4175k; ‍f𑓂.󠺨.ݾ𐹢; [B1, C2, V6]; xn--f-tgn9761i.xn--7656e.xn--fqb4175k; ; ; # f𑓂..ݾ𐹢
+‍f𑓂。󠺨︒ݾ𐹢; ‍f𑓂.󠺨︒ݾ𐹢; [B1, C2, P1, V6]; xn--f-tgn9761i.xn--fqb1637j8hky9452a; ; xn--f-kq9i.xn--fqb1637j8hky9452a; [B1, P1, V6] # f𑓂.︒ݾ𐹢
+xn--f-kq9i.xn--fqb1637j8hky9452a; f𑓂.󠺨︒ݾ𐹢; [B1, V6]; xn--f-kq9i.xn--fqb1637j8hky9452a; ; ; # f𑓂.︒ݾ𐹢
+xn--f-tgn9761i.xn--fqb1637j8hky9452a; ‍f𑓂.󠺨︒ݾ𐹢; [B1, C2, V6]; xn--f-tgn9761i.xn--fqb1637j8hky9452a; ; ; # f𑓂.︒ݾ𐹢
+ࡅ🄇𐼗︒。𐹻𑜫; ࡅ🄇𐼗︒.𐹻𑜫; [B1, B3, P1, V6]; xn--3vb4696jpxkjh7s.xn--zo0di2m; ; ; # ࡅ🄇𐼗︒.𐹻𑜫
+ࡅ6,𐼗。。𐹻𑜫; ࡅ6,𐼗..𐹻𑜫; [B1, P1, V6, X4_2]; xn--6,-r4e4420y..xn--zo0di2m; [B1, P1, V6, A4_2]; ; # ࡅ6,𐼗..𐹻𑜫
+xn--6,-r4e4420y..xn--zo0di2m; ࡅ6,𐼗..𐹻𑜫; [B1, P1, V6, X4_2]; xn--6,-r4e4420y..xn--zo0di2m; [B1, P1, V6, A4_2]; ; # ࡅ6,𐼗..𐹻𑜫
+xn--3vb4696jpxkjh7s.xn--zo0di2m; ࡅ🄇𐼗︒.𐹻𑜫; [B1, B3, V6]; xn--3vb4696jpxkjh7s.xn--zo0di2m; ; ; # ࡅ🄇𐼗︒.𐹻𑜫
+𐹈.᷀𑈱𐦭; ; [B1, P1, V5, V6]; xn--jn0d.xn--7dg0871h3lf; ; ; # .᷀𑈱𐦭
+xn--jn0d.xn--7dg0871h3lf; 𐹈.᷀𑈱𐦭; [B1, V5, V6]; xn--jn0d.xn--7dg0871h3lf; ; ; # .᷀𑈱𐦭
+Ⴂ䠺。𞤃񅏎󙮦ړ; Ⴂ䠺.𞤥񅏎󙮦ړ; [B2, P1, V6]; xn--9md875z.xn--pjb9818vg4xno967d; ; ; # Ⴂ䠺.𞤥ړ
+ⴂ䠺。𞤥񅏎󙮦ړ; ⴂ䠺.𞤥񅏎󙮦ړ; [B2, P1, V6]; xn--tkj638f.xn--pjb9818vg4xno967d; ; ; # ⴂ䠺.𞤥ړ
+xn--tkj638f.xn--pjb9818vg4xno967d; ⴂ䠺.𞤥񅏎󙮦ړ; [B2, V6]; xn--tkj638f.xn--pjb9818vg4xno967d; ; ; # ⴂ䠺.𞤥ړ
+xn--9md875z.xn--pjb9818vg4xno967d; Ⴂ䠺.𞤥񅏎󙮦ړ; [B2, V6]; xn--9md875z.xn--pjb9818vg4xno967d; ; ; # Ⴂ䠺.𞤥ړ
+ⴂ䠺。𞤃񅏎󙮦ړ; ⴂ䠺.𞤥񅏎󙮦ړ; [B2, P1, V6]; xn--tkj638f.xn--pjb9818vg4xno967d; ; ; # ⴂ䠺.𞤥ړ
+🄇伐︒.𜙚꣄; ; [P1, V6]; xn--woqs083bel0g.xn--0f9ao925c; ; ; # 🄇伐︒.꣄
+6,伐。.𜙚꣄; 6,伐..𜙚꣄; [P1, V6, X4_2]; xn--6,-7i3c..xn--0f9ao925c; [P1, V6, A4_2]; ; # 6,伐..꣄
+xn--6,-7i3c..xn--0f9ao925c; 6,伐..𜙚꣄; [P1, V6, X4_2]; xn--6,-7i3c..xn--0f9ao925c; [P1, V6, A4_2]; ; # 6,伐..꣄
+xn--woqs083bel0g.xn--0f9ao925c; 🄇伐︒.𜙚꣄; [V6]; xn--woqs083bel0g.xn--0f9ao925c; ; ; # 🄇伐︒.꣄
+‍𐹠꯭。‍𐫓Ⴚ𑂹; ‍𐹠꯭.‍𐫓Ⴚ𑂹; [B1, C2, P1, V6]; xn--1ugz126coy7bdbm.xn--ynd959evs1pv6e; ; xn--429az70n29i.xn--ynd3619jqyd; [B1, B2, B3, P1, V6] # 𐹠꯭.𐫓Ⴚ𑂹
+‍𐹠꯭。‍𐫓ⴚ𑂹; ‍𐹠꯭.‍𐫓ⴚ𑂹; [B1, C2, P1, V6]; xn--1ugz126coy7bdbm.xn--1ug062chv7ov6e; ; xn--429az70n29i.xn--ilj7702eqyd; [B1, B2, B3, P1, V6] # 𐹠꯭.𐫓ⴚ𑂹
+xn--429az70n29i.xn--ilj7702eqyd; 𐹠꯭.𐫓ⴚ𑂹; [B1, B2, B3, V6]; xn--429az70n29i.xn--ilj7702eqyd; ; ; # 𐹠꯭.𐫓ⴚ𑂹
+xn--1ugz126coy7bdbm.xn--1ug062chv7ov6e; ‍𐹠꯭.‍𐫓ⴚ𑂹; [B1, C2, V6]; xn--1ugz126coy7bdbm.xn--1ug062chv7ov6e; ; ; # 𐹠꯭.𐫓ⴚ𑂹
+xn--429az70n29i.xn--ynd3619jqyd; 𐹠꯭.𐫓Ⴚ𑂹; [B1, B2, B3, V6]; xn--429az70n29i.xn--ynd3619jqyd; ; ; # 𐹠꯭.𐫓Ⴚ𑂹
+xn--1ugz126coy7bdbm.xn--ynd959evs1pv6e; ‍𐹠꯭.‍𐫓Ⴚ𑂹; [B1, C2, V6]; xn--1ugz126coy7bdbm.xn--ynd959evs1pv6e; ; ; # 𐹠꯭.𐫓Ⴚ𑂹
+󠆠.񷐴󌟈; .񷐴󌟈; [P1, V6, X4_2]; .xn--rx21bhv12i; [P1, V6, A4_2]; ; # .
+󠆠.񷐴󌟈; .񷐴󌟈; [P1, V6, X4_2]; .xn--rx21bhv12i; [P1, V6, A4_2]; ; # .
+.xn--rx21bhv12i; .񷐴󌟈; [V6, X4_2]; .xn--rx21bhv12i; [V6, A4_2]; ; # .
+𐫃‌Ⴆ.≠𞷙; ; [B1, B2, B3, C1, P1, V6]; xn--end799ekr1p.xn--1ch2802p; ; xn--end1719j.xn--1ch2802p; [B1, B2, B3, P1, V6] # 𐫃Ⴆ.≠
+𐫃‌Ⴆ.≠𞷙; 𐫃‌Ⴆ.≠𞷙; [B1, B2, B3, C1, P1, V6]; xn--end799ekr1p.xn--1ch2802p; ; xn--end1719j.xn--1ch2802p; [B1, B2, B3, P1, V6] # 𐫃Ⴆ.≠
+𐫃‌ⴆ.≠𞷙; 𐫃‌ⴆ.≠𞷙; [B1, B2, B3, C1, P1, V6]; xn--0ug132csv7o.xn--1ch2802p; ; xn--xkjz802e.xn--1ch2802p; [B1, B2, B3, P1, V6] # 𐫃ⴆ.≠
+𐫃‌ⴆ.≠𞷙; ; [B1, B2, B3, C1, P1, V6]; xn--0ug132csv7o.xn--1ch2802p; ; xn--xkjz802e.xn--1ch2802p; [B1, B2, B3, P1, V6] # 𐫃ⴆ.≠
+xn--xkjz802e.xn--1ch2802p; 𐫃ⴆ.≠𞷙; [B1, B2, B3, V6]; xn--xkjz802e.xn--1ch2802p; ; ; # 𐫃ⴆ.≠
+xn--0ug132csv7o.xn--1ch2802p; 𐫃‌ⴆ.≠𞷙; [B1, B2, B3, C1, V6]; xn--0ug132csv7o.xn--1ch2802p; ; ; # 𐫃ⴆ.≠
+xn--end1719j.xn--1ch2802p; 𐫃Ⴆ.≠𞷙; [B1, B2, B3, V6]; xn--end1719j.xn--1ch2802p; ; ; # 𐫃Ⴆ.≠
+xn--end799ekr1p.xn--1ch2802p; 𐫃‌Ⴆ.≠𞷙; [B1, B2, B3, C1, V6]; xn--end799ekr1p.xn--1ch2802p; ; ; # 𐫃Ⴆ.≠
+󠁲𙩢𝟥ꘌ.ࡁ; 󠁲𙩢3ꘌ.ࡁ; [B1, P1, V6]; xn--3-0g3es485d8i15h.xn--zvb; ; ; # 3ꘌ.ࡁ
+󠁲𙩢3ꘌ.ࡁ; ; [B1, P1, V6]; xn--3-0g3es485d8i15h.xn--zvb; ; ; # 3ꘌ.ࡁ
+xn--3-0g3es485d8i15h.xn--zvb; 󠁲𙩢3ꘌ.ࡁ; [B1, V6]; xn--3-0g3es485d8i15h.xn--zvb; ; ; # 3ꘌ.ࡁ
+-.ᢆ󡲣-; ; [P1, V3, V5, V6]; -.xn----pbkx6497q; ; ; # -.ᢆ-
+-.xn----pbkx6497q; -.ᢆ󡲣-; [V3, V5, V6]; -.xn----pbkx6497q; ; ; # -.ᢆ-
+󲚗‌。‌𞰆ς; 󲚗‌.‌𞰆ς; [B1, B6, C1, P1, V6]; xn--0ug76062m.xn--3xa795lhn92a; ; xn--qp42f.xn--4xa3011w; [B2, B3, P1, V6] # .ς
+󲚗‌。‌𞰆ς; 󲚗‌.‌𞰆ς; [B1, B6, C1, P1, V6]; xn--0ug76062m.xn--3xa795lhn92a; ; xn--qp42f.xn--4xa3011w; [B2, B3, P1, V6] # .ς
+󲚗‌。‌𞰆Σ; 󲚗‌.‌𞰆σ; [B1, B6, C1, P1, V6]; xn--0ug76062m.xn--4xa595lhn92a; ; xn--qp42f.xn--4xa3011w; [B2, B3, P1, V6] # .σ
+󲚗‌。‌𞰆σ; 󲚗‌.‌𞰆σ; [B1, B6, C1, P1, V6]; xn--0ug76062m.xn--4xa595lhn92a; ; xn--qp42f.xn--4xa3011w; [B2, B3, P1, V6] # .σ
+xn--qp42f.xn--4xa3011w; 󲚗.𞰆σ; [B2, B3, V6]; xn--qp42f.xn--4xa3011w; ; ; # .σ
+xn--0ug76062m.xn--4xa595lhn92a; 󲚗‌.‌𞰆σ; [B1, B6, C1, V6]; xn--0ug76062m.xn--4xa595lhn92a; ; ; # .σ
+xn--0ug76062m.xn--3xa795lhn92a; 󲚗‌.‌𞰆ς; [B1, B6, C1, V6]; xn--0ug76062m.xn--3xa795lhn92a; ; ; # .ς
+󲚗‌。‌𞰆Σ; 󲚗‌.‌𞰆σ; [B1, B6, C1, P1, V6]; xn--0ug76062m.xn--4xa595lhn92a; ; xn--qp42f.xn--4xa3011w; [B2, B3, P1, V6] # .σ
+󲚗‌。‌𞰆σ; 󲚗‌.‌𞰆σ; [B1, B6, C1, P1, V6]; xn--0ug76062m.xn--4xa595lhn92a; ; xn--qp42f.xn--4xa3011w; [B2, B3, P1, V6] # .σ
+堕𑓂ᬂ。𐮇𞤽‌-; 堕𑓂ᬂ.𐮇𞤽‌-; [B3, C1, V3]; xn--5sf345zdk8h.xn----rgnt157hwl9g; ; xn--5sf345zdk8h.xn----iv5iw606c; [B3, V3] # 堕𑓂ᬂ.𐮇𞤽-
+堕𑓂ᬂ。𐮇𞤛‌-; 堕𑓂ᬂ.𐮇𞤽‌-; [B3, C1, V3]; xn--5sf345zdk8h.xn----rgnt157hwl9g; ; xn--5sf345zdk8h.xn----iv5iw606c; [B3, V3] # 堕𑓂ᬂ.𐮇𞤽-
+xn--5sf345zdk8h.xn----iv5iw606c; 堕𑓂ᬂ.𐮇𞤽-; [B3, V3]; xn--5sf345zdk8h.xn----iv5iw606c; ; ; # 堕𑓂ᬂ.𐮇𞤽-
+xn--5sf345zdk8h.xn----rgnt157hwl9g; 堕𑓂ᬂ.𐮇𞤽‌-; [B3, C1, V3]; xn--5sf345zdk8h.xn----rgnt157hwl9g; ; ; # 堕𑓂ᬂ.𐮇𞤽-
+𐹶𑁆ᡕ𞤢。ᡥςتς; 𐹶𑁆ᡕ𞤢.ᡥςتς; [B1, B5]; xn--l8e1317j1ebz456b.xn--3xaa16plx4a; ; xn--l8e1317j1ebz456b.xn--4xaa85plx4a; # 𐹶𑁆ᡕ𞤢.ᡥςتς
+𐹶𑁆ᡕ𞤢。ᡥςتς; 𐹶𑁆ᡕ𞤢.ᡥςتς; [B1, B5]; xn--l8e1317j1ebz456b.xn--3xaa16plx4a; ; xn--l8e1317j1ebz456b.xn--4xaa85plx4a; # 𐹶𑁆ᡕ𞤢.ᡥςتς
+𐹶𑁆ᡕ𞤀。ᡥΣتΣ; 𐹶𑁆ᡕ𞤢.ᡥσتσ; [B1, B5]; xn--l8e1317j1ebz456b.xn--4xaa85plx4a; ; ; # 𐹶𑁆ᡕ𞤢.ᡥσتσ
+𐹶𑁆ᡕ𞤢。ᡥσتσ; 𐹶𑁆ᡕ𞤢.ᡥσتσ; [B1, B5]; xn--l8e1317j1ebz456b.xn--4xaa85plx4a; ; ; # 𐹶𑁆ᡕ𞤢.ᡥσتσ
+xn--l8e1317j1ebz456b.xn--4xaa85plx4a; 𐹶𑁆ᡕ𞤢.ᡥσتσ; [B1, B5]; xn--l8e1317j1ebz456b.xn--4xaa85plx4a; ; ; # 𐹶𑁆ᡕ𞤢.ᡥσتσ
+xn--l8e1317j1ebz456b.xn--3xaa16plx4a; 𐹶𑁆ᡕ𞤢.ᡥςتς; [B1, B5]; xn--l8e1317j1ebz456b.xn--3xaa16plx4a; ; ; # 𐹶𑁆ᡕ𞤢.ᡥςتς
+𐹶𑁆ᡕ𞤀。ᡥΣتΣ; 𐹶𑁆ᡕ𞤢.ᡥσتσ; [B1, B5]; xn--l8e1317j1ebz456b.xn--4xaa85plx4a; ; ; # 𐹶𑁆ᡕ𞤢.ᡥσتσ
+𐹶𑁆ᡕ𞤢。ᡥσتσ; 𐹶𑁆ᡕ𞤢.ᡥσتσ; [B1, B5]; xn--l8e1317j1ebz456b.xn--4xaa85plx4a; ; ; # 𐹶𑁆ᡕ𞤢.ᡥσتσ
+𐹶𑁆ᡕ𞤢。ᡥΣتΣ; 𐹶𑁆ᡕ𞤢.ᡥσتσ; [B1, B5]; xn--l8e1317j1ebz456b.xn--4xaa85plx4a; ; ; # 𐹶𑁆ᡕ𞤢.ᡥσتσ
+𐹶𑁆ᡕ𞤢。ᡥΣتσ; 𐹶𑁆ᡕ𞤢.ᡥσتσ; [B1, B5]; xn--l8e1317j1ebz456b.xn--4xaa85plx4a; ; ; # 𐹶𑁆ᡕ𞤢.ᡥσتσ
+𐹶𑁆ᡕ𞤢。ᡥΣتς; 𐹶𑁆ᡕ𞤢.ᡥσتς; [B1, B5]; xn--l8e1317j1ebz456b.xn--3xab95plx4a; ; xn--l8e1317j1ebz456b.xn--4xaa85plx4a; # 𐹶𑁆ᡕ𞤢.ᡥσتς
+𐹶𑁆ᡕ𞤢。ᡥσتς; 𐹶𑁆ᡕ𞤢.ᡥσتς; [B1, B5]; xn--l8e1317j1ebz456b.xn--3xab95plx4a; ; xn--l8e1317j1ebz456b.xn--4xaa85plx4a; # 𐹶𑁆ᡕ𞤢.ᡥσتς
+xn--l8e1317j1ebz456b.xn--3xab95plx4a; 𐹶𑁆ᡕ𞤢.ᡥσتς; [B1, B5]; xn--l8e1317j1ebz456b.xn--3xab95plx4a; ; ; # 𐹶𑁆ᡕ𞤢.ᡥσتς
+𐹶𑁆ᡕ𞤢。ᡥΣتΣ; 𐹶𑁆ᡕ𞤢.ᡥσتσ; [B1, B5]; xn--l8e1317j1ebz456b.xn--4xaa85plx4a; ; ; # 𐹶𑁆ᡕ𞤢.ᡥσتσ
+𐹶𑁆ᡕ𞤢。ᡥΣتσ; 𐹶𑁆ᡕ𞤢.ᡥσتσ; [B1, B5]; xn--l8e1317j1ebz456b.xn--4xaa85plx4a; ; ; # 𐹶𑁆ᡕ𞤢.ᡥσتσ
+𐹶𑁆ᡕ𞤢。ᡥΣتς; 𐹶𑁆ᡕ𞤢.ᡥσتς; [B1, B5]; xn--l8e1317j1ebz456b.xn--3xab95plx4a; ; xn--l8e1317j1ebz456b.xn--4xaa85plx4a; # 𐹶𑁆ᡕ𞤢.ᡥσتς
+𐹶𑁆ᡕ𞤢。ᡥσتς; 𐹶𑁆ᡕ𞤢.ᡥσتς; [B1, B5]; xn--l8e1317j1ebz456b.xn--3xab95plx4a; ; xn--l8e1317j1ebz456b.xn--4xaa85plx4a; # 𐹶𑁆ᡕ𞤢.ᡥσتς
+󏒰.-𝟻ß; 󏒰.-5ß; [P1, V3, V6]; xn--t960e.xn---5-hia; ; xn--t960e.-5ss; # .-5ß
+󏒰.-5ß; ; [P1, V3, V6]; xn--t960e.xn---5-hia; ; xn--t960e.-5ss; # .-5ß
+󏒰.-5SS; 󏒰.-5ss; [P1, V3, V6]; xn--t960e.-5ss; ; ; # .-5ss
+󏒰.-5ss; ; [P1, V3, V6]; xn--t960e.-5ss; ; ; # .-5ss
+xn--t960e.-5ss; 󏒰.-5ss; [V3, V6]; xn--t960e.-5ss; ; ; # .-5ss
+xn--t960e.xn---5-hia; 󏒰.-5ß; [V3, V6]; xn--t960e.xn---5-hia; ; ; # .-5ß
+󏒰.-𝟻SS; 󏒰.-5ss; [P1, V3, V6]; xn--t960e.-5ss; ; ; # .-5ss
+󏒰.-𝟻ss; 󏒰.-5ss; [P1, V3, V6]; xn--t960e.-5ss; ; ; # .-5ss
+󏒰.-𝟻Ss; 󏒰.-5ss; [P1, V3, V6]; xn--t960e.-5ss; ; ; # .-5ss
+󏒰.-5Ss; 󏒰.-5ss; [P1, V3, V6]; xn--t960e.-5ss; ; ; # .-5ss
+‍𐨿.🤒Ⴥ򑮶; ; [C2, P1, V6]; xn--1ug9533g.xn--9nd3211w0gz4b; ; xn--0s9c.xn--9nd3211w0gz4b; [P1, V5, V6] # 𐨿.🤒Ⴥ
+‍𐨿.🤒ⴥ򑮶; ; [C2, P1, V6]; xn--1ug9533g.xn--tljz038l0gz4b; ; xn--0s9c.xn--tljz038l0gz4b; [P1, V5, V6] # 𐨿.🤒ⴥ
+xn--0s9c.xn--tljz038l0gz4b; 𐨿.🤒ⴥ򑮶; [V5, V6]; xn--0s9c.xn--tljz038l0gz4b; ; ; # 𐨿.🤒ⴥ
+xn--1ug9533g.xn--tljz038l0gz4b; ‍𐨿.🤒ⴥ򑮶; [C2, V6]; xn--1ug9533g.xn--tljz038l0gz4b; ; ; # 𐨿.🤒ⴥ
+xn--0s9c.xn--9nd3211w0gz4b; 𐨿.🤒Ⴥ򑮶; [V5, V6]; xn--0s9c.xn--9nd3211w0gz4b; ; ; # 𐨿.🤒Ⴥ
+xn--1ug9533g.xn--9nd3211w0gz4b; ‍𐨿.🤒Ⴥ򑮶; [C2, V6]; xn--1ug9533g.xn--9nd3211w0gz4b; ; ; # 𐨿.🤒Ⴥ
+𵋅。ß𬵩‍; 𵋅.ß𬵩‍; [C2, P1, V6]; xn--ey1p.xn--zca870nz438b; ; xn--ey1p.xn--ss-eq36b; [P1, V6] # .ß𬵩
+𵋅。SS𬵩‍; 𵋅.ss𬵩‍; [C2, P1, V6]; xn--ey1p.xn--ss-n1tx0508a; ; xn--ey1p.xn--ss-eq36b; [P1, V6] # .ss𬵩
+𵋅。ss𬵩‍; 𵋅.ss𬵩‍; [C2, P1, V6]; xn--ey1p.xn--ss-n1tx0508a; ; xn--ey1p.xn--ss-eq36b; [P1, V6] # .ss𬵩
+𵋅。Ss𬵩‍; 𵋅.ss𬵩‍; [C2, P1, V6]; xn--ey1p.xn--ss-n1tx0508a; ; xn--ey1p.xn--ss-eq36b; [P1, V6] # .ss𬵩
+xn--ey1p.xn--ss-eq36b; 𵋅.ss𬵩; [V6]; xn--ey1p.xn--ss-eq36b; ; ; # .ss𬵩
+xn--ey1p.xn--ss-n1tx0508a; 𵋅.ss𬵩‍; [C2, V6]; xn--ey1p.xn--ss-n1tx0508a; ; ; # .ss𬵩
+xn--ey1p.xn--zca870nz438b; 𵋅.ß𬵩‍; [C2, V6]; xn--ey1p.xn--zca870nz438b; ; ; # .ß𬵩
+‌𭉝。߱́𞹻; ‌𭉝.߱́غ; [B1, C1, V5]; xn--0ugy003y.xn--lsa46nuub; ; xn--634m.xn--lsa46nuub; [B1, V5] # 𭉝.߱́غ
+‌𭉝。߱́غ; ‌𭉝.߱́غ; [B1, C1, V5]; xn--0ugy003y.xn--lsa46nuub; ; xn--634m.xn--lsa46nuub; [B1, V5] # 𭉝.߱́غ
+xn--634m.xn--lsa46nuub; 𭉝.߱́غ; [B1, V5]; xn--634m.xn--lsa46nuub; ; ; # 𭉝.߱́غ
+xn--0ugy003y.xn--lsa46nuub; ‌𭉝.߱́غ; [B1, C1, V5]; xn--0ugy003y.xn--lsa46nuub; ; ; # 𭉝.߱́غ
+𞼌‌𑈶。𐹡; 𞼌‌𑈶.𐹡; [B1, B3, C1, P1, V6]; xn--0ug7946gzpxf.xn--8n0d; ; xn--9g1d1288a.xn--8n0d; [B1, P1, V6] # 𑈶.𐹡
+xn--9g1d1288a.xn--8n0d; 𞼌𑈶.𐹡; [B1, V6]; xn--9g1d1288a.xn--8n0d; ; ; # 𑈶.𐹡
+xn--0ug7946gzpxf.xn--8n0d; 𞼌‌𑈶.𐹡; [B1, B3, C1, V6]; xn--0ug7946gzpxf.xn--8n0d; ; ; # 𑈶.𐹡
+󠅯򇽭‌🜭。𑖿᪻ς≠; 򇽭‌🜭.𑖿᪻ς≠; [C1, P1, V5, V6]; xn--0ug3766p5nm1b.xn--3xa578i1mfjw7y; ; xn--zb9h5968x.xn--4xa378i1mfjw7y; [P1, V5, V6] # 🜭.𑖿᪻ς≠
+󠅯򇽭‌🜭。𑖿᪻ς≠; 򇽭‌🜭.𑖿᪻ς≠; [C1, P1, V5, V6]; xn--0ug3766p5nm1b.xn--3xa578i1mfjw7y; ; xn--zb9h5968x.xn--4xa378i1mfjw7y; [P1, V5, V6] # 🜭.𑖿᪻ς≠
+󠅯򇽭‌🜭。𑖿᪻ς≠; 򇽭‌🜭.𑖿᪻ς≠; [C1, P1, V5, V6]; xn--0ug3766p5nm1b.xn--3xa578i1mfjw7y; ; xn--zb9h5968x.xn--4xa378i1mfjw7y; [P1, V5, V6] # 🜭.𑖿᪻ς≠
+󠅯򇽭‌🜭。𑖿᪻ς≠; 򇽭‌🜭.𑖿᪻ς≠; [C1, P1, V5, V6]; xn--0ug3766p5nm1b.xn--3xa578i1mfjw7y; ; xn--zb9h5968x.xn--4xa378i1mfjw7y; [P1, V5, V6] # 🜭.𑖿᪻ς≠
+󠅯򇽭‌🜭。𑖿᪻Σ≠; 򇽭‌🜭.𑖿᪻σ≠; [C1, P1, V5, V6]; xn--0ug3766p5nm1b.xn--4xa378i1mfjw7y; ; xn--zb9h5968x.xn--4xa378i1mfjw7y; [P1, V5, V6] # 🜭.𑖿᪻σ≠
+󠅯򇽭‌🜭。𑖿᪻Σ≠; 򇽭‌🜭.𑖿᪻σ≠; [C1, P1, V5, V6]; xn--0ug3766p5nm1b.xn--4xa378i1mfjw7y; ; xn--zb9h5968x.xn--4xa378i1mfjw7y; [P1, V5, V6] # 🜭.𑖿᪻σ≠
+󠅯򇽭‌🜭。𑖿᪻σ≠; 򇽭‌🜭.𑖿᪻σ≠; [C1, P1, V5, V6]; xn--0ug3766p5nm1b.xn--4xa378i1mfjw7y; ; xn--zb9h5968x.xn--4xa378i1mfjw7y; [P1, V5, V6] # 🜭.𑖿᪻σ≠
+󠅯򇽭‌🜭。𑖿᪻σ≠; 򇽭‌🜭.𑖿᪻σ≠; [C1, P1, V5, V6]; xn--0ug3766p5nm1b.xn--4xa378i1mfjw7y; ; xn--zb9h5968x.xn--4xa378i1mfjw7y; [P1, V5, V6] # 🜭.𑖿᪻σ≠
+xn--zb9h5968x.xn--4xa378i1mfjw7y; 򇽭🜭.𑖿᪻σ≠; [V5, V6]; xn--zb9h5968x.xn--4xa378i1mfjw7y; ; ; # 🜭.𑖿᪻σ≠
+xn--0ug3766p5nm1b.xn--4xa378i1mfjw7y; 򇽭‌🜭.𑖿᪻σ≠; [C1, V5, V6]; xn--0ug3766p5nm1b.xn--4xa378i1mfjw7y; ; ; # 🜭.𑖿᪻σ≠
+xn--0ug3766p5nm1b.xn--3xa578i1mfjw7y; 򇽭‌🜭.𑖿᪻ς≠; [C1, V5, V6]; xn--0ug3766p5nm1b.xn--3xa578i1mfjw7y; ; ; # 🜭.𑖿᪻ς≠
+󠅯򇽭‌🜭。𑖿᪻Σ≠; 򇽭‌🜭.𑖿᪻σ≠; [C1, P1, V5, V6]; xn--0ug3766p5nm1b.xn--4xa378i1mfjw7y; ; xn--zb9h5968x.xn--4xa378i1mfjw7y; [P1, V5, V6] # 🜭.𑖿᪻σ≠
+󠅯򇽭‌🜭。𑖿᪻Σ≠; 򇽭‌🜭.𑖿᪻σ≠; [C1, P1, V5, V6]; xn--0ug3766p5nm1b.xn--4xa378i1mfjw7y; ; xn--zb9h5968x.xn--4xa378i1mfjw7y; [P1, V5, V6] # 🜭.𑖿᪻σ≠
+󠅯򇽭‌🜭。𑖿᪻σ≠; 򇽭‌🜭.𑖿᪻σ≠; [C1, P1, V5, V6]; xn--0ug3766p5nm1b.xn--4xa378i1mfjw7y; ; xn--zb9h5968x.xn--4xa378i1mfjw7y; [P1, V5, V6] # 🜭.𑖿᪻σ≠
+󠅯򇽭‌🜭。𑖿᪻σ≠; 򇽭‌🜭.𑖿᪻σ≠; [C1, P1, V5, V6]; xn--0ug3766p5nm1b.xn--4xa378i1mfjw7y; ; xn--zb9h5968x.xn--4xa378i1mfjw7y; [P1, V5, V6] # 🜭.𑖿᪻σ≠
+⒋。⒈‍򳴢; ⒋.⒈‍򳴢; [C2, P1, V6]; xn--wsh.xn--1ug58o74922a; ; xn--wsh.xn--tsh07994h; [P1, V6] # ⒋.⒈
+4.。1.‍򳴢; 4..1.‍򳴢; [C2, P1, V6, X4_2]; 4..1.xn--1ug64613i; [C2, P1, V6, A4_2]; 4..1.xn--sf51d; [P1, V6, A4_2] # 4..1.
+4..1.xn--sf51d; 4..1.򳴢; [V6, X4_2]; 4..1.xn--sf51d; [V6, A4_2]; ; # 4..1.
+4..1.xn--1ug64613i; 4..1.‍򳴢; [C2, V6, X4_2]; 4..1.xn--1ug64613i; [C2, V6, A4_2]; ; # 4..1.
+xn--wsh.xn--tsh07994h; ⒋.⒈򳴢; [V6]; xn--wsh.xn--tsh07994h; ; ; # ⒋.⒈
+xn--wsh.xn--1ug58o74922a; ⒋.⒈‍򳴢; [C2, V6]; xn--wsh.xn--1ug58o74922a; ; ; # ⒋.⒈
+لß。᩠𐇽򾅢𞤾; لß.᩠𐇽򾅢𞤾; [B1, B2, B3, P1, V5, V6]; xn--zca57y.xn--jof2298hn83fln78f; ; xn--ss-svd.xn--jof2298hn83fln78f; # لß.᩠𐇽𞤾
+لß。᩠𐇽򾅢𞤾; لß.᩠𐇽򾅢𞤾; [B1, B2, B3, P1, V5, V6]; xn--zca57y.xn--jof2298hn83fln78f; ; xn--ss-svd.xn--jof2298hn83fln78f; # لß.᩠𐇽𞤾
+لß。᩠𐇽򾅢𞤾; لß.᩠𐇽򾅢𞤾; [B1, B2, B3, P1, V5, V6]; xn--zca57y.xn--jof2298hn83fln78f; ; xn--ss-svd.xn--jof2298hn83fln78f; # لß.᩠𐇽𞤾
+لSS。᩠𐇽򾅢𞤜; لss.᩠𐇽򾅢𞤾; [B1, B2, B3, P1, V5, V6]; xn--ss-svd.xn--jof2298hn83fln78f; ; ; # لss.᩠𐇽𞤾
+لss。᩠𐇽򾅢𞤾; لss.᩠𐇽򾅢𞤾; [B1, B2, B3, P1, V5, V6]; xn--ss-svd.xn--jof2298hn83fln78f; ; ; # لss.᩠𐇽𞤾
+لss。᩠𐇽򾅢𞤜; لss.᩠𐇽򾅢𞤾; [B1, B2, B3, P1, V5, V6]; xn--ss-svd.xn--jof2298hn83fln78f; ; ; # لss.᩠𐇽𞤾
+xn--ss-svd.xn--jof2298hn83fln78f; لss.᩠𐇽򾅢𞤾; [B1, B2, B3, V5, V6]; xn--ss-svd.xn--jof2298hn83fln78f; ; ; # لss.᩠𐇽𞤾
+لß。᩠𐇽򾅢𞤜; لß.᩠𐇽򾅢𞤾; [B1, B2, B3, P1, V5, V6]; xn--zca57y.xn--jof2298hn83fln78f; ; xn--ss-svd.xn--jof2298hn83fln78f; # لß.᩠𐇽𞤾
+xn--zca57y.xn--jof2298hn83fln78f; لß.᩠𐇽򾅢𞤾; [B1, B2, B3, V5, V6]; xn--zca57y.xn--jof2298hn83fln78f; ; ; # لß.᩠𐇽𞤾
+لSS。᩠𐇽򾅢𞤜; لss.᩠𐇽򾅢𞤾; [B1, B2, B3, P1, V5, V6]; xn--ss-svd.xn--jof2298hn83fln78f; ; ; # لss.᩠𐇽𞤾
+لss。᩠𐇽򾅢𞤾; لss.᩠𐇽򾅢𞤾; [B1, B2, B3, P1, V5, V6]; xn--ss-svd.xn--jof2298hn83fln78f; ; ; # لss.᩠𐇽𞤾
+لss。᩠𐇽򾅢𞤜; لss.᩠𐇽򾅢𞤾; [B1, B2, B3, P1, V5, V6]; xn--ss-svd.xn--jof2298hn83fln78f; ; ; # لss.᩠𐇽𞤾
+لß。᩠𐇽򾅢𞤜; لß.᩠𐇽򾅢𞤾; [B1, B2, B3, P1, V5, V6]; xn--zca57y.xn--jof2298hn83fln78f; ; xn--ss-svd.xn--jof2298hn83fln78f; # لß.᩠𐇽𞤾
+لSS。᩠𐇽򾅢𞤜; لss.᩠𐇽򾅢𞤾; [B1, B2, B3, P1, V5, V6]; xn--ss-svd.xn--jof2298hn83fln78f; ; ; # لss.᩠𐇽𞤾
+لss。᩠𐇽򾅢𞤾; لss.᩠𐇽򾅢𞤾; [B1, B2, B3, P1, V5, V6]; xn--ss-svd.xn--jof2298hn83fln78f; ; ; # لss.᩠𐇽𞤾
+لss。᩠𐇽򾅢𞤜; لss.᩠𐇽򾅢𞤾; [B1, B2, B3, P1, V5, V6]; xn--ss-svd.xn--jof2298hn83fln78f; ; ; # لss.᩠𐇽𞤾
+لß。᩠𐇽򾅢𞤜; لß.᩠𐇽򾅢𞤾; [B1, B2, B3, P1, V5, V6]; xn--zca57y.xn--jof2298hn83fln78f; ; xn--ss-svd.xn--jof2298hn83fln78f; # لß.᩠𐇽𞤾
+لSS。᩠𐇽򾅢𞤾; لss.᩠𐇽򾅢𞤾; [B1, B2, B3, P1, V5, V6]; xn--ss-svd.xn--jof2298hn83fln78f; ; ; # لss.᩠𐇽𞤾
+لSs。᩠𐇽򾅢𞤾; لss.᩠𐇽򾅢𞤾; [B1, B2, B3, P1, V5, V6]; xn--ss-svd.xn--jof2298hn83fln78f; ; ; # لss.᩠𐇽𞤾
+لSS。᩠𐇽򾅢𞤾; لss.᩠𐇽򾅢𞤾; [B1, B2, B3, P1, V5, V6]; xn--ss-svd.xn--jof2298hn83fln78f; ; ; # لss.᩠𐇽𞤾
+لSs。᩠𐇽򾅢𞤾; لss.᩠𐇽򾅢𞤾; [B1, B2, B3, P1, V5, V6]; xn--ss-svd.xn--jof2298hn83fln78f; ; ; # لss.᩠𐇽𞤾
+لSS。᩠𐇽򾅢𞤾; لss.᩠𐇽򾅢𞤾; [B1, B2, B3, P1, V5, V6]; xn--ss-svd.xn--jof2298hn83fln78f; ; ; # لss.᩠𐇽𞤾
+لSs。᩠𐇽򾅢𞤾; لss.᩠𐇽򾅢𞤾; [B1, B2, B3, P1, V5, V6]; xn--ss-svd.xn--jof2298hn83fln78f; ; ; # لss.᩠𐇽𞤾
+𐹽𑄳񼜲.ᷟី꠆𑜫; ; [B1, B3, B6, P1, V5, V6]; xn--1o0di0c0652w.xn--33e362arr1l153d; ; ; # 𐹽𑄳.ᷟី꠆𑜫
+xn--1o0di0c0652w.xn--33e362arr1l153d; 𐹽𑄳񼜲.ᷟី꠆𑜫; [B1, B3, B6, V5, V6]; xn--1o0di0c0652w.xn--33e362arr1l153d; ; ; # 𐹽𑄳.ᷟី꠆𑜫
+Ⴓ𑜫‍򗭓.ڧ𑰶; Ⴓ𑜫‍򗭓.ڧ𑰶; [P1, V6]; xn--rnd479ep20q7x12e.xn--9jb4223l; ; xn--rnd8945ky009c.xn--9jb4223l; # Ⴓ𑜫.ڧ𑰶
+Ⴓ𑜫‍򗭓.ڧ𑰶; ; [P1, V6]; xn--rnd479ep20q7x12e.xn--9jb4223l; ; xn--rnd8945ky009c.xn--9jb4223l; # Ⴓ𑜫.ڧ𑰶
+ⴓ𑜫‍򗭓.ڧ𑰶; ; [P1, V6]; xn--1ugy52cym7p7xu5e.xn--9jb4223l; ; xn--blj6306ey091d.xn--9jb4223l; # ⴓ𑜫.ڧ𑰶
+xn--blj6306ey091d.xn--9jb4223l; ⴓ𑜫򗭓.ڧ𑰶; [V6]; xn--blj6306ey091d.xn--9jb4223l; ; ; # ⴓ𑜫.ڧ𑰶
+xn--1ugy52cym7p7xu5e.xn--9jb4223l; ⴓ𑜫‍򗭓.ڧ𑰶; [V6]; xn--1ugy52cym7p7xu5e.xn--9jb4223l; ; ; # ⴓ𑜫.ڧ𑰶
+xn--rnd8945ky009c.xn--9jb4223l; Ⴓ𑜫򗭓.ڧ𑰶; [V6]; xn--rnd8945ky009c.xn--9jb4223l; ; ; # Ⴓ𑜫.ڧ𑰶
+xn--rnd479ep20q7x12e.xn--9jb4223l; Ⴓ𑜫‍򗭓.ڧ𑰶; [V6]; xn--rnd479ep20q7x12e.xn--9jb4223l; ; ; # Ⴓ𑜫.ڧ𑰶
+ⴓ𑜫‍򗭓.ڧ𑰶; ⴓ𑜫‍򗭓.ڧ𑰶; [P1, V6]; xn--1ugy52cym7p7xu5e.xn--9jb4223l; ; xn--blj6306ey091d.xn--9jb4223l; # ⴓ𑜫.ڧ𑰶
+𐨿.🄆—; ; [P1, V5, V6]; xn--0s9c.xn--8ug8324p; ; ; # 𐨿.🄆—
+𐨿.5,—; ; [P1, V5, V6]; xn--0s9c.xn--5,-81t; ; ; # 𐨿.5,—
+xn--0s9c.xn--5,-81t; 𐨿.5,—; [P1, V5, V6]; xn--0s9c.xn--5,-81t; ; ; # 𐨿.5,—
+xn--0s9c.xn--8ug8324p; 𐨿.🄆—; [V5, V6]; xn--0s9c.xn--8ug8324p; ; ; # 𐨿.🄆—
+򔊱񁦮۸。󠾭-; 򔊱񁦮۸.󠾭-; [P1, V3, V6]; xn--lmb18944c0g2z.xn----2k81m; ; ; # ۸.-
+xn--lmb18944c0g2z.xn----2k81m; 򔊱񁦮۸.󠾭-; [V3, V6]; xn--lmb18944c0g2z.xn----2k81m; ; ; # ۸.-
+𼗸ߍ𐹮。۝ᡎᠴ; 𼗸ߍ𐹮.۝ᡎᠴ; [B1, B5, B6, P1, V6]; xn--osb0855kcc2r.xn--tlb299fhc; ; ; # ߍ𐹮.ᡎᠴ
+xn--osb0855kcc2r.xn--tlb299fhc; 𼗸ߍ𐹮.۝ᡎᠴ; [B1, B5, B6, V6]; xn--osb0855kcc2r.xn--tlb299fhc; ; ; # ߍ𐹮.ᡎᠴ
+‍ᠮႾ🄂.🚗ࡁ𮹌‌; ; [B1, C1, C2, P1, V6]; xn--2nd129ay2gnw71c.xn--zvb692j9664aic1g; ; xn--2nd129ai554b.xn--zvb3124wpkpf; [B1, P1, V6] # ᠮႾ🄂.🚗ࡁ
+‍ᠮႾ1,.🚗ࡁ𮹌‌; ; [B1, C1, C2, P1, V6]; xn--1,-ogkx89c39j.xn--zvb692j9664aic1g; ; xn--1,-ogkx89c.xn--zvb3124wpkpf; [B1, B6, P1, V6] # ᠮႾ1,.🚗ࡁ
+‍ᠮⴞ1,.🚗ࡁ𮹌‌; ; [B1, C1, C2, P1, V6]; xn--1,-v3o161c53q.xn--zvb692j9664aic1g; ; xn--1,-v3o625k.xn--zvb3124wpkpf; [B1, B6, P1, V6] # ᠮⴞ1,.🚗ࡁ
+xn--1,-v3o625k.xn--zvb3124wpkpf; ᠮⴞ1,.🚗ࡁ𮹌; [B1, B6, P1, V6]; xn--1,-v3o625k.xn--zvb3124wpkpf; ; ; # ᠮⴞ1,.🚗ࡁ
+xn--1,-v3o161c53q.xn--zvb692j9664aic1g; ‍ᠮⴞ1,.🚗ࡁ𮹌‌; [B1, C1, C2, P1, V6]; xn--1,-v3o161c53q.xn--zvb692j9664aic1g; ; ; # ᠮⴞ1,.🚗ࡁ
+xn--1,-ogkx89c.xn--zvb3124wpkpf; ᠮႾ1,.🚗ࡁ𮹌; [B1, B6, P1, V6]; xn--1,-ogkx89c.xn--zvb3124wpkpf; ; ; # ᠮႾ1,.🚗ࡁ
+xn--1,-ogkx89c39j.xn--zvb692j9664aic1g; ‍ᠮႾ1,.🚗ࡁ𮹌‌; [B1, C1, C2, P1, V6]; xn--1,-ogkx89c39j.xn--zvb692j9664aic1g; ; ; # ᠮႾ1,.🚗ࡁ
+‍ᠮⴞ🄂.🚗ࡁ𮹌‌; ; [B1, C1, C2, P1, V6]; xn--h7e341b0wlbv45b.xn--zvb692j9664aic1g; ; xn--h7e438h1p44a.xn--zvb3124wpkpf; [B1, P1, V6] # ᠮⴞ🄂.🚗ࡁ
+xn--h7e438h1p44a.xn--zvb3124wpkpf; ᠮⴞ🄂.🚗ࡁ𮹌; [B1, V6]; xn--h7e438h1p44a.xn--zvb3124wpkpf; ; ; # ᠮⴞ🄂.🚗ࡁ
+xn--h7e341b0wlbv45b.xn--zvb692j9664aic1g; ‍ᠮⴞ🄂.🚗ࡁ𮹌‌; [B1, C1, C2, V6]; xn--h7e341b0wlbv45b.xn--zvb692j9664aic1g; ; ; # ᠮⴞ🄂.🚗ࡁ
+xn--2nd129ai554b.xn--zvb3124wpkpf; ᠮႾ🄂.🚗ࡁ𮹌; [B1, V6]; xn--2nd129ai554b.xn--zvb3124wpkpf; ; ; # ᠮႾ🄂.🚗ࡁ
+xn--2nd129ay2gnw71c.xn--zvb692j9664aic1g; ‍ᠮႾ🄂.🚗ࡁ𮹌‌; [B1, C1, C2, V6]; xn--2nd129ay2gnw71c.xn--zvb692j9664aic1g; ; ; # ᠮႾ🄂.🚗ࡁ
+؁ڗ.𑚶񼡷⾆; ؁ڗ.𑚶񼡷舌; [B1, P1, V5, V6]; xn--jfb41a.xn--tc1ap851axo39c; ; ; # ڗ.𑚶舌
+؁ڗ.𑚶񼡷舌; ; [B1, P1, V5, V6]; xn--jfb41a.xn--tc1ap851axo39c; ; ; # ڗ.𑚶舌
+xn--jfb41a.xn--tc1ap851axo39c; ؁ڗ.𑚶񼡷舌; [B1, V5, V6]; xn--jfb41a.xn--tc1ap851axo39c; ; ; # ڗ.𑚶舌
+🞅󠳡󜍙.񲖷; ; [P1, V6]; xn--ie9hi1349bqdlb.xn--oj69a; ; ; # 🞅.
+xn--ie9hi1349bqdlb.xn--oj69a; 🞅󠳡󜍙.񲖷; [V6]; xn--ie9hi1349bqdlb.xn--oj69a; ; ; # 🞅.
+⃧񯡎-򫣝.4Ⴄ‌; ; [C1, P1, V5, V6]; xn----9snu5320fi76w.xn--4-f0g649i; ; xn----9snu5320fi76w.xn--4-f0g; [P1, V5, V6] # ⃧-.4Ⴄ
+⃧񯡎-򫣝.4ⴄ‌; ; [C1, P1, V5, V6]; xn----9snu5320fi76w.xn--4-sgn589c; ; xn----9snu5320fi76w.xn--4-ivs; [P1, V5, V6] # ⃧-.4ⴄ
+xn----9snu5320fi76w.xn--4-ivs; ⃧񯡎-򫣝.4ⴄ; [V5, V6]; xn----9snu5320fi76w.xn--4-ivs; ; ; # ⃧-.4ⴄ
+xn----9snu5320fi76w.xn--4-sgn589c; ⃧񯡎-򫣝.4ⴄ‌; [C1, V5, V6]; xn----9snu5320fi76w.xn--4-sgn589c; ; ; # ⃧-.4ⴄ
+xn----9snu5320fi76w.xn--4-f0g; ⃧񯡎-򫣝.4Ⴄ; [V5, V6]; xn----9snu5320fi76w.xn--4-f0g; ; ; # ⃧-.4Ⴄ
+xn----9snu5320fi76w.xn--4-f0g649i; ⃧񯡎-򫣝.4Ⴄ‌; [C1, V5, V6]; xn----9snu5320fi76w.xn--4-f0g649i; ; ; # ⃧-.4Ⴄ
+ᚭ。𝌠ß𖫱; ᚭ.𝌠ß𖫱; ; xn--hwe.xn--zca4946pblnc; ; xn--hwe.xn--ss-ci1ub261a; # ᚭ.𝌠ß𖫱
+ᚭ。𝌠ß𖫱; ᚭ.𝌠ß𖫱; ; xn--hwe.xn--zca4946pblnc; ; xn--hwe.xn--ss-ci1ub261a; # ᚭ.𝌠ß𖫱
+ᚭ。𝌠SS𖫱; ᚭ.𝌠ss𖫱; ; xn--hwe.xn--ss-ci1ub261a; ; ; # ᚭ.𝌠ss𖫱
+ᚭ。𝌠ss𖫱; ᚭ.𝌠ss𖫱; ; xn--hwe.xn--ss-ci1ub261a; ; ; # ᚭ.𝌠ss𖫱
+ᚭ。𝌠Ss𖫱; ᚭ.𝌠ss𖫱; ; xn--hwe.xn--ss-ci1ub261a; ; ; # ᚭ.𝌠ss𖫱
+xn--hwe.xn--ss-ci1ub261a; ᚭ.𝌠ss𖫱; ; xn--hwe.xn--ss-ci1ub261a; ; ; # ᚭ.𝌠ss𖫱
+ᚭ.𝌠ss𖫱; ; ; xn--hwe.xn--ss-ci1ub261a; ; ; # ᚭ.𝌠ss𖫱
+ᚭ.𝌠SS𖫱; ᚭ.𝌠ss𖫱; ; xn--hwe.xn--ss-ci1ub261a; ; ; # ᚭ.𝌠ss𖫱
+ᚭ.𝌠Ss𖫱; ᚭ.𝌠ss𖫱; ; xn--hwe.xn--ss-ci1ub261a; ; ; # ᚭ.𝌠ss𖫱
+xn--hwe.xn--zca4946pblnc; ᚭ.𝌠ß𖫱; ; xn--hwe.xn--zca4946pblnc; ; ; # ᚭ.𝌠ß𖫱
+ᚭ.𝌠ß𖫱; ; ; xn--hwe.xn--zca4946pblnc; ; xn--hwe.xn--ss-ci1ub261a; # ᚭ.𝌠ß𖫱
+ᚭ。𝌠SS𖫱; ᚭ.𝌠ss𖫱; ; xn--hwe.xn--ss-ci1ub261a; ; ; # ᚭ.𝌠ss𖫱
+ᚭ。𝌠ss𖫱; ᚭ.𝌠ss𖫱; ; xn--hwe.xn--ss-ci1ub261a; ; ; # ᚭ.𝌠ss𖫱
+ᚭ。𝌠Ss𖫱; ᚭ.𝌠ss𖫱; ; xn--hwe.xn--ss-ci1ub261a; ; ; # ᚭ.𝌠ss𖫱
+₁。𞤫ꡪ; 1.𞤫ꡪ; [B1, B2, B3]; 1.xn--gd9al691d; ; ; # 1.𞤫ꡪ
+1。𞤫ꡪ; 1.𞤫ꡪ; [B1, B2, B3]; 1.xn--gd9al691d; ; ; # 1.𞤫ꡪ
+1。𞤉ꡪ; 1.𞤫ꡪ; [B1, B2, B3]; 1.xn--gd9al691d; ; ; # 1.𞤫ꡪ
+1.xn--gd9al691d; 1.𞤫ꡪ; [B1, B2, B3]; 1.xn--gd9al691d; ; ; # 1.𞤫ꡪ
+₁。𞤉ꡪ; 1.𞤫ꡪ; [B1, B2, B3]; 1.xn--gd9al691d; ; ; # 1.𞤫ꡪ
+𯻼‌.𞶞򻙤񥘇; ; [B2, B3, B6, C1, P1, V6]; xn--0ug27500a.xn--2b7hs861pl540a; ; xn--kg4n.xn--2b7hs861pl540a; [B2, B3, P1, V6] # .
+xn--kg4n.xn--2b7hs861pl540a; 𯻼.𞶞򻙤񥘇; [B2, B3, V6]; xn--kg4n.xn--2b7hs861pl540a; ; ; # .
+xn--0ug27500a.xn--2b7hs861pl540a; 𯻼‌.𞶞򻙤񥘇; [B2, B3, B6, C1, V6]; xn--0ug27500a.xn--2b7hs861pl540a; ; ; # .
+𑑄≯。𑜤; 𑑄≯.𑜤; [P1, V5, V6]; xn--hdh5636g.xn--ci2d; ; ; # 𑑄≯.𑜤
+𑑄≯。𑜤; 𑑄≯.𑜤; [P1, V5, V6]; xn--hdh5636g.xn--ci2d; ; ; # 𑑄≯.𑜤
+𑑄≯。𑜤; 𑑄≯.𑜤; [P1, V5, V6]; xn--hdh5636g.xn--ci2d; ; ; # 𑑄≯.𑜤
+𑑄≯。𑜤; 𑑄≯.𑜤; [P1, V5, V6]; xn--hdh5636g.xn--ci2d; ; ; # 𑑄≯.𑜤
+xn--hdh5636g.xn--ci2d; 𑑄≯.𑜤; [V5, V6]; xn--hdh5636g.xn--ci2d; ; ; # 𑑄≯.𑜤
+Ⴋ≮𱲆。‍ާ𐋣; Ⴋ≮𱲆.‍ާ𐋣; [C2, P1, V6]; xn--jnd802gsm17c.xn--lrb506jqr4n; ; xn--jnd802gsm17c.xn--lrb6479j; [P1, V5, V6] # Ⴋ≮.ާ𐋣
+Ⴋ≮𱲆。‍ާ𐋣; Ⴋ≮𱲆.‍ާ𐋣; [C2, P1, V6]; xn--jnd802gsm17c.xn--lrb506jqr4n; ; xn--jnd802gsm17c.xn--lrb6479j; [P1, V5, V6] # Ⴋ≮.ާ𐋣
+ⴋ≮𱲆。‍ާ𐋣; ⴋ≮𱲆.‍ާ𐋣; [C2, P1, V6]; xn--gdhz03bxt42d.xn--lrb506jqr4n; ; xn--gdhz03bxt42d.xn--lrb6479j; [P1, V5, V6] # ⴋ≮.ާ𐋣
+ⴋ≮𱲆。‍ާ𐋣; ⴋ≮𱲆.‍ާ𐋣; [C2, P1, V6]; xn--gdhz03bxt42d.xn--lrb506jqr4n; ; xn--gdhz03bxt42d.xn--lrb6479j; [P1, V5, V6] # ⴋ≮.ާ𐋣
+xn--gdhz03bxt42d.xn--lrb6479j; ⴋ≮𱲆.ާ𐋣; [V5, V6]; xn--gdhz03bxt42d.xn--lrb6479j; ; ; # ⴋ≮.ާ𐋣
+xn--gdhz03bxt42d.xn--lrb506jqr4n; ⴋ≮𱲆.‍ާ𐋣; [C2, V6]; xn--gdhz03bxt42d.xn--lrb506jqr4n; ; ; # ⴋ≮.ާ𐋣
+xn--jnd802gsm17c.xn--lrb6479j; Ⴋ≮𱲆.ާ𐋣; [V5, V6]; xn--jnd802gsm17c.xn--lrb6479j; ; ; # Ⴋ≮.ާ𐋣
+xn--jnd802gsm17c.xn--lrb506jqr4n; Ⴋ≮𱲆.‍ާ𐋣; [C2, V6]; xn--jnd802gsm17c.xn--lrb506jqr4n; ; ; # Ⴋ≮.ާ𐋣
+្.򆽒≯; ; [P1, V5, V6]; xn--u4e.xn--hdhx0084f; ; ; # ្.≯
+្.򆽒≯; ្.򆽒≯; [P1, V5, V6]; xn--u4e.xn--hdhx0084f; ; ; # ្.≯
+xn--u4e.xn--hdhx0084f; ្.򆽒≯; [V5, V6]; xn--u4e.xn--hdhx0084f; ; ; # ្.≯
+񏁇᜴.𐨺É⬓𑄴; 񏁇᜴.𐨺é⬓𑄴; [P1, V5, V6]; xn--c0e34564d.xn--9ca207st53lg3f; ; ; # ᜴.𐨺é⬓𑄴
+񏁇᜴.𐨺É⬓𑄴; 񏁇᜴.𐨺é⬓𑄴; [P1, V5, V6]; xn--c0e34564d.xn--9ca207st53lg3f; ; ; # ᜴.𐨺é⬓𑄴
+񏁇᜴.𐨺É⬓𑄴; 񏁇᜴.𐨺é⬓𑄴; [P1, V5, V6]; xn--c0e34564d.xn--9ca207st53lg3f; ; ; # ᜴.𐨺é⬓𑄴
+񏁇᜴.𐨺É⬓𑄴; 񏁇᜴.𐨺é⬓𑄴; [P1, V5, V6]; xn--c0e34564d.xn--9ca207st53lg3f; ; ; # ᜴.𐨺é⬓𑄴
+񏁇᜴.𐨺é⬓𑄴; 񏁇᜴.𐨺é⬓𑄴; [P1, V5, V6]; xn--c0e34564d.xn--9ca207st53lg3f; ; ; # ᜴.𐨺é⬓𑄴
+񏁇᜴.𐨺é⬓𑄴; ; [P1, V5, V6]; xn--c0e34564d.xn--9ca207st53lg3f; ; ; # ᜴.𐨺é⬓𑄴
+xn--c0e34564d.xn--9ca207st53lg3f; 񏁇᜴.𐨺é⬓𑄴; [V5, V6]; xn--c0e34564d.xn--9ca207st53lg3f; ; ; # ᜴.𐨺é⬓𑄴
+񏁇᜴.𐨺é⬓𑄴; 񏁇᜴.𐨺é⬓𑄴; [P1, V5, V6]; xn--c0e34564d.xn--9ca207st53lg3f; ; ; # ᜴.𐨺é⬓𑄴
+񏁇᜴.𐨺é⬓𑄴; 񏁇᜴.𐨺é⬓𑄴; [P1, V5, V6]; xn--c0e34564d.xn--9ca207st53lg3f; ; ; # ᜴.𐨺é⬓𑄴
+ᢇ‍꣄。︒𞤺; ᢇ‍꣄.︒𞤺; [B1, B6, C2, P1, V6]; xn--09e669a6x8j.xn--y86cv562b; ; xn--09e4694e.xn--y86cv562b; [B1, P1, V6] # ᢇ꣄.︒𞤺
+ᢇ‍꣄。。𞤺; ᢇ‍꣄..𞤺; [B6, C2, X4_2]; xn--09e669a6x8j..xn--ye6h; [B6, C2, A4_2]; xn--09e4694e..xn--ye6h; [A4_2] # ᢇ꣄..𞤺
+ᢇ‍꣄。。𞤘; ᢇ‍꣄..𞤺; [B6, C2, X4_2]; xn--09e669a6x8j..xn--ye6h; [B6, C2, A4_2]; xn--09e4694e..xn--ye6h; [A4_2] # ᢇ꣄..𞤺
+xn--09e4694e..xn--ye6h; ᢇ꣄..𞤺; [X4_2]; xn--09e4694e..xn--ye6h; [A4_2]; ; # ᢇ꣄..𞤺
+xn--09e669a6x8j..xn--ye6h; ᢇ‍꣄..𞤺; [B6, C2, X4_2]; xn--09e669a6x8j..xn--ye6h; [B6, C2, A4_2]; ; # ᢇ꣄..𞤺
+ᢇ‍꣄。︒𞤘; ᢇ‍꣄.︒𞤺; [B1, B6, C2, P1, V6]; xn--09e669a6x8j.xn--y86cv562b; ; xn--09e4694e.xn--y86cv562b; [B1, P1, V6] # ᢇ꣄.︒𞤺
+xn--09e4694e.xn--y86cv562b; ᢇ꣄.︒𞤺; [B1, V6]; xn--09e4694e.xn--y86cv562b; ; ; # ᢇ꣄.︒𞤺
+xn--09e669a6x8j.xn--y86cv562b; ᢇ‍꣄.︒𞤺; [B1, B6, C2, V6]; xn--09e669a6x8j.xn--y86cv562b; ; ; # ᢇ꣄.︒𞤺
+𞩬򖙱᜔‌。رު≮; 𞩬򖙱᜔‌.رު≮; [B2, B3, P1, V6]; xn--fze607b9651bjwl7c.xn--wgb86el10d; ; xn--fze3930v7hz6b.xn--wgb86el10d; # ᜔.رު≮
+𞩬򖙱᜔‌。رު≮; 𞩬򖙱᜔‌.رު≮; [B2, B3, P1, V6]; xn--fze607b9651bjwl7c.xn--wgb86el10d; ; xn--fze3930v7hz6b.xn--wgb86el10d; # ᜔.رު≮
+𞩬򖙱᜔‌。رު≮; 𞩬򖙱᜔‌.رު≮; [B2, B3, P1, V6]; xn--fze607b9651bjwl7c.xn--wgb86el10d; ; xn--fze3930v7hz6b.xn--wgb86el10d; # ᜔.رު≮
+𞩬򖙱᜔‌。رު≮; 𞩬򖙱᜔‌.رު≮; [B2, B3, P1, V6]; xn--fze607b9651bjwl7c.xn--wgb86el10d; ; xn--fze3930v7hz6b.xn--wgb86el10d; # ᜔.رު≮
+xn--fze3930v7hz6b.xn--wgb86el10d; 𞩬򖙱᜔.رު≮; [B2, B3, V6]; xn--fze3930v7hz6b.xn--wgb86el10d; ; ; # ᜔.رު≮
+xn--fze607b9651bjwl7c.xn--wgb86el10d; 𞩬򖙱᜔‌.رު≮; [B2, B3, V6]; xn--fze607b9651bjwl7c.xn--wgb86el10d; ; ; # ᜔.رު≮
+Ⴣ.ٓᢤ; Ⴣ.ٓᢤ; [P1, V5, V6]; xn--7nd.xn--vhb294g; ; ; # Ⴣ.ٓᢤ
+Ⴣ.ٓᢤ; ; [P1, V5, V6]; xn--7nd.xn--vhb294g; ; ; # Ⴣ.ٓᢤ
+ⴣ.ٓᢤ; ; [V5]; xn--rlj.xn--vhb294g; ; ; # ⴣ.ٓᢤ
+xn--rlj.xn--vhb294g; ⴣ.ٓᢤ; [V5]; xn--rlj.xn--vhb294g; ; ; # ⴣ.ٓᢤ
+xn--7nd.xn--vhb294g; Ⴣ.ٓᢤ; [V5, V6]; xn--7nd.xn--vhb294g; ; ; # Ⴣ.ٓᢤ
+ⴣ.ٓᢤ; ⴣ.ٓᢤ; [V5]; xn--rlj.xn--vhb294g; ; ; # ⴣ.ٓᢤ
+󠄈ࠓ.싉򄆻Ⴤ򂡐; ࠓ.싉򄆻Ⴤ򂡐; [P1, V6]; xn--oub.xn--8nd9522gpe69cviva; ; ; # ࠓ.싉Ⴤ
+󠄈ࠓ.싉򄆻Ⴤ򂡐; ࠓ.싉򄆻Ⴤ򂡐; [P1, V6]; xn--oub.xn--8nd9522gpe69cviva; ; ; # ࠓ.싉Ⴤ
+󠄈ࠓ.싉򄆻Ⴤ򂡐; ࠓ.싉򄆻Ⴤ򂡐; [P1, V6]; xn--oub.xn--8nd9522gpe69cviva; ; ; # ࠓ.싉Ⴤ
+󠄈ࠓ.싉򄆻Ⴤ򂡐; ࠓ.싉򄆻Ⴤ򂡐; [P1, V6]; xn--oub.xn--8nd9522gpe69cviva; ; ; # ࠓ.싉Ⴤ
+󠄈ࠓ.싉򄆻ⴤ򂡐; ࠓ.싉򄆻ⴤ򂡐; [P1, V6]; xn--oub.xn--sljz109bpe25dviva; ; ; # ࠓ.싉ⴤ
+󠄈ࠓ.싉򄆻ⴤ򂡐; ࠓ.싉򄆻ⴤ򂡐; [P1, V6]; xn--oub.xn--sljz109bpe25dviva; ; ; # ࠓ.싉ⴤ
+xn--oub.xn--sljz109bpe25dviva; ࠓ.싉򄆻ⴤ򂡐; [V6]; xn--oub.xn--sljz109bpe25dviva; ; ; # ࠓ.싉ⴤ
+xn--oub.xn--8nd9522gpe69cviva; ࠓ.싉򄆻Ⴤ򂡐; [V6]; xn--oub.xn--8nd9522gpe69cviva; ; ; # ࠓ.싉Ⴤ
+󠄈ࠓ.싉򄆻ⴤ򂡐; ࠓ.싉򄆻ⴤ򂡐; [P1, V6]; xn--oub.xn--sljz109bpe25dviva; ; ; # ࠓ.싉ⴤ
+󠄈ࠓ.싉򄆻ⴤ򂡐; ࠓ.싉򄆻ⴤ򂡐; [P1, V6]; xn--oub.xn--sljz109bpe25dviva; ; ; # ࠓ.싉ⴤ
+ꨬ𑲫≮.⤂; ꨬ𑲫≮.⤂; [P1, V5, V6]; xn--gdh1854cn19c.xn--kqi; ; ; # ꨬ𑲫≮.⤂
+ꨬ𑲫≮.⤂; ꨬ𑲫≮.⤂; [P1, V5, V6]; xn--gdh1854cn19c.xn--kqi; ; ; # ꨬ𑲫≮.⤂
+ꨬ𑲫≮.⤂; ; [P1, V5, V6]; xn--gdh1854cn19c.xn--kqi; ; ; # ꨬ𑲫≮.⤂
+ꨬ𑲫≮.⤂; ꨬ𑲫≮.⤂; [P1, V5, V6]; xn--gdh1854cn19c.xn--kqi; ; ; # ꨬ𑲫≮.⤂
+xn--gdh1854cn19c.xn--kqi; ꨬ𑲫≮.⤂; [V5, V6]; xn--gdh1854cn19c.xn--kqi; ; ; # ꨬ𑲫≮.⤂
+؄𐩔≮Ⴢ.Ⴃ; ؄𐩔≮Ⴢ.Ⴃ; [B1, P1, V6]; xn--mfb416c0jox02t.xn--bnd; ; ; # 𐩔≮Ⴢ.Ⴃ
+؄𐩔≮Ⴢ.Ⴃ; ؄𐩔≮Ⴢ.Ⴃ; [B1, P1, V6]; xn--mfb416c0jox02t.xn--bnd; ; ; # 𐩔≮Ⴢ.Ⴃ
+؄𐩔≮Ⴢ.Ⴃ; ; [B1, P1, V6]; xn--mfb416c0jox02t.xn--bnd; ; ; # 𐩔≮Ⴢ.Ⴃ
+؄𐩔≮Ⴢ.Ⴃ; ؄𐩔≮Ⴢ.Ⴃ; [B1, P1, V6]; xn--mfb416c0jox02t.xn--bnd; ; ; # 𐩔≮Ⴢ.Ⴃ
+؄𐩔≮ⴢ.ⴃ; ؄𐩔≮ⴢ.ⴃ; [B1, P1, V6]; xn--mfb266l4khr54u.xn--ukj; ; ; # 𐩔≮ⴢ.ⴃ
+؄𐩔≮ⴢ.ⴃ; ; [B1, P1, V6]; xn--mfb266l4khr54u.xn--ukj; ; ; # 𐩔≮ⴢ.ⴃ
+؄𐩔≮Ⴢ.ⴃ; ; [B1, P1, V6]; xn--mfb416c0jox02t.xn--ukj; ; ; # 𐩔≮Ⴢ.ⴃ
+؄𐩔≮Ⴢ.ⴃ; ؄𐩔≮Ⴢ.ⴃ; [B1, P1, V6]; xn--mfb416c0jox02t.xn--ukj; ; ; # 𐩔≮Ⴢ.ⴃ
+xn--mfb416c0jox02t.xn--ukj; ؄𐩔≮Ⴢ.ⴃ; [B1, V6]; xn--mfb416c0jox02t.xn--ukj; ; ; # 𐩔≮Ⴢ.ⴃ
+xn--mfb266l4khr54u.xn--ukj; ؄𐩔≮ⴢ.ⴃ; [B1, V6]; xn--mfb266l4khr54u.xn--ukj; ; ; # 𐩔≮ⴢ.ⴃ
+xn--mfb416c0jox02t.xn--bnd; ؄𐩔≮Ⴢ.Ⴃ; [B1, V6]; xn--mfb416c0jox02t.xn--bnd; ; ; # 𐩔≮Ⴢ.Ⴃ
+؄𐩔≮ⴢ.ⴃ; ؄𐩔≮ⴢ.ⴃ; [B1, P1, V6]; xn--mfb266l4khr54u.xn--ukj; ; ; # 𐩔≮ⴢ.ⴃ
+؄𐩔≮ⴢ.ⴃ; ؄𐩔≮ⴢ.ⴃ; [B1, P1, V6]; xn--mfb266l4khr54u.xn--ukj; ; ; # 𐩔≮ⴢ.ⴃ
+؄𐩔≮Ⴢ.ⴃ; ؄𐩔≮Ⴢ.ⴃ; [B1, P1, V6]; xn--mfb416c0jox02t.xn--ukj; ; ; # 𐩔≮Ⴢ.ⴃ
+؄𐩔≮Ⴢ.ⴃ; ؄𐩔≮Ⴢ.ⴃ; [B1, P1, V6]; xn--mfb416c0jox02t.xn--ukj; ; ; # 𐩔≮Ⴢ.ⴃ
+𑁅。-; 𑁅.-; [V3, V5]; xn--210d.-; ; ; # 𑁅.-
+xn--210d.-; 𑁅.-; [V3, V5]; xn--210d.-; ; ; # 𑁅.-
+්򕸽󠧱。饈≠٤; ්򕸽󠧱.饈≠٤; [B1, B5, B6, P1, V5, V6]; xn--h1c25913jfwov.xn--dib144ler5f; ; ; # ්.饈≠٤
+්򕸽󠧱。饈≠٤; ්򕸽󠧱.饈≠٤; [B1, B5, B6, P1, V5, V6]; xn--h1c25913jfwov.xn--dib144ler5f; ; ; # ්.饈≠٤
+්򕸽󠧱。饈≠٤; ්򕸽󠧱.饈≠٤; [B1, B5, B6, P1, V5, V6]; xn--h1c25913jfwov.xn--dib144ler5f; ; ; # ්.饈≠٤
+්򕸽󠧱。饈≠٤; ්򕸽󠧱.饈≠٤; [B1, B5, B6, P1, V5, V6]; xn--h1c25913jfwov.xn--dib144ler5f; ; ; # ්.饈≠٤
+xn--h1c25913jfwov.xn--dib144ler5f; ්򕸽󠧱.饈≠٤; [B1, B5, B6, V5, V6]; xn--h1c25913jfwov.xn--dib144ler5f; ; ; # ්.饈≠٤
+𞥃ᠠ⁷。≯邅⬻4; 𞥃ᠠ7.≯邅⬻4; [B1, B2, P1, V6]; xn--7-v4j2826w.xn--4-ogoy01bou3i; ; ; # 𞥃ᠠ7.≯邅⬻4
+𞥃ᠠ⁷。≯邅⬻4; 𞥃ᠠ7.≯邅⬻4; [B1, B2, P1, V6]; xn--7-v4j2826w.xn--4-ogoy01bou3i; ; ; # 𞥃ᠠ7.≯邅⬻4
+𞥃ᠠ7。≯邅⬻4; 𞥃ᠠ7.≯邅⬻4; [B1, B2, P1, V6]; xn--7-v4j2826w.xn--4-ogoy01bou3i; ; ; # 𞥃ᠠ7.≯邅⬻4
+𞥃ᠠ7。≯邅⬻4; 𞥃ᠠ7.≯邅⬻4; [B1, B2, P1, V6]; xn--7-v4j2826w.xn--4-ogoy01bou3i; ; ; # 𞥃ᠠ7.≯邅⬻4
+𞤡ᠠ7。≯邅⬻4; 𞥃ᠠ7.≯邅⬻4; [B1, B2, P1, V6]; xn--7-v4j2826w.xn--4-ogoy01bou3i; ; ; # 𞥃ᠠ7.≯邅⬻4
+𞤡ᠠ7。≯邅⬻4; 𞥃ᠠ7.≯邅⬻4; [B1, B2, P1, V6]; xn--7-v4j2826w.xn--4-ogoy01bou3i; ; ; # 𞥃ᠠ7.≯邅⬻4
+xn--7-v4j2826w.xn--4-ogoy01bou3i; 𞥃ᠠ7.≯邅⬻4; [B1, B2, V6]; xn--7-v4j2826w.xn--4-ogoy01bou3i; ; ; # 𞥃ᠠ7.≯邅⬻4
+𞤡ᠠ⁷。≯邅⬻4; 𞥃ᠠ7.≯邅⬻4; [B1, B2, P1, V6]; xn--7-v4j2826w.xn--4-ogoy01bou3i; ; ; # 𞥃ᠠ7.≯邅⬻4
+𞤡ᠠ⁷。≯邅⬻4; 𞥃ᠠ7.≯邅⬻4; [B1, B2, P1, V6]; xn--7-v4j2826w.xn--4-ogoy01bou3i; ; ; # 𞥃ᠠ7.≯邅⬻4
+򠿯ᡳ-𑐻.𐹴𐋫؅󑎳; ; [B1, B6, P1, V6]; xn----m9j3429kxmy7e.xn--nfb7950kdihrp812a; ; ; # ᡳ-𑐻.𐹴𐋫
+xn----m9j3429kxmy7e.xn--nfb7950kdihrp812a; 򠿯ᡳ-𑐻.𐹴𐋫؅󑎳; [B1, B6, V6]; xn----m9j3429kxmy7e.xn--nfb7950kdihrp812a; ; ; # ᡳ-𑐻.𐹴𐋫
+򠶆ࡅੑ.넨-󶧈; ; [B5, B6, P1, V6]; xn--3vb26hb6834b.xn----i37ez0957g; ; ; # ࡅੑ.넨-
+򠶆ࡅੑ.넨-󶧈; 򠶆ࡅੑ.넨-󶧈; [B5, B6, P1, V6]; xn--3vb26hb6834b.xn----i37ez0957g; ; ; # ࡅੑ.넨-
+xn--3vb26hb6834b.xn----i37ez0957g; 򠶆ࡅੑ.넨-󶧈; [B5, B6, V6]; xn--3vb26hb6834b.xn----i37ez0957g; ; ; # ࡅੑ.넨-
+ꡦᡑ‍⒈。𐋣-; ꡦᡑ‍⒈.𐋣-; [C2, P1, V3, V6]; xn--h8e470bl0d838o.xn----381i; ; xn--h8e863drj7h.xn----381i; [P1, V3, V6] # ꡦᡑ⒈.𐋣-
+ꡦᡑ‍1.。𐋣-; ꡦᡑ‍1..𐋣-; [C2, V3, X4_2]; xn--1-o7j663bdl7m..xn----381i; [C2, V3, A4_2]; xn--1-o7j0610f..xn----381i; [V3, A4_2] # ꡦᡑ1..𐋣-
+xn--1-o7j0610f..xn----381i; ꡦᡑ1..𐋣-; [V3, X4_2]; xn--1-o7j0610f..xn----381i; [V3, A4_2]; ; # ꡦᡑ1..𐋣-
+xn--1-o7j663bdl7m..xn----381i; ꡦᡑ‍1..𐋣-; [C2, V3, X4_2]; xn--1-o7j663bdl7m..xn----381i; [C2, V3, A4_2]; ; # ꡦᡑ1..𐋣-
+xn--h8e863drj7h.xn----381i; ꡦᡑ⒈.𐋣-; [V3, V6]; xn--h8e863drj7h.xn----381i; ; ; # ꡦᡑ⒈.𐋣-
+xn--h8e470bl0d838o.xn----381i; ꡦᡑ‍⒈.𐋣-; [C2, V3, V6]; xn--h8e470bl0d838o.xn----381i; ; ; # ꡦᡑ⒈.𐋣-
+Ⴌ。􍼠ﭩ; Ⴌ.􍼠ٹ; [B5, B6, P1, V6]; xn--knd.xn--yib19191t; ; ; # Ⴌ.ٹ
+Ⴌ。􍼠ٹ; Ⴌ.􍼠ٹ; [B5, B6, P1, V6]; xn--knd.xn--yib19191t; ; ; # Ⴌ.ٹ
+ⴌ。􍼠ٹ; ⴌ.􍼠ٹ; [B5, B6, P1, V6]; xn--3kj.xn--yib19191t; ; ; # ⴌ.ٹ
+xn--3kj.xn--yib19191t; ⴌ.􍼠ٹ; [B5, B6, V6]; xn--3kj.xn--yib19191t; ; ; # ⴌ.ٹ
+xn--knd.xn--yib19191t; Ⴌ.􍼠ٹ; [B5, B6, V6]; xn--knd.xn--yib19191t; ; ; # Ⴌ.ٹ
+ⴌ。􍼠ﭩ; ⴌ.􍼠ٹ; [B5, B6, P1, V6]; xn--3kj.xn--yib19191t; ; ; # ⴌ.ٹ
+𐮁𐭱.྄፞-ᳺ; ; [B1, V5]; xn--r19c5a.xn----xjg270ag3m; ; ; # 𐮁𐭱.྄፞-ᳺ
+xn--r19c5a.xn----xjg270ag3m; 𐮁𐭱.྄፞-ᳺ; [B1, V5]; xn--r19c5a.xn----xjg270ag3m; ; ; # 𐮁𐭱.྄፞-ᳺ
+⒈䰹‍-。웈; ⒈䰹‍-.웈; [C2, P1, V3, V6]; xn----tgnx5rjr6c.xn--kp5b; ; xn----dcp160o.xn--kp5b; [P1, V3, V6] # ⒈䰹-.웈
+⒈䰹‍-。웈; ⒈䰹‍-.웈; [C2, P1, V3, V6]; xn----tgnx5rjr6c.xn--kp5b; ; xn----dcp160o.xn--kp5b; [P1, V3, V6] # ⒈䰹-.웈
+1.䰹‍-。웈; 1.䰹‍-.웈; [C2, V3]; 1.xn----tgnz80r.xn--kp5b; ; 1.xn----zw5a.xn--kp5b; [V3] # 1.䰹-.웈
+1.䰹‍-。웈; 1.䰹‍-.웈; [C2, V3]; 1.xn----tgnz80r.xn--kp5b; ; 1.xn----zw5a.xn--kp5b; [V3] # 1.䰹-.웈
+1.xn----zw5a.xn--kp5b; 1.䰹-.웈; [V3]; 1.xn----zw5a.xn--kp5b; ; ; # 1.䰹-.웈
+1.xn----tgnz80r.xn--kp5b; 1.䰹‍-.웈; [C2, V3]; 1.xn----tgnz80r.xn--kp5b; ; ; # 1.䰹-.웈
+xn----dcp160o.xn--kp5b; ⒈䰹-.웈; [V3, V6]; xn----dcp160o.xn--kp5b; ; ; # ⒈䰹-.웈
+xn----tgnx5rjr6c.xn--kp5b; ⒈䰹‍-.웈; [C2, V3, V6]; xn----tgnx5rjr6c.xn--kp5b; ; ; # ⒈䰹-.웈
+て。‌󠳽߳; て.‌󠳽߳; [C1, P1, V6]; xn--m9j.xn--rtb154j9l73w; ; xn--m9j.xn--rtb10784p; [P1, V6] # て.߳
+xn--m9j.xn--rtb10784p; て.󠳽߳; [V6]; xn--m9j.xn--rtb10784p; ; ; # て.߳
+xn--m9j.xn--rtb154j9l73w; て.‌󠳽߳; [C1, V6]; xn--m9j.xn--rtb154j9l73w; ; ; # て.߳
+ς。꧀ۧ; ς.꧀ۧ; [V5]; xn--3xa.xn--3lb1944f; ; xn--4xa.xn--3lb1944f; # ς.꧀ۧ
+ς。꧀ۧ; ς.꧀ۧ; [V5]; xn--3xa.xn--3lb1944f; ; xn--4xa.xn--3lb1944f; # ς.꧀ۧ
+Σ。꧀ۧ; σ.꧀ۧ; [V5]; xn--4xa.xn--3lb1944f; ; ; # σ.꧀ۧ
+σ。꧀ۧ; σ.꧀ۧ; [V5]; xn--4xa.xn--3lb1944f; ; ; # σ.꧀ۧ
+xn--4xa.xn--3lb1944f; σ.꧀ۧ; [V5]; xn--4xa.xn--3lb1944f; ; ; # σ.꧀ۧ
+xn--3xa.xn--3lb1944f; ς.꧀ۧ; [V5]; xn--3xa.xn--3lb1944f; ; ; # ς.꧀ۧ
+Σ。꧀ۧ; σ.꧀ۧ; [V5]; xn--4xa.xn--3lb1944f; ; ; # σ.꧀ۧ
+σ。꧀ۧ; σ.꧀ۧ; [V5]; xn--4xa.xn--3lb1944f; ; ; # σ.꧀ۧ
+்󥫅򌉑.ႢႵ; ; [P1, V5, V6]; xn--xmc83135idcxza.xn--9md2b; ; ; # ்.ႢႵ
+்󥫅򌉑.ⴂⴕ; ; [P1, V5, V6]; xn--xmc83135idcxza.xn--tkjwb; ; ; # ்.ⴂⴕ
+்󥫅򌉑.Ⴂⴕ; ; [P1, V5, V6]; xn--xmc83135idcxza.xn--9md086l; ; ; # ்.Ⴂⴕ
+xn--xmc83135idcxza.xn--9md086l; ்󥫅򌉑.Ⴂⴕ; [V5, V6]; xn--xmc83135idcxza.xn--9md086l; ; ; # ்.Ⴂⴕ
+xn--xmc83135idcxza.xn--tkjwb; ்󥫅򌉑.ⴂⴕ; [V5, V6]; xn--xmc83135idcxza.xn--tkjwb; ; ; # ்.ⴂⴕ
+xn--xmc83135idcxza.xn--9md2b; ்󥫅򌉑.ႢႵ; [V5, V6]; xn--xmc83135idcxza.xn--9md2b; ; ; # ்.ႢႵ
+ᰲ🄈⾛֦.‍򯥤߽; ᰲ🄈走֦.‍򯥤߽; [C2, P1, V5, V6]; xn--xcb756i493fwi5o.xn--1tb334j1197q; ; xn--xcb756i493fwi5o.xn--1tb13454l; [P1, V5, V6] # ᰲ🄈走֦.߽
+ᰲ7,走֦.‍򯥤߽; ; [C2, P1, V5, V6]; xn--7,-bid991urn3k.xn--1tb334j1197q; ; xn--7,-bid991urn3k.xn--1tb13454l; [P1, V5, V6] # ᰲ7,走֦.߽
+xn--7,-bid991urn3k.xn--1tb13454l; ᰲ7,走֦.򯥤߽; [P1, V5, V6]; xn--7,-bid991urn3k.xn--1tb13454l; ; ; # ᰲ7,走֦.߽
+xn--7,-bid991urn3k.xn--1tb334j1197q; ᰲ7,走֦.‍򯥤߽; [C2, P1, V5, V6]; xn--7,-bid991urn3k.xn--1tb334j1197q; ; ; # ᰲ7,走֦.߽
+xn--xcb756i493fwi5o.xn--1tb13454l; ᰲ🄈走֦.򯥤߽; [V5, V6]; xn--xcb756i493fwi5o.xn--1tb13454l; ; ; # ᰲ🄈走֦.߽
+xn--xcb756i493fwi5o.xn--1tb334j1197q; ᰲ🄈走֦.‍򯥤߽; [C2, V5, V6]; xn--xcb756i493fwi5o.xn--1tb334j1197q; ; ; # ᰲ🄈走֦.߽
+ᢗ。Ӏ񝄻; ᢗ.Ӏ񝄻; [P1, V6]; xn--hbf.xn--d5a86117e; ; ; # ᢗ.Ӏ
+ᢗ。Ӏ񝄻; ᢗ.Ӏ񝄻; [P1, V6]; xn--hbf.xn--d5a86117e; ; ; # ᢗ.Ӏ
+ᢗ。ӏ񝄻; ᢗ.ӏ񝄻; [P1, V6]; xn--hbf.xn--s5a83117e; ; ; # ᢗ.ӏ
+xn--hbf.xn--s5a83117e; ᢗ.ӏ񝄻; [V6]; xn--hbf.xn--s5a83117e; ; ; # ᢗ.ӏ
+xn--hbf.xn--d5a86117e; ᢗ.Ӏ񝄻; [V6]; xn--hbf.xn--d5a86117e; ; ; # ᢗ.Ӏ
+ᢗ。ӏ񝄻; ᢗ.ӏ񝄻; [P1, V6]; xn--hbf.xn--s5a83117e; ; ; # ᢗ.ӏ
+٨-。񠏇🝆ᄾ; ٨-.񠏇🝆ᄾ; [B1, P1, V3, V6]; xn----oqc.xn--qrd1699v327w; ; ; # ٨-.🝆ᄾ
+xn----oqc.xn--qrd1699v327w; ٨-.񠏇🝆ᄾ; [B1, V3, V6]; xn----oqc.xn--qrd1699v327w; ; ; # ٨-.🝆ᄾ
+-𐋷𖾑。󠆬; -𐋷𖾑.; [V3]; xn----991iq40y.; ; ; # -𐋷𖾑.
+xn----991iq40y.; -𐋷𖾑.; [V3]; xn----991iq40y.; ; ; # -𐋷𖾑.
+‌𐹳🐴멈.꯭񐡼; ; [B1, C1, P1, V5, V6]; xn--0ug6681d406b7bwk.xn--429a8682s; ; xn--422b325mqb6i.xn--429a8682s; [B1, P1, V5, V6] # 𐹳🐴멈.꯭
+‌𐹳🐴멈.꯭񐡼; ‌𐹳🐴멈.꯭񐡼; [B1, C1, P1, V5, V6]; xn--0ug6681d406b7bwk.xn--429a8682s; ; xn--422b325mqb6i.xn--429a8682s; [B1, P1, V5, V6] # 𐹳🐴멈.꯭
+xn--422b325mqb6i.xn--429a8682s; 𐹳🐴멈.꯭񐡼; [B1, V5, V6]; xn--422b325mqb6i.xn--429a8682s; ; ; # 𐹳🐴멈.꯭
+xn--0ug6681d406b7bwk.xn--429a8682s; ‌𐹳🐴멈.꯭񐡼; [B1, C1, V5, V6]; xn--0ug6681d406b7bwk.xn--429a8682s; ; ; # 𐹳🐴멈.꯭
+≮.ݩ؃; ; [B1, P1, V6]; xn--gdh.xn--lfb92e; ; ; # ≮.ݩ
+≮.ݩ؃; ≮.ݩ؃; [B1, P1, V6]; xn--gdh.xn--lfb92e; ; ; # ≮.ݩ
+xn--gdh.xn--lfb92e; ≮.ݩ؃; [B1, V6]; xn--gdh.xn--lfb92e; ; ; # ≮.ݩ
+𐶭⾆。‌𑚶򟱃𞰘; 𐶭舌.‌𑚶򟱃𞰘; [B1, B2, B3, C1, P1, V6]; xn--tc1ao37z.xn--0ugx728gi1nfwqz2e; ; xn--tc1ao37z.xn--6e2dw557azds2d; [B2, B3, B5, B6, P1, V5, V6] # 舌.𑚶
+𐶭舌。‌𑚶򟱃𞰘; 𐶭舌.‌𑚶򟱃𞰘; [B1, B2, B3, C1, P1, V6]; xn--tc1ao37z.xn--0ugx728gi1nfwqz2e; ; xn--tc1ao37z.xn--6e2dw557azds2d; [B2, B3, B5, B6, P1, V5, V6] # 舌.𑚶
+xn--tc1ao37z.xn--6e2dw557azds2d; 𐶭舌.𑚶򟱃𞰘; [B2, B3, B5, B6, V5, V6]; xn--tc1ao37z.xn--6e2dw557azds2d; ; ; # 舌.𑚶
+xn--tc1ao37z.xn--0ugx728gi1nfwqz2e; 𐶭舌.‌𑚶򟱃𞰘; [B1, B2, B3, C1, V6]; xn--tc1ao37z.xn--0ugx728gi1nfwqz2e; ; ; # 舌.𑚶
+‌Ⴠ-.𝟷ς𞴺ς; ‌Ⴠ-.1ς𞴺ς; [B1, C1, P1, V3, V6]; xn----z1g168i.xn--1-ymba92321c; ; xn----z1g.xn--1-0mba52321c; [B1, B6, P1, V3, V6] # Ⴠ-.1ς𞴺ς
+‌Ⴠ-.1ς𞴺ς; ; [B1, C1, P1, V3, V6]; xn----z1g168i.xn--1-ymba92321c; ; xn----z1g.xn--1-0mba52321c; [B1, B6, P1, V3, V6] # Ⴠ-.1ς𞴺ς
+‌ⴠ-.1ς𞴺ς; ; [B1, C1, V3]; xn----rgn530d.xn--1-ymba92321c; ; xn----2ws.xn--1-0mba52321c; [B1, B6, V3] # ⴠ-.1ς𞴺ς
+‌Ⴠ-.1Σ𞴺Σ; ‌Ⴠ-.1σ𞴺σ; [B1, C1, P1, V3, V6]; xn----z1g168i.xn--1-0mba52321c; ; xn----z1g.xn--1-0mba52321c; [B1, B6, P1, V3, V6] # Ⴠ-.1σ𞴺σ
+‌ⴠ-.1σ𞴺σ; ; [B1, C1, V3]; xn----rgn530d.xn--1-0mba52321c; ; xn----2ws.xn--1-0mba52321c; [B1, B6, V3] # ⴠ-.1σ𞴺σ
+‌Ⴠ-.1σ𞴺Σ; ‌Ⴠ-.1σ𞴺σ; [B1, C1, P1, V3, V6]; xn----z1g168i.xn--1-0mba52321c; ; xn----z1g.xn--1-0mba52321c; [B1, B6, P1, V3, V6] # Ⴠ-.1σ𞴺σ
+xn----z1g.xn--1-0mba52321c; Ⴠ-.1σ𞴺σ; [B1, B6, V3, V6]; xn----z1g.xn--1-0mba52321c; ; ; # Ⴠ-.1σ𞴺σ
+xn----z1g168i.xn--1-0mba52321c; ‌Ⴠ-.1σ𞴺σ; [B1, C1, V3, V6]; xn----z1g168i.xn--1-0mba52321c; ; ; # Ⴠ-.1σ𞴺σ
+xn----2ws.xn--1-0mba52321c; ⴠ-.1σ𞴺σ; [B1, B6, V3]; xn----2ws.xn--1-0mba52321c; ; ; # ⴠ-.1σ𞴺σ
+xn----rgn530d.xn--1-0mba52321c; ‌ⴠ-.1σ𞴺σ; [B1, C1, V3]; xn----rgn530d.xn--1-0mba52321c; ; ; # ⴠ-.1σ𞴺σ
+‌Ⴠ-.1ς𞴺Σ; ‌Ⴠ-.1ς𞴺σ; [B1, C1, P1, V3, V6]; xn----z1g168i.xn--1-ymbd52321c; ; xn----z1g.xn--1-0mba52321c; [B1, B6, P1, V3, V6] # Ⴠ-.1ς𞴺σ
+‌ⴠ-.1ς𞴺σ; ; [B1, C1, V3]; xn----rgn530d.xn--1-ymbd52321c; ; xn----2ws.xn--1-0mba52321c; [B1, B6, V3] # ⴠ-.1ς𞴺σ
+xn----rgn530d.xn--1-ymbd52321c; ‌ⴠ-.1ς𞴺σ; [B1, C1, V3]; xn----rgn530d.xn--1-ymbd52321c; ; ; # ⴠ-.1ς𞴺σ
+xn----z1g168i.xn--1-ymbd52321c; ‌Ⴠ-.1ς𞴺σ; [B1, C1, V3, V6]; xn----z1g168i.xn--1-ymbd52321c; ; ; # Ⴠ-.1ς𞴺σ
+xn----rgn530d.xn--1-ymba92321c; ‌ⴠ-.1ς𞴺ς; [B1, C1, V3]; xn----rgn530d.xn--1-ymba92321c; ; ; # ⴠ-.1ς𞴺ς
+xn----z1g168i.xn--1-ymba92321c; ‌Ⴠ-.1ς𞴺ς; [B1, C1, V3, V6]; xn----z1g168i.xn--1-ymba92321c; ; ; # Ⴠ-.1ς𞴺ς
+‌ⴠ-.𝟷ς𞴺ς; ‌ⴠ-.1ς𞴺ς; [B1, C1, V3]; xn----rgn530d.xn--1-ymba92321c; ; xn----2ws.xn--1-0mba52321c; [B1, B6, V3] # ⴠ-.1ς𞴺ς
+‌Ⴠ-.𝟷Σ𞴺Σ; ‌Ⴠ-.1σ𞴺σ; [B1, C1, P1, V3, V6]; xn----z1g168i.xn--1-0mba52321c; ; xn----z1g.xn--1-0mba52321c; [B1, B6, P1, V3, V6] # Ⴠ-.1σ𞴺σ
+‌ⴠ-.𝟷σ𞴺σ; ‌ⴠ-.1σ𞴺σ; [B1, C1, V3]; xn----rgn530d.xn--1-0mba52321c; ; xn----2ws.xn--1-0mba52321c; [B1, B6, V3] # ⴠ-.1σ𞴺σ
+‌Ⴠ-.𝟷σ𞴺Σ; ‌Ⴠ-.1σ𞴺σ; [B1, C1, P1, V3, V6]; xn----z1g168i.xn--1-0mba52321c; ; xn----z1g.xn--1-0mba52321c; [B1, B6, P1, V3, V6] # Ⴠ-.1σ𞴺σ
+‌Ⴠ-.𝟷ς𞴺Σ; ‌Ⴠ-.1ς𞴺σ; [B1, C1, P1, V3, V6]; xn----z1g168i.xn--1-ymbd52321c; ; xn----z1g.xn--1-0mba52321c; [B1, B6, P1, V3, V6] # Ⴠ-.1ς𞴺σ
+‌ⴠ-.𝟷ς𞴺σ; ‌ⴠ-.1ς𞴺σ; [B1, C1, V3]; xn----rgn530d.xn--1-ymbd52321c; ; xn----2ws.xn--1-0mba52321c; [B1, B6, V3] # ⴠ-.1ς𞴺σ
+𑲘󠄒𓑡。𝟪Ⴜ; 𑲘𓑡.8Ⴜ; [P1, V5, V6]; xn--7m3d291b.xn--8-s1g; ; ; # 𑲘.8Ⴜ
+𑲘󠄒𓑡。8Ⴜ; 𑲘𓑡.8Ⴜ; [P1, V5, V6]; xn--7m3d291b.xn--8-s1g; ; ; # 𑲘.8Ⴜ
+𑲘󠄒𓑡。8ⴜ; 𑲘𓑡.8ⴜ; [P1, V5, V6]; xn--7m3d291b.xn--8-vws; ; ; # 𑲘.8ⴜ
+xn--7m3d291b.xn--8-vws; 𑲘𓑡.8ⴜ; [V5, V6]; xn--7m3d291b.xn--8-vws; ; ; # 𑲘.8ⴜ
+xn--7m3d291b.xn--8-s1g; 𑲘𓑡.8Ⴜ; [V5, V6]; xn--7m3d291b.xn--8-s1g; ; ; # 𑲘.8Ⴜ
+𑲘󠄒𓑡。𝟪ⴜ; 𑲘𓑡.8ⴜ; [P1, V5, V6]; xn--7m3d291b.xn--8-vws; ; ; # 𑲘.8ⴜ
+䪏ګߠु。뭕ᢝឹ; 䪏ګߠु.뭕ᢝឹ; [B5, B6]; xn--ekb23dj4at01n.xn--43e96bh910b; ; ; # 䪏ګߠु.뭕ᢝឹ
+䪏ګߠु。뭕ᢝឹ; 䪏ګߠु.뭕ᢝឹ; [B5, B6]; xn--ekb23dj4at01n.xn--43e96bh910b; ; ; # 䪏ګߠु.뭕ᢝឹ
+䪏ګߠु。뭕ᢝឹ; 䪏ګߠु.뭕ᢝឹ; [B5, B6]; xn--ekb23dj4at01n.xn--43e96bh910b; ; ; # 䪏ګߠु.뭕ᢝឹ
+䪏ګߠु。뭕ᢝឹ; 䪏ګߠु.뭕ᢝឹ; [B5, B6]; xn--ekb23dj4at01n.xn--43e96bh910b; ; ; # 䪏ګߠु.뭕ᢝឹ
+xn--ekb23dj4at01n.xn--43e96bh910b; 䪏ګߠु.뭕ᢝឹ; [B5, B6]; xn--ekb23dj4at01n.xn--43e96bh910b; ; ; # 䪏ګߠु.뭕ᢝឹ
+᮫。🂉󠁰; ᮫.🂉󠁰; [P1, V5, V6]; xn--zxf.xn--fx7ho0250c; ; ; # ᮫.🂉
+᮫。🂉󠁰; ᮫.🂉󠁰; [P1, V5, V6]; xn--zxf.xn--fx7ho0250c; ; ; # ᮫.🂉
+xn--zxf.xn--fx7ho0250c; ᮫.🂉󠁰; [V5, V6]; xn--zxf.xn--fx7ho0250c; ; ; # ᮫.🂉
+󩎃ૄ。ς‍𐹮𑈵; 󩎃ૄ.ς‍𐹮𑈵; [B5, C2, P1, V6]; xn--dfc53161q.xn--3xa006lzo7nsfd; ; xn--dfc53161q.xn--4xa8467k5mc; [B5, P1, V6] # ૄ.ς𐹮𑈵
+󩎃ૄ。Σ‍𐹮𑈵; 󩎃ૄ.σ‍𐹮𑈵; [B5, C2, P1, V6]; xn--dfc53161q.xn--4xa895lzo7nsfd; ; xn--dfc53161q.xn--4xa8467k5mc; [B5, P1, V6] # ૄ.σ𐹮𑈵
+󩎃ૄ。σ‍𐹮𑈵; 󩎃ૄ.σ‍𐹮𑈵; [B5, C2, P1, V6]; xn--dfc53161q.xn--4xa895lzo7nsfd; ; xn--dfc53161q.xn--4xa8467k5mc; [B5, P1, V6] # ૄ.σ𐹮𑈵
+xn--dfc53161q.xn--4xa8467k5mc; 󩎃ૄ.σ𐹮𑈵; [B5, V6]; xn--dfc53161q.xn--4xa8467k5mc; ; ; # ૄ.σ𐹮𑈵
+xn--dfc53161q.xn--4xa895lzo7nsfd; 󩎃ૄ.σ‍𐹮𑈵; [B5, C2, V6]; xn--dfc53161q.xn--4xa895lzo7nsfd; ; ; # ૄ.σ𐹮𑈵
+xn--dfc53161q.xn--3xa006lzo7nsfd; 󩎃ૄ.ς‍𐹮𑈵; [B5, C2, V6]; xn--dfc53161q.xn--3xa006lzo7nsfd; ; ; # ૄ.ς𐹮𑈵
+𐫀ᡂ𑜫.𑘿; 𐫀ᡂ𑜫.𑘿; [B1, B2, B3, B6, V5]; xn--17e9625js1h.xn--sb2d; ; ; # 𐫀ᡂ𑜫.𑘿
+𐫀ᡂ𑜫.𑘿; ; [B1, B2, B3, B6, V5]; xn--17e9625js1h.xn--sb2d; ; ; # 𐫀ᡂ𑜫.𑘿
+xn--17e9625js1h.xn--sb2d; 𐫀ᡂ𑜫.𑘿; [B1, B2, B3, B6, V5]; xn--17e9625js1h.xn--sb2d; ; ; # 𐫀ᡂ𑜫.𑘿
+󬚶󸋖򖩰-。‌; 󬚶󸋖򖩰-.‌; [C1, P1, V3, V6]; xn----7i12hu122k9ire.xn--0ug; ; xn----7i12hu122k9ire.; [P1, V3, V6] # -.
+xn----7i12hu122k9ire.; 󬚶󸋖򖩰-.; [V3, V6]; xn----7i12hu122k9ire.; ; ; # -.
+xn----7i12hu122k9ire.xn--0ug; 󬚶󸋖򖩰-.‌; [C1, V3, V6]; xn----7i12hu122k9ire.xn--0ug; ; ; # -.
+𐹣.߂; 𐹣.߂; [B1]; xn--bo0d.xn--dsb; ; ; # 𐹣.߂
+𐹣.߂; ; [B1]; xn--bo0d.xn--dsb; ; ; # 𐹣.߂
+xn--bo0d.xn--dsb; 𐹣.߂; [B1]; xn--bo0d.xn--dsb; ; ; # 𐹣.߂
+-ߡ。Ↄ; -ߡ.Ↄ; [B1, P1, V3, V6]; xn----8cd.xn--q5g; ; ; # -ߡ.Ↄ
+-ߡ。Ↄ; -ߡ.Ↄ; [B1, P1, V3, V6]; xn----8cd.xn--q5g; ; ; # -ߡ.Ↄ
+-ߡ。ↄ; -ߡ.ↄ; [B1, V3]; xn----8cd.xn--r5g; ; ; # -ߡ.ↄ
+xn----8cd.xn--r5g; -ߡ.ↄ; [B1, V3]; xn----8cd.xn--r5g; ; ; # -ߡ.ↄ
+xn----8cd.xn--q5g; -ߡ.Ↄ; [B1, V3, V6]; xn----8cd.xn--q5g; ; ; # -ߡ.Ↄ
+-ߡ。ↄ; -ߡ.ↄ; [B1, V3]; xn----8cd.xn--r5g; ; ; # -ߡ.ↄ
+‍-︒󠄄。ß哑‌𐵿; ‍-︒.ß哑‌𐵿; [B1, B5, B6, C1, C2, P1, V6]; xn----tgnt341h.xn--zca670n5f0binyk; ; xn----o89h.xn--ss-h46c5711e; [B1, B5, B6, P1, V3, V6] # -︒.ß哑
+‍-。󠄄。ß哑‌𐵿; ‍-..ß哑‌𐵿; [B1, B5, B6, C1, C2, P1, V3, V6, X4_2]; xn----tgn..xn--zca670n5f0binyk; [B1, B5, B6, C1, C2, P1, V3, V6, A4_2]; -..xn--ss-h46c5711e; [B1, B5, B6, P1, V3, V6, A4_2] # -..ß哑
+‍-。󠄄。SS哑‌𐵿; ‍-..ss哑‌𐵿; [B1, B5, B6, C1, C2, P1, V3, V6, X4_2]; xn----tgn..xn--ss-k1ts75zb8ym; [B1, B5, B6, C1, C2, P1, V3, V6, A4_2]; -..xn--ss-h46c5711e; [B1, B5, B6, P1, V3, V6, A4_2] # -..ss哑
+‍-。󠄄。ss哑‌𐵿; ‍-..ss哑‌𐵿; [B1, B5, B6, C1, C2, P1, V3, V6, X4_2]; xn----tgn..xn--ss-k1ts75zb8ym; [B1, B5, B6, C1, C2, P1, V3, V6, A4_2]; -..xn--ss-h46c5711e; [B1, B5, B6, P1, V3, V6, A4_2] # -..ss哑
+‍-。󠄄。Ss哑‌𐵿; ‍-..ss哑‌𐵿; [B1, B5, B6, C1, C2, P1, V3, V6, X4_2]; xn----tgn..xn--ss-k1ts75zb8ym; [B1, B5, B6, C1, C2, P1, V3, V6, A4_2]; -..xn--ss-h46c5711e; [B1, B5, B6, P1, V3, V6, A4_2] # -..ss哑
+-..xn--ss-h46c5711e; -..ss哑𐵿; [B1, B5, B6, V3, V6, X4_2]; -..xn--ss-h46c5711e; [B1, B5, B6, V3, V6, A4_2]; ; # -..ss哑
+xn----tgn..xn--ss-k1ts75zb8ym; ‍-..ss哑‌𐵿; [B1, B5, B6, C1, C2, V3, V6, X4_2]; xn----tgn..xn--ss-k1ts75zb8ym; [B1, B5, B6, C1, C2, V3, V6, A4_2]; ; # -..ss哑
+xn----tgn..xn--zca670n5f0binyk; ‍-..ß哑‌𐵿; [B1, B5, B6, C1, C2, V3, V6, X4_2]; xn----tgn..xn--zca670n5f0binyk; [B1, B5, B6, C1, C2, V3, V6, A4_2]; ; # -..ß哑
+‍-︒󠄄。SS哑‌𐵿; ‍-︒.ss哑‌𐵿; [B1, B5, B6, C1, C2, P1, V6]; xn----tgnt341h.xn--ss-k1ts75zb8ym; ; xn----o89h.xn--ss-h46c5711e; [B1, B5, B6, P1, V3, V6] # -︒.ss哑
+‍-︒󠄄。ss哑‌𐵿; ‍-︒.ss哑‌𐵿; [B1, B5, B6, C1, C2, P1, V6]; xn----tgnt341h.xn--ss-k1ts75zb8ym; ; xn----o89h.xn--ss-h46c5711e; [B1, B5, B6, P1, V3, V6] # -︒.ss哑
+‍-︒󠄄。Ss哑‌𐵿; ‍-︒.ss哑‌𐵿; [B1, B5, B6, C1, C2, P1, V6]; xn----tgnt341h.xn--ss-k1ts75zb8ym; ; xn----o89h.xn--ss-h46c5711e; [B1, B5, B6, P1, V3, V6] # -︒.ss哑
+xn----o89h.xn--ss-h46c5711e; -︒.ss哑𐵿; [B1, B5, B6, V3, V6]; xn----o89h.xn--ss-h46c5711e; ; ; # -︒.ss哑
+xn----tgnt341h.xn--ss-k1ts75zb8ym; ‍-︒.ss哑‌𐵿; [B1, B5, B6, C1, C2, V6]; xn----tgnt341h.xn--ss-k1ts75zb8ym; ; ; # -︒.ss哑
+xn----tgnt341h.xn--zca670n5f0binyk; ‍-︒.ß哑‌𐵿; [B1, B5, B6, C1, C2, V6]; xn----tgnt341h.xn--zca670n5f0binyk; ; ; # -︒.ß哑
+︒.𑑂︯; ︒.𑑂︯; [P1, V5, V6]; xn--y86c.xn--s96cu30b; ; ; # ︒.𑑂︯
+︒.𑑂︯; ︒.𑑂︯; [P1, V5, V6]; xn--y86c.xn--s96cu30b; ; ; # ︒.𑑂︯
+。.𑑂︯; ..𑑂︯; [V5, X4_2]; ..xn--s96cu30b; [V5, A4_2]; ; # ..𑑂︯
+..xn--s96cu30b; ..𑑂︯; [V5, X4_2]; ..xn--s96cu30b; [V5, A4_2]; ; # ..𑑂︯
+xn--y86c.xn--s96cu30b; ︒.𑑂︯; [V5, V6]; xn--y86c.xn--s96cu30b; ; ; # ︒.𑑂︯
+꤬。‍; ꤬.‍; [C2, V5]; xn--zi9a.xn--1ug; ; xn--zi9a.; [V5] # ꤬.
+xn--zi9a.; ꤬.; [V5]; xn--zi9a.; ; ; # ꤬.
+xn--zi9a.xn--1ug; ꤬.‍; [C2, V5]; xn--zi9a.xn--1ug; ; ; # ꤬.
+‍󠸡。ﳗ; ‍󠸡.هج; [B1, C2, P1, V6]; xn--1ug80651l.xn--rgb7c; ; xn--d356e.xn--rgb7c; [B1, P1, V6] # .هج
+‍󠸡。هج; ‍󠸡.هج; [B1, C2, P1, V6]; xn--1ug80651l.xn--rgb7c; ; xn--d356e.xn--rgb7c; [B1, P1, V6] # .هج
+xn--d356e.xn--rgb7c; 󠸡.هج; [B1, V6]; xn--d356e.xn--rgb7c; ; ; # .هج
+xn--1ug80651l.xn--rgb7c; ‍󠸡.هج; [B1, C2, V6]; xn--1ug80651l.xn--rgb7c; ; ; # .هج
+-Ⴄ𝟢٣.𑍴ς; -Ⴄ0٣.𑍴ς; [B1, P1, V3, V5, V6]; xn---0-iyd216h.xn--3xa1220l; ; xn---0-iyd216h.xn--4xa9120l; # -Ⴄ0٣.𑍴ς
+-Ⴄ0٣.𑍴ς; ; [B1, P1, V3, V5, V6]; xn---0-iyd216h.xn--3xa1220l; ; xn---0-iyd216h.xn--4xa9120l; # -Ⴄ0٣.𑍴ς
+-ⴄ0٣.𑍴ς; ; [B1, V3, V5]; xn---0-iyd8660b.xn--3xa1220l; ; xn---0-iyd8660b.xn--4xa9120l; # -ⴄ0٣.𑍴ς
+-Ⴄ0٣.𑍴Σ; -Ⴄ0٣.𑍴σ; [B1, P1, V3, V5, V6]; xn---0-iyd216h.xn--4xa9120l; ; ; # -Ⴄ0٣.𑍴σ
+-ⴄ0٣.𑍴σ; ; [B1, V3, V5]; xn---0-iyd8660b.xn--4xa9120l; ; ; # -ⴄ0٣.𑍴σ
+xn---0-iyd8660b.xn--4xa9120l; -ⴄ0٣.𑍴σ; [B1, V3, V5]; xn---0-iyd8660b.xn--4xa9120l; ; ; # -ⴄ0٣.𑍴σ
+xn---0-iyd216h.xn--4xa9120l; -Ⴄ0٣.𑍴σ; [B1, V3, V5, V6]; xn---0-iyd216h.xn--4xa9120l; ; ; # -Ⴄ0٣.𑍴σ
+xn---0-iyd8660b.xn--3xa1220l; -ⴄ0٣.𑍴ς; [B1, V3, V5]; xn---0-iyd8660b.xn--3xa1220l; ; ; # -ⴄ0٣.𑍴ς
+xn---0-iyd216h.xn--3xa1220l; -Ⴄ0٣.𑍴ς; [B1, V3, V5, V6]; xn---0-iyd216h.xn--3xa1220l; ; ; # -Ⴄ0٣.𑍴ς
+-ⴄ𝟢٣.𑍴ς; -ⴄ0٣.𑍴ς; [B1, V3, V5]; xn---0-iyd8660b.xn--3xa1220l; ; xn---0-iyd8660b.xn--4xa9120l; # -ⴄ0٣.𑍴ς
+-Ⴄ𝟢٣.𑍴Σ; -Ⴄ0٣.𑍴σ; [B1, P1, V3, V5, V6]; xn---0-iyd216h.xn--4xa9120l; ; ; # -Ⴄ0٣.𑍴σ
+-ⴄ𝟢٣.𑍴σ; -ⴄ0٣.𑍴σ; [B1, V3, V5]; xn---0-iyd8660b.xn--4xa9120l; ; ; # -ⴄ0٣.𑍴σ
+󦈄。-; 󦈄.-; [P1, V3, V6]; xn--xm38e.-; ; ; # .-
+xn--xm38e.-; 󦈄.-; [V3, V6]; xn--xm38e.-; ; ; # .-
+⋠𐋮.򶈮༘ß≯; ⋠𐋮.򶈮༘ß≯; [P1, V6]; xn--pgh4639f.xn--zca593eo6oc013y; ; xn--pgh4639f.xn--ss-ifj426nle504a; # ⋠𐋮.༘ß≯
+⋠𐋮.򶈮༘ß≯; ⋠𐋮.򶈮༘ß≯; [P1, V6]; xn--pgh4639f.xn--zca593eo6oc013y; ; xn--pgh4639f.xn--ss-ifj426nle504a; # ⋠𐋮.༘ß≯
+⋠𐋮.򶈮༘ß≯; ; [P1, V6]; xn--pgh4639f.xn--zca593eo6oc013y; ; xn--pgh4639f.xn--ss-ifj426nle504a; # ⋠𐋮.༘ß≯
+⋠𐋮.򶈮༘ß≯; ⋠𐋮.򶈮༘ß≯; [P1, V6]; xn--pgh4639f.xn--zca593eo6oc013y; ; xn--pgh4639f.xn--ss-ifj426nle504a; # ⋠𐋮.༘ß≯
+⋠𐋮.򶈮༘SS≯; ⋠𐋮.򶈮༘ss≯; [P1, V6]; xn--pgh4639f.xn--ss-ifj426nle504a; ; ; # ⋠𐋮.༘ss≯
+⋠𐋮.򶈮༘SS≯; ⋠𐋮.򶈮༘ss≯; [P1, V6]; xn--pgh4639f.xn--ss-ifj426nle504a; ; ; # ⋠𐋮.༘ss≯
+⋠𐋮.򶈮༘ss≯; ; [P1, V6]; xn--pgh4639f.xn--ss-ifj426nle504a; ; ; # ⋠𐋮.༘ss≯
+⋠𐋮.򶈮༘ss≯; ⋠𐋮.򶈮༘ss≯; [P1, V6]; xn--pgh4639f.xn--ss-ifj426nle504a; ; ; # ⋠𐋮.༘ss≯
+⋠𐋮.򶈮༘Ss≯; ⋠𐋮.򶈮༘ss≯; [P1, V6]; xn--pgh4639f.xn--ss-ifj426nle504a; ; ; # ⋠𐋮.༘ss≯
+⋠𐋮.򶈮༘Ss≯; ⋠𐋮.򶈮༘ss≯; [P1, V6]; xn--pgh4639f.xn--ss-ifj426nle504a; ; ; # ⋠𐋮.༘ss≯
+xn--pgh4639f.xn--ss-ifj426nle504a; ⋠𐋮.򶈮༘ss≯; [V6]; xn--pgh4639f.xn--ss-ifj426nle504a; ; ; # ⋠𐋮.༘ss≯
+xn--pgh4639f.xn--zca593eo6oc013y; ⋠𐋮.򶈮༘ß≯; [V6]; xn--pgh4639f.xn--zca593eo6oc013y; ; ; # ⋠𐋮.༘ß≯
+⋠𐋮.򶈮༘SS≯; ⋠𐋮.򶈮༘ss≯; [P1, V6]; xn--pgh4639f.xn--ss-ifj426nle504a; ; ; # ⋠𐋮.༘ss≯
+⋠𐋮.򶈮༘SS≯; ⋠𐋮.򶈮༘ss≯; [P1, V6]; xn--pgh4639f.xn--ss-ifj426nle504a; ; ; # ⋠𐋮.༘ss≯
+⋠𐋮.򶈮༘ss≯; ⋠𐋮.򶈮༘ss≯; [P1, V6]; xn--pgh4639f.xn--ss-ifj426nle504a; ; ; # ⋠𐋮.༘ss≯
+⋠𐋮.򶈮༘ss≯; ⋠𐋮.򶈮༘ss≯; [P1, V6]; xn--pgh4639f.xn--ss-ifj426nle504a; ; ; # ⋠𐋮.༘ss≯
+⋠𐋮.򶈮༘Ss≯; ⋠𐋮.򶈮༘ss≯; [P1, V6]; xn--pgh4639f.xn--ss-ifj426nle504a; ; ; # ⋠𐋮.༘ss≯
+⋠𐋮.򶈮༘Ss≯; ⋠𐋮.򶈮༘ss≯; [P1, V6]; xn--pgh4639f.xn--ss-ifj426nle504a; ; ; # ⋠𐋮.༘ss≯
+1𐋸٤。󠢮ﮤ񷝊; 1𐋸٤.󠢮ۀ񷝊; [B1, P1, V6]; xn--1-hqc3905q.xn--zkb83268gqee4a; ; ; # 1𐋸٤.ۀ
+1𐋸٤。󠢮ۀ񷝊; 1𐋸٤.󠢮ۀ񷝊; [B1, P1, V6]; xn--1-hqc3905q.xn--zkb83268gqee4a; ; ; # 1𐋸٤.ۀ
+1𐋸٤。󠢮ۀ񷝊; 1𐋸٤.󠢮ۀ񷝊; [B1, P1, V6]; xn--1-hqc3905q.xn--zkb83268gqee4a; ; ; # 1𐋸٤.ۀ
+xn--1-hqc3905q.xn--zkb83268gqee4a; 1𐋸٤.󠢮ۀ񷝊; [B1, V6]; xn--1-hqc3905q.xn--zkb83268gqee4a; ; ; # 1𐋸٤.ۀ
+儭-。𐹴Ⴢ񥳠‌; 儭-.𐹴Ⴢ񥳠‌; [B1, B6, C1, P1, V3, V6]; xn----gz7a.xn--6nd249ejl4pusr7b; ; xn----gz7a.xn--6nd5001kyw98a; [B1, B6, P1, V3, V6] # 儭-.𐹴Ⴢ
+儭-。𐹴Ⴢ񥳠‌; 儭-.𐹴Ⴢ񥳠‌; [B1, B6, C1, P1, V3, V6]; xn----gz7a.xn--6nd249ejl4pusr7b; ; xn----gz7a.xn--6nd5001kyw98a; [B1, B6, P1, V3, V6] # 儭-.𐹴Ⴢ
+儭-。𐹴ⴢ񥳠‌; 儭-.𐹴ⴢ񥳠‌; [B1, B6, C1, P1, V3, V6]; xn----gz7a.xn--0ug472cfq0pus98b; ; xn----gz7a.xn--qlj9223eywx0b; [B1, B6, P1, V3, V6] # 儭-.𐹴ⴢ
+xn----gz7a.xn--qlj9223eywx0b; 儭-.𐹴ⴢ񥳠; [B1, B6, V3, V6]; xn----gz7a.xn--qlj9223eywx0b; ; ; # 儭-.𐹴ⴢ
+xn----gz7a.xn--0ug472cfq0pus98b; 儭-.𐹴ⴢ񥳠‌; [B1, B6, C1, V3, V6]; xn----gz7a.xn--0ug472cfq0pus98b; ; ; # 儭-.𐹴ⴢ
+xn----gz7a.xn--6nd5001kyw98a; 儭-.𐹴Ⴢ񥳠; [B1, B6, V3, V6]; xn----gz7a.xn--6nd5001kyw98a; ; ; # 儭-.𐹴Ⴢ
+xn----gz7a.xn--6nd249ejl4pusr7b; 儭-.𐹴Ⴢ񥳠‌; [B1, B6, C1, V3, V6]; xn----gz7a.xn--6nd249ejl4pusr7b; ; ; # 儭-.𐹴Ⴢ
+儭-。𐹴ⴢ񥳠‌; 儭-.𐹴ⴢ񥳠‌; [B1, B6, C1, P1, V3, V6]; xn----gz7a.xn--0ug472cfq0pus98b; ; xn----gz7a.xn--qlj9223eywx0b; [B1, B6, P1, V3, V6] # 儭-.𐹴ⴢ
+𝟺𐋷ڹ.𞤭򿍡; 4𐋷ڹ.𞤭򿍡; [B1, B2, B3, P1, V6]; xn--4-cvc5384q.xn--le6hi7322b; ; ; # 4𐋷ڹ.𞤭
+4𐋷ڹ.𞤭򿍡; ; [B1, B2, B3, P1, V6]; xn--4-cvc5384q.xn--le6hi7322b; ; ; # 4𐋷ڹ.𞤭
+4𐋷ڹ.𞤋򿍡; 4𐋷ڹ.𞤭򿍡; [B1, B2, B3, P1, V6]; xn--4-cvc5384q.xn--le6hi7322b; ; ; # 4𐋷ڹ.𞤭
+xn--4-cvc5384q.xn--le6hi7322b; 4𐋷ڹ.𞤭򿍡; [B1, B2, B3, V6]; xn--4-cvc5384q.xn--le6hi7322b; ; ; # 4𐋷ڹ.𞤭
+𝟺𐋷ڹ.𞤋򿍡; 4𐋷ڹ.𞤭򿍡; [B1, B2, B3, P1, V6]; xn--4-cvc5384q.xn--le6hi7322b; ; ; # 4𐋷ڹ.𞤭
+≯-ꡋ𑲣.⒈𐹭; ; [B1, P1, V6]; xn----ogox061d5i8d.xn--tsh0666f; ; ; # ≯-ꡋ𑲣.⒈𐹭
+≯-ꡋ𑲣.⒈𐹭; ≯-ꡋ𑲣.⒈𐹭; [B1, P1, V6]; xn----ogox061d5i8d.xn--tsh0666f; ; ; # ≯-ꡋ𑲣.⒈𐹭
+≯-ꡋ𑲣.1.𐹭; ; [B1, P1, V6]; xn----ogox061d5i8d.1.xn--lo0d; ; ; # ≯-ꡋ𑲣.1.𐹭
+≯-ꡋ𑲣.1.𐹭; ≯-ꡋ𑲣.1.𐹭; [B1, P1, V6]; xn----ogox061d5i8d.1.xn--lo0d; ; ; # ≯-ꡋ𑲣.1.𐹭
+xn----ogox061d5i8d.1.xn--lo0d; ≯-ꡋ𑲣.1.𐹭; [B1, V6]; xn----ogox061d5i8d.1.xn--lo0d; ; ; # ≯-ꡋ𑲣.1.𐹭
+xn----ogox061d5i8d.xn--tsh0666f; ≯-ꡋ𑲣.⒈𐹭; [B1, V6]; xn----ogox061d5i8d.xn--tsh0666f; ; ; # ≯-ꡋ𑲣.⒈𐹭
+̰.󰜱蚀; ̰.󰜱蚀; [P1, V5, V6]; xn--xta.xn--e91aw9417e; ; ; # ̰.蚀
+̰.󰜱蚀; ; [P1, V5, V6]; xn--xta.xn--e91aw9417e; ; ; # ̰.蚀
+xn--xta.xn--e91aw9417e; ̰.󰜱蚀; [V5, V6]; xn--xta.xn--e91aw9417e; ; ; # ̰.蚀
+יּႸ.𞡼𑇀ß⃗; יּႸ.𞡼𑇀ß⃗; [B2, B3, P1, V6]; xn--kdb1d867b.xn--zca284nhg9nrrxg; ; xn--kdb1d867b.xn--ss-yju5690ken9h; # יּႸ.𞡼𑇀ß⃗
+יּႸ.𞡼𑇀ß⃗; ; [B2, B3, P1, V6]; xn--kdb1d867b.xn--zca284nhg9nrrxg; ; xn--kdb1d867b.xn--ss-yju5690ken9h; # יּႸ.𞡼𑇀ß⃗
+יּⴘ.𞡼𑇀ß⃗; ; [B2, B3]; xn--kdb1d278n.xn--zca284nhg9nrrxg; ; xn--kdb1d278n.xn--ss-yju5690ken9h; # יּⴘ.𞡼𑇀ß⃗
+יּႸ.𞡼𑇀SS⃗; יּႸ.𞡼𑇀ss⃗; [B2, B3, P1, V6]; xn--kdb1d867b.xn--ss-yju5690ken9h; ; ; # יּႸ.𞡼𑇀ss⃗
+יּⴘ.𞡼𑇀ss⃗; ; [B2, B3]; xn--kdb1d278n.xn--ss-yju5690ken9h; ; ; # יּⴘ.𞡼𑇀ss⃗
+xn--kdb1d278n.xn--ss-yju5690ken9h; יּⴘ.𞡼𑇀ss⃗; [B2, B3]; xn--kdb1d278n.xn--ss-yju5690ken9h; ; ; # יּⴘ.𞡼𑇀ss⃗
+xn--kdb1d867b.xn--ss-yju5690ken9h; יּႸ.𞡼𑇀ss⃗; [B2, B3, V6]; xn--kdb1d867b.xn--ss-yju5690ken9h; ; ; # יּႸ.𞡼𑇀ss⃗
+xn--kdb1d278n.xn--zca284nhg9nrrxg; יּⴘ.𞡼𑇀ß⃗; [B2, B3]; xn--kdb1d278n.xn--zca284nhg9nrrxg; ; ; # יּⴘ.𞡼𑇀ß⃗
+xn--kdb1d867b.xn--zca284nhg9nrrxg; יּႸ.𞡼𑇀ß⃗; [B2, B3, V6]; xn--kdb1d867b.xn--zca284nhg9nrrxg; ; ; # יּႸ.𞡼𑇀ß⃗
+יּⴘ.𞡼𑇀ß⃗; יּⴘ.𞡼𑇀ß⃗; [B2, B3]; xn--kdb1d278n.xn--zca284nhg9nrrxg; ; xn--kdb1d278n.xn--ss-yju5690ken9h; # יּⴘ.𞡼𑇀ß⃗
+יּႸ.𞡼𑇀SS⃗; יּႸ.𞡼𑇀ss⃗; [B2, B3, P1, V6]; xn--kdb1d867b.xn--ss-yju5690ken9h; ; ; # יּႸ.𞡼𑇀ss⃗
+יּⴘ.𞡼𑇀ss⃗; יּⴘ.𞡼𑇀ss⃗; [B2, B3]; xn--kdb1d278n.xn--ss-yju5690ken9h; ; ; # יּⴘ.𞡼𑇀ss⃗
+יּႸ.𞡼𑇀ss⃗; ; [B2, B3, P1, V6]; xn--kdb1d867b.xn--ss-yju5690ken9h; ; ; # יּႸ.𞡼𑇀ss⃗
+יּႸ.𞡼𑇀ss⃗; יּႸ.𞡼𑇀ss⃗; [B2, B3, P1, V6]; xn--kdb1d867b.xn--ss-yju5690ken9h; ; ; # יּႸ.𞡼𑇀ss⃗
+ᮣ𐹰򁱓。凬; ᮣ𐹰򁱓.凬; [B1, P1, V5, V6]; xn--rxfz314ilg20c.xn--t9q; ; ; # ᮣ𐹰.凬
+ᮣ𐹰򁱓。凬; ᮣ𐹰򁱓.凬; [B1, P1, V5, V6]; xn--rxfz314ilg20c.xn--t9q; ; ; # ᮣ𐹰.凬
+xn--rxfz314ilg20c.xn--t9q; ᮣ𐹰򁱓.凬; [B1, V5, V6]; xn--rxfz314ilg20c.xn--t9q; ; ; # ᮣ𐹰.凬
+🢟🄈‍ꡎ。྄; 🢟🄈‍ꡎ.྄; [C2, P1, V5, V6]; xn--1ug4874cfd0kbmg.xn--3ed; ; xn--nc9aq743ds0e.xn--3ed; [P1, V5, V6] # 🢟🄈ꡎ.྄
+🢟7,‍ꡎ。྄; 🢟7,‍ꡎ.྄; [C2, P1, V5, V6]; xn--7,-n1t0654eqo3o.xn--3ed; ; xn--7,-gh9hg322i.xn--3ed; [P1, V5, V6] # 🢟7,ꡎ.྄
+xn--7,-gh9hg322i.xn--3ed; 🢟7,ꡎ.྄; [P1, V5, V6]; xn--7,-gh9hg322i.xn--3ed; ; ; # 🢟7,ꡎ.྄
+xn--7,-n1t0654eqo3o.xn--3ed; 🢟7,‍ꡎ.྄; [C2, P1, V5, V6]; xn--7,-n1t0654eqo3o.xn--3ed; ; ; # 🢟7,ꡎ.྄
+xn--nc9aq743ds0e.xn--3ed; 🢟🄈ꡎ.྄; [V5, V6]; xn--nc9aq743ds0e.xn--3ed; ; ; # 🢟🄈ꡎ.྄
+xn--1ug4874cfd0kbmg.xn--3ed; 🢟🄈‍ꡎ.྄; [C2, V5, V6]; xn--1ug4874cfd0kbmg.xn--3ed; ; ; # 🢟🄈ꡎ.྄
+ꡔ。္ᢇ; ꡔ.္ᢇ; [V5]; xn--tc9a.xn--9jd663b; ; ; # ꡔ.္ᢇ
+xn--tc9a.xn--9jd663b; ꡔ.္ᢇ; [V5]; xn--tc9a.xn--9jd663b; ; ; # ꡔ.္ᢇ
+⃫≮.𝨖; ; [P1, V5, V6]; xn--e1g71d.xn--772h; ; ; # ⃫≮.𝨖
+⃫≮.𝨖; ⃫≮.𝨖; [P1, V5, V6]; xn--e1g71d.xn--772h; ; ; # ⃫≮.𝨖
+xn--e1g71d.xn--772h; ⃫≮.𝨖; [V5, V6]; xn--e1g71d.xn--772h; ; ; # ⃫≮.𝨖
+Ⴢ≯褦.ᠪߪႾݧ; Ⴢ≯褦.ᠪߪႾݧ; [B5, B6, P1, V6]; xn--6nd461g478e.xn--rpb5x49td2h; ; ; # Ⴢ≯褦.ᠪߪႾݧ
+Ⴢ≯褦.ᠪߪႾݧ; Ⴢ≯褦.ᠪߪႾݧ; [B5, B6, P1, V6]; xn--6nd461g478e.xn--rpb5x49td2h; ; ; # Ⴢ≯褦.ᠪߪႾݧ
+Ⴢ≯褦.ᠪߪႾݧ; ; [B5, B6, P1, V6]; xn--6nd461g478e.xn--rpb5x49td2h; ; ; # Ⴢ≯褦.ᠪߪႾݧ
+Ⴢ≯褦.ᠪߪႾݧ; Ⴢ≯褦.ᠪߪႾݧ; [B5, B6, P1, V6]; xn--6nd461g478e.xn--rpb5x49td2h; ; ; # Ⴢ≯褦.ᠪߪႾݧ
+ⴢ≯褦.ᠪߪⴞݧ; ⴢ≯褦.ᠪߪⴞݧ; [B5, B6, P1, V6]; xn--hdh433bev8e.xn--rpb5x392bcyt; ; ; # ⴢ≯褦.ᠪߪⴞݧ
+ⴢ≯褦.ᠪߪⴞݧ; ; [B5, B6, P1, V6]; xn--hdh433bev8e.xn--rpb5x392bcyt; ; ; # ⴢ≯褦.ᠪߪⴞݧ
+Ⴢ≯褦.ᠪߪⴞݧ; ; [B5, B6, P1, V6]; xn--6nd461g478e.xn--rpb5x392bcyt; ; ; # Ⴢ≯褦.ᠪߪⴞݧ
+Ⴢ≯褦.ᠪߪⴞݧ; Ⴢ≯褦.ᠪߪⴞݧ; [B5, B6, P1, V6]; xn--6nd461g478e.xn--rpb5x392bcyt; ; ; # Ⴢ≯褦.ᠪߪⴞݧ
+xn--6nd461g478e.xn--rpb5x392bcyt; Ⴢ≯褦.ᠪߪⴞݧ; [B5, B6, V6]; xn--6nd461g478e.xn--rpb5x392bcyt; ; ; # Ⴢ≯褦.ᠪߪⴞݧ
+xn--hdh433bev8e.xn--rpb5x392bcyt; ⴢ≯褦.ᠪߪⴞݧ; [B5, B6, V6]; xn--hdh433bev8e.xn--rpb5x392bcyt; ; ; # ⴢ≯褦.ᠪߪⴞݧ
+xn--6nd461g478e.xn--rpb5x49td2h; Ⴢ≯褦.ᠪߪႾݧ; [B5, B6, V6]; xn--6nd461g478e.xn--rpb5x49td2h; ; ; # Ⴢ≯褦.ᠪߪႾݧ
+ⴢ≯褦.ᠪߪⴞݧ; ⴢ≯褦.ᠪߪⴞݧ; [B5, B6, P1, V6]; xn--hdh433bev8e.xn--rpb5x392bcyt; ; ; # ⴢ≯褦.ᠪߪⴞݧ
+ⴢ≯褦.ᠪߪⴞݧ; ⴢ≯褦.ᠪߪⴞݧ; [B5, B6, P1, V6]; xn--hdh433bev8e.xn--rpb5x392bcyt; ; ; # ⴢ≯褦.ᠪߪⴞݧ
+Ⴢ≯褦.ᠪߪⴞݧ; Ⴢ≯褦.ᠪߪⴞݧ; [B5, B6, P1, V6]; xn--6nd461g478e.xn--rpb5x392bcyt; ; ; # Ⴢ≯褦.ᠪߪⴞݧ
+Ⴢ≯褦.ᠪߪⴞݧ; Ⴢ≯褦.ᠪߪⴞݧ; [B5, B6, P1, V6]; xn--6nd461g478e.xn--rpb5x392bcyt; ; ; # Ⴢ≯褦.ᠪߪⴞݧ
+򊉆󠆒‌꥓。𞤙ٻꡘ; 򊉆‌꥓.𞤻ٻꡘ; [B2, B3, C1, P1, V6]; xn--0ug8815chtz0e.xn--0ib8893fegvj; ; xn--3j9al6189a.xn--0ib8893fegvj; [B2, B3, P1, V6] # ꥓.𞤻ٻꡘ
+򊉆󠆒‌꥓。𞤻ٻꡘ; 򊉆‌꥓.𞤻ٻꡘ; [B2, B3, C1, P1, V6]; xn--0ug8815chtz0e.xn--0ib8893fegvj; ; xn--3j9al6189a.xn--0ib8893fegvj; [B2, B3, P1, V6] # ꥓.𞤻ٻꡘ
+xn--3j9al6189a.xn--0ib8893fegvj; 򊉆꥓.𞤻ٻꡘ; [B2, B3, V6]; xn--3j9al6189a.xn--0ib8893fegvj; ; ; # ꥓.𞤻ٻꡘ
+xn--0ug8815chtz0e.xn--0ib8893fegvj; 򊉆‌꥓.𞤻ٻꡘ; [B2, B3, C1, V6]; xn--0ug8815chtz0e.xn--0ib8893fegvj; ; ; # ꥓.𞤻ٻꡘ
+‌.≯; ; [C1, P1, V6]; xn--0ug.xn--hdh; ; .xn--hdh; [P1, V6, A4_2] # .≯
+‌.≯; ‌.≯; [C1, P1, V6]; xn--0ug.xn--hdh; ; .xn--hdh; [P1, V6, A4_2] # .≯
+.xn--hdh; .≯; [V6, X4_2]; .xn--hdh; [V6, A4_2]; ; # .≯
+xn--0ug.xn--hdh; ‌.≯; [C1, V6]; xn--0ug.xn--hdh; ; ; # .≯
+𰅧񣩠-.꯭-悜; 𰅧񣩠-.꯭-悜; [P1, V3, V5, V6]; xn----7m53aj640l.xn----8f4br83t; ; ; # 𰅧-.꯭-悜
+𰅧񣩠-.꯭-悜; ; [P1, V3, V5, V6]; xn----7m53aj640l.xn----8f4br83t; ; ; # 𰅧-.꯭-悜
+xn----7m53aj640l.xn----8f4br83t; 𰅧񣩠-.꯭-悜; [V3, V5, V6]; xn----7m53aj640l.xn----8f4br83t; ; ; # 𰅧-.꯭-悜
+ᡉ𶓧⬞ᢜ.-‍𞣑‮; ; [C2, P1, V3, V6]; xn--87e0ol04cdl39e.xn----ugn5e3763s; ; xn--87e0ol04cdl39e.xn----qinu247r; [P1, V3, V6] # ᡉ⬞ᢜ.-𞣑
+xn--87e0ol04cdl39e.xn----qinu247r; ᡉ𶓧⬞ᢜ.-𞣑‮; [V3, V6]; xn--87e0ol04cdl39e.xn----qinu247r; ; ; # ᡉ⬞ᢜ.-𞣑
+xn--87e0ol04cdl39e.xn----ugn5e3763s; ᡉ𶓧⬞ᢜ.-‍𞣑‮; [C2, V3, V6]; xn--87e0ol04cdl39e.xn----ugn5e3763s; ; ; # ᡉ⬞ᢜ.-𞣑
+⒐‌衃Ⴝ.ڂႴ; ; [B1, B2, B3, C1, P1, V6]; xn--1nd159ecmd785k.xn--7ib433c; ; xn--1nd362hy16e.xn--7ib433c; [B1, B2, B3, P1, V6] # ⒐衃Ⴝ.ڂႴ
+9.‌衃Ⴝ.ڂႴ; ; [B1, B2, B3, C1, P1, V6]; 9.xn--1nd159e1y2f.xn--7ib433c; ; 9.xn--1nd9032d.xn--7ib433c; [B1, B2, B3, P1, V6] # 9.衃Ⴝ.ڂႴ
+9.‌衃ⴝ.ڂⴔ; ; [B1, B2, B3, C1]; 9.xn--0ug862cbm5e.xn--7ib268q; ; 9.xn--llj1920a.xn--7ib268q; [B1, B2, B3] # 9.衃ⴝ.ڂⴔ
+9.‌衃Ⴝ.ڂⴔ; ; [B1, B2, B3, C1, P1, V6]; 9.xn--1nd159e1y2f.xn--7ib268q; ; 9.xn--1nd9032d.xn--7ib268q; [B1, B2, B3, P1, V6] # 9.衃Ⴝ.ڂⴔ
+9.xn--1nd9032d.xn--7ib268q; 9.衃Ⴝ.ڂⴔ; [B1, B2, B3, V6]; 9.xn--1nd9032d.xn--7ib268q; ; ; # 9.衃Ⴝ.ڂⴔ
+9.xn--1nd159e1y2f.xn--7ib268q; 9.‌衃Ⴝ.ڂⴔ; [B1, B2, B3, C1, V6]; 9.xn--1nd159e1y2f.xn--7ib268q; ; ; # 9.衃Ⴝ.ڂⴔ
+9.xn--llj1920a.xn--7ib268q; 9.衃ⴝ.ڂⴔ; [B1, B2, B3]; 9.xn--llj1920a.xn--7ib268q; ; ; # 9.衃ⴝ.ڂⴔ
+9.xn--0ug862cbm5e.xn--7ib268q; 9.‌衃ⴝ.ڂⴔ; [B1, B2, B3, C1]; 9.xn--0ug862cbm5e.xn--7ib268q; ; ; # 9.衃ⴝ.ڂⴔ
+9.xn--1nd9032d.xn--7ib433c; 9.衃Ⴝ.ڂႴ; [B1, B2, B3, V6]; 9.xn--1nd9032d.xn--7ib433c; ; ; # 9.衃Ⴝ.ڂႴ
+9.xn--1nd159e1y2f.xn--7ib433c; 9.‌衃Ⴝ.ڂႴ; [B1, B2, B3, C1, V6]; 9.xn--1nd159e1y2f.xn--7ib433c; ; ; # 9.衃Ⴝ.ڂႴ
+⒐‌衃ⴝ.ڂⴔ; ; [B1, B2, B3, C1, P1, V6]; xn--0ugx0px1izu2h.xn--7ib268q; ; xn--1shy52abz3f.xn--7ib268q; [B1, B2, B3, P1, V6] # ⒐衃ⴝ.ڂⴔ
+⒐‌衃Ⴝ.ڂⴔ; ; [B1, B2, B3, C1, P1, V6]; xn--1nd159ecmd785k.xn--7ib268q; ; xn--1nd362hy16e.xn--7ib268q; [B1, B2, B3, P1, V6] # ⒐衃Ⴝ.ڂⴔ
+xn--1nd362hy16e.xn--7ib268q; ⒐衃Ⴝ.ڂⴔ; [B1, B2, B3, V6]; xn--1nd362hy16e.xn--7ib268q; ; ; # ⒐衃Ⴝ.ڂⴔ
+xn--1nd159ecmd785k.xn--7ib268q; ⒐‌衃Ⴝ.ڂⴔ; [B1, B2, B3, C1, V6]; xn--1nd159ecmd785k.xn--7ib268q; ; ; # ⒐衃Ⴝ.ڂⴔ
+xn--1shy52abz3f.xn--7ib268q; ⒐衃ⴝ.ڂⴔ; [B1, B2, B3, V6]; xn--1shy52abz3f.xn--7ib268q; ; ; # ⒐衃ⴝ.ڂⴔ
+xn--0ugx0px1izu2h.xn--7ib268q; ⒐‌衃ⴝ.ڂⴔ; [B1, B2, B3, C1, V6]; xn--0ugx0px1izu2h.xn--7ib268q; ; ; # ⒐衃ⴝ.ڂⴔ
+xn--1nd362hy16e.xn--7ib433c; ⒐衃Ⴝ.ڂႴ; [B1, B2, B3, V6]; xn--1nd362hy16e.xn--7ib433c; ; ; # ⒐衃Ⴝ.ڂႴ
+xn--1nd159ecmd785k.xn--7ib433c; ⒐‌衃Ⴝ.ڂႴ; [B1, B2, B3, C1, V6]; xn--1nd159ecmd785k.xn--7ib433c; ; ; # ⒐衃Ⴝ.ڂႴ
+ߡ‌。--⸬; ߡ‌.--⸬; [B1, B3, C1, V3]; xn--8sb884j.xn-----iw2a; ; xn--8sb.xn-----iw2a; [B1, V3] # ߡ.--⸬
+xn--8sb.xn-----iw2a; ߡ.--⸬; [B1, V3]; xn--8sb.xn-----iw2a; ; ; # ߡ.--⸬
+xn--8sb884j.xn-----iw2a; ߡ‌.--⸬; [B1, B3, C1, V3]; xn--8sb884j.xn-----iw2a; ; ; # ߡ.--⸬
+𞥓.ܘ; 𞥓.ܘ; ; xn--of6h.xn--inb; ; ; # 𞥓.ܘ
+𞥓.ܘ; ; ; xn--of6h.xn--inb; ; ; # 𞥓.ܘ
+xn--of6h.xn--inb; 𞥓.ܘ; ; xn--of6h.xn--inb; ; ; # 𞥓.ܘ
+󠄽-.-්; -.-්; [V3]; -.xn----ptf; ; ; # -.-්
+󠄽-.-්; -.-්; [V3]; -.xn----ptf; ; ; # -.-්
+-.xn----ptf; -.-්; [V3]; -.xn----ptf; ; ; # -.-්
+󠇝ݛ-.ᤧ; ݛ-.ᤧ; [B1, B3, B6, V3, V5]; xn----k4c.xn--lff; ; ; # ݛ-.ᤧ
+xn----k4c.xn--lff; ݛ-.ᤧ; [B1, B3, B6, V3, V5]; xn----k4c.xn--lff; ; ; # ݛ-.ᤧ
+𞤴󠆹⦉𐹺.꠆⒌󘤸; 𞤴⦉𐹺.꠆⒌󘤸; [B1, P1, V5, V6]; xn--fuix729epewf.xn--xsh5029b6e77i; ; ; # 𞤴⦉𐹺.꠆⒌
+𞤴󠆹⦉𐹺.꠆5.󘤸; 𞤴⦉𐹺.꠆5.󘤸; [B1, P1, V5, V6]; xn--fuix729epewf.xn--5-w93e.xn--7b83e; ; ; # 𞤴⦉𐹺.꠆5.
+𞤒󠆹⦉𐹺.꠆5.󘤸; 𞤴⦉𐹺.꠆5.󘤸; [B1, P1, V5, V6]; xn--fuix729epewf.xn--5-w93e.xn--7b83e; ; ; # 𞤴⦉𐹺.꠆5.
+xn--fuix729epewf.xn--5-w93e.xn--7b83e; 𞤴⦉𐹺.꠆5.󘤸; [B1, V5, V6]; xn--fuix729epewf.xn--5-w93e.xn--7b83e; ; ; # 𞤴⦉𐹺.꠆5.
+𞤒󠆹⦉𐹺.꠆⒌󘤸; 𞤴⦉𐹺.꠆⒌󘤸; [B1, P1, V5, V6]; xn--fuix729epewf.xn--xsh5029b6e77i; ; ; # 𞤴⦉𐹺.꠆⒌
+xn--fuix729epewf.xn--xsh5029b6e77i; 𞤴⦉𐹺.꠆⒌󘤸; [B1, V5, V6]; xn--fuix729epewf.xn--xsh5029b6e77i; ; ; # 𞤴⦉𐹺.꠆⒌
+󠄸₀。𑖿‌𐦂‍; 0.𑖿‌𐦂‍; [B1, C2, V5]; 0.xn--0ugc8040p9hk; ; 0.xn--mn9cz2s; [B1, V5] # 0.𑖿𐦂
+󠄸0。𑖿‌𐦂‍; 0.𑖿‌𐦂‍; [B1, C2, V5]; 0.xn--0ugc8040p9hk; ; 0.xn--mn9cz2s; [B1, V5] # 0.𑖿𐦂
+0.xn--mn9cz2s; 0.𑖿𐦂; [B1, V5]; 0.xn--mn9cz2s; ; ; # 0.𑖿𐦂
+0.xn--0ugc8040p9hk; 0.𑖿‌𐦂‍; [B1, C2, V5]; 0.xn--0ugc8040p9hk; ; ; # 0.𑖿𐦂
+Ⴚ𐋸󠄄。𝟝ퟶ်; Ⴚ𐋸.5ퟶ်; [P1, V6]; xn--ynd2415j.xn--5-dug9054m; ; ; # Ⴚ𐋸.5ퟶ်
+Ⴚ𐋸󠄄。5ퟶ်; Ⴚ𐋸.5ퟶ်; [P1, V6]; xn--ynd2415j.xn--5-dug9054m; ; ; # Ⴚ𐋸.5ퟶ်
+ⴚ𐋸󠄄。5ퟶ်; ⴚ𐋸.5ퟶ်; ; xn--ilj2659d.xn--5-dug9054m; ; ; # ⴚ𐋸.5ퟶ်
+xn--ilj2659d.xn--5-dug9054m; ⴚ𐋸.5ퟶ်; ; xn--ilj2659d.xn--5-dug9054m; ; ; # ⴚ𐋸.5ퟶ်
+ⴚ𐋸.5ퟶ်; ; ; xn--ilj2659d.xn--5-dug9054m; ; ; # ⴚ𐋸.5ퟶ်
+Ⴚ𐋸.5ퟶ်; ; [P1, V6]; xn--ynd2415j.xn--5-dug9054m; ; ; # Ⴚ𐋸.5ퟶ်
+xn--ynd2415j.xn--5-dug9054m; Ⴚ𐋸.5ퟶ်; [V6]; xn--ynd2415j.xn--5-dug9054m; ; ; # Ⴚ𐋸.5ퟶ်
+ⴚ𐋸󠄄。𝟝ퟶ်; ⴚ𐋸.5ퟶ်; ; xn--ilj2659d.xn--5-dug9054m; ; ; # ⴚ𐋸.5ퟶ်
+‍-ᠹ﹪.ᷡᤢ; ; [C2, P1, V5, V6]; xn----c6j614b1z4v.xn--gff52t; ; xn----c6jx047j.xn--gff52t; [P1, V3, V5, V6] # -ᠹ﹪.ᷡᤢ
+‍-ᠹ%.ᷡᤢ; ; [C2, P1, V5, V6]; xn---%-u4oy48b.xn--gff52t; ; xn---%-u4o.xn--gff52t; [P1, V3, V5, V6] # -ᠹ%.ᷡᤢ
+xn---%-u4o.xn--gff52t; -ᠹ%.ᷡᤢ; [P1, V3, V5, V6]; xn---%-u4o.xn--gff52t; ; ; # -ᠹ%.ᷡᤢ
+xn---%-u4oy48b.xn--gff52t; ‍-ᠹ%.ᷡᤢ; [C2, P1, V5, V6]; xn---%-u4oy48b.xn--gff52t; ; ; # -ᠹ%.ᷡᤢ
+xn----c6jx047j.xn--gff52t; -ᠹ﹪.ᷡᤢ; [V3, V5, V6]; xn----c6jx047j.xn--gff52t; ; ; # -ᠹ﹪.ᷡᤢ
+xn----c6j614b1z4v.xn--gff52t; ‍-ᠹ﹪.ᷡᤢ; [C2, V5, V6]; xn----c6j614b1z4v.xn--gff52t; ; ; # -ᠹ﹪.ᷡᤢ
+≠.ᠿ; ; [P1, V6]; xn--1ch.xn--y7e; ; ; # ≠.ᠿ
+≠.ᠿ; ≠.ᠿ; [P1, V6]; xn--1ch.xn--y7e; ; ; # ≠.ᠿ
+xn--1ch.xn--y7e; ≠.ᠿ; [V6]; xn--1ch.xn--y7e; ; ; # ≠.ᠿ
+ܣ֣。㌪; ܣ֣.ハイツ; ; xn--ucb18e.xn--eck4c5a; ; ; # ܣ֣.ハイツ
+ܣ֣。ハイツ; ܣ֣.ハイツ; ; xn--ucb18e.xn--eck4c5a; ; ; # ܣ֣.ハイツ
+xn--ucb18e.xn--eck4c5a; ܣ֣.ハイツ; ; xn--ucb18e.xn--eck4c5a; ; ; # ܣ֣.ハイツ
+ܣ֣.ハイツ; ; ; xn--ucb18e.xn--eck4c5a; ; ; # ܣ֣.ハイツ
+𞷥󠆀≮.⵿-; 𞷥≮.⵿-; [B1, B3, P1, V3, V5, V6]; xn--gdhx802p.xn----i2s; ; ; # ≮.⵿-
+𞷥󠆀≮.⵿-; 𞷥≮.⵿-; [B1, B3, P1, V3, V5, V6]; xn--gdhx802p.xn----i2s; ; ; # ≮.⵿-
+xn--gdhx802p.xn----i2s; 𞷥≮.⵿-; [B1, B3, V3, V5, V6]; xn--gdhx802p.xn----i2s; ; ; # ≮.⵿-
+₆榎򦖎്。𞤅ۭﱚ󠮨; 6榎򦖎്.𞤧ۭيي󠮨; [B1, B3, P1, V6]; xn--6-kmf4691ejv41j.xn--mhba10ch545mn8v8h; ; ; # 6榎്.𞤧ۭيي
+6榎򦖎്。𞤅ۭيي󠮨; 6榎򦖎്.𞤧ۭيي󠮨; [B1, B3, P1, V6]; xn--6-kmf4691ejv41j.xn--mhba10ch545mn8v8h; ; ; # 6榎്.𞤧ۭيي
+6榎򦖎്。𞤧ۭيي󠮨; 6榎򦖎്.𞤧ۭيي󠮨; [B1, B3, P1, V6]; xn--6-kmf4691ejv41j.xn--mhba10ch545mn8v8h; ; ; # 6榎്.𞤧ۭيي
+xn--6-kmf4691ejv41j.xn--mhba10ch545mn8v8h; 6榎򦖎്.𞤧ۭيي󠮨; [B1, B3, V6]; xn--6-kmf4691ejv41j.xn--mhba10ch545mn8v8h; ; ; # 6榎്.𞤧ۭيي
+₆榎򦖎്。𞤧ۭﱚ󠮨; 6榎򦖎്.𞤧ۭيي󠮨; [B1, B3, P1, V6]; xn--6-kmf4691ejv41j.xn--mhba10ch545mn8v8h; ; ; # 6榎്.𞤧ۭيي
+𣩫.򌑲; 𣩫.򌑲; [P1, V6]; xn--td3j.xn--4628b; ; ; # 𣩫.
+𣩫.򌑲; ; [P1, V6]; xn--td3j.xn--4628b; ; ; # 𣩫.
+xn--td3j.xn--4628b; 𣩫.򌑲; [V6]; xn--td3j.xn--4628b; ; ; # 𣩫.
+‍︒。ڹ‌; ‍︒.ڹ‌; [B1, B3, C1, C2, P1, V6]; xn--1ug2658f.xn--skb080k; ; xn--y86c.xn--skb; [B1, P1, V6] # ︒.ڹ
+xn--y86c.xn--skb; ︒.ڹ; [B1, V6]; xn--y86c.xn--skb; ; ; # ︒.ڹ
+xn--1ug2658f.xn--skb080k; ‍︒.ڹ‌; [B1, B3, C1, C2, V6]; xn--1ug2658f.xn--skb080k; ; ; # ︒.ڹ
+xn--skb; ڹ; ; xn--skb; ; ; # ڹ
+ڹ; ; ; xn--skb; ; ; # ڹ
+𐹦‌𐹶。; 𐹦‌𐹶.; [B1, C1, P1, V6]; xn--0ug4994goba.xn--sxg; ; xn--eo0d6a.xn--sxg; [B1, P1, V6] # 𐹦𐹶.
+xn--eo0d6a.xn--sxg; 𐹦𐹶.; [B1, V6]; xn--eo0d6a.xn--sxg; ; ; # 𐹦𐹶.
+xn--0ug4994goba.xn--sxg; 𐹦‌𐹶.; [B1, C1, V6]; xn--0ug4994goba.xn--sxg; ; ; # 𐹦𐹶.
+్𝨾֩𝟭。-𑜨; ్𝨾֩1.-𑜨; [V3, V5]; xn--1-rfc312cdp45c.xn----nq0j; ; ; # ్𝨾֩1.-𑜨
+్𝨾֩1。-𑜨; ్𝨾֩1.-𑜨; [V3, V5]; xn--1-rfc312cdp45c.xn----nq0j; ; ; # ్𝨾֩1.-𑜨
+xn--1-rfc312cdp45c.xn----nq0j; ్𝨾֩1.-𑜨; [V3, V5]; xn--1-rfc312cdp45c.xn----nq0j; ; ; # ్𝨾֩1.-𑜨
+򣿈。뙏; 򣿈.뙏; [P1, V6]; xn--ph26c.xn--281b; ; ; # .뙏
+򣿈。뙏; 򣿈.뙏; [P1, V6]; xn--ph26c.xn--281b; ; ; # .뙏
+xn--ph26c.xn--281b; 򣿈.뙏; [V6]; xn--ph26c.xn--281b; ; ; # .뙏
+񕨚󠄌󑽀ᡀ.ࢶ; 񕨚󑽀ᡀ.ࢶ; [P1, V6]; xn--z7e98100evc01b.xn--czb; ; ; # ᡀ.ࢶ
+xn--z7e98100evc01b.xn--czb; 񕨚󑽀ᡀ.ࢶ; [V6]; xn--z7e98100evc01b.xn--czb; ; ; # ᡀ.ࢶ
+‍。񅁛; ‍.񅁛; [C2, P1, V6]; xn--1ug.xn--6x4u; ; .xn--6x4u; [P1, V6, A4_2] # .
+‍。񅁛; ‍.񅁛; [C2, P1, V6]; xn--1ug.xn--6x4u; ; .xn--6x4u; [P1, V6, A4_2] # .
+.xn--6x4u; .񅁛; [V6, X4_2]; .xn--6x4u; [V6, A4_2]; ; # .
+xn--1ug.xn--6x4u; ‍.񅁛; [C2, V6]; xn--1ug.xn--6x4u; ; ; # .
+ࡋ皥.-; ࡋ皥.-; [B1, B2, B3, V3]; xn--9vb4167c.-; ; ; # ࡋ皥.-
+ࡋ皥.-; ; [B1, B2, B3, V3]; xn--9vb4167c.-; ; ; # ࡋ皥.-
+xn--9vb4167c.-; ࡋ皥.-; [B1, B2, B3, V3]; xn--9vb4167c.-; ; ; # ࡋ皥.-
+𐣸̕𐮇.⒈ꡦ; 𐣸̕𐮇.⒈ꡦ; [B1, P1, V6]; xn--5sa9915kgvb.xn--tshw539b; ; ; # ̕𐮇.⒈ꡦ
+𐣸̕𐮇.1.ꡦ; ; [B1, P1, V6]; xn--5sa9915kgvb.1.xn--cd9a; ; ; # ̕𐮇.1.ꡦ
+xn--5sa9915kgvb.1.xn--cd9a; 𐣸̕𐮇.1.ꡦ; [B1, V6]; xn--5sa9915kgvb.1.xn--cd9a; ; ; # ̕𐮇.1.ꡦ
+xn--5sa9915kgvb.xn--tshw539b; 𐣸̕𐮇.⒈ꡦ; [B1, V6]; xn--5sa9915kgvb.xn--tshw539b; ; ; # ̕𐮇.⒈ꡦ
+Ⴛ‌֢‍。ᅠā𐹦; Ⴛ‌֢‍.ᅠā𐹦; [B5, B6, C1, C2, P1, V6]; xn--tcb597cdmmfa.xn--yda9741khjj; ; xn--tcb597c.xn--yda9741khjj; [B5, B6, P1, V6] # Ⴛ֢.ā𐹦
+Ⴛ‌֢‍。ᅠā𐹦; Ⴛ‌֢‍.ᅠā𐹦; [B5, B6, C1, C2, P1, V6]; xn--tcb597cdmmfa.xn--yda9741khjj; ; xn--tcb597c.xn--yda9741khjj; [B5, B6, P1, V6] # Ⴛ֢.ā𐹦
+Ⴛ‌֢‍。ᅠā𐹦; Ⴛ‌֢‍.ᅠā𐹦; [B5, B6, C1, C2, P1, V6]; xn--tcb597cdmmfa.xn--yda594fdn5q; ; xn--tcb597c.xn--yda594fdn5q; [B5, B6, P1, V6] # Ⴛ֢.ā𐹦
+Ⴛ‌֢‍。ᅠā𐹦; Ⴛ‌֢‍.ᅠā𐹦; [B5, B6, C1, C2, P1, V6]; xn--tcb597cdmmfa.xn--yda594fdn5q; ; xn--tcb597c.xn--yda594fdn5q; [B5, B6, P1, V6] # Ⴛ֢.ā𐹦
+ⴛ‌֢‍。ᅠā𐹦; ⴛ‌֢‍.ᅠā𐹦; [B5, B6, C1, C2, P1, V6]; xn--tcb736kea974k.xn--yda594fdn5q; ; xn--tcb323r.xn--yda594fdn5q; [B5, B6, P1, V6] # ⴛ֢.ā𐹦
+ⴛ‌֢‍。ᅠā𐹦; ⴛ‌֢‍.ᅠā𐹦; [B5, B6, C1, C2, P1, V6]; xn--tcb736kea974k.xn--yda594fdn5q; ; xn--tcb323r.xn--yda594fdn5q; [B5, B6, P1, V6] # ⴛ֢.ā𐹦
+Ⴛ‌֢‍。ᅠĀ𐹦; Ⴛ‌֢‍.ᅠā𐹦; [B5, B6, C1, C2, P1, V6]; xn--tcb597cdmmfa.xn--yda594fdn5q; ; xn--tcb597c.xn--yda594fdn5q; [B5, B6, P1, V6] # Ⴛ֢.ā𐹦
+Ⴛ‌֢‍。ᅠĀ𐹦; Ⴛ‌֢‍.ᅠā𐹦; [B5, B6, C1, C2, P1, V6]; xn--tcb597cdmmfa.xn--yda594fdn5q; ; xn--tcb597c.xn--yda594fdn5q; [B5, B6, P1, V6] # Ⴛ֢.ā𐹦
+xn--tcb597c.xn--yda594fdn5q; Ⴛ֢.ᅠā𐹦; [B5, B6, V6]; xn--tcb597c.xn--yda594fdn5q; ; ; # Ⴛ֢.ā𐹦
+xn--tcb597cdmmfa.xn--yda594fdn5q; Ⴛ‌֢‍.ᅠā𐹦; [B5, B6, C1, C2, V6]; xn--tcb597cdmmfa.xn--yda594fdn5q; ; ; # Ⴛ֢.ā𐹦
+xn--tcb323r.xn--yda594fdn5q; ⴛ֢.ᅠā𐹦; [B5, B6, V6]; xn--tcb323r.xn--yda594fdn5q; ; ; # ⴛ֢.ā𐹦
+xn--tcb736kea974k.xn--yda594fdn5q; ⴛ‌֢‍.ᅠā𐹦; [B5, B6, C1, C2, V6]; xn--tcb736kea974k.xn--yda594fdn5q; ; ; # ⴛ֢.ā𐹦
+ⴛ‌֢‍。ᅠā𐹦; ⴛ‌֢‍.ᅠā𐹦; [B5, B6, C1, C2, P1, V6]; xn--tcb736kea974k.xn--yda9741khjj; ; xn--tcb323r.xn--yda9741khjj; [B5, B6, P1, V6] # ⴛ֢.ā𐹦
+ⴛ‌֢‍。ᅠā𐹦; ⴛ‌֢‍.ᅠā𐹦; [B5, B6, C1, C2, P1, V6]; xn--tcb736kea974k.xn--yda9741khjj; ; xn--tcb323r.xn--yda9741khjj; [B5, B6, P1, V6] # ⴛ֢.ā𐹦
+Ⴛ‌֢‍。ᅠĀ𐹦; Ⴛ‌֢‍.ᅠā𐹦; [B5, B6, C1, C2, P1, V6]; xn--tcb597cdmmfa.xn--yda9741khjj; ; xn--tcb597c.xn--yda9741khjj; [B5, B6, P1, V6] # Ⴛ֢.ā𐹦
+Ⴛ‌֢‍。ᅠĀ𐹦; Ⴛ‌֢‍.ᅠā𐹦; [B5, B6, C1, C2, P1, V6]; xn--tcb597cdmmfa.xn--yda9741khjj; ; xn--tcb597c.xn--yda9741khjj; [B5, B6, P1, V6] # Ⴛ֢.ā𐹦
+xn--tcb597c.xn--yda9741khjj; Ⴛ֢.ᅠā𐹦; [B5, B6, V6]; xn--tcb597c.xn--yda9741khjj; ; ; # Ⴛ֢.ā𐹦
+xn--tcb597cdmmfa.xn--yda9741khjj; Ⴛ‌֢‍.ᅠā𐹦; [B5, B6, C1, C2, V6]; xn--tcb597cdmmfa.xn--yda9741khjj; ; ; # Ⴛ֢.ā𐹦
+xn--tcb323r.xn--yda9741khjj; ⴛ֢.ᅠā𐹦; [B5, B6, V6]; xn--tcb323r.xn--yda9741khjj; ; ; # ⴛ֢.ā𐹦
+xn--tcb736kea974k.xn--yda9741khjj; ⴛ‌֢‍.ᅠā𐹦; [B5, B6, C1, C2, V6]; xn--tcb736kea974k.xn--yda9741khjj; ; ; # ⴛ֢.ā𐹦
+‌。曳⾑𐋰≯; ‌.曳襾𐋰≯; [C1, P1, V6]; xn--0ug2139f.xn--hdh501y8wvfs5h; ; xn--vn7c.xn--hdh501y8wvfs5h; [P1, V6] # .曳襾𐋰≯
+‌。曳⾑𐋰≯; ‌.曳襾𐋰≯; [C1, P1, V6]; xn--0ug2139f.xn--hdh501y8wvfs5h; ; xn--vn7c.xn--hdh501y8wvfs5h; [P1, V6] # .曳襾𐋰≯
+‌。曳襾𐋰≯; ‌.曳襾𐋰≯; [C1, P1, V6]; xn--0ug2139f.xn--hdh501y8wvfs5h; ; xn--vn7c.xn--hdh501y8wvfs5h; [P1, V6] # .曳襾𐋰≯
+‌。曳襾𐋰≯; ‌.曳襾𐋰≯; [C1, P1, V6]; xn--0ug2139f.xn--hdh501y8wvfs5h; ; xn--vn7c.xn--hdh501y8wvfs5h; [P1, V6] # .曳襾𐋰≯
+xn--vn7c.xn--hdh501y8wvfs5h; .曳襾𐋰≯; [V6]; xn--vn7c.xn--hdh501y8wvfs5h; ; ; # .曳襾𐋰≯
+xn--0ug2139f.xn--hdh501y8wvfs5h; ‌.曳襾𐋰≯; [C1, V6]; xn--0ug2139f.xn--hdh501y8wvfs5h; ; ; # .曳襾𐋰≯
+≯⒈。ß; ≯⒈.ß; [P1, V6]; xn--hdh84f.xn--zca; ; xn--hdh84f.ss; # ≯⒈.ß
+≯⒈。ß; ≯⒈.ß; [P1, V6]; xn--hdh84f.xn--zca; ; xn--hdh84f.ss; # ≯⒈.ß
+≯1.。ß; ≯1..ß; [P1, V6, X4_2]; xn--1-ogo..xn--zca; [P1, V6, A4_2]; xn--1-ogo..ss; # ≯1..ß
+≯1.。ß; ≯1..ß; [P1, V6, X4_2]; xn--1-ogo..xn--zca; [P1, V6, A4_2]; xn--1-ogo..ss; # ≯1..ß
+≯1.。SS; ≯1..ss; [P1, V6, X4_2]; xn--1-ogo..ss; [P1, V6, A4_2]; ; # ≯1..ss
+≯1.。SS; ≯1..ss; [P1, V6, X4_2]; xn--1-ogo..ss; [P1, V6, A4_2]; ; # ≯1..ss
+≯1.。ss; ≯1..ss; [P1, V6, X4_2]; xn--1-ogo..ss; [P1, V6, A4_2]; ; # ≯1..ss
+≯1.。ss; ≯1..ss; [P1, V6, X4_2]; xn--1-ogo..ss; [P1, V6, A4_2]; ; # ≯1..ss
+≯1.。Ss; ≯1..ss; [P1, V6, X4_2]; xn--1-ogo..ss; [P1, V6, A4_2]; ; # ≯1..ss
+≯1.。Ss; ≯1..ss; [P1, V6, X4_2]; xn--1-ogo..ss; [P1, V6, A4_2]; ; # ≯1..ss
+xn--1-ogo..ss; ≯1..ss; [V6, X4_2]; xn--1-ogo..ss; [V6, A4_2]; ; # ≯1..ss
+xn--1-ogo..xn--zca; ≯1..ß; [V6, X4_2]; xn--1-ogo..xn--zca; [V6, A4_2]; ; # ≯1..ß
+≯⒈。SS; ≯⒈.ss; [P1, V6]; xn--hdh84f.ss; ; ; # ≯⒈.ss
+≯⒈。SS; ≯⒈.ss; [P1, V6]; xn--hdh84f.ss; ; ; # ≯⒈.ss
+≯⒈。ss; ≯⒈.ss; [P1, V6]; xn--hdh84f.ss; ; ; # ≯⒈.ss
+≯⒈。ss; ≯⒈.ss; [P1, V6]; xn--hdh84f.ss; ; ; # ≯⒈.ss
+≯⒈。Ss; ≯⒈.ss; [P1, V6]; xn--hdh84f.ss; ; ; # ≯⒈.ss
+≯⒈。Ss; ≯⒈.ss; [P1, V6]; xn--hdh84f.ss; ; ; # ≯⒈.ss
+xn--hdh84f.ss; ≯⒈.ss; [V6]; xn--hdh84f.ss; ; ; # ≯⒈.ss
+xn--hdh84f.xn--zca; ≯⒈.ß; [V6]; xn--hdh84f.xn--zca; ; ; # ≯⒈.ß
+٧‍ﮖ。ߚ-₆Ⴙ; ٧‍ڳ.ߚ-6Ⴙ; [B1, B2, B3, C2, P1, V6]; xn--gib6m343e.xn---6-lve002g; ; xn--gib6m.xn---6-lve002g; [B1, B2, B3, P1, V6] # ٧ڳ.ߚ-6Ⴙ
+٧‍ڳ。ߚ-6Ⴙ; ٧‍ڳ.ߚ-6Ⴙ; [B1, B2, B3, C2, P1, V6]; xn--gib6m343e.xn---6-lve002g; ; xn--gib6m.xn---6-lve002g; [B1, B2, B3, P1, V6] # ٧ڳ.ߚ-6Ⴙ
+٧‍ڳ。ߚ-6ⴙ; ٧‍ڳ.ߚ-6ⴙ; [B1, B2, B3, C2]; xn--gib6m343e.xn---6-lve6529a; ; xn--gib6m.xn---6-lve6529a; [B1, B2, B3] # ٧ڳ.ߚ-6ⴙ
+xn--gib6m.xn---6-lve6529a; ٧ڳ.ߚ-6ⴙ; [B1, B2, B3]; xn--gib6m.xn---6-lve6529a; ; ; # ٧ڳ.ߚ-6ⴙ
+xn--gib6m343e.xn---6-lve6529a; ٧‍ڳ.ߚ-6ⴙ; [B1, B2, B3, C2]; xn--gib6m343e.xn---6-lve6529a; ; ; # ٧ڳ.ߚ-6ⴙ
+xn--gib6m.xn---6-lve002g; ٧ڳ.ߚ-6Ⴙ; [B1, B2, B3, V6]; xn--gib6m.xn---6-lve002g; ; ; # ٧ڳ.ߚ-6Ⴙ
+xn--gib6m343e.xn---6-lve002g; ٧‍ڳ.ߚ-6Ⴙ; [B1, B2, B3, C2, V6]; xn--gib6m343e.xn---6-lve002g; ; ; # ٧ڳ.ߚ-6Ⴙ
+٧‍ﮖ。ߚ-₆ⴙ; ٧‍ڳ.ߚ-6ⴙ; [B1, B2, B3, C2]; xn--gib6m343e.xn---6-lve6529a; ; xn--gib6m.xn---6-lve6529a; [B1, B2, B3] # ٧ڳ.ߚ-6ⴙ
+‌。≠; ‌.≠; [C1, P1, V6]; xn--0ug.xn--1ch; ; .xn--1ch; [P1, V6, A4_2] # .≠
+‌。≠; ‌.≠; [C1, P1, V6]; xn--0ug.xn--1ch; ; .xn--1ch; [P1, V6, A4_2] # .≠
+‌。≠; ‌.≠; [C1, P1, V6]; xn--0ug.xn--1ch; ; .xn--1ch; [P1, V6, A4_2] # .≠
+‌。≠; ‌.≠; [C1, P1, V6]; xn--0ug.xn--1ch; ; .xn--1ch; [P1, V6, A4_2] # .≠
+.xn--1ch; .≠; [V6, X4_2]; .xn--1ch; [V6, A4_2]; ; # .≠
+xn--0ug.xn--1ch; ‌.≠; [C1, V6]; xn--0ug.xn--1ch; ; ; # .≠
+𑖿𝨔.ᡟ𑖿ᭂ‌; ; [C1, V5]; xn--461dw464a.xn--v8e29ldzfo952a; ; xn--461dw464a.xn--v8e29loy65a; [V5] # 𑖿𝨔.ᡟ𑖿ᭂ
+xn--461dw464a.xn--v8e29loy65a; 𑖿𝨔.ᡟ𑖿ᭂ; [V5]; xn--461dw464a.xn--v8e29loy65a; ; ; # 𑖿𝨔.ᡟ𑖿ᭂ
+xn--461dw464a.xn--v8e29ldzfo952a; 𑖿𝨔.ᡟ𑖿ᭂ‌; [C1, V5]; xn--461dw464a.xn--v8e29ldzfo952a; ; ; # 𑖿𝨔.ᡟ𑖿ᭂ
+򔣳‍򑝱.𖬴Ↄ≠-; ; [C2, P1, V3, V5, V6]; xn--1ug15151gkb5a.xn----61n81bt713h; ; xn--6j00chy9a.xn----61n81bt713h; [P1, V3, V5, V6] # .𖬴Ↄ≠-
+򔣳‍򑝱.𖬴Ↄ≠-; 򔣳‍򑝱.𖬴Ↄ≠-; [C2, P1, V3, V5, V6]; xn--1ug15151gkb5a.xn----61n81bt713h; ; xn--6j00chy9a.xn----61n81bt713h; [P1, V3, V5, V6] # .𖬴Ↄ≠-
+򔣳‍򑝱.𖬴ↄ≠-; 򔣳‍򑝱.𖬴ↄ≠-; [C2, P1, V3, V5, V6]; xn--1ug15151gkb5a.xn----81n51bt713h; ; xn--6j00chy9a.xn----81n51bt713h; [P1, V3, V5, V6] # .𖬴ↄ≠-
+򔣳‍򑝱.𖬴ↄ≠-; ; [C2, P1, V3, V5, V6]; xn--1ug15151gkb5a.xn----81n51bt713h; ; xn--6j00chy9a.xn----81n51bt713h; [P1, V3, V5, V6] # .𖬴ↄ≠-
+xn--6j00chy9a.xn----81n51bt713h; 򔣳򑝱.𖬴ↄ≠-; [V3, V5, V6]; xn--6j00chy9a.xn----81n51bt713h; ; ; # .𖬴ↄ≠-
+xn--1ug15151gkb5a.xn----81n51bt713h; 򔣳‍򑝱.𖬴ↄ≠-; [C2, V3, V5, V6]; xn--1ug15151gkb5a.xn----81n51bt713h; ; ; # .𖬴ↄ≠-
+xn--6j00chy9a.xn----61n81bt713h; 򔣳򑝱.𖬴Ↄ≠-; [V3, V5, V6]; xn--6j00chy9a.xn----61n81bt713h; ; ; # .𖬴Ↄ≠-
+xn--1ug15151gkb5a.xn----61n81bt713h; 򔣳‍򑝱.𖬴Ↄ≠-; [C2, V3, V5, V6]; xn--1ug15151gkb5a.xn----61n81bt713h; ; ; # .𖬴Ↄ≠-
+ߢς‍𝟳。蔑򛖢; ߢς‍7.蔑򛖢; [B2, C2, P1, V6]; xn--7-xmb182aez5a.xn--wy1ao4929b; ; xn--7-zmb872a.xn--wy1ao4929b; [B2, P1, V6] # ߢς7.蔑
+ߢς‍7。蔑򛖢; ߢς‍7.蔑򛖢; [B2, C2, P1, V6]; xn--7-xmb182aez5a.xn--wy1ao4929b; ; xn--7-zmb872a.xn--wy1ao4929b; [B2, P1, V6] # ߢς7.蔑
+ߢΣ‍7。蔑򛖢; ߢσ‍7.蔑򛖢; [B2, C2, P1, V6]; xn--7-zmb872aez5a.xn--wy1ao4929b; ; xn--7-zmb872a.xn--wy1ao4929b; [B2, P1, V6] # ߢσ7.蔑
+ߢσ‍7。蔑򛖢; ߢσ‍7.蔑򛖢; [B2, C2, P1, V6]; xn--7-zmb872aez5a.xn--wy1ao4929b; ; xn--7-zmb872a.xn--wy1ao4929b; [B2, P1, V6] # ߢσ7.蔑
+xn--7-zmb872a.xn--wy1ao4929b; ߢσ7.蔑򛖢; [B2, V6]; xn--7-zmb872a.xn--wy1ao4929b; ; ; # ߢσ7.蔑
+xn--7-zmb872aez5a.xn--wy1ao4929b; ߢσ‍7.蔑򛖢; [B2, C2, V6]; xn--7-zmb872aez5a.xn--wy1ao4929b; ; ; # ߢσ7.蔑
+xn--7-xmb182aez5a.xn--wy1ao4929b; ߢς‍7.蔑򛖢; [B2, C2, V6]; xn--7-xmb182aez5a.xn--wy1ao4929b; ; ; # ߢς7.蔑
+ߢΣ‍𝟳。蔑򛖢; ߢσ‍7.蔑򛖢; [B2, C2, P1, V6]; xn--7-zmb872aez5a.xn--wy1ao4929b; ; xn--7-zmb872a.xn--wy1ao4929b; [B2, P1, V6] # ߢσ7.蔑
+ߢσ‍𝟳。蔑򛖢; ߢσ‍7.蔑򛖢; [B2, C2, P1, V6]; xn--7-zmb872aez5a.xn--wy1ao4929b; ; xn--7-zmb872a.xn--wy1ao4929b; [B2, P1, V6] # ߢσ7.蔑
+𐹰.؀; ; [B1, P1, V6]; xn--oo0d.xn--ifb; ; ; # 𐹰.
+xn--oo0d.xn--ifb; 𐹰.؀; [B1, V6]; xn--oo0d.xn--ifb; ; ; # 𐹰.
+-ࢨ.𱠖; ; [B1, P1, V3, V6]; xn----mod.xn--5o9n; ; ; # -ࢨ.
+xn----mod.xn--5o9n; -ࢨ.𱠖; [B1, V3, V6]; xn----mod.xn--5o9n; ; ; # -ࢨ.
+≯𞱸󠇀。誆⒈; ≯𞱸.誆⒈; [B1, P1, V6]; xn--hdh7151p.xn--tsh1248a; ; ; # ≯𞱸.誆⒈
+≯𞱸󠇀。誆⒈; ≯𞱸.誆⒈; [B1, P1, V6]; xn--hdh7151p.xn--tsh1248a; ; ; # ≯𞱸.誆⒈
+≯𞱸󠇀。誆1.; ≯𞱸.誆1.; [B1, P1, V6]; xn--hdh7151p.xn--1-dy1d.; ; ; # ≯𞱸.誆1.
+≯𞱸󠇀。誆1.; ≯𞱸.誆1.; [B1, P1, V6]; xn--hdh7151p.xn--1-dy1d.; ; ; # ≯𞱸.誆1.
+xn--hdh7151p.xn--1-dy1d.; ≯𞱸.誆1.; [B1, V6]; xn--hdh7151p.xn--1-dy1d.; ; ; # ≯𞱸.誆1.
+xn--hdh7151p.xn--tsh1248a; ≯𞱸.誆⒈; [B1, V6]; xn--hdh7151p.xn--tsh1248a; ; ; # ≯𞱸.誆⒈
+ؖ𞥙䐊ِ.︒م↺ڜ; ؖ𞥙䐊ِ.︒م↺ڜ; [B1, P1, V5, V6]; xn--4fb0j490qjg4x.xn--hhb8o948euo5r; ; ; # ؖ𞥙䐊ِ.︒م↺ڜ
+ؖ𞥙䐊ِ.。م↺ڜ; ؖ𞥙䐊ِ..م↺ڜ; [B1, V5, X4_2]; xn--4fb0j490qjg4x..xn--hhb8o948e; [B1, V5, A4_2]; ; # ؖ𞥙䐊ِ..م↺ڜ
+xn--4fb0j490qjg4x..xn--hhb8o948e; ؖ𞥙䐊ِ..م↺ڜ; [B1, V5, X4_2]; xn--4fb0j490qjg4x..xn--hhb8o948e; [B1, V5, A4_2]; ; # ؖ𞥙䐊ِ..م↺ڜ
+xn--4fb0j490qjg4x.xn--hhb8o948euo5r; ؖ𞥙䐊ِ.︒م↺ڜ; [B1, V5, V6]; xn--4fb0j490qjg4x.xn--hhb8o948euo5r; ; ; # ؖ𞥙䐊ِ.︒م↺ڜ
+퀬-?񶳒.‌ૅ󩸤۴; ; [C1, P1, V6]; xn---?-6g4k75207c.xn--hmb76q48y18505a; ; xn---?-6g4k75207c.xn--hmb76q74166b; [P1, V5, V6] # 퀬-?.ૅ۴
+퀬-?񶳒.‌ૅ󩸤۴; 퀬-?񶳒.‌ૅ󩸤۴; [C1, P1, V6]; xn---?-6g4k75207c.xn--hmb76q48y18505a; ; xn---?-6g4k75207c.xn--hmb76q74166b; [P1, V5, V6] # 퀬-?.ૅ۴
+xn---?-6g4k75207c.xn--hmb76q74166b; 퀬-?񶳒.ૅ󩸤۴; [P1, V5, V6]; xn---?-6g4k75207c.xn--hmb76q74166b; ; ; # 퀬-?.ૅ۴
+xn---?-6g4k75207c.xn--hmb76q48y18505a; 퀬-?񶳒.‌ૅ󩸤۴; [C1, P1, V6]; xn---?-6g4k75207c.xn--hmb76q48y18505a; ; ; # 퀬-?.ૅ۴
+퀬-?񶳒.xn--hmb76q74166b; 퀬-?񶳒.ૅ󩸤۴; [P1, V5, V6]; xn---?-6g4k75207c.xn--hmb76q74166b; ; ; # 퀬-?.ૅ۴
+퀬-?񶳒.xn--hmb76q74166b; 퀬-?񶳒.ૅ󩸤۴; [P1, V5, V6]; xn---?-6g4k75207c.xn--hmb76q74166b; ; ; # 퀬-?.ૅ۴
+퀬-?񶳒.XN--HMB76Q74166B; 퀬-?񶳒.ૅ󩸤۴; [P1, V5, V6]; xn---?-6g4k75207c.xn--hmb76q74166b; ; ; # 퀬-?.ૅ۴
+퀬-?񶳒.XN--HMB76Q74166B; 퀬-?񶳒.ૅ󩸤۴; [P1, V5, V6]; xn---?-6g4k75207c.xn--hmb76q74166b; ; ; # 퀬-?.ૅ۴
+퀬-?񶳒.Xn--Hmb76q74166b; 퀬-?񶳒.ૅ󩸤۴; [P1, V5, V6]; xn---?-6g4k75207c.xn--hmb76q74166b; ; ; # 퀬-?.ૅ۴
+퀬-?񶳒.Xn--Hmb76q74166b; 퀬-?񶳒.ૅ󩸤۴; [P1, V5, V6]; xn---?-6g4k75207c.xn--hmb76q74166b; ; ; # 퀬-?.ૅ۴
+퀬-?񶳒.xn--hmb76q48y18505a; 퀬-?񶳒.‌ૅ󩸤۴; [C1, P1, V6]; xn---?-6g4k75207c.xn--hmb76q48y18505a; ; ; # 퀬-?.ૅ۴
+퀬-?񶳒.xn--hmb76q48y18505a; 퀬-?񶳒.‌ૅ󩸤۴; [C1, P1, V6]; xn---?-6g4k75207c.xn--hmb76q48y18505a; ; ; # 퀬-?.ૅ۴
+퀬-?񶳒.XN--HMB76Q48Y18505A; 퀬-?񶳒.‌ૅ󩸤۴; [C1, P1, V6]; xn---?-6g4k75207c.xn--hmb76q48y18505a; ; ; # 퀬-?.ૅ۴
+퀬-?񶳒.XN--HMB76Q48Y18505A; 퀬-?񶳒.‌ૅ󩸤۴; [C1, P1, V6]; xn---?-6g4k75207c.xn--hmb76q48y18505a; ; ; # 퀬-?.ૅ۴
+퀬-?񶳒.Xn--Hmb76q48y18505a; 퀬-?񶳒.‌ૅ󩸤۴; [C1, P1, V6]; xn---?-6g4k75207c.xn--hmb76q48y18505a; ; ; # 퀬-?.ૅ۴
+퀬-?񶳒.Xn--Hmb76q48y18505a; 퀬-?񶳒.‌ૅ󩸤۴; [C1, P1, V6]; xn---?-6g4k75207c.xn--hmb76q48y18505a; ; ; # 퀬-?.ૅ۴
+Ⴌ.𐹾︒𑁿𞾄; ; [B1, P1, V6]; xn--knd.xn--y86c030a9ob6374b; ; ; # Ⴌ.𐹾︒𑁿
+Ⴌ.𐹾。𑁿𞾄; Ⴌ.𐹾.𑁿𞾄; [B1, P1, V5, V6]; xn--knd.xn--2o0d.xn--q30dg029a; ; ; # Ⴌ.𐹾.𑁿
+ⴌ.𐹾。𑁿𞾄; ⴌ.𐹾.𑁿𞾄; [B1, P1, V5, V6]; xn--3kj.xn--2o0d.xn--q30dg029a; ; ; # ⴌ.𐹾.𑁿
+xn--3kj.xn--2o0d.xn--q30dg029a; ⴌ.𐹾.𑁿𞾄; [B1, V5, V6]; xn--3kj.xn--2o0d.xn--q30dg029a; ; ; # ⴌ.𐹾.𑁿
+xn--knd.xn--2o0d.xn--q30dg029a; Ⴌ.𐹾.𑁿𞾄; [B1, V5, V6]; xn--knd.xn--2o0d.xn--q30dg029a; ; ; # Ⴌ.𐹾.𑁿
+ⴌ.𐹾︒𑁿𞾄; ; [B1, P1, V6]; xn--3kj.xn--y86c030a9ob6374b; ; ; # ⴌ.𐹾︒𑁿
+xn--3kj.xn--y86c030a9ob6374b; ⴌ.𐹾︒𑁿𞾄; [B1, V6]; xn--3kj.xn--y86c030a9ob6374b; ; ; # ⴌ.𐹾︒𑁿
+xn--knd.xn--y86c030a9ob6374b; Ⴌ.𐹾︒𑁿𞾄; [B1, V6]; xn--knd.xn--y86c030a9ob6374b; ; ; # Ⴌ.𐹾︒𑁿
+񧞿╏。𞩕󠁾; 񧞿╏.𞩕󠁾; [B3, B6, P1, V6]; xn--iyh90030d.xn--1m6hs0260c; ; ; # ╏.
+xn--iyh90030d.xn--1m6hs0260c; 񧞿╏.𞩕󠁾; [B3, B6, V6]; xn--iyh90030d.xn--1m6hs0260c; ; ; # ╏.
+‍┮󠇐.ఀ్᜴‍; ‍┮.ఀ్᜴‍; [C2, V5]; xn--1ug04r.xn--eoc8m432a40i; ; xn--kxh.xn--eoc8m432a; [V5] # ┮.ఀ్᜴
+‍┮󠇐.ఀ్᜴‍; ‍┮.ఀ్᜴‍; [C2, V5]; xn--1ug04r.xn--eoc8m432a40i; ; xn--kxh.xn--eoc8m432a; [V5] # ┮.ఀ్᜴
+xn--kxh.xn--eoc8m432a; ┮.ఀ్᜴; [V5]; xn--kxh.xn--eoc8m432a; ; ; # ┮.ఀ్᜴
+xn--1ug04r.xn--eoc8m432a40i; ‍┮.ఀ్᜴‍; [C2, V5]; xn--1ug04r.xn--eoc8m432a40i; ; ; # ┮.ఀ్᜴
+򹚪。🄂; 򹚪.🄂; [P1, V6]; xn--n433d.xn--v07h; ; ; # .🄂
+򹚪。1,; 򹚪.1,; [P1, V6]; xn--n433d.1,; ; ; # .1,
+xn--n433d.1,; 򹚪.1,; [P1, V6]; xn--n433d.1,; ; ; # .1,
+xn--n433d.xn--v07h; 򹚪.🄂; [V6]; xn--n433d.xn--v07h; ; ; # .🄂
+𑍨刍.🛦; ; [V5]; xn--rbry728b.xn--y88h; ; ; # 𑍨刍.🛦
+xn--rbry728b.xn--y88h; 𑍨刍.🛦; [V5]; xn--rbry728b.xn--y88h; ; ; # 𑍨刍.🛦
+󠌏3。ᯱ𝟒; 󠌏3.ᯱ4; [P1, V5, V6]; xn--3-ib31m.xn--4-pql; ; ; # 3.ᯱ4
+󠌏3。ᯱ4; 󠌏3.ᯱ4; [P1, V5, V6]; xn--3-ib31m.xn--4-pql; ; ; # 3.ᯱ4
+xn--3-ib31m.xn--4-pql; 󠌏3.ᯱ4; [V5, V6]; xn--3-ib31m.xn--4-pql; ; ; # 3.ᯱ4
+ڇ6Ⴔ辘.ﴢڇ‌; ڇ6Ⴔ辘.صيڇ‌; [B2, B3, C1, P1, V6]; xn--6-gsc039eqq6k.xn--0gb6bxkx18g; ; xn--6-gsc039eqq6k.xn--0gb6bxk; [B2, B3, P1, V6] # ڇ6Ⴔ辘.صيڇ
+ڇ6Ⴔ辘.صيڇ‌; ; [B2, B3, C1, P1, V6]; xn--6-gsc039eqq6k.xn--0gb6bxkx18g; ; xn--6-gsc039eqq6k.xn--0gb6bxk; [B2, B3, P1, V6] # ڇ6Ⴔ辘.صيڇ
+ڇ6ⴔ辘.صيڇ‌; ; [B2, B3, C1]; xn--6-gsc2270akm6f.xn--0gb6bxkx18g; ; xn--6-gsc2270akm6f.xn--0gb6bxk; [B2, B3] # ڇ6ⴔ辘.صيڇ
+xn--6-gsc2270akm6f.xn--0gb6bxk; ڇ6ⴔ辘.صيڇ; [B2, B3]; xn--6-gsc2270akm6f.xn--0gb6bxk; ; ; # ڇ6ⴔ辘.صيڇ
+xn--6-gsc2270akm6f.xn--0gb6bxkx18g; ڇ6ⴔ辘.صيڇ‌; [B2, B3, C1]; xn--6-gsc2270akm6f.xn--0gb6bxkx18g; ; ; # ڇ6ⴔ辘.صيڇ
+xn--6-gsc039eqq6k.xn--0gb6bxk; ڇ6Ⴔ辘.صيڇ; [B2, B3, V6]; xn--6-gsc039eqq6k.xn--0gb6bxk; ; ; # ڇ6Ⴔ辘.صيڇ
+xn--6-gsc039eqq6k.xn--0gb6bxkx18g; ڇ6Ⴔ辘.صيڇ‌; [B2, B3, C1, V6]; xn--6-gsc039eqq6k.xn--0gb6bxkx18g; ; ; # ڇ6Ⴔ辘.صيڇ
+ڇ6ⴔ辘.ﴢڇ‌; ڇ6ⴔ辘.صيڇ‌; [B2, B3, C1]; xn--6-gsc2270akm6f.xn--0gb6bxkx18g; ; xn--6-gsc2270akm6f.xn--0gb6bxk; [B2, B3] # ڇ6ⴔ辘.صيڇ
+󠄍.𐮭𞰬򻫞۹; .𐮭𞰬򻫞۹; [B2, P1, V6, X4_2]; .xn--mmb3954kd0uf1zx7f; [B2, P1, V6, A4_2]; ; # .𐮭۹
+.xn--mmb3954kd0uf1zx7f; .𐮭𞰬򻫞۹; [B2, V6, X4_2]; .xn--mmb3954kd0uf1zx7f; [B2, V6, A4_2]; ; # .𐮭۹
+꡽≯.򻲀򒳄; ꡽≯.򻲀򒳄; [P1, V6]; xn--hdh8193c.xn--5z40cp629b; ; ; # ≯.
+꡽≯.򻲀򒳄; ꡽≯.򻲀򒳄; [P1, V6]; xn--hdh8193c.xn--5z40cp629b; ; ; # ≯.
+꡽≯.򻲀򒳄; ; [P1, V6]; xn--hdh8193c.xn--5z40cp629b; ; ; # ≯.
+꡽≯.򻲀򒳄; ꡽≯.򻲀򒳄; [P1, V6]; xn--hdh8193c.xn--5z40cp629b; ; ; # ≯.
+xn--hdh8193c.xn--5z40cp629b; ꡽≯.򻲀򒳄; [V6]; xn--hdh8193c.xn--5z40cp629b; ; ; # ≯.
+ςოٻ.ςܔ; ; [B5, B6]; xn--3xa80l26n.xn--3xa41o; ; xn--4xa60l26n.xn--4xa21o; # ςოٻ.ςܔ
+ΣᲝٻ.Σܔ; σოٻ.σܔ; [B5, B6]; xn--4xa60l26n.xn--4xa21o; ; ; # σოٻ.σܔ
+σოٻ.σܔ; ; [B5, B6]; xn--4xa60l26n.xn--4xa21o; ; ; # σოٻ.σܔ
+Σოٻ.σܔ; σოٻ.σܔ; [B5, B6]; xn--4xa60l26n.xn--4xa21o; ; ; # σოٻ.σܔ
+xn--4xa60l26n.xn--4xa21o; σოٻ.σܔ; [B5, B6]; xn--4xa60l26n.xn--4xa21o; ; ; # σოٻ.σܔ
+Σოٻ.ςܔ; σოٻ.ςܔ; [B5, B6]; xn--4xa60l26n.xn--3xa41o; ; xn--4xa60l26n.xn--4xa21o; # σოٻ.ςܔ
+σოٻ.ςܔ; ; [B5, B6]; xn--4xa60l26n.xn--3xa41o; ; xn--4xa60l26n.xn--4xa21o; # σოٻ.ςܔ
+xn--4xa60l26n.xn--3xa41o; σოٻ.ςܔ; [B5, B6]; xn--4xa60l26n.xn--3xa41o; ; ; # σოٻ.ςܔ
+xn--3xa80l26n.xn--3xa41o; ςოٻ.ςܔ; [B5, B6]; xn--3xa80l26n.xn--3xa41o; ; ; # ςოٻ.ςܔ
+Σოٻ.Σܔ; σოٻ.σܔ; [B5, B6]; xn--4xa60l26n.xn--4xa21o; ; ; # σოٻ.σܔ
+򄖚݈𠄯ݟ。󠛩; 򄖚݈𠄯ݟ.󠛩; [B1, B5, B6, P1, V6]; xn--vob0c4369twfv8b.xn--kl46e; ; ; # ݈𠄯ݟ.
+򄖚݈𠄯ݟ。󠛩; 򄖚݈𠄯ݟ.󠛩; [B1, B5, B6, P1, V6]; xn--vob0c4369twfv8b.xn--kl46e; ; ; # ݈𠄯ݟ.
+xn--vob0c4369twfv8b.xn--kl46e; 򄖚݈𠄯ݟ.󠛩; [B1, B5, B6, V6]; xn--vob0c4369twfv8b.xn--kl46e; ; ; # ݈𠄯ݟ.
+󠳛.‍䤫≠Ⴞ; 󠳛.‍䤫≠Ⴞ; [C2, P1, V6]; xn--1t56e.xn--2nd159e9vb743e; ; xn--1t56e.xn--2nd141ghl2a; [P1, V6] # .䤫≠Ⴞ
+󠳛.‍䤫≠Ⴞ; 󠳛.‍䤫≠Ⴞ; [C2, P1, V6]; xn--1t56e.xn--2nd159e9vb743e; ; xn--1t56e.xn--2nd141ghl2a; [P1, V6] # .䤫≠Ⴞ
+󠳛.‍䤫≠Ⴞ; ; [C2, P1, V6]; xn--1t56e.xn--2nd159e9vb743e; ; xn--1t56e.xn--2nd141ghl2a; [P1, V6] # .䤫≠Ⴞ
+󠳛.‍䤫≠Ⴞ; 󠳛.‍䤫≠Ⴞ; [C2, P1, V6]; xn--1t56e.xn--2nd159e9vb743e; ; xn--1t56e.xn--2nd141ghl2a; [P1, V6] # .䤫≠Ⴞ
+󠳛.‍䤫≠ⴞ; 󠳛.‍䤫≠ⴞ; [C2, P1, V6]; xn--1t56e.xn--1ug73gzzpwi3a; ; xn--1t56e.xn--1ch153bqvw; [P1, V6] # .䤫≠ⴞ
+󠳛.‍䤫≠ⴞ; ; [C2, P1, V6]; xn--1t56e.xn--1ug73gzzpwi3a; ; xn--1t56e.xn--1ch153bqvw; [P1, V6] # .䤫≠ⴞ
+xn--1t56e.xn--1ch153bqvw; 󠳛.䤫≠ⴞ; [V6]; xn--1t56e.xn--1ch153bqvw; ; ; # .䤫≠ⴞ
+xn--1t56e.xn--1ug73gzzpwi3a; 󠳛.‍䤫≠ⴞ; [C2, V6]; xn--1t56e.xn--1ug73gzzpwi3a; ; ; # .䤫≠ⴞ
+xn--1t56e.xn--2nd141ghl2a; 󠳛.䤫≠Ⴞ; [V6]; xn--1t56e.xn--2nd141ghl2a; ; ; # .䤫≠Ⴞ
+xn--1t56e.xn--2nd159e9vb743e; 󠳛.‍䤫≠Ⴞ; [C2, V6]; xn--1t56e.xn--2nd159e9vb743e; ; ; # .䤫≠Ⴞ
+󠳛.‍䤫≠ⴞ; 󠳛.‍䤫≠ⴞ; [C2, P1, V6]; xn--1t56e.xn--1ug73gzzpwi3a; ; xn--1t56e.xn--1ch153bqvw; [P1, V6] # .䤫≠ⴞ
+󠳛.‍䤫≠ⴞ; 󠳛.‍䤫≠ⴞ; [C2, P1, V6]; xn--1t56e.xn--1ug73gzzpwi3a; ; xn--1t56e.xn--1ch153bqvw; [P1, V6] # .䤫≠ⴞ
+𐽘𑈵.𐹣🕥; 𐽘𑈵.𐹣🕥; [B1, B2, B3]; xn--bv0d02c.xn--bo0dq650b; ; ; # 𐽘𑈵.𐹣🕥
+𐽘𑈵.𐹣🕥; ; [B1, B2, B3]; xn--bv0d02c.xn--bo0dq650b; ; ; # 𐽘𑈵.𐹣🕥
+xn--bv0d02c.xn--bo0dq650b; 𐽘𑈵.𐹣🕥; [B1, B2, B3]; xn--bv0d02c.xn--bo0dq650b; ; ; # 𐽘𑈵.𐹣🕥
+⒊⒈𑁄。9; ⒊⒈𑁄.9; [P1, V6]; xn--tshd3512p.9; ; ; # ⒊⒈𑁄.9
+3.1.𑁄。9; 3.1.𑁄.9; [V5]; 3.1.xn--110d.9; ; ; # 3.1.𑁄.9
+3.1.xn--110d.9; 3.1.𑁄.9; [V5]; 3.1.xn--110d.9; ; ; # 3.1.𑁄.9
+xn--tshd3512p.9; ⒊⒈𑁄.9; [V6]; xn--tshd3512p.9; ; ; # ⒊⒈𑁄.9
+-‌ⷱ≮.𐹱򭏴4₉; -‌ⷱ≮.𐹱򭏴49; [B1, C1, P1, V3, V6]; xn----sgn20i14s.xn--49-ki3om2611f; ; xn----ngo823c.xn--49-ki3om2611f; [B1, P1, V3, V6] # -ⷱ≮.𐹱49
+-‌ⷱ≮.𐹱򭏴4₉; -‌ⷱ≮.𐹱򭏴49; [B1, C1, P1, V3, V6]; xn----sgn20i14s.xn--49-ki3om2611f; ; xn----ngo823c.xn--49-ki3om2611f; [B1, P1, V3, V6] # -ⷱ≮.𐹱49
+-‌ⷱ≮.𐹱򭏴49; ; [B1, C1, P1, V3, V6]; xn----sgn20i14s.xn--49-ki3om2611f; ; xn----ngo823c.xn--49-ki3om2611f; [B1, P1, V3, V6] # -ⷱ≮.𐹱49
+-‌ⷱ≮.𐹱򭏴49; -‌ⷱ≮.𐹱򭏴49; [B1, C1, P1, V3, V6]; xn----sgn20i14s.xn--49-ki3om2611f; ; xn----ngo823c.xn--49-ki3om2611f; [B1, P1, V3, V6] # -ⷱ≮.𐹱49
+xn----ngo823c.xn--49-ki3om2611f; -ⷱ≮.𐹱򭏴49; [B1, V3, V6]; xn----ngo823c.xn--49-ki3om2611f; ; ; # -ⷱ≮.𐹱49
+xn----sgn20i14s.xn--49-ki3om2611f; -‌ⷱ≮.𐹱򭏴49; [B1, C1, V3, V6]; xn----sgn20i14s.xn--49-ki3om2611f; ; ; # -ⷱ≮.𐹱49
+-≯딾。ࡇ; -≯딾.ࡇ; [B1, P1, V3, V6]; xn----pgow547d.xn--5vb; ; ; # -≯딾.ࡇ
+-≯딾。ࡇ; -≯딾.ࡇ; [B1, P1, V3, V6]; xn----pgow547d.xn--5vb; ; ; # -≯딾.ࡇ
+-≯딾。ࡇ; -≯딾.ࡇ; [B1, P1, V3, V6]; xn----pgow547d.xn--5vb; ; ; # -≯딾.ࡇ
+-≯딾。ࡇ; -≯딾.ࡇ; [B1, P1, V3, V6]; xn----pgow547d.xn--5vb; ; ; # -≯딾.ࡇ
+xn----pgow547d.xn--5vb; -≯딾.ࡇ; [B1, V3, V6]; xn----pgow547d.xn--5vb; ; ; # -≯딾.ࡇ
+𑙢⒈𐹠-。󠗐‌; 𑙢⒈𐹠-.󠗐‌; [B1, C1, P1, V3, V6]; xn----dcpy090hiyg.xn--0ug23321l; ; xn----dcpy090hiyg.xn--jd46e; [B1, P1, V3, V6] # 𑙢⒈𐹠-.
+𑙢1.𐹠-。󠗐‌; 𑙢1.𐹠-.󠗐‌; [B1, C1, P1, V3, V6]; xn--1-bf0j.xn----516i.xn--0ug23321l; ; xn--1-bf0j.xn----516i.xn--jd46e; [B1, P1, V3, V6] # 𑙢1.𐹠-.
+xn--1-bf0j.xn----516i.xn--jd46e; 𑙢1.𐹠-.󠗐; [B1, V3, V6]; xn--1-bf0j.xn----516i.xn--jd46e; ; ; # 𑙢1.𐹠-.
+xn--1-bf0j.xn----516i.xn--0ug23321l; 𑙢1.𐹠-.󠗐‌; [B1, C1, V3, V6]; xn--1-bf0j.xn----516i.xn--0ug23321l; ; ; # 𑙢1.𐹠-.
+xn----dcpy090hiyg.xn--jd46e; 𑙢⒈𐹠-.󠗐; [B1, V3, V6]; xn----dcpy090hiyg.xn--jd46e; ; ; # 𑙢⒈𐹠-.
+xn----dcpy090hiyg.xn--0ug23321l; 𑙢⒈𐹠-.󠗐‌; [B1, C1, V3, V6]; xn----dcpy090hiyg.xn--0ug23321l; ; ; # 𑙢⒈𐹠-.
+͊.𐨎; ͊.𐨎; [V5]; xn--oua.xn--mr9c; ; ; # ͊.𐨎
+͊.𐨎; ; [V5]; xn--oua.xn--mr9c; ; ; # ͊.𐨎
+xn--oua.xn--mr9c; ͊.𐨎; [V5]; xn--oua.xn--mr9c; ; ; # ͊.𐨎
+훉≮。ิ; 훉≮.ิ; [P1, V5, V6]; xn--gdh2512e.xn--i4c; ; ; # 훉≮.ิ
+훉≮。ิ; 훉≮.ิ; [P1, V5, V6]; xn--gdh2512e.xn--i4c; ; ; # 훉≮.ิ
+훉≮。ิ; 훉≮.ิ; [P1, V5, V6]; xn--gdh2512e.xn--i4c; ; ; # 훉≮.ิ
+훉≮。ิ; 훉≮.ิ; [P1, V5, V6]; xn--gdh2512e.xn--i4c; ; ; # 훉≮.ิ
+xn--gdh2512e.xn--i4c; 훉≮.ิ; [V5, V6]; xn--gdh2512e.xn--i4c; ; ; # 훉≮.ิ
+ⷷ򞣉🃘.𴈇𝟸ٙ𞤯; ⷷ򞣉🃘.𴈇2ٙ𞤯; [B1, B5, B6, P1, V5, V6]; xn--trj8045le6s9b.xn--2-upc23918acjsj; ; ; # ⷷ🃘.2ٙ𞤯
+ⷷ򞣉🃘.𴈇2ٙ𞤯; ; [B1, B5, B6, P1, V5, V6]; xn--trj8045le6s9b.xn--2-upc23918acjsj; ; ; # ⷷ🃘.2ٙ𞤯
+ⷷ򞣉🃘.𴈇2ٙ𞤍; ⷷ򞣉🃘.𴈇2ٙ𞤯; [B1, B5, B6, P1, V5, V6]; xn--trj8045le6s9b.xn--2-upc23918acjsj; ; ; # ⷷ🃘.2ٙ𞤯
+xn--trj8045le6s9b.xn--2-upc23918acjsj; ⷷ򞣉🃘.𴈇2ٙ𞤯; [B1, B5, B6, V5, V6]; xn--trj8045le6s9b.xn--2-upc23918acjsj; ; ; # ⷷ🃘.2ٙ𞤯
+ⷷ򞣉🃘.𴈇𝟸ٙ𞤍; ⷷ򞣉🃘.𴈇2ٙ𞤯; [B1, B5, B6, P1, V5, V6]; xn--trj8045le6s9b.xn--2-upc23918acjsj; ; ; # ⷷ🃘.2ٙ𞤯
+󗇩ßᢞ‌。٠𞷻ﳔ-; 󗇩ßᢞ‌.٠𞷻نخ-; [B1, B6, C1, P1, V3, V6]; xn--zca272jbif10059a.xn----dnc5e1er384z; ; xn--ss-jepz4596r.xn----dnc5e1er384z; [B1, P1, V3, V6] # ßᢞ.٠نخ-
+󗇩ßᢞ‌。٠𞷻نخ-; 󗇩ßᢞ‌.٠𞷻نخ-; [B1, B6, C1, P1, V3, V6]; xn--zca272jbif10059a.xn----dnc5e1er384z; ; xn--ss-jepz4596r.xn----dnc5e1er384z; [B1, P1, V3, V6] # ßᢞ.٠نخ-
+󗇩SSᢞ‌。٠𞷻نخ-; 󗇩ssᢞ‌.٠𞷻نخ-; [B1, B6, C1, P1, V3, V6]; xn--ss-jep006bqt765b.xn----dnc5e1er384z; ; xn--ss-jepz4596r.xn----dnc5e1er384z; [B1, P1, V3, V6] # ssᢞ.٠نخ-
+󗇩ssᢞ‌。٠𞷻نخ-; 󗇩ssᢞ‌.٠𞷻نخ-; [B1, B6, C1, P1, V3, V6]; xn--ss-jep006bqt765b.xn----dnc5e1er384z; ; xn--ss-jepz4596r.xn----dnc5e1er384z; [B1, P1, V3, V6] # ssᢞ.٠نخ-
+󗇩Ssᢞ‌。٠𞷻نخ-; 󗇩ssᢞ‌.٠𞷻نخ-; [B1, B6, C1, P1, V3, V6]; xn--ss-jep006bqt765b.xn----dnc5e1er384z; ; xn--ss-jepz4596r.xn----dnc5e1er384z; [B1, P1, V3, V6] # ssᢞ.٠نخ-
+xn--ss-jepz4596r.xn----dnc5e1er384z; 󗇩ssᢞ.٠𞷻نخ-; [B1, V3, V6]; xn--ss-jepz4596r.xn----dnc5e1er384z; ; ; # ssᢞ.٠نخ-
+xn--ss-jep006bqt765b.xn----dnc5e1er384z; 󗇩ssᢞ‌.٠𞷻نخ-; [B1, B6, C1, V3, V6]; xn--ss-jep006bqt765b.xn----dnc5e1er384z; ; ; # ssᢞ.٠نخ-
+xn--zca272jbif10059a.xn----dnc5e1er384z; 󗇩ßᢞ‌.٠𞷻نخ-; [B1, B6, C1, V3, V6]; xn--zca272jbif10059a.xn----dnc5e1er384z; ; ; # ßᢞ.٠نخ-
+󗇩SSᢞ‌。٠𞷻ﳔ-; 󗇩ssᢞ‌.٠𞷻نخ-; [B1, B6, C1, P1, V3, V6]; xn--ss-jep006bqt765b.xn----dnc5e1er384z; ; xn--ss-jepz4596r.xn----dnc5e1er384z; [B1, P1, V3, V6] # ssᢞ.٠نخ-
+󗇩ssᢞ‌。٠𞷻ﳔ-; 󗇩ssᢞ‌.٠𞷻نخ-; [B1, B6, C1, P1, V3, V6]; xn--ss-jep006bqt765b.xn----dnc5e1er384z; ; xn--ss-jepz4596r.xn----dnc5e1er384z; [B1, P1, V3, V6] # ssᢞ.٠نخ-
+󗇩Ssᢞ‌。٠𞷻ﳔ-; 󗇩ssᢞ‌.٠𞷻نخ-; [B1, B6, C1, P1, V3, V6]; xn--ss-jep006bqt765b.xn----dnc5e1er384z; ; xn--ss-jepz4596r.xn----dnc5e1er384z; [B1, P1, V3, V6] # ssᢞ.٠نخ-
+ꡆ。Ↄྵ놮-; ꡆ.Ↄྵ놮-; [P1, V3, V6]; xn--fc9a.xn----qmg787k869k; ; ; # ꡆ.Ↄྵ놮-
+ꡆ。Ↄྵ놮-; ꡆ.Ↄྵ놮-; [P1, V3, V6]; xn--fc9a.xn----qmg787k869k; ; ; # ꡆ.Ↄྵ놮-
+ꡆ。ↄྵ놮-; ꡆ.ↄྵ놮-; [V3]; xn--fc9a.xn----qmg097k469k; ; ; # ꡆ.ↄྵ놮-
+ꡆ。ↄྵ놮-; ꡆ.ↄྵ놮-; [V3]; xn--fc9a.xn----qmg097k469k; ; ; # ꡆ.ↄྵ놮-
+xn--fc9a.xn----qmg097k469k; ꡆ.ↄྵ놮-; [V3]; xn--fc9a.xn----qmg097k469k; ; ; # ꡆ.ↄྵ놮-
+xn--fc9a.xn----qmg787k869k; ꡆ.Ↄྵ놮-; [V3, V6]; xn--fc9a.xn----qmg787k869k; ; ; # ꡆ.Ↄྵ놮-
+ﶭ‍.񥰌ک; لمي‍.񥰌ک; [B3, B5, B6, C2, P1, V6]; xn--ghbcp494x.xn--ckb36214f; ; xn--ghbcp.xn--ckb36214f; [B5, B6, P1, V6] # لمي.ک
+لمي‍.񥰌ک; ; [B3, B5, B6, C2, P1, V6]; xn--ghbcp494x.xn--ckb36214f; ; xn--ghbcp.xn--ckb36214f; [B5, B6, P1, V6] # لمي.ک
+xn--ghbcp.xn--ckb36214f; لمي.񥰌ک; [B5, B6, V6]; xn--ghbcp.xn--ckb36214f; ; ; # لمي.ک
+xn--ghbcp494x.xn--ckb36214f; لمي‍.񥰌ک; [B3, B5, B6, C2, V6]; xn--ghbcp494x.xn--ckb36214f; ; ; # لمي.ک
+Ⴜᰯ𐳒≯。۠ᜲྺ; Ⴜᰯ𐳒≯.۠ᜲྺ; [B1, B3, B5, B6, P1, V5, V6]; xn--0nd679cf3eq67y.xn--wlb646b4ng; ; ; # Ⴜᰯ𐳒≯.۠ᜲྺ
+Ⴜᰯ𐳒≯。۠ᜲྺ; Ⴜᰯ𐳒≯.۠ᜲྺ; [B1, B3, B5, B6, P1, V5, V6]; xn--0nd679cf3eq67y.xn--wlb646b4ng; ; ; # Ⴜᰯ𐳒≯.۠ᜲྺ
+ⴜᰯ𐳒≯。۠ᜲྺ; ⴜᰯ𐳒≯.۠ᜲྺ; [B1, B3, B5, B6, P1, V5, V6]; xn--r1f68xh1jgv7u.xn--wlb646b4ng; ; ; # ⴜᰯ𐳒≯.۠ᜲྺ
+ⴜᰯ𐳒≯。۠ᜲྺ; ⴜᰯ𐳒≯.۠ᜲྺ; [B1, B3, B5, B6, P1, V5, V6]; xn--r1f68xh1jgv7u.xn--wlb646b4ng; ; ; # ⴜᰯ𐳒≯.۠ᜲྺ
+Ⴜᰯ𐲒≯。۠ᜲྺ; Ⴜᰯ𐳒≯.۠ᜲྺ; [B1, B3, B5, B6, P1, V5, V6]; xn--0nd679cf3eq67y.xn--wlb646b4ng; ; ; # Ⴜᰯ𐳒≯.۠ᜲྺ
+Ⴜᰯ𐲒≯。۠ᜲྺ; Ⴜᰯ𐳒≯.۠ᜲྺ; [B1, B3, B5, B6, P1, V5, V6]; xn--0nd679cf3eq67y.xn--wlb646b4ng; ; ; # Ⴜᰯ𐳒≯.۠ᜲྺ
+xn--0nd679cf3eq67y.xn--wlb646b4ng; Ⴜᰯ𐳒≯.۠ᜲྺ; [B1, B3, B5, B6, V5, V6]; xn--0nd679cf3eq67y.xn--wlb646b4ng; ; ; # Ⴜᰯ𐳒≯.۠ᜲྺ
+xn--r1f68xh1jgv7u.xn--wlb646b4ng; ⴜᰯ𐳒≯.۠ᜲྺ; [B1, B3, B5, B6, V5, V6]; xn--r1f68xh1jgv7u.xn--wlb646b4ng; ; ; # ⴜᰯ𐳒≯.۠ᜲྺ
+𐋵。ﳬ; 𐋵.كم; [B1]; xn--p97c.xn--fhbe; ; ; # 𐋵.كم
+𐋵。كم; 𐋵.كم; [B1]; xn--p97c.xn--fhbe; ; ; # 𐋵.كم
+xn--p97c.xn--fhbe; 𐋵.كم; [B1]; xn--p97c.xn--fhbe; ; ; # 𐋵.كم
+𐋵.كم; ; [B1]; xn--p97c.xn--fhbe; ; ; # 𐋵.كم
+≮𝅶.񱲁ꫬ⹈󰥭; ≮𝅶.񱲁ꫬ⹈󰥭; [P1, V6]; xn--gdh0880o.xn--4tjx101bsg00ds9pyc; ; ; # ≮.ꫬ⹈
+≮𝅶.񱲁ꫬ⹈󰥭; ≮𝅶.񱲁ꫬ⹈󰥭; [P1, V6]; xn--gdh0880o.xn--4tjx101bsg00ds9pyc; ; ; # ≮.ꫬ⹈
+≮𝅶.񱲁ꫬ⹈󰥭; ; [P1, V6]; xn--gdh0880o.xn--4tjx101bsg00ds9pyc; ; ; # ≮.ꫬ⹈
+≮𝅶.񱲁ꫬ⹈󰥭; ≮𝅶.񱲁ꫬ⹈󰥭; [P1, V6]; xn--gdh0880o.xn--4tjx101bsg00ds9pyc; ; ; # ≮.ꫬ⹈
+xn--gdh0880o.xn--4tjx101bsg00ds9pyc; ≮𝅶.񱲁ꫬ⹈󰥭; [V6]; xn--gdh0880o.xn--4tjx101bsg00ds9pyc; ; ; # ≮.ꫬ⹈
+ⷰ͘ᢕ.͡𐹷󠴍; ⷰ͘ᢕ.͡𐹷󠴍; [B1, P1, V5, V6]; xn--2ua889htsp.xn--cva2687k2tv0g; ; ; # ⷰ͘ᢕ.͡𐹷
+ⷰ͘ᢕ.͡𐹷󠴍; ; [B1, P1, V5, V6]; xn--2ua889htsp.xn--cva2687k2tv0g; ; ; # ⷰ͘ᢕ.͡𐹷
+xn--2ua889htsp.xn--cva2687k2tv0g; ⷰ͘ᢕ.͡𐹷󠴍; [B1, V5, V6]; xn--2ua889htsp.xn--cva2687k2tv0g; ; ; # ⷰ͘ᢕ.͡𐹷
+ﵹᡐ‌ڭ.𑋪ׇ; غممᡐ‌ڭ.𑋪ׇ; [B1, B2, B3, B6, V5]; xn--5gbwa03bg24eptk.xn--vdb1198k; ; xn--5gbwa03bg24e.xn--vdb1198k; # غممᡐڭ.𑋪ׇ
+غممᡐ‌ڭ.𑋪ׇ; ; [B1, B2, B3, B6, V5]; xn--5gbwa03bg24eptk.xn--vdb1198k; ; xn--5gbwa03bg24e.xn--vdb1198k; # غممᡐڭ.𑋪ׇ
+xn--5gbwa03bg24e.xn--vdb1198k; غممᡐڭ.𑋪ׇ; [B1, B2, B3, B6, V5]; xn--5gbwa03bg24e.xn--vdb1198k; ; ; # غممᡐڭ.𑋪ׇ
+xn--5gbwa03bg24eptk.xn--vdb1198k; غممᡐ‌ڭ.𑋪ׇ; [B1, B2, B3, B6, V5]; xn--5gbwa03bg24eptk.xn--vdb1198k; ; ; # غممᡐڭ.𑋪ׇ
+𑑂。‍󥞀🞕򥁔; 𑑂.‍󥞀🞕򥁔; [C2, P1, V5, V6]; xn--8v1d.xn--1ug1386plvx1cd8vya; ; xn--8v1d.xn--ye9h41035a2qqs; [P1, V5, V6] # 𑑂.🞕
+𑑂。‍󥞀🞕򥁔; 𑑂.‍󥞀🞕򥁔; [C2, P1, V5, V6]; xn--8v1d.xn--1ug1386plvx1cd8vya; ; xn--8v1d.xn--ye9h41035a2qqs; [P1, V5, V6] # 𑑂.🞕
+xn--8v1d.xn--ye9h41035a2qqs; 𑑂.󥞀🞕򥁔; [V5, V6]; xn--8v1d.xn--ye9h41035a2qqs; ; ; # 𑑂.🞕
+xn--8v1d.xn--1ug1386plvx1cd8vya; 𑑂.‍󥞀🞕򥁔; [C2, V5, V6]; xn--8v1d.xn--1ug1386plvx1cd8vya; ; ; # 𑑂.🞕
+-ש。⒚; -ש.⒚; [B1, P1, V3, V6]; xn----gjc.xn--cth; ; ; # -ש.⒚
+-ש。19.; -ש.19.; [B1, V3]; xn----gjc.19.; ; ; # -ש.19.
+xn----gjc.19.; -ש.19.; [B1, V3]; xn----gjc.19.; ; ; # -ש.19.
+xn----gjc.xn--cth; -ש.⒚; [B1, V3, V6]; xn----gjc.xn--cth; ; ; # -ש.⒚
+􊾻ࡅ‌。ᢎ‍; 􊾻ࡅ‌.ᢎ‍; [B5, B6, C1, C2, P1, V6]; xn--3vb882jz4411a.xn--79e259a; ; xn--3vb50049s.xn--79e; [B5, B6, P1, V6] # ࡅ.ᢎ
+􊾻ࡅ‌。ᢎ‍; 􊾻ࡅ‌.ᢎ‍; [B5, B6, C1, C2, P1, V6]; xn--3vb882jz4411a.xn--79e259a; ; xn--3vb50049s.xn--79e; [B5, B6, P1, V6] # ࡅ.ᢎ
+xn--3vb50049s.xn--79e; 􊾻ࡅ.ᢎ; [B5, B6, V6]; xn--3vb50049s.xn--79e; ; ; # ࡅ.ᢎ
+xn--3vb882jz4411a.xn--79e259a; 􊾻ࡅ‌.ᢎ‍; [B5, B6, C1, C2, V6]; xn--3vb882jz4411a.xn--79e259a; ; ; # ࡅ.ᢎ
+ßুᷭ。ؠ8₅; ßুᷭ.ؠ85; ; xn--zca266bwrr.xn--85-psd; ; xn--ss-e2f077r.xn--85-psd; # ßুᷭ.ؠ85
+ßুᷭ。ؠ85; ßুᷭ.ؠ85; ; xn--zca266bwrr.xn--85-psd; ; xn--ss-e2f077r.xn--85-psd; # ßুᷭ.ؠ85
+SSুᷭ。ؠ85; ssুᷭ.ؠ85; ; xn--ss-e2f077r.xn--85-psd; ; ; # ssুᷭ.ؠ85
+ssুᷭ。ؠ85; ssুᷭ.ؠ85; ; xn--ss-e2f077r.xn--85-psd; ; ; # ssুᷭ.ؠ85
+Ssুᷭ。ؠ85; ssুᷭ.ؠ85; ; xn--ss-e2f077r.xn--85-psd; ; ; # ssুᷭ.ؠ85
+xn--ss-e2f077r.xn--85-psd; ssুᷭ.ؠ85; ; xn--ss-e2f077r.xn--85-psd; ; ; # ssুᷭ.ؠ85
+ssুᷭ.ؠ85; ; ; xn--ss-e2f077r.xn--85-psd; ; ; # ssুᷭ.ؠ85
+SSুᷭ.ؠ85; ssুᷭ.ؠ85; ; xn--ss-e2f077r.xn--85-psd; ; ; # ssুᷭ.ؠ85
+Ssুᷭ.ؠ85; ssুᷭ.ؠ85; ; xn--ss-e2f077r.xn--85-psd; ; ; # ssুᷭ.ؠ85
+xn--zca266bwrr.xn--85-psd; ßুᷭ.ؠ85; ; xn--zca266bwrr.xn--85-psd; ; ; # ßুᷭ.ؠ85
+ßুᷭ.ؠ85; ; ; xn--zca266bwrr.xn--85-psd; ; xn--ss-e2f077r.xn--85-psd; # ßুᷭ.ؠ85
+SSুᷭ。ؠ8₅; ssুᷭ.ؠ85; ; xn--ss-e2f077r.xn--85-psd; ; ; # ssুᷭ.ؠ85
+ssুᷭ。ؠ8₅; ssুᷭ.ؠ85; ; xn--ss-e2f077r.xn--85-psd; ; ; # ssুᷭ.ؠ85
+Ssুᷭ。ؠ8₅; ssুᷭ.ؠ85; ; xn--ss-e2f077r.xn--85-psd; ; ; # ssুᷭ.ؠ85
+્҄魅𝟣.₃𐹥ß; ્҄魅1.3𐹥ß; [B1, V5]; xn--1-0xb049b102o.xn--3-qfa7018r; ; xn--1-0xb049b102o.xn--3ss-nv9t; # ્҄魅1.3𐹥ß
+્҄魅1.3𐹥ß; ; [B1, V5]; xn--1-0xb049b102o.xn--3-qfa7018r; ; xn--1-0xb049b102o.xn--3ss-nv9t; # ્҄魅1.3𐹥ß
+્҄魅1.3𐹥SS; ્҄魅1.3𐹥ss; [B1, V5]; xn--1-0xb049b102o.xn--3ss-nv9t; ; ; # ્҄魅1.3𐹥ss
+્҄魅1.3𐹥ss; ; [B1, V5]; xn--1-0xb049b102o.xn--3ss-nv9t; ; ; # ્҄魅1.3𐹥ss
+્҄魅1.3𐹥Ss; ્҄魅1.3𐹥ss; [B1, V5]; xn--1-0xb049b102o.xn--3ss-nv9t; ; ; # ્҄魅1.3𐹥ss
+xn--1-0xb049b102o.xn--3ss-nv9t; ્҄魅1.3𐹥ss; [B1, V5]; xn--1-0xb049b102o.xn--3ss-nv9t; ; ; # ્҄魅1.3𐹥ss
+xn--1-0xb049b102o.xn--3-qfa7018r; ્҄魅1.3𐹥ß; [B1, V5]; xn--1-0xb049b102o.xn--3-qfa7018r; ; ; # ્҄魅1.3𐹥ß
+્҄魅𝟣.₃𐹥SS; ્҄魅1.3𐹥ss; [B1, V5]; xn--1-0xb049b102o.xn--3ss-nv9t; ; ; # ્҄魅1.3𐹥ss
+્҄魅𝟣.₃𐹥ss; ્҄魅1.3𐹥ss; [B1, V5]; xn--1-0xb049b102o.xn--3ss-nv9t; ; ; # ્҄魅1.3𐹥ss
+્҄魅𝟣.₃𐹥Ss; ્҄魅1.3𐹥ss; [B1, V5]; xn--1-0xb049b102o.xn--3ss-nv9t; ; ; # ્҄魅1.3𐹥ss
+ܫ。𑓂⒈𑜫󠿻; ܫ.𑓂⒈𑜫󠿻; [B1, P1, V5, V6]; xn--1nb.xn--tsh7798f6rbrt828c; ; ; # ܫ.𑓂⒈𑜫
+ܫ。𑓂1.𑜫󠿻; ܫ.𑓂1.𑜫󠿻; [B1, P1, V5, V6]; xn--1nb.xn--1-jq9i.xn--ji2dg9877c; ; ; # ܫ.𑓂1.𑜫
+xn--1nb.xn--1-jq9i.xn--ji2dg9877c; ܫ.𑓂1.𑜫󠿻; [B1, V5, V6]; xn--1nb.xn--1-jq9i.xn--ji2dg9877c; ; ; # ܫ.𑓂1.𑜫
+xn--1nb.xn--tsh7798f6rbrt828c; ܫ.𑓂⒈𑜫󠿻; [B1, V5, V6]; xn--1nb.xn--tsh7798f6rbrt828c; ; ; # ܫ.𑓂⒈𑜫
+︍છ。嵨; છ.嵨; ; xn--6dc.xn--tot; ; ; # છ.嵨
+xn--6dc.xn--tot; છ.嵨; ; xn--6dc.xn--tot; ; ; # છ.嵨
+છ.嵨; ; ; xn--6dc.xn--tot; ; ; # છ.嵨
+Ⴔ≠Ⴀ.𐹥𐹰; ; [B1, P1, V6]; xn--7md3b171g.xn--do0dwa; ; ; # Ⴔ≠Ⴀ.𐹥𐹰
+Ⴔ≠Ⴀ.𐹥𐹰; Ⴔ≠Ⴀ.𐹥𐹰; [B1, P1, V6]; xn--7md3b171g.xn--do0dwa; ; ; # Ⴔ≠Ⴀ.𐹥𐹰
+ⴔ≠ⴀ.𐹥𐹰; ⴔ≠ⴀ.𐹥𐹰; [B1, P1, V6]; xn--1ch603bxb.xn--do0dwa; ; ; # ⴔ≠ⴀ.𐹥𐹰
+ⴔ≠ⴀ.𐹥𐹰; ; [B1, P1, V6]; xn--1ch603bxb.xn--do0dwa; ; ; # ⴔ≠ⴀ.𐹥𐹰
+xn--1ch603bxb.xn--do0dwa; ⴔ≠ⴀ.𐹥𐹰; [B1, V6]; xn--1ch603bxb.xn--do0dwa; ; ; # ⴔ≠ⴀ.𐹥𐹰
+xn--7md3b171g.xn--do0dwa; Ⴔ≠Ⴀ.𐹥𐹰; [B1, V6]; xn--7md3b171g.xn--do0dwa; ; ; # Ⴔ≠Ⴀ.𐹥𐹰
+-‌⒙𐫥。𝨵; -‌⒙𐫥.𝨵; [C1, P1, V3, V5, V6]; xn----sgn18r3191a.xn--382h; ; xn----ddps939g.xn--382h; [P1, V3, V5, V6] # -⒙𐫥.𝨵
+-‌18.𐫥。𝨵; -‌18.𐫥.𝨵; [C1, V3, V5]; xn---18-9m0a.xn--rx9c.xn--382h; ; -18.xn--rx9c.xn--382h; [V3, V5] # -18.𐫥.𝨵
+-18.xn--rx9c.xn--382h; -18.𐫥.𝨵; [V3, V5]; -18.xn--rx9c.xn--382h; ; ; # -18.𐫥.𝨵
+xn---18-9m0a.xn--rx9c.xn--382h; -‌18.𐫥.𝨵; [C1, V3, V5]; xn---18-9m0a.xn--rx9c.xn--382h; ; ; # -18.𐫥.𝨵
+xn----ddps939g.xn--382h; -⒙𐫥.𝨵; [V3, V5, V6]; xn----ddps939g.xn--382h; ; ; # -⒙𐫥.𝨵
+xn----sgn18r3191a.xn--382h; -‌⒙𐫥.𝨵; [C1, V3, V5, V6]; xn----sgn18r3191a.xn--382h; ; ; # -⒙𐫥.𝨵
+︒.ʌᠣ-𐹽; ; [B1, B5, B6, P1, V6]; xn--y86c.xn----73a596nuh9t; ; ; # ︒.ʌᠣ-𐹽
+。.ʌᠣ-𐹽; ..ʌᠣ-𐹽; [B5, B6, X4_2]; ..xn----73a596nuh9t; [B5, B6, A4_2]; ; # ..ʌᠣ-𐹽
+。.Ʌᠣ-𐹽; ..ʌᠣ-𐹽; [B5, B6, X4_2]; ..xn----73a596nuh9t; [B5, B6, A4_2]; ; # ..ʌᠣ-𐹽
+..xn----73a596nuh9t; ..ʌᠣ-𐹽; [B5, B6, X4_2]; ..xn----73a596nuh9t; [B5, B6, A4_2]; ; # ..ʌᠣ-𐹽
+︒.Ʌᠣ-𐹽; ︒.ʌᠣ-𐹽; [B1, B5, B6, P1, V6]; xn--y86c.xn----73a596nuh9t; ; ; # ︒.ʌᠣ-𐹽
+xn--y86c.xn----73a596nuh9t; ︒.ʌᠣ-𐹽; [B1, B5, B6, V6]; xn--y86c.xn----73a596nuh9t; ; ; # ︒.ʌᠣ-𐹽
+︅︒。𦀾᳠; ︒.𦀾᳠; [P1, V6]; xn--y86c.xn--t6f5138v; ; ; # ︒.𦀾᳠
+︅。。𦀾᳠; ..𦀾᳠; [X4_2]; ..xn--t6f5138v; [A4_2]; ; # ..𦀾᳠
+..xn--t6f5138v; ..𦀾᳠; [X4_2]; ..xn--t6f5138v; [A4_2]; ; # ..𦀾᳠
+xn--y86c.xn--t6f5138v; ︒.𦀾᳠; [V6]; xn--y86c.xn--t6f5138v; ; ; # ︒.𦀾᳠
+xn--t6f5138v; 𦀾᳠; ; xn--t6f5138v; ; ; # 𦀾᳠
+𦀾᳠; ; ; xn--t6f5138v; ; ; # 𦀾᳠
+𞮑ß􏞞。ᡁ; 𞮑ß􏞞.ᡁ; [B2, B3, P1, V6]; xn--zca9432wb989f.xn--07e; ; xn--ss-o412ac6305g.xn--07e; # ß.ᡁ
+𞮑SS􏞞。ᡁ; 𞮑ss􏞞.ᡁ; [B2, B3, P1, V6]; xn--ss-o412ac6305g.xn--07e; ; ; # ss.ᡁ
+𞮑ss􏞞。ᡁ; 𞮑ss􏞞.ᡁ; [B2, B3, P1, V6]; xn--ss-o412ac6305g.xn--07e; ; ; # ss.ᡁ
+𞮑Ss􏞞。ᡁ; 𞮑ss􏞞.ᡁ; [B2, B3, P1, V6]; xn--ss-o412ac6305g.xn--07e; ; ; # ss.ᡁ
+xn--ss-o412ac6305g.xn--07e; 𞮑ss􏞞.ᡁ; [B2, B3, V6]; xn--ss-o412ac6305g.xn--07e; ; ; # ss.ᡁ
+xn--zca9432wb989f.xn--07e; 𞮑ß􏞞.ᡁ; [B2, B3, V6]; xn--zca9432wb989f.xn--07e; ; ; # ß.ᡁ
+꥓‍ج٬。𱆎󻡟‌󠅆; ꥓‍ج٬.𱆎󻡟‌; [B5, B6, C1, P1, V5, V6]; xn--rgb2k500fhq9j.xn--0ug78870a5sp9d; ; xn--rgb2k6711c.xn--ec8nj3948b; [B5, B6, P1, V5, V6] # ꥓ج٬.𱆎
+xn--rgb2k6711c.xn--ec8nj3948b; ꥓ج٬.𱆎󻡟; [B5, B6, V5, V6]; xn--rgb2k6711c.xn--ec8nj3948b; ; ; # ꥓ج٬.𱆎
+xn--rgb2k500fhq9j.xn--0ug78870a5sp9d; ꥓‍ج٬.𱆎󻡟‌; [B5, B6, C1, V5, V6]; xn--rgb2k500fhq9j.xn--0ug78870a5sp9d; ; ; # ꥓ج٬.𱆎
+󠕏.-ß‌≠; 󠕏.-ß‌≠; [C1, P1, V3, V6]; xn--u836e.xn----qfa750ve7b; ; xn--u836e.xn---ss-gl2a; [P1, V3, V6] # .-ß≠
+󠕏.-ß‌≠; 󠕏.-ß‌≠; [C1, P1, V3, V6]; xn--u836e.xn----qfa750ve7b; ; xn--u836e.xn---ss-gl2a; [P1, V3, V6] # .-ß≠
+󠕏.-ß‌≠; ; [C1, P1, V3, V6]; xn--u836e.xn----qfa750ve7b; ; xn--u836e.xn---ss-gl2a; [P1, V3, V6] # .-ß≠
+󠕏.-ß‌≠; 󠕏.-ß‌≠; [C1, P1, V3, V6]; xn--u836e.xn----qfa750ve7b; ; xn--u836e.xn---ss-gl2a; [P1, V3, V6] # .-ß≠
+󠕏.-SS‌≠; 󠕏.-ss‌≠; [C1, P1, V3, V6]; xn--u836e.xn---ss-cn0at5l; ; xn--u836e.xn---ss-gl2a; [P1, V3, V6] # .-ss≠
+󠕏.-SS‌≠; 󠕏.-ss‌≠; [C1, P1, V3, V6]; xn--u836e.xn---ss-cn0at5l; ; xn--u836e.xn---ss-gl2a; [P1, V3, V6] # .-ss≠
+󠕏.-ss‌≠; ; [C1, P1, V3, V6]; xn--u836e.xn---ss-cn0at5l; ; xn--u836e.xn---ss-gl2a; [P1, V3, V6] # .-ss≠
+󠕏.-ss‌≠; 󠕏.-ss‌≠; [C1, P1, V3, V6]; xn--u836e.xn---ss-cn0at5l; ; xn--u836e.xn---ss-gl2a; [P1, V3, V6] # .-ss≠
+󠕏.-Ss‌≠; 󠕏.-ss‌≠; [C1, P1, V3, V6]; xn--u836e.xn---ss-cn0at5l; ; xn--u836e.xn---ss-gl2a; [P1, V3, V6] # .-ss≠
+󠕏.-Ss‌≠; 󠕏.-ss‌≠; [C1, P1, V3, V6]; xn--u836e.xn---ss-cn0at5l; ; xn--u836e.xn---ss-gl2a; [P1, V3, V6] # .-ss≠
+xn--u836e.xn---ss-gl2a; 󠕏.-ss≠; [V3, V6]; xn--u836e.xn---ss-gl2a; ; ; # .-ss≠
+xn--u836e.xn---ss-cn0at5l; 󠕏.-ss‌≠; [C1, V3, V6]; xn--u836e.xn---ss-cn0at5l; ; ; # .-ss≠
+xn--u836e.xn----qfa750ve7b; 󠕏.-ß‌≠; [C1, V3, V6]; xn--u836e.xn----qfa750ve7b; ; ; # .-ß≠
+󠕏.-SS‌≠; 󠕏.-ss‌≠; [C1, P1, V3, V6]; xn--u836e.xn---ss-cn0at5l; ; xn--u836e.xn---ss-gl2a; [P1, V3, V6] # .-ss≠
+󠕏.-SS‌≠; 󠕏.-ss‌≠; [C1, P1, V3, V6]; xn--u836e.xn---ss-cn0at5l; ; xn--u836e.xn---ss-gl2a; [P1, V3, V6] # .-ss≠
+󠕏.-ss‌≠; 󠕏.-ss‌≠; [C1, P1, V3, V6]; xn--u836e.xn---ss-cn0at5l; ; xn--u836e.xn---ss-gl2a; [P1, V3, V6] # .-ss≠
+󠕏.-ss‌≠; 󠕏.-ss‌≠; [C1, P1, V3, V6]; xn--u836e.xn---ss-cn0at5l; ; xn--u836e.xn---ss-gl2a; [P1, V3, V6] # .-ss≠
+󠕏.-Ss‌≠; 󠕏.-ss‌≠; [C1, P1, V3, V6]; xn--u836e.xn---ss-cn0at5l; ; xn--u836e.xn---ss-gl2a; [P1, V3, V6] # .-ss≠
+󠕏.-Ss‌≠; 󠕏.-ss‌≠; [C1, P1, V3, V6]; xn--u836e.xn---ss-cn0at5l; ; xn--u836e.xn---ss-gl2a; [P1, V3, V6] # .-ss≠
+ᡙ‌。≯𐋲≠; ᡙ‌.≯𐋲≠; [C1, P1, V6]; xn--p8e650b.xn--1ch3a7084l; ; xn--p8e.xn--1ch3a7084l; [P1, V6] # ᡙ.≯𐋲≠
+ᡙ‌。≯𐋲≠; ᡙ‌.≯𐋲≠; [C1, P1, V6]; xn--p8e650b.xn--1ch3a7084l; ; xn--p8e.xn--1ch3a7084l; [P1, V6] # ᡙ.≯𐋲≠
+ᡙ‌。≯𐋲≠; ᡙ‌.≯𐋲≠; [C1, P1, V6]; xn--p8e650b.xn--1ch3a7084l; ; xn--p8e.xn--1ch3a7084l; [P1, V6] # ᡙ.≯𐋲≠
+ᡙ‌。≯𐋲≠; ᡙ‌.≯𐋲≠; [C1, P1, V6]; xn--p8e650b.xn--1ch3a7084l; ; xn--p8e.xn--1ch3a7084l; [P1, V6] # ᡙ.≯𐋲≠
+xn--p8e.xn--1ch3a7084l; ᡙ.≯𐋲≠; [V6]; xn--p8e.xn--1ch3a7084l; ; ; # ᡙ.≯𐋲≠
+xn--p8e650b.xn--1ch3a7084l; ᡙ‌.≯𐋲≠; [C1, V6]; xn--p8e650b.xn--1ch3a7084l; ; ; # ᡙ.≯𐋲≠
+𐹧𞲄󠁭񆼩。͎🄀; 𐹧𞲄󠁭񆼩.͎🄀; [B1, P1, V5, V6]; xn--fo0dw409aq58qrn69d.xn--sua6883w; ; ; # 𐹧𞲄.͎🄀
+𐹧𞲄󠁭񆼩。͎0.; 𐹧𞲄󠁭񆼩.͎0.; [B1, P1, V5, V6]; xn--fo0dw409aq58qrn69d.xn--0-bgb.; ; ; # 𐹧𞲄.͎0.
+xn--fo0dw409aq58qrn69d.xn--0-bgb.; 𐹧𞲄󠁭񆼩.͎0.; [B1, V5, V6]; xn--fo0dw409aq58qrn69d.xn--0-bgb.; ; ; # 𐹧𞲄.͎0.
+xn--fo0dw409aq58qrn69d.xn--sua6883w; 𐹧𞲄󠁭񆼩.͎🄀; [B1, V5, V6]; xn--fo0dw409aq58qrn69d.xn--sua6883w; ; ; # 𐹧𞲄.͎🄀
+Ⴄ.‍ܡ󻣋ς; Ⴄ.‍ܡ󻣋ς; [B1, C2, P1, V6]; xn--cnd.xn--3xa93o3t5ajq467a; ; xn--cnd.xn--4xa73ob5892c; [B2, B3, P1, V6] # Ⴄ.ܡς
+Ⴄ.‍ܡ󻣋ς; ; [B1, C2, P1, V6]; xn--cnd.xn--3xa93o3t5ajq467a; ; xn--cnd.xn--4xa73ob5892c; [B2, B3, P1, V6] # Ⴄ.ܡς
+ⴄ.‍ܡ󻣋ς; ; [B1, C2, P1, V6]; xn--vkj.xn--3xa93o3t5ajq467a; ; xn--vkj.xn--4xa73ob5892c; [B2, B3, P1, V6] # ⴄ.ܡς
+Ⴄ.‍ܡ󻣋Σ; Ⴄ.‍ܡ󻣋σ; [B1, C2, P1, V6]; xn--cnd.xn--4xa73o3t5ajq467a; ; xn--cnd.xn--4xa73ob5892c; [B2, B3, P1, V6] # Ⴄ.ܡσ
+ⴄ.‍ܡ󻣋σ; ; [B1, C2, P1, V6]; xn--vkj.xn--4xa73o3t5ajq467a; ; xn--vkj.xn--4xa73ob5892c; [B2, B3, P1, V6] # ⴄ.ܡσ
+xn--vkj.xn--4xa73ob5892c; ⴄ.ܡ󻣋σ; [B2, B3, V6]; xn--vkj.xn--4xa73ob5892c; ; ; # ⴄ.ܡσ
+xn--vkj.xn--4xa73o3t5ajq467a; ⴄ.‍ܡ󻣋σ; [B1, C2, V6]; xn--vkj.xn--4xa73o3t5ajq467a; ; ; # ⴄ.ܡσ
+xn--cnd.xn--4xa73ob5892c; Ⴄ.ܡ󻣋σ; [B2, B3, V6]; xn--cnd.xn--4xa73ob5892c; ; ; # Ⴄ.ܡσ
+xn--cnd.xn--4xa73o3t5ajq467a; Ⴄ.‍ܡ󻣋σ; [B1, C2, V6]; xn--cnd.xn--4xa73o3t5ajq467a; ; ; # Ⴄ.ܡσ
+xn--vkj.xn--3xa93o3t5ajq467a; ⴄ.‍ܡ󻣋ς; [B1, C2, V6]; xn--vkj.xn--3xa93o3t5ajq467a; ; ; # ⴄ.ܡς
+xn--cnd.xn--3xa93o3t5ajq467a; Ⴄ.‍ܡ󻣋ς; [B1, C2, V6]; xn--cnd.xn--3xa93o3t5ajq467a; ; ; # Ⴄ.ܡς
+ⴄ.‍ܡ󻣋ς; ⴄ.‍ܡ󻣋ς; [B1, C2, P1, V6]; xn--vkj.xn--3xa93o3t5ajq467a; ; xn--vkj.xn--4xa73ob5892c; [B2, B3, P1, V6] # ⴄ.ܡς
+Ⴄ.‍ܡ󻣋Σ; Ⴄ.‍ܡ󻣋σ; [B1, C2, P1, V6]; xn--cnd.xn--4xa73o3t5ajq467a; ; xn--cnd.xn--4xa73ob5892c; [B2, B3, P1, V6] # Ⴄ.ܡσ
+ⴄ.‍ܡ󻣋σ; ⴄ.‍ܡ󻣋σ; [B1, C2, P1, V6]; xn--vkj.xn--4xa73o3t5ajq467a; ; xn--vkj.xn--4xa73ob5892c; [B2, B3, P1, V6] # ⴄ.ܡσ
+򮵛ؓ.Ⴕ; ; [P1, V6]; xn--1fb94204l.xn--tnd; ; ; # ؓ.Ⴕ
+򮵛ؓ.ⴕ; ; [P1, V6]; xn--1fb94204l.xn--dlj; ; ; # ؓ.ⴕ
+xn--1fb94204l.xn--dlj; 򮵛ؓ.ⴕ; [V6]; xn--1fb94204l.xn--dlj; ; ; # ؓ.ⴕ
+xn--1fb94204l.xn--tnd; 򮵛ؓ.Ⴕ; [V6]; xn--1fb94204l.xn--tnd; ; ; # ؓ.Ⴕ
+≯ᷳ𞤥。‌꣄󠪉‍; ≯ᷳ𞤥.‌꣄󠪉‍; [B1, C1, C2, P1, V6]; xn--ofg13qyr21c.xn--0ugc0116hix29k; ; xn--ofg13qyr21c.xn--0f9au6706d; [B1, P1, V5, V6] # ≯ᷳ𞤥.꣄
+≯ᷳ𞤥。‌꣄󠪉‍; ≯ᷳ𞤥.‌꣄󠪉‍; [B1, C1, C2, P1, V6]; xn--ofg13qyr21c.xn--0ugc0116hix29k; ; xn--ofg13qyr21c.xn--0f9au6706d; [B1, P1, V5, V6] # ≯ᷳ𞤥.꣄
+≯ᷳ𞤃。‌꣄󠪉‍; ≯ᷳ𞤥.‌꣄󠪉‍; [B1, C1, C2, P1, V6]; xn--ofg13qyr21c.xn--0ugc0116hix29k; ; xn--ofg13qyr21c.xn--0f9au6706d; [B1, P1, V5, V6] # ≯ᷳ𞤥.꣄
+≯ᷳ𞤃。‌꣄󠪉‍; ≯ᷳ𞤥.‌꣄󠪉‍; [B1, C1, C2, P1, V6]; xn--ofg13qyr21c.xn--0ugc0116hix29k; ; xn--ofg13qyr21c.xn--0f9au6706d; [B1, P1, V5, V6] # ≯ᷳ𞤥.꣄
+xn--ofg13qyr21c.xn--0f9au6706d; ≯ᷳ𞤥.꣄󠪉; [B1, V5, V6]; xn--ofg13qyr21c.xn--0f9au6706d; ; ; # ≯ᷳ𞤥.꣄
+xn--ofg13qyr21c.xn--0ugc0116hix29k; ≯ᷳ𞤥.‌꣄󠪉‍; [B1, C1, C2, V6]; xn--ofg13qyr21c.xn--0ugc0116hix29k; ; ; # ≯ᷳ𞤥.꣄
+‌󠄷。򒑁; ‌.򒑁; [C1, P1, V6]; xn--0ug.xn--w720c; ; .xn--w720c; [P1, V6, A4_2] # .
+‌󠄷。򒑁; ‌.򒑁; [C1, P1, V6]; xn--0ug.xn--w720c; ; .xn--w720c; [P1, V6, A4_2] # .
+.xn--w720c; .򒑁; [V6, X4_2]; .xn--w720c; [V6, A4_2]; ; # .
+xn--0ug.xn--w720c; ‌.򒑁; [C1, V6]; xn--0ug.xn--w720c; ; ; # .
+⒈ූ焅.󗡙‍ꡟ; ; [C2, P1, V6]; xn--t1c337io97c.xn--1ugz184c9lw7i; ; xn--t1c337io97c.xn--4c9a21133d; [P1, V6] # ⒈ූ焅.ꡟ
+1.ූ焅.󗡙‍ꡟ; ; [C2, P1, V5, V6]; 1.xn--t1c6981c.xn--1ugz184c9lw7i; ; 1.xn--t1c6981c.xn--4c9a21133d; [P1, V5, V6] # 1.ූ焅.ꡟ
+1.xn--t1c6981c.xn--4c9a21133d; 1.ූ焅.󗡙ꡟ; [V5, V6]; 1.xn--t1c6981c.xn--4c9a21133d; ; ; # 1.ූ焅.ꡟ
+1.xn--t1c6981c.xn--1ugz184c9lw7i; 1.ූ焅.󗡙‍ꡟ; [C2, V5, V6]; 1.xn--t1c6981c.xn--1ugz184c9lw7i; ; ; # 1.ූ焅.ꡟ
+xn--t1c337io97c.xn--4c9a21133d; ⒈ූ焅.󗡙ꡟ; [V6]; xn--t1c337io97c.xn--4c9a21133d; ; ; # ⒈ූ焅.ꡟ
+xn--t1c337io97c.xn--1ugz184c9lw7i; ⒈ූ焅.󗡙‍ꡟ; [C2, V6]; xn--t1c337io97c.xn--1ugz184c9lw7i; ; ; # ⒈ූ焅.ꡟ
+᷍ς≮.ς𝪦𞤕0; ᷍ς≮.ς𝪦𞤷0; [B1, B5, P1, V5, V6]; xn--3xa744kvid.xn--0-xmb85727aggma; ; xn--4xa544kvid.xn--0-zmb55727aggma; # ᷍ς≮.ς𝪦𞤷0
+᷍ς≮.ς𝪦𞤕0; ᷍ς≮.ς𝪦𞤷0; [B1, B5, P1, V5, V6]; xn--3xa744kvid.xn--0-xmb85727aggma; ; xn--4xa544kvid.xn--0-zmb55727aggma; # ᷍ς≮.ς𝪦𞤷0
+᷍ς≮.ς𝪦𞤷0; ᷍ς≮.ς𝪦𞤷0; [B1, B5, P1, V5, V6]; xn--3xa744kvid.xn--0-xmb85727aggma; ; xn--4xa544kvid.xn--0-zmb55727aggma; # ᷍ς≮.ς𝪦𞤷0
+᷍ς≮.ς𝪦𞤷0; ; [B1, B5, P1, V5, V6]; xn--3xa744kvid.xn--0-xmb85727aggma; ; xn--4xa544kvid.xn--0-zmb55727aggma; # ᷍ς≮.ς𝪦𞤷0
+᷍Σ≮.Σ𝪦𞤕0; ᷍σ≮.σ𝪦𞤷0; [B1, B5, P1, V5, V6]; xn--4xa544kvid.xn--0-zmb55727aggma; ; ; # ᷍σ≮.σ𝪦𞤷0
+᷍Σ≮.Σ𝪦𞤕0; ᷍σ≮.σ𝪦𞤷0; [B1, B5, P1, V5, V6]; xn--4xa544kvid.xn--0-zmb55727aggma; ; ; # ᷍σ≮.σ𝪦𞤷0
+᷍σ≮.σ𝪦𞤷0; ᷍σ≮.σ𝪦𞤷0; [B1, B5, P1, V5, V6]; xn--4xa544kvid.xn--0-zmb55727aggma; ; ; # ᷍σ≮.σ𝪦𞤷0
+᷍σ≮.σ𝪦𞤷0; ; [B1, B5, P1, V5, V6]; xn--4xa544kvid.xn--0-zmb55727aggma; ; ; # ᷍σ≮.σ𝪦𞤷0
+᷍Σ≮.Σ𝪦𞤷0; ᷍σ≮.σ𝪦𞤷0; [B1, B5, P1, V5, V6]; xn--4xa544kvid.xn--0-zmb55727aggma; ; ; # ᷍σ≮.σ𝪦𞤷0
+᷍Σ≮.Σ𝪦𞤷0; ᷍σ≮.σ𝪦𞤷0; [B1, B5, P1, V5, V6]; xn--4xa544kvid.xn--0-zmb55727aggma; ; ; # ᷍σ≮.σ𝪦𞤷0
+xn--4xa544kvid.xn--0-zmb55727aggma; ᷍σ≮.σ𝪦𞤷0; [B1, B5, V5, V6]; xn--4xa544kvid.xn--0-zmb55727aggma; ; ; # ᷍σ≮.σ𝪦𞤷0
+xn--3xa744kvid.xn--0-xmb85727aggma; ᷍ς≮.ς𝪦𞤷0; [B1, B5, V5, V6]; xn--3xa744kvid.xn--0-xmb85727aggma; ; ; # ᷍ς≮.ς𝪦𞤷0
+᷍σ≮.σ𝪦𞤕0; ᷍σ≮.σ𝪦𞤷0; [B1, B5, P1, V5, V6]; xn--4xa544kvid.xn--0-zmb55727aggma; ; ; # ᷍σ≮.σ𝪦𞤷0
+᷍σ≮.σ𝪦𞤕0; ᷍σ≮.σ𝪦𞤷0; [B1, B5, P1, V5, V6]; xn--4xa544kvid.xn--0-zmb55727aggma; ; ; # ᷍σ≮.σ𝪦𞤷0
+򢦾ßֹ𐫙.֭ࢡ; ; [B1, B5, B6, P1, V5, V6]; xn--zca89v339zj118e.xn--4cb62m; ; xn--ss-xjd6058xlz50g.xn--4cb62m; # ßֹ𐫙.֭ࢡ
+򢦾SSֹ𐫙.֭ࢡ; 򢦾ssֹ𐫙.֭ࢡ; [B1, B5, B6, P1, V5, V6]; xn--ss-xjd6058xlz50g.xn--4cb62m; ; ; # ssֹ𐫙.֭ࢡ
+򢦾ssֹ𐫙.֭ࢡ; ; [B1, B5, B6, P1, V5, V6]; xn--ss-xjd6058xlz50g.xn--4cb62m; ; ; # ssֹ𐫙.֭ࢡ
+򢦾Ssֹ𐫙.֭ࢡ; 򢦾ssֹ𐫙.֭ࢡ; [B1, B5, B6, P1, V5, V6]; xn--ss-xjd6058xlz50g.xn--4cb62m; ; ; # ssֹ𐫙.֭ࢡ
+xn--ss-xjd6058xlz50g.xn--4cb62m; 򢦾ssֹ𐫙.֭ࢡ; [B1, B5, B6, V5, V6]; xn--ss-xjd6058xlz50g.xn--4cb62m; ; ; # ssֹ𐫙.֭ࢡ
+xn--zca89v339zj118e.xn--4cb62m; 򢦾ßֹ𐫙.֭ࢡ; [B1, B5, B6, V5, V6]; xn--zca89v339zj118e.xn--4cb62m; ; ; # ßֹ𐫙.֭ࢡ
+-𞣄。⒈; -𞣄.⒈; [B1, P1, V3, V6]; xn----xc8r.xn--tsh; ; ; # -𞣄.⒈
+-𞣄。1.; -𞣄.1.; [B1, V3]; xn----xc8r.1.; ; ; # -𞣄.1.
+xn----xc8r.1.; -𞣄.1.; [B1, V3]; xn----xc8r.1.; ; ; # -𞣄.1.
+xn----xc8r.xn--tsh; -𞣄.⒈; [B1, V3, V6]; xn----xc8r.xn--tsh; ; ; # -𞣄.⒈
+񈠢𐫖𝟡。ؾ𑘿; 񈠢𐫖9.ؾ𑘿; [B5, P1, V6]; xn--9-el5iv442t.xn--9gb0830l; ; ; # 𐫖9.ؾ𑘿
+񈠢𐫖9。ؾ𑘿; 񈠢𐫖9.ؾ𑘿; [B5, P1, V6]; xn--9-el5iv442t.xn--9gb0830l; ; ; # 𐫖9.ؾ𑘿
+xn--9-el5iv442t.xn--9gb0830l; 񈠢𐫖9.ؾ𑘿; [B5, V6]; xn--9-el5iv442t.xn--9gb0830l; ; ; # 𐫖9.ؾ𑘿
+٨ﲌ٨ᩝ.‍; ٨نم٨ᩝ.‍; [B1, C2]; xn--hhbb5hc956w.xn--1ug; ; xn--hhbb5hc956w.; [B1] # ٨نم٨ᩝ.
+٨نم٨ᩝ.‍; ; [B1, C2]; xn--hhbb5hc956w.xn--1ug; ; xn--hhbb5hc956w.; [B1] # ٨نم٨ᩝ.
+xn--hhbb5hc956w.; ٨نم٨ᩝ.; [B1]; xn--hhbb5hc956w.; ; ; # ٨نم٨ᩝ.
+xn--hhbb5hc956w.xn--1ug; ٨نم٨ᩝ.‍; [B1, C2]; xn--hhbb5hc956w.xn--1ug; ; ; # ٨نم٨ᩝ.
+𝟘.Ⴇ󀳑ﵐ񫃱; 0.Ⴇ󀳑تجم񫃱; [B1, B5, P1, V6]; 0.xn--pgbe9e344c2725svff8b; ; ; # 0.Ⴇتجم
+0.Ⴇ󀳑تجم񫃱; ; [B1, B5, P1, V6]; 0.xn--pgbe9e344c2725svff8b; ; ; # 0.Ⴇتجم
+0.ⴇ󀳑تجم񫃱; ; [B1, B5, P1, V6]; 0.xn--pgbe9ez79qd207lvff8b; ; ; # 0.ⴇتجم
+0.xn--pgbe9ez79qd207lvff8b; 0.ⴇ󀳑تجم񫃱; [B1, B5, V6]; 0.xn--pgbe9ez79qd207lvff8b; ; ; # 0.ⴇتجم
+0.xn--pgbe9e344c2725svff8b; 0.Ⴇ󀳑تجم񫃱; [B1, B5, V6]; 0.xn--pgbe9e344c2725svff8b; ; ; # 0.Ⴇتجم
+𝟘.ⴇ󀳑ﵐ񫃱; 0.ⴇ󀳑تجم񫃱; [B1, B5, P1, V6]; 0.xn--pgbe9ez79qd207lvff8b; ; ; # 0.ⴇتجم
+𑇀▍.⁞ᠰ; ; [V5]; xn--9zh3057f.xn--j7e103b; ; ; # 𑇀▍.⁞ᠰ
+xn--9zh3057f.xn--j7e103b; 𑇀▍.⁞ᠰ; [V5]; xn--9zh3057f.xn--j7e103b; ; ; # 𑇀▍.⁞ᠰ
+‍-ٺ.򏯩; ; [B1, C2, P1, V6]; xn----qrc357q.xn--ts49b; ; xn----qrc.xn--ts49b; [B1, P1, V3, V6] # -ٺ.
+xn----qrc.xn--ts49b; -ٺ.򏯩; [B1, V3, V6]; xn----qrc.xn--ts49b; ; ; # -ٺ.
+xn----qrc357q.xn--ts49b; ‍-ٺ.򏯩; [B1, C2, V6]; xn----qrc357q.xn--ts49b; ; ; # -ٺ.
+ᠢ𐮂𐫘寐。‌≯✳; ᠢ𐮂𐫘寐.‌≯✳; [B1, B5, C1, P1, V6]; xn--46e6675axzzhota.xn--0ug06gu8f; ; xn--46e6675axzzhota.xn--hdh99p; [B1, B5, P1, V6] # ᠢ𐮂𐫘寐.≯✳
+ᠢ𐮂𐫘寐。‌≯✳; ᠢ𐮂𐫘寐.‌≯✳; [B1, B5, C1, P1, V6]; xn--46e6675axzzhota.xn--0ug06gu8f; ; xn--46e6675axzzhota.xn--hdh99p; [B1, B5, P1, V6] # ᠢ𐮂𐫘寐.≯✳
+ᠢ𐮂𐫘寐。‌≯✳; ᠢ𐮂𐫘寐.‌≯✳; [B1, B5, C1, P1, V6]; xn--46e6675axzzhota.xn--0ug06gu8f; ; xn--46e6675axzzhota.xn--hdh99p; [B1, B5, P1, V6] # ᠢ𐮂𐫘寐.≯✳
+ᠢ𐮂𐫘寐。‌≯✳; ᠢ𐮂𐫘寐.‌≯✳; [B1, B5, C1, P1, V6]; xn--46e6675axzzhota.xn--0ug06gu8f; ; xn--46e6675axzzhota.xn--hdh99p; [B1, B5, P1, V6] # ᠢ𐮂𐫘寐.≯✳
+xn--46e6675axzzhota.xn--hdh99p; ᠢ𐮂𐫘寐.≯✳; [B1, B5, V6]; xn--46e6675axzzhota.xn--hdh99p; ; ; # ᠢ𐮂𐫘寐.≯✳
+xn--46e6675axzzhota.xn--0ug06gu8f; ᠢ𐮂𐫘寐.‌≯✳; [B1, B5, C1, V6]; xn--46e6675axzzhota.xn--0ug06gu8f; ; ; # ᠢ𐮂𐫘寐.≯✳
+‍。󸲜ႺႴ𞨇; ‍.󸲜ႺႴ𞨇; [B1, B5, B6, C2, P1, V6]; xn--1ug.xn--sndl01647an3h1h; ; .xn--sndl01647an3h1h; [B5, B6, P1, V6, A4_2] # .ႺႴ
+‍。󸲜ႺႴ𞨇; ‍.󸲜ႺႴ𞨇; [B1, B5, B6, C2, P1, V6]; xn--1ug.xn--sndl01647an3h1h; ; .xn--sndl01647an3h1h; [B5, B6, P1, V6, A4_2] # .ႺႴ
+‍。󸲜ⴚⴔ𞨇; ‍.󸲜ⴚⴔ𞨇; [B1, B5, B6, C2, P1, V6]; xn--1ug.xn--cljl81825an3r4h; ; .xn--cljl81825an3r4h; [B5, B6, P1, V6, A4_2] # .ⴚⴔ
+‍。󸲜Ⴚⴔ𞨇; ‍.󸲜Ⴚⴔ𞨇; [B1, B5, B6, C2, P1, V6]; xn--1ug.xn--ynd036lq981an3r4h; ; .xn--ynd036lq981an3r4h; [B5, B6, P1, V6, A4_2] # .Ⴚⴔ
+.xn--ynd036lq981an3r4h; .󸲜Ⴚⴔ𞨇; [B5, B6, V6, X4_2]; .xn--ynd036lq981an3r4h; [B5, B6, V6, A4_2]; ; # .Ⴚⴔ
+xn--1ug.xn--ynd036lq981an3r4h; ‍.󸲜Ⴚⴔ𞨇; [B1, B5, B6, C2, V6]; xn--1ug.xn--ynd036lq981an3r4h; ; ; # .Ⴚⴔ
+.xn--cljl81825an3r4h; .󸲜ⴚⴔ𞨇; [B5, B6, V6, X4_2]; .xn--cljl81825an3r4h; [B5, B6, V6, A4_2]; ; # .ⴚⴔ
+xn--1ug.xn--cljl81825an3r4h; ‍.󸲜ⴚⴔ𞨇; [B1, B5, B6, C2, V6]; xn--1ug.xn--cljl81825an3r4h; ; ; # .ⴚⴔ
+.xn--sndl01647an3h1h; .󸲜ႺႴ𞨇; [B5, B6, V6, X4_2]; .xn--sndl01647an3h1h; [B5, B6, V6, A4_2]; ; # .ႺႴ
+xn--1ug.xn--sndl01647an3h1h; ‍.󸲜ႺႴ𞨇; [B1, B5, B6, C2, V6]; xn--1ug.xn--sndl01647an3h1h; ; ; # .ႺႴ
+‍。󸲜ⴚⴔ𞨇; ‍.󸲜ⴚⴔ𞨇; [B1, B5, B6, C2, P1, V6]; xn--1ug.xn--cljl81825an3r4h; ; .xn--cljl81825an3r4h; [B5, B6, P1, V6, A4_2] # .ⴚⴔ
+‍。󸲜Ⴚⴔ𞨇; ‍.󸲜Ⴚⴔ𞨇; [B1, B5, B6, C2, P1, V6]; xn--1ug.xn--ynd036lq981an3r4h; ; .xn--ynd036lq981an3r4h; [B5, B6, P1, V6, A4_2] # .Ⴚⴔ
+-3.‍ヌᢕ; ; [C2, V3]; -3.xn--fbf739aq5o; ; -3.xn--fbf115j; [V3] # -3.ヌᢕ
+-3.xn--fbf115j; -3.ヌᢕ; [V3]; -3.xn--fbf115j; ; ; # -3.ヌᢕ
+-3.xn--fbf739aq5o; -3.‍ヌᢕ; [C2, V3]; -3.xn--fbf739aq5o; ; ; # -3.ヌᢕ
+🂃٦ß‍。󠠂򭰍𞩒-; 🂃٦ß‍.󠠂򭰍𞩒-; [B1, C2, P1, V3, V6]; xn--zca34z68yzu83b.xn----nz8rh7531csznt; ; xn--ss-pyd98921c.xn----nz8rh7531csznt; [B1, P1, V3, V6] # 🂃٦ß.-
+🂃٦SS‍。󠠂򭰍𞩒-; 🂃٦ss‍.󠠂򭰍𞩒-; [B1, C2, P1, V3, V6]; xn--ss-pyd483x5k99b.xn----nz8rh7531csznt; ; xn--ss-pyd98921c.xn----nz8rh7531csznt; [B1, P1, V3, V6] # 🂃٦ss.-
+🂃٦ss‍。󠠂򭰍𞩒-; 🂃٦ss‍.󠠂򭰍𞩒-; [B1, C2, P1, V3, V6]; xn--ss-pyd483x5k99b.xn----nz8rh7531csznt; ; xn--ss-pyd98921c.xn----nz8rh7531csznt; [B1, P1, V3, V6] # 🂃٦ss.-
+xn--ss-pyd98921c.xn----nz8rh7531csznt; 🂃٦ss.󠠂򭰍𞩒-; [B1, V3, V6]; xn--ss-pyd98921c.xn----nz8rh7531csznt; ; ; # 🂃٦ss.-
+xn--ss-pyd483x5k99b.xn----nz8rh7531csznt; 🂃٦ss‍.󠠂򭰍𞩒-; [B1, C2, V3, V6]; xn--ss-pyd483x5k99b.xn----nz8rh7531csznt; ; ; # 🂃٦ss.-
+xn--zca34z68yzu83b.xn----nz8rh7531csznt; 🂃٦ß‍.󠠂򭰍𞩒-; [B1, C2, V3, V6]; xn--zca34z68yzu83b.xn----nz8rh7531csznt; ; ; # 🂃٦ß.-
+🂃٦Ss‍。󠠂򭰍𞩒-; 🂃٦ss‍.󠠂򭰍𞩒-; [B1, C2, P1, V3, V6]; xn--ss-pyd483x5k99b.xn----nz8rh7531csznt; ; xn--ss-pyd98921c.xn----nz8rh7531csznt; [B1, P1, V3, V6] # 🂃٦ss.-
+ꇟ-𐾺ڟ。򰀺‌; ꇟ-𐾺ڟ.򰀺‌; [B5, B6, C1, P1, V6]; xn----utc4430jd3zd.xn--0ugx6670i; ; xn----utc4430jd3zd.xn--bp20d; [B5, B6, P1, V6] # ꇟ-𐾺ڟ.
+xn----utc4430jd3zd.xn--bp20d; ꇟ-𐾺ڟ.򰀺; [B5, B6, V6]; xn----utc4430jd3zd.xn--bp20d; ; ; # ꇟ-𐾺ڟ.
+xn----utc4430jd3zd.xn--0ugx6670i; ꇟ-𐾺ڟ.򰀺‌; [B5, B6, C1, V6]; xn----utc4430jd3zd.xn--0ugx6670i; ; ; # ꇟ-𐾺ڟ.
+٥.҄𐨗𝩋𴤃; ; [B1, P1, V5, V6]; xn--eib.xn--n3a0405kus8eft5l; ; ; # ٥.҄𐨗𝩋
+xn--eib.xn--n3a0405kus8eft5l; ٥.҄𐨗𝩋𴤃; [B1, V5, V6]; xn--eib.xn--n3a0405kus8eft5l; ; ; # ٥.҄𐨗𝩋
+-.񱼓ى𐨿; ; [B1, B5, B6, P1, V3, V6]; -.xn--lhb4124khbq4b; ; ; # -.ى𐨿
+-.xn--lhb4124khbq4b; -.񱼓ى𐨿; [B1, B5, B6, V3, V6]; -.xn--lhb4124khbq4b; ; ; # -.ى𐨿
+󾬨ς.𞶙녫ß; ; [B2, B3, P1, V6]; xn--3xa96659r.xn--zca5051g4h4i; ; xn--4xa76659r.xn--ss-d64i8755h; # ς.녫ß
+󾬨ς.𞶙녫ß; 󾬨ς.𞶙녫ß; [B2, B3, P1, V6]; xn--3xa96659r.xn--zca5051g4h4i; ; xn--4xa76659r.xn--ss-d64i8755h; # ς.녫ß
+󾬨Σ.𞶙녫SS; 󾬨σ.𞶙녫ss; [B2, B3, P1, V6]; xn--4xa76659r.xn--ss-d64i8755h; ; ; # σ.녫ss
+󾬨Σ.𞶙녫SS; 󾬨σ.𞶙녫ss; [B2, B3, P1, V6]; xn--4xa76659r.xn--ss-d64i8755h; ; ; # σ.녫ss
+󾬨σ.𞶙녫ss; ; [B2, B3, P1, V6]; xn--4xa76659r.xn--ss-d64i8755h; ; ; # σ.녫ss
+󾬨σ.𞶙녫ss; 󾬨σ.𞶙녫ss; [B2, B3, P1, V6]; xn--4xa76659r.xn--ss-d64i8755h; ; ; # σ.녫ss
+󾬨Σ.𞶙녫ss; 󾬨σ.𞶙녫ss; [B2, B3, P1, V6]; xn--4xa76659r.xn--ss-d64i8755h; ; ; # σ.녫ss
+󾬨Σ.𞶙녫ss; 󾬨σ.𞶙녫ss; [B2, B3, P1, V6]; xn--4xa76659r.xn--ss-d64i8755h; ; ; # σ.녫ss
+󾬨Σ.𞶙녫Ss; 󾬨σ.𞶙녫ss; [B2, B3, P1, V6]; xn--4xa76659r.xn--ss-d64i8755h; ; ; # σ.녫ss
+󾬨Σ.𞶙녫Ss; 󾬨σ.𞶙녫ss; [B2, B3, P1, V6]; xn--4xa76659r.xn--ss-d64i8755h; ; ; # σ.녫ss
+xn--4xa76659r.xn--ss-d64i8755h; 󾬨σ.𞶙녫ss; [B2, B3, V6]; xn--4xa76659r.xn--ss-d64i8755h; ; ; # σ.녫ss
+󾬨Σ.𞶙녫ß; 󾬨σ.𞶙녫ß; [B2, B3, P1, V6]; xn--4xa76659r.xn--zca5051g4h4i; ; xn--4xa76659r.xn--ss-d64i8755h; # σ.녫ß
+󾬨Σ.𞶙녫ß; 󾬨σ.𞶙녫ß; [B2, B3, P1, V6]; xn--4xa76659r.xn--zca5051g4h4i; ; xn--4xa76659r.xn--ss-d64i8755h; # σ.녫ß
+󾬨σ.𞶙녫ß; ; [B2, B3, P1, V6]; xn--4xa76659r.xn--zca5051g4h4i; ; xn--4xa76659r.xn--ss-d64i8755h; # σ.녫ß
+󾬨σ.𞶙녫ß; 󾬨σ.𞶙녫ß; [B2, B3, P1, V6]; xn--4xa76659r.xn--zca5051g4h4i; ; xn--4xa76659r.xn--ss-d64i8755h; # σ.녫ß
+xn--4xa76659r.xn--zca5051g4h4i; 󾬨σ.𞶙녫ß; [B2, B3, V6]; xn--4xa76659r.xn--zca5051g4h4i; ; ; # σ.녫ß
+xn--3xa96659r.xn--zca5051g4h4i; 󾬨ς.𞶙녫ß; [B2, B3, V6]; xn--3xa96659r.xn--zca5051g4h4i; ; ; # ς.녫ß
+Ⅎ្‍。≠‍‌; Ⅎ្‍.≠‍‌; [C1, C2, P1, V6]; xn--u4e823bcza.xn--0ugb89o; ; xn--u4e319b.xn--1ch; [P1, V6] # Ⅎ្.≠
+Ⅎ្‍。≠‍‌; Ⅎ្‍.≠‍‌; [C1, C2, P1, V6]; xn--u4e823bcza.xn--0ugb89o; ; xn--u4e319b.xn--1ch; [P1, V6] # Ⅎ្.≠
+Ⅎ្‍。≠‍‌; Ⅎ្‍.≠‍‌; [C1, C2, P1, V6]; xn--u4e823bcza.xn--0ugb89o; ; xn--u4e319b.xn--1ch; [P1, V6] # Ⅎ្.≠
+Ⅎ្‍。≠‍‌; Ⅎ្‍.≠‍‌; [C1, C2, P1, V6]; xn--u4e823bcza.xn--0ugb89o; ; xn--u4e319b.xn--1ch; [P1, V6] # Ⅎ្.≠
+ⅎ្‍。≠‍‌; ⅎ្‍.≠‍‌; [C1, C2, P1, V6]; xn--u4e823bq1a.xn--0ugb89o; ; xn--u4e969b.xn--1ch; [P1, V6] # ⅎ្.≠
+ⅎ្‍。≠‍‌; ⅎ្‍.≠‍‌; [C1, C2, P1, V6]; xn--u4e823bq1a.xn--0ugb89o; ; xn--u4e969b.xn--1ch; [P1, V6] # ⅎ្.≠
+xn--u4e969b.xn--1ch; ⅎ្.≠; [V6]; xn--u4e969b.xn--1ch; ; ; # ⅎ្.≠
+xn--u4e823bq1a.xn--0ugb89o; ⅎ្‍.≠‍‌; [C1, C2, V6]; xn--u4e823bq1a.xn--0ugb89o; ; ; # ⅎ្.≠
+xn--u4e319b.xn--1ch; Ⅎ្.≠; [V6]; xn--u4e319b.xn--1ch; ; ; # Ⅎ្.≠
+xn--u4e823bcza.xn--0ugb89o; Ⅎ្‍.≠‍‌; [C1, C2, V6]; xn--u4e823bcza.xn--0ugb89o; ; ; # Ⅎ្.≠
+ⅎ្‍。≠‍‌; ⅎ្‍.≠‍‌; [C1, C2, P1, V6]; xn--u4e823bq1a.xn--0ugb89o; ; xn--u4e969b.xn--1ch; [P1, V6] # ⅎ្.≠
+ⅎ្‍。≠‍‌; ⅎ្‍.≠‍‌; [C1, C2, P1, V6]; xn--u4e823bq1a.xn--0ugb89o; ; xn--u4e969b.xn--1ch; [P1, V6] # ⅎ្.≠
+𐋺꫶꥓󧦉.‌᜔ڏ; 𐋺꫶꥓󧦉.‌᜔ڏ; [B1, C1, P1, V6]; xn--3j9a14ak27osbz2o.xn--ljb175f1wg; ; xn--3j9a14ak27osbz2o.xn--ljb175f; [B1, P1, V5, V6] # 𐋺꫶꥓.᜔ڏ
+𐋺꫶꥓󧦉.‌᜔ڏ; ; [B1, C1, P1, V6]; xn--3j9a14ak27osbz2o.xn--ljb175f1wg; ; xn--3j9a14ak27osbz2o.xn--ljb175f; [B1, P1, V5, V6] # 𐋺꫶꥓.᜔ڏ
+xn--3j9a14ak27osbz2o.xn--ljb175f; 𐋺꫶꥓󧦉.᜔ڏ; [B1, V5, V6]; xn--3j9a14ak27osbz2o.xn--ljb175f; ; ; # 𐋺꫶꥓.᜔ڏ
+xn--3j9a14ak27osbz2o.xn--ljb175f1wg; 𐋺꫶꥓󧦉.‌᜔ڏ; [B1, C1, V6]; xn--3j9a14ak27osbz2o.xn--ljb175f1wg; ; ; # 𐋺꫶꥓.᜔ڏ
+񺔯ྨ.≯; 񺔯ྨ.≯; [P1, V6]; xn--4fd57150h.xn--hdh; ; ; # ྨ.≯
+񺔯ྨ.≯; 񺔯ྨ.≯; [P1, V6]; xn--4fd57150h.xn--hdh; ; ; # ྨ.≯
+񺔯ྨ.≯; ; [P1, V6]; xn--4fd57150h.xn--hdh; ; ; # ྨ.≯
+񺔯ྨ.≯; 񺔯ྨ.≯; [P1, V6]; xn--4fd57150h.xn--hdh; ; ; # ྨ.≯
+xn--4fd57150h.xn--hdh; 񺔯ྨ.≯; [V6]; xn--4fd57150h.xn--hdh; ; ; # ྨ.≯
+‍𞡄Ⴓ.𐇽; ‍𞡄Ⴓ.𐇽; [B1, B3, B6, C2, P1, V5, V6]; xn--rnd379ex885a.xn--m27c; ; xn--rnd5552v.xn--m27c; [B1, B2, B3, B6, P1, V5, V6] # 𞡄Ⴓ.𐇽
+‍𞡄Ⴓ.𐇽; ; [B1, B3, B6, C2, P1, V5, V6]; xn--rnd379ex885a.xn--m27c; ; xn--rnd5552v.xn--m27c; [B1, B2, B3, B6, P1, V5, V6] # 𞡄Ⴓ.𐇽
+‍𞡄ⴓ.𐇽; ; [B1, B3, B6, C2, V5]; xn--1ugz52c4i16a.xn--m27c; ; xn--blj7492l.xn--m27c; [B1, B2, B3, B6, V5] # 𞡄ⴓ.𐇽
+xn--blj7492l.xn--m27c; 𞡄ⴓ.𐇽; [B1, B2, B3, B6, V5]; xn--blj7492l.xn--m27c; ; ; # 𞡄ⴓ.𐇽
+xn--1ugz52c4i16a.xn--m27c; ‍𞡄ⴓ.𐇽; [B1, B3, B6, C2, V5]; xn--1ugz52c4i16a.xn--m27c; ; ; # 𞡄ⴓ.𐇽
+xn--rnd5552v.xn--m27c; 𞡄Ⴓ.𐇽; [B1, B2, B3, B6, V5, V6]; xn--rnd5552v.xn--m27c; ; ; # 𞡄Ⴓ.𐇽
+xn--rnd379ex885a.xn--m27c; ‍𞡄Ⴓ.𐇽; [B1, B3, B6, C2, V5, V6]; xn--rnd379ex885a.xn--m27c; ; ; # 𞡄Ⴓ.𐇽
+‍𞡄ⴓ.𐇽; ‍𞡄ⴓ.𐇽; [B1, B3, B6, C2, V5]; xn--1ugz52c4i16a.xn--m27c; ; xn--blj7492l.xn--m27c; [B1, B2, B3, B6, V5] # 𞡄ⴓ.𐇽
+𐪒ß꣪.ᡤ; 𐪒ß꣪.ᡤ; [B2, B3]; xn--zca2517f2hvc.xn--08e; ; xn--ss-tu9hw933a.xn--08e; # 𐪒ß꣪.ᡤ
+𐪒ß꣪.ᡤ; ; [B2, B3]; xn--zca2517f2hvc.xn--08e; ; xn--ss-tu9hw933a.xn--08e; # 𐪒ß꣪.ᡤ
+𐪒SS꣪.ᡤ; 𐪒ss꣪.ᡤ; [B2, B3]; xn--ss-tu9hw933a.xn--08e; ; ; # 𐪒ss꣪.ᡤ
+𐪒ss꣪.ᡤ; ; [B2, B3]; xn--ss-tu9hw933a.xn--08e; ; ; # 𐪒ss꣪.ᡤ
+xn--ss-tu9hw933a.xn--08e; 𐪒ss꣪.ᡤ; [B2, B3]; xn--ss-tu9hw933a.xn--08e; ; ; # 𐪒ss꣪.ᡤ
+xn--zca2517f2hvc.xn--08e; 𐪒ß꣪.ᡤ; [B2, B3]; xn--zca2517f2hvc.xn--08e; ; ; # 𐪒ß꣪.ᡤ
+𐪒SS꣪.ᡤ; 𐪒ss꣪.ᡤ; [B2, B3]; xn--ss-tu9hw933a.xn--08e; ; ; # 𐪒ss꣪.ᡤ
+𐪒ss꣪.ᡤ; 𐪒ss꣪.ᡤ; [B2, B3]; xn--ss-tu9hw933a.xn--08e; ; ; # 𐪒ss꣪.ᡤ
+𐪒Ss꣪.ᡤ; 𐪒ss꣪.ᡤ; [B2, B3]; xn--ss-tu9hw933a.xn--08e; ; ; # 𐪒ss꣪.ᡤ
+𐪒Ss꣪.ᡤ; 𐪒ss꣪.ᡤ; [B2, B3]; xn--ss-tu9hw933a.xn--08e; ; ; # 𐪒ss꣪.ᡤ
+𐨿󠆌鸮𑚶.ς; 𐨿鸮𑚶.ς; [V5]; xn--l76a726rt2h.xn--3xa; ; xn--l76a726rt2h.xn--4xa; # 𐨿鸮𑚶.ς
+𐨿󠆌鸮𑚶.Σ; 𐨿鸮𑚶.σ; [V5]; xn--l76a726rt2h.xn--4xa; ; ; # 𐨿鸮𑚶.σ
+𐨿󠆌鸮𑚶.σ; 𐨿鸮𑚶.σ; [V5]; xn--l76a726rt2h.xn--4xa; ; ; # 𐨿鸮𑚶.σ
+xn--l76a726rt2h.xn--4xa; 𐨿鸮𑚶.σ; [V5]; xn--l76a726rt2h.xn--4xa; ; ; # 𐨿鸮𑚶.σ
+xn--l76a726rt2h.xn--3xa; 𐨿鸮𑚶.ς; [V5]; xn--l76a726rt2h.xn--3xa; ; ; # 𐨿鸮𑚶.ς
+⒗𞤬。-𑚶; ⒗𞤬.-𑚶; [B1, P1, V3, V6]; xn--8shw466n.xn----4j0j; ; ; # ⒗𞤬.-𑚶
+16.𞤬。-𑚶; 16.𞤬.-𑚶; [B1, V3]; 16.xn--ke6h.xn----4j0j; ; ; # 16.𞤬.-𑚶
+16.𞤊。-𑚶; 16.𞤬.-𑚶; [B1, V3]; 16.xn--ke6h.xn----4j0j; ; ; # 16.𞤬.-𑚶
+16.xn--ke6h.xn----4j0j; 16.𞤬.-𑚶; [B1, V3]; 16.xn--ke6h.xn----4j0j; ; ; # 16.𞤬.-𑚶
+⒗𞤊。-𑚶; ⒗𞤬.-𑚶; [B1, P1, V3, V6]; xn--8shw466n.xn----4j0j; ; ; # ⒗𞤬.-𑚶
+xn--8shw466n.xn----4j0j; ⒗𞤬.-𑚶; [B1, V3, V6]; xn--8shw466n.xn----4j0j; ; ; # ⒗𞤬.-𑚶
+ࢳ𞤿⾫。𐹣ڏ⒈; ࢳ𞤿隹.𐹣ڏ⒈; [B1, B2, B3, P1, V6]; xn--8yb0383efiwk.xn--ljb064mol4n; ; ; # ࢳ𞤿隹.𐹣ڏ⒈
+ࢳ𞤿隹。𐹣ڏ1.; ࢳ𞤿隹.𐹣ڏ1.; [B1, B2, B3]; xn--8yb0383efiwk.xn--1-wsc3373r.; ; ; # ࢳ𞤿隹.𐹣ڏ1.
+ࢳ𞤝隹。𐹣ڏ1.; ࢳ𞤿隹.𐹣ڏ1.; [B1, B2, B3]; xn--8yb0383efiwk.xn--1-wsc3373r.; ; ; # ࢳ𞤿隹.𐹣ڏ1.
+xn--8yb0383efiwk.xn--1-wsc3373r.; ࢳ𞤿隹.𐹣ڏ1.; [B1, B2, B3]; xn--8yb0383efiwk.xn--1-wsc3373r.; ; ; # ࢳ𞤿隹.𐹣ڏ1.
+ࢳ𞤝⾫。𐹣ڏ⒈; ࢳ𞤿隹.𐹣ڏ⒈; [B1, B2, B3, P1, V6]; xn--8yb0383efiwk.xn--ljb064mol4n; ; ; # ࢳ𞤿隹.𐹣ڏ⒈
+xn--8yb0383efiwk.xn--ljb064mol4n; ࢳ𞤿隹.𐹣ڏ⒈; [B1, B2, B3, V6]; xn--8yb0383efiwk.xn--ljb064mol4n; ; ; # ࢳ𞤿隹.𐹣ڏ⒈
+␳𚎛𝟧١.ᡢ8ི؀; ␳𚎛5١.ᡢ8ི؀; [B5, B6, P1, V6]; xn--5-bqc410un435a.xn--8-rkc763epjj; ; ; # 5١.ᡢ8ི
+␳𚎛5١.ᡢ8ི؀; ; [B5, B6, P1, V6]; xn--5-bqc410un435a.xn--8-rkc763epjj; ; ; # 5١.ᡢ8ི
+xn--5-bqc410un435a.xn--8-rkc763epjj; ␳𚎛5١.ᡢ8ི؀; [B5, B6, V6]; xn--5-bqc410un435a.xn--8-rkc763epjj; ; ; # 5١.ᡢ8ི
+𐹠.🄀⒒-󨰈; ; [B1, P1, V6]; xn--7n0d.xn----xcp9757q1s13g; ; ; # 𐹠.🄀⒒-
+𐹠.0.11.-󨰈; ; [B1, P1, V3, V6]; xn--7n0d.0.11.xn----8j07m; ; ; # 𐹠.0.11.-
+xn--7n0d.0.11.xn----8j07m; 𐹠.0.11.-󨰈; [B1, V3, V6]; xn--7n0d.0.11.xn----8j07m; ; ; # 𐹠.0.11.-
+xn--7n0d.xn----xcp9757q1s13g; 𐹠.🄀⒒-󨰈; [B1, V6]; xn--7n0d.xn----xcp9757q1s13g; ; ; # 𐹠.🄀⒒-
+ς-。‌𝟭-; ς-.‌1-; [C1, V3]; xn----xmb.xn--1--i1t; ; xn----zmb.1-; [V3] # ς-.1-
+ς-。‌1-; ς-.‌1-; [C1, V3]; xn----xmb.xn--1--i1t; ; xn----zmb.1-; [V3] # ς-.1-
+Σ-。‌1-; σ-.‌1-; [C1, V3]; xn----zmb.xn--1--i1t; ; xn----zmb.1-; [V3] # σ-.1-
+σ-。‌1-; σ-.‌1-; [C1, V3]; xn----zmb.xn--1--i1t; ; xn----zmb.1-; [V3] # σ-.1-
+xn----zmb.1-; σ-.1-; [V3]; xn----zmb.1-; ; ; # σ-.1-
+xn----zmb.xn--1--i1t; σ-.‌1-; [C1, V3]; xn----zmb.xn--1--i1t; ; ; # σ-.1-
+xn----xmb.xn--1--i1t; ς-.‌1-; [C1, V3]; xn----xmb.xn--1--i1t; ; ; # ς-.1-
+Σ-。‌𝟭-; σ-.‌1-; [C1, V3]; xn----zmb.xn--1--i1t; ; xn----zmb.1-; [V3] # σ-.1-
+σ-。‌𝟭-; σ-.‌1-; [C1, V3]; xn----zmb.xn--1--i1t; ; xn----zmb.1-; [V3] # σ-.1-
+᜴-ೢ.󠄩Ⴄ; ᜴-ೢ.Ⴄ; [P1, V5, V6]; xn----ggf830f.xn--cnd; ; ; # ᜴-ೢ.Ⴄ
+᜴-ೢ.󠄩Ⴄ; ᜴-ೢ.Ⴄ; [P1, V5, V6]; xn----ggf830f.xn--cnd; ; ; # ᜴-ೢ.Ⴄ
+᜴-ೢ.󠄩ⴄ; ᜴-ೢ.ⴄ; [V5]; xn----ggf830f.xn--vkj; ; ; # ᜴-ೢ.ⴄ
+xn----ggf830f.xn--vkj; ᜴-ೢ.ⴄ; [V5]; xn----ggf830f.xn--vkj; ; ; # ᜴-ೢ.ⴄ
+xn----ggf830f.xn--cnd; ᜴-ೢ.Ⴄ; [V5, V6]; xn----ggf830f.xn--cnd; ; ; # ᜴-ೢ.Ⴄ
+᜴-ೢ.󠄩ⴄ; ᜴-ೢ.ⴄ; [V5]; xn----ggf830f.xn--vkj; ; ; # ᜴-ೢ.ⴄ
+򭈗♋ڻ𐦥。॔⒈; 򭈗♋ڻ𐦥.॔⒈; [B1, B5, B6, P1, V5, V6]; xn--ukb372n129m3rs7f.xn--u3b240l; ; ; # ♋ڻ𐦥.॔⒈
+򭈗♋ڻ𐦥。॔1.; 򭈗♋ڻ𐦥.॔1.; [B1, B5, B6, P1, V5, V6]; xn--ukb372n129m3rs7f.xn--1-fyd.; ; ; # ♋ڻ𐦥.॔1.
+xn--ukb372n129m3rs7f.xn--1-fyd.; 򭈗♋ڻ𐦥.॔1.; [B1, B5, B6, V5, V6]; xn--ukb372n129m3rs7f.xn--1-fyd.; ; ; # ♋ڻ𐦥.॔1.
+xn--ukb372n129m3rs7f.xn--u3b240l; 򭈗♋ڻ𐦥.॔⒈; [B1, B5, B6, V5, V6]; xn--ukb372n129m3rs7f.xn--u3b240l; ; ; # ♋ڻ𐦥.॔⒈
+֤.ہ᪳‌; ֤.ہ᪳‌; [B1, B3, B6, C1, V5]; xn--vcb.xn--0kb623hm1d; ; xn--vcb.xn--0kb623h; [B1, B3, B6, V5] # ֤.ہ᪳
+֤.ہ᪳‌; ; [B1, B3, B6, C1, V5]; xn--vcb.xn--0kb623hm1d; ; xn--vcb.xn--0kb623h; [B1, B3, B6, V5] # ֤.ہ᪳
+xn--vcb.xn--0kb623h; ֤.ہ᪳; [B1, B3, B6, V5]; xn--vcb.xn--0kb623h; ; ; # ֤.ہ᪳
+xn--vcb.xn--0kb623hm1d; ֤.ہ᪳‌; [B1, B3, B6, C1, V5]; xn--vcb.xn--0kb623hm1d; ; ; # ֤.ہ᪳
+񢭏ࡆ≮્.𞦊; 񢭏ࡆ≮્.𞦊; [B5, B6, P1, V6]; xn--4vb80kq29ayo62l.xn--8g6h; ; ; # ࡆ≮્.
+񢭏ࡆ≮્.𞦊; 񢭏ࡆ≮્.𞦊; [B5, B6, P1, V6]; xn--4vb80kq29ayo62l.xn--8g6h; ; ; # ࡆ≮્.
+񢭏ࡆ≮્.𞦊; ; [B5, B6, P1, V6]; xn--4vb80kq29ayo62l.xn--8g6h; ; ; # ࡆ≮્.
+񢭏ࡆ≮્.𞦊; 񢭏ࡆ≮્.𞦊; [B5, B6, P1, V6]; xn--4vb80kq29ayo62l.xn--8g6h; ; ; # ࡆ≮્.
+xn--4vb80kq29ayo62l.xn--8g6h; 񢭏ࡆ≮્.𞦊; [B5, B6, V6]; xn--4vb80kq29ayo62l.xn--8g6h; ; ; # ࡆ≮્.
+‍。𞀘⒈ꡍ擉; ‍.𞀘⒈ꡍ擉; [C2, P1, V5, V6]; xn--1ug.xn--tsh026uql4bew9p; ; .xn--tsh026uql4bew9p; [P1, V5, V6, A4_2] # .𞀘⒈ꡍ擉
+‍。𞀘1.ꡍ擉; ‍.𞀘1.ꡍ擉; [C2, V5]; xn--1ug.xn--1-1p4r.xn--s7uv61m; ; .xn--1-1p4r.xn--s7uv61m; [V5, A4_2] # .𞀘1.ꡍ擉
+.xn--1-1p4r.xn--s7uv61m; .𞀘1.ꡍ擉; [V5, X4_2]; .xn--1-1p4r.xn--s7uv61m; [V5, A4_2]; ; # .𞀘1.ꡍ擉
+xn--1ug.xn--1-1p4r.xn--s7uv61m; ‍.𞀘1.ꡍ擉; [C2, V5]; xn--1ug.xn--1-1p4r.xn--s7uv61m; ; ; # .𞀘1.ꡍ擉
+.xn--tsh026uql4bew9p; .𞀘⒈ꡍ擉; [V5, V6, X4_2]; .xn--tsh026uql4bew9p; [V5, V6, A4_2]; ; # .𞀘⒈ꡍ擉
+xn--1ug.xn--tsh026uql4bew9p; ‍.𞀘⒈ꡍ擉; [C2, V5, V6]; xn--1ug.xn--tsh026uql4bew9p; ; ; # .𞀘⒈ꡍ擉
+₈ߋ.ﭤ≠; 8ߋ.ٿ≠; [B1, B3, P1, V6]; xn--8-zbd.xn--4ib883l; ; ; # 8ߋ.ٿ≠
+₈ߋ.ﭤ≠; 8ߋ.ٿ≠; [B1, B3, P1, V6]; xn--8-zbd.xn--4ib883l; ; ; # 8ߋ.ٿ≠
+8ߋ.ٿ≠; ; [B1, B3, P1, V6]; xn--8-zbd.xn--4ib883l; ; ; # 8ߋ.ٿ≠
+8ߋ.ٿ≠; 8ߋ.ٿ≠; [B1, B3, P1, V6]; xn--8-zbd.xn--4ib883l; ; ; # 8ߋ.ٿ≠
+xn--8-zbd.xn--4ib883l; 8ߋ.ٿ≠; [B1, B3, V6]; xn--8-zbd.xn--4ib883l; ; ; # 8ߋ.ٿ≠
+ᢡߞ򹐣.⒒ق𑍦; ; [B1, B5, P1, V6]; xn--5sb596fi873t.xn--ehb336mvy7n; ; ; # ᢡߞ.⒒ق𑍦
+ᢡߞ򹐣.11.ق𑍦; ; [B1, B5, P1, V6]; xn--5sb596fi873t.11.xn--ehb4198k; ; ; # ᢡߞ.11.ق𑍦
+xn--5sb596fi873t.11.xn--ehb4198k; ᢡߞ򹐣.11.ق𑍦; [B1, B5, V6]; xn--5sb596fi873t.11.xn--ehb4198k; ; ; # ᢡߞ.11.ق𑍦
+xn--5sb596fi873t.xn--ehb336mvy7n; ᢡߞ򹐣.⒒ق𑍦; [B1, B5, V6]; xn--5sb596fi873t.xn--ehb336mvy7n; ; ; # ᢡߞ.⒒ق𑍦
+่-𐹺𝟜.ͣۡ⒏; ่-𐹺4.ͣۡ⒏; [B1, P1, V5, V6]; xn---4-owiz479s.xn--eva20pjv9a; ; ; # ่-𐹺4.ͣۡ⒏
+่-𐹺4.ͣۡ8.; ; [B1, V5]; xn---4-owiz479s.xn--8-ihb69x.; ; ; # ่-𐹺4.ͣۡ8.
+xn---4-owiz479s.xn--8-ihb69x.; ่-𐹺4.ͣۡ8.; [B1, V5]; xn---4-owiz479s.xn--8-ihb69x.; ; ; # ่-𐹺4.ͣۡ8.
+xn---4-owiz479s.xn--eva20pjv9a; ่-𐹺4.ͣۡ⒏; [B1, V5, V6]; xn---4-owiz479s.xn--eva20pjv9a; ; ; # ่-𐹺4.ͣۡ⒏
+⫐。Ⴠ-󃐢; ⫐.Ⴠ-󃐢; [P1, V6]; xn--r3i.xn----z1g58579u; ; ; # ⫐.Ⴠ-
+⫐。Ⴠ-󃐢; ⫐.Ⴠ-󃐢; [P1, V6]; xn--r3i.xn----z1g58579u; ; ; # ⫐.Ⴠ-
+⫐。ⴠ-󃐢; ⫐.ⴠ-󃐢; [P1, V6]; xn--r3i.xn----2wst7439i; ; ; # ⫐.ⴠ-
+xn--r3i.xn----2wst7439i; ⫐.ⴠ-󃐢; [V6]; xn--r3i.xn----2wst7439i; ; ; # ⫐.ⴠ-
+xn--r3i.xn----z1g58579u; ⫐.Ⴠ-󃐢; [V6]; xn--r3i.xn----z1g58579u; ; ; # ⫐.Ⴠ-
+⫐。ⴠ-󃐢; ⫐.ⴠ-󃐢; [P1, V6]; xn--r3i.xn----2wst7439i; ; ; # ⫐.ⴠ-
+𑑂◊.⦟∠; 𑑂◊.⦟∠; [V5]; xn--01h3338f.xn--79g270a; ; ; # 𑑂◊.⦟∠
+𑑂◊.⦟∠; ; [V5]; xn--01h3338f.xn--79g270a; ; ; # 𑑂◊.⦟∠
+xn--01h3338f.xn--79g270a; 𑑂◊.⦟∠; [V5]; xn--01h3338f.xn--79g270a; ; ; # 𑑂◊.⦟∠
+𿌰-٢。󋸛ꡂ; 𿌰-٢.󋸛ꡂ; [B5, B6, P1, V6]; xn----dqc20828e.xn--bc9an2879c; ; ; # -٢.ꡂ
+xn----dqc20828e.xn--bc9an2879c; 𿌰-٢.󋸛ꡂ; [B5, B6, V6]; xn----dqc20828e.xn--bc9an2879c; ; ; # -٢.ꡂ
+ٸ。󠏬݁𞪭𐹪; يٴ.󠏬݁𞪭𐹪; [B1, P1, V6]; xn--mhb8f.xn--oob2585kfdsfsbo7h; ; ; # يٴ.݁𐹪
+يٴ。󠏬݁𞪭𐹪; يٴ.󠏬݁𞪭𐹪; [B1, P1, V6]; xn--mhb8f.xn--oob2585kfdsfsbo7h; ; ; # يٴ.݁𐹪
+xn--mhb8f.xn--oob2585kfdsfsbo7h; يٴ.󠏬݁𞪭𐹪; [B1, V6]; xn--mhb8f.xn--oob2585kfdsfsbo7h; ; ; # يٴ.݁𐹪
+𐫆ꌄ。‍ᣬ; 𐫆ꌄ.‍ᣬ; [B1, B2, B3, C2]; xn--y77ao18q.xn--wdf367a; ; xn--y77ao18q.xn--wdf; [B2, B3] # 𐫆ꌄ.ᣬ
+𐫆ꌄ。‍ᣬ; 𐫆ꌄ.‍ᣬ; [B1, B2, B3, C2]; xn--y77ao18q.xn--wdf367a; ; xn--y77ao18q.xn--wdf; [B2, B3] # 𐫆ꌄ.ᣬ
+xn--y77ao18q.xn--wdf; 𐫆ꌄ.ᣬ; [B2, B3]; xn--y77ao18q.xn--wdf; ; ; # 𐫆ꌄ.ᣬ
+xn--y77ao18q.xn--wdf367a; 𐫆ꌄ.‍ᣬ; [B1, B2, B3, C2]; xn--y77ao18q.xn--wdf367a; ; ; # 𐫆ꌄ.ᣬ
+₀٢。󅪞≯-; 0٢.󅪞≯-; [B1, B6, P1, V3, V6]; xn--0-dqc.xn----ogov3342l; ; ; # 0٢.≯-
+₀٢。󅪞≯-; 0٢.󅪞≯-; [B1, B6, P1, V3, V6]; xn--0-dqc.xn----ogov3342l; ; ; # 0٢.≯-
+0٢。󅪞≯-; 0٢.󅪞≯-; [B1, B6, P1, V3, V6]; xn--0-dqc.xn----ogov3342l; ; ; # 0٢.≯-
+0٢。󅪞≯-; 0٢.󅪞≯-; [B1, B6, P1, V3, V6]; xn--0-dqc.xn----ogov3342l; ; ; # 0٢.≯-
+xn--0-dqc.xn----ogov3342l; 0٢.󅪞≯-; [B1, B6, V3, V6]; xn--0-dqc.xn----ogov3342l; ; ; # 0٢.≯-
+̜𐹫-𞯃.𐋤ࡅ; ; [B1, P1, V5, V6]; xn----gdb7046r692g.xn--3vb1349j; ; ; # ̜𐹫-.𐋤ࡅ
+xn----gdb7046r692g.xn--3vb1349j; ̜𐹫-𞯃.𐋤ࡅ; [B1, V5, V6]; xn----gdb7046r692g.xn--3vb1349j; ; ; # ̜𐹫-.𐋤ࡅ
+≠。𝩑𐹩Ⴡ֔; ≠.𝩑𐹩Ⴡ֔; [B1, P1, V5, V6]; xn--1ch.xn--fcb538c649rypog; ; ; # ≠.𝩑𐹩Ⴡ֔
+≠。𝩑𐹩Ⴡ֔; ≠.𝩑𐹩Ⴡ֔; [B1, P1, V5, V6]; xn--1ch.xn--fcb538c649rypog; ; ; # ≠.𝩑𐹩Ⴡ֔
+≠。𝩑𐹩Ⴡ֔; ≠.𝩑𐹩Ⴡ֔; [B1, P1, V5, V6]; xn--1ch.xn--fcb538c649rypog; ; ; # ≠.𝩑𐹩Ⴡ֔
+≠。𝩑𐹩Ⴡ֔; ≠.𝩑𐹩Ⴡ֔; [B1, P1, V5, V6]; xn--1ch.xn--fcb538c649rypog; ; ; # ≠.𝩑𐹩Ⴡ֔
+≠。𝩑𐹩ⴡ֔; ≠.𝩑𐹩ⴡ֔; [B1, P1, V5, V6]; xn--1ch.xn--fcb363rk03mypug; ; ; # ≠.𝩑𐹩ⴡ֔
+≠。𝩑𐹩ⴡ֔; ≠.𝩑𐹩ⴡ֔; [B1, P1, V5, V6]; xn--1ch.xn--fcb363rk03mypug; ; ; # ≠.𝩑𐹩ⴡ֔
+xn--1ch.xn--fcb363rk03mypug; ≠.𝩑𐹩ⴡ֔; [B1, V5, V6]; xn--1ch.xn--fcb363rk03mypug; ; ; # ≠.𝩑𐹩ⴡ֔
+xn--1ch.xn--fcb538c649rypog; ≠.𝩑𐹩Ⴡ֔; [B1, V5, V6]; xn--1ch.xn--fcb538c649rypog; ; ; # ≠.𝩑𐹩Ⴡ֔
+≠。𝩑𐹩ⴡ֔; ≠.𝩑𐹩ⴡ֔; [B1, P1, V5, V6]; xn--1ch.xn--fcb363rk03mypug; ; ; # ≠.𝩑𐹩ⴡ֔
+≠。𝩑𐹩ⴡ֔; ≠.𝩑𐹩ⴡ֔; [B1, P1, V5, V6]; xn--1ch.xn--fcb363rk03mypug; ; ; # ≠.𝩑𐹩ⴡ֔
+𖫳≠.Ⴀ𐮀; ; [B1, B5, B6, P1, V5, V6]; xn--1ch9250k.xn--7md2659j; ; ; # 𖫳≠.Ⴀ𐮀
+𖫳≠.Ⴀ𐮀; 𖫳≠.Ⴀ𐮀; [B1, B5, B6, P1, V5, V6]; xn--1ch9250k.xn--7md2659j; ; ; # 𖫳≠.Ⴀ𐮀
+𖫳≠.ⴀ𐮀; 𖫳≠.ⴀ𐮀; [B1, B5, B6, P1, V5, V6]; xn--1ch9250k.xn--rkj6232e; ; ; # 𖫳≠.ⴀ𐮀
+𖫳≠.ⴀ𐮀; ; [B1, B5, B6, P1, V5, V6]; xn--1ch9250k.xn--rkj6232e; ; ; # 𖫳≠.ⴀ𐮀
+xn--1ch9250k.xn--rkj6232e; 𖫳≠.ⴀ𐮀; [B1, B5, B6, V5, V6]; xn--1ch9250k.xn--rkj6232e; ; ; # 𖫳≠.ⴀ𐮀
+xn--1ch9250k.xn--7md2659j; 𖫳≠.Ⴀ𐮀; [B1, B5, B6, V5, V6]; xn--1ch9250k.xn--7md2659j; ; ; # 𖫳≠.Ⴀ𐮀
+󠅾ܶܦ.ᢚ閪࣢𝩟; ܶܦ.ᢚ閪࣢𝩟; [B1, B5, B6, P1, V5, V6]; xn--wnb5a.xn--l0b161fis8gbp5m; ; ; # ܶܦ.ᢚ閪𝩟
+󠅾ܶܦ.ᢚ閪࣢𝩟; ܶܦ.ᢚ閪࣢𝩟; [B1, B5, B6, P1, V5, V6]; xn--wnb5a.xn--l0b161fis8gbp5m; ; ; # ܶܦ.ᢚ閪𝩟
+xn--wnb5a.xn--l0b161fis8gbp5m; ܶܦ.ᢚ閪࣢𝩟; [B1, B5, B6, V5, V6]; xn--wnb5a.xn--l0b161fis8gbp5m; ; ; # ܶܦ.ᢚ閪𝩟
+‍󠇜ۋ꣩。⃝ྰ-ᛟ; ‍ۋ꣩.⃝ྰ-ᛟ; [B1, C2, V5]; xn--blb540ke10h.xn----gmg236cj6k; ; xn--blb8114f.xn----gmg236cj6k; [B1, V5] # ۋ꣩.⃝ྰ-ᛟ
+‍󠇜ۋ꣩。⃝ྰ-ᛟ; ‍ۋ꣩.⃝ྰ-ᛟ; [B1, C2, V5]; xn--blb540ke10h.xn----gmg236cj6k; ; xn--blb8114f.xn----gmg236cj6k; [B1, V5] # ۋ꣩.⃝ྰ-ᛟ
+xn--blb8114f.xn----gmg236cj6k; ۋ꣩.⃝ྰ-ᛟ; [B1, V5]; xn--blb8114f.xn----gmg236cj6k; ; ; # ۋ꣩.⃝ྰ-ᛟ
+xn--blb540ke10h.xn----gmg236cj6k; ‍ۋ꣩.⃝ྰ-ᛟ; [B1, C2, V5]; xn--blb540ke10h.xn----gmg236cj6k; ; ; # ۋ꣩.⃝ྰ-ᛟ
+헁󘖙ฺ󚍚。ں𝟜; 헁󘖙ฺ󚍚.ں4; [P1, V6]; xn--o4c1723h8g85gt4ya.xn--4-dvc; ; ; # 헁ฺ.ں4
+헁󘖙ฺ󚍚。ں𝟜; 헁󘖙ฺ󚍚.ں4; [P1, V6]; xn--o4c1723h8g85gt4ya.xn--4-dvc; ; ; # 헁ฺ.ں4
+헁󘖙ฺ󚍚。ں4; 헁󘖙ฺ󚍚.ں4; [P1, V6]; xn--o4c1723h8g85gt4ya.xn--4-dvc; ; ; # 헁ฺ.ں4
+헁󘖙ฺ󚍚。ں4; 헁󘖙ฺ󚍚.ں4; [P1, V6]; xn--o4c1723h8g85gt4ya.xn--4-dvc; ; ; # 헁ฺ.ں4
+xn--o4c1723h8g85gt4ya.xn--4-dvc; 헁󘖙ฺ󚍚.ں4; [V6]; xn--o4c1723h8g85gt4ya.xn--4-dvc; ; ; # 헁ฺ.ں4
+𐹭。󃱂‌Ⴞ; 𐹭.󃱂‌Ⴞ; [B1, C1, P1, V6]; xn--lo0d.xn--2nd949eqw95u; ; xn--lo0d.xn--2nd75260n; [B1, P1, V6] # 𐹭.Ⴞ
+𐹭。󃱂‌Ⴞ; 𐹭.󃱂‌Ⴞ; [B1, C1, P1, V6]; xn--lo0d.xn--2nd949eqw95u; ; xn--lo0d.xn--2nd75260n; [B1, P1, V6] # 𐹭.Ⴞ
+𐹭。󃱂‌ⴞ; 𐹭.󃱂‌ⴞ; [B1, C1, P1, V6]; xn--lo0d.xn--0ugx72cwi33v; ; xn--lo0d.xn--mljx1099g; [B1, P1, V6] # 𐹭.ⴞ
+xn--lo0d.xn--mljx1099g; 𐹭.󃱂ⴞ; [B1, V6]; xn--lo0d.xn--mljx1099g; ; ; # 𐹭.ⴞ
+xn--lo0d.xn--0ugx72cwi33v; 𐹭.󃱂‌ⴞ; [B1, C1, V6]; xn--lo0d.xn--0ugx72cwi33v; ; ; # 𐹭.ⴞ
+xn--lo0d.xn--2nd75260n; 𐹭.󃱂Ⴞ; [B1, V6]; xn--lo0d.xn--2nd75260n; ; ; # 𐹭.Ⴞ
+xn--lo0d.xn--2nd949eqw95u; 𐹭.󃱂‌Ⴞ; [B1, C1, V6]; xn--lo0d.xn--2nd949eqw95u; ; ; # 𐹭.Ⴞ
+𐹭。󃱂‌ⴞ; 𐹭.󃱂‌ⴞ; [B1, C1, P1, V6]; xn--lo0d.xn--0ugx72cwi33v; ; xn--lo0d.xn--mljx1099g; [B1, P1, V6] # 𐹭.ⴞ
+꥓.̽𑂽馋; ; [P1, V5, V6]; xn--3j9a.xn--bua0708eqzrd; ; ; # ꥓.̽馋
+xn--3j9a.xn--bua0708eqzrd; ꥓.̽𑂽馋; [V5, V6]; xn--3j9a.xn--bua0708eqzrd; ; ; # ꥓.̽馋
+󈫝򪛸‍。䜖; 󈫝򪛸‍.䜖; [C2, P1, V6]; xn--1ug30527h9mxi.xn--k0o; ; xn--g138cxw05a.xn--k0o; [P1, V6] # .䜖
+󈫝򪛸‍。䜖; 󈫝򪛸‍.䜖; [C2, P1, V6]; xn--1ug30527h9mxi.xn--k0o; ; xn--g138cxw05a.xn--k0o; [P1, V6] # .䜖
+xn--g138cxw05a.xn--k0o; 󈫝򪛸.䜖; [V6]; xn--g138cxw05a.xn--k0o; ; ; # .䜖
+xn--1ug30527h9mxi.xn--k0o; 󈫝򪛸‍.䜖; [C2, V6]; xn--1ug30527h9mxi.xn--k0o; ; ; # .䜖
+ᡯ⚉姶🄉.۷‍🎪‍; ᡯ⚉姶🄉.۷‍🎪‍; [C2, P1, V6]; xn--c9e433epi4b3j20a.xn--kmb859ja94998b; ; xn--c9e433epi4b3j20a.xn--kmb6733w; [P1, V6] # ᡯ⚉姶🄉.۷🎪
+ᡯ⚉姶8,.۷‍🎪‍; ; [C2, P1, V6]; xn--8,-g9oy26fzu4d.xn--kmb859ja94998b; ; xn--8,-g9oy26fzu4d.xn--kmb6733w; [P1, V6] # ᡯ⚉姶8,.۷🎪
+xn--8,-g9oy26fzu4d.xn--kmb6733w; ᡯ⚉姶8,.۷🎪; [P1, V6]; xn--8,-g9oy26fzu4d.xn--kmb6733w; ; ; # ᡯ⚉姶8,.۷🎪
+xn--8,-g9oy26fzu4d.xn--kmb859ja94998b; ᡯ⚉姶8,.۷‍🎪‍; [C2, P1, V6]; xn--8,-g9oy26fzu4d.xn--kmb859ja94998b; ; ; # ᡯ⚉姶8,.۷🎪
+xn--c9e433epi4b3j20a.xn--kmb6733w; ᡯ⚉姶🄉.۷🎪; [V6]; xn--c9e433epi4b3j20a.xn--kmb6733w; ; ; # ᡯ⚉姶🄉.۷🎪
+xn--c9e433epi4b3j20a.xn--kmb859ja94998b; ᡯ⚉姶🄉.۷‍🎪‍; [C2, V6]; xn--c9e433epi4b3j20a.xn--kmb859ja94998b; ; ; # ᡯ⚉姶🄉.۷🎪
+𞽀.𐹸🚖ฺ; ; [B1, P1, V6]; xn--0n7h.xn--o4c9032klszf; ; ; # .𐹸🚖ฺ
+xn--0n7h.xn--o4c9032klszf; 𞽀.𐹸🚖ฺ; [B1, V6]; xn--0n7h.xn--o4c9032klszf; ; ; # .𐹸🚖ฺ
+Ⴔᠵ。𐹧݇۹; Ⴔᠵ.𐹧݇۹; [B1, P1, V6]; xn--snd659a.xn--mmb9ml895e; ; ; # Ⴔᠵ.𐹧݇۹
+Ⴔᠵ。𐹧݇۹; Ⴔᠵ.𐹧݇۹; [B1, P1, V6]; xn--snd659a.xn--mmb9ml895e; ; ; # Ⴔᠵ.𐹧݇۹
+ⴔᠵ。𐹧݇۹; ⴔᠵ.𐹧݇۹; [B1]; xn--o7e997h.xn--mmb9ml895e; ; ; # ⴔᠵ.𐹧݇۹
+xn--o7e997h.xn--mmb9ml895e; ⴔᠵ.𐹧݇۹; [B1]; xn--o7e997h.xn--mmb9ml895e; ; ; # ⴔᠵ.𐹧݇۹
+xn--snd659a.xn--mmb9ml895e; Ⴔᠵ.𐹧݇۹; [B1, V6]; xn--snd659a.xn--mmb9ml895e; ; ; # Ⴔᠵ.𐹧݇۹
+ⴔᠵ。𐹧݇۹; ⴔᠵ.𐹧݇۹; [B1]; xn--o7e997h.xn--mmb9ml895e; ; ; # ⴔᠵ.𐹧݇۹
+፟ᡈ‌.︒-𖾐-; ፟ᡈ‌.︒-𖾐-; [C1, P1, V3, V5, V6]; xn--b7d82wo4h.xn-----c82nz547a; ; xn--b7d82w.xn-----c82nz547a; [P1, V3, V5, V6] # ፟ᡈ.︒-𖾐-
+፟ᡈ‌.。-𖾐-; ፟ᡈ‌..-𖾐-; [C1, V3, V5, X4_2]; xn--b7d82wo4h..xn-----pe4u; [C1, V3, V5, A4_2]; xn--b7d82w..xn-----pe4u; [V3, V5, A4_2] # ፟ᡈ..-𖾐-
+xn--b7d82w..xn-----pe4u; ፟ᡈ..-𖾐-; [V3, V5, X4_2]; xn--b7d82w..xn-----pe4u; [V3, V5, A4_2]; ; # ፟ᡈ..-𖾐-
+xn--b7d82wo4h..xn-----pe4u; ፟ᡈ‌..-𖾐-; [C1, V3, V5, X4_2]; xn--b7d82wo4h..xn-----pe4u; [C1, V3, V5, A4_2]; ; # ፟ᡈ..-𖾐-
+xn--b7d82w.xn-----c82nz547a; ፟ᡈ.︒-𖾐-; [V3, V5, V6]; xn--b7d82w.xn-----c82nz547a; ; ; # ፟ᡈ.︒-𖾐-
+xn--b7d82wo4h.xn-----c82nz547a; ፟ᡈ‌.︒-𖾐-; [C1, V3, V5, V6]; xn--b7d82wo4h.xn-----c82nz547a; ; ; # ፟ᡈ.︒-𖾐-
+⒈؁⒖‌.ᷰߛ; ; [B1, C1, P1, V5, V6]; xn--jfb844kmfdwb.xn--2sb914i; ; xn--jfb347mib.xn--2sb914i; [B1, P1, V5, V6] # ⒈⒖.ᷰߛ
+1.؁15.‌.ᷰߛ; ; [B1, C1, P1, V5, V6]; 1.xn--15-1pd.xn--0ug.xn--2sb914i; ; 1.xn--15-1pd..xn--2sb914i; [B1, P1, V5, V6, A4_2] # 1.15..ᷰߛ
+1.xn--15-1pd..xn--2sb914i; 1.؁15..ᷰߛ; [B1, V5, V6, X4_2]; 1.xn--15-1pd..xn--2sb914i; [B1, V5, V6, A4_2]; ; # 1.15..ᷰߛ
+1.xn--15-1pd.xn--0ug.xn--2sb914i; 1.؁15.‌.ᷰߛ; [B1, C1, V5, V6]; 1.xn--15-1pd.xn--0ug.xn--2sb914i; ; ; # 1.15..ᷰߛ
+xn--jfb347mib.xn--2sb914i; ⒈؁⒖.ᷰߛ; [B1, V5, V6]; xn--jfb347mib.xn--2sb914i; ; ; # ⒈⒖.ᷰߛ
+xn--jfb844kmfdwb.xn--2sb914i; ⒈؁⒖‌.ᷰߛ; [B1, C1, V5, V6]; xn--jfb844kmfdwb.xn--2sb914i; ; ; # ⒈⒖.ᷰߛ
+𝩜。-୍Ⴋ; 𝩜.-୍Ⴋ; [P1, V3, V5, V6]; xn--792h.xn----bse632b; ; ; # 𝩜.-୍Ⴋ
+𝩜。-୍ⴋ; 𝩜.-୍ⴋ; [V3, V5]; xn--792h.xn----bse820x; ; ; # 𝩜.-୍ⴋ
+xn--792h.xn----bse820x; 𝩜.-୍ⴋ; [V3, V5]; xn--792h.xn----bse820x; ; ; # 𝩜.-୍ⴋ
+xn--792h.xn----bse632b; 𝩜.-୍Ⴋ; [V3, V5, V6]; xn--792h.xn----bse632b; ; ; # 𝩜.-୍Ⴋ
+ßჀ.ؠ刯Ⴝ; ; [B2, B3, P1, V6]; xn--zca442f.xn--fgb845cb66c; ; xn--ss-wgk.xn--fgb845cb66c; # ßჀ.ؠ刯Ⴝ
+ßⴠ.ؠ刯ⴝ; ; [B2, B3]; xn--zca277t.xn--fgb670rovy; ; xn--ss-j81a.xn--fgb670rovy; # ßⴠ.ؠ刯ⴝ
+SSჀ.ؠ刯Ⴝ; ssჀ.ؠ刯Ⴝ; [B2, B3, P1, V6]; xn--ss-wgk.xn--fgb845cb66c; ; ; # ssჀ.ؠ刯Ⴝ
+ssⴠ.ؠ刯ⴝ; ; [B2, B3]; xn--ss-j81a.xn--fgb670rovy; ; ; # ssⴠ.ؠ刯ⴝ
+Ssⴠ.ؠ刯Ⴝ; ssⴠ.ؠ刯Ⴝ; [B2, B3, P1, V6]; xn--ss-j81a.xn--fgb845cb66c; ; ; # ssⴠ.ؠ刯Ⴝ
+xn--ss-j81a.xn--fgb845cb66c; ssⴠ.ؠ刯Ⴝ; [B2, B3, V6]; xn--ss-j81a.xn--fgb845cb66c; ; ; # ssⴠ.ؠ刯Ⴝ
+xn--ss-j81a.xn--fgb670rovy; ssⴠ.ؠ刯ⴝ; [B2, B3]; xn--ss-j81a.xn--fgb670rovy; ; ; # ssⴠ.ؠ刯ⴝ
+xn--ss-wgk.xn--fgb845cb66c; ssჀ.ؠ刯Ⴝ; [B2, B3, V6]; xn--ss-wgk.xn--fgb845cb66c; ; ; # ssჀ.ؠ刯Ⴝ
+xn--zca277t.xn--fgb670rovy; ßⴠ.ؠ刯ⴝ; [B2, B3]; xn--zca277t.xn--fgb670rovy; ; ; # ßⴠ.ؠ刯ⴝ
+xn--zca442f.xn--fgb845cb66c; ßჀ.ؠ刯Ⴝ; [B2, B3, V6]; xn--zca442f.xn--fgb845cb66c; ; ; # ßჀ.ؠ刯Ⴝ
+᮪ႣℲ。ᠳ툻ٳ; ᮪ႣℲ.ᠳ툻ٳ; [B5, B6, P1, V5, V6]; xn--bnd957cone.xn--sib102gc69k; ; ; # ᮪ႣℲ.ᠳ툻ٳ
+᮪ႣℲ。ᠳ툻ٳ; ᮪ႣℲ.ᠳ툻ٳ; [B5, B6, P1, V5, V6]; xn--bnd957cone.xn--sib102gc69k; ; ; # ᮪ႣℲ.ᠳ툻ٳ
+᮪ႣℲ。ᠳ툻ٳ; ᮪ႣℲ.ᠳ툻ٳ; [B5, B6, P1, V5, V6]; xn--bnd957cone.xn--sib102gc69k; ; ; # ᮪ႣℲ.ᠳ툻ٳ
+᮪ႣℲ。ᠳ툻ٳ; ᮪ႣℲ.ᠳ툻ٳ; [B5, B6, P1, V5, V6]; xn--bnd957cone.xn--sib102gc69k; ; ; # ᮪ႣℲ.ᠳ툻ٳ
+᮪ⴃⅎ。ᠳ툻ٳ; ᮪ⴃⅎ.ᠳ툻ٳ; [B5, B6, V5]; xn--yxf24x4ol.xn--sib102gc69k; ; ; # ᮪ⴃⅎ.ᠳ툻ٳ
+᮪ⴃⅎ。ᠳ툻ٳ; ᮪ⴃⅎ.ᠳ툻ٳ; [B5, B6, V5]; xn--yxf24x4ol.xn--sib102gc69k; ; ; # ᮪ⴃⅎ.ᠳ툻ٳ
+᮪Ⴃⅎ。ᠳ툻ٳ; ᮪Ⴃⅎ.ᠳ툻ٳ; [B5, B6, P1, V5, V6]; xn--bnd957c2pe.xn--sib102gc69k; ; ; # ᮪Ⴃⅎ.ᠳ툻ٳ
+᮪Ⴃⅎ。ᠳ툻ٳ; ᮪Ⴃⅎ.ᠳ툻ٳ; [B5, B6, P1, V5, V6]; xn--bnd957c2pe.xn--sib102gc69k; ; ; # ᮪Ⴃⅎ.ᠳ툻ٳ
+xn--bnd957c2pe.xn--sib102gc69k; ᮪Ⴃⅎ.ᠳ툻ٳ; [B5, B6, V5, V6]; xn--bnd957c2pe.xn--sib102gc69k; ; ; # ᮪Ⴃⅎ.ᠳ툻ٳ
+xn--yxf24x4ol.xn--sib102gc69k; ᮪ⴃⅎ.ᠳ툻ٳ; [B5, B6, V5]; xn--yxf24x4ol.xn--sib102gc69k; ; ; # ᮪ⴃⅎ.ᠳ툻ٳ
+xn--bnd957cone.xn--sib102gc69k; ᮪ႣℲ.ᠳ툻ٳ; [B5, B6, V5, V6]; xn--bnd957cone.xn--sib102gc69k; ; ; # ᮪ႣℲ.ᠳ툻ٳ
+᮪ⴃⅎ。ᠳ툻ٳ; ᮪ⴃⅎ.ᠳ툻ٳ; [B5, B6, V5]; xn--yxf24x4ol.xn--sib102gc69k; ; ; # ᮪ⴃⅎ.ᠳ툻ٳ
+᮪ⴃⅎ。ᠳ툻ٳ; ᮪ⴃⅎ.ᠳ툻ٳ; [B5, B6, V5]; xn--yxf24x4ol.xn--sib102gc69k; ; ; # ᮪ⴃⅎ.ᠳ툻ٳ
+᮪Ⴃⅎ。ᠳ툻ٳ; ᮪Ⴃⅎ.ᠳ툻ٳ; [B5, B6, P1, V5, V6]; xn--bnd957c2pe.xn--sib102gc69k; ; ; # ᮪Ⴃⅎ.ᠳ툻ٳ
+᮪Ⴃⅎ。ᠳ툻ٳ; ᮪Ⴃⅎ.ᠳ툻ٳ; [B5, B6, P1, V5, V6]; xn--bnd957c2pe.xn--sib102gc69k; ; ; # ᮪Ⴃⅎ.ᠳ툻ٳ
+۬.ࢢ𐹫ټ; ; [B1, B3, B6, V5]; xn--8lb.xn--1ib31ily45b; ; ; # ۬.ࢢ𐹫ټ
+xn--8lb.xn--1ib31ily45b; ۬.ࢢ𐹫ټ; [B1, B3, B6, V5]; xn--8lb.xn--1ib31ily45b; ; ; # ۬.ࢢ𐹫ټ
+ڶ۟。₇꠆; ڶ۟.7꠆; [B1]; xn--pkb6f.xn--7-x93e; ; ; # ڶ۟.7꠆
+ڶ۟。7꠆; ڶ۟.7꠆; [B1]; xn--pkb6f.xn--7-x93e; ; ; # ڶ۟.7꠆
+xn--pkb6f.xn--7-x93e; ڶ۟.7꠆; [B1]; xn--pkb6f.xn--7-x93e; ; ; # ڶ۟.7꠆
+ڶ۟.7꠆; ; [B1]; xn--pkb6f.xn--7-x93e; ; ; # ڶ۟.7꠆
+Ⴣ𐹻.‌𝪣≮󠩉; ; [B1, B5, B6, C1, P1, V6]; xn--7nd8101k.xn--0ugy6gn120eb103g; ; xn--7nd8101k.xn--gdh4944ob3x3e; [B1, B5, B6, P1, V5, V6] # Ⴣ𐹻.𝪣≮
+Ⴣ𐹻.‌𝪣≮󠩉; Ⴣ𐹻.‌𝪣≮󠩉; [B1, B5, B6, C1, P1, V6]; xn--7nd8101k.xn--0ugy6gn120eb103g; ; xn--7nd8101k.xn--gdh4944ob3x3e; [B1, B5, B6, P1, V5, V6] # Ⴣ𐹻.𝪣≮
+ⴣ𐹻.‌𝪣≮󠩉; ⴣ𐹻.‌𝪣≮󠩉; [B1, B5, B6, C1, P1, V6]; xn--rlj6323e.xn--0ugy6gn120eb103g; ; xn--rlj6323e.xn--gdh4944ob3x3e; [B1, B5, B6, P1, V5, V6] # ⴣ𐹻.𝪣≮
+ⴣ𐹻.‌𝪣≮󠩉; ; [B1, B5, B6, C1, P1, V6]; xn--rlj6323e.xn--0ugy6gn120eb103g; ; xn--rlj6323e.xn--gdh4944ob3x3e; [B1, B5, B6, P1, V5, V6] # ⴣ𐹻.𝪣≮
+xn--rlj6323e.xn--gdh4944ob3x3e; ⴣ𐹻.𝪣≮󠩉; [B1, B5, B6, V5, V6]; xn--rlj6323e.xn--gdh4944ob3x3e; ; ; # ⴣ𐹻.𝪣≮
+xn--rlj6323e.xn--0ugy6gn120eb103g; ⴣ𐹻.‌𝪣≮󠩉; [B1, B5, B6, C1, V6]; xn--rlj6323e.xn--0ugy6gn120eb103g; ; ; # ⴣ𐹻.𝪣≮
+xn--7nd8101k.xn--gdh4944ob3x3e; Ⴣ𐹻.𝪣≮󠩉; [B1, B5, B6, V5, V6]; xn--7nd8101k.xn--gdh4944ob3x3e; ; ; # Ⴣ𐹻.𝪣≮
+xn--7nd8101k.xn--0ugy6gn120eb103g; Ⴣ𐹻.‌𝪣≮󠩉; [B1, B5, B6, C1, V6]; xn--7nd8101k.xn--0ugy6gn120eb103g; ; ; # Ⴣ𐹻.𝪣≮
+𝟵隁⯮.᠍‌; 9隁⯮.‌; [C1]; xn--9-mfs8024b.xn--0ug; ; xn--9-mfs8024b.; [] # 9隁⯮.
+9隁⯮.᠍‌; 9隁⯮.‌; [C1]; xn--9-mfs8024b.xn--0ug; ; xn--9-mfs8024b.; [] # 9隁⯮.
+xn--9-mfs8024b.; 9隁⯮.; ; xn--9-mfs8024b.; ; ; # 9隁⯮.
+9隁⯮.; ; ; xn--9-mfs8024b.; ; ; # 9隁⯮.
+xn--9-mfs8024b.xn--0ug; 9隁⯮.‌; [C1]; xn--9-mfs8024b.xn--0ug; ; ; # 9隁⯮.
+⒏𐹧。Ⴣ྄彦; ⒏𐹧.Ⴣ྄彦; [B1, P1, V6]; xn--0sh2466f.xn--3ed15dt93o; ; ; # ⒏𐹧.Ⴣ྄彦
+8.𐹧。Ⴣ྄彦; 8.𐹧.Ⴣ྄彦; [B1, P1, V6]; 8.xn--fo0d.xn--3ed15dt93o; ; ; # 8.𐹧.Ⴣ྄彦
+8.𐹧。ⴣ྄彦; 8.𐹧.ⴣ྄彦; [B1]; 8.xn--fo0d.xn--3ed972m6o8a; ; ; # 8.𐹧.ⴣ྄彦
+8.xn--fo0d.xn--3ed972m6o8a; 8.𐹧.ⴣ྄彦; [B1]; 8.xn--fo0d.xn--3ed972m6o8a; ; ; # 8.𐹧.ⴣ྄彦
+8.xn--fo0d.xn--3ed15dt93o; 8.𐹧.Ⴣ྄彦; [B1, V6]; 8.xn--fo0d.xn--3ed15dt93o; ; ; # 8.𐹧.Ⴣ྄彦
+⒏𐹧。ⴣ྄彦; ⒏𐹧.ⴣ྄彦; [B1, P1, V6]; xn--0sh2466f.xn--3ed972m6o8a; ; ; # ⒏𐹧.ⴣ྄彦
+xn--0sh2466f.xn--3ed972m6o8a; ⒏𐹧.ⴣ྄彦; [B1, V6]; xn--0sh2466f.xn--3ed972m6o8a; ; ; # ⒏𐹧.ⴣ྄彦
+xn--0sh2466f.xn--3ed15dt93o; ⒏𐹧.Ⴣ྄彦; [B1, V6]; xn--0sh2466f.xn--3ed15dt93o; ; ; # ⒏𐹧.Ⴣ྄彦
+-问񬰔⒛。؄-񜗉橬; -问񬰔⒛.؄-񜗉橬; [B1, P1, V3, V6]; xn----hdpu849bhis3e.xn----ykc7228efm46d; ; ; # -问⒛.-橬
+-问񬰔20.。؄-񜗉橬; -问񬰔20..؄-񜗉橬; [B1, P1, V3, V6, X4_2]; xn---20-658jx1776d..xn----ykc7228efm46d; [B1, P1, V3, V6, A4_2]; ; # -问20..-橬
+xn---20-658jx1776d..xn----ykc7228efm46d; -问񬰔20..؄-񜗉橬; [B1, V3, V6, X4_2]; xn---20-658jx1776d..xn----ykc7228efm46d; [B1, V3, V6, A4_2]; ; # -问20..-橬
+xn----hdpu849bhis3e.xn----ykc7228efm46d; -问񬰔⒛.؄-񜗉橬; [B1, V3, V6]; xn----hdpu849bhis3e.xn----ykc7228efm46d; ; ; # -问⒛.-橬
+ᮬႬ‌̥。𝟸; ᮬႬ‌̥.2; [C1, P1, V5, V6]; xn--mta930emribme.2; ; xn--mta930emri.2; [P1, V5, V6] # ᮬႬ̥.2
+ᮬႬ‌̥。2; ᮬႬ‌̥.2; [C1, P1, V5, V6]; xn--mta930emribme.2; ; xn--mta930emri.2; [P1, V5, V6] # ᮬႬ̥.2
+ᮬⴌ‌̥。2; ᮬⴌ‌̥.2; [C1, V5]; xn--mta176j97cl2q.2; ; xn--mta176jjjm.2; [V5] # ᮬⴌ̥.2
+xn--mta176jjjm.2; ᮬⴌ̥.2; [V5]; xn--mta176jjjm.2; ; ; # ᮬⴌ̥.2
+xn--mta176j97cl2q.2; ᮬⴌ‌̥.2; [C1, V5]; xn--mta176j97cl2q.2; ; ; # ᮬⴌ̥.2
+xn--mta930emri.2; ᮬႬ̥.2; [V5, V6]; xn--mta930emri.2; ; ; # ᮬႬ̥.2
+xn--mta930emribme.2; ᮬႬ‌̥.2; [C1, V5, V6]; xn--mta930emribme.2; ; ; # ᮬႬ̥.2
+ᮬⴌ‌̥。𝟸; ᮬⴌ‌̥.2; [C1, V5]; xn--mta176j97cl2q.2; ; xn--mta176jjjm.2; [V5] # ᮬⴌ̥.2
+?。꠆٩󠒩; ?.꠆٩󠒩; [B1, P1, V5, V6]; ?.xn--iib9583fusy0i; ; ; # ?.꠆٩
+?.xn--iib9583fusy0i; ?.꠆٩󠒩; [B1, P1, V5, V6]; ?.xn--iib9583fusy0i; ; ; # ?.꠆٩
+󠄁͟⾶。₇︒눇≮; ͟飛.7︒눇≮; [P1, V5, V6]; xn--9ua0567e.xn--7-ngou006d1ttc; ; ; # ͟飛.7︒눇≮
+󠄁͟⾶。₇︒눇≮; ͟飛.7︒눇≮; [P1, V5, V6]; xn--9ua0567e.xn--7-ngou006d1ttc; ; ; # ͟飛.7︒눇≮
+󠄁͟飛。7。눇≮; ͟飛.7.눇≮; [P1, V5, V6]; xn--9ua0567e.7.xn--gdh6767c; ; ; # ͟飛.7.눇≮
+󠄁͟飛。7。눇≮; ͟飛.7.눇≮; [P1, V5, V6]; xn--9ua0567e.7.xn--gdh6767c; ; ; # ͟飛.7.눇≮
+xn--9ua0567e.7.xn--gdh6767c; ͟飛.7.눇≮; [V5, V6]; xn--9ua0567e.7.xn--gdh6767c; ; ; # ͟飛.7.눇≮
+xn--9ua0567e.xn--7-ngou006d1ttc; ͟飛.7︒눇≮; [V5, V6]; xn--9ua0567e.xn--7-ngou006d1ttc; ; ; # ͟飛.7︒눇≮
+‌︉𐹴‍.‌⿃; ‌𐹴‍.‌鳥; [B1, C1, C2]; xn--0ugc6024p.xn--0ug1920c; ; xn--so0d.xn--6x6a; [B1] # 𐹴.鳥
+‌︉𐹴‍.‌鳥; ‌𐹴‍.‌鳥; [B1, C1, C2]; xn--0ugc6024p.xn--0ug1920c; ; xn--so0d.xn--6x6a; [B1] # 𐹴.鳥
+xn--so0d.xn--6x6a; 𐹴.鳥; [B1]; xn--so0d.xn--6x6a; ; ; # 𐹴.鳥
+xn--0ugc6024p.xn--0ug1920c; ‌𐹴‍.‌鳥; [B1, C1, C2]; xn--0ugc6024p.xn--0ug1920c; ; ; # 𐹴.鳥
+🍮.‍󠗒𐦁𝨝; 🍮.‍󠗒𐦁𝨝; [B1, C2, P1, V6]; xn--lj8h.xn--1ug6603gr1pfwq37h; ; xn--lj8h.xn--ln9ci476aqmr2g; [B1, P1, V6] # 🍮.𐦁𝨝
+🍮.‍󠗒𐦁𝨝; ; [B1, C2, P1, V6]; xn--lj8h.xn--1ug6603gr1pfwq37h; ; xn--lj8h.xn--ln9ci476aqmr2g; [B1, P1, V6] # 🍮.𐦁𝨝
+xn--lj8h.xn--ln9ci476aqmr2g; 🍮.󠗒𐦁𝨝; [B1, V6]; xn--lj8h.xn--ln9ci476aqmr2g; ; ; # 🍮.𐦁𝨝
+xn--lj8h.xn--1ug6603gr1pfwq37h; 🍮.‍󠗒𐦁𝨝; [B1, C2, V6]; xn--lj8h.xn--1ug6603gr1pfwq37h; ; ; # 🍮.𐦁𝨝
+ٽृ.𞤓‍; ٽृ.𞤵‍; [B3, C2]; xn--2ib43l.xn--1ugy711p; ; xn--2ib43l.xn--te6h; [] # ٽृ.𞤵
+ٽृ.𞤵‍; ; [B3, C2]; xn--2ib43l.xn--1ugy711p; ; xn--2ib43l.xn--te6h; [] # ٽृ.𞤵
+xn--2ib43l.xn--te6h; ٽृ.𞤵; ; xn--2ib43l.xn--te6h; ; ; # ٽृ.𞤵
+ٽृ.𞤵; ; ; xn--2ib43l.xn--te6h; ; ; # ٽृ.𞤵
+ٽृ.𞤓; ٽृ.𞤵; ; xn--2ib43l.xn--te6h; ; ; # ٽृ.𞤵
+xn--2ib43l.xn--1ugy711p; ٽृ.𞤵‍; [B3, C2]; xn--2ib43l.xn--1ugy711p; ; ; # ٽृ.𞤵
+٤੍-.󥜽္񦦐; ٤੍-.󥜽္񦦐; [B1, P1, V3, V6]; xn----gqc711a.xn--9jd88234f3qm0b; ; ; # ٤੍-.္
+٤੍-.󥜽္񦦐; ; [B1, P1, V3, V6]; xn----gqc711a.xn--9jd88234f3qm0b; ; ; # ٤੍-.္
+xn----gqc711a.xn--9jd88234f3qm0b; ٤੍-.󥜽္񦦐; [B1, V3, V6]; xn----gqc711a.xn--9jd88234f3qm0b; ; ; # ٤੍-.္
+4်-𐹸。ꨩ‌𐹴≮; 4်-𐹸.ꨩ‌𐹴≮; [B1, C1, P1, V5, V6]; xn--4--e4j7831r.xn--0ugy6gjy5sl3ud; ; xn--4--e4j7831r.xn--gdh8754cz40c; [B1, P1, V5, V6] # 4်-𐹸.ꨩ𐹴≮
+4်-𐹸。ꨩ‌𐹴≮; 4်-𐹸.ꨩ‌𐹴≮; [B1, C1, P1, V5, V6]; xn--4--e4j7831r.xn--0ugy6gjy5sl3ud; ; xn--4--e4j7831r.xn--gdh8754cz40c; [B1, P1, V5, V6] # 4်-𐹸.ꨩ𐹴≮
+4်-𐹸。ꨩ‌𐹴≮; 4်-𐹸.ꨩ‌𐹴≮; [B1, C1, P1, V5, V6]; xn--4--e4j7831r.xn--0ugy6gjy5sl3ud; ; xn--4--e4j7831r.xn--gdh8754cz40c; [B1, P1, V5, V6] # 4်-𐹸.ꨩ𐹴≮
+4်-𐹸。ꨩ‌𐹴≮; 4်-𐹸.ꨩ‌𐹴≮; [B1, C1, P1, V5, V6]; xn--4--e4j7831r.xn--0ugy6gjy5sl3ud; ; xn--4--e4j7831r.xn--gdh8754cz40c; [B1, P1, V5, V6] # 4်-𐹸.ꨩ𐹴≮
+xn--4--e4j7831r.xn--gdh8754cz40c; 4်-𐹸.ꨩ𐹴≮; [B1, V5, V6]; xn--4--e4j7831r.xn--gdh8754cz40c; ; ; # 4်-𐹸.ꨩ𐹴≮
+xn--4--e4j7831r.xn--0ugy6gjy5sl3ud; 4်-𐹸.ꨩ‌𐹴≮; [B1, C1, V5, V6]; xn--4--e4j7831r.xn--0ugy6gjy5sl3ud; ; ; # 4်-𐹸.ꨩ𐹴≮
+‌。ᅠ྄ྖ; ‌.ᅠ྄ྖ; [C1, P1, V6]; xn--0ug.xn--3ed0by082k; ; .xn--3ed0by082k; [P1, V6, A4_2] # .྄ྖ
+‌。ᅠ྄ྖ; ‌.ᅠ྄ྖ; [C1, P1, V6]; xn--0ug.xn--3ed0b20h; ; .xn--3ed0b20h; [P1, V6, A4_2] # .྄ྖ
+.xn--3ed0b20h; .ᅠ྄ྖ; [V6, X4_2]; .xn--3ed0b20h; [V6, A4_2]; ; # .྄ྖ
+xn--0ug.xn--3ed0b20h; ‌.ᅠ྄ྖ; [C1, V6]; xn--0ug.xn--3ed0b20h; ; ; # .྄ྖ
+.xn--3ed0by082k; .ᅠ྄ྖ; [V6, X4_2]; .xn--3ed0by082k; [V6, A4_2]; ; # .྄ྖ
+xn--0ug.xn--3ed0by082k; ‌.ᅠ྄ྖ; [C1, V6]; xn--0ug.xn--3ed0by082k; ; ; # .྄ྖ
+≯򍘅.‍𐅼򲇛; ≯򍘅.‍𐅼򲇛; [C2, P1, V6]; xn--hdh84488f.xn--1ug8099fbjp4e; ; xn--hdh84488f.xn--xy7cw2886b; [P1, V6] # ≯.𐅼
+≯򍘅.‍𐅼򲇛; ≯򍘅.‍𐅼򲇛; [C2, P1, V6]; xn--hdh84488f.xn--1ug8099fbjp4e; ; xn--hdh84488f.xn--xy7cw2886b; [P1, V6] # ≯.𐅼
+≯򍘅.‍𐅼򲇛; ; [C2, P1, V6]; xn--hdh84488f.xn--1ug8099fbjp4e; ; xn--hdh84488f.xn--xy7cw2886b; [P1, V6] # ≯.𐅼
+≯򍘅.‍𐅼򲇛; ≯򍘅.‍𐅼򲇛; [C2, P1, V6]; xn--hdh84488f.xn--1ug8099fbjp4e; ; xn--hdh84488f.xn--xy7cw2886b; [P1, V6] # ≯.𐅼
+xn--hdh84488f.xn--xy7cw2886b; ≯򍘅.𐅼򲇛; [V6]; xn--hdh84488f.xn--xy7cw2886b; ; ; # ≯.𐅼
+xn--hdh84488f.xn--1ug8099fbjp4e; ≯򍘅.‍𐅼򲇛; [C2, V6]; xn--hdh84488f.xn--1ug8099fbjp4e; ; ; # ≯.𐅼
+فß𐰯。𝟕𐫫; فß𐰯.7𐫫; [B1, B2]; xn--zca96ys96y.xn--7-mm5i; ; xn--ss-jvd2339x.xn--7-mm5i; # فß𐰯.7𐫫
+فß𐰯。7𐫫; فß𐰯.7𐫫; [B1, B2]; xn--zca96ys96y.xn--7-mm5i; ; xn--ss-jvd2339x.xn--7-mm5i; # فß𐰯.7𐫫
+فSS𐰯。7𐫫; فss𐰯.7𐫫; [B1, B2]; xn--ss-jvd2339x.xn--7-mm5i; ; ; # فss𐰯.7𐫫
+فss𐰯。7𐫫; فss𐰯.7𐫫; [B1, B2]; xn--ss-jvd2339x.xn--7-mm5i; ; ; # فss𐰯.7𐫫
+xn--ss-jvd2339x.xn--7-mm5i; فss𐰯.7𐫫; [B1, B2]; xn--ss-jvd2339x.xn--7-mm5i; ; ; # فss𐰯.7𐫫
+xn--zca96ys96y.xn--7-mm5i; فß𐰯.7𐫫; [B1, B2]; xn--zca96ys96y.xn--7-mm5i; ; ; # فß𐰯.7𐫫
+فSS𐰯。𝟕𐫫; فss𐰯.7𐫫; [B1, B2]; xn--ss-jvd2339x.xn--7-mm5i; ; ; # فss𐰯.7𐫫
+فss𐰯。𝟕𐫫; فss𐰯.7𐫫; [B1, B2]; xn--ss-jvd2339x.xn--7-mm5i; ; ; # فss𐰯.7𐫫
+فSs𐰯。7𐫫; فss𐰯.7𐫫; [B1, B2]; xn--ss-jvd2339x.xn--7-mm5i; ; ; # فss𐰯.7𐫫
+فSs𐰯。𝟕𐫫; فss𐰯.7𐫫; [B1, B2]; xn--ss-jvd2339x.xn--7-mm5i; ; ; # فss𐰯.7𐫫
+ßެާࢱ。𐭁􅮙𐹲; ßެާࢱ.𐭁􅮙𐹲; [B2, B5, B6, P1, V6]; xn--zca685aoa95h.xn--e09co8cr9861c; ; xn--ss-9qet02k.xn--e09co8cr9861c; # ßެާࢱ.𐭁𐹲
+SSެާࢱ。𐭁􅮙𐹲; ssެާࢱ.𐭁􅮙𐹲; [B2, B5, B6, P1, V6]; xn--ss-9qet02k.xn--e09co8cr9861c; ; ; # ssެާࢱ.𐭁𐹲
+ssެާࢱ。𐭁􅮙𐹲; ssެާࢱ.𐭁􅮙𐹲; [B2, B5, B6, P1, V6]; xn--ss-9qet02k.xn--e09co8cr9861c; ; ; # ssެާࢱ.𐭁𐹲
+Ssެާࢱ。𐭁􅮙𐹲; ssެާࢱ.𐭁􅮙𐹲; [B2, B5, B6, P1, V6]; xn--ss-9qet02k.xn--e09co8cr9861c; ; ; # ssެާࢱ.𐭁𐹲
+xn--ss-9qet02k.xn--e09co8cr9861c; ssެާࢱ.𐭁􅮙𐹲; [B2, B5, B6, V6]; xn--ss-9qet02k.xn--e09co8cr9861c; ; ; # ssެާࢱ.𐭁𐹲
+xn--zca685aoa95h.xn--e09co8cr9861c; ßެާࢱ.𐭁􅮙𐹲; [B2, B5, B6, V6]; xn--zca685aoa95h.xn--e09co8cr9861c; ; ; # ßެާࢱ.𐭁𐹲
+-。󠉗⒌𞯛; -.󠉗⒌𞯛; [B1, P1, V3, V6]; -.xn--xsh6367n1bi3e; ; ; # -.⒌
+-。󠉗5.𞯛; -.󠉗5.𞯛; [B1, P1, V3, V6]; -.xn--5-zz21m.xn--6x6h; ; ; # -.5.
+-.xn--5-zz21m.xn--6x6h; -.󠉗5.𞯛; [B1, V3, V6]; -.xn--5-zz21m.xn--6x6h; ; ; # -.5.
+-.xn--xsh6367n1bi3e; -.󠉗⒌𞯛; [B1, V3, V6]; -.xn--xsh6367n1bi3e; ; ; # -.⒌
+𼎏ς.-≮ﲫ; 𼎏ς.-≮خج; [B1, P1, V3, V6]; xn--3xa13520c.xn----9mcf1400a; ; xn--4xa92520c.xn----9mcf1400a; # ς.-≮خج
+𼎏ς.-≮ﲫ; 𼎏ς.-≮خج; [B1, P1, V3, V6]; xn--3xa13520c.xn----9mcf1400a; ; xn--4xa92520c.xn----9mcf1400a; # ς.-≮خج
+𼎏ς.-≮خج; ; [B1, P1, V3, V6]; xn--3xa13520c.xn----9mcf1400a; ; xn--4xa92520c.xn----9mcf1400a; # ς.-≮خج
+𼎏ς.-≮خج; 𼎏ς.-≮خج; [B1, P1, V3, V6]; xn--3xa13520c.xn----9mcf1400a; ; xn--4xa92520c.xn----9mcf1400a; # ς.-≮خج
+𼎏Σ.-≮خج; 𼎏σ.-≮خج; [B1, P1, V3, V6]; xn--4xa92520c.xn----9mcf1400a; ; ; # σ.-≮خج
+𼎏Σ.-≮خج; 𼎏σ.-≮خج; [B1, P1, V3, V6]; xn--4xa92520c.xn----9mcf1400a; ; ; # σ.-≮خج
+𼎏σ.-≮خج; ; [B1, P1, V3, V6]; xn--4xa92520c.xn----9mcf1400a; ; ; # σ.-≮خج
+𼎏σ.-≮خج; 𼎏σ.-≮خج; [B1, P1, V3, V6]; xn--4xa92520c.xn----9mcf1400a; ; ; # σ.-≮خج
+xn--4xa92520c.xn----9mcf1400a; 𼎏σ.-≮خج; [B1, V3, V6]; xn--4xa92520c.xn----9mcf1400a; ; ; # σ.-≮خج
+xn--3xa13520c.xn----9mcf1400a; 𼎏ς.-≮خج; [B1, V3, V6]; xn--3xa13520c.xn----9mcf1400a; ; ; # ς.-≮خج
+𼎏Σ.-≮ﲫ; 𼎏σ.-≮خج; [B1, P1, V3, V6]; xn--4xa92520c.xn----9mcf1400a; ; ; # σ.-≮خج
+𼎏Σ.-≮ﲫ; 𼎏σ.-≮خج; [B1, P1, V3, V6]; xn--4xa92520c.xn----9mcf1400a; ; ; # σ.-≮خج
+𼎏σ.-≮ﲫ; 𼎏σ.-≮خج; [B1, P1, V3, V6]; xn--4xa92520c.xn----9mcf1400a; ; ; # σ.-≮خج
+𼎏σ.-≮ﲫ; 𼎏σ.-≮خج; [B1, P1, V3, V6]; xn--4xa92520c.xn----9mcf1400a; ; ; # σ.-≮خج
+ꡗࢸܙ.񔤔󠛙్ﰾ; ꡗࢸܙ.񔤔󠛙్كي; [B5, B6, P1, V6]; xn--jnb34fs003a.xn--fhbo927bk128mpi24d; ; ; # ꡗࢸܙ.్كي
+ꡗࢸܙ.񔤔󠛙్كي; ; [B5, B6, P1, V6]; xn--jnb34fs003a.xn--fhbo927bk128mpi24d; ; ; # ꡗࢸܙ.్كي
+xn--jnb34fs003a.xn--fhbo927bk128mpi24d; ꡗࢸܙ.񔤔󠛙్كي; [B5, B6, V6]; xn--jnb34fs003a.xn--fhbo927bk128mpi24d; ; ; # ꡗࢸܙ.్كي
+𐠰ࢷ𞤌𐫭。𐋦៍𝩃; 𐠰ࢷ𞤮𐫭.𐋦៍𝩃; [B1]; xn--dzb5191kezbrw47a.xn--p4e3841jz9tf; ; ; # 𐠰ࢷ𞤮𐫭.𐋦៍𝩃
+𐠰ࢷ𞤮𐫭。𐋦៍𝩃; 𐠰ࢷ𞤮𐫭.𐋦៍𝩃; [B1]; xn--dzb5191kezbrw47a.xn--p4e3841jz9tf; ; ; # 𐠰ࢷ𞤮𐫭.𐋦៍𝩃
+xn--dzb5191kezbrw47a.xn--p4e3841jz9tf; 𐠰ࢷ𞤮𐫭.𐋦៍𝩃; [B1]; xn--dzb5191kezbrw47a.xn--p4e3841jz9tf; ; ; # 𐠰ࢷ𞤮𐫭.𐋦៍𝩃
+𐠰ࢷ𞤮𐫭.𐋦៍𝩃; ; [B1]; xn--dzb5191kezbrw47a.xn--p4e3841jz9tf; ; ; # 𐠰ࢷ𞤮𐫭.𐋦៍𝩃
+𐠰ࢷ𞤌𐫭.𐋦៍𝩃; 𐠰ࢷ𞤮𐫭.𐋦៍𝩃; [B1]; xn--dzb5191kezbrw47a.xn--p4e3841jz9tf; ; ; # 𐠰ࢷ𞤮𐫭.𐋦៍𝩃
+₂㘷--。ۓ‌𐫆𑖿; 2㘷--.ۓ‌𐫆𑖿; [B1, C1, V2, V3]; xn--2---u58b.xn--jlb820ku99nbgj; ; xn--2---u58b.xn--jlb8024k14g; [B1, V2, V3] # 2㘷--.ۓ𐫆𑖿
+₂㘷--。ۓ‌𐫆𑖿; 2㘷--.ۓ‌𐫆𑖿; [B1, C1, V2, V3]; xn--2---u58b.xn--jlb820ku99nbgj; ; xn--2---u58b.xn--jlb8024k14g; [B1, V2, V3] # 2㘷--.ۓ𐫆𑖿
+2㘷--。ۓ‌𐫆𑖿; 2㘷--.ۓ‌𐫆𑖿; [B1, C1, V2, V3]; xn--2---u58b.xn--jlb820ku99nbgj; ; xn--2---u58b.xn--jlb8024k14g; [B1, V2, V3] # 2㘷--.ۓ𐫆𑖿
+2㘷--。ۓ‌𐫆𑖿; 2㘷--.ۓ‌𐫆𑖿; [B1, C1, V2, V3]; xn--2---u58b.xn--jlb820ku99nbgj; ; xn--2---u58b.xn--jlb8024k14g; [B1, V2, V3] # 2㘷--.ۓ𐫆𑖿
+xn--2---u58b.xn--jlb8024k14g; 2㘷--.ۓ𐫆𑖿; [B1, V2, V3]; xn--2---u58b.xn--jlb8024k14g; ; ; # 2㘷--.ۓ𐫆𑖿
+xn--2---u58b.xn--jlb820ku99nbgj; 2㘷--.ۓ‌𐫆𑖿; [B1, C1, V2, V3]; xn--2---u58b.xn--jlb820ku99nbgj; ; ; # 2㘷--.ۓ𐫆𑖿
+-𘊻.ᡮح-; -𘊻.ᡮح-; [B1, B5, B6, V3]; xn----bp5n.xn----bnc231l; ; ; # -𘊻.ᡮح-
+-𘊻.ᡮح-; ; [B1, B5, B6, V3]; xn----bp5n.xn----bnc231l; ; ; # -𘊻.ᡮح-
+xn----bp5n.xn----bnc231l; -𘊻.ᡮح-; [B1, B5, B6, V3]; xn----bp5n.xn----bnc231l; ; ; # -𘊻.ᡮح-
+‌-ß。ᢣ𐹭ؿ; ‌-ß.ᢣ𐹭ؿ; [B1, B5, B6, C1]; xn----qfa550v.xn--bhb925glx3p; ; -ss.xn--bhb925glx3p; [B1, B5, B6, V3] # -ß.ᢣ𐹭ؿ
+‌-ß。ᢣ𐹭ؿ; ‌-ß.ᢣ𐹭ؿ; [B1, B5, B6, C1]; xn----qfa550v.xn--bhb925glx3p; ; -ss.xn--bhb925glx3p; [B1, B5, B6, V3] # -ß.ᢣ𐹭ؿ
+‌-SS。ᢣ𐹭ؿ; ‌-ss.ᢣ𐹭ؿ; [B1, B5, B6, C1]; xn---ss-8m0a.xn--bhb925glx3p; ; -ss.xn--bhb925glx3p; [B1, B5, B6, V3] # -ss.ᢣ𐹭ؿ
+‌-ss。ᢣ𐹭ؿ; ‌-ss.ᢣ𐹭ؿ; [B1, B5, B6, C1]; xn---ss-8m0a.xn--bhb925glx3p; ; -ss.xn--bhb925glx3p; [B1, B5, B6, V3] # -ss.ᢣ𐹭ؿ
+‌-Ss。ᢣ𐹭ؿ; ‌-ss.ᢣ𐹭ؿ; [B1, B5, B6, C1]; xn---ss-8m0a.xn--bhb925glx3p; ; -ss.xn--bhb925glx3p; [B1, B5, B6, V3] # -ss.ᢣ𐹭ؿ
+-ss.xn--bhb925glx3p; -ss.ᢣ𐹭ؿ; [B1, B5, B6, V3]; -ss.xn--bhb925glx3p; ; ; # -ss.ᢣ𐹭ؿ
+xn---ss-8m0a.xn--bhb925glx3p; ‌-ss.ᢣ𐹭ؿ; [B1, B5, B6, C1]; xn---ss-8m0a.xn--bhb925glx3p; ; ; # -ss.ᢣ𐹭ؿ
+xn----qfa550v.xn--bhb925glx3p; ‌-ß.ᢣ𐹭ؿ; [B1, B5, B6, C1]; xn----qfa550v.xn--bhb925glx3p; ; ; # -ß.ᢣ𐹭ؿ
+‌-SS。ᢣ𐹭ؿ; ‌-ss.ᢣ𐹭ؿ; [B1, B5, B6, C1]; xn---ss-8m0a.xn--bhb925glx3p; ; -ss.xn--bhb925glx3p; [B1, B5, B6, V3] # -ss.ᢣ𐹭ؿ
+‌-ss。ᢣ𐹭ؿ; ‌-ss.ᢣ𐹭ؿ; [B1, B5, B6, C1]; xn---ss-8m0a.xn--bhb925glx3p; ; -ss.xn--bhb925glx3p; [B1, B5, B6, V3] # -ss.ᢣ𐹭ؿ
+‌-Ss。ᢣ𐹭ؿ; ‌-ss.ᢣ𐹭ؿ; [B1, B5, B6, C1]; xn---ss-8m0a.xn--bhb925glx3p; ; -ss.xn--bhb925glx3p; [B1, B5, B6, V3] # -ss.ᢣ𐹭ؿ
+꧐Ӏ᮪ࣶ.눵; ꧐Ӏ᮪ࣶ.눵; [P1, V6]; xn--d5a07sn4u297k.xn--2e1b; ; ; # ꧐Ӏ᮪ࣶ.눵
+꧐Ӏ᮪ࣶ.눵; ꧐Ӏ᮪ࣶ.눵; [P1, V6]; xn--d5a07sn4u297k.xn--2e1b; ; ; # ꧐Ӏ᮪ࣶ.눵
+꧐Ӏ᮪ࣶ.눵; ; [P1, V6]; xn--d5a07sn4u297k.xn--2e1b; ; ; # ꧐Ӏ᮪ࣶ.눵
+꧐Ӏ᮪ࣶ.눵; ꧐Ӏ᮪ࣶ.눵; [P1, V6]; xn--d5a07sn4u297k.xn--2e1b; ; ; # ꧐Ӏ᮪ࣶ.눵
+꧐ӏ᮪ࣶ.눵; ꧐ӏ᮪ࣶ.눵; ; xn--s5a04sn4u297k.xn--2e1b; ; ; # ꧐ӏ᮪ࣶ.눵
+꧐ӏ᮪ࣶ.눵; ; ; xn--s5a04sn4u297k.xn--2e1b; ; ; # ꧐ӏ᮪ࣶ.눵
+xn--s5a04sn4u297k.xn--2e1b; ꧐ӏ᮪ࣶ.눵; ; xn--s5a04sn4u297k.xn--2e1b; ; ; # ꧐ӏ᮪ࣶ.눵
+xn--d5a07sn4u297k.xn--2e1b; ꧐Ӏ᮪ࣶ.눵; [V6]; xn--d5a07sn4u297k.xn--2e1b; ; ; # ꧐Ӏ᮪ࣶ.눵
+꧐ӏ᮪ࣶ.눵; ꧐ӏ᮪ࣶ.눵; ; xn--s5a04sn4u297k.xn--2e1b; ; ; # ꧐ӏ᮪ࣶ.눵
+꧐ӏ᮪ࣶ.눵; ꧐ӏ᮪ࣶ.눵; ; xn--s5a04sn4u297k.xn--2e1b; ; ; # ꧐ӏ᮪ࣶ.눵
+꣪。𖄿𑆾󠇗; ꣪.𖄿𑆾; [P1, V5, V6]; xn--3g9a.xn--ud1dz07k; ; ; # ꣪.𑆾
+꣪。𖄿𑆾󠇗; ꣪.𖄿𑆾; [P1, V5, V6]; xn--3g9a.xn--ud1dz07k; ; ; # ꣪.𑆾
+xn--3g9a.xn--ud1dz07k; ꣪.𖄿𑆾; [V5, V6]; xn--3g9a.xn--ud1dz07k; ; ; # ꣪.𑆾
+󇓓𑚳。񐷿≯⾇; 󇓓𑚳.񐷿≯舛; [P1, V6]; xn--3e2d79770c.xn--hdh0088abyy1c; ; ; # 𑚳.≯舛
+󇓓𑚳。񐷿≯⾇; 󇓓𑚳.񐷿≯舛; [P1, V6]; xn--3e2d79770c.xn--hdh0088abyy1c; ; ; # 𑚳.≯舛
+󇓓𑚳。񐷿≯舛; 󇓓𑚳.񐷿≯舛; [P1, V6]; xn--3e2d79770c.xn--hdh0088abyy1c; ; ; # 𑚳.≯舛
+󇓓𑚳。񐷿≯舛; 󇓓𑚳.񐷿≯舛; [P1, V6]; xn--3e2d79770c.xn--hdh0088abyy1c; ; ; # 𑚳.≯舛
+xn--3e2d79770c.xn--hdh0088abyy1c; 󇓓𑚳.񐷿≯舛; [V6]; xn--3e2d79770c.xn--hdh0088abyy1c; ; ; # 𑚳.≯舛
+𐫇١‌.‍‌; 𐫇١‌.‍‌; [B1, B3, C1, C2]; xn--9hb652kv99n.xn--0ugb; ; xn--9hb7344k.; [] # 𐫇١.
+𐫇١‌.‍‌; ; [B1, B3, C1, C2]; xn--9hb652kv99n.xn--0ugb; ; xn--9hb7344k.; [] # 𐫇١.
+xn--9hb7344k.; 𐫇١.; ; xn--9hb7344k.; ; ; # 𐫇١.
+𐫇١.; ; ; xn--9hb7344k.; ; ; # 𐫇١.
+xn--9hb652kv99n.xn--0ugb; 𐫇١‌.‍‌; [B1, B3, C1, C2]; xn--9hb652kv99n.xn--0ugb; ; ; # 𐫇١.
+񡅈砪≯ᢑ。≯𝩚򓴔‌; 񡅈砪≯ᢑ.≯𝩚򓴔‌; [C1, P1, V6]; xn--bbf561cf95e57y3e.xn--0ugz6gc910ejro8c; ; xn--bbf561cf95e57y3e.xn--hdh0834o7mj6b; [P1, V6] # 砪≯ᢑ.≯𝩚
+񡅈砪≯ᢑ。≯𝩚򓴔‌; 񡅈砪≯ᢑ.≯𝩚򓴔‌; [C1, P1, V6]; xn--bbf561cf95e57y3e.xn--0ugz6gc910ejro8c; ; xn--bbf561cf95e57y3e.xn--hdh0834o7mj6b; [P1, V6] # 砪≯ᢑ.≯𝩚
+񡅈砪≯ᢑ。≯𝩚򓴔‌; 񡅈砪≯ᢑ.≯𝩚򓴔‌; [C1, P1, V6]; xn--bbf561cf95e57y3e.xn--0ugz6gc910ejro8c; ; xn--bbf561cf95e57y3e.xn--hdh0834o7mj6b; [P1, V6] # 砪≯ᢑ.≯𝩚
+񡅈砪≯ᢑ。≯𝩚򓴔‌; 񡅈砪≯ᢑ.≯𝩚򓴔‌; [C1, P1, V6]; xn--bbf561cf95e57y3e.xn--0ugz6gc910ejro8c; ; xn--bbf561cf95e57y3e.xn--hdh0834o7mj6b; [P1, V6] # 砪≯ᢑ.≯𝩚
+xn--bbf561cf95e57y3e.xn--hdh0834o7mj6b; 񡅈砪≯ᢑ.≯𝩚򓴔; [V6]; xn--bbf561cf95e57y3e.xn--hdh0834o7mj6b; ; ; # 砪≯ᢑ.≯𝩚
+xn--bbf561cf95e57y3e.xn--0ugz6gc910ejro8c; 񡅈砪≯ᢑ.≯𝩚򓴔‌; [C1, V6]; xn--bbf561cf95e57y3e.xn--0ugz6gc910ejro8c; ; ; # 砪≯ᢑ.≯𝩚
+Ⴥ.𑄳㊸; Ⴥ.𑄳43; [P1, V5, V6]; xn--9nd.xn--43-274o; ; ; # Ⴥ.𑄳43
+Ⴥ.𑄳43; ; [P1, V5, V6]; xn--9nd.xn--43-274o; ; ; # Ⴥ.𑄳43
+ⴥ.𑄳43; ; [V5]; xn--tlj.xn--43-274o; ; ; # ⴥ.𑄳43
+xn--tlj.xn--43-274o; ⴥ.𑄳43; [V5]; xn--tlj.xn--43-274o; ; ; # ⴥ.𑄳43
+xn--9nd.xn--43-274o; Ⴥ.𑄳43; [V5, V6]; xn--9nd.xn--43-274o; ; ; # Ⴥ.𑄳43
+ⴥ.𑄳㊸; ⴥ.𑄳43; [V5]; xn--tlj.xn--43-274o; ; ; # ⴥ.𑄳43
+𝟎٣。Ⴒᡇࣲ𐹠; 0٣.Ⴒᡇࣲ𐹠; [B1, B5, B6, P1, V6]; xn--0-fqc.xn--10b180bnwgfy0z; ; ; # 0٣.Ⴒᡇࣲ𐹠
+0٣。Ⴒᡇࣲ𐹠; 0٣.Ⴒᡇࣲ𐹠; [B1, B5, B6, P1, V6]; xn--0-fqc.xn--10b180bnwgfy0z; ; ; # 0٣.Ⴒᡇࣲ𐹠
+0٣。ⴒᡇࣲ𐹠; 0٣.ⴒᡇࣲ𐹠; [B1, B5, B6]; xn--0-fqc.xn--10b369eivp359r; ; ; # 0٣.ⴒᡇࣲ𐹠
+xn--0-fqc.xn--10b369eivp359r; 0٣.ⴒᡇࣲ𐹠; [B1, B5, B6]; xn--0-fqc.xn--10b369eivp359r; ; ; # 0٣.ⴒᡇࣲ𐹠
+xn--0-fqc.xn--10b180bnwgfy0z; 0٣.Ⴒᡇࣲ𐹠; [B1, B5, B6, V6]; xn--0-fqc.xn--10b180bnwgfy0z; ; ; # 0٣.Ⴒᡇࣲ𐹠
+𝟎٣。ⴒᡇࣲ𐹠; 0٣.ⴒᡇࣲ𐹠; [B1, B5, B6]; xn--0-fqc.xn--10b369eivp359r; ; ; # 0٣.ⴒᡇࣲ𐹠
+񗪨󠄉ᅠྷ.񸞰꥓; 񗪨ᅠྷ.񸞰꥓; [P1, V6]; xn--kgd7493jee34a.xn--3j9au7544a; ; ; # ྷ.꥓
+񗪨󠄉ᅠྷ.񸞰꥓; 񗪨ᅠྷ.񸞰꥓; [P1, V6]; xn--kgd36f9z57y.xn--3j9au7544a; ; ; # ྷ.꥓
+xn--kgd36f9z57y.xn--3j9au7544a; 񗪨ᅠྷ.񸞰꥓; [V6]; xn--kgd36f9z57y.xn--3j9au7544a; ; ; # ྷ.꥓
+xn--kgd7493jee34a.xn--3j9au7544a; 񗪨ᅠྷ.񸞰꥓; [V6]; xn--kgd7493jee34a.xn--3j9au7544a; ; ; # ྷ.꥓
+ؘ.۳‌꥓; ; [C1, V5]; xn--6fb.xn--gmb469jjf1h; ; xn--6fb.xn--gmb0524f; [V5] # ؘ.۳꥓
+xn--6fb.xn--gmb0524f; ؘ.۳꥓; [V5]; xn--6fb.xn--gmb0524f; ; ; # ؘ.۳꥓
+xn--6fb.xn--gmb469jjf1h; ؘ.۳‌꥓; [C1, V5]; xn--6fb.xn--gmb469jjf1h; ; ; # ؘ.۳꥓
+ᡌ.︒ᢑ; ᡌ.︒ᢑ; [P1, V6]; xn--c8e.xn--bbf9168i; ; ; # ᡌ.︒ᢑ
+ᡌ.。ᢑ; ᡌ..ᢑ; [X4_2]; xn--c8e..xn--bbf; [A4_2]; ; # ᡌ..ᢑ
+xn--c8e..xn--bbf; ᡌ..ᢑ; [X4_2]; xn--c8e..xn--bbf; [A4_2]; ; # ᡌ..ᢑ
+xn--c8e.xn--bbf9168i; ᡌ.︒ᢑ; [V6]; xn--c8e.xn--bbf9168i; ; ; # ᡌ.︒ᢑ
+𑋪ၳ。𞽧; 𑋪ၳ.𞽧; [B1, B3, B6, P1, V5, V6]; xn--xld7443k.xn--4o7h; ; ; # 𑋪ၳ.
+𑋪ၳ。𞽧; 𑋪ၳ.𞽧; [B1, B3, B6, P1, V5, V6]; xn--xld7443k.xn--4o7h; ; ; # 𑋪ၳ.
+xn--xld7443k.xn--4o7h; 𑋪ၳ.𞽧; [B1, B3, B6, V5, V6]; xn--xld7443k.xn--4o7h; ; ; # 𑋪ၳ.
+𞷏。ᠢ򓘆; 𞷏.ᠢ򓘆; [P1, V6]; xn--hd7h.xn--46e66060j; ; ; # .ᠢ
+xn--hd7h.xn--46e66060j; 𞷏.ᠢ򓘆; [V6]; xn--hd7h.xn--46e66060j; ; ; # .ᠢ
+𑄳㴼.‌𐹡⃫񫺦; 𑄳㴼.‌𐹡⃫񫺦; [B1, C1, P1, V5, V6]; xn--iym9428c.xn--0ug46a7218cllv0c; ; xn--iym9428c.xn--e1g3464g08p3b; [B1, P1, V5, V6] # 𑄳㴼.𐹡⃫
+𑄳㴼.‌𐹡⃫񫺦; ; [B1, C1, P1, V5, V6]; xn--iym9428c.xn--0ug46a7218cllv0c; ; xn--iym9428c.xn--e1g3464g08p3b; [B1, P1, V5, V6] # 𑄳㴼.𐹡⃫
+xn--iym9428c.xn--e1g3464g08p3b; 𑄳㴼.𐹡⃫񫺦; [B1, V5, V6]; xn--iym9428c.xn--e1g3464g08p3b; ; ; # 𑄳㴼.𐹡⃫
+xn--iym9428c.xn--0ug46a7218cllv0c; 𑄳㴼.‌𐹡⃫񫺦; [B1, C1, V5, V6]; xn--iym9428c.xn--0ug46a7218cllv0c; ; ; # 𑄳㴼.𐹡⃫
+񠻟𐹳𑈯。̝; 񠻟𐹳𑈯.̝; [B1, B3, B5, B6, P1, V5, V6]; xn--ro0dw7dey96m.xn--eta; ; ; # 𐹳𑈯.̝
+񠻟𐹳𑈯。̝; 񠻟𐹳𑈯.̝; [B1, B3, B5, B6, P1, V5, V6]; xn--ro0dw7dey96m.xn--eta; ; ; # 𐹳𑈯.̝
+xn--ro0dw7dey96m.xn--eta; 񠻟𐹳𑈯.̝; [B1, B3, B5, B6, V5, V6]; xn--ro0dw7dey96m.xn--eta; ; ; # 𐹳𑈯.̝
+ᢊ뾜󠱴𑚶。࢝𐹥; ᢊ뾜󠱴𑚶.࢝𐹥; [B1, P1, V5, V6]; xn--39e4566fjv8bwmt6n.xn--myb6415k; ; ; # ᢊ뾜𑚶.࢝𐹥
+ᢊ뾜󠱴𑚶。࢝𐹥; ᢊ뾜󠱴𑚶.࢝𐹥; [B1, P1, V5, V6]; xn--39e4566fjv8bwmt6n.xn--myb6415k; ; ; # ᢊ뾜𑚶.࢝𐹥
+xn--39e4566fjv8bwmt6n.xn--myb6415k; ᢊ뾜󠱴𑚶.࢝𐹥; [B1, V5, V6]; xn--39e4566fjv8bwmt6n.xn--myb6415k; ; ; # ᢊ뾜𑚶.࢝𐹥
+𐹥≠。𐋲󠧠‌; 𐹥≠.𐋲󠧠‌; [B1, C1, P1, V6]; xn--1ch6704g.xn--0ug3840g51u4g; ; xn--1ch6704g.xn--m97cw2999c; [B1, P1, V6] # 𐹥≠.𐋲
+𐹥≠。𐋲󠧠‌; 𐹥≠.𐋲󠧠‌; [B1, C1, P1, V6]; xn--1ch6704g.xn--0ug3840g51u4g; ; xn--1ch6704g.xn--m97cw2999c; [B1, P1, V6] # 𐹥≠.𐋲
+𐹥≠。𐋲󠧠‌; 𐹥≠.𐋲󠧠‌; [B1, C1, P1, V6]; xn--1ch6704g.xn--0ug3840g51u4g; ; xn--1ch6704g.xn--m97cw2999c; [B1, P1, V6] # 𐹥≠.𐋲
+𐹥≠。𐋲󠧠‌; 𐹥≠.𐋲󠧠‌; [B1, C1, P1, V6]; xn--1ch6704g.xn--0ug3840g51u4g; ; xn--1ch6704g.xn--m97cw2999c; [B1, P1, V6] # 𐹥≠.𐋲
+xn--1ch6704g.xn--m97cw2999c; 𐹥≠.𐋲󠧠; [B1, V6]; xn--1ch6704g.xn--m97cw2999c; ; ; # 𐹥≠.𐋲
+xn--1ch6704g.xn--0ug3840g51u4g; 𐹥≠.𐋲󠧠‌; [B1, C1, V6]; xn--1ch6704g.xn--0ug3840g51u4g; ; ; # 𐹥≠.𐋲
+ᅟ񙯠्.‍꥓𐪤; ᅟ񙯠्.‍꥓𐪤; [B1, C2, P1, V6]; xn--n3b542bb085j.xn--1ug6815co9wc; ; xn--n3b542bb085j.xn--3j9al95p; [B5, B6, P1, V5, V6] # ्.꥓
+ᅟ񙯠्.‍꥓𐪤; ; [B1, C2, P1, V6]; xn--n3b542bb085j.xn--1ug6815co9wc; ; xn--n3b542bb085j.xn--3j9al95p; [B5, B6, P1, V5, V6] # ्.꥓
+xn--n3b542bb085j.xn--3j9al95p; ᅟ񙯠्.꥓𐪤; [B5, B6, V5, V6]; xn--n3b542bb085j.xn--3j9al95p; ; ; # ्.꥓
+xn--n3b542bb085j.xn--1ug6815co9wc; ᅟ񙯠्.‍꥓𐪤; [B1, C2, V6]; xn--n3b542bb085j.xn--1ug6815co9wc; ; ; # ्.꥓
+򌋔󠆎󠆗𑲕。≮; 򌋔𑲕.≮; [P1, V6]; xn--4m3dv4354a.xn--gdh; ; ; # 𑲕.≮
+򌋔󠆎󠆗𑲕。≮; 򌋔𑲕.≮; [P1, V6]; xn--4m3dv4354a.xn--gdh; ; ; # 𑲕.≮
+xn--4m3dv4354a.xn--gdh; 򌋔𑲕.≮; [V6]; xn--4m3dv4354a.xn--gdh; ; ; # 𑲕.≮
+󠆦.ࣣ暀≠; .ࣣ暀≠; [P1, V5, V6, X4_2]; .xn--m0b461k3g2c; [P1, V5, V6, A4_2]; ; # .ࣣ暀≠
+󠆦.ࣣ暀≠; .ࣣ暀≠; [P1, V5, V6, X4_2]; .xn--m0b461k3g2c; [P1, V5, V6, A4_2]; ; # .ࣣ暀≠
+.xn--m0b461k3g2c; .ࣣ暀≠; [V5, V6, X4_2]; .xn--m0b461k3g2c; [V5, V6, A4_2]; ; # .ࣣ暀≠
+𐡤꯭。ﴰ򜖅ᷰ; 𐡤꯭.شم򜖅ᷰ; [B2, B3, P1, V6]; xn--429ak76o.xn--zgb8a701kox37t; ; ; # 𐡤꯭.شمᷰ
+𐡤꯭。شم򜖅ᷰ; 𐡤꯭.شم򜖅ᷰ; [B2, B3, P1, V6]; xn--429ak76o.xn--zgb8a701kox37t; ; ; # 𐡤꯭.شمᷰ
+xn--429ak76o.xn--zgb8a701kox37t; 𐡤꯭.شم򜖅ᷰ; [B2, B3, V6]; xn--429ak76o.xn--zgb8a701kox37t; ; ; # 𐡤꯭.شمᷰ
+𝉃‍⒈。Ⴌ𞱓; 𝉃‍⒈.Ⴌ𞱓; [B1, B5, B6, C2, P1, V5, V6]; xn--1ug68oq348b.xn--knd8464v; ; xn--tshz828m.xn--knd8464v; [B1, B5, B6, P1, V5, V6] # 𝉃⒈.Ⴌ
+𝉃‍1.。Ⴌ𞱓; 𝉃‍1..Ⴌ𞱓; [B1, B5, B6, C2, P1, V5, V6, X4_2]; xn--1-tgn9827q..xn--knd8464v; [B1, B5, B6, C2, P1, V5, V6, A4_2]; xn--1-px8q..xn--knd8464v; [B1, B5, B6, P1, V5, V6, A4_2] # 𝉃1..Ⴌ
+𝉃‍1.。ⴌ𞱓; 𝉃‍1..ⴌ𞱓; [B1, B5, B6, C2, P1, V5, V6, X4_2]; xn--1-tgn9827q..xn--3kj4524l; [B1, B5, B6, C2, P1, V5, V6, A4_2]; xn--1-px8q..xn--3kj4524l; [B1, B5, B6, P1, V5, V6, A4_2] # 𝉃1..ⴌ
+xn--1-px8q..xn--3kj4524l; 𝉃1..ⴌ𞱓; [B1, B5, B6, V5, V6, X4_2]; xn--1-px8q..xn--3kj4524l; [B1, B5, B6, V5, V6, A4_2]; ; # 𝉃1..ⴌ
+xn--1-tgn9827q..xn--3kj4524l; 𝉃‍1..ⴌ𞱓; [B1, B5, B6, C2, V5, V6, X4_2]; xn--1-tgn9827q..xn--3kj4524l; [B1, B5, B6, C2, V5, V6, A4_2]; ; # 𝉃1..ⴌ
+xn--1-px8q..xn--knd8464v; 𝉃1..Ⴌ𞱓; [B1, B5, B6, V5, V6, X4_2]; xn--1-px8q..xn--knd8464v; [B1, B5, B6, V5, V6, A4_2]; ; # 𝉃1..Ⴌ
+xn--1-tgn9827q..xn--knd8464v; 𝉃‍1..Ⴌ𞱓; [B1, B5, B6, C2, V5, V6, X4_2]; xn--1-tgn9827q..xn--knd8464v; [B1, B5, B6, C2, V5, V6, A4_2]; ; # 𝉃1..Ⴌ
+𝉃‍⒈。ⴌ𞱓; 𝉃‍⒈.ⴌ𞱓; [B1, B5, B6, C2, P1, V5, V6]; xn--1ug68oq348b.xn--3kj4524l; ; xn--tshz828m.xn--3kj4524l; [B1, B5, B6, P1, V5, V6] # 𝉃⒈.ⴌ
+xn--tshz828m.xn--3kj4524l; 𝉃⒈.ⴌ𞱓; [B1, B5, B6, V5, V6]; xn--tshz828m.xn--3kj4524l; ; ; # 𝉃⒈.ⴌ
+xn--1ug68oq348b.xn--3kj4524l; 𝉃‍⒈.ⴌ𞱓; [B1, B5, B6, C2, V5, V6]; xn--1ug68oq348b.xn--3kj4524l; ; ; # 𝉃⒈.ⴌ
+xn--tshz828m.xn--knd8464v; 𝉃⒈.Ⴌ𞱓; [B1, B5, B6, V5, V6]; xn--tshz828m.xn--knd8464v; ; ; # 𝉃⒈.Ⴌ
+xn--1ug68oq348b.xn--knd8464v; 𝉃‍⒈.Ⴌ𞱓; [B1, B5, B6, C2, V5, V6]; xn--1ug68oq348b.xn--knd8464v; ; ; # 𝉃⒈.Ⴌ
+󠣙੍𱫘𞤸.ς񵯞􈰔; ; [B1, P1, V6]; xn--ybc0236vjvxgt5q0g.xn--3xa03737giye6b; ; xn--ybc0236vjvxgt5q0g.xn--4xa82737giye6b; # ੍𞤸.ς
+󠣙੍𱫘𞤖.Σ񵯞􈰔; 󠣙੍𱫘𞤸.σ񵯞􈰔; [B1, P1, V6]; xn--ybc0236vjvxgt5q0g.xn--4xa82737giye6b; ; ; # ੍𞤸.σ
+󠣙੍𱫘𞤸.σ񵯞􈰔; ; [B1, P1, V6]; xn--ybc0236vjvxgt5q0g.xn--4xa82737giye6b; ; ; # ੍𞤸.σ
+󠣙੍𱫘𞤖.σ񵯞􈰔; 󠣙੍𱫘𞤸.σ񵯞􈰔; [B1, P1, V6]; xn--ybc0236vjvxgt5q0g.xn--4xa82737giye6b; ; ; # ੍𞤸.σ
+xn--ybc0236vjvxgt5q0g.xn--4xa82737giye6b; 󠣙੍𱫘𞤸.σ񵯞􈰔; [B1, V6]; xn--ybc0236vjvxgt5q0g.xn--4xa82737giye6b; ; ; # ੍𞤸.σ
+󠣙੍𱫘𞤖.ς񵯞􈰔; 󠣙੍𱫘𞤸.ς񵯞􈰔; [B1, P1, V6]; xn--ybc0236vjvxgt5q0g.xn--3xa03737giye6b; ; xn--ybc0236vjvxgt5q0g.xn--4xa82737giye6b; # ੍𞤸.ς
+xn--ybc0236vjvxgt5q0g.xn--3xa03737giye6b; 󠣙੍𱫘𞤸.ς񵯞􈰔; [B1, V6]; xn--ybc0236vjvxgt5q0g.xn--3xa03737giye6b; ; ; # ੍𞤸.ς
+󠣙੍𱫘𞤸.Σ񵯞􈰔; 󠣙੍𱫘𞤸.σ񵯞􈰔; [B1, P1, V6]; xn--ybc0236vjvxgt5q0g.xn--4xa82737giye6b; ; ; # ੍𞤸.σ
+ߓ。‌𐫀򞭱; ߓ.‌𐫀򞭱; [B1, C1, P1, V6]; xn--usb.xn--0ug9553gm3v5d; ; xn--usb.xn--pw9ci1099a; [B2, B3, P1, V6] # ߓ.𐫀
+xn--usb.xn--pw9ci1099a; ߓ.𐫀򞭱; [B2, B3, V6]; xn--usb.xn--pw9ci1099a; ; ; # ߓ.𐫀
+xn--usb.xn--0ug9553gm3v5d; ߓ.‌𐫀򞭱; [B1, C1, V6]; xn--usb.xn--0ug9553gm3v5d; ; ; # ߓ.𐫀
+ᰮ𞀝.֦ꡟ𞤕󠆖; ᰮ𞀝.֦ꡟ𞤷; [B1, B3, B6, V5]; xn--q1f4493q.xn--xcb8244fifvj; ; ; # ᰮ𞀝.֦ꡟ𞤷
+ᰮ𞀝.֦ꡟ𞤷󠆖; ᰮ𞀝.֦ꡟ𞤷; [B1, B3, B6, V5]; xn--q1f4493q.xn--xcb8244fifvj; ; ; # ᰮ𞀝.֦ꡟ𞤷
+xn--q1f4493q.xn--xcb8244fifvj; ᰮ𞀝.֦ꡟ𞤷; [B1, B3, B6, V5]; xn--q1f4493q.xn--xcb8244fifvj; ; ; # ᰮ𞀝.֦ꡟ𞤷
+䂹󾖅𐋦.‍; 䂹󾖅𐋦.‍; [C2, P1, V6]; xn--0on3543c5981i.xn--1ug; ; xn--0on3543c5981i.; [P1, V6] # 䂹𐋦.
+䂹󾖅𐋦.‍; ; [C2, P1, V6]; xn--0on3543c5981i.xn--1ug; ; xn--0on3543c5981i.; [P1, V6] # 䂹𐋦.
+xn--0on3543c5981i.; 䂹󾖅𐋦.; [V6]; xn--0on3543c5981i.; ; ; # 䂹𐋦.
+xn--0on3543c5981i.xn--1ug; 䂹󾖅𐋦.‍; [C2, V6]; xn--0on3543c5981i.xn--1ug; ; ; # 䂹𐋦.
+꧀‌𐹲‌。ݧ🄉; ꧀‌𐹲‌.ݧ🄉; [B5, B6, C1, P1, V5, V6]; xn--0uga8686hdgvd.xn--rpb6081w; ; xn--7m9an32q.xn--rpb6081w; [B5, B6, P1, V5, V6] # ꧀𐹲.ݧ🄉
+꧀‌𐹲‌。ݧ8,; ꧀‌𐹲‌.ݧ8,; [B3, B5, B6, C1, P1, V5, V6]; xn--0uga8686hdgvd.xn--8,-qle; ; xn--7m9an32q.xn--8,-qle; [B3, B5, B6, P1, V5, V6] # ꧀𐹲.ݧ8,
+xn--7m9an32q.xn--8,-qle; ꧀𐹲.ݧ8,; [B3, B5, B6, P1, V5, V6]; xn--7m9an32q.xn--8,-qle; ; ; # ꧀𐹲.ݧ8,
+xn--0uga8686hdgvd.xn--8,-qle; ꧀‌𐹲‌.ݧ8,; [B3, B5, B6, C1, P1, V5, V6]; xn--0uga8686hdgvd.xn--8,-qle; ; ; # ꧀𐹲.ݧ8,
+xn--7m9an32q.xn--rpb6081w; ꧀𐹲.ݧ🄉; [B5, B6, V5, V6]; xn--7m9an32q.xn--rpb6081w; ; ; # ꧀𐹲.ݧ🄉
+xn--0uga8686hdgvd.xn--rpb6081w; ꧀‌𐹲‌.ݧ🄉; [B5, B6, C1, V5, V6]; xn--0uga8686hdgvd.xn--rpb6081w; ; ; # ꧀𐹲.ݧ🄉
+︒。Ⴃ≯; ︒.Ⴃ≯; [P1, V6]; xn--y86c.xn--bnd622g; ; ; # ︒.Ⴃ≯
+︒。Ⴃ≯; ︒.Ⴃ≯; [P1, V6]; xn--y86c.xn--bnd622g; ; ; # ︒.Ⴃ≯
+。。Ⴃ≯; ..Ⴃ≯; [P1, V6, X4_2]; ..xn--bnd622g; [P1, V6, A4_2]; ; # ..Ⴃ≯
+。。Ⴃ≯; ..Ⴃ≯; [P1, V6, X4_2]; ..xn--bnd622g; [P1, V6, A4_2]; ; # ..Ⴃ≯
+。。ⴃ≯; ..ⴃ≯; [P1, V6, X4_2]; ..xn--hdh782b; [P1, V6, A4_2]; ; # ..ⴃ≯
+。。ⴃ≯; ..ⴃ≯; [P1, V6, X4_2]; ..xn--hdh782b; [P1, V6, A4_2]; ; # ..ⴃ≯
+..xn--hdh782b; ..ⴃ≯; [V6, X4_2]; ..xn--hdh782b; [V6, A4_2]; ; # ..ⴃ≯
+..xn--bnd622g; ..Ⴃ≯; [V6, X4_2]; ..xn--bnd622g; [V6, A4_2]; ; # ..Ⴃ≯
+︒。ⴃ≯; ︒.ⴃ≯; [P1, V6]; xn--y86c.xn--hdh782b; ; ; # ︒.ⴃ≯
+︒。ⴃ≯; ︒.ⴃ≯; [P1, V6]; xn--y86c.xn--hdh782b; ; ; # ︒.ⴃ≯
+xn--y86c.xn--hdh782b; ︒.ⴃ≯; [V6]; xn--y86c.xn--hdh782b; ; ; # ︒.ⴃ≯
+xn--y86c.xn--bnd622g; ︒.Ⴃ≯; [V6]; xn--y86c.xn--bnd622g; ; ; # ︒.Ⴃ≯
+𐹮。󠢼‍; 𐹮.󠢼‍; [B1, C2, P1, V6]; xn--mo0d.xn--1ug18431l; ; xn--mo0d.xn--wy46e; [B1, P1, V6] # 𐹮.
+𐹮。󠢼‍; 𐹮.󠢼‍; [B1, C2, P1, V6]; xn--mo0d.xn--1ug18431l; ; xn--mo0d.xn--wy46e; [B1, P1, V6] # 𐹮.
+xn--mo0d.xn--wy46e; 𐹮.󠢼; [B1, V6]; xn--mo0d.xn--wy46e; ; ; # 𐹮.
+xn--mo0d.xn--1ug18431l; 𐹮.󠢼‍; [B1, C2, V6]; xn--mo0d.xn--1ug18431l; ; ; # 𐹮.
+Ⴞ𐹨。︒ݽ‍Ⴏ; Ⴞ𐹨.︒ݽ‍Ⴏ; [B1, B5, B6, C2, P1, V6]; xn--2nd0990k.xn--eqb228bgzmvp0t; ; xn--2nd0990k.xn--eqb228b583r; [B1, B5, B6, P1, V6] # Ⴞ𐹨.︒ݽႯ
+Ⴞ𐹨。。ݽ‍Ⴏ; Ⴞ𐹨..ݽ‍Ⴏ; [B2, B3, B5, B6, C2, P1, V6, X4_2]; xn--2nd0990k..xn--eqb228bgzm; [B2, B3, B5, B6, C2, P1, V6, A4_2]; xn--2nd0990k..xn--eqb228b; [B2, B3, B5, B6, P1, V6, A4_2] # Ⴞ𐹨..ݽႯ
+ⴞ𐹨。。ݽ‍ⴏ; ⴞ𐹨..ݽ‍ⴏ; [B2, B3, B5, B6, C2, X4_2]; xn--mlju223e..xn--eqb096jpgj; [B2, B3, B5, B6, C2, A4_2]; xn--mlju223e..xn--eqb053q; [B2, B3, B5, B6, A4_2] # ⴞ𐹨..ݽⴏ
+Ⴞ𐹨。。ݽ‍ⴏ; Ⴞ𐹨..ݽ‍ⴏ; [B2, B3, B5, B6, C2, P1, V6, X4_2]; xn--2nd0990k..xn--eqb096jpgj; [B2, B3, B5, B6, C2, P1, V6, A4_2]; xn--2nd0990k..xn--eqb053q; [B2, B3, B5, B6, P1, V6, A4_2] # Ⴞ𐹨..ݽⴏ
+xn--2nd0990k..xn--eqb053q; Ⴞ𐹨..ݽⴏ; [B2, B3, B5, B6, V6, X4_2]; xn--2nd0990k..xn--eqb053q; [B2, B3, B5, B6, V6, A4_2]; ; # Ⴞ𐹨..ݽⴏ
+xn--2nd0990k..xn--eqb096jpgj; Ⴞ𐹨..ݽ‍ⴏ; [B2, B3, B5, B6, C2, V6, X4_2]; xn--2nd0990k..xn--eqb096jpgj; [B2, B3, B5, B6, C2, V6, A4_2]; ; # Ⴞ𐹨..ݽⴏ
+xn--mlju223e..xn--eqb053q; ⴞ𐹨..ݽⴏ; [B2, B3, B5, B6, X4_2]; xn--mlju223e..xn--eqb053q; [B2, B3, B5, B6, A4_2]; ; # ⴞ𐹨..ݽⴏ
+xn--mlju223e..xn--eqb096jpgj; ⴞ𐹨..ݽ‍ⴏ; [B2, B3, B5, B6, C2, X4_2]; xn--mlju223e..xn--eqb096jpgj; [B2, B3, B5, B6, C2, A4_2]; ; # ⴞ𐹨..ݽⴏ
+xn--2nd0990k..xn--eqb228b; Ⴞ𐹨..ݽႯ; [B2, B3, B5, B6, V6, X4_2]; xn--2nd0990k..xn--eqb228b; [B2, B3, B5, B6, V6, A4_2]; ; # Ⴞ𐹨..ݽႯ
+xn--2nd0990k..xn--eqb228bgzm; Ⴞ𐹨..ݽ‍Ⴏ; [B2, B3, B5, B6, C2, V6, X4_2]; xn--2nd0990k..xn--eqb228bgzm; [B2, B3, B5, B6, C2, V6, A4_2]; ; # Ⴞ𐹨..ݽႯ
+ⴞ𐹨。︒ݽ‍ⴏ; ⴞ𐹨.︒ݽ‍ⴏ; [B1, B5, B6, C2, P1, V6]; xn--mlju223e.xn--eqb096jpgj9y7r; ; xn--mlju223e.xn--eqb053qjk7l; [B1, B5, B6, P1, V6] # ⴞ𐹨.︒ݽⴏ
+Ⴞ𐹨。︒ݽ‍ⴏ; Ⴞ𐹨.︒ݽ‍ⴏ; [B1, B5, B6, C2, P1, V6]; xn--2nd0990k.xn--eqb096jpgj9y7r; ; xn--2nd0990k.xn--eqb053qjk7l; [B1, B5, B6, P1, V6] # Ⴞ𐹨.︒ݽⴏ
+xn--2nd0990k.xn--eqb053qjk7l; Ⴞ𐹨.︒ݽⴏ; [B1, B5, B6, V6]; xn--2nd0990k.xn--eqb053qjk7l; ; ; # Ⴞ𐹨.︒ݽⴏ
+xn--2nd0990k.xn--eqb096jpgj9y7r; Ⴞ𐹨.︒ݽ‍ⴏ; [B1, B5, B6, C2, V6]; xn--2nd0990k.xn--eqb096jpgj9y7r; ; ; # Ⴞ𐹨.︒ݽⴏ
+xn--mlju223e.xn--eqb053qjk7l; ⴞ𐹨.︒ݽⴏ; [B1, B5, B6, V6]; xn--mlju223e.xn--eqb053qjk7l; ; ; # ⴞ𐹨.︒ݽⴏ
+xn--mlju223e.xn--eqb096jpgj9y7r; ⴞ𐹨.︒ݽ‍ⴏ; [B1, B5, B6, C2, V6]; xn--mlju223e.xn--eqb096jpgj9y7r; ; ; # ⴞ𐹨.︒ݽⴏ
+xn--2nd0990k.xn--eqb228b583r; Ⴞ𐹨.︒ݽႯ; [B1, B5, B6, V6]; xn--2nd0990k.xn--eqb228b583r; ; ; # Ⴞ𐹨.︒ݽႯ
+xn--2nd0990k.xn--eqb228bgzmvp0t; Ⴞ𐹨.︒ݽ‍Ⴏ; [B1, B5, B6, C2, V6]; xn--2nd0990k.xn--eqb228bgzmvp0t; ; ; # Ⴞ𐹨.︒ݽႯ
+‌Ⴆ𝟹。-⃒-ߑ; ‌Ⴆ3.-⃒-ߑ; [B1, C1, P1, V3, V6]; xn--3-i0g939i.xn-----vue617w; ; xn--3-i0g.xn-----vue617w; [B1, P1, V3, V6] # Ⴆ3.-⃒-ߑ
+‌Ⴆ3。-⃒-ߑ; ‌Ⴆ3.-⃒-ߑ; [B1, C1, P1, V3, V6]; xn--3-i0g939i.xn-----vue617w; ; xn--3-i0g.xn-----vue617w; [B1, P1, V3, V6] # Ⴆ3.-⃒-ߑ
+‌ⴆ3。-⃒-ߑ; ‌ⴆ3.-⃒-ߑ; [B1, C1, V3]; xn--3-rgnv99c.xn-----vue617w; ; xn--3-lvs.xn-----vue617w; [B1, V3] # ⴆ3.-⃒-ߑ
+xn--3-lvs.xn-----vue617w; ⴆ3.-⃒-ߑ; [B1, V3]; xn--3-lvs.xn-----vue617w; ; ; # ⴆ3.-⃒-ߑ
+xn--3-rgnv99c.xn-----vue617w; ‌ⴆ3.-⃒-ߑ; [B1, C1, V3]; xn--3-rgnv99c.xn-----vue617w; ; ; # ⴆ3.-⃒-ߑ
+xn--3-i0g.xn-----vue617w; Ⴆ3.-⃒-ߑ; [B1, V3, V6]; xn--3-i0g.xn-----vue617w; ; ; # Ⴆ3.-⃒-ߑ
+xn--3-i0g939i.xn-----vue617w; ‌Ⴆ3.-⃒-ߑ; [B1, C1, V3, V6]; xn--3-i0g939i.xn-----vue617w; ; ; # Ⴆ3.-⃒-ߑ
+‌ⴆ𝟹。-⃒-ߑ; ‌ⴆ3.-⃒-ߑ; [B1, C1, V3]; xn--3-rgnv99c.xn-----vue617w; ; xn--3-lvs.xn-----vue617w; [B1, V3] # ⴆ3.-⃒-ߑ
+箃Ⴡ-󠁝。≠-🤖; 箃Ⴡ-󠁝.≠-🤖; [P1, V6]; xn----11g3013fy8x5m.xn----tfot873s; ; ; # 箃Ⴡ-.≠-🤖
+箃Ⴡ-󠁝。≠-🤖; 箃Ⴡ-󠁝.≠-🤖; [P1, V6]; xn----11g3013fy8x5m.xn----tfot873s; ; ; # 箃Ⴡ-.≠-🤖
+箃Ⴡ-󠁝。≠-🤖; 箃Ⴡ-󠁝.≠-🤖; [P1, V6]; xn----11g3013fy8x5m.xn----tfot873s; ; ; # 箃Ⴡ-.≠-🤖
+箃Ⴡ-󠁝。≠-🤖; 箃Ⴡ-󠁝.≠-🤖; [P1, V6]; xn----11g3013fy8x5m.xn----tfot873s; ; ; # 箃Ⴡ-.≠-🤖
+箃ⴡ-󠁝。≠-🤖; 箃ⴡ-󠁝.≠-🤖; [P1, V6]; xn----4wsr321ay823p.xn----tfot873s; ; ; # 箃ⴡ-.≠-🤖
+箃ⴡ-󠁝。≠-🤖; 箃ⴡ-󠁝.≠-🤖; [P1, V6]; xn----4wsr321ay823p.xn----tfot873s; ; ; # 箃ⴡ-.≠-🤖
+xn----4wsr321ay823p.xn----tfot873s; 箃ⴡ-󠁝.≠-🤖; [V6]; xn----4wsr321ay823p.xn----tfot873s; ; ; # 箃ⴡ-.≠-🤖
+xn----11g3013fy8x5m.xn----tfot873s; 箃Ⴡ-󠁝.≠-🤖; [V6]; xn----11g3013fy8x5m.xn----tfot873s; ; ; # 箃Ⴡ-.≠-🤖
+箃ⴡ-󠁝。≠-🤖; 箃ⴡ-󠁝.≠-🤖; [P1, V6]; xn----4wsr321ay823p.xn----tfot873s; ; ; # 箃ⴡ-.≠-🤖
+箃ⴡ-󠁝。≠-🤖; 箃ⴡ-󠁝.≠-🤖; [P1, V6]; xn----4wsr321ay823p.xn----tfot873s; ; ; # 箃ⴡ-.≠-🤖
+ߥ.ڵ; ; ; xn--dtb.xn--okb; ; ; # ߥ.ڵ
+xn--dtb.xn--okb; ߥ.ڵ; ; xn--dtb.xn--okb; ; ; # ߥ.ڵ
+‌‍.𞤿; ; [B1, C1, C2]; xn--0ugc.xn--3e6h; ; .xn--3e6h; [A4_2] # .𞤿
+‌‍.𞤝; ‌‍.𞤿; [B1, C1, C2]; xn--0ugc.xn--3e6h; ; .xn--3e6h; [A4_2] # .𞤿
+.xn--3e6h; .𞤿; [X4_2]; .xn--3e6h; [A4_2]; ; # .𞤿
+xn--0ugc.xn--3e6h; ‌‍.𞤿; [B1, C1, C2]; xn--0ugc.xn--3e6h; ; ; # .𞤿
+xn--3e6h; 𞤿; ; xn--3e6h; ; ; # 𞤿
+𞤿; ; ; xn--3e6h; ; ; # 𞤿
+𞤝; 𞤿; ; xn--3e6h; ; ; # 𞤿
+🜑𐹧ع.ς𑍍蜹; ; [B1]; xn--4gb3736kk4zf.xn--3xa4248dy27d; ; xn--4gb3736kk4zf.xn--4xa2248dy27d; # 🜑𐹧ع.ς𑍍蜹
+🜑𐹧ع.Σ𑍍蜹; 🜑𐹧ع.σ𑍍蜹; [B1]; xn--4gb3736kk4zf.xn--4xa2248dy27d; ; ; # 🜑𐹧ع.σ𑍍蜹
+🜑𐹧ع.σ𑍍蜹; ; [B1]; xn--4gb3736kk4zf.xn--4xa2248dy27d; ; ; # 🜑𐹧ع.σ𑍍蜹
+xn--4gb3736kk4zf.xn--4xa2248dy27d; 🜑𐹧ع.σ𑍍蜹; [B1]; xn--4gb3736kk4zf.xn--4xa2248dy27d; ; ; # 🜑𐹧ع.σ𑍍蜹
+xn--4gb3736kk4zf.xn--3xa4248dy27d; 🜑𐹧ع.ς𑍍蜹; [B1]; xn--4gb3736kk4zf.xn--3xa4248dy27d; ; ; # 🜑𐹧ع.ς𑍍蜹
+򫠐ス􆟤٩.󚃟; 򫠐ス􆟤٩.󚃟; [B5, B6, P1, V6]; xn--iib777sp230oo708a.xn--7824e; ; ; # ス٩.
+򫠐ス􆟤٩.󚃟; ; [B5, B6, P1, V6]; xn--iib777sp230oo708a.xn--7824e; ; ; # ス٩.
+xn--iib777sp230oo708a.xn--7824e; 򫠐ス􆟤٩.󚃟; [B5, B6, V6]; xn--iib777sp230oo708a.xn--7824e; ; ; # ス٩.
+𝪣򕡝.֚?ۂ; 𝪣򕡝.֚?ۂ; [B1, P1, V5, V6]; xn--8c3hu7971a.xn--?-wec30g; ; ; # 𝪣.֚?ۂ
+𝪣򕡝.֚?ۂ; 𝪣򕡝.֚?ۂ; [B1, P1, V5, V6]; xn--8c3hu7971a.xn--?-wec30g; ; ; # 𝪣.֚?ۂ
+𝪣򕡝.֚?ۂ; ; [B1, P1, V5, V6]; xn--8c3hu7971a.xn--?-wec30g; ; ; # 𝪣.֚?ۂ
+𝪣򕡝.֚?ۂ; 𝪣򕡝.֚?ۂ; [B1, P1, V5, V6]; xn--8c3hu7971a.xn--?-wec30g; ; ; # 𝪣.֚?ۂ
+xn--8c3hu7971a.xn--?-wec30g; 𝪣򕡝.֚?ۂ; [B1, P1, V5, V6]; xn--8c3hu7971a.xn--?-wec30g; ; ; # 𝪣.֚?ۂ
+xn--8c3hu7971a.֚?ۂ; 𝪣򕡝.֚?ۂ; [B1, P1, V5, V6]; xn--8c3hu7971a.xn--?-wec30g; ; ; # 𝪣.֚?ۂ
+xn--8c3hu7971a.֚?ۂ; 𝪣򕡝.֚?ۂ; [B1, P1, V5, V6]; xn--8c3hu7971a.xn--?-wec30g; ; ; # 𝪣.֚?ۂ
+XN--8C3HU7971A.֚?ۂ; 𝪣򕡝.֚?ۂ; [B1, P1, V5, V6]; xn--8c3hu7971a.xn--?-wec30g; ; ; # 𝪣.֚?ۂ
+XN--8C3HU7971A.֚?ۂ; 𝪣򕡝.֚?ۂ; [B1, P1, V5, V6]; xn--8c3hu7971a.xn--?-wec30g; ; ; # 𝪣.֚?ۂ
+Xn--8c3hu7971a.֚?ۂ; 𝪣򕡝.֚?ۂ; [B1, P1, V5, V6]; xn--8c3hu7971a.xn--?-wec30g; ; ; # 𝪣.֚?ۂ
+Xn--8c3hu7971a.֚?ۂ; 𝪣򕡝.֚?ۂ; [B1, P1, V5, V6]; xn--8c3hu7971a.xn--?-wec30g; ; ; # 𝪣.֚?ۂ
+٠򪓵‌。ݗ; ٠򪓵‌.ݗ; [B1, C1, P1, V6]; xn--8hb852ke991q.xn--bpb; ; xn--8hb82030l.xn--bpb; [B1, P1, V6] # ٠.ݗ
+xn--8hb82030l.xn--bpb; ٠򪓵.ݗ; [B1, V6]; xn--8hb82030l.xn--bpb; ; ; # ٠.ݗ
+xn--8hb852ke991q.xn--bpb; ٠򪓵‌.ݗ; [B1, C1, V6]; xn--8hb852ke991q.xn--bpb; ; ; # ٠.ݗ
+်‍‌。-‌; ်‍‌.-‌; [C1, V3, V5]; xn--bkd412fca.xn----sgn; ; xn--bkd.-; [V3, V5] # ်.-
+xn--bkd.-; ်.-; [V3, V5]; xn--bkd.-; ; ; # ်.-
+xn--bkd412fca.xn----sgn; ်‍‌.-‌; [C1, V3, V5]; xn--bkd412fca.xn----sgn; ; ; # ်.-
+︒。᭄ᡉ; ︒.᭄ᡉ; [P1, V5, V6]; xn--y86c.xn--87e93m; ; ; # ︒.᭄ᡉ
+。。᭄ᡉ; ..᭄ᡉ; [V5, X4_2]; ..xn--87e93m; [V5, A4_2]; ; # ..᭄ᡉ
+..xn--87e93m; ..᭄ᡉ; [V5, X4_2]; ..xn--87e93m; [V5, A4_2]; ; # ..᭄ᡉ
+xn--y86c.xn--87e93m; ︒.᭄ᡉ; [V5, V6]; xn--y86c.xn--87e93m; ; ; # ︒.᭄ᡉ
+ݘß。ጫᢊݨ𝟐; ݘß.ጫᢊݨ2; [B2, B3, B5]; xn--zca724a.xn--2-b5c641gfmf; ; xn--ss-gke.xn--2-b5c641gfmf; # ݘß.ጫᢊݨ2
+ݘß。ጫᢊݨ2; ݘß.ጫᢊݨ2; [B2, B3, B5]; xn--zca724a.xn--2-b5c641gfmf; ; xn--ss-gke.xn--2-b5c641gfmf; # ݘß.ጫᢊݨ2
+ݘSS。ጫᢊݨ2; ݘss.ጫᢊݨ2; [B2, B3, B5]; xn--ss-gke.xn--2-b5c641gfmf; ; ; # ݘss.ጫᢊݨ2
+ݘss。ጫᢊݨ2; ݘss.ጫᢊݨ2; [B2, B3, B5]; xn--ss-gke.xn--2-b5c641gfmf; ; ; # ݘss.ጫᢊݨ2
+xn--ss-gke.xn--2-b5c641gfmf; ݘss.ጫᢊݨ2; [B2, B3, B5]; xn--ss-gke.xn--2-b5c641gfmf; ; ; # ݘss.ጫᢊݨ2
+xn--zca724a.xn--2-b5c641gfmf; ݘß.ጫᢊݨ2; [B2, B3, B5]; xn--zca724a.xn--2-b5c641gfmf; ; ; # ݘß.ጫᢊݨ2
+ݘSS。ጫᢊݨ𝟐; ݘss.ጫᢊݨ2; [B2, B3, B5]; xn--ss-gke.xn--2-b5c641gfmf; ; ; # ݘss.ጫᢊݨ2
+ݘss。ጫᢊݨ𝟐; ݘss.ጫᢊݨ2; [B2, B3, B5]; xn--ss-gke.xn--2-b5c641gfmf; ; ; # ݘss.ጫᢊݨ2
+ݘSs。ጫᢊݨ2; ݘss.ጫᢊݨ2; [B2, B3, B5]; xn--ss-gke.xn--2-b5c641gfmf; ; ; # ݘss.ጫᢊݨ2
+ݘSs。ጫᢊݨ𝟐; ݘss.ጫᢊݨ2; [B2, B3, B5]; xn--ss-gke.xn--2-b5c641gfmf; ; ; # ݘss.ጫᢊݨ2
+߃𞶇ᚲ.ं͓𝟚্; ߃𞶇ᚲ.ं͓2্; [B1, B2, B3, P1, V5, V6]; xn--esb067enh07a.xn--2-lgb874bjxa; ; ; # ߃ᚲ.ं͓2্
+߃𞶇ᚲ.ं͓2্; ; [B1, B2, B3, P1, V5, V6]; xn--esb067enh07a.xn--2-lgb874bjxa; ; ; # ߃ᚲ.ं͓2্
+xn--esb067enh07a.xn--2-lgb874bjxa; ߃𞶇ᚲ.ं͓2্; [B1, B2, B3, V5, V6]; xn--esb067enh07a.xn--2-lgb874bjxa; ; ; # ߃ᚲ.ं͓2্
+-᮫︒‍.񒶈񥹓; ; [C2, P1, V3, V6]; xn----qmlv7tw180a.xn--x50zy803a; ; xn----qml1407i.xn--x50zy803a; [P1, V3, V6] # -᮫︒.
+-᮫。‍.񒶈񥹓; -᮫.‍.񒶈񥹓; [C2, P1, V3, V6]; xn----qml.xn--1ug.xn--x50zy803a; ; xn----qml..xn--x50zy803a; [P1, V3, V6, A4_2] # -᮫..
+xn----qml..xn--x50zy803a; -᮫..񒶈񥹓; [V3, V6, X4_2]; xn----qml..xn--x50zy803a; [V3, V6, A4_2]; ; # -᮫..
+xn----qml.xn--1ug.xn--x50zy803a; -᮫.‍.񒶈񥹓; [C2, V3, V6]; xn----qml.xn--1ug.xn--x50zy803a; ; ; # -᮫..
+xn----qml1407i.xn--x50zy803a; -᮫︒.񒶈񥹓; [V3, V6]; xn----qml1407i.xn--x50zy803a; ; ; # -᮫︒.
+xn----qmlv7tw180a.xn--x50zy803a; -᮫︒‍.񒶈񥹓; [C2, V3, V6]; xn----qmlv7tw180a.xn--x50zy803a; ; ; # -᮫︒.
+󠦮.≯𞀆; ; [P1, V6]; xn--t546e.xn--hdh5166o; ; ; # .≯𞀆
+󠦮.≯𞀆; 󠦮.≯𞀆; [P1, V6]; xn--t546e.xn--hdh5166o; ; ; # .≯𞀆
+xn--t546e.xn--hdh5166o; 󠦮.≯𞀆; [V6]; xn--t546e.xn--hdh5166o; ; ; # .≯𞀆
+-𑄳󠊗𐹩。𞮱; -𑄳󠊗𐹩.𞮱; [B1, P1, V3, V6]; xn----p26i72em2894c.xn--zw6h; ; ; # -𑄳𐹩.
+xn----p26i72em2894c.xn--zw6h; -𑄳󠊗𐹩.𞮱; [B1, V3, V6]; xn----p26i72em2894c.xn--zw6h; ; ; # -𑄳𐹩.
+ڹ.ᡳᅟ; ڹ.ᡳᅟ; [P1, V6]; xn--skb.xn--osd737a; ; ; # ڹ.ᡳ
+ڹ.ᡳᅟ; ; [P1, V6]; xn--skb.xn--osd737a; ; ; # ڹ.ᡳ
+xn--skb.xn--osd737a; ڹ.ᡳᅟ; [V6]; xn--skb.xn--osd737a; ; ; # ڹ.ᡳ
+㨛𘱎.︒𝟕ഁ; 㨛𘱎.︒7ഁ; [P1, V6]; xn--mbm8237g.xn--7-7hf1526p; ; ; # 㨛𘱎.︒7ഁ
+㨛𘱎.。7ഁ; 㨛𘱎..7ഁ; [X4_2]; xn--mbm8237g..xn--7-7hf; [A4_2]; ; # 㨛𘱎..7ഁ
+xn--mbm8237g..xn--7-7hf; 㨛𘱎..7ഁ; [X4_2]; xn--mbm8237g..xn--7-7hf; [A4_2]; ; # 㨛𘱎..7ഁ
+xn--mbm8237g.xn--7-7hf1526p; 㨛𘱎.︒7ഁ; [V6]; xn--mbm8237g.xn--7-7hf1526p; ; ; # 㨛𘱎.︒7ഁ
+۝𻱧-。𞷁⁤𞤣≮; ۝𻱧-.𞷁𞤣≮; [B1, B3, P1, V3, V6]; xn----dxc06304e.xn--gdh5020pk5c; ; ; # -.𞤣≮
+۝𻱧-。𞷁⁤𞤣≮; ۝𻱧-.𞷁𞤣≮; [B1, B3, P1, V3, V6]; xn----dxc06304e.xn--gdh5020pk5c; ; ; # -.𞤣≮
+۝𻱧-。𞷁⁤𞤣≮; ۝𻱧-.𞷁𞤣≮; [B1, B3, P1, V3, V6]; xn----dxc06304e.xn--gdh5020pk5c; ; ; # -.𞤣≮
+۝𻱧-。𞷁⁤𞤣≮; ۝𻱧-.𞷁𞤣≮; [B1, B3, P1, V3, V6]; xn----dxc06304e.xn--gdh5020pk5c; ; ; # -.𞤣≮
+۝𻱧-。𞷁⁤𞤁≮; ۝𻱧-.𞷁𞤣≮; [B1, B3, P1, V3, V6]; xn----dxc06304e.xn--gdh5020pk5c; ; ; # -.𞤣≮
+۝𻱧-。𞷁⁤𞤁≮; ۝𻱧-.𞷁𞤣≮; [B1, B3, P1, V3, V6]; xn----dxc06304e.xn--gdh5020pk5c; ; ; # -.𞤣≮
+xn----dxc06304e.xn--gdh5020pk5c; ۝𻱧-.𞷁𞤣≮; [B1, B3, V3, V6]; xn----dxc06304e.xn--gdh5020pk5c; ; ; # -.𞤣≮
+۝𻱧-。𞷁⁤𞤁≮; ۝𻱧-.𞷁𞤣≮; [B1, B3, P1, V3, V6]; xn----dxc06304e.xn--gdh5020pk5c; ; ; # -.𞤣≮
+۝𻱧-。𞷁⁤𞤁≮; ۝𻱧-.𞷁𞤣≮; [B1, B3, P1, V3, V6]; xn----dxc06304e.xn--gdh5020pk5c; ; ; # -.𞤣≮
+ß‌꫶ᢥ.⊶ჁႶ; ß‌꫶ᢥ.⊶ჁႶ; [C1, P1, V6]; xn--zca682johfi89m.xn--undv409k; ; xn--ss-4epx629f.xn--undv409k; [P1, V6] # ß꫶ᢥ.⊶ჁႶ
+ß‌꫶ᢥ.⊶ჁႶ; ; [C1, P1, V6]; xn--zca682johfi89m.xn--undv409k; ; xn--ss-4epx629f.xn--undv409k; [P1, V6] # ß꫶ᢥ.⊶ჁႶ
+ß‌꫶ᢥ.⊶ⴡⴖ; ; [C1]; xn--zca682johfi89m.xn--ifh802b6a; ; xn--ss-4epx629f.xn--ifh802b6a; [] # ß꫶ᢥ.⊶ⴡⴖ
+SS‌꫶ᢥ.⊶ჁႶ; ss‌꫶ᢥ.⊶ჁႶ; [C1, P1, V6]; xn--ss-4ep585bkm5p.xn--undv409k; ; xn--ss-4epx629f.xn--undv409k; [P1, V6] # ss꫶ᢥ.⊶ჁႶ
+ss‌꫶ᢥ.⊶ⴡⴖ; ; [C1]; xn--ss-4ep585bkm5p.xn--ifh802b6a; ; xn--ss-4epx629f.xn--ifh802b6a; [] # ss꫶ᢥ.⊶ⴡⴖ
+Ss‌꫶ᢥ.⊶Ⴡⴖ; ss‌꫶ᢥ.⊶Ⴡⴖ; [C1, P1, V6]; xn--ss-4ep585bkm5p.xn--5nd703gyrh; ; xn--ss-4epx629f.xn--5nd703gyrh; [P1, V6] # ss꫶ᢥ.⊶Ⴡⴖ
+xn--ss-4epx629f.xn--5nd703gyrh; ss꫶ᢥ.⊶Ⴡⴖ; [V6]; xn--ss-4epx629f.xn--5nd703gyrh; ; ; # ss꫶ᢥ.⊶Ⴡⴖ
+xn--ss-4ep585bkm5p.xn--5nd703gyrh; ss‌꫶ᢥ.⊶Ⴡⴖ; [C1, V6]; xn--ss-4ep585bkm5p.xn--5nd703gyrh; ; ; # ss꫶ᢥ.⊶Ⴡⴖ
+xn--ss-4epx629f.xn--ifh802b6a; ss꫶ᢥ.⊶ⴡⴖ; ; xn--ss-4epx629f.xn--ifh802b6a; ; ; # ss꫶ᢥ.⊶ⴡⴖ
+ss꫶ᢥ.⊶ⴡⴖ; ; ; xn--ss-4epx629f.xn--ifh802b6a; ; ; # ss꫶ᢥ.⊶ⴡⴖ
+SS꫶ᢥ.⊶ჁႶ; ss꫶ᢥ.⊶ჁႶ; [P1, V6]; xn--ss-4epx629f.xn--undv409k; ; ; # ss꫶ᢥ.⊶ჁႶ
+Ss꫶ᢥ.⊶Ⴡⴖ; ss꫶ᢥ.⊶Ⴡⴖ; [P1, V6]; xn--ss-4epx629f.xn--5nd703gyrh; ; ; # ss꫶ᢥ.⊶Ⴡⴖ
+xn--ss-4epx629f.xn--undv409k; ss꫶ᢥ.⊶ჁႶ; [V6]; xn--ss-4epx629f.xn--undv409k; ; ; # ss꫶ᢥ.⊶ჁႶ
+xn--ss-4ep585bkm5p.xn--ifh802b6a; ss‌꫶ᢥ.⊶ⴡⴖ; [C1]; xn--ss-4ep585bkm5p.xn--ifh802b6a; ; ; # ss꫶ᢥ.⊶ⴡⴖ
+xn--ss-4ep585bkm5p.xn--undv409k; ss‌꫶ᢥ.⊶ჁႶ; [C1, V6]; xn--ss-4ep585bkm5p.xn--undv409k; ; ; # ss꫶ᢥ.⊶ჁႶ
+xn--zca682johfi89m.xn--ifh802b6a; ß‌꫶ᢥ.⊶ⴡⴖ; [C1]; xn--zca682johfi89m.xn--ifh802b6a; ; ; # ß꫶ᢥ.⊶ⴡⴖ
+xn--zca682johfi89m.xn--undv409k; ß‌꫶ᢥ.⊶ჁႶ; [C1, V6]; xn--zca682johfi89m.xn--undv409k; ; ; # ß꫶ᢥ.⊶ჁႶ
+ß‌꫶ᢥ.⊶ⴡⴖ; ß‌꫶ᢥ.⊶ⴡⴖ; [C1]; xn--zca682johfi89m.xn--ifh802b6a; ; xn--ss-4epx629f.xn--ifh802b6a; [] # ß꫶ᢥ.⊶ⴡⴖ
+SS‌꫶ᢥ.⊶ჁႶ; ss‌꫶ᢥ.⊶ჁႶ; [C1, P1, V6]; xn--ss-4ep585bkm5p.xn--undv409k; ; xn--ss-4epx629f.xn--undv409k; [P1, V6] # ss꫶ᢥ.⊶ჁႶ
+ss‌꫶ᢥ.⊶ⴡⴖ; ss‌꫶ᢥ.⊶ⴡⴖ; [C1]; xn--ss-4ep585bkm5p.xn--ifh802b6a; ; xn--ss-4epx629f.xn--ifh802b6a; [] # ss꫶ᢥ.⊶ⴡⴖ
+Ss‌꫶ᢥ.⊶Ⴡⴖ; ss‌꫶ᢥ.⊶Ⴡⴖ; [C1, P1, V6]; xn--ss-4ep585bkm5p.xn--5nd703gyrh; ; xn--ss-4epx629f.xn--5nd703gyrh; [P1, V6] # ss꫶ᢥ.⊶Ⴡⴖ
+‍。ς󠁉; ‍.ς󠁉; [C2, P1, V6]; xn--1ug.xn--3xa44344p; ; .xn--4xa24344p; [P1, V6, A4_2] # .ς
+‍。Σ󠁉; ‍.σ󠁉; [C2, P1, V6]; xn--1ug.xn--4xa24344p; ; .xn--4xa24344p; [P1, V6, A4_2] # .σ
+‍。σ󠁉; ‍.σ󠁉; [C2, P1, V6]; xn--1ug.xn--4xa24344p; ; .xn--4xa24344p; [P1, V6, A4_2] # .σ
+.xn--4xa24344p; .σ󠁉; [V6, X4_2]; .xn--4xa24344p; [V6, A4_2]; ; # .σ
+xn--1ug.xn--4xa24344p; ‍.σ󠁉; [C2, V6]; xn--1ug.xn--4xa24344p; ; ; # .σ
+xn--1ug.xn--3xa44344p; ‍.ς󠁉; [C2, V6]; xn--1ug.xn--3xa44344p; ; ; # .ς
+𞵑ß.ݑ‍𞤛-; 𞵑ß.ݑ‍𞤽-; [B2, B3, C2, P1, V3, V6]; xn--zca5423w.xn----z3c011q9513b; ; xn--ss-2722a.xn----z3c03218a; [B2, B3, P1, V3, V6] # ß.ݑ𞤽-
+𞵑ß.ݑ‍𞤽-; ; [B2, B3, C2, P1, V3, V6]; xn--zca5423w.xn----z3c011q9513b; ; xn--ss-2722a.xn----z3c03218a; [B2, B3, P1, V3, V6] # ß.ݑ𞤽-
+𞵑SS.ݑ‍𞤛-; 𞵑ss.ݑ‍𞤽-; [B2, B3, C2, P1, V3, V6]; xn--ss-2722a.xn----z3c011q9513b; ; xn--ss-2722a.xn----z3c03218a; [B2, B3, P1, V3, V6] # ss.ݑ𞤽-
+𞵑ss.ݑ‍𞤽-; ; [B2, B3, C2, P1, V3, V6]; xn--ss-2722a.xn----z3c011q9513b; ; xn--ss-2722a.xn----z3c03218a; [B2, B3, P1, V3, V6] # ss.ݑ𞤽-
+𞵑Ss.ݑ‍𞤽-; 𞵑ss.ݑ‍𞤽-; [B2, B3, C2, P1, V3, V6]; xn--ss-2722a.xn----z3c011q9513b; ; xn--ss-2722a.xn----z3c03218a; [B2, B3, P1, V3, V6] # ss.ݑ𞤽-
+xn--ss-2722a.xn----z3c03218a; 𞵑ss.ݑ𞤽-; [B2, B3, V3, V6]; xn--ss-2722a.xn----z3c03218a; ; ; # ss.ݑ𞤽-
+xn--ss-2722a.xn----z3c011q9513b; 𞵑ss.ݑ‍𞤽-; [B2, B3, C2, V3, V6]; xn--ss-2722a.xn----z3c011q9513b; ; ; # ss.ݑ𞤽-
+xn--zca5423w.xn----z3c011q9513b; 𞵑ß.ݑ‍𞤽-; [B2, B3, C2, V3, V6]; xn--zca5423w.xn----z3c011q9513b; ; ; # ß.ݑ𞤽-
+𞵑ss.ݑ‍𞤛-; 𞵑ss.ݑ‍𞤽-; [B2, B3, C2, P1, V3, V6]; xn--ss-2722a.xn----z3c011q9513b; ; xn--ss-2722a.xn----z3c03218a; [B2, B3, P1, V3, V6] # ss.ݑ𞤽-
+𞵑Ss.ݑ‍𞤛-; 𞵑ss.ݑ‍𞤽-; [B2, B3, C2, P1, V3, V6]; xn--ss-2722a.xn----z3c011q9513b; ; xn--ss-2722a.xn----z3c03218a; [B2, B3, P1, V3, V6] # ss.ݑ𞤽-
+𑘽‍𞤧.𐹧󡦪-; 𑘽‍𞤧.𐹧󡦪-; [B1, C2, P1, V3, V5, V6]; xn--1ugz808gdimf.xn----k26iq1483f; ; xn--qb2ds317a.xn----k26iq1483f; [B1, P1, V3, V5, V6] # 𑘽𞤧.𐹧-
+𑘽‍𞤧.𐹧󡦪-; ; [B1, C2, P1, V3, V5, V6]; xn--1ugz808gdimf.xn----k26iq1483f; ; xn--qb2ds317a.xn----k26iq1483f; [B1, P1, V3, V5, V6] # 𑘽𞤧.𐹧-
+𑘽‍𞤅.𐹧󡦪-; 𑘽‍𞤧.𐹧󡦪-; [B1, C2, P1, V3, V5, V6]; xn--1ugz808gdimf.xn----k26iq1483f; ; xn--qb2ds317a.xn----k26iq1483f; [B1, P1, V3, V5, V6] # 𑘽𞤧.𐹧-
+xn--qb2ds317a.xn----k26iq1483f; 𑘽𞤧.𐹧󡦪-; [B1, V3, V5, V6]; xn--qb2ds317a.xn----k26iq1483f; ; ; # 𑘽𞤧.𐹧-
+xn--1ugz808gdimf.xn----k26iq1483f; 𑘽‍𞤧.𐹧󡦪-; [B1, C2, V3, V5, V6]; xn--1ugz808gdimf.xn----k26iq1483f; ; ; # 𑘽𞤧.𐹧-
+𑘽‍𞤅.𐹧󡦪-; 𑘽‍𞤧.𐹧󡦪-; [B1, C2, P1, V3, V5, V6]; xn--1ugz808gdimf.xn----k26iq1483f; ; xn--qb2ds317a.xn----k26iq1483f; [B1, P1, V3, V5, V6] # 𑘽𞤧.𐹧-
+⒒򨘙򳳠𑓀.-󞡊; ; [P1, V3, V6]; xn--3shy698frsu9dt1me.xn----x310m; ; ; # ⒒𑓀.-
+11.򨘙򳳠𑓀.-󞡊; ; [P1, V3, V6]; 11.xn--uz1d59632bxujd.xn----x310m; ; ; # 11.𑓀.-
+11.xn--uz1d59632bxujd.xn----x310m; 11.򨘙򳳠𑓀.-󞡊; [V3, V6]; 11.xn--uz1d59632bxujd.xn----x310m; ; ; # 11.𑓀.-
+xn--3shy698frsu9dt1me.xn----x310m; ⒒򨘙򳳠𑓀.-󞡊; [V3, V6]; xn--3shy698frsu9dt1me.xn----x310m; ; ; # ⒒𑓀.-
+-。‍; -.‍; [C2, V3]; -.xn--1ug; ; -.; [V3] # -.
+-。‍; -.‍; [C2, V3]; -.xn--1ug; ; -.; [V3] # -.
+-.; ; [V3]; ; ; ; # -.
+-.xn--1ug; -.‍; [C2, V3]; -.xn--1ug; ; ; # -.
+≮ᡬ.ς¹-?; ≮ᡬ.ς1-?; [P1, V6]; xn--88e732c.xn--1-?-lzc; ; xn--88e732c.xn--1-?-pzc; # ≮ᡬ.ς1-?
+≮ᡬ.ς¹-?; ≮ᡬ.ς1-?; [P1, V6]; xn--88e732c.xn--1-?-lzc; ; xn--88e732c.xn--1-?-pzc; # ≮ᡬ.ς1-?
+≮ᡬ.ς1-?; ; [P1, V6]; xn--88e732c.xn--1-?-lzc; ; xn--88e732c.xn--1-?-pzc; # ≮ᡬ.ς1-?
+≮ᡬ.ς1-?; ≮ᡬ.ς1-?; [P1, V6]; xn--88e732c.xn--1-?-lzc; ; xn--88e732c.xn--1-?-pzc; # ≮ᡬ.ς1-?
+≮ᡬ.Σ1-?; ≮ᡬ.σ1-?; [P1, V6]; xn--88e732c.xn--1-?-pzc; ; ; # ≮ᡬ.σ1-?
+≮ᡬ.Σ1-?; ≮ᡬ.σ1-?; [P1, V6]; xn--88e732c.xn--1-?-pzc; ; ; # ≮ᡬ.σ1-?
+≮ᡬ.σ1-?; ; [P1, V6]; xn--88e732c.xn--1-?-pzc; ; ; # ≮ᡬ.σ1-?
+≮ᡬ.σ1-?; ≮ᡬ.σ1-?; [P1, V6]; xn--88e732c.xn--1-?-pzc; ; ; # ≮ᡬ.σ1-?
+xn--88e732c.xn--1-?-pzc; ≮ᡬ.σ1-?; [P1, V6]; xn--88e732c.xn--1-?-pzc; ; ; # ≮ᡬ.σ1-?
+xn--88e732c.xn--1-?-lzc; ≮ᡬ.ς1-?; [P1, V6]; xn--88e732c.xn--1-?-lzc; ; ; # ≮ᡬ.ς1-?
+≮ᡬ.Σ¹-?; ≮ᡬ.σ1-?; [P1, V6]; xn--88e732c.xn--1-?-pzc; ; ; # ≮ᡬ.σ1-?
+≮ᡬ.Σ¹-?; ≮ᡬ.σ1-?; [P1, V6]; xn--88e732c.xn--1-?-pzc; ; ; # ≮ᡬ.σ1-?
+≮ᡬ.σ¹-?; ≮ᡬ.σ1-?; [P1, V6]; xn--88e732c.xn--1-?-pzc; ; ; # ≮ᡬ.σ1-?
+≮ᡬ.σ¹-?; ≮ᡬ.σ1-?; [P1, V6]; xn--88e732c.xn--1-?-pzc; ; ; # ≮ᡬ.σ1-?
+xn--88e732c.σ1-?; ≮ᡬ.σ1-?; [P1, V6]; xn--88e732c.xn--1-?-pzc; ; ; # ≮ᡬ.σ1-?
+XN--88E732C.Σ1-?; ≮ᡬ.σ1-?; [P1, V6]; xn--88e732c.xn--1-?-pzc; ; ; # ≮ᡬ.σ1-?
+xn--88e732c.ς1-?; ≮ᡬ.ς1-?; [P1, V6]; xn--88e732c.xn--1-?-lzc; ; xn--88e732c.xn--1-?-pzc; # ≮ᡬ.ς1-?
+Xn--88e732c.ς1-?; ≮ᡬ.ς1-?; [P1, V6]; xn--88e732c.xn--1-?-lzc; ; xn--88e732c.xn--1-?-pzc; # ≮ᡬ.ς1-?
+Xn--88e732c.σ1-?; ≮ᡬ.σ1-?; [P1, V6]; xn--88e732c.xn--1-?-pzc; ; ; # ≮ᡬ.σ1-?
+ቬ򔠼񁗶。𐨬𝟠; ቬ򔠼񁗶.𐨬8; [P1, V6]; xn--d0d41273c887z.xn--8-ob5i; ; ; # ቬ.𐨬8
+ቬ򔠼񁗶。𐨬8; ቬ򔠼񁗶.𐨬8; [P1, V6]; xn--d0d41273c887z.xn--8-ob5i; ; ; # ቬ.𐨬8
+xn--d0d41273c887z.xn--8-ob5i; ቬ򔠼񁗶.𐨬8; [V6]; xn--d0d41273c887z.xn--8-ob5i; ; ; # ቬ.𐨬8
+𐱲。蔫ݦ; 𐱲.蔫ݦ; [B5, B6, P1, V6]; xn--389c.xn--qpb7055d; ; ; # .蔫ݦ
+xn--389c.xn--qpb7055d; 𐱲.蔫ݦ; [B5, B6, V6]; xn--389c.xn--qpb7055d; ; ; # .蔫ݦ
+򒲧₃。ꡚ𛇑󠄳ه; 򒲧3.ꡚ𛇑ه; [B5, B6, P1, V6]; xn--3-ep59g.xn--jhb5904fcp0h; ; ; # 3.ꡚ𛇑ه
+򒲧3。ꡚ𛇑󠄳ه; 򒲧3.ꡚ𛇑ه; [B5, B6, P1, V6]; xn--3-ep59g.xn--jhb5904fcp0h; ; ; # 3.ꡚ𛇑ه
+xn--3-ep59g.xn--jhb5904fcp0h; 򒲧3.ꡚ𛇑ه; [B5, B6, V6]; xn--3-ep59g.xn--jhb5904fcp0h; ; ; # 3.ꡚ𛇑ه
+蓸ق≠.ß; ; [B5, B6, P1, V6]; xn--ehb015lnt1e.xn--zca; ; xn--ehb015lnt1e.ss; # 蓸ق≠.ß
+蓸ق≠.ß; 蓸ق≠.ß; [B5, B6, P1, V6]; xn--ehb015lnt1e.xn--zca; ; xn--ehb015lnt1e.ss; # 蓸ق≠.ß
+蓸ق≠.SS; 蓸ق≠.ss; [B5, B6, P1, V6]; xn--ehb015lnt1e.ss; ; ; # 蓸ق≠.ss
+蓸ق≠.SS; 蓸ق≠.ss; [B5, B6, P1, V6]; xn--ehb015lnt1e.ss; ; ; # 蓸ق≠.ss
+蓸ق≠.ss; ; [B5, B6, P1, V6]; xn--ehb015lnt1e.ss; ; ; # 蓸ق≠.ss
+蓸ق≠.ss; 蓸ق≠.ss; [B5, B6, P1, V6]; xn--ehb015lnt1e.ss; ; ; # 蓸ق≠.ss
+蓸ق≠.Ss; 蓸ق≠.ss; [B5, B6, P1, V6]; xn--ehb015lnt1e.ss; ; ; # 蓸ق≠.ss
+蓸ق≠.Ss; 蓸ق≠.ss; [B5, B6, P1, V6]; xn--ehb015lnt1e.ss; ; ; # 蓸ق≠.ss
+xn--ehb015lnt1e.ss; 蓸ق≠.ss; [B5, B6, V6]; xn--ehb015lnt1e.ss; ; ; # 蓸ق≠.ss
+xn--ehb015lnt1e.xn--zca; 蓸ق≠.ß; [B5, B6, V6]; xn--ehb015lnt1e.xn--zca; ; ; # 蓸ق≠.ß
+ࡎٺී⒊.𐹹𞱩󠃪‌; ; [B1, C1, P1, V6]; xn--zib94gfziuq1a.xn--0ug3205g7eyf3c96h; ; xn--zib94gfziuq1a.xn--xo0dw109an237f; [B1, P1, V6] # ࡎٺී⒊.𐹹
+ࡎٺී3..𐹹𞱩󠃪‌; ; [B1, C1, P1, V6, X4_2]; xn--3-prc71ls9j..xn--0ug3205g7eyf3c96h; [B1, C1, P1, V6, A4_2]; xn--3-prc71ls9j..xn--xo0dw109an237f; [B1, P1, V6, A4_2] # ࡎٺී3..𐹹
+xn--3-prc71ls9j..xn--xo0dw109an237f; ࡎٺී3..𐹹𞱩󠃪; [B1, V6, X4_2]; xn--3-prc71ls9j..xn--xo0dw109an237f; [B1, V6, A4_2]; ; # ࡎٺී3..𐹹
+xn--3-prc71ls9j..xn--0ug3205g7eyf3c96h; ࡎٺී3..𐹹𞱩󠃪‌; [B1, C1, V6, X4_2]; xn--3-prc71ls9j..xn--0ug3205g7eyf3c96h; [B1, C1, V6, A4_2]; ; # ࡎٺී3..𐹹
+xn--zib94gfziuq1a.xn--xo0dw109an237f; ࡎٺී⒊.𐹹𞱩󠃪; [B1, V6]; xn--zib94gfziuq1a.xn--xo0dw109an237f; ; ; # ࡎٺී⒊.𐹹
+xn--zib94gfziuq1a.xn--0ug3205g7eyf3c96h; ࡎٺී⒊.𐹹𞱩󠃪‌; [B1, C1, V6]; xn--zib94gfziuq1a.xn--0ug3205g7eyf3c96h; ; ; # ࡎٺී⒊.𐹹
+ς‍-.Ⴣ𦟙; ; [C2, P1, V3, V6]; xn----xmb348s.xn--7nd64871a; ; xn----zmb.xn--7nd64871a; [P1, V3, V6] # ς-.Ⴣ𦟙
+ς‍-.ⴣ𦟙; ; [C2, V3]; xn----xmb348s.xn--rlj2573p; ; xn----zmb.xn--rlj2573p; [V3] # ς-.ⴣ𦟙
+Σ‍-.Ⴣ𦟙; σ‍-.Ⴣ𦟙; [C2, P1, V3, V6]; xn----zmb048s.xn--7nd64871a; ; xn----zmb.xn--7nd64871a; [P1, V3, V6] # σ-.Ⴣ𦟙
+σ‍-.ⴣ𦟙; ; [C2, V3]; xn----zmb048s.xn--rlj2573p; ; xn----zmb.xn--rlj2573p; [V3] # σ-.ⴣ𦟙
+xn----zmb.xn--rlj2573p; σ-.ⴣ𦟙; [V3]; xn----zmb.xn--rlj2573p; ; ; # σ-.ⴣ𦟙
+xn----zmb048s.xn--rlj2573p; σ‍-.ⴣ𦟙; [C2, V3]; xn----zmb048s.xn--rlj2573p; ; ; # σ-.ⴣ𦟙
+xn----zmb.xn--7nd64871a; σ-.Ⴣ𦟙; [V3, V6]; xn----zmb.xn--7nd64871a; ; ; # σ-.Ⴣ𦟙
+xn----zmb048s.xn--7nd64871a; σ‍-.Ⴣ𦟙; [C2, V3, V6]; xn----zmb048s.xn--7nd64871a; ; ; # σ-.Ⴣ𦟙
+xn----xmb348s.xn--rlj2573p; ς‍-.ⴣ𦟙; [C2, V3]; xn----xmb348s.xn--rlj2573p; ; ; # ς-.ⴣ𦟙
+xn----xmb348s.xn--7nd64871a; ς‍-.Ⴣ𦟙; [C2, V3, V6]; xn----xmb348s.xn--7nd64871a; ; ; # ς-.Ⴣ𦟙
+≠。🞳𝟲; ≠.🞳6; [P1, V6]; xn--1ch.xn--6-dl4s; ; ; # ≠.🞳6
+≠。🞳𝟲; ≠.🞳6; [P1, V6]; xn--1ch.xn--6-dl4s; ; ; # ≠.🞳6
+≠。🞳6; ≠.🞳6; [P1, V6]; xn--1ch.xn--6-dl4s; ; ; # ≠.🞳6
+≠。🞳6; ≠.🞳6; [P1, V6]; xn--1ch.xn--6-dl4s; ; ; # ≠.🞳6
+xn--1ch.xn--6-dl4s; ≠.🞳6; [V6]; xn--1ch.xn--6-dl4s; ; ; # ≠.🞳6
+󅬽.蠔; ; [P1, V6]; xn--g747d.xn--xl2a; ; ; # .蠔
+xn--g747d.xn--xl2a; 󅬽.蠔; [V6]; xn--g747d.xn--xl2a; ; ; # .蠔
+ࣦ‍.뼽; ࣦ‍.뼽; [C2, V5]; xn--p0b869i.xn--e43b; ; xn--p0b.xn--e43b; [V5] # ࣦ.뼽
+ࣦ‍.뼽; ࣦ‍.뼽; [C2, V5]; xn--p0b869i.xn--e43b; ; xn--p0b.xn--e43b; [V5] # ࣦ.뼽
+ࣦ‍.뼽; ; [C2, V5]; xn--p0b869i.xn--e43b; ; xn--p0b.xn--e43b; [V5] # ࣦ.뼽
+ࣦ‍.뼽; ࣦ‍.뼽; [C2, V5]; xn--p0b869i.xn--e43b; ; xn--p0b.xn--e43b; [V5] # ࣦ.뼽
+xn--p0b.xn--e43b; ࣦ.뼽; [V5]; xn--p0b.xn--e43b; ; ; # ࣦ.뼽
+xn--p0b869i.xn--e43b; ࣦ‍.뼽; [C2, V5]; xn--p0b869i.xn--e43b; ; ; # ࣦ.뼽
+₇்􃂷ے。👖ٵ-𞪑; 7்􃂷ے.👖اٴ-𞪑; [B1, P1, V6]; xn--7-rwc839aj3073c.xn----ymc5uv818oghka; ; ; # 7்ے.👖اٴ-
+7்􃂷ے。👖اٴ-𞪑; 7்􃂷ے.👖اٴ-𞪑; [B1, P1, V6]; xn--7-rwc839aj3073c.xn----ymc5uv818oghka; ; ; # 7்ے.👖اٴ-
+xn--7-rwc839aj3073c.xn----ymc5uv818oghka; 7்􃂷ے.👖اٴ-𞪑; [B1, V6]; xn--7-rwc839aj3073c.xn----ymc5uv818oghka; ; ; # 7்ے.👖اٴ-
+-。ݻ; -.ݻ; [B1, V3]; -.xn--cqb; ; ; # -.ݻ
+-。ݻ; -.ݻ; [B1, V3]; -.xn--cqb; ; ; # -.ݻ
+-.xn--cqb; -.ݻ; [B1, V3]; -.xn--cqb; ; ; # -.ݻ
+𑇌𵛓。-⒈ꡏܫ; 𑇌𵛓.-⒈ꡏܫ; [B1, P1, V3, V5, V6]; xn--8d1dg030h.xn----u1c466tp10j; ; ; # 𑇌.-⒈ꡏܫ
+𑇌𵛓。-1.ꡏܫ; 𑇌𵛓.-1.ꡏܫ; [B1, B5, B6, P1, V3, V5, V6]; xn--8d1dg030h.-1.xn--1nb7163f; ; ; # 𑇌.-1.ꡏܫ
+xn--8d1dg030h.-1.xn--1nb7163f; 𑇌𵛓.-1.ꡏܫ; [B1, B5, B6, V3, V5, V6]; xn--8d1dg030h.-1.xn--1nb7163f; ; ; # 𑇌.-1.ꡏܫ
+xn--8d1dg030h.xn----u1c466tp10j; 𑇌𵛓.-⒈ꡏܫ; [B1, V3, V5, V6]; xn--8d1dg030h.xn----u1c466tp10j; ; ; # 𑇌.-⒈ꡏܫ
+璛᜴گ.-; ; [B1, B5, B6, V3]; xn--ikb175frt4e.-; ; ; # 璛᜴گ.-
+xn--ikb175frt4e.-; 璛᜴گ.-; [B1, B5, B6, V3]; xn--ikb175frt4e.-; ; ; # 璛᜴گ.-
+󠆰ࢡ੍샕.𐹲휁; ࢡ੍샕.𐹲휁; [B1, B2, B3]; xn--qyb07fj857a.xn--728bv72h; ; ; # ࢡ੍샕.𐹲휁
+󠆰ࢡ੍샕.𐹲휁; ࢡ੍샕.𐹲휁; [B1, B2, B3]; xn--qyb07fj857a.xn--728bv72h; ; ; # ࢡ੍샕.𐹲휁
+󠆰ࢡ੍샕.𐹲휁; ࢡ੍샕.𐹲휁; [B1, B2, B3]; xn--qyb07fj857a.xn--728bv72h; ; ; # ࢡ੍샕.𐹲휁
+󠆰ࢡ੍샕.𐹲휁; ࢡ੍샕.𐹲휁; [B1, B2, B3]; xn--qyb07fj857a.xn--728bv72h; ; ; # ࢡ੍샕.𐹲휁
+xn--qyb07fj857a.xn--728bv72h; ࢡ੍샕.𐹲휁; [B1, B2, B3]; xn--qyb07fj857a.xn--728bv72h; ; ; # ࢡ੍샕.𐹲휁
+񍨽.񋸕; 񍨽.񋸕; [P1, V6]; xn--pr3x.xn--rv7w; ; ; # .
+񍨽.񋸕; ; [P1, V6]; xn--pr3x.xn--rv7w; ; ; # .
+xn--pr3x.xn--rv7w; 񍨽.񋸕; [V6]; xn--pr3x.xn--rv7w; ; ; # .
+ٽ𞥕。𑑂𞤶Ⴍ-; ٽ𞥕.𑑂𞤶Ⴍ-; [B1, P1, V3, V5, V6]; xn--2ib0338v.xn----w0g2740ro9vg; ; ; # ٽ𞥕.𑑂𞤶Ⴍ-
+ٽ𞥕。𑑂𞤶Ⴍ-; ٽ𞥕.𑑂𞤶Ⴍ-; [B1, P1, V3, V5, V6]; xn--2ib0338v.xn----w0g2740ro9vg; ; ; # ٽ𞥕.𑑂𞤶Ⴍ-
+ٽ𞥕。𑑂𞤶ⴍ-; ٽ𞥕.𑑂𞤶ⴍ-; [B1, V3, V5]; xn--2ib0338v.xn----zvs0199fo91g; ; ; # ٽ𞥕.𑑂𞤶ⴍ-
+ٽ𞥕。𑑂𞤔Ⴍ-; ٽ𞥕.𑑂𞤶Ⴍ-; [B1, P1, V3, V5, V6]; xn--2ib0338v.xn----w0g2740ro9vg; ; ; # ٽ𞥕.𑑂𞤶Ⴍ-
+ٽ𞥕。𑑂𞤔ⴍ-; ٽ𞥕.𑑂𞤶ⴍ-; [B1, V3, V5]; xn--2ib0338v.xn----zvs0199fo91g; ; ; # ٽ𞥕.𑑂𞤶ⴍ-
+xn--2ib0338v.xn----zvs0199fo91g; ٽ𞥕.𑑂𞤶ⴍ-; [B1, V3, V5]; xn--2ib0338v.xn----zvs0199fo91g; ; ; # ٽ𞥕.𑑂𞤶ⴍ-
+xn--2ib0338v.xn----w0g2740ro9vg; ٽ𞥕.𑑂𞤶Ⴍ-; [B1, V3, V5, V6]; xn--2ib0338v.xn----w0g2740ro9vg; ; ; # ٽ𞥕.𑑂𞤶Ⴍ-
+ٽ𞥕。𑑂𞤶ⴍ-; ٽ𞥕.𑑂𞤶ⴍ-; [B1, V3, V5]; xn--2ib0338v.xn----zvs0199fo91g; ; ; # ٽ𞥕.𑑂𞤶ⴍ-
+ٽ𞥕。𑑂𞤔Ⴍ-; ٽ𞥕.𑑂𞤶Ⴍ-; [B1, P1, V3, V5, V6]; xn--2ib0338v.xn----w0g2740ro9vg; ; ; # ٽ𞥕.𑑂𞤶Ⴍ-
+ٽ𞥕。𑑂𞤔ⴍ-; ٽ𞥕.𑑂𞤶ⴍ-; [B1, V3, V5]; xn--2ib0338v.xn----zvs0199fo91g; ; ; # ٽ𞥕.𑑂𞤶ⴍ-
+𐯀𐸉𞧏。񢚧₄Ⴋ񂹫; 𐯀𐸉𞧏.񢚧4Ⴋ񂹫; [P1, V6]; xn--039c42bq865a.xn--4-t0g49302fnrzm; ; ; # .4Ⴋ
+𐯀𐸉𞧏。񢚧4Ⴋ񂹫; 𐯀𐸉𞧏.񢚧4Ⴋ񂹫; [P1, V6]; xn--039c42bq865a.xn--4-t0g49302fnrzm; ; ; # .4Ⴋ
+𐯀𐸉𞧏。񢚧4ⴋ񂹫; 𐯀𐸉𞧏.񢚧4ⴋ񂹫; [P1, V6]; xn--039c42bq865a.xn--4-wvs27840bnrzm; ; ; # .4ⴋ
+xn--039c42bq865a.xn--4-wvs27840bnrzm; 𐯀𐸉𞧏.񢚧4ⴋ񂹫; [V6]; xn--039c42bq865a.xn--4-wvs27840bnrzm; ; ; # .4ⴋ
+xn--039c42bq865a.xn--4-t0g49302fnrzm; 𐯀𐸉𞧏.񢚧4Ⴋ񂹫; [V6]; xn--039c42bq865a.xn--4-t0g49302fnrzm; ; ; # .4Ⴋ
+𐯀𐸉𞧏。񢚧₄ⴋ񂹫; 𐯀𐸉𞧏.񢚧4ⴋ񂹫; [P1, V6]; xn--039c42bq865a.xn--4-wvs27840bnrzm; ; ; # .4ⴋ
+4ڽ︒󠑥.≠; ; [B1, P1, V6]; xn--4-kvc5601q2h50i.xn--1ch; ; ; # 4ڽ︒.≠
+4ڽ︒󠑥.≠; 4ڽ︒󠑥.≠; [B1, P1, V6]; xn--4-kvc5601q2h50i.xn--1ch; ; ; # 4ڽ︒.≠
+4ڽ。󠑥.≠; 4ڽ.󠑥.≠; [B1, P1, V6]; xn--4-kvc.xn--5136e.xn--1ch; ; ; # 4ڽ..≠
+4ڽ。󠑥.≠; 4ڽ.󠑥.≠; [B1, P1, V6]; xn--4-kvc.xn--5136e.xn--1ch; ; ; # 4ڽ..≠
+xn--4-kvc.xn--5136e.xn--1ch; 4ڽ.󠑥.≠; [B1, V6]; xn--4-kvc.xn--5136e.xn--1ch; ; ; # 4ڽ..≠
+xn--4-kvc5601q2h50i.xn--1ch; 4ڽ︒󠑥.≠; [B1, V6]; xn--4-kvc5601q2h50i.xn--1ch; ; ; # 4ڽ︒.≠
+𝟓。ۗ; 5.ۗ; [V5]; 5.xn--nlb; ; ; # 5.ۗ
+5。ۗ; 5.ۗ; [V5]; 5.xn--nlb; ; ; # 5.ۗ
+5.xn--nlb; 5.ۗ; [V5]; 5.xn--nlb; ; ; # 5.ۗ
+‌򺸩.⾕; ‌򺸩.谷; [C1, P1, V6]; xn--0ug26167i.xn--6g3a; ; xn--i183d.xn--6g3a; [P1, V6] # .谷
+‌򺸩.谷; ; [C1, P1, V6]; xn--0ug26167i.xn--6g3a; ; xn--i183d.xn--6g3a; [P1, V6] # .谷
+xn--i183d.xn--6g3a; 򺸩.谷; [V6]; xn--i183d.xn--6g3a; ; ; # .谷
+xn--0ug26167i.xn--6g3a; ‌򺸩.谷; [C1, V6]; xn--0ug26167i.xn--6g3a; ; ; # .谷
+︒󎰇‍.-ܼ‌; ; [C1, C2, P1, V3, V6]; xn--1ug1658ftw26f.xn----t2c071q; ; xn--y86c71305c.xn----t2c; [P1, V3, V6] # ︒.-ܼ
+。󎰇‍.-ܼ‌; .󎰇‍.-ܼ‌; [C1, C2, P1, V3, V6, X4_2]; .xn--1ug05310k.xn----t2c071q; [C1, C2, P1, V3, V6, A4_2]; .xn--hh50e.xn----t2c; [P1, V3, V6, A4_2] # ..-ܼ
+.xn--hh50e.xn----t2c; .󎰇.-ܼ; [V3, V6, X4_2]; .xn--hh50e.xn----t2c; [V3, V6, A4_2]; ; # ..-ܼ
+.xn--1ug05310k.xn----t2c071q; .󎰇‍.-ܼ‌; [C1, C2, V3, V6, X4_2]; .xn--1ug05310k.xn----t2c071q; [C1, C2, V3, V6, A4_2]; ; # ..-ܼ
+xn--y86c71305c.xn----t2c; ︒󎰇.-ܼ; [V3, V6]; xn--y86c71305c.xn----t2c; ; ; # ︒.-ܼ
+xn--1ug1658ftw26f.xn----t2c071q; ︒󎰇‍.-ܼ‌; [C1, C2, V3, V6]; xn--1ug1658ftw26f.xn----t2c071q; ; ; # ︒.-ܼ
+≯𞤟。ᡨ; ≯𞥁.ᡨ; [B1, P1, V6]; xn--hdhz520p.xn--48e; ; ; # ≯𞥁.ᡨ
+≯𞤟。ᡨ; ≯𞥁.ᡨ; [B1, P1, V6]; xn--hdhz520p.xn--48e; ; ; # ≯𞥁.ᡨ
+≯𞥁。ᡨ; ≯𞥁.ᡨ; [B1, P1, V6]; xn--hdhz520p.xn--48e; ; ; # ≯𞥁.ᡨ
+≯𞥁。ᡨ; ≯𞥁.ᡨ; [B1, P1, V6]; xn--hdhz520p.xn--48e; ; ; # ≯𞥁.ᡨ
+xn--hdhz520p.xn--48e; ≯𞥁.ᡨ; [B1, V6]; xn--hdhz520p.xn--48e; ; ; # ≯𞥁.ᡨ
+ུ𫫰𝨄。ܓ𐹦; ུ𫫰𝨄.ܓ𐹦; [B1, V5]; xn--ned8985uo92e.xn--dnb6395k; ; ; # ུ𫫰𝨄.ܓ𐹦
+xn--ned8985uo92e.xn--dnb6395k; ུ𫫰𝨄.ܓ𐹦; [B1, V5]; xn--ned8985uo92e.xn--dnb6395k; ; ; # ུ𫫰𝨄.ܓ𐹦
+̼ߛ⁷𝟹。𝟬; ̼ߛ73.0; [B1, V5]; xn--73-9yb648b.0; ; ; # ̼ߛ73.0
+̼ߛ73。0; ̼ߛ73.0; [B1, V5]; xn--73-9yb648b.0; ; ; # ̼ߛ73.0
+xn--73-9yb648b.0; ̼ߛ73.0; [B1, V5]; xn--73-9yb648b.0; ; ; # ̼ߛ73.0
+‍.𝟗; ‍.9; [C2]; xn--1ug.9; ; .9; [A4_2] # .9
+‍.9; ; [C2]; xn--1ug.9; ; .9; [A4_2] # .9
+.9; ; [X4_2]; ; [A4_2]; ; # .9
+xn--1ug.9; ‍.9; [C2]; xn--1ug.9; ; ; # .9
+9; ; ; ; ; ; # 9
+ݹᡭ𪕈。ڶࣙ; ݹᡭ𪕈.ڶࣙ; [B2, B3]; xn--9pb497fs270c.xn--pkb80i; ; ; # ݹᡭ𪕈.ڶࣙ
+xn--9pb497fs270c.xn--pkb80i; ݹᡭ𪕈.ڶࣙ; [B2, B3]; xn--9pb497fs270c.xn--pkb80i; ; ; # ݹᡭ𪕈.ڶࣙ
+ܦ5ߢ겙。᳴𐷚; ܦ5ߢ겙.᳴𐷚; [B1, B2, B3, P1, V5, V6]; xn--5-j1c97c2483c.xn--e7f2093h; ; ; # ܦ5ߢ겙.᳴
+ܦ5ߢ겙。᳴𐷚; ܦ5ߢ겙.᳴𐷚; [B1, B2, B3, P1, V5, V6]; xn--5-j1c97c2483c.xn--e7f2093h; ; ; # ܦ5ߢ겙.᳴
+ܦ5ߢ겙。᳴𐷚; ܦ5ߢ겙.᳴𐷚; [B1, B2, B3, P1, V5, V6]; xn--5-j1c97c2483c.xn--e7f2093h; ; ; # ܦ5ߢ겙.᳴
+ܦ5ߢ겙。᳴𐷚; ܦ5ߢ겙.᳴𐷚; [B1, B2, B3, P1, V5, V6]; xn--5-j1c97c2483c.xn--e7f2093h; ; ; # ܦ5ߢ겙.᳴
+xn--5-j1c97c2483c.xn--e7f2093h; ܦ5ߢ겙.᳴𐷚; [B1, B2, B3, V5, V6]; xn--5-j1c97c2483c.xn--e7f2093h; ; ; # ܦ5ߢ겙.᳴
+Ⴍ𿣍ꡨ֮。Ⴞ‌‌; Ⴍ𿣍ꡨ֮.Ⴞ‌‌; [C1, P1, V6]; xn--5cb347co96jug15a.xn--2nd059ea; ; xn--5cb347co96jug15a.xn--2nd; [P1, V6] # Ⴍꡨ֮.Ⴞ
+ⴍ𿣍ꡨ֮。ⴞ‌‌; ⴍ𿣍ꡨ֮.ⴞ‌‌; [C1, P1, V6]; xn--5cb172r175fug38a.xn--0uga051h; ; xn--5cb172r175fug38a.xn--mlj; [P1, V6] # ⴍꡨ֮.ⴞ
+xn--5cb172r175fug38a.xn--mlj; ⴍ𿣍ꡨ֮.ⴞ; [V6]; xn--5cb172r175fug38a.xn--mlj; ; ; # ⴍꡨ֮.ⴞ
+xn--5cb172r175fug38a.xn--0uga051h; ⴍ𿣍ꡨ֮.ⴞ‌‌; [C1, V6]; xn--5cb172r175fug38a.xn--0uga051h; ; ; # ⴍꡨ֮.ⴞ
+xn--5cb347co96jug15a.xn--2nd; Ⴍ𿣍ꡨ֮.Ⴞ; [V6]; xn--5cb347co96jug15a.xn--2nd; ; ; # Ⴍꡨ֮.Ⴞ
+xn--5cb347co96jug15a.xn--2nd059ea; Ⴍ𿣍ꡨ֮.Ⴞ‌‌; [C1, V6]; xn--5cb347co96jug15a.xn--2nd059ea; ; ; # Ⴍꡨ֮.Ⴞ
+𐋰。󑓱; 𐋰.󑓱; [P1, V6]; xn--k97c.xn--q031e; ; ; # 𐋰.
+xn--k97c.xn--q031e; 𐋰.󑓱; [V6]; xn--k97c.xn--q031e; ; ; # 𐋰.
+󡎦឴୍.𐹾; ; [B1, P1, V6]; xn--9ic364dho91z.xn--2o0d; ; ; # ୍.𐹾
+xn--9ic364dho91z.xn--2o0d; 󡎦឴୍.𐹾; [B1, V6]; xn--9ic364dho91z.xn--2o0d; ; ; # ୍.𐹾
+ࣟႫ𶿸귤.򠅼𝟢휪ૣ; ࣟႫ𶿸귤.򠅼0휪ૣ; [P1, V5, V6]; xn--i0b601b6r7l2hs0a.xn--0-8le8997mulr5f; ; ; # ࣟႫ귤.0휪ૣ
+ࣟႫ𶿸귤.򠅼𝟢휪ૣ; ࣟႫ𶿸귤.򠅼0휪ૣ; [P1, V5, V6]; xn--i0b601b6r7l2hs0a.xn--0-8le8997mulr5f; ; ; # ࣟႫ귤.0휪ૣ
+ࣟႫ𶿸귤.򠅼0휪ૣ; ; [P1, V5, V6]; xn--i0b601b6r7l2hs0a.xn--0-8le8997mulr5f; ; ; # ࣟႫ귤.0휪ૣ
+ࣟႫ𶿸귤.򠅼0휪ૣ; ࣟႫ𶿸귤.򠅼0휪ૣ; [P1, V5, V6]; xn--i0b601b6r7l2hs0a.xn--0-8le8997mulr5f; ; ; # ࣟႫ귤.0휪ૣ
+ࣟⴋ𶿸귤.򠅼0휪ૣ; ࣟⴋ𶿸귤.򠅼0휪ૣ; [P1, V5, V6]; xn--i0b436pkl2g2h42a.xn--0-8le8997mulr5f; ; ; # ࣟⴋ귤.0휪ૣ
+ࣟⴋ𶿸귤.򠅼0휪ૣ; ; [P1, V5, V6]; xn--i0b436pkl2g2h42a.xn--0-8le8997mulr5f; ; ; # ࣟⴋ귤.0휪ૣ
+xn--i0b436pkl2g2h42a.xn--0-8le8997mulr5f; ࣟⴋ𶿸귤.򠅼0휪ૣ; [V5, V6]; xn--i0b436pkl2g2h42a.xn--0-8le8997mulr5f; ; ; # ࣟⴋ귤.0휪ૣ
+xn--i0b601b6r7l2hs0a.xn--0-8le8997mulr5f; ࣟႫ𶿸귤.򠅼0휪ૣ; [V5, V6]; xn--i0b601b6r7l2hs0a.xn--0-8le8997mulr5f; ; ; # ࣟႫ귤.0휪ૣ
+ࣟⴋ𶿸귤.򠅼𝟢휪ૣ; ࣟⴋ𶿸귤.򠅼0휪ૣ; [P1, V5, V6]; xn--i0b436pkl2g2h42a.xn--0-8le8997mulr5f; ; ; # ࣟⴋ귤.0휪ૣ
+ࣟⴋ𶿸귤.򠅼𝟢휪ૣ; ࣟⴋ𶿸귤.򠅼0휪ૣ; [P1, V5, V6]; xn--i0b436pkl2g2h42a.xn--0-8le8997mulr5f; ; ; # ࣟⴋ귤.0휪ૣ
+ބ.𞡝؁; ބ.𞡝؁; [P1, V6]; xn--lqb.xn--jfb1808v; ; ; # ބ.𞡝
+ބ.𞡝؁; ; [P1, V6]; xn--lqb.xn--jfb1808v; ; ; # ބ.𞡝
+xn--lqb.xn--jfb1808v; ބ.𞡝؁; [V6]; xn--lqb.xn--jfb1808v; ; ; # ބ.𞡝
+્₃.8꣄‍🃤; ્3.8꣄‍🃤; [V5]; xn--3-yke.xn--8-ugnv982dbkwm; ; xn--3-yke.xn--8-sl4et308f; # ્3.8꣄🃤
+્3.8꣄‍🃤; ; [V5]; xn--3-yke.xn--8-ugnv982dbkwm; ; xn--3-yke.xn--8-sl4et308f; # ્3.8꣄🃤
+xn--3-yke.xn--8-sl4et308f; ્3.8꣄🃤; [V5]; xn--3-yke.xn--8-sl4et308f; ; ; # ્3.8꣄🃤
+xn--3-yke.xn--8-ugnv982dbkwm; ્3.8꣄‍🃤; [V5]; xn--3-yke.xn--8-ugnv982dbkwm; ; ; # ્3.8꣄🃤
+℻⩷𝆆。𞤠󠆁᠌; fax⩷𝆆.𞥂; [B6]; xn--fax-4c9a1676t.xn--6e6h; ; ; # fax⩷𝆆.𞥂
+FAX⩷𝆆。𞤠󠆁᠌; fax⩷𝆆.𞥂; [B6]; xn--fax-4c9a1676t.xn--6e6h; ; ; # fax⩷𝆆.𞥂
+fax⩷𝆆。𞥂󠆁᠌; fax⩷𝆆.𞥂; [B6]; xn--fax-4c9a1676t.xn--6e6h; ; ; # fax⩷𝆆.𞥂
+Fax⩷𝆆。𞤠󠆁᠌; fax⩷𝆆.𞥂; [B6]; xn--fax-4c9a1676t.xn--6e6h; ; ; # fax⩷𝆆.𞥂
+xn--fax-4c9a1676t.xn--6e6h; fax⩷𝆆.𞥂; [B6]; xn--fax-4c9a1676t.xn--6e6h; ; ; # fax⩷𝆆.𞥂
+℻⩷𝆆。𞥂󠆁᠌; fax⩷𝆆.𞥂; [B6]; xn--fax-4c9a1676t.xn--6e6h; ; ; # fax⩷𝆆.𞥂
+FAX⩷𝆆。𞥂󠆁᠌; fax⩷𝆆.𞥂; [B6]; xn--fax-4c9a1676t.xn--6e6h; ; ; # fax⩷𝆆.𞥂
+fax⩷𝆆。𞤠󠆁᠌; fax⩷𝆆.𞥂; [B6]; xn--fax-4c9a1676t.xn--6e6h; ; ; # fax⩷𝆆.𞥂
+fax⩷𝆆.𞥂; ; [B6]; xn--fax-4c9a1676t.xn--6e6h; ; ; # fax⩷𝆆.𞥂
+FAX⩷𝆆.𞤠; fax⩷𝆆.𞥂; [B6]; xn--fax-4c9a1676t.xn--6e6h; ; ; # fax⩷𝆆.𞥂
+Fax⩷𝆆.𞤠; fax⩷𝆆.𞥂; [B6]; xn--fax-4c9a1676t.xn--6e6h; ; ; # fax⩷𝆆.𞥂
+FAX⩷𝆆.𞥂; fax⩷𝆆.𞥂; [B6]; xn--fax-4c9a1676t.xn--6e6h; ; ; # fax⩷𝆆.𞥂
+Fax⩷𝆆.𞥂; fax⩷𝆆.𞥂; [B6]; xn--fax-4c9a1676t.xn--6e6h; ; ; # fax⩷𝆆.𞥂
+ꡕ≠ၞ󮿱。𐵧󠄫ᅠ; ꡕ≠ၞ󮿱.𐵧ᅠ; [B2, B3, P1, V6]; xn--cld333gn31h0158l.xn--cl7c96v; ; ; # ꡕ≠ၞ.
+ꡕ≠ၞ󮿱。𐵧󠄫ᅠ; ꡕ≠ၞ󮿱.𐵧ᅠ; [B2, B3, P1, V6]; xn--cld333gn31h0158l.xn--cl7c96v; ; ; # ꡕ≠ၞ.
+ꡕ≠ၞ󮿱。𐵧󠄫ᅠ; ꡕ≠ၞ󮿱.𐵧ᅠ; [B2, B3, P1, V6]; xn--cld333gn31h0158l.xn--psd1510k; ; ; # ꡕ≠ၞ.
+ꡕ≠ၞ󮿱。𐵧󠄫ᅠ; ꡕ≠ၞ󮿱.𐵧ᅠ; [B2, B3, P1, V6]; xn--cld333gn31h0158l.xn--psd1510k; ; ; # ꡕ≠ၞ.
+xn--cld333gn31h0158l.xn--psd1510k; ꡕ≠ၞ󮿱.𐵧ᅠ; [B2, B3, V6]; xn--cld333gn31h0158l.xn--psd1510k; ; ; # ꡕ≠ၞ.
+xn--cld333gn31h0158l.xn--cl7c96v; ꡕ≠ၞ󮿱.𐵧ᅠ; [B2, B3, V6]; xn--cld333gn31h0158l.xn--cl7c96v; ; ; # ꡕ≠ၞ.
+鱊。‌; 鱊.‌; [C1]; xn--rt6a.xn--0ug; ; xn--rt6a.; [] # 鱊.
+xn--rt6a.; 鱊.; ; xn--rt6a.; ; ; # 鱊.
+鱊.; ; ; xn--rt6a.; ; ; # 鱊.
+xn--rt6a.xn--0ug; 鱊.‌; [C1]; xn--rt6a.xn--0ug; ; ; # 鱊.
+8𐹣.𑍨; 8𐹣.𑍨; [B1, B3, B6, V5]; xn--8-d26i.xn--0p1d; ; ; # 8𐹣.𑍨
+8𐹣.𑍨; ; [B1, B3, B6, V5]; xn--8-d26i.xn--0p1d; ; ; # 8𐹣.𑍨
+xn--8-d26i.xn--0p1d; 8𐹣.𑍨; [B1, B3, B6, V5]; xn--8-d26i.xn--0p1d; ; ; # 8𐹣.𑍨
+⏹𐧀.𐫯; ⏹𐧀.𐫯; [B1]; xn--qoh9161g.xn--1x9c; ; ; # ⏹𐧀.𐫯
+⏹𐧀.𐫯; ; [B1]; xn--qoh9161g.xn--1x9c; ; ; # ⏹𐧀.𐫯
+xn--qoh9161g.xn--1x9c; ⏹𐧀.𐫯; [B1]; xn--qoh9161g.xn--1x9c; ; ; # ⏹𐧀.𐫯
+𞤺ߌ4.‍; 𞤺ߌ4.‍; [B1, C2]; xn--4-0bd15808a.xn--1ug; ; xn--4-0bd15808a.; [] # 𞤺ߌ4.
+𞤺ߌ4.‍; ; [B1, C2]; xn--4-0bd15808a.xn--1ug; ; xn--4-0bd15808a.; [] # 𞤺ߌ4.
+𞤘ߌ4.‍; 𞤺ߌ4.‍; [B1, C2]; xn--4-0bd15808a.xn--1ug; ; xn--4-0bd15808a.; [] # 𞤺ߌ4.
+xn--4-0bd15808a.; 𞤺ߌ4.; ; xn--4-0bd15808a.; ; ; # 𞤺ߌ4.
+𞤺ߌ4.; ; ; xn--4-0bd15808a.; ; ; # 𞤺ߌ4.
+𞤘ߌ4.; 𞤺ߌ4.; ; xn--4-0bd15808a.; ; ; # 𞤺ߌ4.
+xn--4-0bd15808a.xn--1ug; 𞤺ߌ4.‍; [B1, C2]; xn--4-0bd15808a.xn--1ug; ; ; # 𞤺ߌ4.
+𞤘ߌ4.‍; 𞤺ߌ4.‍; [B1, C2]; xn--4-0bd15808a.xn--1ug; ; xn--4-0bd15808a.; [] # 𞤺ߌ4.
+⒗ঁ⃯-.࣢•; ; [B1, P1, V3, V6]; xn----z0d801p6kd.xn--l0b810j; ; ; # ⒗ঁ⃯-.•
+16.ঁ⃯-.࣢•; ; [B1, P1, V3, V5, V6]; 16.xn----z0d801p.xn--l0b810j; ; ; # 16.ঁ⃯-.•
+16.xn----z0d801p.xn--l0b810j; 16.ঁ⃯-.࣢•; [B1, V3, V5, V6]; 16.xn----z0d801p.xn--l0b810j; ; ; # 16.ঁ⃯-.•
+xn----z0d801p6kd.xn--l0b810j; ⒗ঁ⃯-.࣢•; [B1, V3, V6]; xn----z0d801p6kd.xn--l0b810j; ; ; # ⒗ঁ⃯-.•
+-。䏛; -.䏛; [V3]; -.xn--xco; ; ; # -.䏛
+-。䏛; -.䏛; [V3]; -.xn--xco; ; ; # -.䏛
+-.xn--xco; -.䏛; [V3]; -.xn--xco; ; ; # -.䏛
+‌񒃠.‍; ‌񒃠.‍; [C1, C2, P1, V6]; xn--0ugz7551c.xn--1ug; ; xn--dj8y.; [P1, V6] # .
+‌񒃠.‍; ; [C1, C2, P1, V6]; xn--0ugz7551c.xn--1ug; ; xn--dj8y.; [P1, V6] # .
+xn--dj8y.; 񒃠.; [V6]; xn--dj8y.; ; ; # .
+xn--0ugz7551c.xn--1ug; ‌񒃠.‍; [C1, C2, V6]; xn--0ugz7551c.xn--1ug; ; ; # .
+⒈⓰󥣇。𐹠‍򗷦Ⴕ; ⒈⓰󥣇.𐹠‍򗷦Ⴕ; [B1, C2, P1, V6]; xn--tsh0nz9380h.xn--tnd969erj4psgl3e; ; xn--tsh0nz9380h.xn--tnd1990ke579c; [B1, P1, V6] # ⒈⓰.𐹠Ⴕ
+1.⓰󥣇。𐹠‍򗷦Ⴕ; 1.⓰󥣇.𐹠‍򗷦Ⴕ; [B1, C2, P1, V6]; 1.xn--svh00804k.xn--tnd969erj4psgl3e; ; 1.xn--svh00804k.xn--tnd1990ke579c; [B1, P1, V6] # 1.⓰.𐹠Ⴕ
+1.⓰󥣇。𐹠‍򗷦ⴕ; 1.⓰󥣇.𐹠‍򗷦ⴕ; [B1, C2, P1, V6]; 1.xn--svh00804k.xn--1ug352csp0psg45e; ; 1.xn--svh00804k.xn--dljv223ee5t2d; [B1, P1, V6] # 1.⓰.𐹠ⴕ
+1.xn--svh00804k.xn--dljv223ee5t2d; 1.⓰󥣇.𐹠򗷦ⴕ; [B1, V6]; 1.xn--svh00804k.xn--dljv223ee5t2d; ; ; # 1.⓰.𐹠ⴕ
+1.xn--svh00804k.xn--1ug352csp0psg45e; 1.⓰󥣇.𐹠‍򗷦ⴕ; [B1, C2, V6]; 1.xn--svh00804k.xn--1ug352csp0psg45e; ; ; # 1.⓰.𐹠ⴕ
+1.xn--svh00804k.xn--tnd1990ke579c; 1.⓰󥣇.𐹠򗷦Ⴕ; [B1, V6]; 1.xn--svh00804k.xn--tnd1990ke579c; ; ; # 1.⓰.𐹠Ⴕ
+1.xn--svh00804k.xn--tnd969erj4psgl3e; 1.⓰󥣇.𐹠‍򗷦Ⴕ; [B1, C2, V6]; 1.xn--svh00804k.xn--tnd969erj4psgl3e; ; ; # 1.⓰.𐹠Ⴕ
+⒈⓰󥣇。𐹠‍򗷦ⴕ; ⒈⓰󥣇.𐹠‍򗷦ⴕ; [B1, C2, P1, V6]; xn--tsh0nz9380h.xn--1ug352csp0psg45e; ; xn--tsh0nz9380h.xn--dljv223ee5t2d; [B1, P1, V6] # ⒈⓰.𐹠ⴕ
+xn--tsh0nz9380h.xn--dljv223ee5t2d; ⒈⓰󥣇.𐹠򗷦ⴕ; [B1, V6]; xn--tsh0nz9380h.xn--dljv223ee5t2d; ; ; # ⒈⓰.𐹠ⴕ
+xn--tsh0nz9380h.xn--1ug352csp0psg45e; ⒈⓰󥣇.𐹠‍򗷦ⴕ; [B1, C2, V6]; xn--tsh0nz9380h.xn--1ug352csp0psg45e; ; ; # ⒈⓰.𐹠ⴕ
+xn--tsh0nz9380h.xn--tnd1990ke579c; ⒈⓰󥣇.𐹠򗷦Ⴕ; [B1, V6]; xn--tsh0nz9380h.xn--tnd1990ke579c; ; ; # ⒈⓰.𐹠Ⴕ
+xn--tsh0nz9380h.xn--tnd969erj4psgl3e; ⒈⓰󥣇.𐹠‍򗷦Ⴕ; [B1, C2, V6]; xn--tsh0nz9380h.xn--tnd969erj4psgl3e; ; ; # ⒈⓰.𐹠Ⴕ
+𞠊ᠮ-ß。᳐効؁𷣭; 𞠊ᠮ-ß.᳐効؁𷣭; [B1, B2, B3, P1, V5, V6]; xn----qfa310pg973b.xn--jfb197i791bi6x4c; ; xn---ss-21t18904a.xn--jfb197i791bi6x4c; # 𞠊ᠮ-ß.᳐効
+𞠊ᠮ-ß。᳐効؁𷣭; 𞠊ᠮ-ß.᳐効؁𷣭; [B1, B2, B3, P1, V5, V6]; xn----qfa310pg973b.xn--jfb197i791bi6x4c; ; xn---ss-21t18904a.xn--jfb197i791bi6x4c; # 𞠊ᠮ-ß.᳐効
+𞠊ᠮ-SS。᳐効؁𷣭; 𞠊ᠮ-ss.᳐効؁𷣭; [B1, B2, B3, P1, V5, V6]; xn---ss-21t18904a.xn--jfb197i791bi6x4c; ; ; # 𞠊ᠮ-ss.᳐効
+𞠊ᠮ-ss。᳐効؁𷣭; 𞠊ᠮ-ss.᳐効؁𷣭; [B1, B2, B3, P1, V5, V6]; xn---ss-21t18904a.xn--jfb197i791bi6x4c; ; ; # 𞠊ᠮ-ss.᳐効
+𞠊ᠮ-Ss。᳐効؁𷣭; 𞠊ᠮ-ss.᳐効؁𷣭; [B1, B2, B3, P1, V5, V6]; xn---ss-21t18904a.xn--jfb197i791bi6x4c; ; ; # 𞠊ᠮ-ss.᳐効
+xn---ss-21t18904a.xn--jfb197i791bi6x4c; 𞠊ᠮ-ss.᳐効؁𷣭; [B1, B2, B3, V5, V6]; xn---ss-21t18904a.xn--jfb197i791bi6x4c; ; ; # 𞠊ᠮ-ss.᳐効
+xn----qfa310pg973b.xn--jfb197i791bi6x4c; 𞠊ᠮ-ß.᳐効؁𷣭; [B1, B2, B3, V5, V6]; xn----qfa310pg973b.xn--jfb197i791bi6x4c; ; ; # 𞠊ᠮ-ß.᳐効
+𞠊ᠮ-SS。᳐効؁𷣭; 𞠊ᠮ-ss.᳐効؁𷣭; [B1, B2, B3, P1, V5, V6]; xn---ss-21t18904a.xn--jfb197i791bi6x4c; ; ; # 𞠊ᠮ-ss.᳐効
+𞠊ᠮ-ss。᳐効؁𷣭; 𞠊ᠮ-ss.᳐効؁𷣭; [B1, B2, B3, P1, V5, V6]; xn---ss-21t18904a.xn--jfb197i791bi6x4c; ; ; # 𞠊ᠮ-ss.᳐効
+𞠊ᠮ-Ss。᳐効؁𷣭; 𞠊ᠮ-ss.᳐効؁𷣭; [B1, B2, B3, P1, V5, V6]; xn---ss-21t18904a.xn--jfb197i791bi6x4c; ; ; # 𞠊ᠮ-ss.᳐効
+𑇀.󠨱; ; [P1, V5, V6]; xn--wd1d.xn--k946e; ; ; # 𑇀.
+xn--wd1d.xn--k946e; 𑇀.󠨱; [V5, V6]; xn--wd1d.xn--k946e; ; ; # 𑇀.
+␒3ﮈ。𝟘𐨿𐹆; ␒3ڈ.0𐨿𐹆; [B1, P1, V6]; xn--3-jsc897t.xn--0-sc5iy3h; ; ; # ␒3ڈ.0𐨿
+␒3ڈ。0𐨿𐹆; ␒3ڈ.0𐨿𐹆; [B1, P1, V6]; xn--3-jsc897t.xn--0-sc5iy3h; ; ; # ␒3ڈ.0𐨿
+xn--3-jsc897t.xn--0-sc5iy3h; ␒3ڈ.0𐨿𐹆; [B1, V6]; xn--3-jsc897t.xn--0-sc5iy3h; ; ; # ␒3ڈ.0𐨿
+ݫ6ઁࢦ。ᷣ; ݫ6ઁࢦ.ᷣ; [B1, B3, B6, V5]; xn--6-h5c06gj6c.xn--7eg; ; ; # ݫ6ઁࢦ.ᷣ
+ݫ6ઁࢦ。ᷣ; ݫ6ઁࢦ.ᷣ; [B1, B3, B6, V5]; xn--6-h5c06gj6c.xn--7eg; ; ; # ݫ6ઁࢦ.ᷣ
+xn--6-h5c06gj6c.xn--7eg; ݫ6ઁࢦ.ᷣ; [B1, B3, B6, V5]; xn--6-h5c06gj6c.xn--7eg; ; ; # ݫ6ઁࢦ.ᷣ
+؅-𽤞Ⴂ。򅤶‍; ؅-𽤞Ⴂ.򅤶‍; [B1, B6, C2, P1, V6]; xn----0kc662fc152h.xn--1ugy3204f; ; xn----0kc662fc152h.xn--ss06b; [B1, P1, V6] # -Ⴂ.
+؅-𽤞ⴂ。򅤶‍; ؅-𽤞ⴂ.򅤶‍; [B1, B6, C2, P1, V6]; xn----0kc8501a5399e.xn--1ugy3204f; ; xn----0kc8501a5399e.xn--ss06b; [B1, P1, V6] # -ⴂ.
+xn----0kc8501a5399e.xn--ss06b; ؅-𽤞ⴂ.򅤶; [B1, V6]; xn----0kc8501a5399e.xn--ss06b; ; ; # -ⴂ.
+xn----0kc8501a5399e.xn--1ugy3204f; ؅-𽤞ⴂ.򅤶‍; [B1, B6, C2, V6]; xn----0kc8501a5399e.xn--1ugy3204f; ; ; # -ⴂ.
+xn----0kc662fc152h.xn--ss06b; ؅-𽤞Ⴂ.򅤶; [B1, V6]; xn----0kc662fc152h.xn--ss06b; ; ; # -Ⴂ.
+xn----0kc662fc152h.xn--1ugy3204f; ؅-𽤞Ⴂ.򅤶‍; [B1, B6, C2, V6]; xn----0kc662fc152h.xn--1ugy3204f; ; ; # -Ⴂ.
+⾆.ꡈ5≯ß; 舌.ꡈ5≯ß; [P1, V6]; xn--tc1a.xn--5-qfa988w745i; ; xn--tc1a.xn--5ss-3m2a5009e; # 舌.ꡈ5≯ß
+⾆.ꡈ5≯ß; 舌.ꡈ5≯ß; [P1, V6]; xn--tc1a.xn--5-qfa988w745i; ; xn--tc1a.xn--5ss-3m2a5009e; # 舌.ꡈ5≯ß
+舌.ꡈ5≯ß; ; [P1, V6]; xn--tc1a.xn--5-qfa988w745i; ; xn--tc1a.xn--5ss-3m2a5009e; # 舌.ꡈ5≯ß
+舌.ꡈ5≯ß; 舌.ꡈ5≯ß; [P1, V6]; xn--tc1a.xn--5-qfa988w745i; ; xn--tc1a.xn--5ss-3m2a5009e; # 舌.ꡈ5≯ß
+舌.ꡈ5≯SS; 舌.ꡈ5≯ss; [P1, V6]; xn--tc1a.xn--5ss-3m2a5009e; ; ; # 舌.ꡈ5≯ss
+舌.ꡈ5≯SS; 舌.ꡈ5≯ss; [P1, V6]; xn--tc1a.xn--5ss-3m2a5009e; ; ; # 舌.ꡈ5≯ss
+舌.ꡈ5≯ss; ; [P1, V6]; xn--tc1a.xn--5ss-3m2a5009e; ; ; # 舌.ꡈ5≯ss
+舌.ꡈ5≯ss; 舌.ꡈ5≯ss; [P1, V6]; xn--tc1a.xn--5ss-3m2a5009e; ; ; # 舌.ꡈ5≯ss
+舌.ꡈ5≯Ss; 舌.ꡈ5≯ss; [P1, V6]; xn--tc1a.xn--5ss-3m2a5009e; ; ; # 舌.ꡈ5≯ss
+舌.ꡈ5≯Ss; 舌.ꡈ5≯ss; [P1, V6]; xn--tc1a.xn--5ss-3m2a5009e; ; ; # 舌.ꡈ5≯ss
+xn--tc1a.xn--5ss-3m2a5009e; 舌.ꡈ5≯ss; [V6]; xn--tc1a.xn--5ss-3m2a5009e; ; ; # 舌.ꡈ5≯ss
+xn--tc1a.xn--5-qfa988w745i; 舌.ꡈ5≯ß; [V6]; xn--tc1a.xn--5-qfa988w745i; ; ; # 舌.ꡈ5≯ß
+⾆.ꡈ5≯SS; 舌.ꡈ5≯ss; [P1, V6]; xn--tc1a.xn--5ss-3m2a5009e; ; ; # 舌.ꡈ5≯ss
+⾆.ꡈ5≯SS; 舌.ꡈ5≯ss; [P1, V6]; xn--tc1a.xn--5ss-3m2a5009e; ; ; # 舌.ꡈ5≯ss
+⾆.ꡈ5≯ss; 舌.ꡈ5≯ss; [P1, V6]; xn--tc1a.xn--5ss-3m2a5009e; ; ; # 舌.ꡈ5≯ss
+⾆.ꡈ5≯ss; 舌.ꡈ5≯ss; [P1, V6]; xn--tc1a.xn--5ss-3m2a5009e; ; ; # 舌.ꡈ5≯ss
+⾆.ꡈ5≯Ss; 舌.ꡈ5≯ss; [P1, V6]; xn--tc1a.xn--5ss-3m2a5009e; ; ; # 舌.ꡈ5≯ss
+⾆.ꡈ5≯Ss; 舌.ꡈ5≯ss; [P1, V6]; xn--tc1a.xn--5ss-3m2a5009e; ; ; # 舌.ꡈ5≯ss
+્8‍.򾂈ݜ; ્8‍.򾂈ݜ; [B1, B5, B6, C2, P1, V5, V6]; xn--8-yke534n.xn--gpb79046m; ; xn--8-yke.xn--gpb79046m; [B1, B5, B6, P1, V5, V6] # ્8.ݜ
+્8‍.򾂈ݜ; ; [B1, B5, B6, C2, P1, V5, V6]; xn--8-yke534n.xn--gpb79046m; ; xn--8-yke.xn--gpb79046m; [B1, B5, B6, P1, V5, V6] # ્8.ݜ
+xn--8-yke.xn--gpb79046m; ્8.򾂈ݜ; [B1, B5, B6, V5, V6]; xn--8-yke.xn--gpb79046m; ; ; # ્8.ݜ
+xn--8-yke534n.xn--gpb79046m; ્8‍.򾂈ݜ; [B1, B5, B6, C2, V5, V6]; xn--8-yke534n.xn--gpb79046m; ; ; # ્8.ݜ
+򸷆ੰ≮򹓙.񞎧⁷󠯙ڶ; 򸷆ੰ≮򹓙.񞎧7󠯙ڶ; [B5, B6, P1, V6]; xn--ycc893jqh38rb6fa.xn--7-5uc53836ixt41c; ; ; # ੰ≮.7ڶ
+򸷆ੰ≮򹓙.񞎧⁷󠯙ڶ; 򸷆ੰ≮򹓙.񞎧7󠯙ڶ; [B5, B6, P1, V6]; xn--ycc893jqh38rb6fa.xn--7-5uc53836ixt41c; ; ; # ੰ≮.7ڶ
+򸷆ੰ≮򹓙.񞎧7󠯙ڶ; ; [B5, B6, P1, V6]; xn--ycc893jqh38rb6fa.xn--7-5uc53836ixt41c; ; ; # ੰ≮.7ڶ
+򸷆ੰ≮򹓙.񞎧7󠯙ڶ; 򸷆ੰ≮򹓙.񞎧7󠯙ڶ; [B5, B6, P1, V6]; xn--ycc893jqh38rb6fa.xn--7-5uc53836ixt41c; ; ; # ੰ≮.7ڶ
+xn--ycc893jqh38rb6fa.xn--7-5uc53836ixt41c; 򸷆ੰ≮򹓙.񞎧7󠯙ڶ; [B5, B6, V6]; xn--ycc893jqh38rb6fa.xn--7-5uc53836ixt41c; ; ; # ੰ≮.7ڶ
+𞤪.ς; ; ; xn--ie6h.xn--3xa; ; xn--ie6h.xn--4xa; # 𞤪.ς
+𞤈.Σ; 𞤪.σ; ; xn--ie6h.xn--4xa; ; ; # 𞤪.σ
+𞤪.σ; ; ; xn--ie6h.xn--4xa; ; ; # 𞤪.σ
+𞤈.σ; 𞤪.σ; ; xn--ie6h.xn--4xa; ; ; # 𞤪.σ
+xn--ie6h.xn--4xa; 𞤪.σ; ; xn--ie6h.xn--4xa; ; ; # 𞤪.σ
+𞤈.ς; 𞤪.ς; ; xn--ie6h.xn--3xa; ; xn--ie6h.xn--4xa; # 𞤪.ς
+xn--ie6h.xn--3xa; 𞤪.ς; ; xn--ie6h.xn--3xa; ; ; # 𞤪.ς
+𞤪.Σ; 𞤪.σ; ; xn--ie6h.xn--4xa; ; ; # 𞤪.σ
+‌Ⴚ。ς; ‌Ⴚ.ς; [C1, P1, V6]; xn--ynd759e.xn--3xa; ; xn--ynd.xn--4xa; [P1, V6] # Ⴚ.ς
+‌Ⴚ。ς; ‌Ⴚ.ς; [C1, P1, V6]; xn--ynd759e.xn--3xa; ; xn--ynd.xn--4xa; [P1, V6] # Ⴚ.ς
+‌ⴚ。ς; ‌ⴚ.ς; [C1]; xn--0ug262c.xn--3xa; ; xn--ilj.xn--4xa; [] # ⴚ.ς
+‌Ⴚ。Σ; ‌Ⴚ.σ; [C1, P1, V6]; xn--ynd759e.xn--4xa; ; xn--ynd.xn--4xa; [P1, V6] # Ⴚ.σ
+‌ⴚ。σ; ‌ⴚ.σ; [C1]; xn--0ug262c.xn--4xa; ; xn--ilj.xn--4xa; [] # ⴚ.σ
+xn--ilj.xn--4xa; ⴚ.σ; ; xn--ilj.xn--4xa; ; ; # ⴚ.σ
+ⴚ.σ; ; ; xn--ilj.xn--4xa; ; ; # ⴚ.σ
+Ⴚ.Σ; Ⴚ.σ; [P1, V6]; xn--ynd.xn--4xa; ; ; # Ⴚ.σ
+ⴚ.ς; ; ; xn--ilj.xn--3xa; ; xn--ilj.xn--4xa; # ⴚ.ς
+Ⴚ.ς; ; [P1, V6]; xn--ynd.xn--3xa; ; xn--ynd.xn--4xa; # Ⴚ.ς
+xn--ynd.xn--4xa; Ⴚ.σ; [V6]; xn--ynd.xn--4xa; ; ; # Ⴚ.σ
+xn--ynd.xn--3xa; Ⴚ.ς; [V6]; xn--ynd.xn--3xa; ; ; # Ⴚ.ς
+xn--ilj.xn--3xa; ⴚ.ς; ; xn--ilj.xn--3xa; ; ; # ⴚ.ς
+Ⴚ.σ; ; [P1, V6]; xn--ynd.xn--4xa; ; ; # Ⴚ.σ
+xn--0ug262c.xn--4xa; ‌ⴚ.σ; [C1]; xn--0ug262c.xn--4xa; ; ; # ⴚ.σ
+xn--ynd759e.xn--4xa; ‌Ⴚ.σ; [C1, V6]; xn--ynd759e.xn--4xa; ; ; # Ⴚ.σ
+xn--0ug262c.xn--3xa; ‌ⴚ.ς; [C1]; xn--0ug262c.xn--3xa; ; ; # ⴚ.ς
+xn--ynd759e.xn--3xa; ‌Ⴚ.ς; [C1, V6]; xn--ynd759e.xn--3xa; ; ; # Ⴚ.ς
+‌ⴚ。ς; ‌ⴚ.ς; [C1]; xn--0ug262c.xn--3xa; ; xn--ilj.xn--4xa; [] # ⴚ.ς
+‌Ⴚ。Σ; ‌Ⴚ.σ; [C1, P1, V6]; xn--ynd759e.xn--4xa; ; xn--ynd.xn--4xa; [P1, V6] # Ⴚ.σ
+‌ⴚ。σ; ‌ⴚ.σ; [C1]; xn--0ug262c.xn--4xa; ; xn--ilj.xn--4xa; [] # ⴚ.σ
+𞤃.𐹦; 𞤥.𐹦; [B1]; xn--de6h.xn--eo0d; ; ; # 𞤥.𐹦
+𞤃.𐹦; 𞤥.𐹦; [B1]; xn--de6h.xn--eo0d; ; ; # 𞤥.𐹦
+𞤥.𐹦; ; [B1]; xn--de6h.xn--eo0d; ; ; # 𞤥.𐹦
+xn--de6h.xn--eo0d; 𞤥.𐹦; [B1]; xn--de6h.xn--eo0d; ; ; # 𞤥.𐹦
+𞤥.𐹦; 𞤥.𐹦; [B1]; xn--de6h.xn--eo0d; ; ; # 𞤥.𐹦
+‍⾕。‌꥓̐ꡎ; ‍谷.‌꥓̐ꡎ; [C1, C2]; xn--1ug0273b.xn--0sa359l6n7g13a; ; xn--6g3a.xn--0sa8175flwa; [V5] # 谷.꥓̐ꡎ
+‍⾕。‌꥓̐ꡎ; ‍谷.‌꥓̐ꡎ; [C1, C2]; xn--1ug0273b.xn--0sa359l6n7g13a; ; xn--6g3a.xn--0sa8175flwa; [V5] # 谷.꥓̐ꡎ
+‍谷。‌꥓̐ꡎ; ‍谷.‌꥓̐ꡎ; [C1, C2]; xn--1ug0273b.xn--0sa359l6n7g13a; ; xn--6g3a.xn--0sa8175flwa; [V5] # 谷.꥓̐ꡎ
+xn--6g3a.xn--0sa8175flwa; 谷.꥓̐ꡎ; [V5]; xn--6g3a.xn--0sa8175flwa; ; ; # 谷.꥓̐ꡎ
+xn--1ug0273b.xn--0sa359l6n7g13a; ‍谷.‌꥓̐ꡎ; [C1, C2]; xn--1ug0273b.xn--0sa359l6n7g13a; ; ; # 谷.꥓̐ꡎ
+ڪ-뉔.𞤐‌; ڪ-뉔.𞤲‌; [B2, B3, C1]; xn----guc3592k.xn--0ug7611p; ; xn----guc3592k.xn--qe6h; [B2, B3] # ڪ-뉔.𞤲
+ڪ-뉔.𞤐‌; ڪ-뉔.𞤲‌; [B2, B3, C1]; xn----guc3592k.xn--0ug7611p; ; xn----guc3592k.xn--qe6h; [B2, B3] # ڪ-뉔.𞤲
+ڪ-뉔.𞤐‌; ڪ-뉔.𞤲‌; [B2, B3, C1]; xn----guc3592k.xn--0ug7611p; ; xn----guc3592k.xn--qe6h; [B2, B3] # ڪ-뉔.𞤲
+ڪ-뉔.𞤐‌; ڪ-뉔.𞤲‌; [B2, B3, C1]; xn----guc3592k.xn--0ug7611p; ; xn----guc3592k.xn--qe6h; [B2, B3] # ڪ-뉔.𞤲
+ڪ-뉔.𞤲‌; ڪ-뉔.𞤲‌; [B2, B3, C1]; xn----guc3592k.xn--0ug7611p; ; xn----guc3592k.xn--qe6h; [B2, B3] # ڪ-뉔.𞤲
+ڪ-뉔.𞤲‌; ; [B2, B3, C1]; xn----guc3592k.xn--0ug7611p; ; xn----guc3592k.xn--qe6h; [B2, B3] # ڪ-뉔.𞤲
+xn----guc3592k.xn--qe6h; ڪ-뉔.𞤲; [B2, B3]; xn----guc3592k.xn--qe6h; ; ; # ڪ-뉔.𞤲
+xn----guc3592k.xn--0ug7611p; ڪ-뉔.𞤲‌; [B2, B3, C1]; xn----guc3592k.xn--0ug7611p; ; ; # ڪ-뉔.𞤲
+ڪ-뉔.𞤲‌; ڪ-뉔.𞤲‌; [B2, B3, C1]; xn----guc3592k.xn--0ug7611p; ; xn----guc3592k.xn--qe6h; [B2, B3] # ڪ-뉔.𞤲
+ڪ-뉔.𞤲‌; ڪ-뉔.𞤲‌; [B2, B3, C1]; xn----guc3592k.xn--0ug7611p; ; xn----guc3592k.xn--qe6h; [B2, B3] # ڪ-뉔.𞤲
+񔲵5ᦛς.꣄ݻܸ᳒; 񔲵5ᦛς.꣄ݻܸ᳒; [B1, P1, V5, V6]; xn--5-ymb298ng603j.xn--fob7kk44dl41k; ; xn--5-0mb988ng603j.xn--fob7kk44dl41k; # 5ᦛς.꣄ݻܸ᳒
+񔲵5ᦛς.꣄ݻܸ᳒; 񔲵5ᦛς.꣄ݻܸ᳒; [B1, P1, V5, V6]; xn--5-ymb298ng603j.xn--fob7kk44dl41k; ; xn--5-0mb988ng603j.xn--fob7kk44dl41k; # 5ᦛς.꣄ݻܸ᳒
+񔲵5ᦛς.꣄ݻܸ᳒; ; [B1, P1, V5, V6]; xn--5-ymb298ng603j.xn--fob7kk44dl41k; ; xn--5-0mb988ng603j.xn--fob7kk44dl41k; # 5ᦛς.꣄ݻܸ᳒
+񔲵5ᦛΣ.꣄ݻܸ᳒; 񔲵5ᦛσ.꣄ݻܸ᳒; [B1, P1, V5, V6]; xn--5-0mb988ng603j.xn--fob7kk44dl41k; ; ; # 5ᦛσ.꣄ݻܸ᳒
+񔲵5ᦛσ.꣄ݻܸ᳒; ; [B1, P1, V5, V6]; xn--5-0mb988ng603j.xn--fob7kk44dl41k; ; ; # 5ᦛσ.꣄ݻܸ᳒
+xn--5-0mb988ng603j.xn--fob7kk44dl41k; 񔲵5ᦛσ.꣄ݻܸ᳒; [B1, V5, V6]; xn--5-0mb988ng603j.xn--fob7kk44dl41k; ; ; # 5ᦛσ.꣄ݻܸ᳒
+xn--5-ymb298ng603j.xn--fob7kk44dl41k; 񔲵5ᦛς.꣄ݻܸ᳒; [B1, V5, V6]; xn--5-ymb298ng603j.xn--fob7kk44dl41k; ; ; # 5ᦛς.꣄ݻܸ᳒
+񔲵5ᦛΣ.꣄ݻܸ᳒; 񔲵5ᦛσ.꣄ݻܸ᳒; [B1, P1, V5, V6]; xn--5-0mb988ng603j.xn--fob7kk44dl41k; ; ; # 5ᦛσ.꣄ݻܸ᳒
+񔲵5ᦛσ.꣄ݻܸ᳒; 񔲵5ᦛσ.꣄ݻܸ᳒; [B1, P1, V5, V6]; xn--5-0mb988ng603j.xn--fob7kk44dl41k; ; ; # 5ᦛσ.꣄ݻܸ᳒
+񔲵5ᦛΣ.꣄ݻܸ᳒; 񔲵5ᦛσ.꣄ݻܸ᳒; [B1, P1, V5, V6]; xn--5-0mb988ng603j.xn--fob7kk44dl41k; ; ; # 5ᦛσ.꣄ݻܸ᳒
+񔲵5ᦛσ.꣄ݻܸ᳒; 񔲵5ᦛσ.꣄ݻܸ᳒; [B1, P1, V5, V6]; xn--5-0mb988ng603j.xn--fob7kk44dl41k; ; ; # 5ᦛσ.꣄ݻܸ᳒
+淽。ᠾ; 淽.ᠾ; ; xn--34w.xn--x7e; ; ; # 淽.ᠾ
+xn--34w.xn--x7e; 淽.ᠾ; ; xn--34w.xn--x7e; ; ; # 淽.ᠾ
+淽.ᠾ; ; ; xn--34w.xn--x7e; ; ; # 淽.ᠾ
+𐹴𑘷。-; 𐹴𑘷.-; [B1, V3]; xn--so0do6k.-; ; ; # 𐹴𑘷.-
+xn--so0do6k.-; 𐹴𑘷.-; [B1, V3]; xn--so0do6k.-; ; ; # 𐹴𑘷.-
+򬨩Ⴓ❓。𑄨; 򬨩Ⴓ❓.𑄨; [P1, V5, V6]; xn--rnd896i0j14q.xn--k80d; ; ; # Ⴓ❓.𑄨
+򬨩Ⴓ❓。𑄨; 򬨩Ⴓ❓.𑄨; [P1, V5, V6]; xn--rnd896i0j14q.xn--k80d; ; ; # Ⴓ❓.𑄨
+򬨩ⴓ❓。𑄨; 򬨩ⴓ❓.𑄨; [P1, V5, V6]; xn--8di78qvw32y.xn--k80d; ; ; # ⴓ❓.𑄨
+xn--8di78qvw32y.xn--k80d; 򬨩ⴓ❓.𑄨; [V5, V6]; xn--8di78qvw32y.xn--k80d; ; ; # ⴓ❓.𑄨
+xn--rnd896i0j14q.xn--k80d; 򬨩Ⴓ❓.𑄨; [V5, V6]; xn--rnd896i0j14q.xn--k80d; ; ; # Ⴓ❓.𑄨
+򬨩ⴓ❓。𑄨; 򬨩ⴓ❓.𑄨; [P1, V5, V6]; xn--8di78qvw32y.xn--k80d; ; ; # ⴓ❓.𑄨
+‌𐹡𞤌Ⴇ。ßႣ; ‌𐹡𞤮Ⴇ.ßႣ; [B1, C1, P1, V6]; xn--fnd599eyj4pr50g.xn--zca681f; ; xn--fnd1201kegrf.xn--ss-fek; [B1, P1, V6] # 𐹡𞤮Ⴇ.ßႣ
+‌𐹡𞤌Ⴇ。ßႣ; ‌𐹡𞤮Ⴇ.ßႣ; [B1, C1, P1, V6]; xn--fnd599eyj4pr50g.xn--zca681f; ; xn--fnd1201kegrf.xn--ss-fek; [B1, P1, V6] # 𐹡𞤮Ⴇ.ßႣ
+‌𐹡𞤮ⴇ。ßⴃ; ‌𐹡𞤮ⴇ.ßⴃ; [B1, C1]; xn--0ug332c3q0pr56g.xn--zca417t; ; xn--ykj9323eegwf.xn--ss-151a; [B1] # 𐹡𞤮ⴇ.ßⴃ
+‌𐹡𞤌Ⴇ。SSႣ; ‌𐹡𞤮Ⴇ.ssႣ; [B1, C1, P1, V6]; xn--fnd599eyj4pr50g.xn--ss-fek; ; xn--fnd1201kegrf.xn--ss-fek; [B1, P1, V6] # 𐹡𞤮Ⴇ.ssႣ
+‌𐹡𞤮ⴇ。ssⴃ; ‌𐹡𞤮ⴇ.ssⴃ; [B1, C1]; xn--0ug332c3q0pr56g.xn--ss-151a; ; xn--ykj9323eegwf.xn--ss-151a; [B1] # 𐹡𞤮ⴇ.ssⴃ
+‌𐹡𞤌ⴇ。Ssⴃ; ‌𐹡𞤮ⴇ.ssⴃ; [B1, C1]; xn--0ug332c3q0pr56g.xn--ss-151a; ; xn--ykj9323eegwf.xn--ss-151a; [B1] # 𐹡𞤮ⴇ.ssⴃ
+xn--ykj9323eegwf.xn--ss-151a; 𐹡𞤮ⴇ.ssⴃ; [B1]; xn--ykj9323eegwf.xn--ss-151a; ; ; # 𐹡𞤮ⴇ.ssⴃ
+xn--0ug332c3q0pr56g.xn--ss-151a; ‌𐹡𞤮ⴇ.ssⴃ; [B1, C1]; xn--0ug332c3q0pr56g.xn--ss-151a; ; ; # 𐹡𞤮ⴇ.ssⴃ
+xn--fnd1201kegrf.xn--ss-fek; 𐹡𞤮Ⴇ.ssႣ; [B1, V6]; xn--fnd1201kegrf.xn--ss-fek; ; ; # 𐹡𞤮Ⴇ.ssႣ
+xn--fnd599eyj4pr50g.xn--ss-fek; ‌𐹡𞤮Ⴇ.ssႣ; [B1, C1, V6]; xn--fnd599eyj4pr50g.xn--ss-fek; ; ; # 𐹡𞤮Ⴇ.ssႣ
+xn--0ug332c3q0pr56g.xn--zca417t; ‌𐹡𞤮ⴇ.ßⴃ; [B1, C1]; xn--0ug332c3q0pr56g.xn--zca417t; ; ; # 𐹡𞤮ⴇ.ßⴃ
+xn--fnd599eyj4pr50g.xn--zca681f; ‌𐹡𞤮Ⴇ.ßႣ; [B1, C1, V6]; xn--fnd599eyj4pr50g.xn--zca681f; ; ; # 𐹡𞤮Ⴇ.ßႣ
+‌𐹡𞤮ⴇ。ßⴃ; ‌𐹡𞤮ⴇ.ßⴃ; [B1, C1]; xn--0ug332c3q0pr56g.xn--zca417t; ; xn--ykj9323eegwf.xn--ss-151a; [B1] # 𐹡𞤮ⴇ.ßⴃ
+‌𐹡𞤌Ⴇ。SSႣ; ‌𐹡𞤮Ⴇ.ssႣ; [B1, C1, P1, V6]; xn--fnd599eyj4pr50g.xn--ss-fek; ; xn--fnd1201kegrf.xn--ss-fek; [B1, P1, V6] # 𐹡𞤮Ⴇ.ssႣ
+‌𐹡𞤮ⴇ。ssⴃ; ‌𐹡𞤮ⴇ.ssⴃ; [B1, C1]; xn--0ug332c3q0pr56g.xn--ss-151a; ; xn--ykj9323eegwf.xn--ss-151a; [B1] # 𐹡𞤮ⴇ.ssⴃ
+‌𐹡𞤌ⴇ。Ssⴃ; ‌𐹡𞤮ⴇ.ssⴃ; [B1, C1]; xn--0ug332c3q0pr56g.xn--ss-151a; ; xn--ykj9323eegwf.xn--ss-151a; [B1] # 𐹡𞤮ⴇ.ssⴃ
+‌𐹡𞤌ⴇ。ßⴃ; ‌𐹡𞤮ⴇ.ßⴃ; [B1, C1]; xn--0ug332c3q0pr56g.xn--zca417t; ; xn--ykj9323eegwf.xn--ss-151a; [B1] # 𐹡𞤮ⴇ.ßⴃ
+‌𐹡𞤌ⴇ。ssⴃ; ‌𐹡𞤮ⴇ.ssⴃ; [B1, C1]; xn--0ug332c3q0pr56g.xn--ss-151a; ; xn--ykj9323eegwf.xn--ss-151a; [B1] # 𐹡𞤮ⴇ.ssⴃ
+‌𐹡𞤌Ⴇ。Ssⴃ; ‌𐹡𞤮Ⴇ.ssⴃ; [B1, C1, P1, V6]; xn--fnd599eyj4pr50g.xn--ss-151a; ; xn--fnd1201kegrf.xn--ss-151a; [B1, P1, V6] # 𐹡𞤮Ⴇ.ssⴃ
+xn--fnd1201kegrf.xn--ss-151a; 𐹡𞤮Ⴇ.ssⴃ; [B1, V6]; xn--fnd1201kegrf.xn--ss-151a; ; ; # 𐹡𞤮Ⴇ.ssⴃ
+xn--fnd599eyj4pr50g.xn--ss-151a; ‌𐹡𞤮Ⴇ.ssⴃ; [B1, C1, V6]; xn--fnd599eyj4pr50g.xn--ss-151a; ; ; # 𐹡𞤮Ⴇ.ssⴃ
+‌𐹡𞤌ⴇ。ßⴃ; ‌𐹡𞤮ⴇ.ßⴃ; [B1, C1]; xn--0ug332c3q0pr56g.xn--zca417t; ; xn--ykj9323eegwf.xn--ss-151a; [B1] # 𐹡𞤮ⴇ.ßⴃ
+‌𐹡𞤌ⴇ。ssⴃ; ‌𐹡𞤮ⴇ.ssⴃ; [B1, C1]; xn--0ug332c3q0pr56g.xn--ss-151a; ; xn--ykj9323eegwf.xn--ss-151a; [B1] # 𐹡𞤮ⴇ.ssⴃ
+‌𐹡𞤌Ⴇ。Ssⴃ; ‌𐹡𞤮Ⴇ.ssⴃ; [B1, C1, P1, V6]; xn--fnd599eyj4pr50g.xn--ss-151a; ; xn--fnd1201kegrf.xn--ss-151a; [B1, P1, V6] # 𐹡𞤮Ⴇ.ssⴃ
+៿。𞬳; ៿.𞬳; [P1, V6]; xn--45e.xn--et6h; ; ; # .
+៿。𞬳; ៿.𞬳; [P1, V6]; xn--45e.xn--et6h; ; ; # .
+xn--45e.xn--et6h; ៿.𞬳; [V6]; xn--45e.xn--et6h; ; ; # .
+ْ‍。್𑚳; ْ‍.್𑚳; [C2, V5]; xn--uhb882k.xn--8tc4527k; ; xn--uhb.xn--8tc4527k; [V5] # ْ.್𑚳
+ْ‍。್𑚳; ْ‍.್𑚳; [C2, V5]; xn--uhb882k.xn--8tc4527k; ; xn--uhb.xn--8tc4527k; [V5] # ْ.್𑚳
+xn--uhb.xn--8tc4527k; ْ.್𑚳; [V5]; xn--uhb.xn--8tc4527k; ; ; # ْ.್𑚳
+xn--uhb882k.xn--8tc4527k; ْ‍.್𑚳; [C2, V5]; xn--uhb882k.xn--8tc4527k; ; ; # ْ.್𑚳
+-≠ᠻ.ݭ𞥃≮󟷺; -≠ᠻ.ݭ𞥃≮󟷺; [B1, B2, B3, P1, V3, V6]; xn----g6j886c.xn--xpb049kk353abj99f; ; ; # -≠ᠻ.ݭ𞥃≮
+-≠ᠻ.ݭ𞥃≮󟷺; -≠ᠻ.ݭ𞥃≮󟷺; [B1, B2, B3, P1, V3, V6]; xn----g6j886c.xn--xpb049kk353abj99f; ; ; # -≠ᠻ.ݭ𞥃≮
+-≠ᠻ.ݭ𞥃≮󟷺; ; [B1, B2, B3, P1, V3, V6]; xn----g6j886c.xn--xpb049kk353abj99f; ; ; # -≠ᠻ.ݭ𞥃≮
+-≠ᠻ.ݭ𞥃≮󟷺; -≠ᠻ.ݭ𞥃≮󟷺; [B1, B2, B3, P1, V3, V6]; xn----g6j886c.xn--xpb049kk353abj99f; ; ; # -≠ᠻ.ݭ𞥃≮
+-≠ᠻ.ݭ𞤡≮󟷺; -≠ᠻ.ݭ𞥃≮󟷺; [B1, B2, B3, P1, V3, V6]; xn----g6j886c.xn--xpb049kk353abj99f; ; ; # -≠ᠻ.ݭ𞥃≮
+-≠ᠻ.ݭ𞤡≮󟷺; -≠ᠻ.ݭ𞥃≮󟷺; [B1, B2, B3, P1, V3, V6]; xn----g6j886c.xn--xpb049kk353abj99f; ; ; # -≠ᠻ.ݭ𞥃≮
+xn----g6j886c.xn--xpb049kk353abj99f; -≠ᠻ.ݭ𞥃≮󟷺; [B1, B2, B3, V3, V6]; xn----g6j886c.xn--xpb049kk353abj99f; ; ; # -≠ᠻ.ݭ𞥃≮
+-≠ᠻ.ݭ𞤡≮󟷺; -≠ᠻ.ݭ𞥃≮󟷺; [B1, B2, B3, P1, V3, V6]; xn----g6j886c.xn--xpb049kk353abj99f; ; ; # -≠ᠻ.ݭ𞥃≮
+-≠ᠻ.ݭ𞤡≮󟷺; -≠ᠻ.ݭ𞥃≮󟷺; [B1, B2, B3, P1, V3, V6]; xn----g6j886c.xn--xpb049kk353abj99f; ; ; # -≠ᠻ.ݭ𞥃≮
+󠰆≯޵𐻪.򊥕≮𑁆ࡌ; 󠰆≯޵𐻪.򊥕≮𑁆ࡌ; [B1, B5, B6, P1, V6]; xn--zrb797kdm1oes34i.xn--bwb394k8k2o25n6d; ; ; # ≯.≮𑁆ࡌ
+󠰆≯޵𐻪.򊥕≮𑁆ࡌ; 󠰆≯޵𐻪.򊥕≮𑁆ࡌ; [B1, B5, B6, P1, V6]; xn--zrb797kdm1oes34i.xn--bwb394k8k2o25n6d; ; ; # ≯.≮𑁆ࡌ
+󠰆≯޵𐻪.򊥕≮𑁆ࡌ; ; [B1, B5, B6, P1, V6]; xn--zrb797kdm1oes34i.xn--bwb394k8k2o25n6d; ; ; # ≯.≮𑁆ࡌ
+󠰆≯޵𐻪.򊥕≮𑁆ࡌ; 󠰆≯޵𐻪.򊥕≮𑁆ࡌ; [B1, B5, B6, P1, V6]; xn--zrb797kdm1oes34i.xn--bwb394k8k2o25n6d; ; ; # ≯.≮𑁆ࡌ
+xn--zrb797kdm1oes34i.xn--bwb394k8k2o25n6d; 󠰆≯޵𐻪.򊥕≮𑁆ࡌ; [B1, B5, B6, V6]; xn--zrb797kdm1oes34i.xn--bwb394k8k2o25n6d; ; ; # ≯.≮𑁆ࡌ
+≠󦋂.؀்-ڹ; ; [B1, P1, V6]; xn--1ch22084l.xn----qkc07co6n; ; ; # ≠.்-ڹ
+≠󦋂.؀்-ڹ; ≠󦋂.؀்-ڹ; [B1, P1, V6]; xn--1ch22084l.xn----qkc07co6n; ; ; # ≠.்-ڹ
+xn--1ch22084l.xn----qkc07co6n; ≠󦋂.؀்-ڹ; [B1, V6]; xn--1ch22084l.xn----qkc07co6n; ; ; # ≠.்-ڹ
+៝󠁣≠。𐹼𐋤; ៝󠁣≠.𐹼𐋤; [B1, P1, V5, V6]; xn--54e694cn389z.xn--787ct8r; ; ; # ៝≠.𐹼𐋤
+៝󠁣≠。𐹼𐋤; ៝󠁣≠.𐹼𐋤; [B1, P1, V5, V6]; xn--54e694cn389z.xn--787ct8r; ; ; # ៝≠.𐹼𐋤
+៝󠁣≠。𐹼𐋤; ៝󠁣≠.𐹼𐋤; [B1, P1, V5, V6]; xn--54e694cn389z.xn--787ct8r; ; ; # ៝≠.𐹼𐋤
+៝󠁣≠。𐹼𐋤; ៝󠁣≠.𐹼𐋤; [B1, P1, V5, V6]; xn--54e694cn389z.xn--787ct8r; ; ; # ៝≠.𐹼𐋤
+xn--54e694cn389z.xn--787ct8r; ៝󠁣≠.𐹼𐋤; [B1, V5, V6]; xn--54e694cn389z.xn--787ct8r; ; ; # ៝≠.𐹼𐋤
+ß𰀻񆬗。𝩨🕮ß; ß𰀻񆬗.𝩨🕮ß; [P1, V5, V6]; xn--zca20040bgrkh.xn--zca3653v86qa; ; xn--ss-jl59biy67d.xn--ss-4d11aw87d; # ß𰀻.𝩨🕮ß
+ß𰀻񆬗。𝩨🕮ß; ß𰀻񆬗.𝩨🕮ß; [P1, V5, V6]; xn--zca20040bgrkh.xn--zca3653v86qa; ; xn--ss-jl59biy67d.xn--ss-4d11aw87d; # ß𰀻.𝩨🕮ß
+SS𰀻񆬗。𝩨🕮SS; ss𰀻񆬗.𝩨🕮ss; [P1, V5, V6]; xn--ss-jl59biy67d.xn--ss-4d11aw87d; ; ; # ss𰀻.𝩨🕮ss
+ss𰀻񆬗。𝩨🕮ss; ss𰀻񆬗.𝩨🕮ss; [P1, V5, V6]; xn--ss-jl59biy67d.xn--ss-4d11aw87d; ; ; # ss𰀻.𝩨🕮ss
+Ss𰀻񆬗。𝩨🕮Ss; ss𰀻񆬗.𝩨🕮ss; [P1, V5, V6]; xn--ss-jl59biy67d.xn--ss-4d11aw87d; ; ; # ss𰀻.𝩨🕮ss
+xn--ss-jl59biy67d.xn--ss-4d11aw87d; ss𰀻񆬗.𝩨🕮ss; [V5, V6]; xn--ss-jl59biy67d.xn--ss-4d11aw87d; ; ; # ss𰀻.𝩨🕮ss
+xn--zca20040bgrkh.xn--zca3653v86qa; ß𰀻񆬗.𝩨🕮ß; [V5, V6]; xn--zca20040bgrkh.xn--zca3653v86qa; ; ; # ß𰀻.𝩨🕮ß
+SS𰀻񆬗。𝩨🕮SS; ss𰀻񆬗.𝩨🕮ss; [P1, V5, V6]; xn--ss-jl59biy67d.xn--ss-4d11aw87d; ; ; # ss𰀻.𝩨🕮ss
+ss𰀻񆬗。𝩨🕮ss; ss𰀻񆬗.𝩨🕮ss; [P1, V5, V6]; xn--ss-jl59biy67d.xn--ss-4d11aw87d; ; ; # ss𰀻.𝩨🕮ss
+Ss𰀻񆬗。𝩨🕮Ss; ss𰀻񆬗.𝩨🕮ss; [P1, V5, V6]; xn--ss-jl59biy67d.xn--ss-4d11aw87d; ; ; # ss𰀻.𝩨🕮ss
+‍。‌; ‍.‌; [C1, C2]; xn--1ug.xn--0ug; ; .; [A4_2] # .
+xn--1ug.xn--0ug; ‍.‌; [C1, C2]; xn--1ug.xn--0ug; ; ; # .
+҃𐭞‍.ឹ𞯌򟩚; ; [B1, C2, P1, V5, V6]; xn--m3a412lrr0o.xn--43e8670vmd79b; ; xn--m3a6965k.xn--43e8670vmd79b; [B1, P1, V5, V6] # ҃𐭞.ឹ
+xn--m3a6965k.xn--43e8670vmd79b; ҃𐭞.ឹ𞯌򟩚; [B1, V5, V6]; xn--m3a6965k.xn--43e8670vmd79b; ; ; # ҃𐭞.ឹ
+xn--m3a412lrr0o.xn--43e8670vmd79b; ҃𐭞‍.ឹ𞯌򟩚; [B1, C2, V5, V6]; xn--m3a412lrr0o.xn--43e8670vmd79b; ; ; # ҃𐭞.ឹ
+‌𐠨‌临。ꡢ򄷞ⶏ𐹣; ‌𐠨‌临.ꡢ򄷞ⶏ𐹣; [B1, B5, B6, C1, P1, V6]; xn--0uga2656aop9k.xn--uojv340bk71c99u9f; ; xn--miq9646b.xn--uojv340bk71c99u9f; [B2, B3, B5, B6, P1, V6] # 𐠨临.ꡢⶏ𐹣
+xn--miq9646b.xn--uojv340bk71c99u9f; 𐠨临.ꡢ򄷞ⶏ𐹣; [B2, B3, B5, B6, V6]; xn--miq9646b.xn--uojv340bk71c99u9f; ; ; # 𐠨临.ꡢⶏ𐹣
+xn--0uga2656aop9k.xn--uojv340bk71c99u9f; ‌𐠨‌临.ꡢ򄷞ⶏ𐹣; [B1, B5, B6, C1, V6]; xn--0uga2656aop9k.xn--uojv340bk71c99u9f; ; ; # 𐠨临.ꡢⶏ𐹣
+󠑘.󠄮; 󠑘.; [P1, V6]; xn--s136e.; ; ; # .
+󠑘.󠄮; 󠑘.; [P1, V6]; xn--s136e.; ; ; # .
+xn--s136e.; 󠑘.; [V6]; xn--s136e.; ; ; # .
+𐫄്.꫶; 𐫄്.꫶; [B1, B3, B6, V5]; xn--wxc7880k.xn--2v9a; ; ; # 𐫄്.꫶
+𐫄്.꫶; ; [B1, B3, B6, V5]; xn--wxc7880k.xn--2v9a; ; ; # 𐫄്.꫶
+xn--wxc7880k.xn--2v9a; 𐫄്.꫶; [B1, B3, B6, V5]; xn--wxc7880k.xn--2v9a; ; ; # 𐫄്.꫶
+ꦷ󝵙멹。⒛󠨇; ꦷ󝵙멹.⒛󠨇; [P1, V5, V6]; xn--ym9av13acp85w.xn--dth22121k; ; ; # ꦷ멹.⒛
+ꦷ󝵙멹。⒛󠨇; ꦷ󝵙멹.⒛󠨇; [P1, V5, V6]; xn--ym9av13acp85w.xn--dth22121k; ; ; # ꦷ멹.⒛
+ꦷ󝵙멹。20.󠨇; ꦷ󝵙멹.20.󠨇; [P1, V5, V6]; xn--ym9av13acp85w.20.xn--d846e; ; ; # ꦷ멹.20.
+ꦷ󝵙멹。20.󠨇; ꦷ󝵙멹.20.󠨇; [P1, V5, V6]; xn--ym9av13acp85w.20.xn--d846e; ; ; # ꦷ멹.20.
+xn--ym9av13acp85w.20.xn--d846e; ꦷ󝵙멹.20.󠨇; [V5, V6]; xn--ym9av13acp85w.20.xn--d846e; ; ; # ꦷ멹.20.
+xn--ym9av13acp85w.xn--dth22121k; ꦷ󝵙멹.⒛󠨇; [V5, V6]; xn--ym9av13acp85w.xn--dth22121k; ; ; # ꦷ멹.⒛
+Ⴅ󲬹릖󠶚.ݷ𐹳⒊; ; [B4, B6, P1, V6]; xn--dnd2167fnet0io02g.xn--7pb000mwm4n; ; ; # Ⴅ릖.ݷ𐹳⒊
+Ⴅ󲬹릖󠶚.ݷ𐹳⒊; Ⴅ󲬹릖󠶚.ݷ𐹳⒊; [B4, B6, P1, V6]; xn--dnd2167fnet0io02g.xn--7pb000mwm4n; ; ; # Ⴅ릖.ݷ𐹳⒊
+Ⴅ󲬹릖󠶚.ݷ𐹳3.; ; [B4, B6, P1, V6]; xn--dnd2167fnet0io02g.xn--3-55c6803r.; ; ; # Ⴅ릖.ݷ𐹳3.
+Ⴅ󲬹릖󠶚.ݷ𐹳3.; Ⴅ󲬹릖󠶚.ݷ𐹳3.; [B4, B6, P1, V6]; xn--dnd2167fnet0io02g.xn--3-55c6803r.; ; ; # Ⴅ릖.ݷ𐹳3.
+ⴅ󲬹릖󠶚.ݷ𐹳3.; ⴅ󲬹릖󠶚.ݷ𐹳3.; [B4, B6, P1, V6]; xn--wkj8016bne45io02g.xn--3-55c6803r.; ; ; # ⴅ릖.ݷ𐹳3.
+ⴅ󲬹릖󠶚.ݷ𐹳3.; ; [B4, B6, P1, V6]; xn--wkj8016bne45io02g.xn--3-55c6803r.; ; ; # ⴅ릖.ݷ𐹳3.
+xn--wkj8016bne45io02g.xn--3-55c6803r.; ⴅ󲬹릖󠶚.ݷ𐹳3.; [B4, B6, V6]; xn--wkj8016bne45io02g.xn--3-55c6803r.; ; ; # ⴅ릖.ݷ𐹳3.
+xn--dnd2167fnet0io02g.xn--3-55c6803r.; Ⴅ󲬹릖󠶚.ݷ𐹳3.; [B4, B6, V6]; xn--dnd2167fnet0io02g.xn--3-55c6803r.; ; ; # Ⴅ릖.ݷ𐹳3.
+ⴅ󲬹릖󠶚.ݷ𐹳⒊; ⴅ󲬹릖󠶚.ݷ𐹳⒊; [B4, B6, P1, V6]; xn--wkj8016bne45io02g.xn--7pb000mwm4n; ; ; # ⴅ릖.ݷ𐹳⒊
+ⴅ󲬹릖󠶚.ݷ𐹳⒊; ; [B4, B6, P1, V6]; xn--wkj8016bne45io02g.xn--7pb000mwm4n; ; ; # ⴅ릖.ݷ𐹳⒊
+xn--wkj8016bne45io02g.xn--7pb000mwm4n; ⴅ󲬹릖󠶚.ݷ𐹳⒊; [B4, B6, V6]; xn--wkj8016bne45io02g.xn--7pb000mwm4n; ; ; # ⴅ릖.ݷ𐹳⒊
+xn--dnd2167fnet0io02g.xn--7pb000mwm4n; Ⴅ󲬹릖󠶚.ݷ𐹳⒊; [B4, B6, V6]; xn--dnd2167fnet0io02g.xn--7pb000mwm4n; ; ; # Ⴅ릖.ݷ𐹳⒊
+‌。︒; ‌.︒; [C1, P1, V6]; xn--0ug.xn--y86c; ; .xn--y86c; [P1, V6, A4_2] # .︒
+‌。。; ‌..; [C1, X4_2]; xn--0ug..; [C1, A4_2]; ..; [A4_2] # ..
+..; ; [X4_2]; ; [A4_2]; ; # ..
+xn--0ug..; ‌..; [C1, X4_2]; xn--0ug..; [C1, A4_2]; ; # ..
+.xn--y86c; .︒; [V6, X4_2]; .xn--y86c; [V6, A4_2]; ; # .︒
+xn--0ug.xn--y86c; ‌.︒; [C1, V6]; xn--0ug.xn--y86c; ; ; # .︒
+≯ݭ.₄; ≯ݭ.4; [B1, P1, V6]; xn--xpb149k.4; ; ; # ≯ݭ.4
+≯ݭ.₄; ≯ݭ.4; [B1, P1, V6]; xn--xpb149k.4; ; ; # ≯ݭ.4
+≯ݭ.4; ; [B1, P1, V6]; xn--xpb149k.4; ; ; # ≯ݭ.4
+≯ݭ.4; ≯ݭ.4; [B1, P1, V6]; xn--xpb149k.4; ; ; # ≯ݭ.4
+xn--xpb149k.4; ≯ݭ.4; [B1, V6]; xn--xpb149k.4; ; ; # ≯ݭ.4
+ᡲ-𝟹.ß-‌-; ᡲ-3.ß-‌-; [C1, V3]; xn---3-p9o.xn-----fia9303a; ; xn---3-p9o.ss--; [V2, V3] # ᡲ-3.ß--
+ᡲ-3.ß-‌-; ; [C1, V3]; xn---3-p9o.xn-----fia9303a; ; xn---3-p9o.ss--; [V2, V3] # ᡲ-3.ß--
+ᡲ-3.SS-‌-; ᡲ-3.ss-‌-; [C1, V3]; xn---3-p9o.xn--ss---276a; ; xn---3-p9o.ss--; [V2, V3] # ᡲ-3.ss--
+ᡲ-3.ss-‌-; ; [C1, V3]; xn---3-p9o.xn--ss---276a; ; xn---3-p9o.ss--; [V2, V3] # ᡲ-3.ss--
+ᡲ-3.Ss-‌-; ᡲ-3.ss-‌-; [C1, V3]; xn---3-p9o.xn--ss---276a; ; xn---3-p9o.ss--; [V2, V3] # ᡲ-3.ss--
+xn---3-p9o.ss--; ᡲ-3.ss--; [V2, V3]; xn---3-p9o.ss--; ; ; # ᡲ-3.ss--
+xn---3-p9o.xn--ss---276a; ᡲ-3.ss-‌-; [C1, V3]; xn---3-p9o.xn--ss---276a; ; ; # ᡲ-3.ss--
+xn---3-p9o.xn-----fia9303a; ᡲ-3.ß-‌-; [C1, V3]; xn---3-p9o.xn-----fia9303a; ; ; # ᡲ-3.ß--
+ᡲ-𝟹.SS-‌-; ᡲ-3.ss-‌-; [C1, V3]; xn---3-p9o.xn--ss---276a; ; xn---3-p9o.ss--; [V2, V3] # ᡲ-3.ss--
+ᡲ-𝟹.ss-‌-; ᡲ-3.ss-‌-; [C1, V3]; xn---3-p9o.xn--ss---276a; ; xn---3-p9o.ss--; [V2, V3] # ᡲ-3.ss--
+ᡲ-𝟹.Ss-‌-; ᡲ-3.ss-‌-; [C1, V3]; xn---3-p9o.xn--ss---276a; ; xn---3-p9o.ss--; [V2, V3] # ᡲ-3.ss--
+ﴈ𝟦ه󎊯。Ӏ; ضي4ه󎊯.Ӏ; [B2, B3, P1, V6]; xn--4-tnc6ck183523b.xn--d5a; ; ; # ضي4ه.Ӏ
+ضي4ه󎊯。Ӏ; ضي4ه󎊯.Ӏ; [B2, B3, P1, V6]; xn--4-tnc6ck183523b.xn--d5a; ; ; # ضي4ه.Ӏ
+ضي4ه󎊯。ӏ; ضي4ه󎊯.ӏ; [B2, B3, P1, V6]; xn--4-tnc6ck183523b.xn--s5a; ; ; # ضي4ه.ӏ
+xn--4-tnc6ck183523b.xn--s5a; ضي4ه󎊯.ӏ; [B2, B3, V6]; xn--4-tnc6ck183523b.xn--s5a; ; ; # ضي4ه.ӏ
+xn--4-tnc6ck183523b.xn--d5a; ضي4ه󎊯.Ӏ; [B2, B3, V6]; xn--4-tnc6ck183523b.xn--d5a; ; ; # ضي4ه.Ӏ
+ﴈ𝟦ه󎊯。ӏ; ضي4ه󎊯.ӏ; [B2, B3, P1, V6]; xn--4-tnc6ck183523b.xn--s5a; ; ; # ضي4ه.ӏ
+-.؂آ𑆾🐹; ; [B1, P1, V3, V6]; -.xn--kfb8dy983hgl7g; ; ; # -.آ𑆾🐹
+-.؂آ𑆾🐹; -.؂آ𑆾🐹; [B1, P1, V3, V6]; -.xn--kfb8dy983hgl7g; ; ; # -.آ𑆾🐹
+-.xn--kfb8dy983hgl7g; -.؂آ𑆾🐹; [B1, V3, V6]; -.xn--kfb8dy983hgl7g; ; ; # -.آ𑆾🐹
+󙶜ᢘ。᩿⺢; 󙶜ᢘ.᩿⺢; [P1, V5, V6]; xn--ibf35138o.xn--fpfz94g; ; ; # ᢘ.᩿⺢
+xn--ibf35138o.xn--fpfz94g; 󙶜ᢘ.᩿⺢; [V5, V6]; xn--ibf35138o.xn--fpfz94g; ; ; # ᢘ.᩿⺢
+≠ႷᠤႫ。?͌س觴; ≠ႷᠤႫ.?͌س觴; [B1, P1, V6]; xn--jndx718cnnl.xn--?-7fb34t0u7s; ; ; # ≠ႷᠤႫ.?͌س觴
+≠ႷᠤႫ。?͌س觴; ≠ႷᠤႫ.?͌س觴; [B1, P1, V6]; xn--jndx718cnnl.xn--?-7fb34t0u7s; ; ; # ≠ႷᠤႫ.?͌س觴
+≠ႷᠤႫ。?͌س觴; ≠ႷᠤႫ.?͌س觴; [B1, P1, V6]; xn--jndx718cnnl.xn--?-7fb34t0u7s; ; ; # ≠ႷᠤႫ.?͌س觴
+≠ႷᠤႫ。?͌س觴; ≠ႷᠤႫ.?͌س觴; [B1, P1, V6]; xn--jndx718cnnl.xn--?-7fb34t0u7s; ; ; # ≠ႷᠤႫ.?͌س觴
+≠ⴗᠤⴋ。?͌س觴; ≠ⴗᠤⴋ.?͌س觴; [B1, P1, V6]; xn--66e353ce0ilb.xn--?-7fb34t0u7s; ; ; # ≠ⴗᠤⴋ.?͌س觴
+≠ⴗᠤⴋ。?͌س觴; ≠ⴗᠤⴋ.?͌س觴; [B1, P1, V6]; xn--66e353ce0ilb.xn--?-7fb34t0u7s; ; ; # ≠ⴗᠤⴋ.?͌س觴
+≠Ⴗᠤⴋ。?͌س觴; ≠Ⴗᠤⴋ.?͌س觴; [B1, P1, V6]; xn--vnd619as6ig6k.xn--?-7fb34t0u7s; ; ; # ≠Ⴗᠤⴋ.?͌س觴
+≠Ⴗᠤⴋ。?͌س觴; ≠Ⴗᠤⴋ.?͌س觴; [B1, P1, V6]; xn--vnd619as6ig6k.xn--?-7fb34t0u7s; ; ; # ≠Ⴗᠤⴋ.?͌س觴
+xn--vnd619as6ig6k.xn--?-7fb34t0u7s; ≠Ⴗᠤⴋ.?͌س觴; [B1, P1, V6]; xn--vnd619as6ig6k.xn--?-7fb34t0u7s; ; ; # ≠Ⴗᠤⴋ.?͌س觴
+xn--66e353ce0ilb.xn--?-7fb34t0u7s; ≠ⴗᠤⴋ.?͌س觴; [B1, P1, V6]; xn--66e353ce0ilb.xn--?-7fb34t0u7s; ; ; # ≠ⴗᠤⴋ.?͌س觴
+xn--jndx718cnnl.xn--?-7fb34t0u7s; ≠ႷᠤႫ.?͌س觴; [B1, P1, V6]; xn--jndx718cnnl.xn--?-7fb34t0u7s; ; ; # ≠ႷᠤႫ.?͌س觴
+≠ⴗᠤⴋ。?͌س觴; ≠ⴗᠤⴋ.?͌س觴; [B1, P1, V6]; xn--66e353ce0ilb.xn--?-7fb34t0u7s; ; ; # ≠ⴗᠤⴋ.?͌س觴
+≠ⴗᠤⴋ。?͌س觴; ≠ⴗᠤⴋ.?͌س觴; [B1, P1, V6]; xn--66e353ce0ilb.xn--?-7fb34t0u7s; ; ; # ≠ⴗᠤⴋ.?͌س觴
+≠Ⴗᠤⴋ。?͌س觴; ≠Ⴗᠤⴋ.?͌س觴; [B1, P1, V6]; xn--vnd619as6ig6k.xn--?-7fb34t0u7s; ; ; # ≠Ⴗᠤⴋ.?͌س觴
+≠Ⴗᠤⴋ。?͌س觴; ≠Ⴗᠤⴋ.?͌س觴; [B1, P1, V6]; xn--vnd619as6ig6k.xn--?-7fb34t0u7s; ; ; # ≠Ⴗᠤⴋ.?͌س觴
+xn--vnd619as6ig6k.?͌س觴; ≠Ⴗᠤⴋ.?͌س觴; [B1, P1, V6]; xn--vnd619as6ig6k.xn--?-7fb34t0u7s; ; ; # ≠Ⴗᠤⴋ.?͌س觴
+XN--VND619AS6IG6K.?͌س觴; ≠Ⴗᠤⴋ.?͌س觴; [B1, P1, V6]; xn--vnd619as6ig6k.xn--?-7fb34t0u7s; ; ; # ≠Ⴗᠤⴋ.?͌س觴
+Xn--Vnd619as6ig6k.?͌س觴; ≠Ⴗᠤⴋ.?͌س觴; [B1, P1, V6]; xn--vnd619as6ig6k.xn--?-7fb34t0u7s; ; ; # ≠Ⴗᠤⴋ.?͌س觴
+xn--66e353ce0ilb.?͌س觴; ≠ⴗᠤⴋ.?͌س觴; [B1, P1, V6]; xn--66e353ce0ilb.xn--?-7fb34t0u7s; ; ; # ≠ⴗᠤⴋ.?͌س觴
+XN--66E353CE0ILB.?͌س觴; ≠ⴗᠤⴋ.?͌س觴; [B1, P1, V6]; xn--66e353ce0ilb.xn--?-7fb34t0u7s; ; ; # ≠ⴗᠤⴋ.?͌س觴
+Xn--66e353ce0ilb.?͌س觴; ≠ⴗᠤⴋ.?͌س觴; [B1, P1, V6]; xn--66e353ce0ilb.xn--?-7fb34t0u7s; ; ; # ≠ⴗᠤⴋ.?͌س觴
+xn--jndx718cnnl.?͌س觴; ≠ႷᠤႫ.?͌س觴; [B1, P1, V6]; xn--jndx718cnnl.xn--?-7fb34t0u7s; ; ; # ≠ႷᠤႫ.?͌س觴
+XN--JNDX718CNNL.?͌س觴; ≠ႷᠤႫ.?͌س觴; [B1, P1, V6]; xn--jndx718cnnl.xn--?-7fb34t0u7s; ; ; # ≠ႷᠤႫ.?͌س觴
+Xn--Jndx718cnnl.?͌س觴; ≠ႷᠤႫ.?͌س觴; [B1, P1, V6]; xn--jndx718cnnl.xn--?-7fb34t0u7s; ; ; # ≠ႷᠤႫ.?͌س觴
+٧.𐥨; ; [B1, P1, V6]; xn--gib.xn--vm9c; ; ; # ٧.
+xn--gib.xn--vm9c; ٧.𐥨; [B1, V6]; xn--gib.xn--vm9c; ; ; # ٧.
+꧀𝟯。‍񼑥𐹪᯳; ꧀3.‍񼑥𐹪᯳; [B1, C2, P1, V5, V6]; xn--3-5z4e.xn--1zf96ony8ygd68c; ; xn--3-5z4e.xn--1zfz754hncv8b; [B5, P1, V5, V6] # ꧀3.𐹪᯳
+꧀3。‍񼑥𐹪᯳; ꧀3.‍񼑥𐹪᯳; [B1, C2, P1, V5, V6]; xn--3-5z4e.xn--1zf96ony8ygd68c; ; xn--3-5z4e.xn--1zfz754hncv8b; [B5, P1, V5, V6] # ꧀3.𐹪᯳
+xn--3-5z4e.xn--1zfz754hncv8b; ꧀3.񼑥𐹪᯳; [B5, V5, V6]; xn--3-5z4e.xn--1zfz754hncv8b; ; ; # ꧀3.𐹪᯳
+xn--3-5z4e.xn--1zf96ony8ygd68c; ꧀3.‍񼑥𐹪᯳; [B1, C2, V5, V6]; xn--3-5z4e.xn--1zf96ony8ygd68c; ; ; # ꧀3.𐹪᯳
+򣕄4񠖽.≯٤𑀾󠸌; ; [B1, P1, V6]; xn--4-fg85dl688i.xn--dib174li86ntdy0i; ; ; # 4.≯٤𑀾
+򣕄4񠖽.≯٤𑀾󠸌; 򣕄4񠖽.≯٤𑀾󠸌; [B1, P1, V6]; xn--4-fg85dl688i.xn--dib174li86ntdy0i; ; ; # 4.≯٤𑀾
+xn--4-fg85dl688i.xn--dib174li86ntdy0i; 򣕄4񠖽.≯٤𑀾󠸌; [B1, V6]; xn--4-fg85dl688i.xn--dib174li86ntdy0i; ; ; # 4.≯٤𑀾
+򗆧𝟯。⒈᩶𝟚򠘌; 򗆧3.⒈᩶2򠘌; [P1, V6]; xn--3-rj42h.xn--2-13k746cq465x; ; ; # 3.⒈᩶2
+򗆧3。1.᩶2򠘌; 򗆧3.1.᩶2򠘌; [P1, V5, V6]; xn--3-rj42h.1.xn--2-13k96240l; ; ; # 3.1.᩶2
+xn--3-rj42h.1.xn--2-13k96240l; 򗆧3.1.᩶2򠘌; [V5, V6]; xn--3-rj42h.1.xn--2-13k96240l; ; ; # 3.1.᩶2
+xn--3-rj42h.xn--2-13k746cq465x; 򗆧3.⒈᩶2򠘌; [V6]; xn--3-rj42h.xn--2-13k746cq465x; ; ; # 3.⒈᩶2
+‍₅⒈。≯𝟴‍; ‍5⒈.≯8‍; [C2, P1, V6]; xn--5-tgnz5r.xn--8-ugn00i; ; xn--5-ecp.xn--8-ogo; [P1, V6] # 5⒈.≯8
+‍₅⒈。≯𝟴‍; ‍5⒈.≯8‍; [C2, P1, V6]; xn--5-tgnz5r.xn--8-ugn00i; ; xn--5-ecp.xn--8-ogo; [P1, V6] # 5⒈.≯8
+‍51.。≯8‍; ‍51..≯8‍; [C2, P1, V6, X4_2]; xn--51-l1t..xn--8-ugn00i; [C2, P1, V6, A4_2]; 51..xn--8-ogo; [P1, V6, A4_2] # 51..≯8
+‍51.。≯8‍; ‍51..≯8‍; [C2, P1, V6, X4_2]; xn--51-l1t..xn--8-ugn00i; [C2, P1, V6, A4_2]; 51..xn--8-ogo; [P1, V6, A4_2] # 51..≯8
+51..xn--8-ogo; 51..≯8; [V6, X4_2]; 51..xn--8-ogo; [V6, A4_2]; ; # 51..≯8
+xn--51-l1t..xn--8-ugn00i; ‍51..≯8‍; [C2, V6, X4_2]; xn--51-l1t..xn--8-ugn00i; [C2, V6, A4_2]; ; # 51..≯8
+xn--5-ecp.xn--8-ogo; 5⒈.≯8; [V6]; xn--5-ecp.xn--8-ogo; ; ; # 5⒈.≯8
+xn--5-tgnz5r.xn--8-ugn00i; ‍5⒈.≯8‍; [C2, V6]; xn--5-tgnz5r.xn--8-ugn00i; ; ; # 5⒈.≯8
+ꡰڗႆ.򪘙ܯ≠‌; ꡰڗႆ.򪘙ܯ≠‌; [B5, B6, C1, P1, V6]; xn--tjb002cn51k.xn--5nb448jcubcz547b; ; xn--tjb002cn51k.xn--5nb630lbj91q; [B5, B6, P1, V6] # ꡰڗႆ.ܯ≠
+ꡰڗႆ.򪘙ܯ≠‌; ꡰڗႆ.򪘙ܯ≠‌; [B5, B6, C1, P1, V6]; xn--tjb002cn51k.xn--5nb448jcubcz547b; ; xn--tjb002cn51k.xn--5nb630lbj91q; [B5, B6, P1, V6] # ꡰڗႆ.ܯ≠
+ꡰڗႆ.򪘙ܯ≠‌; ; [B5, B6, C1, P1, V6]; xn--tjb002cn51k.xn--5nb448jcubcz547b; ; xn--tjb002cn51k.xn--5nb630lbj91q; [B5, B6, P1, V6] # ꡰڗႆ.ܯ≠
+ꡰڗႆ.򪘙ܯ≠‌; ꡰڗႆ.򪘙ܯ≠‌; [B5, B6, C1, P1, V6]; xn--tjb002cn51k.xn--5nb448jcubcz547b; ; xn--tjb002cn51k.xn--5nb630lbj91q; [B5, B6, P1, V6] # ꡰڗႆ.ܯ≠
+xn--tjb002cn51k.xn--5nb630lbj91q; ꡰڗႆ.򪘙ܯ≠; [B5, B6, V6]; xn--tjb002cn51k.xn--5nb630lbj91q; ; ; # ꡰڗႆ.ܯ≠
+xn--tjb002cn51k.xn--5nb448jcubcz547b; ꡰڗႆ.򪘙ܯ≠‌; [B5, B6, C1, V6]; xn--tjb002cn51k.xn--5nb448jcubcz547b; ; ; # ꡰڗႆ.ܯ≠
+𑄱。򪌿𐹵; 𑄱.򪌿𐹵; [B1, B3, B5, B6, P1, V5, V6]; xn--t80d.xn--to0d14792b; ; ; # 𑄱.𐹵
+𑄱。򪌿𐹵; 𑄱.򪌿𐹵; [B1, B3, B5, B6, P1, V5, V6]; xn--t80d.xn--to0d14792b; ; ; # 𑄱.𐹵
+xn--t80d.xn--to0d14792b; 𑄱.򪌿𐹵; [B1, B3, B5, B6, V5, V6]; xn--t80d.xn--to0d14792b; ; ; # 𑄱.𐹵
+𝟥؀。ܽ; 3؀.ܽ; [B1, B3, B6, P1, V5, V6]; xn--3-rkc.xn--kob; ; ; # 3.ܽ
+3؀。ܽ; 3؀.ܽ; [B1, B3, B6, P1, V5, V6]; xn--3-rkc.xn--kob; ; ; # 3.ܽ
+xn--3-rkc.xn--kob; 3؀.ܽ; [B1, B3, B6, V5, V6]; xn--3-rkc.xn--kob; ; ; # 3.ܽ
+ط𐹣٦.ݭ긷; ; [B2, B3]; xn--2gb8gu829f.xn--xpb0156f; ; ; # ط𐹣٦.ݭ긷
+ط𐹣٦.ݭ긷; ط𐹣٦.ݭ긷; [B2, B3]; xn--2gb8gu829f.xn--xpb0156f; ; ; # ط𐹣٦.ݭ긷
+xn--2gb8gu829f.xn--xpb0156f; ط𐹣٦.ݭ긷; [B2, B3]; xn--2gb8gu829f.xn--xpb0156f; ; ; # ط𐹣٦.ݭ긷
+︒Ↄⷧ򾀃.Ⴗ𐣞; ︒Ↄⷧ򾀃.Ⴗ𐣞; [B1, B5, B6, P1, V6]; xn--q5g000c056n0226g.xn--vnd8618j; ; ; # ︒Ↄⷧ.Ⴗ
+。Ↄⷧ򾀃.Ⴗ𐣞; .Ↄⷧ򾀃.Ⴗ𐣞; [B5, B6, P1, V6, X4_2]; .xn--q5g000cll06u.xn--vnd8618j; [B5, B6, P1, V6, A4_2]; ; # .Ↄⷧ.Ⴗ
+。ↄⷧ򾀃.ⴗ𐣞; .ↄⷧ򾀃.ⴗ𐣞; [B5, B6, P1, V6, X4_2]; .xn--r5gy00cll06u.xn--flj4541e; [B5, B6, P1, V6, A4_2]; ; # .ↄⷧ.ⴗ
+.xn--r5gy00cll06u.xn--flj4541e; .ↄⷧ򾀃.ⴗ𐣞; [B5, B6, V6, X4_2]; .xn--r5gy00cll06u.xn--flj4541e; [B5, B6, V6, A4_2]; ; # .ↄⷧ.ⴗ
+.xn--q5g000cll06u.xn--vnd8618j; .Ↄⷧ򾀃.Ⴗ𐣞; [B5, B6, V6, X4_2]; .xn--q5g000cll06u.xn--vnd8618j; [B5, B6, V6, A4_2]; ; # .Ↄⷧ.Ⴗ
+︒ↄⷧ򾀃.ⴗ𐣞; ︒ↄⷧ򾀃.ⴗ𐣞; [B1, B5, B6, P1, V6]; xn--r5gy00c056n0226g.xn--flj4541e; ; ; # ︒ↄⷧ.ⴗ
+xn--r5gy00c056n0226g.xn--flj4541e; ︒ↄⷧ򾀃.ⴗ𐣞; [B1, B5, B6, V6]; xn--r5gy00c056n0226g.xn--flj4541e; ; ; # ︒ↄⷧ.ⴗ
+xn--q5g000c056n0226g.xn--vnd8618j; ︒Ↄⷧ򾀃.Ⴗ𐣞; [B1, B5, B6, V6]; xn--q5g000c056n0226g.xn--vnd8618j; ; ; # ︒Ↄⷧ.Ⴗ
+؀.ֱ; ; [B1, B3, B6, P1, V5, V6]; xn--ifb.xn--8cb; ; ; # .ֱ
+xn--ifb.xn--8cb; ؀.ֱ; [B1, B3, B6, V5, V6]; xn--ifb.xn--8cb; ; ; # .ֱ
+ς≯。𐹽; ς≯.𐹽; [B1, B6, P1, V6]; xn--3xa028m.xn--1o0d; ; xn--4xa818m.xn--1o0d; # ς≯.𐹽
+ς≯。𐹽; ς≯.𐹽; [B1, B6, P1, V6]; xn--3xa028m.xn--1o0d; ; xn--4xa818m.xn--1o0d; # ς≯.𐹽
+ς≯。𐹽; ς≯.𐹽; [B1, B6, P1, V6]; xn--3xa028m.xn--1o0d; ; xn--4xa818m.xn--1o0d; # ς≯.𐹽
+ς≯。𐹽; ς≯.𐹽; [B1, B6, P1, V6]; xn--3xa028m.xn--1o0d; ; xn--4xa818m.xn--1o0d; # ς≯.𐹽
+Σ≯。𐹽; σ≯.𐹽; [B1, B6, P1, V6]; xn--4xa818m.xn--1o0d; ; ; # σ≯.𐹽
+Σ≯。𐹽; σ≯.𐹽; [B1, B6, P1, V6]; xn--4xa818m.xn--1o0d; ; ; # σ≯.𐹽
+σ≯。𐹽; σ≯.𐹽; [B1, B6, P1, V6]; xn--4xa818m.xn--1o0d; ; ; # σ≯.𐹽
+σ≯。𐹽; σ≯.𐹽; [B1, B6, P1, V6]; xn--4xa818m.xn--1o0d; ; ; # σ≯.𐹽
+xn--4xa818m.xn--1o0d; σ≯.𐹽; [B1, B6, V6]; xn--4xa818m.xn--1o0d; ; ; # σ≯.𐹽
+xn--3xa028m.xn--1o0d; ς≯.𐹽; [B1, B6, V6]; xn--3xa028m.xn--1o0d; ; ; # ς≯.𐹽
+Σ≯。𐹽; σ≯.𐹽; [B1, B6, P1, V6]; xn--4xa818m.xn--1o0d; ; ; # σ≯.𐹽
+Σ≯。𐹽; σ≯.𐹽; [B1, B6, P1, V6]; xn--4xa818m.xn--1o0d; ; ; # σ≯.𐹽
+σ≯。𐹽; σ≯.𐹽; [B1, B6, P1, V6]; xn--4xa818m.xn--1o0d; ; ; # σ≯.𐹽
+σ≯。𐹽; σ≯.𐹽; [B1, B6, P1, V6]; xn--4xa818m.xn--1o0d; ; ; # σ≯.𐹽
+្‍ݟ。𐹶; ្‍ݟ.𐹶; [B1, V5]; xn--jpb535fv9f.xn--uo0d; ; xn--jpb535f.xn--uo0d; # ្ݟ.𐹶
+xn--jpb535f.xn--uo0d; ្ݟ.𐹶; [B1, V5]; xn--jpb535f.xn--uo0d; ; ; # ្ݟ.𐹶
+xn--jpb535fv9f.xn--uo0d; ្‍ݟ.𐹶; [B1, V5]; xn--jpb535fv9f.xn--uo0d; ; ; # ្ݟ.𐹶
+𾷂ੂႪ񂂟.≮; ; [P1, V6]; xn--nbc493aro75ggskb.xn--gdh; ; ; # ੂႪ.≮
+𾷂ੂႪ񂂟.≮; 𾷂ੂႪ񂂟.≮; [P1, V6]; xn--nbc493aro75ggskb.xn--gdh; ; ; # ੂႪ.≮
+𾷂ੂⴊ񂂟.≮; 𾷂ੂⴊ񂂟.≮; [P1, V6]; xn--nbc229o4y27dgskb.xn--gdh; ; ; # ੂⴊ.≮
+𾷂ੂⴊ񂂟.≮; ; [P1, V6]; xn--nbc229o4y27dgskb.xn--gdh; ; ; # ੂⴊ.≮
+xn--nbc229o4y27dgskb.xn--gdh; 𾷂ੂⴊ񂂟.≮; [V6]; xn--nbc229o4y27dgskb.xn--gdh; ; ; # ੂⴊ.≮
+xn--nbc493aro75ggskb.xn--gdh; 𾷂ੂႪ񂂟.≮; [V6]; xn--nbc493aro75ggskb.xn--gdh; ; ; # ੂႪ.≮
+ꡠ.۲; ꡠ.۲; ; xn--5c9a.xn--fmb; ; ; # ꡠ.۲
+ꡠ.۲; ; ; xn--5c9a.xn--fmb; ; ; # ꡠ.۲
+xn--5c9a.xn--fmb; ꡠ.۲; ; xn--5c9a.xn--fmb; ; ; # ꡠ.۲
+𐹣񄷄。ꡬ🄄; 𐹣񄷄.ꡬ🄄; [B1, P1, V6]; xn--bo0d0203l.xn--id9a4443d; ; ; # 𐹣.ꡬ🄄
+𐹣񄷄。ꡬ3,; 𐹣񄷄.ꡬ3,; [B1, B6, P1, V6]; xn--bo0d0203l.xn--3,-yj9h; ; ; # 𐹣.ꡬ3,
+xn--bo0d0203l.xn--3,-yj9h; 𐹣񄷄.ꡬ3,; [B1, B6, P1, V6]; xn--bo0d0203l.xn--3,-yj9h; ; ; # 𐹣.ꡬ3,
+xn--bo0d0203l.xn--id9a4443d; 𐹣񄷄.ꡬ🄄; [B1, V6]; xn--bo0d0203l.xn--id9a4443d; ; ; # 𐹣.ꡬ🄄
+-్𞾀𑲓。‍്; -్𞾀𑲓.‍്; [B1, C2, P1, V3, V6]; xn----x6e0220sclug.xn--wxc317g; ; xn----x6e0220sclug.xn--wxc; [B1, B3, B6, P1, V3, V5, V6] # -్𑲓.്
+-్𞾀𑲓。‍്; -్𞾀𑲓.‍്; [B1, C2, P1, V3, V6]; xn----x6e0220sclug.xn--wxc317g; ; xn----x6e0220sclug.xn--wxc; [B1, B3, B6, P1, V3, V5, V6] # -్𑲓.്
+xn----x6e0220sclug.xn--wxc; -్𞾀𑲓.്; [B1, B3, B6, V3, V5, V6]; xn----x6e0220sclug.xn--wxc; ; ; # -్𑲓.്
+xn----x6e0220sclug.xn--wxc317g; -్𞾀𑲓.‍്; [B1, C2, V3, V6]; xn----x6e0220sclug.xn--wxc317g; ; ; # -్𑲓.്
+꙽‌霣🄆。‌𑁂ᬁ; ꙽‌霣🄆.‌𑁂ᬁ; [C1, P1, V5, V6]; xn--0ug4208b2vjuk63a.xn--4sf36u6u4w; ; xn--2q5a751a653w.xn--4sf0725i; [P1, V5, V6] # ꙽霣🄆.𑁂ᬁ
+꙽‌霣🄆。‌𑁂ᬁ; ꙽‌霣🄆.‌𑁂ᬁ; [C1, P1, V5, V6]; xn--0ug4208b2vjuk63a.xn--4sf36u6u4w; ; xn--2q5a751a653w.xn--4sf0725i; [P1, V5, V6] # ꙽霣🄆.𑁂ᬁ
+꙽‌霣5,。‌𑁂ᬁ; ꙽‌霣5,.‌𑁂ᬁ; [C1, P1, V5, V6]; xn--5,-i1tz135dnbqa.xn--4sf36u6u4w; ; xn--5,-op8g373c.xn--4sf0725i; [P1, V5, V6] # ꙽霣5,.𑁂ᬁ
+xn--5,-op8g373c.xn--4sf0725i; ꙽霣5,.𑁂ᬁ; [P1, V5, V6]; xn--5,-op8g373c.xn--4sf0725i; ; ; # ꙽霣5,.𑁂ᬁ
+xn--5,-i1tz135dnbqa.xn--4sf36u6u4w; ꙽‌霣5,.‌𑁂ᬁ; [C1, P1, V5, V6]; xn--5,-i1tz135dnbqa.xn--4sf36u6u4w; ; ; # ꙽霣5,.𑁂ᬁ
+xn--2q5a751a653w.xn--4sf0725i; ꙽霣🄆.𑁂ᬁ; [V5, V6]; xn--2q5a751a653w.xn--4sf0725i; ; ; # ꙽霣🄆.𑁂ᬁ
+xn--0ug4208b2vjuk63a.xn--4sf36u6u4w; ꙽‌霣🄆.‌𑁂ᬁ; [C1, V5, V6]; xn--0ug4208b2vjuk63a.xn--4sf36u6u4w; ; ; # ꙽霣🄆.𑁂ᬁ
+兎。ᠼ󠴜𑚶𑰿; 兎.ᠼ󠴜𑚶𑰿; [P1, V6]; xn--b5q.xn--v7e6041kqqd4m251b; ; ; # 兎.ᠼ𑚶𑰿
+兎。ᠼ󠴜𑚶𑰿; 兎.ᠼ󠴜𑚶𑰿; [P1, V6]; xn--b5q.xn--v7e6041kqqd4m251b; ; ; # 兎.ᠼ𑚶𑰿
+xn--b5q.xn--v7e6041kqqd4m251b; 兎.ᠼ󠴜𑚶𑰿; [V6]; xn--b5q.xn--v7e6041kqqd4m251b; ; ; # 兎.ᠼ𑚶𑰿
+𝟙。‍𝟸‍⁷; 1.‍2‍7; [C2]; 1.xn--27-l1tb; ; 1.27; [] # 1.27
+1。‍2‍7; 1.‍2‍7; [C2]; 1.xn--27-l1tb; ; 1.27; [] # 1.27
+1.27; ; ; ; ; ; # 1.27
+1.xn--27-l1tb; 1.‍2‍7; [C2]; 1.xn--27-l1tb; ; ; # 1.27
+ᡨ-。󠻋𝟷; ᡨ-.󠻋1; [P1, V3, V6]; xn----z8j.xn--1-5671m; ; ; # ᡨ-.1
+ᡨ-。󠻋1; ᡨ-.󠻋1; [P1, V3, V6]; xn----z8j.xn--1-5671m; ; ; # ᡨ-.1
+xn----z8j.xn--1-5671m; ᡨ-.󠻋1; [V3, V6]; xn----z8j.xn--1-5671m; ; ; # ᡨ-.1
+𑰻񵀐𐫚.٨⁹; 𑰻񵀐𐫚.٨9; [B1, P1, V5, V6]; xn--gx9cr01aul57i.xn--9-oqc; ; ; # 𑰻𐫚.٨9
+𑰻񵀐𐫚.٨9; ; [B1, P1, V5, V6]; xn--gx9cr01aul57i.xn--9-oqc; ; ; # 𑰻𐫚.٨9
+xn--gx9cr01aul57i.xn--9-oqc; 𑰻񵀐𐫚.٨9; [B1, V5, V6]; xn--gx9cr01aul57i.xn--9-oqc; ; ; # 𑰻𐫚.٨9
+Ⴜ򈷭ྀ⾇。Ⴏ♀‌‌; Ⴜ򈷭ྀ舛.Ⴏ♀‌‌; [C1, P1, V6]; xn--zed54dz10wo343g.xn--nnd089ea464d; ; xn--zed54dz10wo343g.xn--nnd651i; [P1, V6] # Ⴜྀ舛.Ⴏ♀
+Ⴜ򈷭ྀ舛。Ⴏ♀‌‌; Ⴜ򈷭ྀ舛.Ⴏ♀‌‌; [C1, P1, V6]; xn--zed54dz10wo343g.xn--nnd089ea464d; ; xn--zed54dz10wo343g.xn--nnd651i; [P1, V6] # Ⴜྀ舛.Ⴏ♀
+ⴜ򈷭ྀ舛。ⴏ♀‌‌; ⴜ򈷭ྀ舛.ⴏ♀‌‌; [C1, P1, V6]; xn--zed372mdj2do3v4h.xn--0uga678bgyh; ; xn--zed372mdj2do3v4h.xn--e5h11w; [P1, V6] # ⴜྀ舛.ⴏ♀
+xn--zed372mdj2do3v4h.xn--e5h11w; ⴜ򈷭ྀ舛.ⴏ♀; [V6]; xn--zed372mdj2do3v4h.xn--e5h11w; ; ; # ⴜྀ舛.ⴏ♀
+xn--zed372mdj2do3v4h.xn--0uga678bgyh; ⴜ򈷭ྀ舛.ⴏ♀‌‌; [C1, V6]; xn--zed372mdj2do3v4h.xn--0uga678bgyh; ; ; # ⴜྀ舛.ⴏ♀
+xn--zed54dz10wo343g.xn--nnd651i; Ⴜ򈷭ྀ舛.Ⴏ♀; [V6]; xn--zed54dz10wo343g.xn--nnd651i; ; ; # Ⴜྀ舛.Ⴏ♀
+xn--zed54dz10wo343g.xn--nnd089ea464d; Ⴜ򈷭ྀ舛.Ⴏ♀‌‌; [C1, V6]; xn--zed54dz10wo343g.xn--nnd089ea464d; ; ; # Ⴜྀ舛.Ⴏ♀
+ⴜ򈷭ྀ⾇。ⴏ♀‌‌; ⴜ򈷭ྀ舛.ⴏ♀‌‌; [C1, P1, V6]; xn--zed372mdj2do3v4h.xn--0uga678bgyh; ; xn--zed372mdj2do3v4h.xn--e5h11w; [P1, V6] # ⴜྀ舛.ⴏ♀
+𑁆𝟰.‍; 𑁆4.‍; [C2, V5]; xn--4-xu7i.xn--1ug; ; xn--4-xu7i.; [V5] # 𑁆4.
+𑁆4.‍; ; [C2, V5]; xn--4-xu7i.xn--1ug; ; xn--4-xu7i.; [V5] # 𑁆4.
+xn--4-xu7i.; 𑁆4.; [V5]; xn--4-xu7i.; ; ; # 𑁆4.
+xn--4-xu7i.xn--1ug; 𑁆4.‍; [C2, V5]; xn--4-xu7i.xn--1ug; ; ; # 𑁆4.
+񮴘Ⴞ癀。𑘿‍‌붼; 񮴘Ⴞ癀.𑘿‍‌붼; [C1, P1, V5, V6]; xn--2nd6803c7q37d.xn--0ugb6122js83c; ; xn--2nd6803c7q37d.xn--et3bn23n; [P1, V5, V6] # Ⴞ癀.𑘿붼
+񮴘Ⴞ癀。𑘿‍‌붼; 񮴘Ⴞ癀.𑘿‍‌붼; [C1, P1, V5, V6]; xn--2nd6803c7q37d.xn--0ugb6122js83c; ; xn--2nd6803c7q37d.xn--et3bn23n; [P1, V5, V6] # Ⴞ癀.𑘿붼
+񮴘Ⴞ癀。𑘿‍‌붼; 񮴘Ⴞ癀.𑘿‍‌붼; [C1, P1, V5, V6]; xn--2nd6803c7q37d.xn--0ugb6122js83c; ; xn--2nd6803c7q37d.xn--et3bn23n; [P1, V5, V6] # Ⴞ癀.𑘿붼
+񮴘Ⴞ癀。𑘿‍‌붼; 񮴘Ⴞ癀.𑘿‍‌붼; [C1, P1, V5, V6]; xn--2nd6803c7q37d.xn--0ugb6122js83c; ; xn--2nd6803c7q37d.xn--et3bn23n; [P1, V5, V6] # Ⴞ癀.𑘿붼
+񮴘ⴞ癀。𑘿‍‌붼; 񮴘ⴞ癀.𑘿‍‌붼; [C1, P1, V5, V6]; xn--mlju35u7qx2f.xn--0ugb6122js83c; ; xn--mlju35u7qx2f.xn--et3bn23n; [P1, V5, V6] # ⴞ癀.𑘿붼
+񮴘ⴞ癀。𑘿‍‌붼; 񮴘ⴞ癀.𑘿‍‌붼; [C1, P1, V5, V6]; xn--mlju35u7qx2f.xn--0ugb6122js83c; ; xn--mlju35u7qx2f.xn--et3bn23n; [P1, V5, V6] # ⴞ癀.𑘿붼
+xn--mlju35u7qx2f.xn--et3bn23n; 񮴘ⴞ癀.𑘿붼; [V5, V6]; xn--mlju35u7qx2f.xn--et3bn23n; ; ; # ⴞ癀.𑘿붼
+xn--mlju35u7qx2f.xn--0ugb6122js83c; 񮴘ⴞ癀.𑘿‍‌붼; [C1, V5, V6]; xn--mlju35u7qx2f.xn--0ugb6122js83c; ; ; # ⴞ癀.𑘿붼
+xn--2nd6803c7q37d.xn--et3bn23n; 񮴘Ⴞ癀.𑘿붼; [V5, V6]; xn--2nd6803c7q37d.xn--et3bn23n; ; ; # Ⴞ癀.𑘿붼
+xn--2nd6803c7q37d.xn--0ugb6122js83c; 񮴘Ⴞ癀.𑘿‍‌붼; [C1, V5, V6]; xn--2nd6803c7q37d.xn--0ugb6122js83c; ; ; # Ⴞ癀.𑘿붼
+񮴘ⴞ癀。𑘿‍‌붼; 񮴘ⴞ癀.𑘿‍‌붼; [C1, P1, V5, V6]; xn--mlju35u7qx2f.xn--0ugb6122js83c; ; xn--mlju35u7qx2f.xn--et3bn23n; [P1, V5, V6] # ⴞ癀.𑘿붼
+񮴘ⴞ癀。𑘿‍‌붼; 񮴘ⴞ癀.𑘿‍‌붼; [C1, P1, V5, V6]; xn--mlju35u7qx2f.xn--0ugb6122js83c; ; xn--mlju35u7qx2f.xn--et3bn23n; [P1, V5, V6] # ⴞ癀.𑘿붼
+󚀅-்。ڹ; 󚀅-்.ڹ; [B6, P1, V6]; xn----mze84808x.xn--skb; ; ; # -்.ڹ
+xn----mze84808x.xn--skb; 󚀅-்.ڹ; [B6, V6]; xn----mze84808x.xn--skb; ; ; # -்.ڹ
+ᡃ𝟧≯ᠣ.氁񨏱ꁫ; ᡃ5≯ᠣ.氁񨏱ꁫ; [P1, V6]; xn--5-24jyf768b.xn--lqw213ime95g; ; ; # ᡃ5≯ᠣ.氁ꁫ
+ᡃ𝟧≯ᠣ.氁񨏱ꁫ; ᡃ5≯ᠣ.氁񨏱ꁫ; [P1, V6]; xn--5-24jyf768b.xn--lqw213ime95g; ; ; # ᡃ5≯ᠣ.氁ꁫ
+ᡃ5≯ᠣ.氁񨏱ꁫ; ; [P1, V6]; xn--5-24jyf768b.xn--lqw213ime95g; ; ; # ᡃ5≯ᠣ.氁ꁫ
+ᡃ5≯ᠣ.氁񨏱ꁫ; ᡃ5≯ᠣ.氁񨏱ꁫ; [P1, V6]; xn--5-24jyf768b.xn--lqw213ime95g; ; ; # ᡃ5≯ᠣ.氁ꁫ
+xn--5-24jyf768b.xn--lqw213ime95g; ᡃ5≯ᠣ.氁񨏱ꁫ; [V6]; xn--5-24jyf768b.xn--lqw213ime95g; ; ; # ᡃ5≯ᠣ.氁ꁫ
+𐹬𝩇.ྲྀ; 𐹬𝩇.ྲྀ; [B1, B3, B6, V5]; xn--ko0d8295a.xn--zed3h; ; ; # 𐹬𝩇.ྲྀ
+𐹬𝩇.ྲྀ; 𐹬𝩇.ྲྀ; [B1, B3, B6, V5]; xn--ko0d8295a.xn--zed3h; ; ; # 𐹬𝩇.ྲྀ
+𐹬𝩇.ྲྀ; ; [B1, B3, B6, V5]; xn--ko0d8295a.xn--zed3h; ; ; # 𐹬𝩇.ྲྀ
+xn--ko0d8295a.xn--zed3h; 𐹬𝩇.ྲྀ; [B1, B3, B6, V5]; xn--ko0d8295a.xn--zed3h; ; ; # 𐹬𝩇.ྲྀ
+-𑈶⒏.⒎𰛢󠎭; -𑈶⒏.⒎𰛢󠎭; [P1, V3, V6]; xn----scp6252h.xn--zshy411yzpx2d; ; ; # -𑈶⒏.⒎𰛢
+-𑈶8..7.𰛢󠎭; ; [P1, V3, V6, X4_2]; xn---8-bv5o..7.xn--c35nf1622b; [P1, V3, V6, A4_2]; ; # -𑈶8..7.𰛢
+xn---8-bv5o..7.xn--c35nf1622b; -𑈶8..7.𰛢󠎭; [V3, V6, X4_2]; xn---8-bv5o..7.xn--c35nf1622b; [V3, V6, A4_2]; ; # -𑈶8..7.𰛢
+xn----scp6252h.xn--zshy411yzpx2d; -𑈶⒏.⒎𰛢󠎭; [V3, V6]; xn----scp6252h.xn--zshy411yzpx2d; ; ; # -𑈶⒏.⒎𰛢
+‌Ⴁ畝‍.≮; ‌Ⴁ畝‍.≮; [C1, C2, P1, V6]; xn--8md700fea3748f.xn--gdh; ; xn--8md0962c.xn--gdh; [P1, V6] # Ⴁ畝.≮
+‌Ⴁ畝‍.≮; ‌Ⴁ畝‍.≮; [C1, C2, P1, V6]; xn--8md700fea3748f.xn--gdh; ; xn--8md0962c.xn--gdh; [P1, V6] # Ⴁ畝.≮
+‌Ⴁ畝‍.≮; ; [C1, C2, P1, V6]; xn--8md700fea3748f.xn--gdh; ; xn--8md0962c.xn--gdh; [P1, V6] # Ⴁ畝.≮
+‌Ⴁ畝‍.≮; ‌Ⴁ畝‍.≮; [C1, C2, P1, V6]; xn--8md700fea3748f.xn--gdh; ; xn--8md0962c.xn--gdh; [P1, V6] # Ⴁ畝.≮
+‌ⴁ畝‍.≮; ‌ⴁ畝‍.≮; [C1, C2, P1, V6]; xn--0ugc160hb36e.xn--gdh; ; xn--skjy82u.xn--gdh; [P1, V6] # ⴁ畝.≮
+‌ⴁ畝‍.≮; ; [C1, C2, P1, V6]; xn--0ugc160hb36e.xn--gdh; ; xn--skjy82u.xn--gdh; [P1, V6] # ⴁ畝.≮
+xn--skjy82u.xn--gdh; ⴁ畝.≮; [V6]; xn--skjy82u.xn--gdh; ; ; # ⴁ畝.≮
+xn--0ugc160hb36e.xn--gdh; ‌ⴁ畝‍.≮; [C1, C2, V6]; xn--0ugc160hb36e.xn--gdh; ; ; # ⴁ畝.≮
+xn--8md0962c.xn--gdh; Ⴁ畝.≮; [V6]; xn--8md0962c.xn--gdh; ; ; # Ⴁ畝.≮
+xn--8md700fea3748f.xn--gdh; ‌Ⴁ畝‍.≮; [C1, C2, V6]; xn--8md700fea3748f.xn--gdh; ; ; # Ⴁ畝.≮
+‌ⴁ畝‍.≮; ‌ⴁ畝‍.≮; [C1, C2, P1, V6]; xn--0ugc160hb36e.xn--gdh; ; xn--skjy82u.xn--gdh; [P1, V6] # ⴁ畝.≮
+‌ⴁ畝‍.≮; ‌ⴁ畝‍.≮; [C1, C2, P1, V6]; xn--0ugc160hb36e.xn--gdh; ; xn--skjy82u.xn--gdh; [P1, V6] # ⴁ畝.≮
+歷。𐹻≯󳛽‍; 歷.𐹻≯󳛽‍; [B1, C2, P1, V6]; xn--nmw.xn--1ugx6gs128a1134j; ; xn--nmw.xn--hdh7804gdms2h; [B1, P1, V6] # 歷.𐹻≯
+歷。𐹻≯󳛽‍; 歷.𐹻≯󳛽‍; [B1, C2, P1, V6]; xn--nmw.xn--1ugx6gs128a1134j; ; xn--nmw.xn--hdh7804gdms2h; [B1, P1, V6] # 歷.𐹻≯
+歷。𐹻≯󳛽‍; 歷.𐹻≯󳛽‍; [B1, C2, P1, V6]; xn--nmw.xn--1ugx6gs128a1134j; ; xn--nmw.xn--hdh7804gdms2h; [B1, P1, V6] # 歷.𐹻≯
+歷。𐹻≯󳛽‍; 歷.𐹻≯󳛽‍; [B1, C2, P1, V6]; xn--nmw.xn--1ugx6gs128a1134j; ; xn--nmw.xn--hdh7804gdms2h; [B1, P1, V6] # 歷.𐹻≯
+xn--nmw.xn--hdh7804gdms2h; 歷.𐹻≯󳛽; [B1, V6]; xn--nmw.xn--hdh7804gdms2h; ; ; # 歷.𐹻≯
+xn--nmw.xn--1ugx6gs128a1134j; 歷.𐹻≯󳛽‍; [B1, C2, V6]; xn--nmw.xn--1ugx6gs128a1134j; ; ; # 歷.𐹻≯
+໋‍.鎁󠰑; ໋‍.鎁󠰑; [C2, P1, V5, V6]; xn--t8c059f.xn--iz4a43209d; ; xn--t8c.xn--iz4a43209d; [P1, V5, V6] # ໋.鎁
+໋‍.鎁󠰑; ; [C2, P1, V5, V6]; xn--t8c059f.xn--iz4a43209d; ; xn--t8c.xn--iz4a43209d; [P1, V5, V6] # ໋.鎁
+xn--t8c.xn--iz4a43209d; ໋.鎁󠰑; [V5, V6]; xn--t8c.xn--iz4a43209d; ; ; # ໋.鎁
+xn--t8c059f.xn--iz4a43209d; ໋‍.鎁󠰑; [C2, V5, V6]; xn--t8c059f.xn--iz4a43209d; ; ; # ໋.鎁
+‍‌𞤀。𱘅𐶃; ‍‌𞤢.𱘅𐶃; [B1, B5, B6, C1, C2, P1, V6]; xn--0ugb45126a.xn--wh0dj799f; ; xn--9d6h.xn--wh0dj799f; [B5, B6, P1, V6] # 𞤢.
+‍‌𞤀。𱘅𐶃; ‍‌𞤢.𱘅𐶃; [B1, B5, B6, C1, C2, P1, V6]; xn--0ugb45126a.xn--wh0dj799f; ; xn--9d6h.xn--wh0dj799f; [B5, B6, P1, V6] # 𞤢.
+‍‌𞤢。𱘅𐶃; ‍‌𞤢.𱘅𐶃; [B1, B5, B6, C1, C2, P1, V6]; xn--0ugb45126a.xn--wh0dj799f; ; xn--9d6h.xn--wh0dj799f; [B5, B6, P1, V6] # 𞤢.
+xn--9d6h.xn--wh0dj799f; 𞤢.𱘅𐶃; [B5, B6, V6]; xn--9d6h.xn--wh0dj799f; ; ; # 𞤢.
+xn--0ugb45126a.xn--wh0dj799f; ‍‌𞤢.𱘅𐶃; [B1, B5, B6, C1, C2, V6]; xn--0ugb45126a.xn--wh0dj799f; ; ; # 𞤢.
+‍‌𞤢。𱘅𐶃; ‍‌𞤢.𱘅𐶃; [B1, B5, B6, C1, C2, P1, V6]; xn--0ugb45126a.xn--wh0dj799f; ; xn--9d6h.xn--wh0dj799f; [B5, B6, P1, V6] # 𞤢.
+ب≠𝟫-.ς⒍𐹦≠; ب≠9-.ς⒍𐹦≠; [B3, B5, B6, P1, V3, V6]; xn--9--etd0100a.xn--3xa097mzpbzz04b; ; xn--9--etd0100a.xn--4xa887mzpbzz04b; # ب≠9-.ς⒍𐹦≠
+ب≠𝟫-.ς⒍𐹦≠; ب≠9-.ς⒍𐹦≠; [B3, B5, B6, P1, V3, V6]; xn--9--etd0100a.xn--3xa097mzpbzz04b; ; xn--9--etd0100a.xn--4xa887mzpbzz04b; # ب≠9-.ς⒍𐹦≠
+ب≠9-.ς6.𐹦≠; ; [B1, B3, P1, V3, V6]; xn--9--etd0100a.xn--6-xmb.xn--1ch8704g; ; xn--9--etd0100a.xn--6-zmb.xn--1ch8704g; # ب≠9-.ς6.𐹦≠
+ب≠9-.ς6.𐹦≠; ب≠9-.ς6.𐹦≠; [B1, B3, P1, V3, V6]; xn--9--etd0100a.xn--6-xmb.xn--1ch8704g; ; xn--9--etd0100a.xn--6-zmb.xn--1ch8704g; # ب≠9-.ς6.𐹦≠
+ب≠9-.Σ6.𐹦≠; ب≠9-.σ6.𐹦≠; [B1, B3, P1, V3, V6]; xn--9--etd0100a.xn--6-zmb.xn--1ch8704g; ; ; # ب≠9-.σ6.𐹦≠
+ب≠9-.Σ6.𐹦≠; ب≠9-.σ6.𐹦≠; [B1, B3, P1, V3, V6]; xn--9--etd0100a.xn--6-zmb.xn--1ch8704g; ; ; # ب≠9-.σ6.𐹦≠
+ب≠9-.σ6.𐹦≠; ; [B1, B3, P1, V3, V6]; xn--9--etd0100a.xn--6-zmb.xn--1ch8704g; ; ; # ب≠9-.σ6.𐹦≠
+ب≠9-.σ6.𐹦≠; ب≠9-.σ6.𐹦≠; [B1, B3, P1, V3, V6]; xn--9--etd0100a.xn--6-zmb.xn--1ch8704g; ; ; # ب≠9-.σ6.𐹦≠
+xn--9--etd0100a.xn--6-zmb.xn--1ch8704g; ب≠9-.σ6.𐹦≠; [B1, B3, V3, V6]; xn--9--etd0100a.xn--6-zmb.xn--1ch8704g; ; ; # ب≠9-.σ6.𐹦≠
+xn--9--etd0100a.xn--6-xmb.xn--1ch8704g; ب≠9-.ς6.𐹦≠; [B1, B3, V3, V6]; xn--9--etd0100a.xn--6-xmb.xn--1ch8704g; ; ; # ب≠9-.ς6.𐹦≠
+ب≠𝟫-.Σ⒍𐹦≠; ب≠9-.σ⒍𐹦≠; [B3, B5, B6, P1, V3, V6]; xn--9--etd0100a.xn--4xa887mzpbzz04b; ; ; # ب≠9-.σ⒍𐹦≠
+ب≠𝟫-.Σ⒍𐹦≠; ب≠9-.σ⒍𐹦≠; [B3, B5, B6, P1, V3, V6]; xn--9--etd0100a.xn--4xa887mzpbzz04b; ; ; # ب≠9-.σ⒍𐹦≠
+ب≠𝟫-.σ⒍𐹦≠; ب≠9-.σ⒍𐹦≠; [B3, B5, B6, P1, V3, V6]; xn--9--etd0100a.xn--4xa887mzpbzz04b; ; ; # ب≠9-.σ⒍𐹦≠
+ب≠𝟫-.σ⒍𐹦≠; ب≠9-.σ⒍𐹦≠; [B3, B5, B6, P1, V3, V6]; xn--9--etd0100a.xn--4xa887mzpbzz04b; ; ; # ب≠9-.σ⒍𐹦≠
+xn--9--etd0100a.xn--4xa887mzpbzz04b; ب≠9-.σ⒍𐹦≠; [B3, B5, B6, V3, V6]; xn--9--etd0100a.xn--4xa887mzpbzz04b; ; ; # ب≠9-.σ⒍𐹦≠
+xn--9--etd0100a.xn--3xa097mzpbzz04b; ب≠9-.ς⒍𐹦≠; [B3, B5, B6, V3, V6]; xn--9--etd0100a.xn--3xa097mzpbzz04b; ; ; # ب≠9-.ς⒍𐹦≠
+򉛴.-ᡢ֒𝨠; ; [P1, V3, V6]; xn--ep37b.xn----hec165lho83b; ; ; # .-ᡢ֒𝨠
+xn--ep37b.xn----hec165lho83b; 򉛴.-ᡢ֒𝨠; [V3, V6]; xn--ep37b.xn----hec165lho83b; ; ; # .-ᡢ֒𝨠
+ۋ⒈ß󠄽。񷋍-; ۋ⒈ß.񷋍-; [B2, B3, B6, P1, V3, V6]; xn--zca541ato3a.xn----q001f; ; xn--ss-d7d6651a.xn----q001f; # ۋ⒈ß.-
+ۋ1.ß󠄽。񷋍-; ۋ1.ß.񷋍-; [B6, P1, V3, V6]; xn--1-cwc.xn--zca.xn----q001f; ; xn--1-cwc.ss.xn----q001f; # ۋ1.ß.-
+ۋ1.SS󠄽。񷋍-; ۋ1.ss.񷋍-; [B6, P1, V3, V6]; xn--1-cwc.ss.xn----q001f; ; ; # ۋ1.ss.-
+ۋ1.ss󠄽。񷋍-; ۋ1.ss.񷋍-; [B6, P1, V3, V6]; xn--1-cwc.ss.xn----q001f; ; ; # ۋ1.ss.-
+ۋ1.Ss󠄽。񷋍-; ۋ1.ss.񷋍-; [B6, P1, V3, V6]; xn--1-cwc.ss.xn----q001f; ; ; # ۋ1.ss.-
+xn--1-cwc.ss.xn----q001f; ۋ1.ss.񷋍-; [B6, V3, V6]; xn--1-cwc.ss.xn----q001f; ; ; # ۋ1.ss.-
+xn--1-cwc.xn--zca.xn----q001f; ۋ1.ß.񷋍-; [B6, V3, V6]; xn--1-cwc.xn--zca.xn----q001f; ; ; # ۋ1.ß.-
+ۋ⒈SS󠄽。񷋍-; ۋ⒈ss.񷋍-; [B2, B3, B6, P1, V3, V6]; xn--ss-d7d6651a.xn----q001f; ; ; # ۋ⒈ss.-
+ۋ⒈ss󠄽。񷋍-; ۋ⒈ss.񷋍-; [B2, B3, B6, P1, V3, V6]; xn--ss-d7d6651a.xn----q001f; ; ; # ۋ⒈ss.-
+ۋ⒈Ss󠄽。񷋍-; ۋ⒈ss.񷋍-; [B2, B3, B6, P1, V3, V6]; xn--ss-d7d6651a.xn----q001f; ; ; # ۋ⒈ss.-
+xn--ss-d7d6651a.xn----q001f; ۋ⒈ss.񷋍-; [B2, B3, B6, V3, V6]; xn--ss-d7d6651a.xn----q001f; ; ; # ۋ⒈ss.-
+xn--zca541ato3a.xn----q001f; ۋ⒈ß.񷋍-; [B2, B3, B6, V3, V6]; xn--zca541ato3a.xn----q001f; ; ; # ۋ⒈ß.-
+𿀫.᮪ςႦ‍; 𿀫.᮪ςႦ‍; [C2, P1, V5, V6]; xn--nu4s.xn--3xa417dxriome; ; xn--nu4s.xn--4xa217dxri; [P1, V5, V6] # .᮪ςႦ
+𿀫.᮪ςႦ‍; ; [C2, P1, V5, V6]; xn--nu4s.xn--3xa417dxriome; ; xn--nu4s.xn--4xa217dxri; [P1, V5, V6] # .᮪ςႦ
+𿀫.᮪ςⴆ‍; ; [C2, P1, V5, V6]; xn--nu4s.xn--3xa353jk8cs1q; ; xn--nu4s.xn--4xa153j7im; [P1, V5, V6] # .᮪ςⴆ
+𿀫.᮪ΣႦ‍; 𿀫.᮪σႦ‍; [C2, P1, V5, V6]; xn--nu4s.xn--4xa217dxriome; ; xn--nu4s.xn--4xa217dxri; [P1, V5, V6] # .᮪σႦ
+𿀫.᮪σⴆ‍; ; [C2, P1, V5, V6]; xn--nu4s.xn--4xa153jk8cs1q; ; xn--nu4s.xn--4xa153j7im; [P1, V5, V6] # .᮪σⴆ
+𿀫.᮪Σⴆ‍; 𿀫.᮪σⴆ‍; [C2, P1, V5, V6]; xn--nu4s.xn--4xa153jk8cs1q; ; xn--nu4s.xn--4xa153j7im; [P1, V5, V6] # .᮪σⴆ
+xn--nu4s.xn--4xa153j7im; 𿀫.᮪σⴆ; [V5, V6]; xn--nu4s.xn--4xa153j7im; ; ; # .᮪σⴆ
+xn--nu4s.xn--4xa153jk8cs1q; 𿀫.᮪σⴆ‍; [C2, V5, V6]; xn--nu4s.xn--4xa153jk8cs1q; ; ; # .᮪σⴆ
+xn--nu4s.xn--4xa217dxri; 𿀫.᮪σႦ; [V5, V6]; xn--nu4s.xn--4xa217dxri; ; ; # .᮪σႦ
+xn--nu4s.xn--4xa217dxriome; 𿀫.᮪σႦ‍; [C2, V5, V6]; xn--nu4s.xn--4xa217dxriome; ; ; # .᮪σႦ
+xn--nu4s.xn--3xa353jk8cs1q; 𿀫.᮪ςⴆ‍; [C2, V5, V6]; xn--nu4s.xn--3xa353jk8cs1q; ; ; # .᮪ςⴆ
+xn--nu4s.xn--3xa417dxriome; 𿀫.᮪ςႦ‍; [C2, V5, V6]; xn--nu4s.xn--3xa417dxriome; ; ; # .᮪ςႦ
+𿀫.᮪ςⴆ‍; 𿀫.᮪ςⴆ‍; [C2, P1, V5, V6]; xn--nu4s.xn--3xa353jk8cs1q; ; xn--nu4s.xn--4xa153j7im; [P1, V5, V6] # .᮪ςⴆ
+𿀫.᮪ΣႦ‍; 𿀫.᮪σႦ‍; [C2, P1, V5, V6]; xn--nu4s.xn--4xa217dxriome; ; xn--nu4s.xn--4xa217dxri; [P1, V5, V6] # .᮪σႦ
+𿀫.᮪σⴆ‍; 𿀫.᮪σⴆ‍; [C2, P1, V5, V6]; xn--nu4s.xn--4xa153jk8cs1q; ; xn--nu4s.xn--4xa153j7im; [P1, V5, V6] # .᮪σⴆ
+𿀫.᮪Σⴆ‍; 𿀫.᮪σⴆ‍; [C2, P1, V5, V6]; xn--nu4s.xn--4xa153jk8cs1q; ; xn--nu4s.xn--4xa153j7im; [P1, V5, V6] # .᮪σⴆ
+⾆࣢.𝈴; 舌࣢.𝈴; [B1, B5, B6, P1, V6]; xn--l0b9413d.xn--kl1h; ; ; # 舌.𝈴
+舌࣢.𝈴; ; [B1, B5, B6, P1, V6]; xn--l0b9413d.xn--kl1h; ; ; # 舌.𝈴
+xn--l0b9413d.xn--kl1h; 舌࣢.𝈴; [B1, B5, B6, V6]; xn--l0b9413d.xn--kl1h; ; ; # 舌.𝈴
+⫞𐹶𖫴。⭠⒈; ⫞𐹶𖫴.⭠⒈; [B1, P1, V6]; xn--53ix188et88b.xn--tsh52w; ; ; # ⫞𐹶𖫴.⭠⒈
+⫞𐹶𖫴。⭠1.; ⫞𐹶𖫴.⭠1.; [B1]; xn--53ix188et88b.xn--1-h6r.; ; ; # ⫞𐹶𖫴.⭠1.
+xn--53ix188et88b.xn--1-h6r.; ⫞𐹶𖫴.⭠1.; [B1]; xn--53ix188et88b.xn--1-h6r.; ; ; # ⫞𐹶𖫴.⭠1.
+xn--53ix188et88b.xn--tsh52w; ⫞𐹶𖫴.⭠⒈; [B1, V6]; xn--53ix188et88b.xn--tsh52w; ; ; # ⫞𐹶𖫴.⭠⒈
+⒈‌ꫬ︒.્; ⒈‌ꫬ︒.્; [C1, P1, V5, V6]; xn--0ug78o720myr1c.xn--mfc; ; xn--tsh0720cse8b.xn--mfc; [P1, V5, V6] # ⒈ꫬ︒.્
+1.‌ꫬ。.્; 1.‌ꫬ..્; [C1, V5, X4_2]; 1.xn--0ug7185c..xn--mfc; [C1, V5, A4_2]; 1.xn--sv9a..xn--mfc; [V5, A4_2] # 1.ꫬ..્
+1.xn--sv9a..xn--mfc; 1.ꫬ..્; [V5, X4_2]; 1.xn--sv9a..xn--mfc; [V5, A4_2]; ; # 1.ꫬ..્
+1.xn--0ug7185c..xn--mfc; 1.‌ꫬ..્; [C1, V5, X4_2]; 1.xn--0ug7185c..xn--mfc; [C1, V5, A4_2]; ; # 1.ꫬ..્
+xn--tsh0720cse8b.xn--mfc; ⒈ꫬ︒.્; [V5, V6]; xn--tsh0720cse8b.xn--mfc; ; ; # ⒈ꫬ︒.્
+xn--0ug78o720myr1c.xn--mfc; ⒈‌ꫬ︒.્; [C1, V5, V6]; xn--0ug78o720myr1c.xn--mfc; ; ; # ⒈ꫬ︒.્
+ె。䰀٨𞭅󠅼; ె.䰀٨𞭅; [B1, B3, B5, B6, P1, V5, V6]; xn--eqc.xn--hib5476aim6t; ; ; # ె.䰀٨
+xn--eqc.xn--hib5476aim6t; ె.䰀٨𞭅; [B1, B3, B5, B6, V5, V6]; xn--eqc.xn--hib5476aim6t; ; ; # ె.䰀٨
+ß‍.᯲񄾼; ; [C2, P1, V5, V6]; xn--zca870n.xn--0zf22107b; ; ss.xn--0zf22107b; [P1, V5, V6] # ß.᯲
+SS‍.᯲񄾼; ss‍.᯲񄾼; [C2, P1, V5, V6]; xn--ss-n1t.xn--0zf22107b; ; ss.xn--0zf22107b; [P1, V5, V6] # ss.᯲
+ss‍.᯲񄾼; ; [C2, P1, V5, V6]; xn--ss-n1t.xn--0zf22107b; ; ss.xn--0zf22107b; [P1, V5, V6] # ss.᯲
+Ss‍.᯲񄾼; ss‍.᯲񄾼; [C2, P1, V5, V6]; xn--ss-n1t.xn--0zf22107b; ; ss.xn--0zf22107b; [P1, V5, V6] # ss.᯲
+ss.xn--0zf22107b; ss.᯲񄾼; [V5, V6]; ss.xn--0zf22107b; ; ; # ss.᯲
+xn--ss-n1t.xn--0zf22107b; ss‍.᯲񄾼; [C2, V5, V6]; xn--ss-n1t.xn--0zf22107b; ; ; # ss.᯲
+xn--zca870n.xn--0zf22107b; ß‍.᯲񄾼; [C2, V5, V6]; xn--zca870n.xn--0zf22107b; ; ; # ß.᯲
+𑓂‌≮.≮; ; [P1, V5, V6]; xn--0ugy6glz29a.xn--gdh; ; xn--gdhz656g.xn--gdh; # 𑓂≮.≮
+𑓂‌≮.≮; 𑓂‌≮.≮; [P1, V5, V6]; xn--0ugy6glz29a.xn--gdh; ; xn--gdhz656g.xn--gdh; # 𑓂≮.≮
+xn--gdhz656g.xn--gdh; 𑓂≮.≮; [V5, V6]; xn--gdhz656g.xn--gdh; ; ; # 𑓂≮.≮
+xn--0ugy6glz29a.xn--gdh; 𑓂‌≮.≮; [V5, V6]; xn--0ugy6glz29a.xn--gdh; ; ; # 𑓂≮.≮
+🕼.ᅠ; 🕼.ᅠ; [P1, V6]; xn--my8h.xn--cl7c; ; ; # 🕼.
+🕼.ᅠ; ; [P1, V6]; xn--my8h.xn--psd; ; ; # 🕼.
+xn--my8h.xn--psd; 🕼.ᅠ; [V6]; xn--my8h.xn--psd; ; ; # 🕼.
+xn--my8h.xn--cl7c; 🕼.ᅠ; [V6]; xn--my8h.xn--cl7c; ; ; # 🕼.
+ᡔﶂ。񷘎; ᡔلحى.񷘎; [B5, B6, P1, V6]; xn--sgb9bq785p.xn--bc31b; ; ; # ᡔلحى.
+ᡔلحى。񷘎; ᡔلحى.񷘎; [B5, B6, P1, V6]; xn--sgb9bq785p.xn--bc31b; ; ; # ᡔلحى.
+xn--sgb9bq785p.xn--bc31b; ᡔلحى.񷘎; [B5, B6, V6]; xn--sgb9bq785p.xn--bc31b; ; ; # ᡔلحى.
+爕򳙑.𝟰気; 爕򳙑.4気; [P1, V6]; xn--1zxq3199c.xn--4-678b; ; ; # 爕.4気
+爕򳙑.4気; ; [P1, V6]; xn--1zxq3199c.xn--4-678b; ; ; # 爕.4気
+xn--1zxq3199c.xn--4-678b; 爕򳙑.4気; [V6]; xn--1zxq3199c.xn--4-678b; ; ; # 爕.4気
+⒋𑍍Ⴝ-.𞬪්ֵ; ⒋𑍍Ⴝ-.𞬪්ֵ; [B1, P1, V3, V6]; xn----t1g323mnk9t.xn--ddb152b7y23b; ; ; # ⒋𑍍Ⴝ-.්ֵ
+4.𑍍Ⴝ-.𞬪්ֵ; ; [B1, B6, P1, V3, V5, V6]; 4.xn----t1g9869q.xn--ddb152b7y23b; ; ; # 4.𑍍Ⴝ-.්ֵ
+4.𑍍ⴝ-.𞬪්ֵ; ; [B1, B6, P1, V3, V5, V6]; 4.xn----wwsx259f.xn--ddb152b7y23b; ; ; # 4.𑍍ⴝ-.්ֵ
+4.xn----wwsx259f.xn--ddb152b7y23b; 4.𑍍ⴝ-.𞬪්ֵ; [B1, B6, V3, V5, V6]; 4.xn----wwsx259f.xn--ddb152b7y23b; ; ; # 4.𑍍ⴝ-.්ֵ
+4.xn----t1g9869q.xn--ddb152b7y23b; 4.𑍍Ⴝ-.𞬪්ֵ; [B1, B6, V3, V5, V6]; 4.xn----t1g9869q.xn--ddb152b7y23b; ; ; # 4.𑍍Ⴝ-.්ֵ
+⒋𑍍ⴝ-.𞬪්ֵ; ⒋𑍍ⴝ-.𞬪්ֵ; [B1, P1, V3, V6]; xn----jcp487avl3w.xn--ddb152b7y23b; ; ; # ⒋𑍍ⴝ-.්ֵ
+xn----jcp487avl3w.xn--ddb152b7y23b; ⒋𑍍ⴝ-.𞬪්ֵ; [B1, V3, V6]; xn----jcp487avl3w.xn--ddb152b7y23b; ; ; # ⒋𑍍ⴝ-.්ֵ
+xn----t1g323mnk9t.xn--ddb152b7y23b; ⒋𑍍Ⴝ-.𞬪්ֵ; [B1, V3, V6]; xn----t1g323mnk9t.xn--ddb152b7y23b; ; ; # ⒋𑍍Ⴝ-.්ֵ
+󞝃。򑆃񉢗--; 󞝃.򑆃񉢗--; [P1, V2, V3, V6]; xn--2y75e.xn-----1l15eer88n; ; ; # .--
+xn--2y75e.xn-----1l15eer88n; 󞝃.򑆃񉢗--; [V2, V3, V6]; xn--2y75e.xn-----1l15eer88n; ; ; # .--
+‍ߟ。‌꯭; ‍ߟ.‌꯭; [B1, C1, C2]; xn--6sb394j.xn--0ug1126c; ; xn--6sb.xn--429a; [B1, B3, B6, V5] # ߟ.꯭
+‍ߟ。‌꯭; ‍ߟ.‌꯭; [B1, C1, C2]; xn--6sb394j.xn--0ug1126c; ; xn--6sb.xn--429a; [B1, B3, B6, V5] # ߟ.꯭
+xn--6sb.xn--429a; ߟ.꯭; [B1, B3, B6, V5]; xn--6sb.xn--429a; ; ; # ߟ.꯭
+xn--6sb394j.xn--0ug1126c; ‍ߟ.‌꯭; [B1, C1, C2]; xn--6sb394j.xn--0ug1126c; ; ; # ߟ.꯭
+𞮽߿ࡎ。ᢍ򝹁𐫘; 𞮽߿ࡎ.ᢍ򝹁𐫘; [B5, B6, P1, V6]; xn--3tb2nz468k.xn--69e8615j5rn5d; ; ; # ߿ࡎ.ᢍ𐫘
+𞮽߿ࡎ。ᢍ򝹁𐫘; 𞮽߿ࡎ.ᢍ򝹁𐫘; [B5, B6, P1, V6]; xn--3tb2nz468k.xn--69e8615j5rn5d; ; ; # ߿ࡎ.ᢍ𐫘
+xn--3tb2nz468k.xn--69e8615j5rn5d; 𞮽߿ࡎ.ᢍ򝹁𐫘; [B5, B6, V6]; xn--3tb2nz468k.xn--69e8615j5rn5d; ; ; # ߿ࡎ.ᢍ𐫘
+ۭ𞺌𑄚᜔.ꡞࢷ; ۭم𑄚᜔.ꡞࢷ; [B1, B5, B6, V5]; xn--hhb94ag41b739u.xn--dzb5582f; ; ; # ۭم𑄚᜔.ꡞࢷ
+ۭم𑄚᜔.ꡞࢷ; ; [B1, B5, B6, V5]; xn--hhb94ag41b739u.xn--dzb5582f; ; ; # ۭم𑄚᜔.ꡞࢷ
+xn--hhb94ag41b739u.xn--dzb5582f; ۭم𑄚᜔.ꡞࢷ; [B1, B5, B6, V5]; xn--hhb94ag41b739u.xn--dzb5582f; ; ; # ۭم𑄚᜔.ꡞࢷ
+񻂵킃𑘶ߜ。ςؼς; 񻂵킃𑘶ߜ.ςؼς; [B5, B6, P1, V6]; xn--3sb7483hoyvbbe76g.xn--3xaa51q; ; xn--3sb7483hoyvbbe76g.xn--4xaa21q; # 킃𑘶ߜ.ςؼς
+񻂵킃𑘶ߜ。ςؼς; 񻂵킃𑘶ߜ.ςؼς; [B5, B6, P1, V6]; xn--3sb7483hoyvbbe76g.xn--3xaa51q; ; xn--3sb7483hoyvbbe76g.xn--4xaa21q; # 킃𑘶ߜ.ςؼς
+񻂵킃𑘶ߜ。ςؼς; 񻂵킃𑘶ߜ.ςؼς; [B5, B6, P1, V6]; xn--3sb7483hoyvbbe76g.xn--3xaa51q; ; xn--3sb7483hoyvbbe76g.xn--4xaa21q; # 킃𑘶ߜ.ςؼς
+񻂵킃𑘶ߜ。ςؼς; 񻂵킃𑘶ߜ.ςؼς; [B5, B6, P1, V6]; xn--3sb7483hoyvbbe76g.xn--3xaa51q; ; xn--3sb7483hoyvbbe76g.xn--4xaa21q; # 킃𑘶ߜ.ςؼς
+񻂵킃𑘶ߜ。ΣؼΣ; 񻂵킃𑘶ߜ.σؼσ; [B5, B6, P1, V6]; xn--3sb7483hoyvbbe76g.xn--4xaa21q; ; ; # 킃𑘶ߜ.σؼσ
+񻂵킃𑘶ߜ。ΣؼΣ; 񻂵킃𑘶ߜ.σؼσ; [B5, B6, P1, V6]; xn--3sb7483hoyvbbe76g.xn--4xaa21q; ; ; # 킃𑘶ߜ.σؼσ
+񻂵킃𑘶ߜ。σؼσ; 񻂵킃𑘶ߜ.σؼσ; [B5, B6, P1, V6]; xn--3sb7483hoyvbbe76g.xn--4xaa21q; ; ; # 킃𑘶ߜ.σؼσ
+񻂵킃𑘶ߜ。σؼσ; 񻂵킃𑘶ߜ.σؼσ; [B5, B6, P1, V6]; xn--3sb7483hoyvbbe76g.xn--4xaa21q; ; ; # 킃𑘶ߜ.σؼσ
+񻂵킃𑘶ߜ。Σؼσ; 񻂵킃𑘶ߜ.σؼσ; [B5, B6, P1, V6]; xn--3sb7483hoyvbbe76g.xn--4xaa21q; ; ; # 킃𑘶ߜ.σؼσ
+񻂵킃𑘶ߜ。Σؼσ; 񻂵킃𑘶ߜ.σؼσ; [B5, B6, P1, V6]; xn--3sb7483hoyvbbe76g.xn--4xaa21q; ; ; # 킃𑘶ߜ.σؼσ
+xn--3sb7483hoyvbbe76g.xn--4xaa21q; 񻂵킃𑘶ߜ.σؼσ; [B5, B6, V6]; xn--3sb7483hoyvbbe76g.xn--4xaa21q; ; ; # 킃𑘶ߜ.σؼσ
+񻂵킃𑘶ߜ。Σؼς; 񻂵킃𑘶ߜ.σؼς; [B5, B6, P1, V6]; xn--3sb7483hoyvbbe76g.xn--3xab31q; ; xn--3sb7483hoyvbbe76g.xn--4xaa21q; # 킃𑘶ߜ.σؼς
+񻂵킃𑘶ߜ。Σؼς; 񻂵킃𑘶ߜ.σؼς; [B5, B6, P1, V6]; xn--3sb7483hoyvbbe76g.xn--3xab31q; ; xn--3sb7483hoyvbbe76g.xn--4xaa21q; # 킃𑘶ߜ.σؼς
+񻂵킃𑘶ߜ。σؼς; 񻂵킃𑘶ߜ.σؼς; [B5, B6, P1, V6]; xn--3sb7483hoyvbbe76g.xn--3xab31q; ; xn--3sb7483hoyvbbe76g.xn--4xaa21q; # 킃𑘶ߜ.σؼς
+񻂵킃𑘶ߜ。σؼς; 񻂵킃𑘶ߜ.σؼς; [B5, B6, P1, V6]; xn--3sb7483hoyvbbe76g.xn--3xab31q; ; xn--3sb7483hoyvbbe76g.xn--4xaa21q; # 킃𑘶ߜ.σؼς
+xn--3sb7483hoyvbbe76g.xn--3xab31q; 񻂵킃𑘶ߜ.σؼς; [B5, B6, V6]; xn--3sb7483hoyvbbe76g.xn--3xab31q; ; ; # 킃𑘶ߜ.σؼς
+xn--3sb7483hoyvbbe76g.xn--3xaa51q; 񻂵킃𑘶ߜ.ςؼς; [B5, B6, V6]; xn--3sb7483hoyvbbe76g.xn--3xaa51q; ; ; # 킃𑘶ߜ.ςؼς
+񻂵킃𑘶ߜ。ΣؼΣ; 񻂵킃𑘶ߜ.σؼσ; [B5, B6, P1, V6]; xn--3sb7483hoyvbbe76g.xn--4xaa21q; ; ; # 킃𑘶ߜ.σؼσ
+񻂵킃𑘶ߜ。ΣؼΣ; 񻂵킃𑘶ߜ.σؼσ; [B5, B6, P1, V6]; xn--3sb7483hoyvbbe76g.xn--4xaa21q; ; ; # 킃𑘶ߜ.σؼσ
+񻂵킃𑘶ߜ。σؼσ; 񻂵킃𑘶ߜ.σؼσ; [B5, B6, P1, V6]; xn--3sb7483hoyvbbe76g.xn--4xaa21q; ; ; # 킃𑘶ߜ.σؼσ
+񻂵킃𑘶ߜ。σؼσ; 񻂵킃𑘶ߜ.σؼσ; [B5, B6, P1, V6]; xn--3sb7483hoyvbbe76g.xn--4xaa21q; ; ; # 킃𑘶ߜ.σؼσ
+񻂵킃𑘶ߜ。Σؼσ; 񻂵킃𑘶ߜ.σؼσ; [B5, B6, P1, V6]; xn--3sb7483hoyvbbe76g.xn--4xaa21q; ; ; # 킃𑘶ߜ.σؼσ
+񻂵킃𑘶ߜ。Σؼσ; 񻂵킃𑘶ߜ.σؼσ; [B5, B6, P1, V6]; xn--3sb7483hoyvbbe76g.xn--4xaa21q; ; ; # 킃𑘶ߜ.σؼσ
+񻂵킃𑘶ߜ。Σؼς; 񻂵킃𑘶ߜ.σؼς; [B5, B6, P1, V6]; xn--3sb7483hoyvbbe76g.xn--3xab31q; ; xn--3sb7483hoyvbbe76g.xn--4xaa21q; # 킃𑘶ߜ.σؼς
+񻂵킃𑘶ߜ。Σؼς; 񻂵킃𑘶ߜ.σؼς; [B5, B6, P1, V6]; xn--3sb7483hoyvbbe76g.xn--3xab31q; ; xn--3sb7483hoyvbbe76g.xn--4xaa21q; # 킃𑘶ߜ.σؼς
+񻂵킃𑘶ߜ。σؼς; 񻂵킃𑘶ߜ.σؼς; [B5, B6, P1, V6]; xn--3sb7483hoyvbbe76g.xn--3xab31q; ; xn--3sb7483hoyvbbe76g.xn--4xaa21q; # 킃𑘶ߜ.σؼς
+񻂵킃𑘶ߜ。σؼς; 񻂵킃𑘶ߜ.σؼς; [B5, B6, P1, V6]; xn--3sb7483hoyvbbe76g.xn--3xab31q; ; xn--3sb7483hoyvbbe76g.xn--4xaa21q; # 킃𑘶ߜ.σؼς
+蔰。󠁹ࣝ-𑈵; 蔰.󠁹ࣝ-𑈵; [P1, V6]; xn--sz1a.xn----mrd9984r3dl0i; ; ; # 蔰.ࣝ-𑈵
+xn--sz1a.xn----mrd9984r3dl0i; 蔰.󠁹ࣝ-𑈵; [V6]; xn--sz1a.xn----mrd9984r3dl0i; ; ; # 蔰.ࣝ-𑈵
+ςჅ。ݚ; ςჅ.ݚ; [P1, V6]; xn--3xa677d.xn--epb; ; xn--4xa477d.xn--epb; # ςჅ.ݚ
+ςⴥ。ݚ; ςⴥ.ݚ; ; xn--3xa403s.xn--epb; ; xn--4xa203s.xn--epb; # ςⴥ.ݚ
+ΣჅ。ݚ; σჅ.ݚ; [P1, V6]; xn--4xa477d.xn--epb; ; ; # σჅ.ݚ
+σⴥ。ݚ; σⴥ.ݚ; ; xn--4xa203s.xn--epb; ; ; # σⴥ.ݚ
+Σⴥ。ݚ; σⴥ.ݚ; ; xn--4xa203s.xn--epb; ; ; # σⴥ.ݚ
+xn--4xa203s.xn--epb; σⴥ.ݚ; ; xn--4xa203s.xn--epb; ; ; # σⴥ.ݚ
+σⴥ.ݚ; ; ; xn--4xa203s.xn--epb; ; ; # σⴥ.ݚ
+ΣჅ.ݚ; σჅ.ݚ; [P1, V6]; xn--4xa477d.xn--epb; ; ; # σჅ.ݚ
+Σⴥ.ݚ; σⴥ.ݚ; ; xn--4xa203s.xn--epb; ; ; # σⴥ.ݚ
+xn--4xa477d.xn--epb; σჅ.ݚ; [V6]; xn--4xa477d.xn--epb; ; ; # σჅ.ݚ
+xn--3xa403s.xn--epb; ςⴥ.ݚ; ; xn--3xa403s.xn--epb; ; ; # ςⴥ.ݚ
+ςⴥ.ݚ; ; ; xn--3xa403s.xn--epb; ; xn--4xa203s.xn--epb; # ςⴥ.ݚ
+xn--3xa677d.xn--epb; ςჅ.ݚ; [V6]; xn--3xa677d.xn--epb; ; ; # ςჅ.ݚ
+్Ⴉ𞰓.᭲; ్Ⴉ𞰓.᭲; [B1, B3, B6, P1, V5, V6]; xn--lqc64t7t26c.xn--dwf; ; ; # ్Ⴉ.᭲
+్Ⴉ𞰓.᭲; ; [B1, B3, B6, P1, V5, V6]; xn--lqc64t7t26c.xn--dwf; ; ; # ్Ⴉ.᭲
+్ⴉ𞰓.᭲; ; [B1, B3, B6, P1, V5, V6]; xn--lqc478nlr02a.xn--dwf; ; ; # ్ⴉ.᭲
+xn--lqc478nlr02a.xn--dwf; ్ⴉ𞰓.᭲; [B1, B3, B6, V5, V6]; xn--lqc478nlr02a.xn--dwf; ; ; # ్ⴉ.᭲
+xn--lqc64t7t26c.xn--dwf; ్Ⴉ𞰓.᭲; [B1, B3, B6, V5, V6]; xn--lqc64t7t26c.xn--dwf; ; ; # ్Ⴉ.᭲
+్ⴉ𞰓.᭲; ్ⴉ𞰓.᭲; [B1, B3, B6, P1, V5, V6]; xn--lqc478nlr02a.xn--dwf; ; ; # ్ⴉ.᭲
+⮷≮񎈴󠄟。𐠄; ⮷≮񎈴.𐠄; [B1, P1, V6]; xn--gdh877a3513h.xn--pc9c; ; ; # ⮷≮.𐠄
+⮷≮񎈴󠄟。𐠄; ⮷≮񎈴.𐠄; [B1, P1, V6]; xn--gdh877a3513h.xn--pc9c; ; ; # ⮷≮.𐠄
+xn--gdh877a3513h.xn--pc9c; ⮷≮񎈴.𐠄; [B1, V6]; xn--gdh877a3513h.xn--pc9c; ; ; # ⮷≮.𐠄
+ڼ。‍ẏ‌ᡤ; ڼ.‍ẏ‌ᡤ; [B1, C1, C2]; xn--vkb.xn--08e172ax6aca; ; xn--vkb.xn--08e172a; [] # ڼ.ẏᡤ
+ڼ。‍ẏ‌ᡤ; ڼ.‍ẏ‌ᡤ; [B1, C1, C2]; xn--vkb.xn--08e172ax6aca; ; xn--vkb.xn--08e172a; [] # ڼ.ẏᡤ
+ڼ。‍ẏ‌ᡤ; ڼ.‍ẏ‌ᡤ; [B1, C1, C2]; xn--vkb.xn--08e172ax6aca; ; xn--vkb.xn--08e172a; [] # ڼ.ẏᡤ
+ڼ。‍ẏ‌ᡤ; ڼ.‍ẏ‌ᡤ; [B1, C1, C2]; xn--vkb.xn--08e172ax6aca; ; xn--vkb.xn--08e172a; [] # ڼ.ẏᡤ
+ڼ。‍Ẏ‌ᡤ; ڼ.‍ẏ‌ᡤ; [B1, C1, C2]; xn--vkb.xn--08e172ax6aca; ; xn--vkb.xn--08e172a; [] # ڼ.ẏᡤ
+ڼ。‍Ẏ‌ᡤ; ڼ.‍ẏ‌ᡤ; [B1, C1, C2]; xn--vkb.xn--08e172ax6aca; ; xn--vkb.xn--08e172a; [] # ڼ.ẏᡤ
+xn--vkb.xn--08e172a; ڼ.ẏᡤ; ; xn--vkb.xn--08e172a; ; ; # ڼ.ẏᡤ
+ڼ.ẏᡤ; ; ; xn--vkb.xn--08e172a; ; ; # ڼ.ẏᡤ
+ڼ.ẏᡤ; ڼ.ẏᡤ; ; xn--vkb.xn--08e172a; ; ; # ڼ.ẏᡤ
+ڼ.Ẏᡤ; ڼ.ẏᡤ; ; xn--vkb.xn--08e172a; ; ; # ڼ.ẏᡤ
+ڼ.Ẏᡤ; ڼ.ẏᡤ; ; xn--vkb.xn--08e172a; ; ; # ڼ.ẏᡤ
+xn--vkb.xn--08e172ax6aca; ڼ.‍ẏ‌ᡤ; [B1, C1, C2]; xn--vkb.xn--08e172ax6aca; ; ; # ڼ.ẏᡤ
+ڼ。‍Ẏ‌ᡤ; ڼ.‍ẏ‌ᡤ; [B1, C1, C2]; xn--vkb.xn--08e172ax6aca; ; xn--vkb.xn--08e172a; [] # ڼ.ẏᡤ
+ڼ。‍Ẏ‌ᡤ; ڼ.‍ẏ‌ᡤ; [B1, C1, C2]; xn--vkb.xn--08e172ax6aca; ; xn--vkb.xn--08e172a; [] # ڼ.ẏᡤ
+𐹹𑲛。񑂐්; 𐹹𑲛.񑂐්; [B1, P1, V6]; xn--xo0dg5v.xn--h1c39876d; ; ; # 𐹹𑲛.්
+xn--xo0dg5v.xn--h1c39876d; 𐹹𑲛.񑂐්; [B1, V6]; xn--xo0dg5v.xn--h1c39876d; ; ; # 𐹹𑲛.්
+-≠𑈵。嵕ﻱ۴꥓; -≠𑈵.嵕ي۴꥓; [B1, B5, P1, V3, V6]; xn----ufo4749h.xn--mhb45a235sns3c; ; ; # -≠𑈵.嵕ي۴꥓
+-≠𑈵。嵕ﻱ۴꥓; -≠𑈵.嵕ي۴꥓; [B1, B5, P1, V3, V6]; xn----ufo4749h.xn--mhb45a235sns3c; ; ; # -≠𑈵.嵕ي۴꥓
+-≠𑈵。嵕ي۴꥓; -≠𑈵.嵕ي۴꥓; [B1, B5, P1, V3, V6]; xn----ufo4749h.xn--mhb45a235sns3c; ; ; # -≠𑈵.嵕ي۴꥓
+-≠𑈵。嵕ي۴꥓; -≠𑈵.嵕ي۴꥓; [B1, B5, P1, V3, V6]; xn----ufo4749h.xn--mhb45a235sns3c; ; ; # -≠𑈵.嵕ي۴꥓
+xn----ufo4749h.xn--mhb45a235sns3c; -≠𑈵.嵕ي۴꥓; [B1, B5, V3, V6]; xn----ufo4749h.xn--mhb45a235sns3c; ; ; # -≠𑈵.嵕ي۴꥓
+‌񍸰𐹶ݮ.ہ‍≯‍; ‌񍸰𐹶ݮ.ہ‍≯‍; [B1, B3, C1, C2, P1, V6]; xn--ypb717jrx2o7v94a.xn--0kb660ka35v; ; xn--ypb5875khz9y.xn--0kb682l; [B3, B5, B6, P1, V6] # 𐹶ݮ.ہ≯
+‌񍸰𐹶ݮ.ہ‍≯‍; ‌񍸰𐹶ݮ.ہ‍≯‍; [B1, B3, C1, C2, P1, V6]; xn--ypb717jrx2o7v94a.xn--0kb660ka35v; ; xn--ypb5875khz9y.xn--0kb682l; [B3, B5, B6, P1, V6] # 𐹶ݮ.ہ≯
+‌񍸰𐹶ݮ.ہ‍≯‍; ; [B1, B3, C1, C2, P1, V6]; xn--ypb717jrx2o7v94a.xn--0kb660ka35v; ; xn--ypb5875khz9y.xn--0kb682l; [B3, B5, B6, P1, V6] # 𐹶ݮ.ہ≯
+‌񍸰𐹶ݮ.ہ‍≯‍; ‌񍸰𐹶ݮ.ہ‍≯‍; [B1, B3, C1, C2, P1, V6]; xn--ypb717jrx2o7v94a.xn--0kb660ka35v; ; xn--ypb5875khz9y.xn--0kb682l; [B3, B5, B6, P1, V6] # 𐹶ݮ.ہ≯
+xn--ypb5875khz9y.xn--0kb682l; 񍸰𐹶ݮ.ہ≯; [B3, B5, B6, V6]; xn--ypb5875khz9y.xn--0kb682l; ; ; # 𐹶ݮ.ہ≯
+xn--ypb717jrx2o7v94a.xn--0kb660ka35v; ‌񍸰𐹶ݮ.ہ‍≯‍; [B1, B3, C1, C2, V6]; xn--ypb717jrx2o7v94a.xn--0kb660ka35v; ; ; # 𐹶ݮ.ہ≯
+≮.឵ࡕ𐫔; ≮.឵ࡕ𐫔; [B1, P1, V5, V6]; xn--gdh.xn--kwb589e217p; ; ; # ≮.ࡕ𐫔
+≮.឵ࡕ𐫔; ≮.឵ࡕ𐫔; [B1, P1, V5, V6]; xn--gdh.xn--kwb589e217p; ; ; # ≮.ࡕ𐫔
+≮.឵ࡕ𐫔; ; [B1, P1, V5, V6]; xn--gdh.xn--kwb589e217p; ; ; # ≮.ࡕ𐫔
+≮.឵ࡕ𐫔; ≮.឵ࡕ𐫔; [B1, P1, V5, V6]; xn--gdh.xn--kwb589e217p; ; ; # ≮.ࡕ𐫔
+xn--gdh.xn--kwb589e217p; ≮.឵ࡕ𐫔; [B1, V5, V6]; xn--gdh.xn--kwb589e217p; ; ; # ≮.ࡕ𐫔
+𐩗‍。ႩႵ; 𐩗‍.ႩႵ; [B3, C2, P1, V6]; xn--1ug4933g.xn--hndy; ; xn--pt9c.xn--hndy; [P1, V6] # 𐩗.ႩႵ
+𐩗‍。ႩႵ; 𐩗‍.ႩႵ; [B3, C2, P1, V6]; xn--1ug4933g.xn--hndy; ; xn--pt9c.xn--hndy; [P1, V6] # 𐩗.ႩႵ
+𐩗‍。ⴉⴕ; 𐩗‍.ⴉⴕ; [B3, C2]; xn--1ug4933g.xn--0kjya; ; xn--pt9c.xn--0kjya; [] # 𐩗.ⴉⴕ
+𐩗‍。Ⴉⴕ; 𐩗‍.Ⴉⴕ; [B3, C2, P1, V6]; xn--1ug4933g.xn--hnd666l; ; xn--pt9c.xn--hnd666l; [P1, V6] # 𐩗.Ⴉⴕ
+xn--pt9c.xn--hnd666l; 𐩗.Ⴉⴕ; [V6]; xn--pt9c.xn--hnd666l; ; ; # 𐩗.Ⴉⴕ
+xn--1ug4933g.xn--hnd666l; 𐩗‍.Ⴉⴕ; [B3, C2, V6]; xn--1ug4933g.xn--hnd666l; ; ; # 𐩗.Ⴉⴕ
+xn--pt9c.xn--0kjya; 𐩗.ⴉⴕ; ; xn--pt9c.xn--0kjya; ; ; # 𐩗.ⴉⴕ
+𐩗.ⴉⴕ; ; ; xn--pt9c.xn--0kjya; ; ; # 𐩗.ⴉⴕ
+𐩗.ႩႵ; ; [P1, V6]; xn--pt9c.xn--hndy; ; ; # 𐩗.ႩႵ
+𐩗.Ⴉⴕ; ; [P1, V6]; xn--pt9c.xn--hnd666l; ; ; # 𐩗.Ⴉⴕ
+xn--pt9c.xn--hndy; 𐩗.ႩႵ; [V6]; xn--pt9c.xn--hndy; ; ; # 𐩗.ႩႵ
+xn--1ug4933g.xn--0kjya; 𐩗‍.ⴉⴕ; [B3, C2]; xn--1ug4933g.xn--0kjya; ; ; # 𐩗.ⴉⴕ
+xn--1ug4933g.xn--hndy; 𐩗‍.ႩႵ; [B3, C2, V6]; xn--1ug4933g.xn--hndy; ; ; # 𐩗.ႩႵ
+𐩗‍。ⴉⴕ; 𐩗‍.ⴉⴕ; [B3, C2]; xn--1ug4933g.xn--0kjya; ; xn--pt9c.xn--0kjya; [] # 𐩗.ⴉⴕ
+𐩗‍。Ⴉⴕ; 𐩗‍.Ⴉⴕ; [B3, C2, P1, V6]; xn--1ug4933g.xn--hnd666l; ; xn--pt9c.xn--hnd666l; [P1, V6] # 𐩗.Ⴉⴕ
+‌‌ㄤ.̮󕨑ূ; ‌‌ㄤ.̮󕨑ূ; [C1, P1, V5, V6]; xn--0uga242k.xn--vta284a9o563a; ; xn--1fk.xn--vta284a9o563a; [P1, V5, V6] # ㄤ.̮ূ
+‌‌ㄤ.̮󕨑ূ; ; [C1, P1, V5, V6]; xn--0uga242k.xn--vta284a9o563a; ; xn--1fk.xn--vta284a9o563a; [P1, V5, V6] # ㄤ.̮ূ
+xn--1fk.xn--vta284a9o563a; ㄤ.̮󕨑ূ; [V5, V6]; xn--1fk.xn--vta284a9o563a; ; ; # ㄤ.̮ূ
+xn--0uga242k.xn--vta284a9o563a; ‌‌ㄤ.̮󕨑ূ; [C1, V5, V6]; xn--0uga242k.xn--vta284a9o563a; ; ; # ㄤ.̮ূ
+𐋻。-‌𐫄Ⴗ; 𐋻.-‌𐫄Ⴗ; [B1, C1, P1, V3, V6]; xn--v97c.xn----i1g888ih12u; ; xn--v97c.xn----i1g2513q; [B1, P1, V3, V6] # 𐋻.-𐫄Ⴗ
+𐋻。-‌𐫄Ⴗ; 𐋻.-‌𐫄Ⴗ; [B1, C1, P1, V3, V6]; xn--v97c.xn----i1g888ih12u; ; xn--v97c.xn----i1g2513q; [B1, P1, V3, V6] # 𐋻.-𐫄Ⴗ
+𐋻。-‌𐫄ⴗ; 𐋻.-‌𐫄ⴗ; [B1, C1, V3]; xn--v97c.xn----sgnv20du99s; ; xn--v97c.xn----lws0526f; [B1, V3] # 𐋻.-𐫄ⴗ
+xn--v97c.xn----lws0526f; 𐋻.-𐫄ⴗ; [B1, V3]; xn--v97c.xn----lws0526f; ; ; # 𐋻.-𐫄ⴗ
+xn--v97c.xn----sgnv20du99s; 𐋻.-‌𐫄ⴗ; [B1, C1, V3]; xn--v97c.xn----sgnv20du99s; ; ; # 𐋻.-𐫄ⴗ
+xn--v97c.xn----i1g2513q; 𐋻.-𐫄Ⴗ; [B1, V3, V6]; xn--v97c.xn----i1g2513q; ; ; # 𐋻.-𐫄Ⴗ
+xn--v97c.xn----i1g888ih12u; 𐋻.-‌𐫄Ⴗ; [B1, C1, V3, V6]; xn--v97c.xn----i1g888ih12u; ; ; # 𐋻.-𐫄Ⴗ
+𐋻。-‌𐫄ⴗ; 𐋻.-‌𐫄ⴗ; [B1, C1, V3]; xn--v97c.xn----sgnv20du99s; ; xn--v97c.xn----lws0526f; [B1, V3] # 𐋻.-𐫄ⴗ
+🙑𐷺.≠‌; 🙑𐷺.≠‌; [B1, C1, P1, V6]; xn--bl0dh970b.xn--0ug83g; ; xn--bl0dh970b.xn--1ch; [B1, P1, V6] # 🙑.≠
+🙑𐷺.≠‌; 🙑𐷺.≠‌; [B1, C1, P1, V6]; xn--bl0dh970b.xn--0ug83g; ; xn--bl0dh970b.xn--1ch; [B1, P1, V6] # 🙑.≠
+🙑𐷺.≠‌; ; [B1, C1, P1, V6]; xn--bl0dh970b.xn--0ug83g; ; xn--bl0dh970b.xn--1ch; [B1, P1, V6] # 🙑.≠
+🙑𐷺.≠‌; 🙑𐷺.≠‌; [B1, C1, P1, V6]; xn--bl0dh970b.xn--0ug83g; ; xn--bl0dh970b.xn--1ch; [B1, P1, V6] # 🙑.≠
+xn--bl0dh970b.xn--1ch; 🙑𐷺.≠; [B1, V6]; xn--bl0dh970b.xn--1ch; ; ; # 🙑.≠
+xn--bl0dh970b.xn--0ug83g; 🙑𐷺.≠‌; [B1, C1, V6]; xn--bl0dh970b.xn--0ug83g; ; ; # 🙑.≠
+ٌ᳒。𞮞⵿⧎; ٌ᳒.𞮞⵿⧎; [B1, B3, B6, P1, V5, V6]; xn--ohb646i.xn--ewi38jf765c; ; ; # ٌ᳒.⵿⧎
+ٌ᳒。𞮞⵿⧎; ٌ᳒.𞮞⵿⧎; [B1, B3, B6, P1, V5, V6]; xn--ohb646i.xn--ewi38jf765c; ; ; # ٌ᳒.⵿⧎
+xn--ohb646i.xn--ewi38jf765c; ٌ᳒.𞮞⵿⧎; [B1, B3, B6, V5, V6]; xn--ohb646i.xn--ewi38jf765c; ; ; # ٌ᳒.⵿⧎
+Ⴔ𝨨₃󠁦.𝟳𑂹ஂ; Ⴔ𝨨3󠁦.7𑂹ஂ; [P1, V6]; xn--3-b1g83426a35t0g.xn--7-cve6271r; ; ; # Ⴔ𝨨3.7𑂹ஂ
+Ⴔ𝨨3󠁦.7𑂹ஂ; ; [P1, V6]; xn--3-b1g83426a35t0g.xn--7-cve6271r; ; ; # Ⴔ𝨨3.7𑂹ஂ
+ⴔ𝨨3󠁦.7𑂹ஂ; ; [P1, V6]; xn--3-ews6985n35s3g.xn--7-cve6271r; ; ; # ⴔ𝨨3.7𑂹ஂ
+xn--3-ews6985n35s3g.xn--7-cve6271r; ⴔ𝨨3󠁦.7𑂹ஂ; [V6]; xn--3-ews6985n35s3g.xn--7-cve6271r; ; ; # ⴔ𝨨3.7𑂹ஂ
+xn--3-b1g83426a35t0g.xn--7-cve6271r; Ⴔ𝨨3󠁦.7𑂹ஂ; [V6]; xn--3-b1g83426a35t0g.xn--7-cve6271r; ; ; # Ⴔ𝨨3.7𑂹ஂ
+ⴔ𝨨₃󠁦.𝟳𑂹ஂ; ⴔ𝨨3󠁦.7𑂹ஂ; [P1, V6]; xn--3-ews6985n35s3g.xn--7-cve6271r; ; ; # ⴔ𝨨3.7𑂹ஂ
+䏈‌。‌⒈񱢕; 䏈‌.‌⒈񱢕; [C1, P1, V6]; xn--0ug491l.xn--0ug88oot66q; ; xn--eco.xn--tsh21126d; [P1, V6] # 䏈.⒈
+䏈‌。‌1.񱢕; 䏈‌.‌1.񱢕; [C1, P1, V6]; xn--0ug491l.xn--1-rgn.xn--ms39a; ; xn--eco.1.xn--ms39a; [P1, V6] # 䏈.1.
+xn--eco.1.xn--ms39a; 䏈.1.񱢕; [V6]; xn--eco.1.xn--ms39a; ; ; # 䏈.1.
+xn--0ug491l.xn--1-rgn.xn--ms39a; 䏈‌.‌1.񱢕; [C1, V6]; xn--0ug491l.xn--1-rgn.xn--ms39a; ; ; # 䏈.1.
+xn--eco.xn--tsh21126d; 䏈.⒈񱢕; [V6]; xn--eco.xn--tsh21126d; ; ; # 䏈.⒈
+xn--0ug491l.xn--0ug88oot66q; 䏈‌.‌⒈񱢕; [C1, V6]; xn--0ug491l.xn--0ug88oot66q; ; ; # 䏈.⒈
+1꫶ß𑲥。ᷘ; 1꫶ß𑲥.ᷘ; [V5]; xn--1-qfa2471kdb0d.xn--weg; ; xn--1ss-ir6ln166b.xn--weg; # 1꫶ß𑲥.ᷘ
+1꫶ß𑲥。ᷘ; 1꫶ß𑲥.ᷘ; [V5]; xn--1-qfa2471kdb0d.xn--weg; ; xn--1ss-ir6ln166b.xn--weg; # 1꫶ß𑲥.ᷘ
+1꫶SS𑲥。ᷘ; 1꫶ss𑲥.ᷘ; [V5]; xn--1ss-ir6ln166b.xn--weg; ; ; # 1꫶ss𑲥.ᷘ
+1꫶ss𑲥。ᷘ; 1꫶ss𑲥.ᷘ; [V5]; xn--1ss-ir6ln166b.xn--weg; ; ; # 1꫶ss𑲥.ᷘ
+xn--1ss-ir6ln166b.xn--weg; 1꫶ss𑲥.ᷘ; [V5]; xn--1ss-ir6ln166b.xn--weg; ; ; # 1꫶ss𑲥.ᷘ
+xn--1-qfa2471kdb0d.xn--weg; 1꫶ß𑲥.ᷘ; [V5]; xn--1-qfa2471kdb0d.xn--weg; ; ; # 1꫶ß𑲥.ᷘ
+1꫶SS𑲥。ᷘ; 1꫶ss𑲥.ᷘ; [V5]; xn--1ss-ir6ln166b.xn--weg; ; ; # 1꫶ss𑲥.ᷘ
+1꫶ss𑲥。ᷘ; 1꫶ss𑲥.ᷘ; [V5]; xn--1ss-ir6ln166b.xn--weg; ; ; # 1꫶ss𑲥.ᷘ
+1꫶Ss𑲥。ᷘ; 1꫶ss𑲥.ᷘ; [V5]; xn--1ss-ir6ln166b.xn--weg; ; ; # 1꫶ss𑲥.ᷘ
+1꫶Ss𑲥。ᷘ; 1꫶ss𑲥.ᷘ; [V5]; xn--1ss-ir6ln166b.xn--weg; ; ; # 1꫶ss𑲥.ᷘ
+‍񫶩𞪯್。ݼ⒈; ‍񫶩𞪯್.ݼ⒈; [B1, C2, P1, V6]; xn--8tc969gzn94a4lm8a.xn--dqb689l; ; xn--8tc9875v5is1a.xn--dqb689l; [B5, B6, P1, V6] # ್.ݼ⒈
+‍񫶩𞪯್。ݼ1.; ‍񫶩𞪯್.ݼ1.; [B1, C2, P1, V6]; xn--8tc969gzn94a4lm8a.xn--1-g6c.; ; xn--8tc9875v5is1a.xn--1-g6c.; [B5, B6, P1, V6] # ್.ݼ1.
+xn--8tc9875v5is1a.xn--1-g6c.; 񫶩𞪯್.ݼ1.; [B5, B6, V6]; xn--8tc9875v5is1a.xn--1-g6c.; ; ; # ್.ݼ1.
+xn--8tc969gzn94a4lm8a.xn--1-g6c.; ‍񫶩𞪯್.ݼ1.; [B1, C2, V6]; xn--8tc969gzn94a4lm8a.xn--1-g6c.; ; ; # ್.ݼ1.
+xn--8tc9875v5is1a.xn--dqb689l; 񫶩𞪯್.ݼ⒈; [B5, B6, V6]; xn--8tc9875v5is1a.xn--dqb689l; ; ; # ್.ݼ⒈
+xn--8tc969gzn94a4lm8a.xn--dqb689l; ‍񫶩𞪯್.ݼ⒈; [B1, C2, V6]; xn--8tc969gzn94a4lm8a.xn--dqb689l; ; ; # ್.ݼ⒈
+᪶.𞤳򓢖򻉒ߗ; ᪶.𞤳򓢖򻉒ߗ; [B1, B2, B3, B6, P1, V5, V6]; xn--zqf.xn--ysb9657vuiz5bj0ep; ; ; # ᪶.𞤳ߗ
+᪶.𞤳򓢖򻉒ߗ; ; [B1, B2, B3, B6, P1, V5, V6]; xn--zqf.xn--ysb9657vuiz5bj0ep; ; ; # ᪶.𞤳ߗ
+᪶.𞤑򓢖򻉒ߗ; ᪶.𞤳򓢖򻉒ߗ; [B1, B2, B3, B6, P1, V5, V6]; xn--zqf.xn--ysb9657vuiz5bj0ep; ; ; # ᪶.𞤳ߗ
+xn--zqf.xn--ysb9657vuiz5bj0ep; ᪶.𞤳򓢖򻉒ߗ; [B1, B2, B3, B6, V5, V6]; xn--zqf.xn--ysb9657vuiz5bj0ep; ; ; # ᪶.𞤳ߗ
+᪶.𞤑򓢖򻉒ߗ; ᪶.𞤳򓢖򻉒ߗ; [B1, B2, B3, B6, P1, V5, V6]; xn--zqf.xn--ysb9657vuiz5bj0ep; ; ; # ᪶.𞤳ߗ
+ࡂ𞩚⒈.󠬌8򏳏ݰ; ࡂ𞩚⒈.󠬌8򏳏ݰ; [B1, P1, V6]; xn--0vb095ldg52a.xn--8-s5c22427ox454a; ; ; # ࡂ⒈.8ݰ
+ࡂ𞩚1..󠬌8򏳏ݰ; ; [B1, P1, V6, X4_2]; xn--1-rid26318a..xn--8-s5c22427ox454a; [B1, P1, V6, A4_2]; ; # ࡂ1..8ݰ
+xn--1-rid26318a..xn--8-s5c22427ox454a; ࡂ𞩚1..󠬌8򏳏ݰ; [B1, V6, X4_2]; xn--1-rid26318a..xn--8-s5c22427ox454a; [B1, V6, A4_2]; ; # ࡂ1..8ݰ
+xn--0vb095ldg52a.xn--8-s5c22427ox454a; ࡂ𞩚⒈.󠬌8򏳏ݰ; [B1, V6]; xn--0vb095ldg52a.xn--8-s5c22427ox454a; ; ; # ࡂ⒈.8ݰ
+͡𐫫ͩᡷ。-󠰛鞰; ͡𐫫ͩᡷ.-󠰛鞰; [B1, P1, V3, V5, V6]; xn--cvaq482npv5t.xn----yg7dt1332g; ; ; # ͡𐫫ͩᡷ.-鞰
+xn--cvaq482npv5t.xn----yg7dt1332g; ͡𐫫ͩᡷ.-󠰛鞰; [B1, V3, V5, V6]; xn--cvaq482npv5t.xn----yg7dt1332g; ; ; # ͡𐫫ͩᡷ.-鞰
+-.્剘ß𐫃; ; [B1, V3, V5]; -.xn--zca791c493duf8i; ; -.xn--ss-bqg4734erywk; # -.્剘ß𐫃
+-.્剘SS𐫃; -.્剘ss𐫃; [B1, V3, V5]; -.xn--ss-bqg4734erywk; ; ; # -.્剘ss𐫃
+-.્剘ss𐫃; ; [B1, V3, V5]; -.xn--ss-bqg4734erywk; ; ; # -.્剘ss𐫃
+-.્剘Ss𐫃; -.્剘ss𐫃; [B1, V3, V5]; -.xn--ss-bqg4734erywk; ; ; # -.્剘ss𐫃
+-.xn--ss-bqg4734erywk; -.્剘ss𐫃; [B1, V3, V5]; -.xn--ss-bqg4734erywk; ; ; # -.્剘ss𐫃
+-.xn--zca791c493duf8i; -.્剘ß𐫃; [B1, V3, V5]; -.xn--zca791c493duf8i; ; ; # -.્剘ß𐫃
+ࣻ𞵸。-; ࣻ𞵸.-; [B1, P1, V3, V5, V6]; xn--b1b2719v.-; ; ; # ࣻ.-
+ࣻ𞵸。-; ࣻ𞵸.-; [B1, P1, V3, V5, V6]; xn--b1b2719v.-; ; ; # ࣻ.-
+xn--b1b2719v.-; ࣻ𞵸.-; [B1, V3, V5, V6]; xn--b1b2719v.-; ; ; # ࣻ.-
+⒈󠈻𐹲。≠؃𐹽; ⒈󠈻𐹲.≠؃𐹽; [B1, P1, V6]; xn--tshw766f1153g.xn--lfb536lb35n; ; ; # ⒈𐹲.≠𐹽
+⒈󠈻𐹲。≠؃𐹽; ⒈󠈻𐹲.≠؃𐹽; [B1, P1, V6]; xn--tshw766f1153g.xn--lfb536lb35n; ; ; # ⒈𐹲.≠𐹽
+1.󠈻𐹲。≠؃𐹽; 1.󠈻𐹲.≠؃𐹽; [B1, P1, V6]; 1.xn--qo0dl3077c.xn--lfb536lb35n; ; ; # 1.𐹲.≠𐹽
+1.󠈻𐹲。≠؃𐹽; 1.󠈻𐹲.≠؃𐹽; [B1, P1, V6]; 1.xn--qo0dl3077c.xn--lfb536lb35n; ; ; # 1.𐹲.≠𐹽
+1.xn--qo0dl3077c.xn--lfb536lb35n; 1.󠈻𐹲.≠؃𐹽; [B1, V6]; 1.xn--qo0dl3077c.xn--lfb536lb35n; ; ; # 1.𐹲.≠𐹽
+xn--tshw766f1153g.xn--lfb536lb35n; ⒈󠈻𐹲.≠؃𐹽; [B1, V6]; xn--tshw766f1153g.xn--lfb536lb35n; ; ; # ⒈𐹲.≠𐹽
+𐹢󠈚Ⴎ‌.㖾𐹡; ; [B1, B5, B6, C1, P1, V6]; xn--mnd289ezj4pqxp0i.xn--pelu572d; ; xn--mnd9001km0o0g.xn--pelu572d; [B1, B5, B6, P1, V6] # 𐹢Ⴎ.㖾𐹡
+𐹢󠈚ⴎ‌.㖾𐹡; ; [B1, B5, B6, C1, P1, V6]; xn--0ug342clq0pqxv4i.xn--pelu572d; ; xn--5kjx323em053g.xn--pelu572d; [B1, B5, B6, P1, V6] # 𐹢ⴎ.㖾𐹡
+xn--5kjx323em053g.xn--pelu572d; 𐹢󠈚ⴎ.㖾𐹡; [B1, B5, B6, V6]; xn--5kjx323em053g.xn--pelu572d; ; ; # 𐹢ⴎ.㖾𐹡
+xn--0ug342clq0pqxv4i.xn--pelu572d; 𐹢󠈚ⴎ‌.㖾𐹡; [B1, B5, B6, C1, V6]; xn--0ug342clq0pqxv4i.xn--pelu572d; ; ; # 𐹢ⴎ.㖾𐹡
+xn--mnd9001km0o0g.xn--pelu572d; 𐹢󠈚Ⴎ.㖾𐹡; [B1, B5, B6, V6]; xn--mnd9001km0o0g.xn--pelu572d; ; ; # 𐹢Ⴎ.㖾𐹡
+xn--mnd289ezj4pqxp0i.xn--pelu572d; 𐹢󠈚Ⴎ‌.㖾𐹡; [B1, B5, B6, C1, V6]; xn--mnd289ezj4pqxp0i.xn--pelu572d; ; ; # 𐹢Ⴎ.㖾𐹡
+򩼗.߇ᡖႳႧ; 򩼗.߇ᡖႳႧ; [B2, B3, P1, V6]; xn--te28c.xn--isb856b9a631d; ; ; # .߇ᡖႳႧ
+򩼗.߇ᡖႳႧ; ; [B2, B3, P1, V6]; xn--te28c.xn--isb856b9a631d; ; ; # .߇ᡖႳႧ
+򩼗.߇ᡖⴓⴇ; ; [B2, B3, P1, V6]; xn--te28c.xn--isb295fbtpmb; ; ; # .߇ᡖⴓⴇ
+xn--te28c.xn--isb295fbtpmb; 򩼗.߇ᡖⴓⴇ; [B2, B3, V6]; xn--te28c.xn--isb295fbtpmb; ; ; # .߇ᡖⴓⴇ
+xn--te28c.xn--isb856b9a631d; 򩼗.߇ᡖႳႧ; [B2, B3, V6]; xn--te28c.xn--isb856b9a631d; ; ; # .߇ᡖႳႧ
+򩼗.߇ᡖⴓⴇ; 򩼗.߇ᡖⴓⴇ; [B2, B3, P1, V6]; xn--te28c.xn--isb295fbtpmb; ; ; # .߇ᡖⴓⴇ
+򩼗.߇ᡖႳⴇ; ; [B2, B3, P1, V6]; xn--te28c.xn--isb286btrgo7w; ; ; # .߇ᡖႳⴇ
+xn--te28c.xn--isb286btrgo7w; 򩼗.߇ᡖႳⴇ; [B2, B3, V6]; xn--te28c.xn--isb286btrgo7w; ; ; # .߇ᡖႳⴇ
+򩼗.߇ᡖႳⴇ; 򩼗.߇ᡖႳⴇ; [B2, B3, P1, V6]; xn--te28c.xn--isb286btrgo7w; ; ; # .߇ᡖႳⴇ
+‍􅍉.ڳݵ; ; [B1, C2, P1, V6]; xn--1ug39444n.xn--mkb20b; ; xn--3j78f.xn--mkb20b; [P1, V6] # .ڳݵ
+xn--3j78f.xn--mkb20b; 􅍉.ڳݵ; [V6]; xn--3j78f.xn--mkb20b; ; ; # .ڳݵ
+xn--1ug39444n.xn--mkb20b; ‍􅍉.ڳݵ; [B1, C2, V6]; xn--1ug39444n.xn--mkb20b; ; ; # .ڳݵ
+𲤱⒛⾳.ꡦ⒈; 𲤱⒛音.ꡦ⒈; [P1, V6]; xn--dth6033bzbvx.xn--tsh9439b; ; ; # ⒛音.ꡦ⒈
+𲤱20.音.ꡦ1.; ; [P1, V6]; xn--20-9802c.xn--0w5a.xn--1-eg4e.; ; ; # 20.音.ꡦ1.
+xn--20-9802c.xn--0w5a.xn--1-eg4e.; 𲤱20.音.ꡦ1.; [V6]; xn--20-9802c.xn--0w5a.xn--1-eg4e.; ; ; # 20.音.ꡦ1.
+xn--dth6033bzbvx.xn--tsh9439b; 𲤱⒛音.ꡦ⒈; [V6]; xn--dth6033bzbvx.xn--tsh9439b; ; ; # ⒛音.ꡦ⒈
+ߜ8񳦓-。򞲙𑁿𐩥্; ߜ8񳦓-.򞲙𑁿𐩥্; [B2, B3, B5, B6, P1, V3, V6]; xn--8--rve13079p.xn--b7b9842k42df776x; ; ; # ߜ8-.𑁿𐩥্
+ߜ8񳦓-。򞲙𑁿𐩥্; ߜ8񳦓-.򞲙𑁿𐩥্; [B2, B3, B5, B6, P1, V3, V6]; xn--8--rve13079p.xn--b7b9842k42df776x; ; ; # ߜ8-.𑁿𐩥্
+xn--8--rve13079p.xn--b7b9842k42df776x; ߜ8񳦓-.򞲙𑁿𐩥্; [B2, B3, B5, B6, V3, V6]; xn--8--rve13079p.xn--b7b9842k42df776x; ; ; # ߜ8-.𑁿𐩥্
+Ⴕ。۰≮ß݅; Ⴕ.۰≮ß݅; [P1, V6]; xn--tnd.xn--zca912alh227g; ; xn--tnd.xn--ss-jbe65aw27i; # Ⴕ.۰≮ß݅
+Ⴕ。۰≮ß݅; Ⴕ.۰≮ß݅; [P1, V6]; xn--tnd.xn--zca912alh227g; ; xn--tnd.xn--ss-jbe65aw27i; # Ⴕ.۰≮ß݅
+ⴕ。۰≮ß݅; ⴕ.۰≮ß݅; [P1, V6]; xn--dlj.xn--zca912alh227g; ; xn--dlj.xn--ss-jbe65aw27i; # ⴕ.۰≮ß݅
+ⴕ。۰≮ß݅; ⴕ.۰≮ß݅; [P1, V6]; xn--dlj.xn--zca912alh227g; ; xn--dlj.xn--ss-jbe65aw27i; # ⴕ.۰≮ß݅
+Ⴕ。۰≮SS݅; Ⴕ.۰≮ss݅; [P1, V6]; xn--tnd.xn--ss-jbe65aw27i; ; ; # Ⴕ.۰≮ss݅
+Ⴕ。۰≮SS݅; Ⴕ.۰≮ss݅; [P1, V6]; xn--tnd.xn--ss-jbe65aw27i; ; ; # Ⴕ.۰≮ss݅
+ⴕ。۰≮ss݅; ⴕ.۰≮ss݅; [P1, V6]; xn--dlj.xn--ss-jbe65aw27i; ; ; # ⴕ.۰≮ss݅
+ⴕ。۰≮ss݅; ⴕ.۰≮ss݅; [P1, V6]; xn--dlj.xn--ss-jbe65aw27i; ; ; # ⴕ.۰≮ss݅
+Ⴕ。۰≮Ss݅; Ⴕ.۰≮ss݅; [P1, V6]; xn--tnd.xn--ss-jbe65aw27i; ; ; # Ⴕ.۰≮ss݅
+Ⴕ。۰≮Ss݅; Ⴕ.۰≮ss݅; [P1, V6]; xn--tnd.xn--ss-jbe65aw27i; ; ; # Ⴕ.۰≮ss݅
+xn--tnd.xn--ss-jbe65aw27i; Ⴕ.۰≮ss݅; [V6]; xn--tnd.xn--ss-jbe65aw27i; ; ; # Ⴕ.۰≮ss݅
+xn--dlj.xn--ss-jbe65aw27i; ⴕ.۰≮ss݅; [V6]; xn--dlj.xn--ss-jbe65aw27i; ; ; # ⴕ.۰≮ss݅
+xn--dlj.xn--zca912alh227g; ⴕ.۰≮ß݅; [V6]; xn--dlj.xn--zca912alh227g; ; ; # ⴕ.۰≮ß݅
+xn--tnd.xn--zca912alh227g; Ⴕ.۰≮ß݅; [V6]; xn--tnd.xn--zca912alh227g; ; ; # Ⴕ.۰≮ß݅
+ߩ-.𝨗꒱᭲; ; [B1, B3, V3, V5]; xn----odd.xn--dwf8994dc8wj; ; ; # ߩ-.𝨗꒱᭲
+xn----odd.xn--dwf8994dc8wj; ߩ-.𝨗꒱᭲; [B1, B3, V3, V5]; xn----odd.xn--dwf8994dc8wj; ; ; # ߩ-.𝨗꒱᭲
+𞼸‌.≯䕵⫧; ; [B1, B3, C1, P1, V6]; xn--0ugx453p.xn--hdh754ax6w; ; xn--sn7h.xn--hdh754ax6w; [B1, P1, V6] # .≯䕵⫧
+𞼸‌.≯䕵⫧; 𞼸‌.≯䕵⫧; [B1, B3, C1, P1, V6]; xn--0ugx453p.xn--hdh754ax6w; ; xn--sn7h.xn--hdh754ax6w; [B1, P1, V6] # .≯䕵⫧
+xn--sn7h.xn--hdh754ax6w; 𞼸.≯䕵⫧; [B1, V6]; xn--sn7h.xn--hdh754ax6w; ; ; # .≯䕵⫧
+xn--0ugx453p.xn--hdh754ax6w; 𞼸‌.≯䕵⫧; [B1, B3, C1, V6]; xn--0ugx453p.xn--hdh754ax6w; ; ; # .≯䕵⫧
+𐨅ßﱗ.ڬ۳︒; 𐨅ßيخ.ڬ۳︒; [B1, B3, P1, V5, V6]; xn--zca23yncs877j.xn--fkb6lp314e; ; xn--ss-ytd5i7765l.xn--fkb6lp314e; # 𐨅ßيخ.ڬ۳︒
+𐨅ßيخ.ڬ۳。; 𐨅ßيخ.ڬ۳.; [B1, V5]; xn--zca23yncs877j.xn--fkb6l.; ; xn--ss-ytd5i7765l.xn--fkb6l.; # 𐨅ßيخ.ڬ۳.
+𐨅SSيخ.ڬ۳。; 𐨅ssيخ.ڬ۳.; [B1, V5]; xn--ss-ytd5i7765l.xn--fkb6l.; ; ; # 𐨅ssيخ.ڬ۳.
+𐨅ssيخ.ڬ۳。; 𐨅ssيخ.ڬ۳.; [B1, V5]; xn--ss-ytd5i7765l.xn--fkb6l.; ; ; # 𐨅ssيخ.ڬ۳.
+𐨅Ssيخ.ڬ۳。; 𐨅ssيخ.ڬ۳.; [B1, V5]; xn--ss-ytd5i7765l.xn--fkb6l.; ; ; # 𐨅ssيخ.ڬ۳.
+xn--ss-ytd5i7765l.xn--fkb6l.; 𐨅ssيخ.ڬ۳.; [B1, V5]; xn--ss-ytd5i7765l.xn--fkb6l.; ; ; # 𐨅ssيخ.ڬ۳.
+xn--zca23yncs877j.xn--fkb6l.; 𐨅ßيخ.ڬ۳.; [B1, V5]; xn--zca23yncs877j.xn--fkb6l.; ; ; # 𐨅ßيخ.ڬ۳.
+𐨅SSﱗ.ڬ۳︒; 𐨅ssيخ.ڬ۳︒; [B1, B3, P1, V5, V6]; xn--ss-ytd5i7765l.xn--fkb6lp314e; ; ; # 𐨅ssيخ.ڬ۳︒
+𐨅ssﱗ.ڬ۳︒; 𐨅ssيخ.ڬ۳︒; [B1, B3, P1, V5, V6]; xn--ss-ytd5i7765l.xn--fkb6lp314e; ; ; # 𐨅ssيخ.ڬ۳︒
+𐨅Ssﱗ.ڬ۳︒; 𐨅ssيخ.ڬ۳︒; [B1, B3, P1, V5, V6]; xn--ss-ytd5i7765l.xn--fkb6lp314e; ; ; # 𐨅ssيخ.ڬ۳︒
+xn--ss-ytd5i7765l.xn--fkb6lp314e; 𐨅ssيخ.ڬ۳︒; [B1, B3, V5, V6]; xn--ss-ytd5i7765l.xn--fkb6lp314e; ; ; # 𐨅ssيخ.ڬ۳︒
+xn--zca23yncs877j.xn--fkb6lp314e; 𐨅ßيخ.ڬ۳︒; [B1, B3, V5, V6]; xn--zca23yncs877j.xn--fkb6lp314e; ; ; # 𐨅ßيخ.ڬ۳︒
+-≮🡒᳭.񏿾Ⴁܔ; ; [B1, P1, V3, V6]; xn----44l04zxt68c.xn--enb300c1597h; ; ; # -≮🡒᳭.Ⴁܔ
+-≮🡒᳭.񏿾Ⴁܔ; -≮🡒᳭.񏿾Ⴁܔ; [B1, P1, V3, V6]; xn----44l04zxt68c.xn--enb300c1597h; ; ; # -≮🡒᳭.Ⴁܔ
+-≮🡒᳭.񏿾ⴁܔ; -≮🡒᳭.񏿾ⴁܔ; [B1, P1, V3, V6]; xn----44l04zxt68c.xn--enb135qf106f; ; ; # -≮🡒᳭.ⴁܔ
+-≮🡒᳭.񏿾ⴁܔ; ; [B1, P1, V3, V6]; xn----44l04zxt68c.xn--enb135qf106f; ; ; # -≮🡒᳭.ⴁܔ
+xn----44l04zxt68c.xn--enb135qf106f; -≮🡒᳭.񏿾ⴁܔ; [B1, V3, V6]; xn----44l04zxt68c.xn--enb135qf106f; ; ; # -≮🡒᳭.ⴁܔ
+xn----44l04zxt68c.xn--enb300c1597h; -≮🡒᳭.񏿾Ⴁܔ; [B1, V3, V6]; xn----44l04zxt68c.xn--enb300c1597h; ; ; # -≮🡒᳭.Ⴁܔ
+𞤨。ꡏ‍‌; 𞤨.ꡏ‍‌; [B6, C1, C2]; xn--ge6h.xn--0ugb9575h; ; xn--ge6h.xn--oc9a; [] # 𞤨.ꡏ
+𞤨。ꡏ‍‌; 𞤨.ꡏ‍‌; [B6, C1, C2]; xn--ge6h.xn--0ugb9575h; ; xn--ge6h.xn--oc9a; [] # 𞤨.ꡏ
+𞤆。ꡏ‍‌; 𞤨.ꡏ‍‌; [B6, C1, C2]; xn--ge6h.xn--0ugb9575h; ; xn--ge6h.xn--oc9a; [] # 𞤨.ꡏ
+xn--ge6h.xn--oc9a; 𞤨.ꡏ; ; xn--ge6h.xn--oc9a; ; ; # 𞤨.ꡏ
+𞤨.ꡏ; ; ; xn--ge6h.xn--oc9a; ; ; # 𞤨.ꡏ
+𞤆.ꡏ; 𞤨.ꡏ; ; xn--ge6h.xn--oc9a; ; ; # 𞤨.ꡏ
+xn--ge6h.xn--0ugb9575h; 𞤨.ꡏ‍‌; [B6, C1, C2]; xn--ge6h.xn--0ugb9575h; ; ; # 𞤨.ꡏ
+𞤆。ꡏ‍‌; 𞤨.ꡏ‍‌; [B6, C1, C2]; xn--ge6h.xn--0ugb9575h; ; xn--ge6h.xn--oc9a; [] # 𞤨.ꡏ
+󠅹𑂶.ᢌ𑂹٩; 𑂶.ᢌ𑂹٩; [B1, B3, B5, B6, V5]; xn--b50d.xn--iib993gyp5p; ; ; # 𑂶.ᢌ𑂹٩
+󠅹𑂶.ᢌ𑂹٩; 𑂶.ᢌ𑂹٩; [B1, B3, B5, B6, V5]; xn--b50d.xn--iib993gyp5p; ; ; # 𑂶.ᢌ𑂹٩
+xn--b50d.xn--iib993gyp5p; 𑂶.ᢌ𑂹٩; [B1, B3, B5, B6, V5]; xn--b50d.xn--iib993gyp5p; ; ; # 𑂶.ᢌ𑂹٩
+Ⅎ󠅺񝵒。≯⾑; Ⅎ񝵒.≯襾; [P1, V6]; xn--f3g73398c.xn--hdhz171b; ; ; # Ⅎ.≯襾
+Ⅎ󠅺񝵒。≯⾑; Ⅎ񝵒.≯襾; [P1, V6]; xn--f3g73398c.xn--hdhz171b; ; ; # Ⅎ.≯襾
+Ⅎ󠅺񝵒。≯襾; Ⅎ񝵒.≯襾; [P1, V6]; xn--f3g73398c.xn--hdhz171b; ; ; # Ⅎ.≯襾
+Ⅎ󠅺񝵒。≯襾; Ⅎ񝵒.≯襾; [P1, V6]; xn--f3g73398c.xn--hdhz171b; ; ; # Ⅎ.≯襾
+ⅎ󠅺񝵒。≯襾; ⅎ񝵒.≯襾; [P1, V6]; xn--73g39298c.xn--hdhz171b; ; ; # ⅎ.≯襾
+ⅎ󠅺񝵒。≯襾; ⅎ񝵒.≯襾; [P1, V6]; xn--73g39298c.xn--hdhz171b; ; ; # ⅎ.≯襾
+xn--73g39298c.xn--hdhz171b; ⅎ񝵒.≯襾; [V6]; xn--73g39298c.xn--hdhz171b; ; ; # ⅎ.≯襾
+xn--f3g73398c.xn--hdhz171b; Ⅎ񝵒.≯襾; [V6]; xn--f3g73398c.xn--hdhz171b; ; ; # Ⅎ.≯襾
+ⅎ󠅺񝵒。≯⾑; ⅎ񝵒.≯襾; [P1, V6]; xn--73g39298c.xn--hdhz171b; ; ; # ⅎ.≯襾
+ⅎ󠅺񝵒。≯⾑; ⅎ񝵒.≯襾; [P1, V6]; xn--73g39298c.xn--hdhz171b; ; ; # ⅎ.≯襾
+ς‍ු٠。-; ς‍ු٠.-; [B1, B5, B6, C2, V3]; xn--3xa45ks2jenu.-; ; xn--4xa25ks2j.-; [B1, B5, B6, V3] # ςු٠.-
+ς‍ු٠。-; ς‍ු٠.-; [B1, B5, B6, C2, V3]; xn--3xa45ks2jenu.-; ; xn--4xa25ks2j.-; [B1, B5, B6, V3] # ςු٠.-
+Σ‍ු٠。-; σ‍ු٠.-; [B1, B5, B6, C2, V3]; xn--4xa25ks2jenu.-; ; xn--4xa25ks2j.-; [B1, B5, B6, V3] # σු٠.-
+σ‍ු٠。-; σ‍ු٠.-; [B1, B5, B6, C2, V3]; xn--4xa25ks2jenu.-; ; xn--4xa25ks2j.-; [B1, B5, B6, V3] # σු٠.-
+xn--4xa25ks2j.-; σු٠.-; [B1, B5, B6, V3]; xn--4xa25ks2j.-; ; ; # σු٠.-
+xn--4xa25ks2jenu.-; σ‍ු٠.-; [B1, B5, B6, C2, V3]; xn--4xa25ks2jenu.-; ; ; # σු٠.-
+xn--3xa45ks2jenu.-; ς‍ු٠.-; [B1, B5, B6, C2, V3]; xn--3xa45ks2jenu.-; ; ; # ςු٠.-
+Σ‍ු٠。-; σ‍ු٠.-; [B1, B5, B6, C2, V3]; xn--4xa25ks2jenu.-; ; xn--4xa25ks2j.-; [B1, B5, B6, V3] # σු٠.-
+σ‍ු٠。-; σ‍ු٠.-; [B1, B5, B6, C2, V3]; xn--4xa25ks2jenu.-; ; xn--4xa25ks2j.-; [B1, B5, B6, V3] # σු٠.-
+‌.ßႩ-; ; [C1, P1, V3, V6]; xn--0ug.xn----pfa042j; ; .xn--ss--4rn; [P1, V3, V6, A4_2] # .ßႩ-
+‌.ßⴉ-; ; [C1, V3]; xn--0ug.xn----pfa2305a; ; .xn--ss--bi1b; [V3, A4_2] # .ßⴉ-
+‌.SSႩ-; ‌.ssႩ-; [C1, P1, V3, V6]; xn--0ug.xn--ss--4rn; ; .xn--ss--4rn; [P1, V3, V6, A4_2] # .ssႩ-
+‌.ssⴉ-; ; [C1, V3]; xn--0ug.xn--ss--bi1b; ; .xn--ss--bi1b; [V3, A4_2] # .ssⴉ-
+‌.Ssⴉ-; ‌.ssⴉ-; [C1, V3]; xn--0ug.xn--ss--bi1b; ; .xn--ss--bi1b; [V3, A4_2] # .ssⴉ-
+.xn--ss--bi1b; .ssⴉ-; [V3, X4_2]; .xn--ss--bi1b; [V3, A4_2]; ; # .ssⴉ-
+xn--0ug.xn--ss--bi1b; ‌.ssⴉ-; [C1, V3]; xn--0ug.xn--ss--bi1b; ; ; # .ssⴉ-
+.xn--ss--4rn; .ssႩ-; [V3, V6, X4_2]; .xn--ss--4rn; [V3, V6, A4_2]; ; # .ssႩ-
+xn--0ug.xn--ss--4rn; ‌.ssႩ-; [C1, V3, V6]; xn--0ug.xn--ss--4rn; ; ; # .ssႩ-
+xn--0ug.xn----pfa2305a; ‌.ßⴉ-; [C1, V3]; xn--0ug.xn----pfa2305a; ; ; # .ßⴉ-
+xn--0ug.xn----pfa042j; ‌.ßႩ-; [C1, V3, V6]; xn--0ug.xn----pfa042j; ; ; # .ßႩ-
+󍭲𐫍㓱。⾑; 󍭲𐫍㓱.襾; [B5, P1, V6]; xn--u7kt691dlj09f.xn--9v2a; ; ; # 𐫍㓱.襾
+󍭲𐫍㓱。襾; 󍭲𐫍㓱.襾; [B5, P1, V6]; xn--u7kt691dlj09f.xn--9v2a; ; ; # 𐫍㓱.襾
+xn--u7kt691dlj09f.xn--9v2a; 󍭲𐫍㓱.襾; [B5, V6]; xn--u7kt691dlj09f.xn--9v2a; ; ; # 𐫍㓱.襾
+ڠ𐮋𐹰≮。≯󠦗‍; ڠ𐮋𐹰≮.≯󠦗‍; [B1, B3, C2, P1, V6]; xn--2jb053lf13nyoc.xn--1ugx6gc8096c; ; xn--2jb053lf13nyoc.xn--hdh08821l; [B1, B3, P1, V6] # ڠ𐮋𐹰≮.≯
+ڠ𐮋𐹰≮。≯󠦗‍; ڠ𐮋𐹰≮.≯󠦗‍; [B1, B3, C2, P1, V6]; xn--2jb053lf13nyoc.xn--1ugx6gc8096c; ; xn--2jb053lf13nyoc.xn--hdh08821l; [B1, B3, P1, V6] # ڠ𐮋𐹰≮.≯
+xn--2jb053lf13nyoc.xn--hdh08821l; ڠ𐮋𐹰≮.≯󠦗; [B1, B3, V6]; xn--2jb053lf13nyoc.xn--hdh08821l; ; ; # ڠ𐮋𐹰≮.≯
+xn--2jb053lf13nyoc.xn--1ugx6gc8096c; ڠ𐮋𐹰≮.≯󠦗‍; [B1, B3, C2, V6]; xn--2jb053lf13nyoc.xn--1ugx6gc8096c; ; ; # ڠ𐮋𐹰≮.≯
+𝟞。񃰶ݷࢰ⩋; 6.񃰶ݷࢰ⩋; [B1, B5, B6, P1, V6]; 6.xn--7pb04do15eq748f; ; ; # 6.ݷࢰ⩋
+6。񃰶ݷࢰ⩋; 6.񃰶ݷࢰ⩋; [B1, B5, B6, P1, V6]; 6.xn--7pb04do15eq748f; ; ; # 6.ݷࢰ⩋
+6.xn--7pb04do15eq748f; 6.񃰶ݷࢰ⩋; [B1, B5, B6, V6]; 6.xn--7pb04do15eq748f; ; ; # 6.ݷࢰ⩋
+-ﳽ。𑇀𑍴; -شى.𑇀𑍴; [B1, V3, V5]; xn----qnc7d.xn--wd1d62a; ; ; # -شى.𑇀𑍴
+-ﳽ。𑇀𑍴; -شى.𑇀𑍴; [B1, V3, V5]; xn----qnc7d.xn--wd1d62a; ; ; # -شى.𑇀𑍴
+-شى。𑇀𑍴; -شى.𑇀𑍴; [B1, V3, V5]; xn----qnc7d.xn--wd1d62a; ; ; # -شى.𑇀𑍴
+xn----qnc7d.xn--wd1d62a; -شى.𑇀𑍴; [B1, V3, V5]; xn----qnc7d.xn--wd1d62a; ; ; # -شى.𑇀𑍴
+‌󠊶𝟏.ൃ򪥐𐹬󊓶; ‌󠊶1.ൃ򪥐𐹬󊓶; [B1, C1, P1, V5, V6]; xn--1-rgnu0071n.xn--mxc0872kcu37dnmem; ; xn--1-f521m.xn--mxc0872kcu37dnmem; [B1, P1, V5, V6] # 1.ൃ𐹬
+‌󠊶1.ൃ򪥐𐹬󊓶; ; [B1, C1, P1, V5, V6]; xn--1-rgnu0071n.xn--mxc0872kcu37dnmem; ; xn--1-f521m.xn--mxc0872kcu37dnmem; [B1, P1, V5, V6] # 1.ൃ𐹬
+xn--1-f521m.xn--mxc0872kcu37dnmem; 󠊶1.ൃ򪥐𐹬󊓶; [B1, V5, V6]; xn--1-f521m.xn--mxc0872kcu37dnmem; ; ; # 1.ൃ𐹬
+xn--1-rgnu0071n.xn--mxc0872kcu37dnmem; ‌󠊶1.ൃ򪥐𐹬󊓶; [B1, C1, V5, V6]; xn--1-rgnu0071n.xn--mxc0872kcu37dnmem; ; ; # 1.ൃ𐹬
+齙--𝟰.ß; 齙--4.ß; ; xn----4-p16k.xn--zca; ; xn----4-p16k.ss; # 齙--4.ß
+齙--4.ß; ; ; xn----4-p16k.xn--zca; ; xn----4-p16k.ss; # 齙--4.ß
+齙--4.SS; 齙--4.ss; ; xn----4-p16k.ss; ; ; # 齙--4.ss
+齙--4.ss; ; ; xn----4-p16k.ss; ; ; # 齙--4.ss
+齙--4.Ss; 齙--4.ss; ; xn----4-p16k.ss; ; ; # 齙--4.ss
+xn----4-p16k.ss; 齙--4.ss; ; xn----4-p16k.ss; ; ; # 齙--4.ss
+xn----4-p16k.xn--zca; 齙--4.ß; ; xn----4-p16k.xn--zca; ; ; # 齙--4.ß
+齙--𝟰.SS; 齙--4.ss; ; xn----4-p16k.ss; ; ; # 齙--4.ss
+齙--𝟰.ss; 齙--4.ss; ; xn----4-p16k.ss; ; ; # 齙--4.ss
+齙--𝟰.Ss; 齙--4.ss; ; xn----4-p16k.ss; ; ; # 齙--4.ss
+᯲.𐹢𞀖‌; ; [B1, C1, V5]; xn--0zf.xn--0ug9894grqqf; ; xn--0zf.xn--9n0d2296a; [B1, V5] # ᯲.𐹢𞀖
+xn--0zf.xn--9n0d2296a; ᯲.𐹢𞀖; [B1, V5]; xn--0zf.xn--9n0d2296a; ; ; # ᯲.𐹢𞀖
+xn--0zf.xn--0ug9894grqqf; ᯲.𐹢𞀖‌; [B1, C1, V5]; xn--0zf.xn--0ug9894grqqf; ; ; # ᯲.𐹢𞀖
+󃲙󠋘。?-‍; 󃲙󠋘.?-‍; [C2, P1, V6]; xn--ct86d8w51a.xn--?--n1t; ; xn--ct86d8w51a.?-; [P1, V3, V6] # .?-
+󃲙󠋘。?-‍; 󃲙󠋘.?-‍; [C2, P1, V6]; xn--ct86d8w51a.xn--?--n1t; ; xn--ct86d8w51a.?-; [P1, V3, V6] # .?-
+xn--ct86d8w51a.?-; 󃲙󠋘.?-; [P1, V3, V6]; xn--ct86d8w51a.?-; ; ; # .?-
+xn--ct86d8w51a.xn--?--n1t; 󃲙󠋘.?-‍; [C2, P1, V6]; xn--ct86d8w51a.xn--?--n1t; ; ; # .?-
+xn--ct86d8w51a.?-‍; 󃲙󠋘.?-‍; [C2, P1, V6]; xn--ct86d8w51a.xn--?--n1t; ; xn--ct86d8w51a.?-; [P1, V3, V6] # .?-
+XN--CT86D8W51A.?-‍; 󃲙󠋘.?-‍; [C2, P1, V6]; xn--ct86d8w51a.xn--?--n1t; ; xn--ct86d8w51a.?-; [P1, V3, V6] # .?-
+Xn--Ct86d8w51a.?-‍; 󃲙󠋘.?-‍; [C2, P1, V6]; xn--ct86d8w51a.xn--?--n1t; ; xn--ct86d8w51a.?-; [P1, V3, V6] # .?-
+᩠.𞵷-𝪩悎; ᩠.𞵷-𝪩悎; [B1, B2, B3, B6, P1, V5, V6]; xn--jof.xn----gf4bq282iezpa; ; ; # ᩠.-𝪩悎
+᩠.𞵷-𝪩悎; ; [B1, B2, B3, B6, P1, V5, V6]; xn--jof.xn----gf4bq282iezpa; ; ; # ᩠.-𝪩悎
+xn--jof.xn----gf4bq282iezpa; ᩠.𞵷-𝪩悎; [B1, B2, B3, B6, V5, V6]; xn--jof.xn----gf4bq282iezpa; ; ; # ᩠.-𝪩悎
+𛜯󠊛.𞤳񏥾; 𛜯󠊛.𞤳񏥾; [B2, B3, B6, P1, V6]; xn--xx5gy2741c.xn--re6hw266j; ; ; # .𞤳
+𛜯󠊛.𞤳񏥾; ; [B2, B3, B6, P1, V6]; xn--xx5gy2741c.xn--re6hw266j; ; ; # .𞤳
+𛜯󠊛.𞤑񏥾; 𛜯󠊛.𞤳񏥾; [B2, B3, B6, P1, V6]; xn--xx5gy2741c.xn--re6hw266j; ; ; # .𞤳
+xn--xx5gy2741c.xn--re6hw266j; 𛜯󠊛.𞤳񏥾; [B2, B3, B6, V6]; xn--xx5gy2741c.xn--re6hw266j; ; ; # .𞤳
+𛜯󠊛.𞤑񏥾; 𛜯󠊛.𞤳񏥾; [B2, B3, B6, P1, V6]; xn--xx5gy2741c.xn--re6hw266j; ; ; # .𞤳
+ܜ𐫒خ.𐋲; ; [B1]; xn--tgb98b8643d.xn--m97c; ; ; # ܜ𐫒خ.𐋲
+xn--tgb98b8643d.xn--m97c; ܜ𐫒خ.𐋲; [B1]; xn--tgb98b8643d.xn--m97c; ; ; # ܜ𐫒خ.𐋲
+𐼑𞤓ط࣢.?; 𐼑𞤵ط࣢.?; [B1, P1, V6]; xn--2gb08k9w69agm0g.?; ; ; # 𐼑𞤵ط.?
+𐼑𞤵ط࣢.?; ; [B1, P1, V6]; xn--2gb08k9w69agm0g.?; ; ; # 𐼑𞤵ط.?
+xn--2gb08k9w69agm0g.?; 𐼑𞤵ط࣢.?; [B1, P1, V6]; xn--2gb08k9w69agm0g.?; ; ; # 𐼑𞤵ط.?
+Ↄ。᳔੍𞷣; Ↄ.᳔੍𞷣; [B1, P1, V5, V6]; xn--q5g.xn--ybc995g0835a; ; ; # Ↄ.᳔੍
+Ↄ。᳔੍𞷣; Ↄ.᳔੍𞷣; [B1, P1, V5, V6]; xn--q5g.xn--ybc995g0835a; ; ; # Ↄ.᳔੍
+ↄ。᳔੍𞷣; ↄ.᳔੍𞷣; [B1, P1, V5, V6]; xn--r5g.xn--ybc995g0835a; ; ; # ↄ.᳔੍
+xn--r5g.xn--ybc995g0835a; ↄ.᳔੍𞷣; [B1, V5, V6]; xn--r5g.xn--ybc995g0835a; ; ; # ↄ.᳔੍
+xn--q5g.xn--ybc995g0835a; Ↄ.᳔੍𞷣; [B1, V5, V6]; xn--q5g.xn--ybc995g0835a; ; ; # Ↄ.᳔੍
+ↄ。᳔੍𞷣; ↄ.᳔੍𞷣; [B1, P1, V5, V6]; xn--r5g.xn--ybc995g0835a; ; ; # ↄ.᳔੍
+󠪢-。򛂏≮𑜫; 󠪢-.򛂏≮𑜫; [P1, V3, V6]; xn----bh61m.xn--gdhz157g0em1d; ; ; # -.≮𑜫
+󠪢-。򛂏≮𑜫; 󠪢-.򛂏≮𑜫; [P1, V3, V6]; xn----bh61m.xn--gdhz157g0em1d; ; ; # -.≮𑜫
+xn----bh61m.xn--gdhz157g0em1d; 󠪢-.򛂏≮𑜫; [V3, V6]; xn----bh61m.xn--gdhz157g0em1d; ; ; # -.≮𑜫
+‌󠉹‍。򌿧≮Ⴉ; ‌󠉹‍.򌿧≮Ⴉ; [C1, C2, P1, V6]; xn--0ugc90904y.xn--hnd112gpz83n; ; xn--3n36e.xn--hnd112gpz83n; [P1, V6] # .≮Ⴉ
+‌󠉹‍。򌿧≮Ⴉ; ‌󠉹‍.򌿧≮Ⴉ; [C1, C2, P1, V6]; xn--0ugc90904y.xn--hnd112gpz83n; ; xn--3n36e.xn--hnd112gpz83n; [P1, V6] # .≮Ⴉ
+‌󠉹‍。򌿧≮ⴉ; ‌󠉹‍.򌿧≮ⴉ; [C1, C2, P1, V6]; xn--0ugc90904y.xn--gdh992byu01p; ; xn--3n36e.xn--gdh992byu01p; [P1, V6] # .≮ⴉ
+‌󠉹‍。򌿧≮ⴉ; ‌󠉹‍.򌿧≮ⴉ; [C1, C2, P1, V6]; xn--0ugc90904y.xn--gdh992byu01p; ; xn--3n36e.xn--gdh992byu01p; [P1, V6] # .≮ⴉ
+xn--3n36e.xn--gdh992byu01p; 󠉹.򌿧≮ⴉ; [V6]; xn--3n36e.xn--gdh992byu01p; ; ; # .≮ⴉ
+xn--0ugc90904y.xn--gdh992byu01p; ‌󠉹‍.򌿧≮ⴉ; [C1, C2, V6]; xn--0ugc90904y.xn--gdh992byu01p; ; ; # .≮ⴉ
+xn--3n36e.xn--hnd112gpz83n; 󠉹.򌿧≮Ⴉ; [V6]; xn--3n36e.xn--hnd112gpz83n; ; ; # .≮Ⴉ
+xn--0ugc90904y.xn--hnd112gpz83n; ‌󠉹‍.򌿧≮Ⴉ; [C1, C2, V6]; xn--0ugc90904y.xn--hnd112gpz83n; ; ; # .≮Ⴉ
+𐹯-𑄴ࢼ。︒䖐⾆; 𐹯-𑄴ࢼ.︒䖐舌; [B1, P1, V6]; xn----rpd7902rclc.xn--fpo216mn07e; ; ; # 𐹯-𑄴ࢼ.︒䖐舌
+𐹯-𑄴ࢼ。。䖐舌; 𐹯-𑄴ࢼ..䖐舌; [B1, X4_2]; xn----rpd7902rclc..xn--fpo216m; [B1, A4_2]; ; # 𐹯-𑄴ࢼ..䖐舌
+xn----rpd7902rclc..xn--fpo216m; 𐹯-𑄴ࢼ..䖐舌; [B1, X4_2]; xn----rpd7902rclc..xn--fpo216m; [B1, A4_2]; ; # 𐹯-𑄴ࢼ..䖐舌
+xn----rpd7902rclc.xn--fpo216mn07e; 𐹯-𑄴ࢼ.︒䖐舌; [B1, V6]; xn----rpd7902rclc.xn--fpo216mn07e; ; ; # 𐹯-𑄴ࢼ.︒䖐舌
+𝪞Ⴐ。쪡; 𝪞Ⴐ.쪡; [P1, V5, V6]; xn--ond3755u.xn--pi6b; ; ; # 𝪞Ⴐ.쪡
+𝪞Ⴐ。쪡; 𝪞Ⴐ.쪡; [P1, V5, V6]; xn--ond3755u.xn--pi6b; ; ; # 𝪞Ⴐ.쪡
+𝪞Ⴐ。쪡; 𝪞Ⴐ.쪡; [P1, V5, V6]; xn--ond3755u.xn--pi6b; ; ; # 𝪞Ⴐ.쪡
+𝪞Ⴐ。쪡; 𝪞Ⴐ.쪡; [P1, V5, V6]; xn--ond3755u.xn--pi6b; ; ; # 𝪞Ⴐ.쪡
+𝪞ⴐ。쪡; 𝪞ⴐ.쪡; [V5]; xn--7kj1858k.xn--pi6b; ; ; # 𝪞ⴐ.쪡
+𝪞ⴐ。쪡; 𝪞ⴐ.쪡; [V5]; xn--7kj1858k.xn--pi6b; ; ; # 𝪞ⴐ.쪡
+xn--7kj1858k.xn--pi6b; 𝪞ⴐ.쪡; [V5]; xn--7kj1858k.xn--pi6b; ; ; # 𝪞ⴐ.쪡
+xn--ond3755u.xn--pi6b; 𝪞Ⴐ.쪡; [V5, V6]; xn--ond3755u.xn--pi6b; ; ; # 𝪞Ⴐ.쪡
+𝪞ⴐ。쪡; 𝪞ⴐ.쪡; [V5]; xn--7kj1858k.xn--pi6b; ; ; # 𝪞ⴐ.쪡
+𝪞ⴐ。쪡; 𝪞ⴐ.쪡; [V5]; xn--7kj1858k.xn--pi6b; ; ; # 𝪞ⴐ.쪡
+ฺ쩁𐹬.􋉳; ; [B1, P1, V5, V6]; xn--o4c4837g2zvb.xn--5f70g; ; ; # ฺ쩁𐹬.
+ฺ쩁𐹬.􋉳; ฺ쩁𐹬.􋉳; [B1, P1, V5, V6]; xn--o4c4837g2zvb.xn--5f70g; ; ; # ฺ쩁𐹬.
+xn--o4c4837g2zvb.xn--5f70g; ฺ쩁𐹬.􋉳; [B1, V5, V6]; xn--o4c4837g2zvb.xn--5f70g; ; ; # ฺ쩁𐹬.
+ᡅ0‌。⎢󤨄; ᡅ0‌.⎢󤨄; [C1, P1, V6]; xn--0-z6jy93b.xn--8lh28773l; ; xn--0-z6j.xn--8lh28773l; [P1, V6] # ᡅ0.⎢
+ᡅ0‌。⎢󤨄; ᡅ0‌.⎢󤨄; [C1, P1, V6]; xn--0-z6jy93b.xn--8lh28773l; ; xn--0-z6j.xn--8lh28773l; [P1, V6] # ᡅ0.⎢
+xn--0-z6j.xn--8lh28773l; ᡅ0.⎢󤨄; [V6]; xn--0-z6j.xn--8lh28773l; ; ; # ᡅ0.⎢
+xn--0-z6jy93b.xn--8lh28773l; ᡅ0‌.⎢󤨄; [C1, V6]; xn--0-z6jy93b.xn--8lh28773l; ; ; # ᡅ0.⎢
+𲮚9ꍩ៓.‍ß; 𲮚9ꍩ៓.‍ß; [C2, P1, V6]; xn--9-i0j5967eg3qz.xn--zca770n; ; xn--9-i0j5967eg3qz.ss; [P1, V6] # 9ꍩ៓.ß
+𲮚9ꍩ៓.‍ß; ; [C2, P1, V6]; xn--9-i0j5967eg3qz.xn--zca770n; ; xn--9-i0j5967eg3qz.ss; [P1, V6] # 9ꍩ៓.ß
+𲮚9ꍩ៓.‍SS; 𲮚9ꍩ៓.‍ss; [C2, P1, V6]; xn--9-i0j5967eg3qz.xn--ss-l1t; ; xn--9-i0j5967eg3qz.ss; [P1, V6] # 9ꍩ៓.ss
+𲮚9ꍩ៓.‍ss; ; [C2, P1, V6]; xn--9-i0j5967eg3qz.xn--ss-l1t; ; xn--9-i0j5967eg3qz.ss; [P1, V6] # 9ꍩ៓.ss
+xn--9-i0j5967eg3qz.ss; 𲮚9ꍩ៓.ss; [V6]; xn--9-i0j5967eg3qz.ss; ; ; # 9ꍩ៓.ss
+xn--9-i0j5967eg3qz.xn--ss-l1t; 𲮚9ꍩ៓.‍ss; [C2, V6]; xn--9-i0j5967eg3qz.xn--ss-l1t; ; ; # 9ꍩ៓.ss
+xn--9-i0j5967eg3qz.xn--zca770n; 𲮚9ꍩ៓.‍ß; [C2, V6]; xn--9-i0j5967eg3qz.xn--zca770n; ; ; # 9ꍩ៓.ß
+𲮚9ꍩ៓.‍SS; 𲮚9ꍩ៓.‍ss; [C2, P1, V6]; xn--9-i0j5967eg3qz.xn--ss-l1t; ; xn--9-i0j5967eg3qz.ss; [P1, V6] # 9ꍩ៓.ss
+𲮚9ꍩ៓.‍ss; 𲮚9ꍩ៓.‍ss; [C2, P1, V6]; xn--9-i0j5967eg3qz.xn--ss-l1t; ; xn--9-i0j5967eg3qz.ss; [P1, V6] # 9ꍩ៓.ss
+𲮚9ꍩ៓.‍Ss; 𲮚9ꍩ៓.‍ss; [C2, P1, V6]; xn--9-i0j5967eg3qz.xn--ss-l1t; ; xn--9-i0j5967eg3qz.ss; [P1, V6] # 9ꍩ៓.ss
+𲮚9ꍩ៓.‍Ss; 𲮚9ꍩ៓.‍ss; [C2, P1, V6]; xn--9-i0j5967eg3qz.xn--ss-l1t; ; xn--9-i0j5967eg3qz.ss; [P1, V6] # 9ꍩ៓.ss
+ꗷ𑆀.ݝ𐩒; ; ; xn--ju8a625r.xn--hpb0073k; ; ; # ꗷ𑆀.ݝ𐩒
+xn--ju8a625r.xn--hpb0073k; ꗷ𑆀.ݝ𐩒; ; xn--ju8a625r.xn--hpb0073k; ; ; # ꗷ𑆀.ݝ𐩒
+⒐≯-。︒򩑣-񞛠; ⒐≯-.︒򩑣-񞛠; [P1, V3, V6]; xn----ogot9g.xn----n89hl0522az9u2a; ; ; # ⒐≯-.︒-
+⒐≯-。︒򩑣-񞛠; ⒐≯-.︒򩑣-񞛠; [P1, V3, V6]; xn----ogot9g.xn----n89hl0522az9u2a; ; ; # ⒐≯-.︒-
+9.≯-。。򩑣-񞛠; 9.≯-..򩑣-񞛠; [P1, V3, V6, X4_2]; 9.xn----ogo..xn----xj54d1s69k; [P1, V3, V6, A4_2]; ; # 9.≯-..-
+9.≯-。。򩑣-񞛠; 9.≯-..򩑣-񞛠; [P1, V3, V6, X4_2]; 9.xn----ogo..xn----xj54d1s69k; [P1, V3, V6, A4_2]; ; # 9.≯-..-
+9.xn----ogo..xn----xj54d1s69k; 9.≯-..򩑣-񞛠; [V3, V6, X4_2]; 9.xn----ogo..xn----xj54d1s69k; [V3, V6, A4_2]; ; # 9.≯-..-
+xn----ogot9g.xn----n89hl0522az9u2a; ⒐≯-.︒򩑣-񞛠; [V3, V6]; xn----ogot9g.xn----n89hl0522az9u2a; ; ; # ⒐≯-.︒-
+򈪚ೣჁ󠢏.؝; 򈪚ೣჁ󠢏.؝; [B6, P1, V6]; xn--vuc49qvu85xmju7a.xn--cgb; ; ; # ೣჁ.؝
+򈪚ೣჁ󠢏.؝; ; [B6, P1, V6]; xn--vuc49qvu85xmju7a.xn--cgb; ; ; # ೣჁ.؝
+򈪚ೣⴡ󠢏.؝; ; [B6, P1, V6]; xn--vuc226n8n28lmju7a.xn--cgb; ; ; # ೣⴡ.؝
+xn--vuc226n8n28lmju7a.xn--cgb; 򈪚ೣⴡ󠢏.؝; [B6, V6]; xn--vuc226n8n28lmju7a.xn--cgb; ; ; # ೣⴡ.؝
+xn--vuc49qvu85xmju7a.xn--cgb; 򈪚ೣჁ󠢏.؝; [B6, V6]; xn--vuc49qvu85xmju7a.xn--cgb; ; ; # ೣჁ.؝
+򈪚ೣⴡ󠢏.؝; 򈪚ೣⴡ󠢏.؝; [B6, P1, V6]; xn--vuc226n8n28lmju7a.xn--cgb; ; ; # ೣⴡ.؝
+ᷫ。𐋩ظ-𐫮; ᷫ.𐋩ظ-𐫮; [B1, B3, B6, V5]; xn--gfg.xn----xnc0815qyyg; ; ; # ᷫ.𐋩ظ-𐫮
+xn--gfg.xn----xnc0815qyyg; ᷫ.𐋩ظ-𐫮; [B1, B3, B6, V5]; xn--gfg.xn----xnc0815qyyg; ; ; # ᷫ.𐋩ظ-𐫮
+싇。⾇𐳋Ⴝ; 싇.舛𐳋Ⴝ; [B5, P1, V6]; xn--9u4b.xn--1nd7519ch79d; ; ; # 싇.舛𐳋Ⴝ
+싇。⾇𐳋Ⴝ; 싇.舛𐳋Ⴝ; [B5, P1, V6]; xn--9u4b.xn--1nd7519ch79d; ; ; # 싇.舛𐳋Ⴝ
+싇。舛𐳋Ⴝ; 싇.舛𐳋Ⴝ; [B5, P1, V6]; xn--9u4b.xn--1nd7519ch79d; ; ; # 싇.舛𐳋Ⴝ
+싇。舛𐳋Ⴝ; 싇.舛𐳋Ⴝ; [B5, P1, V6]; xn--9u4b.xn--1nd7519ch79d; ; ; # 싇.舛𐳋Ⴝ
+싇。舛𐳋ⴝ; 싇.舛𐳋ⴝ; [B5]; xn--9u4b.xn--llj123yh74e; ; ; # 싇.舛𐳋ⴝ
+싇。舛𐳋ⴝ; 싇.舛𐳋ⴝ; [B5]; xn--9u4b.xn--llj123yh74e; ; ; # 싇.舛𐳋ⴝ
+싇。舛𐲋Ⴝ; 싇.舛𐳋Ⴝ; [B5, P1, V6]; xn--9u4b.xn--1nd7519ch79d; ; ; # 싇.舛𐳋Ⴝ
+싇。舛𐲋Ⴝ; 싇.舛𐳋Ⴝ; [B5, P1, V6]; xn--9u4b.xn--1nd7519ch79d; ; ; # 싇.舛𐳋Ⴝ
+싇。舛𐲋ⴝ; 싇.舛𐳋ⴝ; [B5]; xn--9u4b.xn--llj123yh74e; ; ; # 싇.舛𐳋ⴝ
+싇。舛𐲋ⴝ; 싇.舛𐳋ⴝ; [B5]; xn--9u4b.xn--llj123yh74e; ; ; # 싇.舛𐳋ⴝ
+xn--9u4b.xn--llj123yh74e; 싇.舛𐳋ⴝ; [B5]; xn--9u4b.xn--llj123yh74e; ; ; # 싇.舛𐳋ⴝ
+xn--9u4b.xn--1nd7519ch79d; 싇.舛𐳋Ⴝ; [B5, V6]; xn--9u4b.xn--1nd7519ch79d; ; ; # 싇.舛𐳋Ⴝ
+싇。⾇𐳋ⴝ; 싇.舛𐳋ⴝ; [B5]; xn--9u4b.xn--llj123yh74e; ; ; # 싇.舛𐳋ⴝ
+싇。⾇𐳋ⴝ; 싇.舛𐳋ⴝ; [B5]; xn--9u4b.xn--llj123yh74e; ; ; # 싇.舛𐳋ⴝ
+싇。⾇𐲋Ⴝ; 싇.舛𐳋Ⴝ; [B5, P1, V6]; xn--9u4b.xn--1nd7519ch79d; ; ; # 싇.舛𐳋Ⴝ
+싇。⾇𐲋Ⴝ; 싇.舛𐳋Ⴝ; [B5, P1, V6]; xn--9u4b.xn--1nd7519ch79d; ; ; # 싇.舛𐳋Ⴝ
+싇。⾇𐲋ⴝ; 싇.舛𐳋ⴝ; [B5]; xn--9u4b.xn--llj123yh74e; ; ; # 싇.舛𐳋ⴝ
+싇。⾇𐲋ⴝ; 싇.舛𐳋ⴝ; [B5]; xn--9u4b.xn--llj123yh74e; ; ; # 싇.舛𐳋ⴝ
+𐹠ς。‌ڿჀ; 𐹠ς.‌ڿჀ; [B1, C1, P1, V6]; xn--3xa1267k.xn--ykb632cvxm; ; xn--4xa9167k.xn--ykb632c; [B1, B2, B3, P1, V6] # 𐹠ς.ڿჀ
+𐹠ς。‌ڿⴠ; 𐹠ς.‌ڿⴠ; [B1, C1]; xn--3xa1267k.xn--ykb760k9hj; ; xn--4xa9167k.xn--ykb467q; [B1, B2, B3] # 𐹠ς.ڿⴠ
+𐹠Σ。‌ڿჀ; 𐹠σ.‌ڿჀ; [B1, C1, P1, V6]; xn--4xa9167k.xn--ykb632cvxm; ; xn--4xa9167k.xn--ykb632c; [B1, B2, B3, P1, V6] # 𐹠σ.ڿჀ
+𐹠σ。‌ڿⴠ; 𐹠σ.‌ڿⴠ; [B1, C1]; xn--4xa9167k.xn--ykb760k9hj; ; xn--4xa9167k.xn--ykb467q; [B1, B2, B3] # 𐹠σ.ڿⴠ
+𐹠Σ。‌ڿⴠ; 𐹠σ.‌ڿⴠ; [B1, C1]; xn--4xa9167k.xn--ykb760k9hj; ; xn--4xa9167k.xn--ykb467q; [B1, B2, B3] # 𐹠σ.ڿⴠ
+xn--4xa9167k.xn--ykb467q; 𐹠σ.ڿⴠ; [B1, B2, B3]; xn--4xa9167k.xn--ykb467q; ; ; # 𐹠σ.ڿⴠ
+xn--4xa9167k.xn--ykb760k9hj; 𐹠σ.‌ڿⴠ; [B1, C1]; xn--4xa9167k.xn--ykb760k9hj; ; ; # 𐹠σ.ڿⴠ
+xn--4xa9167k.xn--ykb632c; 𐹠σ.ڿჀ; [B1, B2, B3, V6]; xn--4xa9167k.xn--ykb632c; ; ; # 𐹠σ.ڿჀ
+xn--4xa9167k.xn--ykb632cvxm; 𐹠σ.‌ڿჀ; [B1, C1, V6]; xn--4xa9167k.xn--ykb632cvxm; ; ; # 𐹠σ.ڿჀ
+xn--3xa1267k.xn--ykb760k9hj; 𐹠ς.‌ڿⴠ; [B1, C1]; xn--3xa1267k.xn--ykb760k9hj; ; ; # 𐹠ς.ڿⴠ
+xn--3xa1267k.xn--ykb632cvxm; 𐹠ς.‌ڿჀ; [B1, C1, V6]; xn--3xa1267k.xn--ykb632cvxm; ; ; # 𐹠ς.ڿჀ
+򇒐‌؄.ښ-ß; ; [B2, B3, B5, B6, C1, P1, V6]; xn--mfb144kqo32m.xn----qfa315b; ; xn--mfb98261i.xn---ss-sdf; [B2, B3, B5, B6, P1, V6] # .ښ-ß
+򇒐‌؄.ښ-SS; 򇒐‌؄.ښ-ss; [B2, B3, B5, B6, C1, P1, V6]; xn--mfb144kqo32m.xn---ss-sdf; ; xn--mfb98261i.xn---ss-sdf; [B2, B3, B5, B6, P1, V6] # .ښ-ss
+򇒐‌؄.ښ-ss; ; [B2, B3, B5, B6, C1, P1, V6]; xn--mfb144kqo32m.xn---ss-sdf; ; xn--mfb98261i.xn---ss-sdf; [B2, B3, B5, B6, P1, V6] # .ښ-ss
+򇒐‌؄.ښ-Ss; 򇒐‌؄.ښ-ss; [B2, B3, B5, B6, C1, P1, V6]; xn--mfb144kqo32m.xn---ss-sdf; ; xn--mfb98261i.xn---ss-sdf; [B2, B3, B5, B6, P1, V6] # .ښ-ss
+xn--mfb98261i.xn---ss-sdf; 򇒐؄.ښ-ss; [B2, B3, B5, B6, V6]; xn--mfb98261i.xn---ss-sdf; ; ; # .ښ-ss
+xn--mfb144kqo32m.xn---ss-sdf; 򇒐‌؄.ښ-ss; [B2, B3, B5, B6, C1, V6]; xn--mfb144kqo32m.xn---ss-sdf; ; ; # .ښ-ss
+xn--mfb144kqo32m.xn----qfa315b; 򇒐‌؄.ښ-ß; [B2, B3, B5, B6, C1, V6]; xn--mfb144kqo32m.xn----qfa315b; ; ; # .ښ-ß
+‌‍឵ٺ.-ﮰ󅄞𐸚; ‌‍឵ٺ.-ۓ󅄞𐸚; [B1, C1, C2, P1, V3, V6]; xn--zib539f8igea.xn----twc1133r17r6g; ; xn--zib539f.xn----twc1133r17r6g; [B1, P1, V3, V5, V6] # ٺ.-ۓ
+‌‍឵ٺ.-ۓ󅄞𐸚; ; [B1, C1, C2, P1, V3, V6]; xn--zib539f8igea.xn----twc1133r17r6g; ; xn--zib539f.xn----twc1133r17r6g; [B1, P1, V3, V5, V6] # ٺ.-ۓ
+‌‍឵ٺ.-ۓ󅄞𐸚; ‌‍឵ٺ.-ۓ󅄞𐸚; [B1, C1, C2, P1, V3, V6]; xn--zib539f8igea.xn----twc1133r17r6g; ; xn--zib539f.xn----twc1133r17r6g; [B1, P1, V3, V5, V6] # ٺ.-ۓ
+xn--zib539f.xn----twc1133r17r6g; ឵ٺ.-ۓ󅄞𐸚; [B1, V3, V5, V6]; xn--zib539f.xn----twc1133r17r6g; ; ; # ٺ.-ۓ
+xn--zib539f8igea.xn----twc1133r17r6g; ‌‍឵ٺ.-ۓ󅄞𐸚; [B1, C1, C2, V3, V6]; xn--zib539f8igea.xn----twc1133r17r6g; ; ; # ٺ.-ۓ
+򡶱。𐮬≠; 򡶱.𐮬≠; [B3, P1, V6]; xn--dd55c.xn--1ch3003g; ; ; # .𐮬≠
+򡶱。𐮬≠; 򡶱.𐮬≠; [B3, P1, V6]; xn--dd55c.xn--1ch3003g; ; ; # .𐮬≠
+򡶱。𐮬≠; 򡶱.𐮬≠; [B3, P1, V6]; xn--dd55c.xn--1ch3003g; ; ; # .𐮬≠
+򡶱。𐮬≠; 򡶱.𐮬≠; [B3, P1, V6]; xn--dd55c.xn--1ch3003g; ; ; # .𐮬≠
+xn--dd55c.xn--1ch3003g; 򡶱.𐮬≠; [B3, V6]; xn--dd55c.xn--1ch3003g; ; ; # .𐮬≠
+ྲ𞶅。𐹮𐹷덝۵; ྲ𞶅.𐹮𐹷덝۵; [B1, P1, V5, V6]; xn--fgd0675v.xn--imb5839fidpcbba; ; ; # ྲ.𐹮𐹷덝۵
+ྲ𞶅。𐹮𐹷덝۵; ྲ𞶅.𐹮𐹷덝۵; [B1, P1, V5, V6]; xn--fgd0675v.xn--imb5839fidpcbba; ; ; # ྲ.𐹮𐹷덝۵
+ྲ𞶅。𐹮𐹷덝۵; ྲ𞶅.𐹮𐹷덝۵; [B1, P1, V5, V6]; xn--fgd0675v.xn--imb5839fidpcbba; ; ; # ྲ.𐹮𐹷덝۵
+ྲ𞶅。𐹮𐹷덝۵; ྲ𞶅.𐹮𐹷덝۵; [B1, P1, V5, V6]; xn--fgd0675v.xn--imb5839fidpcbba; ; ; # ྲ.𐹮𐹷덝۵
+xn--fgd0675v.xn--imb5839fidpcbba; ྲ𞶅.𐹮𐹷덝۵; [B1, V5, V6]; xn--fgd0675v.xn--imb5839fidpcbba; ; ; # ྲ.𐹮𐹷덝۵
+Ⴏ󠅋-.‍Ⴉ; Ⴏ-.‍Ⴉ; [C2, P1, V3, V6]; xn----00g.xn--hnd399e; ; xn----00g.xn--hnd; [P1, V3, V6] # Ⴏ-.Ⴉ
+Ⴏ󠅋-.‍Ⴉ; Ⴏ-.‍Ⴉ; [C2, P1, V3, V6]; xn----00g.xn--hnd399e; ; xn----00g.xn--hnd; [P1, V3, V6] # Ⴏ-.Ⴉ
+ⴏ󠅋-.‍ⴉ; ⴏ-.‍ⴉ; [C2, V3]; xn----3vs.xn--1ug532c; ; xn----3vs.xn--0kj; [V3] # ⴏ-.ⴉ
+xn----3vs.xn--0kj; ⴏ-.ⴉ; [V3]; xn----3vs.xn--0kj; ; ; # ⴏ-.ⴉ
+xn----3vs.xn--1ug532c; ⴏ-.‍ⴉ; [C2, V3]; xn----3vs.xn--1ug532c; ; ; # ⴏ-.ⴉ
+xn----00g.xn--hnd; Ⴏ-.Ⴉ; [V3, V6]; xn----00g.xn--hnd; ; ; # Ⴏ-.Ⴉ
+xn----00g.xn--hnd399e; Ⴏ-.‍Ⴉ; [C2, V3, V6]; xn----00g.xn--hnd399e; ; ; # Ⴏ-.Ⴉ
+ⴏ󠅋-.‍ⴉ; ⴏ-.‍ⴉ; [C2, V3]; xn----3vs.xn--1ug532c; ; xn----3vs.xn--0kj; [V3] # ⴏ-.ⴉ
+⇧𐨏󠾈󯶅。؀󠈵󠆉; ⇧𐨏󠾈󯶅.؀󠈵; [B1, P1, V6]; xn--l8g5552g64t4g46xf.xn--ifb08144p; ; ; # ⇧𐨏.
+xn--l8g5552g64t4g46xf.xn--ifb08144p; ⇧𐨏󠾈󯶅.؀󠈵; [B1, V6]; xn--l8g5552g64t4g46xf.xn--ifb08144p; ; ; # ⇧𐨏.
+≠𐮂.↑🄇⒈; ; [B1, P1, V6]; xn--1chy492g.xn--45gx9iuy44d; ; ; # ≠𐮂.↑🄇⒈
+≠𐮂.↑🄇⒈; ≠𐮂.↑🄇⒈; [B1, P1, V6]; xn--1chy492g.xn--45gx9iuy44d; ; ; # ≠𐮂.↑🄇⒈
+≠𐮂.↑6,1.; ; [B1, P1, V6]; xn--1chy492g.xn--6,1-pw1a.; ; ; # ≠𐮂.↑6,1.
+≠𐮂.↑6,1.; ≠𐮂.↑6,1.; [B1, P1, V6]; xn--1chy492g.xn--6,1-pw1a.; ; ; # ≠𐮂.↑6,1.
+xn--1chy492g.xn--6,1-pw1a.; ≠𐮂.↑6,1.; [B1, P1, V6]; xn--1chy492g.xn--6,1-pw1a.; ; ; # ≠𐮂.↑6,1.
+xn--1chy492g.xn--45gx9iuy44d; ≠𐮂.↑🄇⒈; [B1, V6]; xn--1chy492g.xn--45gx9iuy44d; ; ; # ≠𐮂.↑🄇⒈
+𝩏󠲉ß.ᢤ򄦌‌𐹫; ; [B1, B5, B6, C1, P1, V5, V6]; xn--zca3153vupz3e.xn--ubf609atw1tynn3d; ; xn--ss-zb11ap1427e.xn--ubf2596jbt61c; [B1, B5, B6, P1, V5, V6] # 𝩏ß.ᢤ𐹫
+𝩏󠲉SS.ᢤ򄦌‌𐹫; 𝩏󠲉ss.ᢤ򄦌‌𐹫; [B1, B5, B6, C1, P1, V5, V6]; xn--ss-zb11ap1427e.xn--ubf609atw1tynn3d; ; xn--ss-zb11ap1427e.xn--ubf2596jbt61c; [B1, B5, B6, P1, V5, V6] # 𝩏ss.ᢤ𐹫
+𝩏󠲉ss.ᢤ򄦌‌𐹫; ; [B1, B5, B6, C1, P1, V5, V6]; xn--ss-zb11ap1427e.xn--ubf609atw1tynn3d; ; xn--ss-zb11ap1427e.xn--ubf2596jbt61c; [B1, B5, B6, P1, V5, V6] # 𝩏ss.ᢤ𐹫
+𝩏󠲉Ss.ᢤ򄦌‌𐹫; 𝩏󠲉ss.ᢤ򄦌‌𐹫; [B1, B5, B6, C1, P1, V5, V6]; xn--ss-zb11ap1427e.xn--ubf609atw1tynn3d; ; xn--ss-zb11ap1427e.xn--ubf2596jbt61c; [B1, B5, B6, P1, V5, V6] # 𝩏ss.ᢤ𐹫
+xn--ss-zb11ap1427e.xn--ubf2596jbt61c; 𝩏󠲉ss.ᢤ򄦌𐹫; [B1, B5, B6, V5, V6]; xn--ss-zb11ap1427e.xn--ubf2596jbt61c; ; ; # 𝩏ss.ᢤ𐹫
+xn--ss-zb11ap1427e.xn--ubf609atw1tynn3d; 𝩏󠲉ss.ᢤ򄦌‌𐹫; [B1, B5, B6, C1, V5, V6]; xn--ss-zb11ap1427e.xn--ubf609atw1tynn3d; ; ; # 𝩏ss.ᢤ𐹫
+xn--zca3153vupz3e.xn--ubf609atw1tynn3d; 𝩏󠲉ß.ᢤ򄦌‌𐹫; [B1, B5, B6, C1, V5, V6]; xn--zca3153vupz3e.xn--ubf609atw1tynn3d; ; ; # 𝩏ß.ᢤ𐹫
+ß𐵳񗘁Ⴇ。ꙺ; ß𐵳񗘁Ⴇ.ꙺ; [B1, B3, B5, B6, P1, V5, V6]; xn--zca491fci5qkn79a.xn--9x8a; ; xn--ss-rek7420r4hs7b.xn--9x8a; # ßႧ.ꙺ
+ß𐵳񗘁Ⴇ。ꙺ; ß𐵳񗘁Ⴇ.ꙺ; [B1, B3, B5, B6, P1, V5, V6]; xn--zca491fci5qkn79a.xn--9x8a; ; xn--ss-rek7420r4hs7b.xn--9x8a; # ßႧ.ꙺ
+ß𐵳񗘁ⴇ。ꙺ; ß𐵳񗘁ⴇ.ꙺ; [B1, B3, B5, B6, P1, V5, V6]; xn--zca227tpy4lkns1b.xn--9x8a; ; xn--ss-e61ar955h4hs7b.xn--9x8a; # ßⴇ.ꙺ
+SS𐵳񗘁Ⴇ。ꙺ; ss𐵳񗘁Ⴇ.ꙺ; [B1, B3, B5, B6, P1, V5, V6]; xn--ss-rek7420r4hs7b.xn--9x8a; ; ; # ssႧ.ꙺ
+ss𐵳񗘁ⴇ。ꙺ; ss𐵳񗘁ⴇ.ꙺ; [B1, B3, B5, B6, P1, V5, V6]; xn--ss-e61ar955h4hs7b.xn--9x8a; ; ; # ssⴇ.ꙺ
+Ss𐵳񗘁Ⴇ。ꙺ; ss𐵳񗘁Ⴇ.ꙺ; [B1, B3, B5, B6, P1, V5, V6]; xn--ss-rek7420r4hs7b.xn--9x8a; ; ; # ssႧ.ꙺ
+xn--ss-rek7420r4hs7b.xn--9x8a; ss𐵳񗘁Ⴇ.ꙺ; [B1, B3, B5, B6, V5, V6]; xn--ss-rek7420r4hs7b.xn--9x8a; ; ; # ssႧ.ꙺ
+xn--ss-e61ar955h4hs7b.xn--9x8a; ss𐵳񗘁ⴇ.ꙺ; [B1, B3, B5, B6, V5, V6]; xn--ss-e61ar955h4hs7b.xn--9x8a; ; ; # ssⴇ.ꙺ
+xn--zca227tpy4lkns1b.xn--9x8a; ß𐵳񗘁ⴇ.ꙺ; [B1, B3, B5, B6, V5, V6]; xn--zca227tpy4lkns1b.xn--9x8a; ; ; # ßⴇ.ꙺ
+xn--zca491fci5qkn79a.xn--9x8a; ß𐵳񗘁Ⴇ.ꙺ; [B1, B3, B5, B6, V5, V6]; xn--zca491fci5qkn79a.xn--9x8a; ; ; # ßႧ.ꙺ
+ß𐵳񗘁ⴇ。ꙺ; ß𐵳񗘁ⴇ.ꙺ; [B1, B3, B5, B6, P1, V5, V6]; xn--zca227tpy4lkns1b.xn--9x8a; ; xn--ss-e61ar955h4hs7b.xn--9x8a; # ßⴇ.ꙺ
+SS𐵳񗘁Ⴇ。ꙺ; ss𐵳񗘁Ⴇ.ꙺ; [B1, B3, B5, B6, P1, V5, V6]; xn--ss-rek7420r4hs7b.xn--9x8a; ; ; # ssႧ.ꙺ
+ss𐵳񗘁ⴇ。ꙺ; ss𐵳񗘁ⴇ.ꙺ; [B1, B3, B5, B6, P1, V5, V6]; xn--ss-e61ar955h4hs7b.xn--9x8a; ; ; # ssⴇ.ꙺ
+Ss𐵳񗘁Ⴇ。ꙺ; ss𐵳񗘁Ⴇ.ꙺ; [B1, B3, B5, B6, P1, V5, V6]; xn--ss-rek7420r4hs7b.xn--9x8a; ; ; # ssႧ.ꙺ
+᜔。󠆣-𑋪; ᜔.-𑋪; [V3, V5]; xn--fze.xn----ly8i; ; ; # ᜔.-𑋪
+xn--fze.xn----ly8i; ᜔.-𑋪; [V3, V5]; xn--fze.xn----ly8i; ; ; # ᜔.-𑋪
+ꯨ-.򨏜ֽß; ꯨ-.򨏜ֽß; [P1, V3, V5, V6]; xn----pw5e.xn--zca50wfv060a; ; xn----pw5e.xn--ss-7jd10716y; # ꯨ-.ֽß
+ꯨ-.򨏜ֽß; ; [P1, V3, V5, V6]; xn----pw5e.xn--zca50wfv060a; ; xn----pw5e.xn--ss-7jd10716y; # ꯨ-.ֽß
+ꯨ-.򨏜ֽSS; ꯨ-.򨏜ֽss; [P1, V3, V5, V6]; xn----pw5e.xn--ss-7jd10716y; ; ; # ꯨ-.ֽss
+ꯨ-.򨏜ֽss; ; [P1, V3, V5, V6]; xn----pw5e.xn--ss-7jd10716y; ; ; # ꯨ-.ֽss
+ꯨ-.򨏜ֽSs; ꯨ-.򨏜ֽss; [P1, V3, V5, V6]; xn----pw5e.xn--ss-7jd10716y; ; ; # ꯨ-.ֽss
+xn----pw5e.xn--ss-7jd10716y; ꯨ-.򨏜ֽss; [V3, V5, V6]; xn----pw5e.xn--ss-7jd10716y; ; ; # ꯨ-.ֽss
+xn----pw5e.xn--zca50wfv060a; ꯨ-.򨏜ֽß; [V3, V5, V6]; xn----pw5e.xn--zca50wfv060a; ; ; # ꯨ-.ֽß
+ꯨ-.򨏜ֽSS; ꯨ-.򨏜ֽss; [P1, V3, V5, V6]; xn----pw5e.xn--ss-7jd10716y; ; ; # ꯨ-.ֽss
+ꯨ-.򨏜ֽss; ꯨ-.򨏜ֽss; [P1, V3, V5, V6]; xn----pw5e.xn--ss-7jd10716y; ; ; # ꯨ-.ֽss
+ꯨ-.򨏜ֽSs; ꯨ-.򨏜ֽss; [P1, V3, V5, V6]; xn----pw5e.xn--ss-7jd10716y; ; ; # ꯨ-.ֽss
+ᡓ-≮。٫󠅱ᡄ; ᡓ-≮.٫ᡄ; [B1, B6, P1, V6]; xn----s7j866c.xn--kib252g; ; ; # ᡓ-≮.٫ᡄ
+ᡓ-≮。٫󠅱ᡄ; ᡓ-≮.٫ᡄ; [B1, B6, P1, V6]; xn----s7j866c.xn--kib252g; ; ; # ᡓ-≮.٫ᡄ
+xn----s7j866c.xn--kib252g; ᡓ-≮.٫ᡄ; [B1, B6, V6]; xn----s7j866c.xn--kib252g; ; ; # ᡓ-≮.٫ᡄ
+𝟥♮𑜫࣭.្𑜫8󠆏; 3♮𑜫࣭.្𑜫8; [V5]; xn--3-ksd277tlo7s.xn--8-f0jx021l; ; ; # 3♮𑜫࣭.្𑜫8
+3♮𑜫࣭.្𑜫8󠆏; 3♮𑜫࣭.្𑜫8; [V5]; xn--3-ksd277tlo7s.xn--8-f0jx021l; ; ; # 3♮𑜫࣭.្𑜫8
+xn--3-ksd277tlo7s.xn--8-f0jx021l; 3♮𑜫࣭.្𑜫8; [V5]; xn--3-ksd277tlo7s.xn--8-f0jx021l; ; ; # 3♮𑜫࣭.្𑜫8
+-。򕌀‍❡; -.򕌀‍❡; [C2, P1, V3, V6]; -.xn--1ug800aq795s; ; -.xn--nei54421f; [P1, V3, V6] # -.❡
+-。򕌀‍❡; -.򕌀‍❡; [C2, P1, V3, V6]; -.xn--1ug800aq795s; ; -.xn--nei54421f; [P1, V3, V6] # -.❡
+-.xn--nei54421f; -.򕌀❡; [V3, V6]; -.xn--nei54421f; ; ; # -.❡
+-.xn--1ug800aq795s; -.򕌀‍❡; [C2, V3, V6]; -.xn--1ug800aq795s; ; ; # -.❡
+𝟓☱𝟐򥰵。𝪮񐡳; 5☱2򥰵.𝪮񐡳; [P1, V5, V6]; xn--52-dwx47758j.xn--kd3hk431k; ; ; # 5☱2.𝪮
+5☱2򥰵。𝪮񐡳; 5☱2򥰵.𝪮񐡳; [P1, V5, V6]; xn--52-dwx47758j.xn--kd3hk431k; ; ; # 5☱2.𝪮
+xn--52-dwx47758j.xn--kd3hk431k; 5☱2򥰵.𝪮񐡳; [V5, V6]; xn--52-dwx47758j.xn--kd3hk431k; ; ; # 5☱2.𝪮
+-.-├򖦣; ; [P1, V3, V6]; -.xn----ukp70432h; ; ; # -.-├
+-.xn----ukp70432h; -.-├򖦣; [V3, V6]; -.xn----ukp70432h; ; ; # -.-├
+֥ݭ。‍󠀘; ֥ݭ.‍󠀘; [B1, C2, P1, V5, V6]; xn--wcb62g.xn--1ugy8001l; ; xn--wcb62g.xn--p526e; [B1, P1, V5, V6] # ֥ݭ.
+֥ݭ。‍󠀘; ֥ݭ.‍󠀘; [B1, C2, P1, V5, V6]; xn--wcb62g.xn--1ugy8001l; ; xn--wcb62g.xn--p526e; [B1, P1, V5, V6] # ֥ݭ.
+xn--wcb62g.xn--p526e; ֥ݭ.󠀘; [B1, V5, V6]; xn--wcb62g.xn--p526e; ; ; # ֥ݭ.
+xn--wcb62g.xn--1ugy8001l; ֥ݭ.‍󠀘; [B1, C2, V5, V6]; xn--wcb62g.xn--1ugy8001l; ; ; # ֥ݭ.
+쥥󔏉Ⴎ.‌⒈⒈𐫒; 쥥󔏉Ⴎ.‌⒈⒈𐫒; [B1, C1, P1, V6]; xn--mnd7865gcy28g.xn--0ug88oa0396u; ; xn--mnd7865gcy28g.xn--tsha6797o; [B1, P1, V6] # 쥥Ⴎ.⒈⒈𐫒
+쥥󔏉Ⴎ.‌⒈⒈𐫒; 쥥󔏉Ⴎ.‌⒈⒈𐫒; [B1, C1, P1, V6]; xn--mnd7865gcy28g.xn--0ug88oa0396u; ; xn--mnd7865gcy28g.xn--tsha6797o; [B1, P1, V6] # 쥥Ⴎ.⒈⒈𐫒
+쥥󔏉Ⴎ.‌1.1.𐫒; ; [B1, C1, P1, V6]; xn--mnd7865gcy28g.xn--1-rgn.1.xn--7w9c; ; xn--mnd7865gcy28g.1.1.xn--7w9c; [B1, P1, V6] # 쥥Ⴎ.1.1.𐫒
+쥥󔏉Ⴎ.‌1.1.𐫒; 쥥󔏉Ⴎ.‌1.1.𐫒; [B1, C1, P1, V6]; xn--mnd7865gcy28g.xn--1-rgn.1.xn--7w9c; ; xn--mnd7865gcy28g.1.1.xn--7w9c; [B1, P1, V6] # 쥥Ⴎ.1.1.𐫒
+쥥󔏉ⴎ.‌1.1.𐫒; 쥥󔏉ⴎ.‌1.1.𐫒; [B1, C1, P1, V6]; xn--5kj3511ccyw3h.xn--1-rgn.1.xn--7w9c; ; xn--5kj3511ccyw3h.1.1.xn--7w9c; [B1, P1, V6] # 쥥ⴎ.1.1.𐫒
+쥥󔏉ⴎ.‌1.1.𐫒; ; [B1, C1, P1, V6]; xn--5kj3511ccyw3h.xn--1-rgn.1.xn--7w9c; ; xn--5kj3511ccyw3h.1.1.xn--7w9c; [B1, P1, V6] # 쥥ⴎ.1.1.𐫒
+xn--5kj3511ccyw3h.1.1.xn--7w9c; 쥥󔏉ⴎ.1.1.𐫒; [B1, V6]; xn--5kj3511ccyw3h.1.1.xn--7w9c; ; ; # 쥥ⴎ.1.1.𐫒
+xn--5kj3511ccyw3h.xn--1-rgn.1.xn--7w9c; 쥥󔏉ⴎ.‌1.1.𐫒; [B1, C1, V6]; xn--5kj3511ccyw3h.xn--1-rgn.1.xn--7w9c; ; ; # 쥥ⴎ.1.1.𐫒
+xn--mnd7865gcy28g.1.1.xn--7w9c; 쥥󔏉Ⴎ.1.1.𐫒; [B1, V6]; xn--mnd7865gcy28g.1.1.xn--7w9c; ; ; # 쥥Ⴎ.1.1.𐫒
+xn--mnd7865gcy28g.xn--1-rgn.1.xn--7w9c; 쥥󔏉Ⴎ.‌1.1.𐫒; [B1, C1, V6]; xn--mnd7865gcy28g.xn--1-rgn.1.xn--7w9c; ; ; # 쥥Ⴎ.1.1.𐫒
+쥥󔏉ⴎ.‌⒈⒈𐫒; 쥥󔏉ⴎ.‌⒈⒈𐫒; [B1, C1, P1, V6]; xn--5kj3511ccyw3h.xn--0ug88oa0396u; ; xn--5kj3511ccyw3h.xn--tsha6797o; [B1, P1, V6] # 쥥ⴎ.⒈⒈𐫒
+쥥󔏉ⴎ.‌⒈⒈𐫒; 쥥󔏉ⴎ.‌⒈⒈𐫒; [B1, C1, P1, V6]; xn--5kj3511ccyw3h.xn--0ug88oa0396u; ; xn--5kj3511ccyw3h.xn--tsha6797o; [B1, P1, V6] # 쥥ⴎ.⒈⒈𐫒
+xn--5kj3511ccyw3h.xn--tsha6797o; 쥥󔏉ⴎ.⒈⒈𐫒; [B1, V6]; xn--5kj3511ccyw3h.xn--tsha6797o; ; ; # 쥥ⴎ.⒈⒈𐫒
+xn--5kj3511ccyw3h.xn--0ug88oa0396u; 쥥󔏉ⴎ.‌⒈⒈𐫒; [B1, C1, V6]; xn--5kj3511ccyw3h.xn--0ug88oa0396u; ; ; # 쥥ⴎ.⒈⒈𐫒
+xn--mnd7865gcy28g.xn--tsha6797o; 쥥󔏉Ⴎ.⒈⒈𐫒; [B1, V6]; xn--mnd7865gcy28g.xn--tsha6797o; ; ; # 쥥Ⴎ.⒈⒈𐫒
+xn--mnd7865gcy28g.xn--0ug88oa0396u; 쥥󔏉Ⴎ.‌⒈⒈𐫒; [B1, C1, V6]; xn--mnd7865gcy28g.xn--0ug88oa0396u; ; ; # 쥥Ⴎ.⒈⒈𐫒
+ࠧ𝟶ڠ-。𑄳; ࠧ0ڠ-.𑄳; [B1, B3, B6, V3, V5]; xn--0--p3d67m.xn--v80d; ; ; # ࠧ0ڠ-.𑄳
+ࠧ0ڠ-。𑄳; ࠧ0ڠ-.𑄳; [B1, B3, B6, V3, V5]; xn--0--p3d67m.xn--v80d; ; ; # ࠧ0ڠ-.𑄳
+xn--0--p3d67m.xn--v80d; ࠧ0ڠ-.𑄳; [B1, B3, B6, V3, V5]; xn--0--p3d67m.xn--v80d; ; ; # ࠧ0ڠ-.𑄳
+ς.ﷁ🞛⒈; ς.فمي🞛⒈; [P1, V6]; xn--3xa.xn--dhbip2802atb20c; ; xn--4xa.xn--dhbip2802atb20c; # ς.فمي🞛⒈
+ς.فمي🞛1.; ; ; xn--3xa.xn--1-gocmu97674d.; ; xn--4xa.xn--1-gocmu97674d.; # ς.فمي🞛1.
+Σ.فمي🞛1.; σ.فمي🞛1.; ; xn--4xa.xn--1-gocmu97674d.; ; ; # σ.فمي🞛1.
+σ.فمي🞛1.; ; ; xn--4xa.xn--1-gocmu97674d.; ; ; # σ.فمي🞛1.
+xn--4xa.xn--1-gocmu97674d.; σ.فمي🞛1.; ; xn--4xa.xn--1-gocmu97674d.; ; ; # σ.فمي🞛1.
+xn--3xa.xn--1-gocmu97674d.; ς.فمي🞛1.; ; xn--3xa.xn--1-gocmu97674d.; ; ; # ς.فمي🞛1.
+Σ.ﷁ🞛⒈; σ.فمي🞛⒈; [P1, V6]; xn--4xa.xn--dhbip2802atb20c; ; ; # σ.فمي🞛⒈
+σ.ﷁ🞛⒈; σ.فمي🞛⒈; [P1, V6]; xn--4xa.xn--dhbip2802atb20c; ; ; # σ.فمي🞛⒈
+xn--4xa.xn--dhbip2802atb20c; σ.فمي🞛⒈; [V6]; xn--4xa.xn--dhbip2802atb20c; ; ; # σ.فمي🞛⒈
+xn--3xa.xn--dhbip2802atb20c; ς.فمي🞛⒈; [V6]; xn--3xa.xn--dhbip2802atb20c; ; ; # ς.فمي🞛⒈
+🗩-。𐹻󐞆񥉮; 🗩-.𐹻󐞆񥉮; [B1, P1, V3, V6]; xn----6t3s.xn--zo0d4811u6ru6a; ; ; # 🗩-.𐹻
+🗩-。𐹻󐞆񥉮; 🗩-.𐹻󐞆񥉮; [B1, P1, V3, V6]; xn----6t3s.xn--zo0d4811u6ru6a; ; ; # 🗩-.𐹻
+xn----6t3s.xn--zo0d4811u6ru6a; 🗩-.𐹻󐞆񥉮; [B1, V3, V6]; xn----6t3s.xn--zo0d4811u6ru6a; ; ; # 🗩-.𐹻
+𐡜-🔪。𝟻‌𐿀; 𐡜-🔪.5‌𐿀; [B1, B3, C1]; xn----5j4iv089c.xn--5-sgn7149h; ; xn----5j4iv089c.xn--5-bn7i; [B1, B3] # 𐡜-🔪.5𐿀
+𐡜-🔪。5‌𐿀; 𐡜-🔪.5‌𐿀; [B1, B3, C1]; xn----5j4iv089c.xn--5-sgn7149h; ; xn----5j4iv089c.xn--5-bn7i; [B1, B3] # 𐡜-🔪.5𐿀
+xn----5j4iv089c.xn--5-bn7i; 𐡜-🔪.5𐿀; [B1, B3]; xn----5j4iv089c.xn--5-bn7i; ; ; # 𐡜-🔪.5𐿀
+xn----5j4iv089c.xn--5-sgn7149h; 𐡜-🔪.5‌𐿀; [B1, B3, C1]; xn----5j4iv089c.xn--5-sgn7149h; ; ; # 𐡜-🔪.5𐿀
+𐹣늿‍ß.ߏ0ּ; 𐹣늿‍ß.ߏ0ּ; [B1, C2]; xn--zca770n5s4hev6c.xn--0-vgc50n; ; xn--ss-i05i7041a.xn--0-vgc50n; [B1] # 𐹣늿ß.ߏ0ּ
+𐹣늿‍ß.ߏ0ּ; 𐹣늿‍ß.ߏ0ּ; [B1, C2]; xn--zca770n5s4hev6c.xn--0-vgc50n; ; xn--ss-i05i7041a.xn--0-vgc50n; [B1] # 𐹣늿ß.ߏ0ּ
+𐹣늿‍ß.ߏ0ּ; ; [B1, C2]; xn--zca770n5s4hev6c.xn--0-vgc50n; ; xn--ss-i05i7041a.xn--0-vgc50n; [B1] # 𐹣늿ß.ߏ0ּ
+𐹣늿‍ß.ߏ0ּ; 𐹣늿‍ß.ߏ0ּ; [B1, C2]; xn--zca770n5s4hev6c.xn--0-vgc50n; ; xn--ss-i05i7041a.xn--0-vgc50n; [B1] # 𐹣늿ß.ߏ0ּ
+𐹣늿‍SS.ߏ0ּ; 𐹣늿‍ss.ߏ0ּ; [B1, C2]; xn--ss-l1tu910fo0xd.xn--0-vgc50n; ; xn--ss-i05i7041a.xn--0-vgc50n; [B1] # 𐹣늿ss.ߏ0ּ
+𐹣늿‍SS.ߏ0ּ; 𐹣늿‍ss.ߏ0ּ; [B1, C2]; xn--ss-l1tu910fo0xd.xn--0-vgc50n; ; xn--ss-i05i7041a.xn--0-vgc50n; [B1] # 𐹣늿ss.ߏ0ּ
+𐹣늿‍ss.ߏ0ּ; ; [B1, C2]; xn--ss-l1tu910fo0xd.xn--0-vgc50n; ; xn--ss-i05i7041a.xn--0-vgc50n; [B1] # 𐹣늿ss.ߏ0ּ
+𐹣늿‍ss.ߏ0ּ; 𐹣늿‍ss.ߏ0ּ; [B1, C2]; xn--ss-l1tu910fo0xd.xn--0-vgc50n; ; xn--ss-i05i7041a.xn--0-vgc50n; [B1] # 𐹣늿ss.ߏ0ּ
+xn--ss-i05i7041a.xn--0-vgc50n; 𐹣늿ss.ߏ0ּ; [B1]; xn--ss-i05i7041a.xn--0-vgc50n; ; ; # 𐹣늿ss.ߏ0ּ
+xn--ss-l1tu910fo0xd.xn--0-vgc50n; 𐹣늿‍ss.ߏ0ּ; [B1, C2]; xn--ss-l1tu910fo0xd.xn--0-vgc50n; ; ; # 𐹣늿ss.ߏ0ּ
+𐹣늿‍Ss.ߏ0ּ; 𐹣늿‍ss.ߏ0ּ; [B1, C2]; xn--ss-l1tu910fo0xd.xn--0-vgc50n; ; xn--ss-i05i7041a.xn--0-vgc50n; [B1] # 𐹣늿ss.ߏ0ּ
+𐹣늿‍Ss.ߏ0ּ; 𐹣늿‍ss.ߏ0ּ; [B1, C2]; xn--ss-l1tu910fo0xd.xn--0-vgc50n; ; xn--ss-i05i7041a.xn--0-vgc50n; [B1] # 𐹣늿ss.ߏ0ּ
+xn--zca770n5s4hev6c.xn--0-vgc50n; 𐹣늿‍ß.ߏ0ּ; [B1, C2]; xn--zca770n5s4hev6c.xn--0-vgc50n; ; ; # 𐹣늿ß.ߏ0ּ
+𐹣늿‍SS.ߏ0ּ; 𐹣늿‍ss.ߏ0ּ; [B1, C2]; xn--ss-l1tu910fo0xd.xn--0-vgc50n; ; xn--ss-i05i7041a.xn--0-vgc50n; [B1] # 𐹣늿ss.ߏ0ּ
+𐹣늿‍SS.ߏ0ּ; 𐹣늿‍ss.ߏ0ּ; [B1, C2]; xn--ss-l1tu910fo0xd.xn--0-vgc50n; ; xn--ss-i05i7041a.xn--0-vgc50n; [B1] # 𐹣늿ss.ߏ0ּ
+𐹣늿‍ss.ߏ0ּ; 𐹣늿‍ss.ߏ0ּ; [B1, C2]; xn--ss-l1tu910fo0xd.xn--0-vgc50n; ; xn--ss-i05i7041a.xn--0-vgc50n; [B1] # 𐹣늿ss.ߏ0ּ
+𐹣늿‍ss.ߏ0ּ; 𐹣늿‍ss.ߏ0ּ; [B1, C2]; xn--ss-l1tu910fo0xd.xn--0-vgc50n; ; xn--ss-i05i7041a.xn--0-vgc50n; [B1] # 𐹣늿ss.ߏ0ּ
+𐹣늿‍Ss.ߏ0ּ; 𐹣늿‍ss.ߏ0ּ; [B1, C2]; xn--ss-l1tu910fo0xd.xn--0-vgc50n; ; xn--ss-i05i7041a.xn--0-vgc50n; [B1] # 𐹣늿ss.ߏ0ּ
+𐹣늿‍Ss.ߏ0ּ; 𐹣늿‍ss.ߏ0ּ; [B1, C2]; xn--ss-l1tu910fo0xd.xn--0-vgc50n; ; xn--ss-i05i7041a.xn--0-vgc50n; [B1] # 𐹣늿ss.ߏ0ּ
+9󠇥.󪴴ᢓ; 9.󪴴ᢓ; [P1, V6]; 9.xn--dbf91222q; ; ; # 9.ᢓ
+9󠇥.󪴴ᢓ; 9.󪴴ᢓ; [P1, V6]; 9.xn--dbf91222q; ; ; # 9.ᢓ
+9.xn--dbf91222q; 9.󪴴ᢓ; [V6]; 9.xn--dbf91222q; ; ; # 9.ᢓ
+‌ᅠ.𐫭🠗ß⽟; ‌ᅠ.𐫭🠗ß玉; [B1, B2, B3, C1, P1, V6]; xn--0ug7719f.xn--zca2289c550e0iwi; ; xn--cl7c.xn--ss-je6eq954cp25j; [B2, B3, P1, V6] # .𐫭🠗ß玉
+‌ᅠ.𐫭🠗ß玉; ; [B1, B2, B3, C1, P1, V6]; xn--psd526e.xn--zca2289c550e0iwi; ; xn--psd.xn--ss-je6eq954cp25j; [B2, B3, P1, V6] # .𐫭🠗ß玉
+‌ᅠ.𐫭🠗SS玉; ‌ᅠ.𐫭🠗ss玉; [B1, B2, B3, C1, P1, V6]; xn--psd526e.xn--ss-je6eq954cp25j; ; xn--psd.xn--ss-je6eq954cp25j; [B2, B3, P1, V6] # .𐫭🠗ss玉
+‌ᅠ.𐫭🠗ss玉; ; [B1, B2, B3, C1, P1, V6]; xn--psd526e.xn--ss-je6eq954cp25j; ; xn--psd.xn--ss-je6eq954cp25j; [B2, B3, P1, V6] # .𐫭🠗ss玉
+‌ᅠ.𐫭🠗Ss玉; ‌ᅠ.𐫭🠗ss玉; [B1, B2, B3, C1, P1, V6]; xn--psd526e.xn--ss-je6eq954cp25j; ; xn--psd.xn--ss-je6eq954cp25j; [B2, B3, P1, V6] # .𐫭🠗ss玉
+xn--psd.xn--ss-je6eq954cp25j; ᅠ.𐫭🠗ss玉; [B2, B3, V6]; xn--psd.xn--ss-je6eq954cp25j; ; ; # .𐫭🠗ss玉
+xn--psd526e.xn--ss-je6eq954cp25j; ‌ᅠ.𐫭🠗ss玉; [B1, B2, B3, C1, V6]; xn--psd526e.xn--ss-je6eq954cp25j; ; ; # .𐫭🠗ss玉
+xn--psd526e.xn--zca2289c550e0iwi; ‌ᅠ.𐫭🠗ß玉; [B1, B2, B3, C1, V6]; xn--psd526e.xn--zca2289c550e0iwi; ; ; # .𐫭🠗ß玉
+‌ᅠ.𐫭🠗SS⽟; ‌ᅠ.𐫭🠗ss玉; [B1, B2, B3, C1, P1, V6]; xn--0ug7719f.xn--ss-je6eq954cp25j; ; xn--cl7c.xn--ss-je6eq954cp25j; [B2, B3, P1, V6] # .𐫭🠗ss玉
+‌ᅠ.𐫭🠗ss⽟; ‌ᅠ.𐫭🠗ss玉; [B1, B2, B3, C1, P1, V6]; xn--0ug7719f.xn--ss-je6eq954cp25j; ; xn--cl7c.xn--ss-je6eq954cp25j; [B2, B3, P1, V6] # .𐫭🠗ss玉
+‌ᅠ.𐫭🠗Ss⽟; ‌ᅠ.𐫭🠗ss玉; [B1, B2, B3, C1, P1, V6]; xn--0ug7719f.xn--ss-je6eq954cp25j; ; xn--cl7c.xn--ss-je6eq954cp25j; [B2, B3, P1, V6] # .𐫭🠗ss玉
+xn--cl7c.xn--ss-je6eq954cp25j; ᅠ.𐫭🠗ss玉; [B2, B3, V6]; xn--cl7c.xn--ss-je6eq954cp25j; ; ; # .𐫭🠗ss玉
+xn--0ug7719f.xn--ss-je6eq954cp25j; ‌ᅠ.𐫭🠗ss玉; [B1, B2, B3, C1, V6]; xn--0ug7719f.xn--ss-je6eq954cp25j; ; ; # .𐫭🠗ss玉
+xn--0ug7719f.xn--zca2289c550e0iwi; ‌ᅠ.𐫭🠗ß玉; [B1, B2, B3, C1, V6]; xn--0ug7719f.xn--zca2289c550e0iwi; ; ; # .𐫭🠗ß玉
+︒Ⴖͦ.‌; ︒Ⴖͦ.‌; [C1, P1, V6]; xn--hva929dl29p.xn--0ug; ; xn--hva929dl29p.; [P1, V6] # ︒Ⴖͦ.
+。Ⴖͦ.‌; .Ⴖͦ.‌; [C1, P1, V6, X4_2]; .xn--hva929d.xn--0ug; [C1, P1, V6, A4_2]; .xn--hva929d.; [P1, V6, A4_2] # .Ⴖͦ.
+。ⴖͦ.‌; .ⴖͦ.‌; [C1, X4_2]; .xn--hva754s.xn--0ug; [C1, A4_2]; .xn--hva754s.; [A4_2] # .ⴖͦ.
+.xn--hva754s.; .ⴖͦ.; [X4_2]; .xn--hva754s.; [A4_2]; ; # .ⴖͦ.
+.xn--hva754s.xn--0ug; .ⴖͦ.‌; [C1, X4_2]; .xn--hva754s.xn--0ug; [C1, A4_2]; ; # .ⴖͦ.
+.xn--hva929d.; .Ⴖͦ.; [V6, X4_2]; .xn--hva929d.; [V6, A4_2]; ; # .Ⴖͦ.
+.xn--hva929d.xn--0ug; .Ⴖͦ.‌; [C1, V6, X4_2]; .xn--hva929d.xn--0ug; [C1, V6, A4_2]; ; # .Ⴖͦ.
+︒ⴖͦ.‌; ︒ⴖͦ.‌; [C1, P1, V6]; xn--hva754sy94k.xn--0ug; ; xn--hva754sy94k.; [P1, V6] # ︒ⴖͦ.
+xn--hva754sy94k.; ︒ⴖͦ.; [V6]; xn--hva754sy94k.; ; ; # ︒ⴖͦ.
+xn--hva754sy94k.xn--0ug; ︒ⴖͦ.‌; [C1, V6]; xn--hva754sy94k.xn--0ug; ; ; # ︒ⴖͦ.
+xn--hva929dl29p.; ︒Ⴖͦ.; [V6]; xn--hva929dl29p.; ; ; # ︒Ⴖͦ.
+xn--hva929dl29p.xn--0ug; ︒Ⴖͦ.‌; [C1, V6]; xn--hva929dl29p.xn--0ug; ; ; # ︒Ⴖͦ.
+xn--hva754s.; ⴖͦ.; ; xn--hva754s.; ; ; # ⴖͦ.
+ⴖͦ.; ; ; xn--hva754s.; ; ; # ⴖͦ.
+Ⴖͦ.; ; [P1, V6]; xn--hva929d.; ; ; # Ⴖͦ.
+xn--hva929d.; Ⴖͦ.; [V6]; xn--hva929d.; ; ; # Ⴖͦ.
+ࢻ.‌Ⴃ𞀒; ࢻ.‌Ⴃ𞀒; [B1, C1, P1, V6]; xn--hzb.xn--bnd300f7225a; ; xn--hzb.xn--bnd2938u; [P1, V6] # ࢻ.Ⴃ𞀒
+ࢻ.‌Ⴃ𞀒; ; [B1, C1, P1, V6]; xn--hzb.xn--bnd300f7225a; ; xn--hzb.xn--bnd2938u; [P1, V6] # ࢻ.Ⴃ𞀒
+ࢻ.‌ⴃ𞀒; ; [B1, C1]; xn--hzb.xn--0ug822cp045a; ; xn--hzb.xn--ukj4430l; [] # ࢻ.ⴃ𞀒
+xn--hzb.xn--ukj4430l; ࢻ.ⴃ𞀒; ; xn--hzb.xn--ukj4430l; ; ; # ࢻ.ⴃ𞀒
+ࢻ.ⴃ𞀒; ; ; xn--hzb.xn--ukj4430l; ; ; # ࢻ.ⴃ𞀒
+ࢻ.Ⴃ𞀒; ; [P1, V6]; xn--hzb.xn--bnd2938u; ; ; # ࢻ.Ⴃ𞀒
+xn--hzb.xn--bnd2938u; ࢻ.Ⴃ𞀒; [V6]; xn--hzb.xn--bnd2938u; ; ; # ࢻ.Ⴃ𞀒
+xn--hzb.xn--0ug822cp045a; ࢻ.‌ⴃ𞀒; [B1, C1]; xn--hzb.xn--0ug822cp045a; ; ; # ࢻ.ⴃ𞀒
+xn--hzb.xn--bnd300f7225a; ࢻ.‌Ⴃ𞀒; [B1, C1, V6]; xn--hzb.xn--bnd300f7225a; ; ; # ࢻ.Ⴃ𞀒
+ࢻ.‌ⴃ𞀒; ࢻ.‌ⴃ𞀒; [B1, C1]; xn--hzb.xn--0ug822cp045a; ; xn--hzb.xn--ukj4430l; [] # ࢻ.ⴃ𞀒
+‍‌。2䫷󠧷; ‍‌.2䫷󠧷; [C1, C2, P1, V6]; xn--0ugb.xn--2-me5ay1273i; ; .xn--2-me5ay1273i; [P1, V6, A4_2] # .2䫷
+‍‌。2䫷󠧷; ‍‌.2䫷󠧷; [C1, C2, P1, V6]; xn--0ugb.xn--2-me5ay1273i; ; .xn--2-me5ay1273i; [P1, V6, A4_2] # .2䫷
+.xn--2-me5ay1273i; .2䫷󠧷; [V6, X4_2]; .xn--2-me5ay1273i; [V6, A4_2]; ; # .2䫷
+xn--0ugb.xn--2-me5ay1273i; ‍‌.2䫷󠧷; [C1, C2, V6]; xn--0ugb.xn--2-me5ay1273i; ; ; # .2䫷
+-𞀤󜠐。򈬖; -𞀤󜠐.򈬖; [P1, V3, V6]; xn----rq4re4997d.xn--l707b; ; ; # -𞀤.
+xn----rq4re4997d.xn--l707b; -𞀤󜠐.򈬖; [V3, V6]; xn----rq4re4997d.xn--l707b; ; ; # -𞀤.
+󳛂︒‌㟀.ؤ⒈; 󳛂︒‌㟀.ؤ⒈; [C1, P1, V6]; xn--0ug754gxl4ldlt0k.xn--jgb476m; ; xn--etlt457ccrq7h.xn--jgb476m; [P1, V6] # ︒㟀.ؤ⒈
+󳛂︒‌㟀.ؤ⒈; 󳛂︒‌㟀.ؤ⒈; [C1, P1, V6]; xn--0ug754gxl4ldlt0k.xn--jgb476m; ; xn--etlt457ccrq7h.xn--jgb476m; [P1, V6] # ︒㟀.ؤ⒈
+󳛂。‌㟀.ؤ1.; 󳛂.‌㟀.ؤ1.; [B1, C1, P1, V6]; xn--z272f.xn--0ug754g.xn--1-smc.; ; xn--z272f.xn--etl.xn--1-smc.; [P1, V6] # .㟀.ؤ1.
+󳛂。‌㟀.ؤ1.; 󳛂.‌㟀.ؤ1.; [B1, C1, P1, V6]; xn--z272f.xn--0ug754g.xn--1-smc.; ; xn--z272f.xn--etl.xn--1-smc.; [P1, V6] # .㟀.ؤ1.
+xn--z272f.xn--etl.xn--1-smc.; 󳛂.㟀.ؤ1.; [V6]; xn--z272f.xn--etl.xn--1-smc.; ; ; # .㟀.ؤ1.
+xn--z272f.xn--0ug754g.xn--1-smc.; 󳛂.‌㟀.ؤ1.; [B1, C1, V6]; xn--z272f.xn--0ug754g.xn--1-smc.; ; ; # .㟀.ؤ1.
+xn--etlt457ccrq7h.xn--jgb476m; 󳛂︒㟀.ؤ⒈; [V6]; xn--etlt457ccrq7h.xn--jgb476m; ; ; # ︒㟀.ؤ⒈
+xn--0ug754gxl4ldlt0k.xn--jgb476m; 󳛂︒‌㟀.ؤ⒈; [C1, V6]; xn--0ug754gxl4ldlt0k.xn--jgb476m; ; ; # ︒㟀.ؤ⒈
+𑲜ߊ𝅼。-‍; 𑲜ߊ𝅼.-‍; [B1, C2, V3, V5]; xn--lsb5482l7nre.xn----ugn; ; xn--lsb5482l7nre.-; [B1, V3, V5] # 𑲜ߊ𝅼.-
+xn--lsb5482l7nre.-; 𑲜ߊ𝅼.-; [B1, V3, V5]; xn--lsb5482l7nre.-; ; ; # 𑲜ߊ𝅼.-
+xn--lsb5482l7nre.xn----ugn; 𑲜ߊ𝅼.-‍; [B1, C2, V3, V5]; xn--lsb5482l7nre.xn----ugn; ; ; # 𑲜ߊ𝅼.-
+‌.Ⴉ≠𐫶; ‌.Ⴉ≠𐫶; [B1, B5, B6, C1, P1, V6]; xn--0ug.xn--hnd481gv73o; ; .xn--hnd481gv73o; [B5, B6, P1, V6, A4_2] # .Ⴉ≠𐫶
+‌.Ⴉ≠𐫶; ‌.Ⴉ≠𐫶; [B1, B5, B6, C1, P1, V6]; xn--0ug.xn--hnd481gv73o; ; .xn--hnd481gv73o; [B5, B6, P1, V6, A4_2] # .Ⴉ≠𐫶
+‌.Ⴉ≠𐫶; ; [B1, B5, B6, C1, P1, V6]; xn--0ug.xn--hnd481gv73o; ; .xn--hnd481gv73o; [B5, B6, P1, V6, A4_2] # .Ⴉ≠𐫶
+‌.Ⴉ≠𐫶; ‌.Ⴉ≠𐫶; [B1, B5, B6, C1, P1, V6]; xn--0ug.xn--hnd481gv73o; ; .xn--hnd481gv73o; [B5, B6, P1, V6, A4_2] # .Ⴉ≠𐫶
+‌.ⴉ≠𐫶; ‌.ⴉ≠𐫶; [B1, B5, B6, C1, P1, V6]; xn--0ug.xn--1chx23bzj4p; ; .xn--1chx23bzj4p; [B5, B6, P1, V6, A4_2] # .ⴉ≠𐫶
+‌.ⴉ≠𐫶; ; [B1, B5, B6, C1, P1, V6]; xn--0ug.xn--1chx23bzj4p; ; .xn--1chx23bzj4p; [B5, B6, P1, V6, A4_2] # .ⴉ≠𐫶
+.xn--1chx23bzj4p; .ⴉ≠𐫶; [B5, B6, V6, X4_2]; .xn--1chx23bzj4p; [B5, B6, V6, A4_2]; ; # .ⴉ≠𐫶
+xn--0ug.xn--1chx23bzj4p; ‌.ⴉ≠𐫶; [B1, B5, B6, C1, V6]; xn--0ug.xn--1chx23bzj4p; ; ; # .ⴉ≠𐫶
+.xn--hnd481gv73o; .Ⴉ≠𐫶; [B5, B6, V6, X4_2]; .xn--hnd481gv73o; [B5, B6, V6, A4_2]; ; # .Ⴉ≠𐫶
+xn--0ug.xn--hnd481gv73o; ‌.Ⴉ≠𐫶; [B1, B5, B6, C1, V6]; xn--0ug.xn--hnd481gv73o; ; ; # .Ⴉ≠𐫶
+‌.ⴉ≠𐫶; ‌.ⴉ≠𐫶; [B1, B5, B6, C1, P1, V6]; xn--0ug.xn--1chx23bzj4p; ; .xn--1chx23bzj4p; [B5, B6, P1, V6, A4_2] # .ⴉ≠𐫶
+‌.ⴉ≠𐫶; ‌.ⴉ≠𐫶; [B1, B5, B6, C1, P1, V6]; xn--0ug.xn--1chx23bzj4p; ; .xn--1chx23bzj4p; [B5, B6, P1, V6, A4_2] # .ⴉ≠𐫶
+ݐ。≯ς; ݐ.≯ς; [B1, P1, V6]; xn--3ob.xn--3xa918m; ; xn--3ob.xn--4xa718m; # ݐ.≯ς
+ݐ。≯ς; ݐ.≯ς; [B1, P1, V6]; xn--3ob.xn--3xa918m; ; xn--3ob.xn--4xa718m; # ݐ.≯ς
+ݐ。≯Σ; ݐ.≯σ; [B1, P1, V6]; xn--3ob.xn--4xa718m; ; ; # ݐ.≯σ
+ݐ。≯Σ; ݐ.≯σ; [B1, P1, V6]; xn--3ob.xn--4xa718m; ; ; # ݐ.≯σ
+ݐ。≯σ; ݐ.≯σ; [B1, P1, V6]; xn--3ob.xn--4xa718m; ; ; # ݐ.≯σ
+ݐ。≯σ; ݐ.≯σ; [B1, P1, V6]; xn--3ob.xn--4xa718m; ; ; # ݐ.≯σ
+xn--3ob.xn--4xa718m; ݐ.≯σ; [B1, V6]; xn--3ob.xn--4xa718m; ; ; # ݐ.≯σ
+xn--3ob.xn--3xa918m; ݐ.≯ς; [B1, V6]; xn--3ob.xn--3xa918m; ; ; # ݐ.≯ς
+߼𐸆.𓖏︒񊨩Ⴐ; ; [P1, V6]; xn--0tb8725k.xn--ond3562jt18a7py9c; ; ; # .︒Ⴐ
+߼𐸆.𓖏。񊨩Ⴐ; ߼𐸆.𓖏.񊨩Ⴐ; [P1, V6]; xn--0tb8725k.xn--tu8d.xn--ond97931d; ; ; # ..Ⴐ
+߼𐸆.𓖏。񊨩ⴐ; ߼𐸆.𓖏.񊨩ⴐ; [P1, V6]; xn--0tb8725k.xn--tu8d.xn--7kj73887a; ; ; # ..ⴐ
+xn--0tb8725k.xn--tu8d.xn--7kj73887a; ߼𐸆.𓖏.񊨩ⴐ; [V6]; xn--0tb8725k.xn--tu8d.xn--7kj73887a; ; ; # ..ⴐ
+xn--0tb8725k.xn--tu8d.xn--ond97931d; ߼𐸆.𓖏.񊨩Ⴐ; [V6]; xn--0tb8725k.xn--tu8d.xn--ond97931d; ; ; # ..Ⴐ
+߼𐸆.𓖏︒񊨩ⴐ; ; [P1, V6]; xn--0tb8725k.xn--7kj9008dt18a7py9c; ; ; # .︒ⴐ
+xn--0tb8725k.xn--7kj9008dt18a7py9c; ߼𐸆.𓖏︒񊨩ⴐ; [V6]; xn--0tb8725k.xn--7kj9008dt18a7py9c; ; ; # .︒ⴐ
+xn--0tb8725k.xn--ond3562jt18a7py9c; ߼𐸆.𓖏︒񊨩Ⴐ; [V6]; xn--0tb8725k.xn--ond3562jt18a7py9c; ; ; # .︒Ⴐ
+Ⴥ⚭󠖫⋃。𑌼; Ⴥ⚭󠖫⋃.𑌼; [P1, V5, V6]; xn--9nd623g4zc5z060c.xn--ro1d; ; ; # Ⴥ⚭⋃.𑌼
+Ⴥ⚭󠖫⋃。𑌼; Ⴥ⚭󠖫⋃.𑌼; [P1, V5, V6]; xn--9nd623g4zc5z060c.xn--ro1d; ; ; # Ⴥ⚭⋃.𑌼
+ⴥ⚭󠖫⋃。𑌼; ⴥ⚭󠖫⋃.𑌼; [P1, V5, V6]; xn--vfh16m67gx1162b.xn--ro1d; ; ; # ⴥ⚭⋃.𑌼
+xn--vfh16m67gx1162b.xn--ro1d; ⴥ⚭󠖫⋃.𑌼; [V5, V6]; xn--vfh16m67gx1162b.xn--ro1d; ; ; # ⴥ⚭⋃.𑌼
+xn--9nd623g4zc5z060c.xn--ro1d; Ⴥ⚭󠖫⋃.𑌼; [V5, V6]; xn--9nd623g4zc5z060c.xn--ro1d; ; ; # Ⴥ⚭⋃.𑌼
+ⴥ⚭󠖫⋃。𑌼; ⴥ⚭󠖫⋃.𑌼; [P1, V5, V6]; xn--vfh16m67gx1162b.xn--ro1d; ; ; # ⴥ⚭⋃.𑌼
+🄈。󠷳ࡄ; 🄈.󠷳ࡄ; [B1, P1, V6]; xn--107h.xn--2vb13094p; ; ; # 🄈.ࡄ
+7,。󠷳ࡄ; 7,.󠷳ࡄ; [B1, P1, V6]; 7,.xn--2vb13094p; ; ; # 7,.ࡄ
+7,.xn--2vb13094p; 7,.󠷳ࡄ; [B1, P1, V6]; 7,.xn--2vb13094p; ; ; # 7,.ࡄ
+xn--107h.xn--2vb13094p; 🄈.󠷳ࡄ; [B1, V6]; xn--107h.xn--2vb13094p; ; ; # 🄈.ࡄ
+≮ࡆ。섖쮖ß; ≮ࡆ.섖쮖ß; [B1, P1, V6]; xn--4vb505k.xn--zca7259goug; ; xn--4vb505k.xn--ss-5z4j006a; # ≮ࡆ.섖쮖ß
+≮ࡆ。섖쮖ß; ≮ࡆ.섖쮖ß; [B1, P1, V6]; xn--4vb505k.xn--zca7259goug; ; xn--4vb505k.xn--ss-5z4j006a; # ≮ࡆ.섖쮖ß
+≮ࡆ。섖쮖SS; ≮ࡆ.섖쮖ss; [B1, P1, V6]; xn--4vb505k.xn--ss-5z4j006a; ; ; # ≮ࡆ.섖쮖ss
+≮ࡆ。섖쮖SS; ≮ࡆ.섖쮖ss; [B1, P1, V6]; xn--4vb505k.xn--ss-5z4j006a; ; ; # ≮ࡆ.섖쮖ss
+≮ࡆ。섖쮖ss; ≮ࡆ.섖쮖ss; [B1, P1, V6]; xn--4vb505k.xn--ss-5z4j006a; ; ; # ≮ࡆ.섖쮖ss
+≮ࡆ。섖쮖ss; ≮ࡆ.섖쮖ss; [B1, P1, V6]; xn--4vb505k.xn--ss-5z4j006a; ; ; # ≮ࡆ.섖쮖ss
+xn--4vb505k.xn--ss-5z4j006a; ≮ࡆ.섖쮖ss; [B1, V6]; xn--4vb505k.xn--ss-5z4j006a; ; ; # ≮ࡆ.섖쮖ss
+≮ࡆ。섖쮖Ss; ≮ࡆ.섖쮖ss; [B1, P1, V6]; xn--4vb505k.xn--ss-5z4j006a; ; ; # ≮ࡆ.섖쮖ss
+≮ࡆ。섖쮖Ss; ≮ࡆ.섖쮖ss; [B1, P1, V6]; xn--4vb505k.xn--ss-5z4j006a; ; ; # ≮ࡆ.섖쮖ss
+xn--4vb505k.xn--zca7259goug; ≮ࡆ.섖쮖ß; [B1, V6]; xn--4vb505k.xn--zca7259goug; ; ; # ≮ࡆ.섖쮖ß
+󠆓⛏-。ꡒ; ⛏-.ꡒ; [V3]; xn----o9p.xn--rc9a; ; ; # ⛏-.ꡒ
+xn----o9p.xn--rc9a; ⛏-.ꡒ; [V3]; xn----o9p.xn--rc9a; ; ; # ⛏-.ꡒ
+޻𐹳ئ𑁆。ࢧڰ‌ᢒ; ޻𐹳ئ𑁆.ࢧڰ‌ᢒ; [B2, B3, P1, V6]; xn--lgb32f2753cosb.xn--jkb91hlz1azih; ; xn--lgb32f2753cosb.xn--jkb91hlz1a; # 𐹳ئ𑁆.ࢧڰᢒ
+޻𐹳ئ𑁆。ࢧڰ‌ᢒ; ޻𐹳ئ𑁆.ࢧڰ‌ᢒ; [B2, B3, P1, V6]; xn--lgb32f2753cosb.xn--jkb91hlz1azih; ; xn--lgb32f2753cosb.xn--jkb91hlz1a; # 𐹳ئ𑁆.ࢧڰᢒ
+xn--lgb32f2753cosb.xn--jkb91hlz1a; ޻𐹳ئ𑁆.ࢧڰᢒ; [B2, B3, V6]; xn--lgb32f2753cosb.xn--jkb91hlz1a; ; ; # 𐹳ئ𑁆.ࢧڰᢒ
+xn--lgb32f2753cosb.xn--jkb91hlz1azih; ޻𐹳ئ𑁆.ࢧڰ‌ᢒ; [B2, B3, V6]; xn--lgb32f2753cosb.xn--jkb91hlz1azih; ; ; # 𐹳ئ𑁆.ࢧڰᢒ
+ࠖ.𐨕𚚕; ; [B1, B2, B3, B6, P1, V5, V6]; xn--rub.xn--tr9c248x; ; ; # ࠖ.𐨕
+xn--rub.xn--tr9c248x; ࠖ.𐨕𚚕; [B1, B2, B3, B6, V5, V6]; xn--rub.xn--tr9c248x; ; ; # ࠖ.𐨕
+--。𽊆ݧ𐽋𞠬; --.𽊆ݧ𐽋𞠬; [B1, B5, B6, P1, V3, V6]; --.xn--rpb6226k77pfh58p; ; ; # --.ݧ𐽋𞠬
+--.xn--rpb6226k77pfh58p; --.𽊆ݧ𐽋𞠬; [B1, B5, B6, V3, V6]; --.xn--rpb6226k77pfh58p; ; ; # --.ݧ𐽋𞠬
+򛭦𐋥𹸐.≯ࢰࢦ󔛣; ; [B1, P1, V6]; xn--887c2298i5mv6a.xn--vybt688qm8981a; ; ; # 𐋥.≯ࢰࢦ
+򛭦𐋥𹸐.≯ࢰࢦ󔛣; 򛭦𐋥𹸐.≯ࢰࢦ󔛣; [B1, P1, V6]; xn--887c2298i5mv6a.xn--vybt688qm8981a; ; ; # 𐋥.≯ࢰࢦ
+xn--887c2298i5mv6a.xn--vybt688qm8981a; 򛭦𐋥𹸐.≯ࢰࢦ󔛣; [B1, V6]; xn--887c2298i5mv6a.xn--vybt688qm8981a; ; ; # 𐋥.≯ࢰࢦ
+䔛󠇒򤸞𐹧.-䤷; 䔛򤸞𐹧.-䤷; [B1, B5, B6, P1, V3, V6]; xn--2loy662coo60e.xn----0n4a; ; ; # 䔛𐹧.-䤷
+䔛󠇒򤸞𐹧.-䤷; 䔛򤸞𐹧.-䤷; [B1, B5, B6, P1, V3, V6]; xn--2loy662coo60e.xn----0n4a; ; ; # 䔛𐹧.-䤷
+xn--2loy662coo60e.xn----0n4a; 䔛򤸞𐹧.-䤷; [B1, B5, B6, V3, V6]; xn--2loy662coo60e.xn----0n4a; ; ; # 䔛𐹧.-䤷
+𐹩.‍-; 𐹩.‍-; [B1, C2, V3]; xn--ho0d.xn----tgn; ; xn--ho0d.-; [B1, V3] # 𐹩.-
+𐹩.‍-; ; [B1, C2, V3]; xn--ho0d.xn----tgn; ; xn--ho0d.-; [B1, V3] # 𐹩.-
+xn--ho0d.-; 𐹩.-; [B1, V3]; xn--ho0d.-; ; ; # 𐹩.-
+xn--ho0d.xn----tgn; 𐹩.‍-; [B1, C2, V3]; xn--ho0d.xn----tgn; ; ; # 𐹩.-
+񂈦帷。≯萺᷈-; 񂈦帷.≯萺᷈-; [P1, V3, V6]; xn--qutw175s.xn----mimu6tf67j; ; ; # 帷.≯萺᷈-
+񂈦帷。≯萺᷈-; 񂈦帷.≯萺᷈-; [P1, V3, V6]; xn--qutw175s.xn----mimu6tf67j; ; ; # 帷.≯萺᷈-
+񂈦帷。≯萺᷈-; 񂈦帷.≯萺᷈-; [P1, V3, V6]; xn--qutw175s.xn----mimu6tf67j; ; ; # 帷.≯萺᷈-
+񂈦帷。≯萺᷈-; 񂈦帷.≯萺᷈-; [P1, V3, V6]; xn--qutw175s.xn----mimu6tf67j; ; ; # 帷.≯萺᷈-
+xn--qutw175s.xn----mimu6tf67j; 񂈦帷.≯萺᷈-; [V3, V6]; xn--qutw175s.xn----mimu6tf67j; ; ; # 帷.≯萺᷈-
+‍攌꯭。ᢖ-Ⴘ; ‍攌꯭.ᢖ-Ⴘ; [C2, P1, V6]; xn--1ug592ykp6b.xn----k1g451d; ; xn--p9ut19m.xn----k1g451d; [P1, V6] # 攌꯭.ᢖ-Ⴘ
+‍攌꯭。ᢖ-ⴘ; ‍攌꯭.ᢖ-ⴘ; [C2]; xn--1ug592ykp6b.xn----mck373i; ; xn--p9ut19m.xn----mck373i; [] # 攌꯭.ᢖ-ⴘ
+xn--p9ut19m.xn----mck373i; 攌꯭.ᢖ-ⴘ; ; xn--p9ut19m.xn----mck373i; ; ; # 攌꯭.ᢖ-ⴘ
+攌꯭.ᢖ-ⴘ; ; ; xn--p9ut19m.xn----mck373i; ; ; # 攌꯭.ᢖ-ⴘ
+攌꯭.ᢖ-Ⴘ; ; [P1, V6]; xn--p9ut19m.xn----k1g451d; ; ; # 攌꯭.ᢖ-Ⴘ
+xn--p9ut19m.xn----k1g451d; 攌꯭.ᢖ-Ⴘ; [V6]; xn--p9ut19m.xn----k1g451d; ; ; # 攌꯭.ᢖ-Ⴘ
+xn--1ug592ykp6b.xn----mck373i; ‍攌꯭.ᢖ-ⴘ; [C2]; xn--1ug592ykp6b.xn----mck373i; ; ; # 攌꯭.ᢖ-ⴘ
+xn--1ug592ykp6b.xn----k1g451d; ‍攌꯭.ᢖ-Ⴘ; [C2, V6]; xn--1ug592ykp6b.xn----k1g451d; ; ; # 攌꯭.ᢖ-Ⴘ
+‌ꖨ.⒗3툒۳; ‌ꖨ.⒗3툒۳; [C1, P1, V6]; xn--0ug2473c.xn--3-nyc678tu07m; ; xn--9r8a.xn--3-nyc678tu07m; [P1, V6] # ꖨ.⒗3툒۳
+‌ꖨ.⒗3툒۳; ‌ꖨ.⒗3툒۳; [C1, P1, V6]; xn--0ug2473c.xn--3-nyc678tu07m; ; xn--9r8a.xn--3-nyc678tu07m; [P1, V6] # ꖨ.⒗3툒۳
+‌ꖨ.16.3툒۳; ; [C1]; xn--0ug2473c.16.xn--3-nyc0117m; ; xn--9r8a.16.xn--3-nyc0117m; [] # ꖨ.16.3툒۳
+‌ꖨ.16.3툒۳; ‌ꖨ.16.3툒۳; [C1]; xn--0ug2473c.16.xn--3-nyc0117m; ; xn--9r8a.16.xn--3-nyc0117m; [] # ꖨ.16.3툒۳
+xn--9r8a.16.xn--3-nyc0117m; ꖨ.16.3툒۳; ; xn--9r8a.16.xn--3-nyc0117m; ; ; # ꖨ.16.3툒۳
+ꖨ.16.3툒۳; ; ; xn--9r8a.16.xn--3-nyc0117m; ; ; # ꖨ.16.3툒۳
+ꖨ.16.3툒۳; ꖨ.16.3툒۳; ; xn--9r8a.16.xn--3-nyc0117m; ; ; # ꖨ.16.3툒۳
+xn--0ug2473c.16.xn--3-nyc0117m; ‌ꖨ.16.3툒۳; [C1]; xn--0ug2473c.16.xn--3-nyc0117m; ; ; # ꖨ.16.3툒۳
+xn--9r8a.xn--3-nyc678tu07m; ꖨ.⒗3툒۳; [V6]; xn--9r8a.xn--3-nyc678tu07m; ; ; # ꖨ.⒗3툒۳
+xn--0ug2473c.xn--3-nyc678tu07m; ‌ꖨ.⒗3툒۳; [C1, V6]; xn--0ug2473c.xn--3-nyc678tu07m; ; ; # ꖨ.⒗3툒۳
+⒈걾6.𐱁ې; ; [B1, P1, V6]; xn--6-dcps419c.xn--glb1794k; ; ; # ⒈걾6.𐱁ې
+⒈걾6.𐱁ې; ⒈걾6.𐱁ې; [B1, P1, V6]; xn--6-dcps419c.xn--glb1794k; ; ; # ⒈걾6.𐱁ې
+1.걾6.𐱁ې; ; [B1]; 1.xn--6-945e.xn--glb1794k; ; ; # 1.걾6.𐱁ې
+1.걾6.𐱁ې; 1.걾6.𐱁ې; [B1]; 1.xn--6-945e.xn--glb1794k; ; ; # 1.걾6.𐱁ې
+1.xn--6-945e.xn--glb1794k; 1.걾6.𐱁ې; [B1]; 1.xn--6-945e.xn--glb1794k; ; ; # 1.걾6.𐱁ې
+xn--6-dcps419c.xn--glb1794k; ⒈걾6.𐱁ې; [B1, V6]; xn--6-dcps419c.xn--glb1794k; ; ; # ⒈걾6.𐱁ې
+𐲞𝟶≮≮.󠀧ع; 𐳞0≮≮.󠀧ع; [B1, B3, P1, V6]; xn--0-ngoa5711v.xn--4gb31034p; ; ; # 𐳞0≮≮.ع
+𐲞𝟶≮≮.󠀧ع; 𐳞0≮≮.󠀧ع; [B1, B3, P1, V6]; xn--0-ngoa5711v.xn--4gb31034p; ; ; # 𐳞0≮≮.ع
+𐲞0≮≮.󠀧ع; 𐳞0≮≮.󠀧ع; [B1, B3, P1, V6]; xn--0-ngoa5711v.xn--4gb31034p; ; ; # 𐳞0≮≮.ع
+𐲞0≮≮.󠀧ع; 𐳞0≮≮.󠀧ع; [B1, B3, P1, V6]; xn--0-ngoa5711v.xn--4gb31034p; ; ; # 𐳞0≮≮.ع
+𐳞0≮≮.󠀧ع; 𐳞0≮≮.󠀧ع; [B1, B3, P1, V6]; xn--0-ngoa5711v.xn--4gb31034p; ; ; # 𐳞0≮≮.ع
+𐳞0≮≮.󠀧ع; ; [B1, B3, P1, V6]; xn--0-ngoa5711v.xn--4gb31034p; ; ; # 𐳞0≮≮.ع
+xn--0-ngoa5711v.xn--4gb31034p; 𐳞0≮≮.󠀧ع; [B1, B3, V6]; xn--0-ngoa5711v.xn--4gb31034p; ; ; # 𐳞0≮≮.ع
+𐳞𝟶≮≮.󠀧ع; 𐳞0≮≮.󠀧ع; [B1, B3, P1, V6]; xn--0-ngoa5711v.xn--4gb31034p; ; ; # 𐳞0≮≮.ع
+𐳞𝟶≮≮.󠀧ع; 𐳞0≮≮.󠀧ع; [B1, B3, P1, V6]; xn--0-ngoa5711v.xn--4gb31034p; ; ; # 𐳞0≮≮.ع
+ૣ.𐹺ᅟ; ; [B1, B3, B6, P1, V5, V6]; xn--8fc.xn--osd3070k; ; ; # ૣ.𐹺
+xn--8fc.xn--osd3070k; ૣ.𐹺ᅟ; [B1, B3, B6, V5, V6]; xn--8fc.xn--osd3070k; ; ; # ૣ.𐹺
+𝟏𝨙⸖.‍; 1𝨙⸖.‍; [C2]; xn--1-5bt6845n.xn--1ug; ; xn--1-5bt6845n.; [] # 1𝨙⸖.
+1𝨙⸖.‍; ; [C2]; xn--1-5bt6845n.xn--1ug; ; xn--1-5bt6845n.; [] # 1𝨙⸖.
+xn--1-5bt6845n.; 1𝨙⸖.; ; xn--1-5bt6845n.; ; ; # 1𝨙⸖.
+1𝨙⸖.; ; ; xn--1-5bt6845n.; ; ; # 1𝨙⸖.
+xn--1-5bt6845n.xn--1ug; 1𝨙⸖.‍; [C2]; xn--1-5bt6845n.xn--1ug; ; ; # 1𝨙⸖.
+𞤐≠ܦ᩠。-‌ߕ; 𞤲≠ܦ᩠.-‌ߕ; [B1, C1, P1, V3, V6]; xn--wnb859grzfzw60c.xn----kcd017p; ; xn--wnb859grzfzw60c.xn----kcd; [B1, P1, V3, V6] # 𞤲≠ܦ᩠.-ߕ
+𞤐≠ܦ᩠。-‌ߕ; 𞤲≠ܦ᩠.-‌ߕ; [B1, C1, P1, V3, V6]; xn--wnb859grzfzw60c.xn----kcd017p; ; xn--wnb859grzfzw60c.xn----kcd; [B1, P1, V3, V6] # 𞤲≠ܦ᩠.-ߕ
+𞤐≠ܦ᩠。-‌ߕ; 𞤲≠ܦ᩠.-‌ߕ; [B1, C1, P1, V3, V6]; xn--wnb859grzfzw60c.xn----kcd017p; ; xn--wnb859grzfzw60c.xn----kcd; [B1, P1, V3, V6] # 𞤲≠ܦ᩠.-ߕ
+𞤐≠ܦ᩠。-‌ߕ; 𞤲≠ܦ᩠.-‌ߕ; [B1, C1, P1, V3, V6]; xn--wnb859grzfzw60c.xn----kcd017p; ; xn--wnb859grzfzw60c.xn----kcd; [B1, P1, V3, V6] # 𞤲≠ܦ᩠.-ߕ
+𞤲≠ܦ᩠。-‌ߕ; 𞤲≠ܦ᩠.-‌ߕ; [B1, C1, P1, V3, V6]; xn--wnb859grzfzw60c.xn----kcd017p; ; xn--wnb859grzfzw60c.xn----kcd; [B1, P1, V3, V6] # 𞤲≠ܦ᩠.-ߕ
+𞤲≠ܦ᩠。-‌ߕ; 𞤲≠ܦ᩠.-‌ߕ; [B1, C1, P1, V3, V6]; xn--wnb859grzfzw60c.xn----kcd017p; ; xn--wnb859grzfzw60c.xn----kcd; [B1, P1, V3, V6] # 𞤲≠ܦ᩠.-ߕ
+xn--wnb859grzfzw60c.xn----kcd; 𞤲≠ܦ᩠.-ߕ; [B1, V3, V6]; xn--wnb859grzfzw60c.xn----kcd; ; ; # 𞤲≠ܦ᩠.-ߕ
+xn--wnb859grzfzw60c.xn----kcd017p; 𞤲≠ܦ᩠.-‌ߕ; [B1, C1, V3, V6]; xn--wnb859grzfzw60c.xn----kcd017p; ; ; # 𞤲≠ܦ᩠.-ߕ
+𞤲≠ܦ᩠。-‌ߕ; 𞤲≠ܦ᩠.-‌ߕ; [B1, C1, P1, V3, V6]; xn--wnb859grzfzw60c.xn----kcd017p; ; xn--wnb859grzfzw60c.xn----kcd; [B1, P1, V3, V6] # 𞤲≠ܦ᩠.-ߕ
+𞤲≠ܦ᩠。-‌ߕ; 𞤲≠ܦ᩠.-‌ߕ; [B1, C1, P1, V3, V6]; xn--wnb859grzfzw60c.xn----kcd017p; ; xn--wnb859grzfzw60c.xn----kcd; [B1, P1, V3, V6] # 𞤲≠ܦ᩠.-ߕ
+𐹰ͨ-ꡧ。ٵ; 𐹰ͨ-ꡧ.اٴ; [B1]; xn----shb2387jgkqd.xn--mgb8m; ; ; # 𐹰ͨ-ꡧ.اٴ
+𐹰ͨ-ꡧ。اٴ; 𐹰ͨ-ꡧ.اٴ; [B1]; xn----shb2387jgkqd.xn--mgb8m; ; ; # 𐹰ͨ-ꡧ.اٴ
+xn----shb2387jgkqd.xn--mgb8m; 𐹰ͨ-ꡧ.اٴ; [B1]; xn----shb2387jgkqd.xn--mgb8m; ; ; # 𐹰ͨ-ꡧ.اٴ
+F󠅟。򏗅♚; f.򏗅♚; [P1, V6]; f.xn--45hz6953f; ; ; # f.♚
+F󠅟。򏗅♚; f.򏗅♚; [P1, V6]; f.xn--45hz6953f; ; ; # f.♚
+f󠅟。򏗅♚; f.򏗅♚; [P1, V6]; f.xn--45hz6953f; ; ; # f.♚
+f.xn--45hz6953f; f.򏗅♚; [V6]; f.xn--45hz6953f; ; ; # f.♚
+f󠅟。򏗅♚; f.򏗅♚; [P1, V6]; f.xn--45hz6953f; ; ; # f.♚
+୍𑄴ᷩ。𝟮Ⴘ𞀨񃥇; ୍𑄴ᷩ.2Ⴘ𞀨񃥇; [P1, V5, V6]; xn--9ic246gs21p.xn--2-k1g43076adrwq; ; ; # ୍𑄴ᷩ.2Ⴘ𞀨
+୍𑄴ᷩ。2Ⴘ𞀨񃥇; ୍𑄴ᷩ.2Ⴘ𞀨񃥇; [P1, V5, V6]; xn--9ic246gs21p.xn--2-k1g43076adrwq; ; ; # ୍𑄴ᷩ.2Ⴘ𞀨
+୍𑄴ᷩ。2ⴘ𞀨񃥇; ୍𑄴ᷩ.2ⴘ𞀨񃥇; [P1, V5, V6]; xn--9ic246gs21p.xn--2-nws2918ndrjr; ; ; # ୍𑄴ᷩ.2ⴘ𞀨
+xn--9ic246gs21p.xn--2-nws2918ndrjr; ୍𑄴ᷩ.2ⴘ𞀨񃥇; [V5, V6]; xn--9ic246gs21p.xn--2-nws2918ndrjr; ; ; # ୍𑄴ᷩ.2ⴘ𞀨
+xn--9ic246gs21p.xn--2-k1g43076adrwq; ୍𑄴ᷩ.2Ⴘ𞀨񃥇; [V5, V6]; xn--9ic246gs21p.xn--2-k1g43076adrwq; ; ; # ୍𑄴ᷩ.2Ⴘ𞀨
+୍𑄴ᷩ。𝟮ⴘ𞀨񃥇; ୍𑄴ᷩ.2ⴘ𞀨񃥇; [P1, V5, V6]; xn--9ic246gs21p.xn--2-nws2918ndrjr; ; ; # ୍𑄴ᷩ.2ⴘ𞀨
+򓠭‌‌⒈。勉𑁅; 򓠭‌‌⒈.勉𑁅; [C1, P1, V6]; xn--0uga855aez302a.xn--4grs325b; ; xn--tsh11906f.xn--4grs325b; [P1, V6] # ⒈.勉𑁅
+򓠭‌‌1.。勉𑁅; 򓠭‌‌1..勉𑁅; [C1, P1, V6, X4_2]; xn--1-rgna61159u..xn--4grs325b; [C1, P1, V6, A4_2]; xn--1-yi00h..xn--4grs325b; [P1, V6, A4_2] # 1..勉𑁅
+xn--1-yi00h..xn--4grs325b; 򓠭1..勉𑁅; [V6, X4_2]; xn--1-yi00h..xn--4grs325b; [V6, A4_2]; ; # 1..勉𑁅
+xn--1-rgna61159u..xn--4grs325b; 򓠭‌‌1..勉𑁅; [C1, V6, X4_2]; xn--1-rgna61159u..xn--4grs325b; [C1, V6, A4_2]; ; # 1..勉𑁅
+xn--tsh11906f.xn--4grs325b; 򓠭⒈.勉𑁅; [V6]; xn--tsh11906f.xn--4grs325b; ; ; # ⒈.勉𑁅
+xn--0uga855aez302a.xn--4grs325b; 򓠭‌‌⒈.勉𑁅; [C1, V6]; xn--0uga855aez302a.xn--4grs325b; ; ; # ⒈.勉𑁅
+ᡃ.玿񫈜󕞐; ; [P1, V6]; xn--27e.xn--7cy81125a0yq4a; ; ; # ᡃ.玿
+xn--27e.xn--7cy81125a0yq4a; ᡃ.玿񫈜󕞐; [V6]; xn--27e.xn--7cy81125a0yq4a; ; ; # ᡃ.玿
+‌‌。⒈≯𝟵; ‌‌.⒈≯9; [C1, P1, V6]; xn--0uga.xn--9-ogo37g; ; .xn--9-ogo37g; [P1, V6, A4_2] # .⒈≯9
+‌‌。⒈≯𝟵; ‌‌.⒈≯9; [C1, P1, V6]; xn--0uga.xn--9-ogo37g; ; .xn--9-ogo37g; [P1, V6, A4_2] # .⒈≯9
+‌‌。1.≯9; ‌‌.1.≯9; [C1, P1, V6]; xn--0uga.1.xn--9-ogo; ; .1.xn--9-ogo; [P1, V6, A4_2] # .1.≯9
+‌‌。1.≯9; ‌‌.1.≯9; [C1, P1, V6]; xn--0uga.1.xn--9-ogo; ; .1.xn--9-ogo; [P1, V6, A4_2] # .1.≯9
+.1.xn--9-ogo; .1.≯9; [V6, X4_2]; .1.xn--9-ogo; [V6, A4_2]; ; # .1.≯9
+xn--0uga.1.xn--9-ogo; ‌‌.1.≯9; [C1, V6]; xn--0uga.1.xn--9-ogo; ; ; # .1.≯9
+.xn--9-ogo37g; .⒈≯9; [V6, X4_2]; .xn--9-ogo37g; [V6, A4_2]; ; # .⒈≯9
+xn--0uga.xn--9-ogo37g; ‌‌.⒈≯9; [C1, V6]; xn--0uga.xn--9-ogo37g; ; ; # .⒈≯9
+ᅟᷠ򐀁.𺻆≯𐮁; ; [B5, B6, P1, V6]; xn--osd615d5659o.xn--hdh5192gkm6r; ; ; # ᷠ.≯𐮁
+ᅟᷠ򐀁.𺻆≯𐮁; ᅟᷠ򐀁.𺻆≯𐮁; [B5, B6, P1, V6]; xn--osd615d5659o.xn--hdh5192gkm6r; ; ; # ᷠ.≯𐮁
+xn--osd615d5659o.xn--hdh5192gkm6r; ᅟᷠ򐀁.𺻆≯𐮁; [B5, B6, V6]; xn--osd615d5659o.xn--hdh5192gkm6r; ; ; # ᷠ.≯𐮁
+󠄫𝩤‍ؾ.𝩩-ࠞ󑼩; 𝩤‍ؾ.𝩩-ࠞ󑼩; [B1, C2, P1, V5, V6]; xn--9gb723kg862a.xn----qgd52296avol4f; ; xn--9gb5080v.xn----qgd52296avol4f; [B1, P1, V5, V6] # 𝩤ؾ.𝩩-ࠞ
+xn--9gb5080v.xn----qgd52296avol4f; 𝩤ؾ.𝩩-ࠞ󑼩; [B1, V5, V6]; xn--9gb5080v.xn----qgd52296avol4f; ; ; # 𝩤ؾ.𝩩-ࠞ
+xn--9gb723kg862a.xn----qgd52296avol4f; 𝩤‍ؾ.𝩩-ࠞ󑼩; [B1, C2, V5, V6]; xn--9gb723kg862a.xn----qgd52296avol4f; ; ; # 𝩤ؾ.𝩩-ࠞ
+⃚.𑘿-; ⃚.𑘿-; [V3, V5]; xn--w0g.xn----bd0j; ; ; # ⃚.𑘿-
+⃚.𑘿-; ; [V3, V5]; xn--w0g.xn----bd0j; ; ; # ⃚.𑘿-
+xn--w0g.xn----bd0j; ⃚.𑘿-; [V3, V5]; xn--w0g.xn----bd0j; ; ; # ⃚.𑘿-
+䮸ß.󠵟󠭎紙ࢨ; ; [B1, P1, V6]; xn--zca5349a.xn--xyb1370div70kpzba; ; xn--ss-sf1c.xn--xyb1370div70kpzba; # 䮸ß.紙ࢨ
+䮸SS.󠵟󠭎紙ࢨ; 䮸ss.󠵟󠭎紙ࢨ; [B1, P1, V6]; xn--ss-sf1c.xn--xyb1370div70kpzba; ; ; # 䮸ss.紙ࢨ
+䮸ss.󠵟󠭎紙ࢨ; ; [B1, P1, V6]; xn--ss-sf1c.xn--xyb1370div70kpzba; ; ; # 䮸ss.紙ࢨ
+䮸Ss.󠵟󠭎紙ࢨ; 䮸ss.󠵟󠭎紙ࢨ; [B1, P1, V6]; xn--ss-sf1c.xn--xyb1370div70kpzba; ; ; # 䮸ss.紙ࢨ
+xn--ss-sf1c.xn--xyb1370div70kpzba; 䮸ss.󠵟󠭎紙ࢨ; [B1, V6]; xn--ss-sf1c.xn--xyb1370div70kpzba; ; ; # 䮸ss.紙ࢨ
+xn--zca5349a.xn--xyb1370div70kpzba; 䮸ß.󠵟󠭎紙ࢨ; [B1, V6]; xn--zca5349a.xn--xyb1370div70kpzba; ; ; # 䮸ß.紙ࢨ
+-Ⴞ.-𝩨⅔𐦕; -Ⴞ.-𝩨2⁄3𐦕; [B1, P1, V3, V6]; xn----w1g.xn---23-pt0a0433lk3jj; ; ; # -Ⴞ.-𝩨2⁄3𐦕
+-Ⴞ.-𝩨2⁄3𐦕; ; [B1, P1, V3, V6]; xn----w1g.xn---23-pt0a0433lk3jj; ; ; # -Ⴞ.-𝩨2⁄3𐦕
+-ⴞ.-𝩨2⁄3𐦕; ; [B1, V3]; xn----zws.xn---23-pt0a0433lk3jj; ; ; # -ⴞ.-𝩨2⁄3𐦕
+xn----zws.xn---23-pt0a0433lk3jj; -ⴞ.-𝩨2⁄3𐦕; [B1, V3]; xn----zws.xn---23-pt0a0433lk3jj; ; ; # -ⴞ.-𝩨2⁄3𐦕
+xn----w1g.xn---23-pt0a0433lk3jj; -Ⴞ.-𝩨2⁄3𐦕; [B1, V3, V6]; xn----w1g.xn---23-pt0a0433lk3jj; ; ; # -Ⴞ.-𝩨2⁄3𐦕
+-ⴞ.-𝩨⅔𐦕; -ⴞ.-𝩨2⁄3𐦕; [B1, V3]; xn----zws.xn---23-pt0a0433lk3jj; ; ; # -ⴞ.-𝩨2⁄3𐦕
+󧈯𐹯ૂ。򖢨𐮁񇼖ᡂ; 󧈯𐹯ૂ.򖢨𐮁񇼖ᡂ; [B5, B6, P1, V6]; xn--bfc7604kv8m3g.xn--17e5565jl7zw4h16a; ; ; # 𐹯ૂ.𐮁ᡂ
+󧈯𐹯ૂ。򖢨𐮁񇼖ᡂ; 󧈯𐹯ૂ.򖢨𐮁񇼖ᡂ; [B5, B6, P1, V6]; xn--bfc7604kv8m3g.xn--17e5565jl7zw4h16a; ; ; # 𐹯ૂ.𐮁ᡂ
+xn--bfc7604kv8m3g.xn--17e5565jl7zw4h16a; 󧈯𐹯ૂ.򖢨𐮁񇼖ᡂ; [B5, B6, V6]; xn--bfc7604kv8m3g.xn--17e5565jl7zw4h16a; ; ; # 𐹯ૂ.𐮁ᡂ
+ႂ-‍꣪.ꡊ‍񼸳; ႂ-‍꣪.ꡊ‍񼸳; [C2, P1, V5, V6]; xn----gyg250jio7k.xn--1ug8774cri56d; ; xn----gyg3618i.xn--jc9ao4185a; [P1, V5, V6] # ႂ-꣪.ꡊ
+ႂ-‍꣪.ꡊ‍񼸳; ; [C2, P1, V5, V6]; xn----gyg250jio7k.xn--1ug8774cri56d; ; xn----gyg3618i.xn--jc9ao4185a; [P1, V5, V6] # ႂ-꣪.ꡊ
+xn----gyg3618i.xn--jc9ao4185a; ႂ-꣪.ꡊ񼸳; [V5, V6]; xn----gyg3618i.xn--jc9ao4185a; ; ; # ႂ-꣪.ꡊ
+xn----gyg250jio7k.xn--1ug8774cri56d; ႂ-‍꣪.ꡊ‍񼸳; [C2, V5, V6]; xn----gyg250jio7k.xn--1ug8774cri56d; ; ; # ႂ-꣪.ꡊ
+۱。≠٨; ۱.≠٨; [B1, P1, V6]; xn--emb.xn--hib334l; ; ; # ۱.≠٨
+۱。≠٨; ۱.≠٨; [B1, P1, V6]; xn--emb.xn--hib334l; ; ; # ۱.≠٨
+xn--emb.xn--hib334l; ۱.≠٨; [B1, V6]; xn--emb.xn--hib334l; ; ; # ۱.≠٨
+𑈵廊.𐠍; ; [V5]; xn--xytw701b.xn--yc9c; ; ; # 𑈵廊.𐠍
+xn--xytw701b.xn--yc9c; 𑈵廊.𐠍; [V5]; xn--xytw701b.xn--yc9c; ; ; # 𑈵廊.𐠍
+‍͖-.-Ⴐ١; ‍͖-.-Ⴐ١; [B1, C2, P1, V3, V6]; xn----rgb661t.xn----bqc030f; ; xn----rgb.xn----bqc030f; [B1, P1, V3, V5, V6] # ͖-.-Ⴐ١
+‍͖-.-Ⴐ١; ; [B1, C2, P1, V3, V6]; xn----rgb661t.xn----bqc030f; ; xn----rgb.xn----bqc030f; [B1, P1, V3, V5, V6] # ͖-.-Ⴐ١
+‍͖-.-ⴐ١; ; [B1, C2, V3]; xn----rgb661t.xn----bqc2280a; ; xn----rgb.xn----bqc2280a; [B1, V3, V5] # ͖-.-ⴐ١
+xn----rgb.xn----bqc2280a; ͖-.-ⴐ١; [B1, V3, V5]; xn----rgb.xn----bqc2280a; ; ; # ͖-.-ⴐ١
+xn----rgb661t.xn----bqc2280a; ‍͖-.-ⴐ١; [B1, C2, V3]; xn----rgb661t.xn----bqc2280a; ; ; # ͖-.-ⴐ١
+xn----rgb.xn----bqc030f; ͖-.-Ⴐ١; [B1, V3, V5, V6]; xn----rgb.xn----bqc030f; ; ; # ͖-.-Ⴐ١
+xn----rgb661t.xn----bqc030f; ‍͖-.-Ⴐ١; [B1, C2, V3, V6]; xn----rgb661t.xn----bqc030f; ; ; # ͖-.-Ⴐ١
+‍͖-.-ⴐ١; ‍͖-.-ⴐ١; [B1, C2, V3]; xn----rgb661t.xn----bqc2280a; ; xn----rgb.xn----bqc2280a; [B1, V3, V5] # ͖-.-ⴐ١
+غ١挏󾯐.-; ; [B1, B2, B3, P1, V3, V6]; xn--5gb2f4205aqi47p.-; ; ; # غ١挏.-
+xn--5gb2f4205aqi47p.-; غ١挏󾯐.-; [B1, B2, B3, V3, V6]; xn--5gb2f4205aqi47p.-; ; ; # غ١挏.-
+ۯ。𐹧𞤽; ۯ.𐹧𞤽; [B1]; xn--cmb.xn--fo0dy848a; ; ; # ۯ.𐹧𞤽
+ۯ。𐹧𞤽; ۯ.𐹧𞤽; [B1]; xn--cmb.xn--fo0dy848a; ; ; # ۯ.𐹧𞤽
+ۯ。𐹧𞤛; ۯ.𐹧𞤽; [B1]; xn--cmb.xn--fo0dy848a; ; ; # ۯ.𐹧𞤽
+xn--cmb.xn--fo0dy848a; ۯ.𐹧𞤽; [B1]; xn--cmb.xn--fo0dy848a; ; ; # ۯ.𐹧𞤽
+ۯ。𐹧𞤛; ۯ.𐹧𞤽; [B1]; xn--cmb.xn--fo0dy848a; ; ; # ۯ.𐹧𞤽
+Ⴞ𶛀𛗻.ᢗ릫; Ⴞ𶛀𛗻.ᢗ릫; [P1, V6]; xn--2nd8876sgl2j.xn--hbf6853f; ; ; # Ⴞ.ᢗ릫
+Ⴞ𶛀𛗻.ᢗ릫; Ⴞ𶛀𛗻.ᢗ릫; [P1, V6]; xn--2nd8876sgl2j.xn--hbf6853f; ; ; # Ⴞ.ᢗ릫
+Ⴞ𶛀𛗻.ᢗ릫; ; [P1, V6]; xn--2nd8876sgl2j.xn--hbf6853f; ; ; # Ⴞ.ᢗ릫
+Ⴞ𶛀𛗻.ᢗ릫; Ⴞ𶛀𛗻.ᢗ릫; [P1, V6]; xn--2nd8876sgl2j.xn--hbf6853f; ; ; # Ⴞ.ᢗ릫
+ⴞ𶛀𛗻.ᢗ릫; ⴞ𶛀𛗻.ᢗ릫; [P1, V6]; xn--mlj0486jgl2j.xn--hbf6853f; ; ; # ⴞ.ᢗ릫
+ⴞ𶛀𛗻.ᢗ릫; ; [P1, V6]; xn--mlj0486jgl2j.xn--hbf6853f; ; ; # ⴞ.ᢗ릫
+xn--mlj0486jgl2j.xn--hbf6853f; ⴞ𶛀𛗻.ᢗ릫; [V6]; xn--mlj0486jgl2j.xn--hbf6853f; ; ; # ⴞ.ᢗ릫
+xn--2nd8876sgl2j.xn--hbf6853f; Ⴞ𶛀𛗻.ᢗ릫; [V6]; xn--2nd8876sgl2j.xn--hbf6853f; ; ; # Ⴞ.ᢗ릫
+ⴞ𶛀𛗻.ᢗ릫; ⴞ𶛀𛗻.ᢗ릫; [P1, V6]; xn--mlj0486jgl2j.xn--hbf6853f; ; ; # ⴞ.ᢗ릫
+ⴞ𶛀𛗻.ᢗ릫; ⴞ𶛀𛗻.ᢗ릫; [P1, V6]; xn--mlj0486jgl2j.xn--hbf6853f; ; ; # ⴞ.ᢗ릫
+󠎃󗭞ڷ𐹷。≯‌᷾; 󠎃󗭞ڷ𐹷.≯‌᷾; [B1, C1, P1, V6]; xn--qkb4516kbi06fg2id.xn--zfg59fm0c; ; xn--qkb4516kbi06fg2id.xn--zfg31q; [B1, P1, V6] # ڷ𐹷.≯᷾
+󠎃󗭞ڷ𐹷。≯‌᷾; 󠎃󗭞ڷ𐹷.≯‌᷾; [B1, C1, P1, V6]; xn--qkb4516kbi06fg2id.xn--zfg59fm0c; ; xn--qkb4516kbi06fg2id.xn--zfg31q; [B1, P1, V6] # ڷ𐹷.≯᷾
+󠎃󗭞ڷ𐹷。≯‌᷾; 󠎃󗭞ڷ𐹷.≯‌᷾; [B1, C1, P1, V6]; xn--qkb4516kbi06fg2id.xn--zfg59fm0c; ; xn--qkb4516kbi06fg2id.xn--zfg31q; [B1, P1, V6] # ڷ𐹷.≯᷾
+󠎃󗭞ڷ𐹷。≯‌᷾; 󠎃󗭞ڷ𐹷.≯‌᷾; [B1, C1, P1, V6]; xn--qkb4516kbi06fg2id.xn--zfg59fm0c; ; xn--qkb4516kbi06fg2id.xn--zfg31q; [B1, P1, V6] # ڷ𐹷.≯᷾
+xn--qkb4516kbi06fg2id.xn--zfg31q; 󠎃󗭞ڷ𐹷.≯᷾; [B1, V6]; xn--qkb4516kbi06fg2id.xn--zfg31q; ; ; # ڷ𐹷.≯᷾
+xn--qkb4516kbi06fg2id.xn--zfg59fm0c; 󠎃󗭞ڷ𐹷.≯‌᷾; [B1, C1, V6]; xn--qkb4516kbi06fg2id.xn--zfg59fm0c; ; ; # ڷ𐹷.≯᷾
+ᛎ󠅍󠐕‍。𐹾𐹪𐻝-; ᛎ󠐕‍.𐹾𐹪𐻝-; [B1, B6, C2, P1, V3, V6]; xn--fxe848bq3411a.xn----q26i2bvu; ; xn--fxe63563p.xn----q26i2bvu; [B1, B6, P1, V3, V6] # ᛎ.𐹾𐹪-
+ᛎ󠅍󠐕‍。𐹾𐹪𐻝-; ᛎ󠐕‍.𐹾𐹪𐻝-; [B1, B6, C2, P1, V3, V6]; xn--fxe848bq3411a.xn----q26i2bvu; ; xn--fxe63563p.xn----q26i2bvu; [B1, B6, P1, V3, V6] # ᛎ.𐹾𐹪-
+xn--fxe63563p.xn----q26i2bvu; ᛎ󠐕.𐹾𐹪𐻝-; [B1, B6, V3, V6]; xn--fxe63563p.xn----q26i2bvu; ; ; # ᛎ.𐹾𐹪-
+xn--fxe848bq3411a.xn----q26i2bvu; ᛎ󠐕‍.𐹾𐹪𐻝-; [B1, B6, C2, V3, V6]; xn--fxe848bq3411a.xn----q26i2bvu; ; ; # ᛎ.𐹾𐹪-
+𐹶.𐫂; ; [B1]; xn--uo0d.xn--rw9c; ; ; # 𐹶.𐫂
+xn--uo0d.xn--rw9c; 𐹶.𐫂; [B1]; xn--uo0d.xn--rw9c; ; ; # 𐹶.𐫂
+ß‍်。⒈; ß‍်.⒈; [C2, P1, V6]; xn--zca679eh2l.xn--tsh; ; xn--ss-f4j.xn--tsh; [P1, V6] # ß်.⒈
+ß‍်。1.; ß‍်.1.; [C2]; xn--zca679eh2l.1.; ; xn--ss-f4j.1.; [] # ß်.1.
+SS‍်。1.; ss‍်.1.; [C2]; xn--ss-f4j585j.1.; ; xn--ss-f4j.1.; [] # ss်.1.
+ss‍်。1.; ss‍်.1.; [C2]; xn--ss-f4j585j.1.; ; xn--ss-f4j.1.; [] # ss်.1.
+Ss‍်。1.; ss‍်.1.; [C2]; xn--ss-f4j585j.1.; ; xn--ss-f4j.1.; [] # ss်.1.
+xn--ss-f4j.1.; ss်.1.; ; xn--ss-f4j.1.; ; ; # ss်.1.
+ss်.1.; ; ; xn--ss-f4j.1.; ; ; # ss်.1.
+SS်.1.; ss်.1.; ; xn--ss-f4j.1.; ; ; # ss်.1.
+Ss်.1.; ss်.1.; ; xn--ss-f4j.1.; ; ; # ss်.1.
+xn--ss-f4j585j.1.; ss‍်.1.; [C2]; xn--ss-f4j585j.1.; ; ; # ss်.1.
+xn--zca679eh2l.1.; ß‍်.1.; [C2]; xn--zca679eh2l.1.; ; ; # ß်.1.
+SS‍်。⒈; ss‍်.⒈; [C2, P1, V6]; xn--ss-f4j585j.xn--tsh; ; xn--ss-f4j.xn--tsh; [P1, V6] # ss်.⒈
+ss‍်。⒈; ss‍်.⒈; [C2, P1, V6]; xn--ss-f4j585j.xn--tsh; ; xn--ss-f4j.xn--tsh; [P1, V6] # ss်.⒈
+Ss‍်。⒈; ss‍်.⒈; [C2, P1, V6]; xn--ss-f4j585j.xn--tsh; ; xn--ss-f4j.xn--tsh; [P1, V6] # ss်.⒈
+xn--ss-f4j.xn--tsh; ss်.⒈; [V6]; xn--ss-f4j.xn--tsh; ; ; # ss်.⒈
+xn--ss-f4j585j.xn--tsh; ss‍်.⒈; [C2, V6]; xn--ss-f4j585j.xn--tsh; ; ; # ss်.⒈
+xn--zca679eh2l.xn--tsh; ß‍်.⒈; [C2, V6]; xn--zca679eh2l.xn--tsh; ; ; # ß်.⒈
+୍‌𙶵𞻘。‍; ୍‌𙶵𞻘.‍; [B1, C2, P1, V5, V6]; xn--9ic637hz82z32jc.xn--1ug; ; xn--9ic6417rn4xb.; [B1, P1, V5, V6] # ୍.
+xn--9ic6417rn4xb.; ୍𙶵𞻘.; [B1, V5, V6]; xn--9ic6417rn4xb.; ; ; # ୍.
+xn--9ic637hz82z32jc.xn--1ug; ୍‌𙶵𞻘.‍; [B1, C2, V5, V6]; xn--9ic637hz82z32jc.xn--1ug; ; ; # ୍.
+𐮅。ڼ🁕; 𐮅.ڼ🁕; [B3]; xn--c29c.xn--vkb8871w; ; ; # 𐮅.ڼ🁕
+𐮅。ڼ🁕; 𐮅.ڼ🁕; [B3]; xn--c29c.xn--vkb8871w; ; ; # 𐮅.ڼ🁕
+xn--c29c.xn--vkb8871w; 𐮅.ڼ🁕; [B3]; xn--c29c.xn--vkb8871w; ; ; # 𐮅.ڼ🁕
+ؠ្。𐫔󠀧‌𑈵; ؠ្.𐫔󠀧‌𑈵; [B2, B3, C1, P1, V6]; xn--fgb471g.xn--0ug9853g7verp838a; ; xn--fgb471g.xn--9w9c29jw3931a; [B2, B3, P1, V6] # ؠ្.𐫔𑈵
+xn--fgb471g.xn--9w9c29jw3931a; ؠ្.𐫔󠀧𑈵; [B2, B3, V6]; xn--fgb471g.xn--9w9c29jw3931a; ; ; # ؠ្.𐫔𑈵
+xn--fgb471g.xn--0ug9853g7verp838a; ؠ្.𐫔󠀧‌𑈵; [B2, B3, C1, V6]; xn--fgb471g.xn--0ug9853g7verp838a; ; ; # ؠ្.𐫔𑈵
+񋉕.𞣕𞤊; 񋉕.𞣕𞤬; [B1, P1, V5, V6]; xn--tf5w.xn--2b6hof; ; ; # .𞣕𞤬
+񋉕.𞣕𞤬; ; [B1, P1, V5, V6]; xn--tf5w.xn--2b6hof; ; ; # .𞣕𞤬
+xn--tf5w.xn--2b6hof; 񋉕.𞣕𞤬; [B1, V5, V6]; xn--tf5w.xn--2b6hof; ; ; # .𞣕𞤬
+ی𐨿.ß྄𑍬; ی𐨿.ß྄𑍬; ; xn--clb2593k.xn--zca216edt0r; ; xn--clb2593k.xn--ss-toj6092t; # ی𐨿.ß྄𑍬
+ی𐨿.ß྄𑍬; ; ; xn--clb2593k.xn--zca216edt0r; ; xn--clb2593k.xn--ss-toj6092t; # ی𐨿.ß྄𑍬
+ی𐨿.SS྄𑍬; ی𐨿.ss྄𑍬; ; xn--clb2593k.xn--ss-toj6092t; ; ; # ی𐨿.ss྄𑍬
+ی𐨿.ss྄𑍬; ; ; xn--clb2593k.xn--ss-toj6092t; ; ; # ی𐨿.ss྄𑍬
+xn--clb2593k.xn--ss-toj6092t; ی𐨿.ss྄𑍬; ; xn--clb2593k.xn--ss-toj6092t; ; ; # ی𐨿.ss྄𑍬
+xn--clb2593k.xn--zca216edt0r; ی𐨿.ß྄𑍬; ; xn--clb2593k.xn--zca216edt0r; ; ; # ی𐨿.ß྄𑍬
+ی𐨿.SS྄𑍬; ی𐨿.ss྄𑍬; ; xn--clb2593k.xn--ss-toj6092t; ; ; # ی𐨿.ss྄𑍬
+ی𐨿.ss྄𑍬; ی𐨿.ss྄𑍬; ; xn--clb2593k.xn--ss-toj6092t; ; ; # ی𐨿.ss྄𑍬
+ی𐨿.Ss྄𑍬; ی𐨿.ss྄𑍬; ; xn--clb2593k.xn--ss-toj6092t; ; ; # ی𐨿.ss྄𑍬
+ی𐨿.Ss྄𑍬; ی𐨿.ss྄𑍬; ; xn--clb2593k.xn--ss-toj6092t; ; ; # ی𐨿.ss྄𑍬
+𝟠≮‌。󠅱឴; 8≮‌.឴; [C1, P1, V5, V6]; xn--8-sgn10i.xn--z3e; ; xn--8-ngo.xn--z3e; [P1, V5, V6] # 8≮.
+𝟠≮‌。󠅱឴; 8≮‌.឴; [C1, P1, V5, V6]; xn--8-sgn10i.xn--z3e; ; xn--8-ngo.xn--z3e; [P1, V5, V6] # 8≮.
+8≮‌。󠅱឴; 8≮‌.឴; [C1, P1, V5, V6]; xn--8-sgn10i.xn--z3e; ; xn--8-ngo.xn--z3e; [P1, V5, V6] # 8≮.
+8≮‌。󠅱឴; 8≮‌.឴; [C1, P1, V5, V6]; xn--8-sgn10i.xn--z3e; ; xn--8-ngo.xn--z3e; [P1, V5, V6] # 8≮.
+xn--8-ngo.xn--z3e; 8≮.឴; [V5, V6]; xn--8-ngo.xn--z3e; ; ; # 8≮.
+xn--8-sgn10i.xn--z3e; 8≮‌.឴; [C1, V5, V6]; xn--8-sgn10i.xn--z3e; ; ; # 8≮.
+ᢕ≯︒񄂯.Ⴀ; ᢕ≯︒񄂯.Ⴀ; [P1, V6]; xn--fbf851cq98poxw1a.xn--7md; ; ; # ᢕ≯︒.Ⴀ
+ᢕ≯︒񄂯.Ⴀ; ᢕ≯︒񄂯.Ⴀ; [P1, V6]; xn--fbf851cq98poxw1a.xn--7md; ; ; # ᢕ≯︒.Ⴀ
+ᢕ≯。񄂯.Ⴀ; ᢕ≯.񄂯.Ⴀ; [P1, V6]; xn--fbf851c.xn--ko1u.xn--7md; ; ; # ᢕ≯..Ⴀ
+ᢕ≯。񄂯.Ⴀ; ᢕ≯.񄂯.Ⴀ; [P1, V6]; xn--fbf851c.xn--ko1u.xn--7md; ; ; # ᢕ≯..Ⴀ
+ᢕ≯。񄂯.ⴀ; ᢕ≯.񄂯.ⴀ; [P1, V6]; xn--fbf851c.xn--ko1u.xn--rkj; ; ; # ᢕ≯..ⴀ
+ᢕ≯。񄂯.ⴀ; ᢕ≯.񄂯.ⴀ; [P1, V6]; xn--fbf851c.xn--ko1u.xn--rkj; ; ; # ᢕ≯..ⴀ
+xn--fbf851c.xn--ko1u.xn--rkj; ᢕ≯.񄂯.ⴀ; [V6]; xn--fbf851c.xn--ko1u.xn--rkj; ; ; # ᢕ≯..ⴀ
+xn--fbf851c.xn--ko1u.xn--7md; ᢕ≯.񄂯.Ⴀ; [V6]; xn--fbf851c.xn--ko1u.xn--7md; ; ; # ᢕ≯..Ⴀ
+ᢕ≯︒񄂯.ⴀ; ᢕ≯︒񄂯.ⴀ; [P1, V6]; xn--fbf851cq98poxw1a.xn--rkj; ; ; # ᢕ≯︒.ⴀ
+ᢕ≯︒񄂯.ⴀ; ᢕ≯︒񄂯.ⴀ; [P1, V6]; xn--fbf851cq98poxw1a.xn--rkj; ; ; # ᢕ≯︒.ⴀ
+xn--fbf851cq98poxw1a.xn--rkj; ᢕ≯︒񄂯.ⴀ; [V6]; xn--fbf851cq98poxw1a.xn--rkj; ; ; # ᢕ≯︒.ⴀ
+xn--fbf851cq98poxw1a.xn--7md; ᢕ≯︒񄂯.Ⴀ; [V6]; xn--fbf851cq98poxw1a.xn--7md; ; ; # ᢕ≯︒.Ⴀ
+ྟ.-ࠪ; ྟ.-ࠪ; [V3, V5]; xn--vfd.xn----fhd; ; ; # ྟ.-ࠪ
+ྟ.-ࠪ; ; [V3, V5]; xn--vfd.xn----fhd; ; ; # ྟ.-ࠪ
+xn--vfd.xn----fhd; ྟ.-ࠪ; [V3, V5]; xn--vfd.xn----fhd; ; ; # ྟ.-ࠪ
+ᵬ󠆠.핒⒒⒈􈄦; ᵬ.핒⒒⒈􈄦; [P1, V6]; xn--tbg.xn--tsht7586kyts9l; ; ; # ᵬ.핒⒒⒈
+ᵬ󠆠.핒⒒⒈􈄦; ᵬ.핒⒒⒈􈄦; [P1, V6]; xn--tbg.xn--tsht7586kyts9l; ; ; # ᵬ.핒⒒⒈
+ᵬ󠆠.핒11.1.􈄦; ᵬ.핒11.1.􈄦; [P1, V6]; xn--tbg.xn--11-5o7k.1.xn--k469f; ; ; # ᵬ.핒11.1.
+ᵬ󠆠.핒11.1.􈄦; ᵬ.핒11.1.􈄦; [P1, V6]; xn--tbg.xn--11-5o7k.1.xn--k469f; ; ; # ᵬ.핒11.1.
+xn--tbg.xn--11-5o7k.1.xn--k469f; ᵬ.핒11.1.􈄦; [V6]; xn--tbg.xn--11-5o7k.1.xn--k469f; ; ; # ᵬ.핒11.1.
+xn--tbg.xn--tsht7586kyts9l; ᵬ.핒⒒⒈􈄦; [V6]; xn--tbg.xn--tsht7586kyts9l; ; ; # ᵬ.핒⒒⒈
+ς𑓂𐋢.٨; ς𑓂𐋢.٨; [B1]; xn--3xa8371khhl.xn--hib; ; xn--4xa6371khhl.xn--hib; # ς𑓂𐋢.٨
+ς𑓂𐋢.٨; ; [B1]; xn--3xa8371khhl.xn--hib; ; xn--4xa6371khhl.xn--hib; # ς𑓂𐋢.٨
+Σ𑓂𐋢.٨; σ𑓂𐋢.٨; [B1]; xn--4xa6371khhl.xn--hib; ; ; # σ𑓂𐋢.٨
+σ𑓂𐋢.٨; ; [B1]; xn--4xa6371khhl.xn--hib; ; ; # σ𑓂𐋢.٨
+xn--4xa6371khhl.xn--hib; σ𑓂𐋢.٨; [B1]; xn--4xa6371khhl.xn--hib; ; ; # σ𑓂𐋢.٨
+xn--3xa8371khhl.xn--hib; ς𑓂𐋢.٨; [B1]; xn--3xa8371khhl.xn--hib; ; ; # ς𑓂𐋢.٨
+Σ𑓂𐋢.٨; σ𑓂𐋢.٨; [B1]; xn--4xa6371khhl.xn--hib; ; ; # σ𑓂𐋢.٨
+σ𑓂𐋢.٨; σ𑓂𐋢.٨; [B1]; xn--4xa6371khhl.xn--hib; ; ; # σ𑓂𐋢.٨
+꥓‌𐋻‍.ⷸ𞿄𐹲; ; [B1, B6, C2, P1, V5, V6]; xn--0ugc8356he76c.xn--urju692efj0f; ; xn--3j9a531o.xn--urju692efj0f; [B1, P1, V5, V6] # ꥓𐋻.ⷸ𐹲
+xn--3j9a531o.xn--urju692efj0f; ꥓𐋻.ⷸ𞿄𐹲; [B1, V5, V6]; xn--3j9a531o.xn--urju692efj0f; ; ; # ꥓𐋻.ⷸ𐹲
+xn--0ugc8356he76c.xn--urju692efj0f; ꥓‌𐋻‍.ⷸ𞿄𐹲; [B1, B6, C2, V5, V6]; xn--0ugc8356he76c.xn--urju692efj0f; ; ; # ꥓𐋻.ⷸ𐹲
+⊼。񪧖ڕ; ⊼.񪧖ڕ; [B1, B5, B6, P1, V6]; xn--ofh.xn--rjb13118f; ; ; # ⊼.ڕ
+xn--ofh.xn--rjb13118f; ⊼.񪧖ڕ; [B1, B5, B6, V6]; xn--ofh.xn--rjb13118f; ; ; # ⊼.ڕ
+𐯬񖋔。󜳥; 𐯬񖋔.󜳥; [B2, B3, P1, V6]; xn--949co370q.xn--7g25e; ; ; # .
+xn--949co370q.xn--7g25e; 𐯬񖋔.󜳥; [B2, B3, V6]; xn--949co370q.xn--7g25e; ; ; # .
+؁𑍧ߝ。ς򬍘🀞឵; ؁𑍧ߝ.ς򬍘🀞឵; [B1, B6, P1, V6]; xn--jfb66gt010c.xn--3xa823h9p95ars26d; ; xn--jfb66gt010c.xn--4xa623h9p95ars26d; # 𑍧ߝ.ς🀞
+؁𑍧ߝ。Σ򬍘🀞឵; ؁𑍧ߝ.σ򬍘🀞឵; [B1, B6, P1, V6]; xn--jfb66gt010c.xn--4xa623h9p95ars26d; ; ; # 𑍧ߝ.σ🀞
+؁𑍧ߝ。σ򬍘🀞឵; ؁𑍧ߝ.σ򬍘🀞឵; [B1, B6, P1, V6]; xn--jfb66gt010c.xn--4xa623h9p95ars26d; ; ; # 𑍧ߝ.σ🀞
+xn--jfb66gt010c.xn--4xa623h9p95ars26d; ؁𑍧ߝ.σ򬍘🀞឵; [B1, B6, V6]; xn--jfb66gt010c.xn--4xa623h9p95ars26d; ; ; # 𑍧ߝ.σ🀞
+xn--jfb66gt010c.xn--3xa823h9p95ars26d; ؁𑍧ߝ.ς򬍘🀞឵; [B1, B6, V6]; xn--jfb66gt010c.xn--3xa823h9p95ars26d; ; ; # 𑍧ߝ.ς🀞
+-𐳲ن󠺐。꯭𝟥; -𐳲ن󠺐.꯭3; [B1, P1, V3, V5, V6]; xn----roc5482rek10i.xn--3-zw5e; ; ; # -𐳲ن.꯭3
+-𐳲ن󠺐。꯭3; -𐳲ن󠺐.꯭3; [B1, P1, V3, V5, V6]; xn----roc5482rek10i.xn--3-zw5e; ; ; # -𐳲ن.꯭3
+-𐲲ن󠺐。꯭3; -𐳲ن󠺐.꯭3; [B1, P1, V3, V5, V6]; xn----roc5482rek10i.xn--3-zw5e; ; ; # -𐳲ن.꯭3
+xn----roc5482rek10i.xn--3-zw5e; -𐳲ن󠺐.꯭3; [B1, V3, V5, V6]; xn----roc5482rek10i.xn--3-zw5e; ; ; # -𐳲ن.꯭3
+-𐲲ن󠺐。꯭𝟥; -𐳲ن󠺐.꯭3; [B1, P1, V3, V5, V6]; xn----roc5482rek10i.xn--3-zw5e; ; ; # -𐳲ن.꯭3
+‌󠴦。񲨕≮𐦜; ‌󠴦.񲨕≮𐦜; [B1, B5, B6, C1, P1, V6]; xn--0ug22251l.xn--gdhz712gzlr6b; ; xn--6v56e.xn--gdhz712gzlr6b; [B1, B5, B6, P1, V6] # .≮𐦜
+‌󠴦。񲨕≮𐦜; ‌󠴦.񲨕≮𐦜; [B1, B5, B6, C1, P1, V6]; xn--0ug22251l.xn--gdhz712gzlr6b; ; xn--6v56e.xn--gdhz712gzlr6b; [B1, B5, B6, P1, V6] # .≮𐦜
+‌󠴦。񲨕≮𐦜; ‌󠴦.񲨕≮𐦜; [B1, B5, B6, C1, P1, V6]; xn--0ug22251l.xn--gdhz712gzlr6b; ; xn--6v56e.xn--gdhz712gzlr6b; [B1, B5, B6, P1, V6] # .≮𐦜
+‌󠴦。񲨕≮𐦜; ‌󠴦.񲨕≮𐦜; [B1, B5, B6, C1, P1, V6]; xn--0ug22251l.xn--gdhz712gzlr6b; ; xn--6v56e.xn--gdhz712gzlr6b; [B1, B5, B6, P1, V6] # .≮𐦜
+xn--6v56e.xn--gdhz712gzlr6b; 󠴦.񲨕≮𐦜; [B1, B5, B6, V6]; xn--6v56e.xn--gdhz712gzlr6b; ; ; # .≮𐦜
+xn--0ug22251l.xn--gdhz712gzlr6b; ‌󠴦.񲨕≮𐦜; [B1, B5, B6, C1, V6]; xn--0ug22251l.xn--gdhz712gzlr6b; ; ; # .≮𐦜
+⒈✌򟬟.𝟡񠱣; ⒈✌򟬟.9񠱣; [P1, V6]; xn--tsh24g49550b.xn--9-o706d; ; ; # ⒈✌.9
+1.✌򟬟.9񠱣; ; [P1, V6]; 1.xn--7bi44996f.xn--9-o706d; ; ; # 1.✌.9
+1.xn--7bi44996f.xn--9-o706d; 1.✌򟬟.9񠱣; [V6]; 1.xn--7bi44996f.xn--9-o706d; ; ; # 1.✌.9
+xn--tsh24g49550b.xn--9-o706d; ⒈✌򟬟.9񠱣; [V6]; xn--tsh24g49550b.xn--9-o706d; ; ; # ⒈✌.9
+𑆾𞤬𐮆.٦ᷔ; ; [B1, V5]; xn--d29c79hf98r.xn--fib011j; ; ; # 𑆾𞤬𐮆.٦ᷔ
+𑆾𞤊𐮆.٦ᷔ; 𑆾𞤬𐮆.٦ᷔ; [B1, V5]; xn--d29c79hf98r.xn--fib011j; ; ; # 𑆾𞤬𐮆.٦ᷔ
+xn--d29c79hf98r.xn--fib011j; 𑆾𞤬𐮆.٦ᷔ; [B1, V5]; xn--d29c79hf98r.xn--fib011j; ; ; # 𑆾𞤬𐮆.٦ᷔ
+ς.꧀꣄; ς.꧀꣄; [V5]; xn--3xa.xn--0f9ars; ; xn--4xa.xn--0f9ars; # ς.꧀꣄
+ς.꧀꣄; ; [V5]; xn--3xa.xn--0f9ars; ; xn--4xa.xn--0f9ars; # ς.꧀꣄
+Σ.꧀꣄; σ.꧀꣄; [V5]; xn--4xa.xn--0f9ars; ; ; # σ.꧀꣄
+σ.꧀꣄; ; [V5]; xn--4xa.xn--0f9ars; ; ; # σ.꧀꣄
+xn--4xa.xn--0f9ars; σ.꧀꣄; [V5]; xn--4xa.xn--0f9ars; ; ; # σ.꧀꣄
+xn--3xa.xn--0f9ars; ς.꧀꣄; [V5]; xn--3xa.xn--0f9ars; ; ; # ς.꧀꣄
+Σ.꧀꣄; σ.꧀꣄; [V5]; xn--4xa.xn--0f9ars; ; ; # σ.꧀꣄
+σ.꧀꣄; σ.꧀꣄; [V5]; xn--4xa.xn--0f9ars; ; ; # σ.꧀꣄
+𑰶‌≯𐳐.࡛; 𑰶‌≯𐳐.࡛; [B1, B3, B6, C1, P1, V5, V6]; xn--0ug06g7697ap4ma.xn--qwb; ; xn--hdhz343g3wj.xn--qwb; [B1, B3, B6, P1, V5, V6] # 𑰶≯𐳐.࡛
+𑰶‌≯𐳐.࡛; 𑰶‌≯𐳐.࡛; [B1, B3, B6, C1, P1, V5, V6]; xn--0ug06g7697ap4ma.xn--qwb; ; xn--hdhz343g3wj.xn--qwb; [B1, B3, B6, P1, V5, V6] # 𑰶≯𐳐.࡛
+𑰶‌≯𐳐.࡛; ; [B1, B3, B6, C1, P1, V5, V6]; xn--0ug06g7697ap4ma.xn--qwb; ; xn--hdhz343g3wj.xn--qwb; [B1, B3, B6, P1, V5, V6] # 𑰶≯𐳐.࡛
+𑰶‌≯𐳐.࡛; 𑰶‌≯𐳐.࡛; [B1, B3, B6, C1, P1, V5, V6]; xn--0ug06g7697ap4ma.xn--qwb; ; xn--hdhz343g3wj.xn--qwb; [B1, B3, B6, P1, V5, V6] # 𑰶≯𐳐.࡛
+𑰶‌≯𐲐.࡛; 𑰶‌≯𐳐.࡛; [B1, B3, B6, C1, P1, V5, V6]; xn--0ug06g7697ap4ma.xn--qwb; ; xn--hdhz343g3wj.xn--qwb; [B1, B3, B6, P1, V5, V6] # 𑰶≯𐳐.࡛
+𑰶‌≯𐲐.࡛; 𑰶‌≯𐳐.࡛; [B1, B3, B6, C1, P1, V5, V6]; xn--0ug06g7697ap4ma.xn--qwb; ; xn--hdhz343g3wj.xn--qwb; [B1, B3, B6, P1, V5, V6] # 𑰶≯𐳐.࡛
+xn--hdhz343g3wj.xn--qwb; 𑰶≯𐳐.࡛; [B1, B3, B6, V5, V6]; xn--hdhz343g3wj.xn--qwb; ; ; # 𑰶≯𐳐.࡛
+xn--0ug06g7697ap4ma.xn--qwb; 𑰶‌≯𐳐.࡛; [B1, B3, B6, C1, V5, V6]; xn--0ug06g7697ap4ma.xn--qwb; ; ; # 𑰶≯𐳐.࡛
+𑰶‌≯𐲐.࡛; 𑰶‌≯𐳐.࡛; [B1, B3, B6, C1, P1, V5, V6]; xn--0ug06g7697ap4ma.xn--qwb; ; xn--hdhz343g3wj.xn--qwb; [B1, B3, B6, P1, V5, V6] # 𑰶≯𐳐.࡛
+𑰶‌≯𐲐.࡛; 𑰶‌≯𐳐.࡛; [B1, B3, B6, C1, P1, V5, V6]; xn--0ug06g7697ap4ma.xn--qwb; ; xn--hdhz343g3wj.xn--qwb; [B1, B3, B6, P1, V5, V6] # 𑰶≯𐳐.࡛
+羚。≯; 羚.≯; [P1, V6]; xn--xt0a.xn--hdh; ; ; # 羚.≯
+羚。≯; 羚.≯; [P1, V6]; xn--xt0a.xn--hdh; ; ; # 羚.≯
+羚。≯; 羚.≯; [P1, V6]; xn--xt0a.xn--hdh; ; ; # 羚.≯
+羚。≯; 羚.≯; [P1, V6]; xn--xt0a.xn--hdh; ; ; # 羚.≯
+xn--xt0a.xn--hdh; 羚.≯; [V6]; xn--xt0a.xn--hdh; ; ; # 羚.≯
+𑓂᝙.ࢨ; 𑓂᝙.ࢨ; [B1, P1, V5, V6]; xn--e1e9580k.xn--xyb; ; ; # 𑓂.ࢨ
+𑓂᝙.ࢨ; ; [B1, P1, V5, V6]; xn--e1e9580k.xn--xyb; ; ; # 𑓂.ࢨ
+xn--e1e9580k.xn--xyb; 𑓂᝙.ࢨ; [B1, V5, V6]; xn--e1e9580k.xn--xyb; ; ; # 𑓂.ࢨ
+󨣿󠇀‍。٣ҠჀ𝟑; 󨣿‍.٣ҡჀ3; [B1, B6, C2, P1, V6]; xn--1ug89936l.xn--3-ozb36kixu; ; xn--1r19e.xn--3-ozb36kixu; [B1, P1, V6] # .٣ҡჀ3
+󨣿󠇀‍。٣ҠჀ3; 󨣿‍.٣ҡჀ3; [B1, B6, C2, P1, V6]; xn--1ug89936l.xn--3-ozb36kixu; ; xn--1r19e.xn--3-ozb36kixu; [B1, P1, V6] # .٣ҡჀ3
+󨣿󠇀‍。٣ҡⴠ3; 󨣿‍.٣ҡⴠ3; [B1, B6, C2, P1, V6]; xn--1ug89936l.xn--3-ozb36ko13f; ; xn--1r19e.xn--3-ozb36ko13f; [B1, P1, V6] # .٣ҡⴠ3
+xn--1r19e.xn--3-ozb36ko13f; 󨣿.٣ҡⴠ3; [B1, V6]; xn--1r19e.xn--3-ozb36ko13f; ; ; # .٣ҡⴠ3
+xn--1ug89936l.xn--3-ozb36ko13f; 󨣿‍.٣ҡⴠ3; [B1, B6, C2, V6]; xn--1ug89936l.xn--3-ozb36ko13f; ; ; # .٣ҡⴠ3
+xn--1r19e.xn--3-ozb36kixu; 󨣿.٣ҡჀ3; [B1, V6]; xn--1r19e.xn--3-ozb36kixu; ; ; # .٣ҡჀ3
+xn--1ug89936l.xn--3-ozb36kixu; 󨣿‍.٣ҡჀ3; [B1, B6, C2, V6]; xn--1ug89936l.xn--3-ozb36kixu; ; ; # .٣ҡჀ3
+󨣿󠇀‍。٣ҡⴠ𝟑; 󨣿‍.٣ҡⴠ3; [B1, B6, C2, P1, V6]; xn--1ug89936l.xn--3-ozb36ko13f; ; xn--1r19e.xn--3-ozb36ko13f; [B1, P1, V6] # .٣ҡⴠ3
+󨣿󠇀‍。٣Ҡⴠ3; 󨣿‍.٣ҡⴠ3; [B1, B6, C2, P1, V6]; xn--1ug89936l.xn--3-ozb36ko13f; ; xn--1r19e.xn--3-ozb36ko13f; [B1, P1, V6] # .٣ҡⴠ3
+󨣿󠇀‍。٣Ҡⴠ𝟑; 󨣿‍.٣ҡⴠ3; [B1, B6, C2, P1, V6]; xn--1ug89936l.xn--3-ozb36ko13f; ; xn--1r19e.xn--3-ozb36ko13f; [B1, P1, V6] # .٣ҡⴠ3
+ᡷ。𐹢࣠; ᡷ.𐹢࣠; [B1]; xn--k9e.xn--j0b5005k; ; ; # ᡷ.𐹢࣠
+xn--k9e.xn--j0b5005k; ᡷ.𐹢࣠; [B1]; xn--k9e.xn--j0b5005k; ; ; # ᡷ.𐹢࣠
+򕮇᯳。٦񗜼្ß; 򕮇᯳.٦񗜼្ß; [B1, P1, V6]; xn--1zf58212h.xn--zca34zk4qx711k; ; xn--1zf58212h.xn--ss-pyd459o3258m; # ᯳.٦្ß
+򕮇᯳。٦񗜼្ß; 򕮇᯳.٦񗜼្ß; [B1, P1, V6]; xn--1zf58212h.xn--zca34zk4qx711k; ; xn--1zf58212h.xn--ss-pyd459o3258m; # ᯳.٦្ß
+򕮇᯳。٦񗜼្SS; 򕮇᯳.٦񗜼្ss; [B1, P1, V6]; xn--1zf58212h.xn--ss-pyd459o3258m; ; ; # ᯳.٦្ss
+򕮇᯳。٦񗜼្ss; 򕮇᯳.٦񗜼្ss; [B1, P1, V6]; xn--1zf58212h.xn--ss-pyd459o3258m; ; ; # ᯳.٦្ss
+򕮇᯳。٦񗜼្Ss; 򕮇᯳.٦񗜼្ss; [B1, P1, V6]; xn--1zf58212h.xn--ss-pyd459o3258m; ; ; # ᯳.٦្ss
+xn--1zf58212h.xn--ss-pyd459o3258m; 򕮇᯳.٦񗜼្ss; [B1, V6]; xn--1zf58212h.xn--ss-pyd459o3258m; ; ; # ᯳.٦្ss
+xn--1zf58212h.xn--zca34zk4qx711k; 򕮇᯳.٦񗜼្ß; [B1, V6]; xn--1zf58212h.xn--zca34zk4qx711k; ; ; # ᯳.٦្ß
+򕮇᯳。٦񗜼្SS; 򕮇᯳.٦񗜼្ss; [B1, P1, V6]; xn--1zf58212h.xn--ss-pyd459o3258m; ; ; # ᯳.٦្ss
+򕮇᯳。٦񗜼្ss; 򕮇᯳.٦񗜼្ss; [B1, P1, V6]; xn--1zf58212h.xn--ss-pyd459o3258m; ; ; # ᯳.٦្ss
+򕮇᯳。٦񗜼្Ss; 򕮇᯳.٦񗜼្ss; [B1, P1, V6]; xn--1zf58212h.xn--ss-pyd459o3258m; ; ; # ᯳.٦្ss
+٤򤽎𑲛.󠔢︒≠; ; [B1, P1, V6]; xn--dib0653l2i02d.xn--1ch7467f14u4g; ; ; # ٤𑲛.︒≠
+٤򤽎𑲛.󠔢︒≠; ٤򤽎𑲛.󠔢︒≠; [B1, P1, V6]; xn--dib0653l2i02d.xn--1ch7467f14u4g; ; ; # ٤𑲛.︒≠
+٤򤽎𑲛.󠔢。≠; ٤򤽎𑲛.󠔢.≠; [B1, P1, V6]; xn--dib0653l2i02d.xn--k736e.xn--1ch; ; ; # ٤𑲛..≠
+٤򤽎𑲛.󠔢。≠; ٤򤽎𑲛.󠔢.≠; [B1, P1, V6]; xn--dib0653l2i02d.xn--k736e.xn--1ch; ; ; # ٤𑲛..≠
+xn--dib0653l2i02d.xn--k736e.xn--1ch; ٤򤽎𑲛.󠔢.≠; [B1, V6]; xn--dib0653l2i02d.xn--k736e.xn--1ch; ; ; # ٤𑲛..≠
+xn--dib0653l2i02d.xn--1ch7467f14u4g; ٤򤽎𑲛.󠔢︒≠; [B1, V6]; xn--dib0653l2i02d.xn--1ch7467f14u4g; ; ; # ٤𑲛.︒≠
+➆񷧕ỗ⒈.򑬒񡘮࡛𝟫; ➆񷧕ỗ⒈.򑬒񡘮࡛9; [P1, V6]; xn--6lg26tvvc6v99z.xn--9-6jd87310jtcqs; ; ; # ➆ỗ⒈.࡛9
+➆񷧕ỗ⒈.򑬒񡘮࡛𝟫; ➆񷧕ỗ⒈.򑬒񡘮࡛9; [P1, V6]; xn--6lg26tvvc6v99z.xn--9-6jd87310jtcqs; ; ; # ➆ỗ⒈.࡛9
+➆񷧕ỗ1..򑬒񡘮࡛9; ; [P1, V6, X4_2]; xn--1-3xm292b6044r..xn--9-6jd87310jtcqs; [P1, V6, A4_2]; ; # ➆ỗ1..࡛9
+➆񷧕ỗ1..򑬒񡘮࡛9; ➆񷧕ỗ1..򑬒񡘮࡛9; [P1, V6, X4_2]; xn--1-3xm292b6044r..xn--9-6jd87310jtcqs; [P1, V6, A4_2]; ; # ➆ỗ1..࡛9
+➆񷧕Ỗ1..򑬒񡘮࡛9; ➆񷧕ỗ1..򑬒񡘮࡛9; [P1, V6, X4_2]; xn--1-3xm292b6044r..xn--9-6jd87310jtcqs; [P1, V6, A4_2]; ; # ➆ỗ1..࡛9
+➆񷧕Ỗ1..򑬒񡘮࡛9; ➆񷧕ỗ1..򑬒񡘮࡛9; [P1, V6, X4_2]; xn--1-3xm292b6044r..xn--9-6jd87310jtcqs; [P1, V6, A4_2]; ; # ➆ỗ1..࡛9
+xn--1-3xm292b6044r..xn--9-6jd87310jtcqs; ➆񷧕ỗ1..򑬒񡘮࡛9; [V6, X4_2]; xn--1-3xm292b6044r..xn--9-6jd87310jtcqs; [V6, A4_2]; ; # ➆ỗ1..࡛9
+➆񷧕Ỗ⒈.򑬒񡘮࡛𝟫; ➆񷧕ỗ⒈.򑬒񡘮࡛9; [P1, V6]; xn--6lg26tvvc6v99z.xn--9-6jd87310jtcqs; ; ; # ➆ỗ⒈.࡛9
+➆񷧕Ỗ⒈.򑬒񡘮࡛𝟫; ➆񷧕ỗ⒈.򑬒񡘮࡛9; [P1, V6]; xn--6lg26tvvc6v99z.xn--9-6jd87310jtcqs; ; ; # ➆ỗ⒈.࡛9
+xn--6lg26tvvc6v99z.xn--9-6jd87310jtcqs; ➆񷧕ỗ⒈.򑬒񡘮࡛9; [V6]; xn--6lg26tvvc6v99z.xn--9-6jd87310jtcqs; ; ; # ➆ỗ⒈.࡛9
+‍。𞤘; ‍.𞤺; [B1, C2]; xn--1ug.xn--ye6h; ; .xn--ye6h; [A4_2] # .𞤺
+‍。𞤘; ‍.𞤺; [B1, C2]; xn--1ug.xn--ye6h; ; .xn--ye6h; [A4_2] # .𞤺
+‍。𞤺; ‍.𞤺; [B1, C2]; xn--1ug.xn--ye6h; ; .xn--ye6h; [A4_2] # .𞤺
+.xn--ye6h; .𞤺; [X4_2]; .xn--ye6h; [A4_2]; ; # .𞤺
+xn--1ug.xn--ye6h; ‍.𞤺; [B1, C2]; xn--1ug.xn--ye6h; ; ; # .𞤺
+‍。𞤺; ‍.𞤺; [B1, C2]; xn--1ug.xn--ye6h; ; .xn--ye6h; [A4_2] # .𞤺
+xn--ye6h; 𞤺; ; xn--ye6h; ; ; # 𞤺
+𞤺; ; ; xn--ye6h; ; ; # 𞤺
+𞤘; 𞤺; ; xn--ye6h; ; ; # 𞤺
+ࠩܤ.ᢣ; ; [B1, V5]; xn--unb53c.xn--tbf; ; ; # ࠩܤ.ᢣ
+xn--unb53c.xn--tbf; ࠩܤ.ᢣ; [B1, V5]; xn--unb53c.xn--tbf; ; ; # ࠩܤ.ᢣ
+ܼ‌-。𓐾ß; ܼ‌-.𓐾ß; [C1, P1, V3, V5, V6]; xn----s2c071q.xn--zca7848m; ; xn----s2c.xn--ss-066q; [P1, V3, V5, V6] # ܼ-.ß
+ܼ‌-。𓐾SS; ܼ‌-.𓐾ss; [C1, P1, V3, V5, V6]; xn----s2c071q.xn--ss-066q; ; xn----s2c.xn--ss-066q; [P1, V3, V5, V6] # ܼ-.ss
+ܼ‌-。𓐾ss; ܼ‌-.𓐾ss; [C1, P1, V3, V5, V6]; xn----s2c071q.xn--ss-066q; ; xn----s2c.xn--ss-066q; [P1, V3, V5, V6] # ܼ-.ss
+ܼ‌-。𓐾Ss; ܼ‌-.𓐾ss; [C1, P1, V3, V5, V6]; xn----s2c071q.xn--ss-066q; ; xn----s2c.xn--ss-066q; [P1, V3, V5, V6] # ܼ-.ss
+xn----s2c.xn--ss-066q; ܼ-.𓐾ss; [V3, V5, V6]; xn----s2c.xn--ss-066q; ; ; # ܼ-.ss
+xn----s2c071q.xn--ss-066q; ܼ‌-.𓐾ss; [C1, V3, V5, V6]; xn----s2c071q.xn--ss-066q; ; ; # ܼ-.ss
+xn----s2c071q.xn--zca7848m; ܼ‌-.𓐾ß; [C1, V3, V5, V6]; xn----s2c071q.xn--zca7848m; ; ; # ܼ-.ß
+‌ς🃡⒗.ೆ仧ݖ; ; [B1, B5, B6, C1, P1, V5, V6]; xn--3xa795lz9czy52d.xn--9ob79ycx2e; ; xn--4xa229nbu92a.xn--9ob79ycx2e; [B5, B6, P1, V5, V6] # ς🃡⒗.ೆ仧ݖ
+‌ς🃡16..ೆ仧ݖ; ; [B1, B5, B6, C1, V5, X4_2]; xn--16-rbc1800avy99b..xn--9ob79ycx2e; [B1, B5, B6, C1, V5, A4_2]; xn--16-ubc66061c..xn--9ob79ycx2e; [B5, B6, V5, A4_2] # ς🃡16..ೆ仧ݖ
+‌Σ🃡16..ೆ仧ݖ; ‌σ🃡16..ೆ仧ݖ; [B1, B5, B6, C1, V5, X4_2]; xn--16-ubc7700avy99b..xn--9ob79ycx2e; [B1, B5, B6, C1, V5, A4_2]; xn--16-ubc66061c..xn--9ob79ycx2e; [B5, B6, V5, A4_2] # σ🃡16..ೆ仧ݖ
+‌σ🃡16..ೆ仧ݖ; ; [B1, B5, B6, C1, V5, X4_2]; xn--16-ubc7700avy99b..xn--9ob79ycx2e; [B1, B5, B6, C1, V5, A4_2]; xn--16-ubc66061c..xn--9ob79ycx2e; [B5, B6, V5, A4_2] # σ🃡16..ೆ仧ݖ
+xn--16-ubc66061c..xn--9ob79ycx2e; σ🃡16..ೆ仧ݖ; [B5, B6, V5, X4_2]; xn--16-ubc66061c..xn--9ob79ycx2e; [B5, B6, V5, A4_2]; ; # σ🃡16..ೆ仧ݖ
+xn--16-ubc7700avy99b..xn--9ob79ycx2e; ‌σ🃡16..ೆ仧ݖ; [B1, B5, B6, C1, V5, X4_2]; xn--16-ubc7700avy99b..xn--9ob79ycx2e; [B1, B5, B6, C1, V5, A4_2]; ; # σ🃡16..ೆ仧ݖ
+xn--16-rbc1800avy99b..xn--9ob79ycx2e; ‌ς🃡16..ೆ仧ݖ; [B1, B5, B6, C1, V5, X4_2]; xn--16-rbc1800avy99b..xn--9ob79ycx2e; [B1, B5, B6, C1, V5, A4_2]; ; # ς🃡16..ೆ仧ݖ
+‌Σ🃡⒗.ೆ仧ݖ; ‌σ🃡⒗.ೆ仧ݖ; [B1, B5, B6, C1, P1, V5, V6]; xn--4xa595lz9czy52d.xn--9ob79ycx2e; ; xn--4xa229nbu92a.xn--9ob79ycx2e; [B5, B6, P1, V5, V6] # σ🃡⒗.ೆ仧ݖ
+‌σ🃡⒗.ೆ仧ݖ; ; [B1, B5, B6, C1, P1, V5, V6]; xn--4xa595lz9czy52d.xn--9ob79ycx2e; ; xn--4xa229nbu92a.xn--9ob79ycx2e; [B5, B6, P1, V5, V6] # σ🃡⒗.ೆ仧ݖ
+xn--4xa229nbu92a.xn--9ob79ycx2e; σ🃡⒗.ೆ仧ݖ; [B5, B6, V5, V6]; xn--4xa229nbu92a.xn--9ob79ycx2e; ; ; # σ🃡⒗.ೆ仧ݖ
+xn--4xa595lz9czy52d.xn--9ob79ycx2e; ‌σ🃡⒗.ೆ仧ݖ; [B1, B5, B6, C1, V5, V6]; xn--4xa595lz9czy52d.xn--9ob79ycx2e; ; ; # σ🃡⒗.ೆ仧ݖ
+xn--3xa795lz9czy52d.xn--9ob79ycx2e; ‌ς🃡⒗.ೆ仧ݖ; [B1, B5, B6, C1, V5, V6]; xn--3xa795lz9czy52d.xn--9ob79ycx2e; ; ; # ς🃡⒗.ೆ仧ݖ
+-.𞸚; -.ظ; [B1, V3]; -.xn--3gb; ; ; # -.ظ
+-.ظ; ; [B1, V3]; -.xn--3gb; ; ; # -.ظ
+-.xn--3gb; -.ظ; [B1, V3]; -.xn--3gb; ; ; # -.ظ
+򏛓ڃ.ཾش; ; [B1, B5, B6, P1, V5, V6]; xn--8ib92728i.xn--zgb968b; ; ; # ڃ.ཾش
+xn--8ib92728i.xn--zgb968b; 򏛓ڃ.ཾش; [B1, B5, B6, V5, V6]; xn--8ib92728i.xn--zgb968b; ; ; # ڃ.ཾش
+࿦ࡃ񽶬.𐮏; ; [B5, P1, V6]; xn--1vb320b5m04p.xn--m29c; ; ; # ࡃ.𐮏
+xn--1vb320b5m04p.xn--m29c; ࿦ࡃ񽶬.𐮏; [B5, V6]; xn--1vb320b5m04p.xn--m29c; ; ; # ࡃ.𐮏
+2񎨠ߋß。ᠽ; 2񎨠ߋß.ᠽ; [B1, P1, V6]; xn--2-qfa924cez02l.xn--w7e; ; xn--2ss-odg83511n.xn--w7e; # 2ߋß.ᠽ
+2񎨠ߋSS。ᠽ; 2񎨠ߋss.ᠽ; [B1, P1, V6]; xn--2ss-odg83511n.xn--w7e; ; ; # 2ߋss.ᠽ
+2񎨠ߋss。ᠽ; 2񎨠ߋss.ᠽ; [B1, P1, V6]; xn--2ss-odg83511n.xn--w7e; ; ; # 2ߋss.ᠽ
+xn--2ss-odg83511n.xn--w7e; 2񎨠ߋss.ᠽ; [B1, V6]; xn--2ss-odg83511n.xn--w7e; ; ; # 2ߋss.ᠽ
+xn--2-qfa924cez02l.xn--w7e; 2񎨠ߋß.ᠽ; [B1, V6]; xn--2-qfa924cez02l.xn--w7e; ; ; # 2ߋß.ᠽ
+2񎨠ߋSs。ᠽ; 2񎨠ߋss.ᠽ; [B1, P1, V6]; xn--2ss-odg83511n.xn--w7e; ; ; # 2ߋss.ᠽ
+㸳ߊ≮.ێß-‍; 㸳ߊ≮.ێß-‍; [B2, B3, B5, B6, C2, P1, V6]; xn--lsb457kkut.xn----pfa076bys4a; ; xn--lsb457kkut.xn--ss--qjf; [B2, B3, B5, B6, P1, V3, V6] # 㸳ߊ≮.ێß-
+㸳ߊ≮.ێß-‍; 㸳ߊ≮.ێß-‍; [B2, B3, B5, B6, C2, P1, V6]; xn--lsb457kkut.xn----pfa076bys4a; ; xn--lsb457kkut.xn--ss--qjf; [B2, B3, B5, B6, P1, V3, V6] # 㸳ߊ≮.ێß-
+㸳ߊ≮.ێß-‍; ; [B2, B3, B5, B6, C2, P1, V6]; xn--lsb457kkut.xn----pfa076bys4a; ; xn--lsb457kkut.xn--ss--qjf; [B2, B3, B5, B6, P1, V3, V6] # 㸳ߊ≮.ێß-
+㸳ߊ≮.ێß-‍; 㸳ߊ≮.ێß-‍; [B2, B3, B5, B6, C2, P1, V6]; xn--lsb457kkut.xn----pfa076bys4a; ; xn--lsb457kkut.xn--ss--qjf; [B2, B3, B5, B6, P1, V3, V6] # 㸳ߊ≮.ێß-
+㸳ߊ≮.ێSS-‍; 㸳ߊ≮.ێss-‍; [B2, B3, B5, B6, C2, P1, V6]; xn--lsb457kkut.xn--ss--qjf2343a; ; xn--lsb457kkut.xn--ss--qjf; [B2, B3, B5, B6, P1, V3, V6] # 㸳ߊ≮.ێss-
+㸳ߊ≮.ێSS-‍; 㸳ߊ≮.ێss-‍; [B2, B3, B5, B6, C2, P1, V6]; xn--lsb457kkut.xn--ss--qjf2343a; ; xn--lsb457kkut.xn--ss--qjf; [B2, B3, B5, B6, P1, V3, V6] # 㸳ߊ≮.ێss-
+㸳ߊ≮.ێss-‍; ; [B2, B3, B5, B6, C2, P1, V6]; xn--lsb457kkut.xn--ss--qjf2343a; ; xn--lsb457kkut.xn--ss--qjf; [B2, B3, B5, B6, P1, V3, V6] # 㸳ߊ≮.ێss-
+㸳ߊ≮.ێss-‍; 㸳ߊ≮.ێss-‍; [B2, B3, B5, B6, C2, P1, V6]; xn--lsb457kkut.xn--ss--qjf2343a; ; xn--lsb457kkut.xn--ss--qjf; [B2, B3, B5, B6, P1, V3, V6] # 㸳ߊ≮.ێss-
+xn--lsb457kkut.xn--ss--qjf; 㸳ߊ≮.ێss-; [B2, B3, B5, B6, V3, V6]; xn--lsb457kkut.xn--ss--qjf; ; ; # 㸳ߊ≮.ێss-
+xn--lsb457kkut.xn--ss--qjf2343a; 㸳ߊ≮.ێss-‍; [B2, B3, B5, B6, C2, V6]; xn--lsb457kkut.xn--ss--qjf2343a; ; ; # 㸳ߊ≮.ێss-
+xn--lsb457kkut.xn----pfa076bys4a; 㸳ߊ≮.ێß-‍; [B2, B3, B5, B6, C2, V6]; xn--lsb457kkut.xn----pfa076bys4a; ; ; # 㸳ߊ≮.ێß-
+㸳ߊ≮.ێSS-‍; 㸳ߊ≮.ێss-‍; [B2, B3, B5, B6, C2, P1, V6]; xn--lsb457kkut.xn--ss--qjf2343a; ; xn--lsb457kkut.xn--ss--qjf; [B2, B3, B5, B6, P1, V3, V6] # 㸳ߊ≮.ێss-
+㸳ߊ≮.ێSS-‍; 㸳ߊ≮.ێss-‍; [B2, B3, B5, B6, C2, P1, V6]; xn--lsb457kkut.xn--ss--qjf2343a; ; xn--lsb457kkut.xn--ss--qjf; [B2, B3, B5, B6, P1, V3, V6] # 㸳ߊ≮.ێss-
+㸳ߊ≮.ێss-‍; 㸳ߊ≮.ێss-‍; [B2, B3, B5, B6, C2, P1, V6]; xn--lsb457kkut.xn--ss--qjf2343a; ; xn--lsb457kkut.xn--ss--qjf; [B2, B3, B5, B6, P1, V3, V6] # 㸳ߊ≮.ێss-
+㸳ߊ≮.ێss-‍; 㸳ߊ≮.ێss-‍; [B2, B3, B5, B6, C2, P1, V6]; xn--lsb457kkut.xn--ss--qjf2343a; ; xn--lsb457kkut.xn--ss--qjf; [B2, B3, B5, B6, P1, V3, V6] # 㸳ߊ≮.ێss-
+㸳ߊ≮.ێSs-‍; 㸳ߊ≮.ێss-‍; [B2, B3, B5, B6, C2, P1, V6]; xn--lsb457kkut.xn--ss--qjf2343a; ; xn--lsb457kkut.xn--ss--qjf; [B2, B3, B5, B6, P1, V3, V6] # 㸳ߊ≮.ێss-
+㸳ߊ≮.ێSs-‍; 㸳ߊ≮.ێss-‍; [B2, B3, B5, B6, C2, P1, V6]; xn--lsb457kkut.xn--ss--qjf2343a; ; xn--lsb457kkut.xn--ss--qjf; [B2, B3, B5, B6, P1, V3, V6] # 㸳ߊ≮.ێss-
+㸳ߊ≮.ێSs-‍; 㸳ߊ≮.ێss-‍; [B2, B3, B5, B6, C2, P1, V6]; xn--lsb457kkut.xn--ss--qjf2343a; ; xn--lsb457kkut.xn--ss--qjf; [B2, B3, B5, B6, P1, V3, V6] # 㸳ߊ≮.ێss-
+㸳ߊ≮.ێSs-‍; 㸳ߊ≮.ێss-‍; [B2, B3, B5, B6, C2, P1, V6]; xn--lsb457kkut.xn--ss--qjf2343a; ; xn--lsb457kkut.xn--ss--qjf; [B2, B3, B5, B6, P1, V3, V6] # 㸳ߊ≮.ێss-
+-򷝬፞𑜧.ᷫ-︒; ; [P1, V3, V5, V6]; xn----b5h1837n2ok9f.xn----mkmw278h; ; ; # -፞𑜧.ᷫ-︒
+-򷝬፞𑜧.ᷫ-。; -򷝬፞𑜧.ᷫ-.; [P1, V3, V5, V6]; xn----b5h1837n2ok9f.xn----mkm.; ; ; # -፞𑜧.ᷫ-.
+xn----b5h1837n2ok9f.xn----mkm.; -򷝬፞𑜧.ᷫ-.; [V3, V5, V6]; xn----b5h1837n2ok9f.xn----mkm.; ; ; # -፞𑜧.ᷫ-.
+xn----b5h1837n2ok9f.xn----mkmw278h; -򷝬፞𑜧.ᷫ-︒; [V3, V5, V6]; xn----b5h1837n2ok9f.xn----mkmw278h; ; ; # -፞𑜧.ᷫ-︒
+︒.򚠡ᩙ; ; [P1, V6]; xn--y86c.xn--cof61594i; ; ; # ︒.ᩙ
+。.򚠡ᩙ; ..򚠡ᩙ; [P1, V6, X4_2]; ..xn--cof61594i; [P1, V6, A4_2]; ; # ..ᩙ
+..xn--cof61594i; ..򚠡ᩙ; [V6, X4_2]; ..xn--cof61594i; [V6, A4_2]; ; # ..ᩙ
+xn--y86c.xn--cof61594i; ︒.򚠡ᩙ; [V6]; xn--y86c.xn--cof61594i; ; ; # ︒.ᩙ
+̣ⷡ。‌⓾‌ڹ; ̣ⷡ.‌⓾‌ڹ; [B1, B3, B6, C1, V5]; xn--kta899s.xn--skb970ka771c; ; xn--kta899s.xn--skb116m; [B1, B3, B6, V5] # ̣ⷡ.⓾ڹ
+xn--kta899s.xn--skb116m; ̣ⷡ.⓾ڹ; [B1, B3, B6, V5]; xn--kta899s.xn--skb116m; ; ; # ̣ⷡ.⓾ڹ
+xn--kta899s.xn--skb970ka771c; ̣ⷡ.‌⓾‌ڹ; [B1, B3, B6, C1, V5]; xn--kta899s.xn--skb970ka771c; ; ; # ̣ⷡ.⓾ڹ
+𞠶ᠴ۝。ၴ𞤵󠅦; 𞠶ᠴ۝.ၴ𞤵; [B1, B2, P1, V5, V6]; xn--tlb199fwl35a.xn--yld4613v; ; ; # 𞠶ᠴ.ၴ𞤵
+𞠶ᠴ۝。ၴ𞤵󠅦; 𞠶ᠴ۝.ၴ𞤵; [B1, B2, P1, V5, V6]; xn--tlb199fwl35a.xn--yld4613v; ; ; # 𞠶ᠴ.ၴ𞤵
+𞠶ᠴ۝。ၴ𞤓󠅦; 𞠶ᠴ۝.ၴ𞤵; [B1, B2, P1, V5, V6]; xn--tlb199fwl35a.xn--yld4613v; ; ; # 𞠶ᠴ.ၴ𞤵
+xn--tlb199fwl35a.xn--yld4613v; 𞠶ᠴ۝.ၴ𞤵; [B1, B2, V5, V6]; xn--tlb199fwl35a.xn--yld4613v; ; ; # 𞠶ᠴ.ၴ𞤵
+𞠶ᠴ۝。ၴ𞤓󠅦; 𞠶ᠴ۝.ၴ𞤵; [B1, B2, P1, V5, V6]; xn--tlb199fwl35a.xn--yld4613v; ; ; # 𞠶ᠴ.ၴ𞤵
+𑰺.-򑟏; ; [P1, V3, V5, V6]; xn--jk3d.xn----iz68g; ; ; # 𑰺.-
+xn--jk3d.xn----iz68g; 𑰺.-򑟏; [V3, V5, V6]; xn--jk3d.xn----iz68g; ; ; # 𑰺.-
+󠻩.赏; 󠻩.赏; [P1, V6]; xn--2856e.xn--6o3a; ; ; # .赏
+󠻩.赏; ; [P1, V6]; xn--2856e.xn--6o3a; ; ; # .赏
+xn--2856e.xn--6o3a; 󠻩.赏; [V6]; xn--2856e.xn--6o3a; ; ; # .赏
+ڰᠡ。Ⴁ; ڰᠡ.Ⴁ; [B2, B3, P1, V6]; xn--jkb440g.xn--8md; ; ; # ڰᠡ.Ⴁ
+ڰᠡ。Ⴁ; ڰᠡ.Ⴁ; [B2, B3, P1, V6]; xn--jkb440g.xn--8md; ; ; # ڰᠡ.Ⴁ
+ڰᠡ。ⴁ; ڰᠡ.ⴁ; [B2, B3]; xn--jkb440g.xn--skj; ; ; # ڰᠡ.ⴁ
+xn--jkb440g.xn--skj; ڰᠡ.ⴁ; [B2, B3]; xn--jkb440g.xn--skj; ; ; # ڰᠡ.ⴁ
+xn--jkb440g.xn--8md; ڰᠡ.Ⴁ; [B2, B3, V6]; xn--jkb440g.xn--8md; ; ; # ڰᠡ.Ⴁ
+ڰᠡ。ⴁ; ڰᠡ.ⴁ; [B2, B3]; xn--jkb440g.xn--skj; ; ; # ڰᠡ.ⴁ
+⃞Ⴊڻς。-; ⃞Ⴊڻς.-; [B1, P1, V3, V5, V6]; xn--3xa53m7zmb0q.-; ; xn--4xa33m7zmb0q.-; # ⃞Ⴊڻς.-
+⃞Ⴊڻς。-; ⃞Ⴊڻς.-; [B1, P1, V3, V5, V6]; xn--3xa53m7zmb0q.-; ; xn--4xa33m7zmb0q.-; # ⃞Ⴊڻς.-
+⃞ⴊڻς。-; ⃞ⴊڻς.-; [B1, V3, V5]; xn--3xa53mr38aeel.-; ; xn--4xa33mr38aeel.-; # ⃞ⴊڻς.-
+⃞ႪڻΣ。-; ⃞Ⴊڻσ.-; [B1, P1, V3, V5, V6]; xn--4xa33m7zmb0q.-; ; ; # ⃞Ⴊڻσ.-
+⃞ⴊڻσ。-; ⃞ⴊڻσ.-; [B1, V3, V5]; xn--4xa33mr38aeel.-; ; ; # ⃞ⴊڻσ.-
+⃞Ⴊڻσ。-; ⃞Ⴊڻσ.-; [B1, P1, V3, V5, V6]; xn--4xa33m7zmb0q.-; ; ; # ⃞Ⴊڻσ.-
+xn--4xa33m7zmb0q.-; ⃞Ⴊڻσ.-; [B1, V3, V5, V6]; xn--4xa33m7zmb0q.-; ; ; # ⃞Ⴊڻσ.-
+xn--4xa33mr38aeel.-; ⃞ⴊڻσ.-; [B1, V3, V5]; xn--4xa33mr38aeel.-; ; ; # ⃞ⴊڻσ.-
+xn--3xa53mr38aeel.-; ⃞ⴊڻς.-; [B1, V3, V5]; xn--3xa53mr38aeel.-; ; ; # ⃞ⴊڻς.-
+xn--3xa53m7zmb0q.-; ⃞Ⴊڻς.-; [B1, V3, V5, V6]; xn--3xa53m7zmb0q.-; ; ; # ⃞Ⴊڻς.-
+⃞ⴊڻς。-; ⃞ⴊڻς.-; [B1, V3, V5]; xn--3xa53mr38aeel.-; ; xn--4xa33mr38aeel.-; # ⃞ⴊڻς.-
+⃞ႪڻΣ。-; ⃞Ⴊڻσ.-; [B1, P1, V3, V5, V6]; xn--4xa33m7zmb0q.-; ; ; # ⃞Ⴊڻσ.-
+⃞ⴊڻσ。-; ⃞ⴊڻσ.-; [B1, V3, V5]; xn--4xa33mr38aeel.-; ; ; # ⃞ⴊڻσ.-
+⃞Ⴊڻσ。-; ⃞Ⴊڻσ.-; [B1, P1, V3, V5, V6]; xn--4xa33m7zmb0q.-; ; ; # ⃞Ⴊڻσ.-
+Ⴍ.񍇦‌; Ⴍ.񍇦‌; [C1, P1, V6]; xn--lnd.xn--0ug56448b; ; xn--lnd.xn--p01x; [P1, V6] # Ⴍ.
+Ⴍ.񍇦‌; ; [C1, P1, V6]; xn--lnd.xn--0ug56448b; ; xn--lnd.xn--p01x; [P1, V6] # Ⴍ.
+ⴍ.񍇦‌; ; [C1, P1, V6]; xn--4kj.xn--0ug56448b; ; xn--4kj.xn--p01x; [P1, V6] # ⴍ.
+xn--4kj.xn--p01x; ⴍ.񍇦; [V6]; xn--4kj.xn--p01x; ; ; # ⴍ.
+xn--4kj.xn--0ug56448b; ⴍ.񍇦‌; [C1, V6]; xn--4kj.xn--0ug56448b; ; ; # ⴍ.
+xn--lnd.xn--p01x; Ⴍ.񍇦; [V6]; xn--lnd.xn--p01x; ; ; # Ⴍ.
+xn--lnd.xn--0ug56448b; Ⴍ.񍇦‌; [C1, V6]; xn--lnd.xn--0ug56448b; ; ; # Ⴍ.
+ⴍ.񍇦‌; ⴍ.񍇦‌; [C1, P1, V6]; xn--4kj.xn--0ug56448b; ; xn--4kj.xn--p01x; [P1, V6] # ⴍ.
+򉟂󠵣.𐫫᩠󴺖᭄; ; [B2, B3, B6, P1, V6]; xn--9u37blu98h.xn--jof13bt568cork1j; ; ; # .𐫫᩠᭄
+xn--9u37blu98h.xn--jof13bt568cork1j; 򉟂󠵣.𐫫᩠󴺖᭄; [B2, B3, B6, V6]; xn--9u37blu98h.xn--jof13bt568cork1j; ; ; # .𐫫᩠᭄
+≯❊ᠯ。𐹱⺨; ≯❊ᠯ.𐹱⺨; [B1, P1, V6]; xn--i7e163ct2d.xn--vwj7372e; ; ; # ≯❊ᠯ.𐹱⺨
+≯❊ᠯ。𐹱⺨; ≯❊ᠯ.𐹱⺨; [B1, P1, V6]; xn--i7e163ct2d.xn--vwj7372e; ; ; # ≯❊ᠯ.𐹱⺨
+≯❊ᠯ。𐹱⺨; ≯❊ᠯ.𐹱⺨; [B1, P1, V6]; xn--i7e163ct2d.xn--vwj7372e; ; ; # ≯❊ᠯ.𐹱⺨
+≯❊ᠯ。𐹱⺨; ≯❊ᠯ.𐹱⺨; [B1, P1, V6]; xn--i7e163ct2d.xn--vwj7372e; ; ; # ≯❊ᠯ.𐹱⺨
+xn--i7e163ct2d.xn--vwj7372e; ≯❊ᠯ.𐹱⺨; [B1, V6]; xn--i7e163ct2d.xn--vwj7372e; ; ; # ≯❊ᠯ.𐹱⺨
+􁕜𐹧𞭁𐹩。Ⴈ𐫮Ⴏ; 􁕜𐹧𞭁𐹩.Ⴈ𐫮Ⴏ; [B5, B6, P1, V6]; xn--fo0de1270ope54j.xn--gndo2033q; ; ; # 𐹧𐹩.Ⴈ𐫮Ⴏ
+􁕜𐹧𞭁𐹩。ⴈ𐫮ⴏ; 􁕜𐹧𞭁𐹩.ⴈ𐫮ⴏ; [B5, B6, P1, V6]; xn--fo0de1270ope54j.xn--zkjo0151o; ; ; # 𐹧𐹩.ⴈ𐫮ⴏ
+xn--fo0de1270ope54j.xn--zkjo0151o; 􁕜𐹧𞭁𐹩.ⴈ𐫮ⴏ; [B5, B6, V6]; xn--fo0de1270ope54j.xn--zkjo0151o; ; ; # 𐹧𐹩.ⴈ𐫮ⴏ
+xn--fo0de1270ope54j.xn--gndo2033q; 􁕜𐹧𞭁𐹩.Ⴈ𐫮Ⴏ; [B5, B6, V6]; xn--fo0de1270ope54j.xn--gndo2033q; ; ; # 𐹧𐹩.Ⴈ𐫮Ⴏ
+𞠂。ꤦ; 𞠂.ꤦ; [B1, B3, B6, V5]; xn--145h.xn--ti9a; ; ; # 𞠂.ꤦ
+xn--145h.xn--ti9a; 𞠂.ꤦ; [B1, B3, B6, V5]; xn--145h.xn--ti9a; ; ; # 𞠂.ꤦ
+𝟔𐹫.့ܳ9ꡇ; 6𐹫.့ܳ9ꡇ; [B1, V5]; xn--6-t26i.xn--9-91c730e8u8n; ; ; # 6𐹫.့ܳ9ꡇ
+𝟔𐹫.့ܳ9ꡇ; 6𐹫.့ܳ9ꡇ; [B1, V5]; xn--6-t26i.xn--9-91c730e8u8n; ; ; # 6𐹫.့ܳ9ꡇ
+6𐹫.့ܳ9ꡇ; ; [B1, V5]; xn--6-t26i.xn--9-91c730e8u8n; ; ; # 6𐹫.့ܳ9ꡇ
+xn--6-t26i.xn--9-91c730e8u8n; 6𐹫.့ܳ9ꡇ; [B1, V5]; xn--6-t26i.xn--9-91c730e8u8n; ; ; # 6𐹫.့ܳ9ꡇ
+ܤ؃𞲶.ۘ; ܤ؃𞲶.ۘ; [B1, B3, B6, P1, V5, V6]; xn--lfb19ct414i.xn--olb; ; ; # ܤ.ۘ
+ܤ؃𞲶.ۘ; ; [B1, B3, B6, P1, V5, V6]; xn--lfb19ct414i.xn--olb; ; ; # ܤ.ۘ
+xn--lfb19ct414i.xn--olb; ܤ؃𞲶.ۘ; [B1, B3, B6, V5, V6]; xn--lfb19ct414i.xn--olb; ; ; # ܤ.ۘ
+✆񱔩ꡋ.ز‍𞣴; ✆񱔩ꡋ.ز‍𞣴; [B1, C2, P1, V6]; xn--1biv525bcix0d.xn--xgb253k0m73a; ; xn--1biv525bcix0d.xn--xgb6828v; [B1, P1, V6] # ✆ꡋ.ز
+✆񱔩ꡋ.ز‍𞣴; ; [B1, C2, P1, V6]; xn--1biv525bcix0d.xn--xgb253k0m73a; ; xn--1biv525bcix0d.xn--xgb6828v; [B1, P1, V6] # ✆ꡋ.ز
+xn--1biv525bcix0d.xn--xgb6828v; ✆񱔩ꡋ.ز𞣴; [B1, V6]; xn--1biv525bcix0d.xn--xgb6828v; ; ; # ✆ꡋ.ز
+xn--1biv525bcix0d.xn--xgb253k0m73a; ✆񱔩ꡋ.ز‍𞣴; [B1, C2, V6]; xn--1biv525bcix0d.xn--xgb253k0m73a; ; ; # ✆ꡋ.ز
+ࡅ񃾰𞸍-.≠򃁟𑋪; ࡅ񃾰ن-.≠򃁟𑋪; [B1, B2, B3, P1, V3, V6]; xn----qoc64my971s.xn--1ch7585g76o3c; ; ; # ࡅن-.≠𑋪
+ࡅ񃾰𞸍-.≠򃁟𑋪; ࡅ񃾰ن-.≠򃁟𑋪; [B1, B2, B3, P1, V3, V6]; xn----qoc64my971s.xn--1ch7585g76o3c; ; ; # ࡅن-.≠𑋪
+ࡅ񃾰ن-.≠򃁟𑋪; ; [B1, B2, B3, P1, V3, V6]; xn----qoc64my971s.xn--1ch7585g76o3c; ; ; # ࡅن-.≠𑋪
+ࡅ񃾰ن-.≠򃁟𑋪; ࡅ񃾰ن-.≠򃁟𑋪; [B1, B2, B3, P1, V3, V6]; xn----qoc64my971s.xn--1ch7585g76o3c; ; ; # ࡅن-.≠𑋪
+xn----qoc64my971s.xn--1ch7585g76o3c; ࡅ񃾰ن-.≠򃁟𑋪; [B1, B2, B3, V3, V6]; xn----qoc64my971s.xn--1ch7585g76o3c; ; ; # ࡅن-.≠𑋪
+𝟛.笠; 3.笠; ; 3.xn--6vz; ; ; # 3.笠
+𝟛.笠; 3.笠; ; 3.xn--6vz; ; ; # 3.笠
+3.笠; ; ; 3.xn--6vz; ; ; # 3.笠
+3.xn--6vz; 3.笠; ; 3.xn--6vz; ; ; # 3.笠
+-‍.Ⴞ𐋷; ; [C2, P1, V3, V6]; xn----ugn.xn--2nd2315j; ; -.xn--2nd2315j; [P1, V3, V6] # -.Ⴞ𐋷
+-‍.ⴞ𐋷; ; [C2, V3]; xn----ugn.xn--mlj8559d; ; -.xn--mlj8559d; [V3] # -.ⴞ𐋷
+-.xn--mlj8559d; -.ⴞ𐋷; [V3]; -.xn--mlj8559d; ; ; # -.ⴞ𐋷
+xn----ugn.xn--mlj8559d; -‍.ⴞ𐋷; [C2, V3]; xn----ugn.xn--mlj8559d; ; ; # -.ⴞ𐋷
+-.xn--2nd2315j; -.Ⴞ𐋷; [V3, V6]; -.xn--2nd2315j; ; ; # -.Ⴞ𐋷
+xn----ugn.xn--2nd2315j; -‍.Ⴞ𐋷; [C2, V3, V6]; xn----ugn.xn--2nd2315j; ; ; # -.Ⴞ𐋷
+‍ςßܱ.்; ‍ςßܱ.்; [C2, V5]; xn--zca19ln1di19a.xn--xmc; ; xn--ss-ubc826a.xn--xmc; [V5] # ςßܱ.்
+‍ςßܱ.்; ; [C2, V5]; xn--zca19ln1di19a.xn--xmc; ; xn--ss-ubc826a.xn--xmc; [V5] # ςßܱ.்
+‍ΣSSܱ.்; ‍σssܱ.்; [C2, V5]; xn--ss-ubc826ab34b.xn--xmc; ; xn--ss-ubc826a.xn--xmc; [V5] # σssܱ.்
+‍σssܱ.்; ; [C2, V5]; xn--ss-ubc826ab34b.xn--xmc; ; xn--ss-ubc826a.xn--xmc; [V5] # σssܱ.்
+‍Σssܱ.்; ‍σssܱ.்; [C2, V5]; xn--ss-ubc826ab34b.xn--xmc; ; xn--ss-ubc826a.xn--xmc; [V5] # σssܱ.்
+xn--ss-ubc826a.xn--xmc; σssܱ.்; [V5]; xn--ss-ubc826a.xn--xmc; ; ; # σssܱ.்
+xn--ss-ubc826ab34b.xn--xmc; ‍σssܱ.்; [C2, V5]; xn--ss-ubc826ab34b.xn--xmc; ; ; # σssܱ.்
+‍Σßܱ.்; ‍σßܱ.்; [C2, V5]; xn--zca39lk1di19a.xn--xmc; ; xn--ss-ubc826a.xn--xmc; [V5] # σßܱ.்
+‍σßܱ.்; ; [C2, V5]; xn--zca39lk1di19a.xn--xmc; ; xn--ss-ubc826a.xn--xmc; [V5] # σßܱ.்
+xn--zca39lk1di19a.xn--xmc; ‍σßܱ.்; [C2, V5]; xn--zca39lk1di19a.xn--xmc; ; ; # σßܱ.்
+xn--zca19ln1di19a.xn--xmc; ‍ςßܱ.்; [C2, V5]; xn--zca19ln1di19a.xn--xmc; ; ; # ςßܱ.்
+‍ΣSSܱ.்; ‍σssܱ.்; [C2, V5]; xn--ss-ubc826ab34b.xn--xmc; ; xn--ss-ubc826a.xn--xmc; [V5] # σssܱ.்
+‍σssܱ.்; ‍σssܱ.்; [C2, V5]; xn--ss-ubc826ab34b.xn--xmc; ; xn--ss-ubc826a.xn--xmc; [V5] # σssܱ.்
+‍Σssܱ.்; ‍σssܱ.்; [C2, V5]; xn--ss-ubc826ab34b.xn--xmc; ; xn--ss-ubc826a.xn--xmc; [V5] # σssܱ.்
+‍Σßܱ.்; ‍σßܱ.்; [C2, V5]; xn--zca39lk1di19a.xn--xmc; ; xn--ss-ubc826a.xn--xmc; [V5] # σßܱ.்
+‍σßܱ.்; ‍σßܱ.்; [C2, V5]; xn--zca39lk1di19a.xn--xmc; ; xn--ss-ubc826a.xn--xmc; [V5] # σßܱ.்
+≠.‍; ≠.‍; [C2, P1, V6]; xn--1ch.xn--1ug; ; xn--1ch.; [P1, V6] # ≠.
+≠.‍; ≠.‍; [C2, P1, V6]; xn--1ch.xn--1ug; ; xn--1ch.; [P1, V6] # ≠.
+≠.‍; ; [C2, P1, V6]; xn--1ch.xn--1ug; ; xn--1ch.; [P1, V6] # ≠.
+≠.‍; ≠.‍; [C2, P1, V6]; xn--1ch.xn--1ug; ; xn--1ch.; [P1, V6] # ≠.
+xn--1ch.; ≠.; [V6]; xn--1ch.; ; ; # ≠.
+xn--1ch.xn--1ug; ≠.‍; [C2, V6]; xn--1ch.xn--1ug; ; ; # ≠.
+ﰁ。ಁᠼ▗򒁋; ئح.ಁᠼ▗򒁋; [B1, P1, V5, V6]; xn--lgbo.xn--2rc021dcxkrx55t; ; ; # ئح.ಁᠼ▗
+ئح。ಁᠼ▗򒁋; ئح.ಁᠼ▗򒁋; [B1, P1, V5, V6]; xn--lgbo.xn--2rc021dcxkrx55t; ; ; # ئح.ಁᠼ▗
+ئح。ಁᠼ▗򒁋; ئح.ಁᠼ▗򒁋; [B1, P1, V5, V6]; xn--lgbo.xn--2rc021dcxkrx55t; ; ; # ئح.ಁᠼ▗
+xn--lgbo.xn--2rc021dcxkrx55t; ئح.ಁᠼ▗򒁋; [B1, V5, V6]; xn--lgbo.xn--2rc021dcxkrx55t; ; ; # ئح.ಁᠼ▗
+󧋵্ς.ς𐨿; 󧋵্ς.ς𐨿; [P1, V6]; xn--3xa702av8297a.xn--3xa8055k; ; xn--4xa502av8297a.xn--4xa6055k; # ্ς.ς𐨿
+󧋵্ς.ς𐨿; ; [P1, V6]; xn--3xa702av8297a.xn--3xa8055k; ; xn--4xa502av8297a.xn--4xa6055k; # ্ς.ς𐨿
+󧋵্Σ.Σ𐨿; 󧋵্σ.σ𐨿; [P1, V6]; xn--4xa502av8297a.xn--4xa6055k; ; ; # ্σ.σ𐨿
+󧋵্σ.ς𐨿; ; [P1, V6]; xn--4xa502av8297a.xn--3xa8055k; ; xn--4xa502av8297a.xn--4xa6055k; # ্σ.ς𐨿
+󧋵্σ.σ𐨿; ; [P1, V6]; xn--4xa502av8297a.xn--4xa6055k; ; ; # ্σ.σ𐨿
+󧋵্Σ.σ𐨿; 󧋵্σ.σ𐨿; [P1, V6]; xn--4xa502av8297a.xn--4xa6055k; ; ; # ্σ.σ𐨿
+xn--4xa502av8297a.xn--4xa6055k; 󧋵্σ.σ𐨿; [V6]; xn--4xa502av8297a.xn--4xa6055k; ; ; # ্σ.σ𐨿
+󧋵্Σ.ς𐨿; 󧋵্σ.ς𐨿; [P1, V6]; xn--4xa502av8297a.xn--3xa8055k; ; xn--4xa502av8297a.xn--4xa6055k; # ্σ.ς𐨿
+xn--4xa502av8297a.xn--3xa8055k; 󧋵্σ.ς𐨿; [V6]; xn--4xa502av8297a.xn--3xa8055k; ; ; # ্σ.ς𐨿
+xn--3xa702av8297a.xn--3xa8055k; 󧋵্ς.ς𐨿; [V6]; xn--3xa702av8297a.xn--3xa8055k; ; ; # ্ς.ς𐨿
+󧋵্Σ.Σ𐨿; 󧋵্σ.σ𐨿; [P1, V6]; xn--4xa502av8297a.xn--4xa6055k; ; ; # ্σ.σ𐨿
+󧋵্σ.ς𐨿; 󧋵্σ.ς𐨿; [P1, V6]; xn--4xa502av8297a.xn--3xa8055k; ; xn--4xa502av8297a.xn--4xa6055k; # ্σ.ς𐨿
+󧋵্σ.σ𐨿; 󧋵্σ.σ𐨿; [P1, V6]; xn--4xa502av8297a.xn--4xa6055k; ; ; # ্σ.σ𐨿
+󧋵্Σ.σ𐨿; 󧋵্σ.σ𐨿; [P1, V6]; xn--4xa502av8297a.xn--4xa6055k; ; ; # ্σ.σ𐨿
+󧋵্Σ.ς𐨿; 󧋵্σ.ς𐨿; [P1, V6]; xn--4xa502av8297a.xn--3xa8055k; ; xn--4xa502av8297a.xn--4xa6055k; # ্σ.ς𐨿
+𐫓ߘ牅ࣸ。𞦤ᨗ򱍰Ⴙ; 𐫓ߘ牅ࣸ.𞦤ᨗ򱍰Ⴙ; [B2, B3, P1, V6]; xn--zsb09cu46vjs6f.xn--xnd909bv540bm5k9d; ; ; # 𐫓ߘ牅ࣸ.ᨗႹ
+𐫓ߘ牅ࣸ。𞦤ᨗ򱍰Ⴙ; 𐫓ߘ牅ࣸ.𞦤ᨗ򱍰Ⴙ; [B2, B3, P1, V6]; xn--zsb09cu46vjs6f.xn--xnd909bv540bm5k9d; ; ; # 𐫓ߘ牅ࣸ.ᨗႹ
+𐫓ߘ牅ࣸ。𞦤ᨗ򱍰ⴙ; 𐫓ߘ牅ࣸ.𞦤ᨗ򱍰ⴙ; [B2, B3, P1, V6]; xn--zsb09cu46vjs6f.xn--gmf469fr883am5r1e; ; ; # 𐫓ߘ牅ࣸ.ᨗⴙ
+xn--zsb09cu46vjs6f.xn--gmf469fr883am5r1e; 𐫓ߘ牅ࣸ.𞦤ᨗ򱍰ⴙ; [B2, B3, V6]; xn--zsb09cu46vjs6f.xn--gmf469fr883am5r1e; ; ; # 𐫓ߘ牅ࣸ.ᨗⴙ
+xn--zsb09cu46vjs6f.xn--xnd909bv540bm5k9d; 𐫓ߘ牅ࣸ.𞦤ᨗ򱍰Ⴙ; [B2, B3, V6]; xn--zsb09cu46vjs6f.xn--xnd909bv540bm5k9d; ; ; # 𐫓ߘ牅ࣸ.ᨗႹ
+𐫓ߘ牅ࣸ。𞦤ᨗ򱍰ⴙ; 𐫓ߘ牅ࣸ.𞦤ᨗ򱍰ⴙ; [B2, B3, P1, V6]; xn--zsb09cu46vjs6f.xn--gmf469fr883am5r1e; ; ; # 𐫓ߘ牅ࣸ.ᨗⴙ
+񣤒。륧; 񣤒.륧; [P1, V6]; xn--s264a.xn--pw2b; ; ; # .륧
+񣤒。륧; 񣤒.륧; [P1, V6]; xn--s264a.xn--pw2b; ; ; # .륧
+񣤒。륧; 񣤒.륧; [P1, V6]; xn--s264a.xn--pw2b; ; ; # .륧
+񣤒。륧; 񣤒.륧; [P1, V6]; xn--s264a.xn--pw2b; ; ; # .륧
+xn--s264a.xn--pw2b; 񣤒.륧; [V6]; xn--s264a.xn--pw2b; ; ; # .륧
+𐹷‍。󉵢; 𐹷‍.󉵢; [B1, C2, P1, V6]; xn--1ugx205g.xn--8088d; ; xn--vo0d.xn--8088d; [B1, P1, V6] # 𐹷.
+xn--vo0d.xn--8088d; 𐹷.󉵢; [B1, V6]; xn--vo0d.xn--8088d; ; ; # 𐹷.
+xn--1ugx205g.xn--8088d; 𐹷‍.󉵢; [B1, C2, V6]; xn--1ugx205g.xn--8088d; ; ; # 𐹷.
+Ⴘۂ𑲭。-; Ⴘۂ𑲭.-; [B1, B5, B6, P1, V3, V6]; xn--1kb312c139t.-; ; ; # Ⴘۂ𑲭.-
+Ⴘۂ𑲭。-; Ⴘۂ𑲭.-; [B1, B5, B6, P1, V3, V6]; xn--1kb312c139t.-; ; ; # Ⴘۂ𑲭.-
+Ⴘۂ𑲭。-; Ⴘۂ𑲭.-; [B1, B5, B6, P1, V3, V6]; xn--1kb312c139t.-; ; ; # Ⴘۂ𑲭.-
+Ⴘۂ𑲭。-; Ⴘۂ𑲭.-; [B1, B5, B6, P1, V3, V6]; xn--1kb312c139t.-; ; ; # Ⴘۂ𑲭.-
+ⴘۂ𑲭。-; ⴘۂ𑲭.-; [B1, B5, B6, V3]; xn--1kb147qfk3n.-; ; ; # ⴘۂ𑲭.-
+ⴘۂ𑲭。-; ⴘۂ𑲭.-; [B1, B5, B6, V3]; xn--1kb147qfk3n.-; ; ; # ⴘۂ𑲭.-
+xn--1kb147qfk3n.-; ⴘۂ𑲭.-; [B1, B5, B6, V3]; xn--1kb147qfk3n.-; ; ; # ⴘۂ𑲭.-
+xn--1kb312c139t.-; Ⴘۂ𑲭.-; [B1, B5, B6, V3, V6]; xn--1kb312c139t.-; ; ; # Ⴘۂ𑲭.-
+ⴘۂ𑲭。-; ⴘۂ𑲭.-; [B1, B5, B6, V3]; xn--1kb147qfk3n.-; ; ; # ⴘۂ𑲭.-
+ⴘۂ𑲭。-; ⴘۂ𑲭.-; [B1, B5, B6, V3]; xn--1kb147qfk3n.-; ; ; # ⴘۂ𑲭.-
+꠆ٻ₆ᡐ。🛇ﳝ; ꠆ٻ6ᡐ.🛇يم; [B1, V5]; xn--6-rrc018krt9k.xn--hhbj61429a; ; ; # ꠆ٻ6ᡐ.🛇يم
+꠆ٻ6ᡐ。🛇يم; ꠆ٻ6ᡐ.🛇يم; [B1, V5]; xn--6-rrc018krt9k.xn--hhbj61429a; ; ; # ꠆ٻ6ᡐ.🛇يم
+xn--6-rrc018krt9k.xn--hhbj61429a; ꠆ٻ6ᡐ.🛇يم; [B1, V5]; xn--6-rrc018krt9k.xn--hhbj61429a; ; ; # ꠆ٻ6ᡐ.🛇يم
+򸍂.㇄ᡟ𐫂آ; ; [B1, P1, V6]; xn--p292d.xn--hgb154ghrsvm2r; ; ; # .㇄ᡟ𐫂آ
+򸍂.㇄ᡟ𐫂آ; 򸍂.㇄ᡟ𐫂آ; [B1, P1, V6]; xn--p292d.xn--hgb154ghrsvm2r; ; ; # .㇄ᡟ𐫂آ
+xn--p292d.xn--hgb154ghrsvm2r; 򸍂.㇄ᡟ𐫂آ; [B1, V6]; xn--p292d.xn--hgb154ghrsvm2r; ; ; # .㇄ᡟ𐫂آ
+ߟ򵚌。-ߩ; ߟ򵚌.-ߩ; [B1, B2, B3, P1, V3, V6]; xn--6sb88139l.xn----pdd; ; ; # ߟ.-ߩ
+xn--6sb88139l.xn----pdd; ߟ򵚌.-ߩ; [B1, B2, B3, V3, V6]; xn--6sb88139l.xn----pdd; ; ; # ߟ.-ߩ
+ςك⾑.‌ᢟ‌⒈; ςك襾.‌ᢟ‌⒈; [B1, B5, C1, P1, V6]; xn--3xa69jux8r.xn--pbf519aba607b; ; xn--4xa49jux8r.xn--pbf212d; [B5, P1, V6] # ςك襾.ᢟ⒈
+ςك襾.‌ᢟ‌1.; ; [B1, B5, C1]; xn--3xa69jux8r.xn--1-4ck691bba.; ; xn--4xa49jux8r.xn--1-4ck.; [B5] # ςك襾.ᢟ1.
+Σك襾.‌ᢟ‌1.; σك襾.‌ᢟ‌1.; [B1, B5, C1]; xn--4xa49jux8r.xn--1-4ck691bba.; ; xn--4xa49jux8r.xn--1-4ck.; [B5] # σك襾.ᢟ1.
+σك襾.‌ᢟ‌1.; ; [B1, B5, C1]; xn--4xa49jux8r.xn--1-4ck691bba.; ; xn--4xa49jux8r.xn--1-4ck.; [B5] # σك襾.ᢟ1.
+xn--4xa49jux8r.xn--1-4ck.; σك襾.ᢟ1.; [B5]; xn--4xa49jux8r.xn--1-4ck.; ; ; # σك襾.ᢟ1.
+xn--4xa49jux8r.xn--1-4ck691bba.; σك襾.‌ᢟ‌1.; [B1, B5, C1]; xn--4xa49jux8r.xn--1-4ck691bba.; ; ; # σك襾.ᢟ1.
+xn--3xa69jux8r.xn--1-4ck691bba.; ςك襾.‌ᢟ‌1.; [B1, B5, C1]; xn--3xa69jux8r.xn--1-4ck691bba.; ; ; # ςك襾.ᢟ1.
+Σك⾑.‌ᢟ‌⒈; σك襾.‌ᢟ‌⒈; [B1, B5, C1, P1, V6]; xn--4xa49jux8r.xn--pbf519aba607b; ; xn--4xa49jux8r.xn--pbf212d; [B5, P1, V6] # σك襾.ᢟ⒈
+σك⾑.‌ᢟ‌⒈; σك襾.‌ᢟ‌⒈; [B1, B5, C1, P1, V6]; xn--4xa49jux8r.xn--pbf519aba607b; ; xn--4xa49jux8r.xn--pbf212d; [B5, P1, V6] # σك襾.ᢟ⒈
+xn--4xa49jux8r.xn--pbf212d; σك襾.ᢟ⒈; [B5, V6]; xn--4xa49jux8r.xn--pbf212d; ; ; # σك襾.ᢟ⒈
+xn--4xa49jux8r.xn--pbf519aba607b; σك襾.‌ᢟ‌⒈; [B1, B5, C1, V6]; xn--4xa49jux8r.xn--pbf519aba607b; ; ; # σك襾.ᢟ⒈
+xn--3xa69jux8r.xn--pbf519aba607b; ςك襾.‌ᢟ‌⒈; [B1, B5, C1, V6]; xn--3xa69jux8r.xn--pbf519aba607b; ; ; # ςك襾.ᢟ⒈
+ᡆ𑓝.𞵆; ᡆ𑓝.𞵆; [P1, V6]; xn--57e0440k.xn--k86h; ; ; # ᡆ.
+ᡆ𑓝.𞵆; ; [P1, V6]; xn--57e0440k.xn--k86h; ; ; # ᡆ.
+xn--57e0440k.xn--k86h; ᡆ𑓝.𞵆; [V6]; xn--57e0440k.xn--k86h; ; ; # ᡆ.
+੍𦍓ᷮ。‌ࢽ񝹲; ੍𦍓ᷮ.‌ࢽ񝹲; [B1, C1, P1, V5, V6]; xn--ybc461hph93b.xn--jzb740j1y45h; ; xn--ybc461hph93b.xn--jzb29857e; [B1, B2, B3, P1, V5, V6] # ੍𦍓ᷮ.ࢽ
+੍𦍓ᷮ。‌ࢽ񝹲; ੍𦍓ᷮ.‌ࢽ񝹲; [B1, C1, P1, V5, V6]; xn--ybc461hph93b.xn--jzb740j1y45h; ; xn--ybc461hph93b.xn--jzb29857e; [B1, B2, B3, P1, V5, V6] # ੍𦍓ᷮ.ࢽ
+xn--ybc461hph93b.xn--jzb29857e; ੍𦍓ᷮ.ࢽ񝹲; [B1, B2, B3, V5, V6]; xn--ybc461hph93b.xn--jzb29857e; ; ; # ੍𦍓ᷮ.ࢽ
+xn--ybc461hph93b.xn--jzb740j1y45h; ੍𦍓ᷮ.‌ࢽ񝹲; [B1, C1, V5, V6]; xn--ybc461hph93b.xn--jzb740j1y45h; ; ; # ੍𦍓ᷮ.ࢽ
+خ݈񅪪-.‌먿; خ݈񅪪-.‌먿; [B1, B2, B3, C1, P1, V3, V6]; xn----dnc06f42153a.xn--0ug1581d; ; xn----dnc06f42153a.xn--v22b; [B2, B3, P1, V3, V6] # خ݈-.먿
+خ݈񅪪-.‌먿; خ݈񅪪-.‌먿; [B1, B2, B3, C1, P1, V3, V6]; xn----dnc06f42153a.xn--0ug1581d; ; xn----dnc06f42153a.xn--v22b; [B2, B3, P1, V3, V6] # خ݈-.먿
+خ݈񅪪-.‌먿; ; [B1, B2, B3, C1, P1, V3, V6]; xn----dnc06f42153a.xn--0ug1581d; ; xn----dnc06f42153a.xn--v22b; [B2, B3, P1, V3, V6] # خ݈-.먿
+خ݈񅪪-.‌먿; خ݈񅪪-.‌먿; [B1, B2, B3, C1, P1, V3, V6]; xn----dnc06f42153a.xn--0ug1581d; ; xn----dnc06f42153a.xn--v22b; [B2, B3, P1, V3, V6] # خ݈-.먿
+xn----dnc06f42153a.xn--v22b; خ݈񅪪-.먿; [B2, B3, V3, V6]; xn----dnc06f42153a.xn--v22b; ; ; # خ݈-.먿
+xn----dnc06f42153a.xn--0ug1581d; خ݈񅪪-.‌먿; [B1, B2, B3, C1, V3, V6]; xn----dnc06f42153a.xn--0ug1581d; ; ; # خ݈-.먿
+􋿦。ᠽ; 􋿦.ᠽ; [P1, V6]; xn--j890g.xn--w7e; ; ; # .ᠽ
+􋿦。ᠽ; 􋿦.ᠽ; [P1, V6]; xn--j890g.xn--w7e; ; ; # .ᠽ
+xn--j890g.xn--w7e; 􋿦.ᠽ; [V6]; xn--j890g.xn--w7e; ; ; # .ᠽ
+嬃𝍌.‍ୄ; 嬃𝍌.‍ୄ; [C2]; xn--b6s0078f.xn--0ic557h; ; xn--b6s0078f.xn--0ic; [V5] # 嬃𝍌.ୄ
+嬃𝍌.‍ୄ; ; [C2]; xn--b6s0078f.xn--0ic557h; ; xn--b6s0078f.xn--0ic; [V5] # 嬃𝍌.ୄ
+xn--b6s0078f.xn--0ic; 嬃𝍌.ୄ; [V5]; xn--b6s0078f.xn--0ic; ; ; # 嬃𝍌.ୄ
+xn--b6s0078f.xn--0ic557h; 嬃𝍌.‍ୄ; [C2]; xn--b6s0078f.xn--0ic557h; ; ; # 嬃𝍌.ୄ
+؂𝌪≯.𚋲򵁨; ؂𝌪≯.𚋲򵁨; [B1, P1, V6]; xn--kfb866llx01a.xn--wp1gm3570b; ; ; # 𝌪≯.
+؂𝌪≯.𚋲򵁨; ؂𝌪≯.𚋲򵁨; [B1, P1, V6]; xn--kfb866llx01a.xn--wp1gm3570b; ; ; # 𝌪≯.
+؂𝌪≯.𚋲򵁨; ; [B1, P1, V6]; xn--kfb866llx01a.xn--wp1gm3570b; ; ; # 𝌪≯.
+؂𝌪≯.𚋲򵁨; ؂𝌪≯.𚋲򵁨; [B1, P1, V6]; xn--kfb866llx01a.xn--wp1gm3570b; ; ; # 𝌪≯.
+xn--kfb866llx01a.xn--wp1gm3570b; ؂𝌪≯.𚋲򵁨; [B1, V6]; xn--kfb866llx01a.xn--wp1gm3570b; ; ; # 𝌪≯.
+򫾥ࢷ៌꧀.𞼠; ; [B5, P1, V6]; xn--dzb638ewm4i1iy1h.xn--3m7h; ; ; # ࢷ៌꧀.
+xn--dzb638ewm4i1iy1h.xn--3m7h; 򫾥ࢷ៌꧀.𞼠; [B5, V6]; xn--dzb638ewm4i1iy1h.xn--3m7h; ; ; # ࢷ៌꧀.
+‌.񟛤; ; [C1, P1, V6]; xn--0ug.xn--q823a; ; .xn--q823a; [P1, V6, A4_2] # .
+.xn--q823a; .񟛤; [V6, X4_2]; .xn--q823a; [V6, A4_2]; ; # .
+xn--0ug.xn--q823a; ‌.񟛤; [C1, V6]; xn--0ug.xn--q823a; ; ; # .
+򺛕Ⴃ䠅.𐸑; 򺛕Ⴃ䠅.𐸑; [P1, V6]; xn--bnd074zr557n.xn--yl0d; ; ; # Ⴃ䠅.
+򺛕Ⴃ䠅.𐸑; ; [P1, V6]; xn--bnd074zr557n.xn--yl0d; ; ; # Ⴃ䠅.
+򺛕ⴃ䠅.𐸑; ; [P1, V6]; xn--ukju77frl47r.xn--yl0d; ; ; # ⴃ䠅.
+xn--ukju77frl47r.xn--yl0d; 򺛕ⴃ䠅.𐸑; [V6]; xn--ukju77frl47r.xn--yl0d; ; ; # ⴃ䠅.
+xn--bnd074zr557n.xn--yl0d; 򺛕Ⴃ䠅.𐸑; [V6]; xn--bnd074zr557n.xn--yl0d; ; ; # Ⴃ䠅.
+򺛕ⴃ䠅.𐸑; 򺛕ⴃ䠅.𐸑; [P1, V6]; xn--ukju77frl47r.xn--yl0d; ; ; # ⴃ䠅.
+ᯱ𐹳𐹵𞤚。𝟨Ⴅ; ᯱ𐹳𐹵𞤼.6Ⴅ; [B1, P1, V5, V6]; xn--zzfy954hga2415t.xn--6-h0g; ; ; # ᯱ𐹳𐹵𞤼.6Ⴅ
+ᯱ𐹳𐹵𞤚。6Ⴅ; ᯱ𐹳𐹵𞤼.6Ⴅ; [B1, P1, V5, V6]; xn--zzfy954hga2415t.xn--6-h0g; ; ; # ᯱ𐹳𐹵𞤼.6Ⴅ
+ᯱ𐹳𐹵𞤼。6ⴅ; ᯱ𐹳𐹵𞤼.6ⴅ; [B1, V5]; xn--zzfy954hga2415t.xn--6-kvs; ; ; # ᯱ𐹳𐹵𞤼.6ⴅ
+ᯱ𐹳𐹵𞤚。6ⴅ; ᯱ𐹳𐹵𞤼.6ⴅ; [B1, V5]; xn--zzfy954hga2415t.xn--6-kvs; ; ; # ᯱ𐹳𐹵𞤼.6ⴅ
+xn--zzfy954hga2415t.xn--6-kvs; ᯱ𐹳𐹵𞤼.6ⴅ; [B1, V5]; xn--zzfy954hga2415t.xn--6-kvs; ; ; # ᯱ𐹳𐹵𞤼.6ⴅ
+xn--zzfy954hga2415t.xn--6-h0g; ᯱ𐹳𐹵𞤼.6Ⴅ; [B1, V5, V6]; xn--zzfy954hga2415t.xn--6-h0g; ; ; # ᯱ𐹳𐹵𞤼.6Ⴅ
+ᯱ𐹳𐹵𞤼。𝟨ⴅ; ᯱ𐹳𐹵𞤼.6ⴅ; [B1, V5]; xn--zzfy954hga2415t.xn--6-kvs; ; ; # ᯱ𐹳𐹵𞤼.6ⴅ
+ᯱ𐹳𐹵𞤚。𝟨ⴅ; ᯱ𐹳𐹵𞤼.6ⴅ; [B1, V5]; xn--zzfy954hga2415t.xn--6-kvs; ; ; # ᯱ𐹳𐹵𞤼.6ⴅ
+-。︒; -.︒; [P1, V3, V6]; -.xn--y86c; ; ; # -.︒
+-。。; -..; [V3, X4_2]; ; [V3, A4_2]; ; # -..
+-..; ; [V3, X4_2]; ; [V3, A4_2]; ; # -..
+-.xn--y86c; -.︒; [V3, V6]; -.xn--y86c; ; ; # -.︒
+ߛჀ。-⁵--; ߛჀ.-5--; [B1, B2, B3, P1, V2, V3, V6]; xn--2sb866b.-5--; ; ; # ߛჀ.-5--
+ߛჀ。-5--; ߛჀ.-5--; [B1, B2, B3, P1, V2, V3, V6]; xn--2sb866b.-5--; ; ; # ߛჀ.-5--
+ߛⴠ。-5--; ߛⴠ.-5--; [B1, B2, B3, V2, V3]; xn--2sb691q.-5--; ; ; # ߛⴠ.-5--
+xn--2sb691q.-5--; ߛⴠ.-5--; [B1, B2, B3, V2, V3]; xn--2sb691q.-5--; ; ; # ߛⴠ.-5--
+xn--2sb866b.-5--; ߛჀ.-5--; [B1, B2, B3, V2, V3, V6]; xn--2sb866b.-5--; ; ; # ߛჀ.-5--
+ߛⴠ。-⁵--; ߛⴠ.-5--; [B1, B2, B3, V2, V3]; xn--2sb691q.-5--; ; ; # ߛⴠ.-5--
+≯?󠑕。𐹷𐹻≯𐷒; ≯?󠑕.𐹷𐹻≯𐷒; [B1, P1, V6]; xn--?-ogo25661n.xn--hdh8283gdoaqa; ; ; # ≯?.𐹷𐹻≯
+≯?󠑕。𐹷𐹻≯𐷒; ≯?󠑕.𐹷𐹻≯𐷒; [B1, P1, V6]; xn--?-ogo25661n.xn--hdh8283gdoaqa; ; ; # ≯?.𐹷𐹻≯
+≯?󠑕。𐹷𐹻≯𐷒; ≯?󠑕.𐹷𐹻≯𐷒; [B1, P1, V6]; xn--?-ogo25661n.xn--hdh8283gdoaqa; ; ; # ≯?.𐹷𐹻≯
+≯?󠑕。𐹷𐹻≯𐷒; ≯?󠑕.𐹷𐹻≯𐷒; [B1, P1, V6]; xn--?-ogo25661n.xn--hdh8283gdoaqa; ; ; # ≯?.𐹷𐹻≯
+xn--?-ogo25661n.xn--hdh8283gdoaqa; ≯?󠑕.𐹷𐹻≯𐷒; [B1, P1, V6]; xn--?-ogo25661n.xn--hdh8283gdoaqa; ; ; # ≯?.𐹷𐹻≯
+≯?󠑕.xn--hdh8283gdoaqa; ≯?󠑕.𐹷𐹻≯𐷒; [B1, P1, V6]; xn--?-ogo25661n.xn--hdh8283gdoaqa; ; ; # ≯?.𐹷𐹻≯
+≯?󠑕.xn--hdh8283gdoaqa; ≯?󠑕.𐹷𐹻≯𐷒; [B1, P1, V6]; xn--?-ogo25661n.xn--hdh8283gdoaqa; ; ; # ≯?.𐹷𐹻≯
+≯?󠑕.XN--HDH8283GDOAQA; ≯?󠑕.𐹷𐹻≯𐷒; [B1, P1, V6]; xn--?-ogo25661n.xn--hdh8283gdoaqa; ; ; # ≯?.𐹷𐹻≯
+≯?󠑕.XN--HDH8283GDOAQA; ≯?󠑕.𐹷𐹻≯𐷒; [B1, P1, V6]; xn--?-ogo25661n.xn--hdh8283gdoaqa; ; ; # ≯?.𐹷𐹻≯
+≯?󠑕.Xn--Hdh8283gdoaqa; ≯?󠑕.𐹷𐹻≯𐷒; [B1, P1, V6]; xn--?-ogo25661n.xn--hdh8283gdoaqa; ; ; # ≯?.𐹷𐹻≯
+≯?󠑕.Xn--Hdh8283gdoaqa; ≯?󠑕.𐹷𐹻≯𐷒; [B1, P1, V6]; xn--?-ogo25661n.xn--hdh8283gdoaqa; ; ; # ≯?.𐹷𐹻≯
+㍔ࣦݼ‍。͆򁳊𝅶؄; ルーブルࣦݼ‍.͆򁳊𝅶؄; [B1, B5, B6, C2, P1, V5, V6]; xn--dqb73ec22c9kp8cb1j.xn--kua81ls548d3608b; ; xn--dqb73el09fncab4h.xn--kua81ls548d3608b; [B1, B5, B6, P1, V5, V6] # ルーブルࣦݼ.͆
+ルーブルࣦݼ‍。͆򁳊𝅶؄; ルーブルࣦݼ‍.͆򁳊𝅶؄; [B1, B5, B6, C2, P1, V5, V6]; xn--dqb73ec22c9kp8cb1j.xn--kua81ls548d3608b; ; xn--dqb73el09fncab4h.xn--kua81ls548d3608b; [B1, B5, B6, P1, V5, V6] # ルーブルࣦݼ.͆
+ルーブルࣦݼ‍。͆򁳊𝅶؄; ルーブルࣦݼ‍.͆򁳊𝅶؄; [B1, B5, B6, C2, P1, V5, V6]; xn--dqb73ec22c9kp8cb1j.xn--kua81ls548d3608b; ; xn--dqb73el09fncab4h.xn--kua81ls548d3608b; [B1, B5, B6, P1, V5, V6] # ルーブルࣦݼ.͆
+xn--dqb73el09fncab4h.xn--kua81ls548d3608b; ルーブルࣦݼ.͆򁳊𝅶؄; [B1, B5, B6, V5, V6]; xn--dqb73el09fncab4h.xn--kua81ls548d3608b; ; ; # ルーブルࣦݼ.͆
+xn--dqb73ec22c9kp8cb1j.xn--kua81ls548d3608b; ルーブルࣦݼ‍.͆򁳊𝅶؄; [B1, B5, B6, C2, V5, V6]; xn--dqb73ec22c9kp8cb1j.xn--kua81ls548d3608b; ; ; # ルーブルࣦݼ.͆
+‍.F; ‍.f; [C2]; xn--1ug.f; ; .f; [A4_2] # .f
+‍.f; ; [C2]; xn--1ug.f; ; .f; [A4_2] # .f
+.f; ; [X4_2]; ; [A4_2]; ; # .f
+xn--1ug.f; ‍.f; [C2]; xn--1ug.f; ; ; # .f
+f; ; ; ; ; ; # f
+‍㨲。ß; ‍㨲.ß; [C2]; xn--1ug914h.xn--zca; ; xn--9bm.ss; [] # 㨲.ß
+‍㨲。ß; ‍㨲.ß; [C2]; xn--1ug914h.xn--zca; ; xn--9bm.ss; [] # 㨲.ß
+‍㨲。SS; ‍㨲.ss; [C2]; xn--1ug914h.ss; ; xn--9bm.ss; [] # 㨲.ss
+‍㨲。ss; ‍㨲.ss; [C2]; xn--1ug914h.ss; ; xn--9bm.ss; [] # 㨲.ss
+‍㨲。Ss; ‍㨲.ss; [C2]; xn--1ug914h.ss; ; xn--9bm.ss; [] # 㨲.ss
+xn--9bm.ss; 㨲.ss; ; xn--9bm.ss; ; ; # 㨲.ss
+㨲.ss; ; ; xn--9bm.ss; ; ; # 㨲.ss
+㨲.SS; 㨲.ss; ; xn--9bm.ss; ; ; # 㨲.ss
+㨲.Ss; 㨲.ss; ; xn--9bm.ss; ; ; # 㨲.ss
+xn--1ug914h.ss; ‍㨲.ss; [C2]; xn--1ug914h.ss; ; ; # 㨲.ss
+xn--1ug914h.xn--zca; ‍㨲.ß; [C2]; xn--1ug914h.xn--zca; ; ; # 㨲.ß
+‍㨲。SS; ‍㨲.ss; [C2]; xn--1ug914h.ss; ; xn--9bm.ss; [] # 㨲.ss
+‍㨲。ss; ‍㨲.ss; [C2]; xn--1ug914h.ss; ; xn--9bm.ss; [] # 㨲.ss
+‍㨲。Ss; ‍㨲.ss; [C2]; xn--1ug914h.ss; ; xn--9bm.ss; [] # 㨲.ss
+؅پ。ࢨ; ؅پ.ࢨ; [B1, P1, V6]; xn--nfb6v.xn--xyb; ; ; # پ.ࢨ
+؅پ。ࢨ; ؅پ.ࢨ; [B1, P1, V6]; xn--nfb6v.xn--xyb; ; ; # پ.ࢨ
+xn--nfb6v.xn--xyb; ؅پ.ࢨ; [B1, V6]; xn--nfb6v.xn--xyb; ; ; # پ.ࢨ
+⾑ݓ𞤁。𐹵ڂ; 襾ݓ𞤣.𐹵ڂ; [B1, B5, B6]; xn--6ob9577deqwl.xn--7ib5526k; ; ; # 襾ݓ𞤣.𐹵ڂ
+襾ݓ𞤁。𐹵ڂ; 襾ݓ𞤣.𐹵ڂ; [B1, B5, B6]; xn--6ob9577deqwl.xn--7ib5526k; ; ; # 襾ݓ𞤣.𐹵ڂ
+襾ݓ𞤣。𐹵ڂ; 襾ݓ𞤣.𐹵ڂ; [B1, B5, B6]; xn--6ob9577deqwl.xn--7ib5526k; ; ; # 襾ݓ𞤣.𐹵ڂ
+xn--6ob9577deqwl.xn--7ib5526k; 襾ݓ𞤣.𐹵ڂ; [B1, B5, B6]; xn--6ob9577deqwl.xn--7ib5526k; ; ; # 襾ݓ𞤣.𐹵ڂ
+⾑ݓ𞤣。𐹵ڂ; 襾ݓ𞤣.𐹵ڂ; [B1, B5, B6]; xn--6ob9577deqwl.xn--7ib5526k; ; ; # 襾ݓ𞤣.𐹵ڂ
+񦴻ς-⃫。ݔ-ꡛ; 񦴻ς-⃫.ݔ-ꡛ; [B2, B3, B6, P1, V6]; xn----xmb015tuo34l.xn----53c4874j; ; xn----zmb705tuo34l.xn----53c4874j; # ς-⃫.ݔ-ꡛ
+񦴻ς-⃫。ݔ-ꡛ; 񦴻ς-⃫.ݔ-ꡛ; [B2, B3, B6, P1, V6]; xn----xmb015tuo34l.xn----53c4874j; ; xn----zmb705tuo34l.xn----53c4874j; # ς-⃫.ݔ-ꡛ
+񦴻Σ-⃫。ݔ-ꡛ; 񦴻σ-⃫.ݔ-ꡛ; [B2, B3, B6, P1, V6]; xn----zmb705tuo34l.xn----53c4874j; ; ; # σ-⃫.ݔ-ꡛ
+񦴻σ-⃫。ݔ-ꡛ; 񦴻σ-⃫.ݔ-ꡛ; [B2, B3, B6, P1, V6]; xn----zmb705tuo34l.xn----53c4874j; ; ; # σ-⃫.ݔ-ꡛ
+xn----zmb705tuo34l.xn----53c4874j; 񦴻σ-⃫.ݔ-ꡛ; [B2, B3, B6, V6]; xn----zmb705tuo34l.xn----53c4874j; ; ; # σ-⃫.ݔ-ꡛ
+xn----xmb015tuo34l.xn----53c4874j; 񦴻ς-⃫.ݔ-ꡛ; [B2, B3, B6, V6]; xn----xmb015tuo34l.xn----53c4874j; ; ; # ς-⃫.ݔ-ꡛ
+񦴻Σ-⃫。ݔ-ꡛ; 񦴻σ-⃫.ݔ-ꡛ; [B2, B3, B6, P1, V6]; xn----zmb705tuo34l.xn----53c4874j; ; ; # σ-⃫.ݔ-ꡛ
+񦴻σ-⃫。ݔ-ꡛ; 񦴻σ-⃫.ݔ-ꡛ; [B2, B3, B6, P1, V6]; xn----zmb705tuo34l.xn----53c4874j; ; ; # σ-⃫.ݔ-ꡛ
+‍.􀸨; ‍.􀸨; [C2, P1, V6]; xn--1ug.xn--h327f; ; .xn--h327f; [P1, V6, A4_2] # .
+‍.􀸨; ; [C2, P1, V6]; xn--1ug.xn--h327f; ; .xn--h327f; [P1, V6, A4_2] # .
+.xn--h327f; .􀸨; [V6, X4_2]; .xn--h327f; [V6, A4_2]; ; # .
+xn--1ug.xn--h327f; ‍.􀸨; [C2, V6]; xn--1ug.xn--h327f; ; ; # .
+񣭻񌥁。≠𝟲; 񣭻񌥁.≠6; [P1, V6]; xn--h79w4z99a.xn--6-tfo; ; ; # .≠6
+񣭻񌥁。≠𝟲; 񣭻񌥁.≠6; [P1, V6]; xn--h79w4z99a.xn--6-tfo; ; ; # .≠6
+񣭻񌥁。≠6; 񣭻񌥁.≠6; [P1, V6]; xn--h79w4z99a.xn--6-tfo; ; ; # .≠6
+񣭻񌥁。≠6; 񣭻񌥁.≠6; [P1, V6]; xn--h79w4z99a.xn--6-tfo; ; ; # .≠6
+xn--h79w4z99a.xn--6-tfo; 񣭻񌥁.≠6; [V6]; xn--h79w4z99a.xn--6-tfo; ; ; # .≠6
+󠅊ᡭ‍.𐥡; ᡭ‍.𐥡; [B6, C2, P1, V6]; xn--98e810b.xn--om9c; ; xn--98e.xn--om9c; [P1, V6] # ᡭ.
+xn--98e.xn--om9c; ᡭ.𐥡; [V6]; xn--98e.xn--om9c; ; ; # ᡭ.
+xn--98e810b.xn--om9c; ᡭ‍.𐥡; [B6, C2, V6]; xn--98e810b.xn--om9c; ; ; # ᡭ.
+ీࡕ𐥛𑄴.󭰵; ీࡕ𐥛𑄴.󭰵; [B1, P1, V5, V6]; xn--kwb91r5112avtg.xn--o580f; ; ; # ీࡕ𑄴.
+ీࡕ𐥛𑄴.󭰵; ; [B1, P1, V5, V6]; xn--kwb91r5112avtg.xn--o580f; ; ; # ీࡕ𑄴.
+xn--kwb91r5112avtg.xn--o580f; ీࡕ𐥛𑄴.󭰵; [B1, V5, V6]; xn--kwb91r5112avtg.xn--o580f; ; ; # ీࡕ𑄴.
+𞤮。𑇊‌≯᳦; 𞤮.𑇊‌≯᳦; [B1, C1, P1, V5, V6]; xn--me6h.xn--z6f16kn9b2642b; ; xn--me6h.xn--z6fz8ueq2v; [B1, P1, V5, V6] # 𞤮.𑇊≯᳦
+𞤮。𑇊‌≯᳦; 𞤮.𑇊‌≯᳦; [B1, C1, P1, V5, V6]; xn--me6h.xn--z6f16kn9b2642b; ; xn--me6h.xn--z6fz8ueq2v; [B1, P1, V5, V6] # 𞤮.𑇊≯᳦
+𞤌。𑇊‌≯᳦; 𞤮.𑇊‌≯᳦; [B1, C1, P1, V5, V6]; xn--me6h.xn--z6f16kn9b2642b; ; xn--me6h.xn--z6fz8ueq2v; [B1, P1, V5, V6] # 𞤮.𑇊≯᳦
+𞤌。𑇊‌≯᳦; 𞤮.𑇊‌≯᳦; [B1, C1, P1, V5, V6]; xn--me6h.xn--z6f16kn9b2642b; ; xn--me6h.xn--z6fz8ueq2v; [B1, P1, V5, V6] # 𞤮.𑇊≯᳦
+xn--me6h.xn--z6fz8ueq2v; 𞤮.𑇊≯᳦; [B1, V5, V6]; xn--me6h.xn--z6fz8ueq2v; ; ; # 𞤮.𑇊≯᳦
+xn--me6h.xn--z6f16kn9b2642b; 𞤮.𑇊‌≯᳦; [B1, C1, V5, V6]; xn--me6h.xn--z6f16kn9b2642b; ; ; # 𞤮.𑇊≯᳦
+󠄀𝟕.𞤌񛗓Ⴉ; 7.𞤮񛗓Ⴉ; [B1, B2, B3, P1, V6]; 7.xn--hnd3403vv1vv; ; ; # 7.𞤮Ⴉ
+󠄀7.𞤌񛗓Ⴉ; 7.𞤮񛗓Ⴉ; [B1, B2, B3, P1, V6]; 7.xn--hnd3403vv1vv; ; ; # 7.𞤮Ⴉ
+󠄀7.𞤮񛗓ⴉ; 7.𞤮񛗓ⴉ; [B1, B2, B3, P1, V6]; 7.xn--0kjz523lv1vv; ; ; # 7.𞤮ⴉ
+7.xn--0kjz523lv1vv; 7.𞤮񛗓ⴉ; [B1, B2, B3, V6]; 7.xn--0kjz523lv1vv; ; ; # 7.𞤮ⴉ
+7.xn--hnd3403vv1vv; 7.𞤮񛗓Ⴉ; [B1, B2, B3, V6]; 7.xn--hnd3403vv1vv; ; ; # 7.𞤮Ⴉ
+󠄀𝟕.𞤮񛗓ⴉ; 7.𞤮񛗓ⴉ; [B1, B2, B3, P1, V6]; 7.xn--0kjz523lv1vv; ; ; # 7.𞤮ⴉ
+󠄀7.𞤌񛗓ⴉ; 7.𞤮񛗓ⴉ; [B1, B2, B3, P1, V6]; 7.xn--0kjz523lv1vv; ; ; # 7.𞤮ⴉ
+󠄀𝟕.𞤌񛗓ⴉ; 7.𞤮񛗓ⴉ; [B1, B2, B3, P1, V6]; 7.xn--0kjz523lv1vv; ; ; # 7.𞤮ⴉ
+閃9𝩍。Ↄ٩ࢱ୍; 閃9𝩍.Ↄ٩ࢱ୍; [B5, B6, P1, V6]; xn--9-3j6dk517f.xn--iib28ij3c0t9a; ; ; # 閃9𝩍.Ↄ٩ࢱ୍
+閃9𝩍。ↄ٩ࢱ୍; 閃9𝩍.ↄ٩ࢱ୍; [B5, B6]; xn--9-3j6dk517f.xn--iib28ij3c4t9a; ; ; # 閃9𝩍.ↄ٩ࢱ୍
+xn--9-3j6dk517f.xn--iib28ij3c4t9a; 閃9𝩍.ↄ٩ࢱ୍; [B5, B6]; xn--9-3j6dk517f.xn--iib28ij3c4t9a; ; ; # 閃9𝩍.ↄ٩ࢱ୍
+xn--9-3j6dk517f.xn--iib28ij3c0t9a; 閃9𝩍.Ↄ٩ࢱ୍; [B5, B6, V6]; xn--9-3j6dk517f.xn--iib28ij3c0t9a; ; ; # 閃9𝩍.Ↄ٩ࢱ୍
+꫶ᢏฺ2.𐋢݅ྟ︒; ꫶ᢏฺ2.𐋢݅ྟ︒; [P1, V5, V6]; xn--2-2zf840fk16m.xn--sob093bj62sz9d; ; ; # ꫶ᢏฺ2.𐋢݅ྟ︒
+꫶ᢏฺ2.𐋢݅ྟ。; ꫶ᢏฺ2.𐋢݅ྟ.; [V5]; xn--2-2zf840fk16m.xn--sob093b2m7s.; ; ; # ꫶ᢏฺ2.𐋢݅ྟ.
+xn--2-2zf840fk16m.xn--sob093b2m7s.; ꫶ᢏฺ2.𐋢݅ྟ.; [V5]; xn--2-2zf840fk16m.xn--sob093b2m7s.; ; ; # ꫶ᢏฺ2.𐋢݅ྟ.
+xn--2-2zf840fk16m.xn--sob093bj62sz9d; ꫶ᢏฺ2.𐋢݅ྟ︒; [V5, V6]; xn--2-2zf840fk16m.xn--sob093bj62sz9d; ; ; # ꫶ᢏฺ2.𐋢݅ྟ︒
+󅴧。≠-󠙄⾛; 󅴧.≠-󠙄走; [P1, V6]; xn--gm57d.xn----tfo4949b3664m; ; ; # .≠-走
+󅴧。≠-󠙄⾛; 󅴧.≠-󠙄走; [P1, V6]; xn--gm57d.xn----tfo4949b3664m; ; ; # .≠-走
+󅴧。≠-󠙄走; 󅴧.≠-󠙄走; [P1, V6]; xn--gm57d.xn----tfo4949b3664m; ; ; # .≠-走
+󅴧。≠-󠙄走; 󅴧.≠-󠙄走; [P1, V6]; xn--gm57d.xn----tfo4949b3664m; ; ; # .≠-走
+xn--gm57d.xn----tfo4949b3664m; 󅴧.≠-󠙄走; [V6]; xn--gm57d.xn----tfo4949b3664m; ; ; # .≠-走
+ݮ؄Ⴊ。-≠ᅠ; ݮ؄Ⴊ.-≠ᅠ; [B1, B2, B3, P1, V3, V6]; xn--mfb73ex6r.xn----5bh589i; ; ; # ݮႪ.-≠
+ݮ؄Ⴊ。-≠ᅠ; ݮ؄Ⴊ.-≠ᅠ; [B1, B2, B3, P1, V3, V6]; xn--mfb73ex6r.xn----5bh589i; ; ; # ݮႪ.-≠
+ݮ؄ⴊ。-≠ᅠ; ݮ؄ⴊ.-≠ᅠ; [B1, B2, B3, P1, V3, V6]; xn--mfb73ek93f.xn----5bh589i; ; ; # ݮⴊ.-≠
+ݮ؄ⴊ。-≠ᅠ; ݮ؄ⴊ.-≠ᅠ; [B1, B2, B3, P1, V3, V6]; xn--mfb73ek93f.xn----5bh589i; ; ; # ݮⴊ.-≠
+xn--mfb73ek93f.xn----5bh589i; ݮ؄ⴊ.-≠ᅠ; [B1, B2, B3, V3, V6]; xn--mfb73ek93f.xn----5bh589i; ; ; # ݮⴊ.-≠
+xn--mfb73ex6r.xn----5bh589i; ݮ؄Ⴊ.-≠ᅠ; [B1, B2, B3, V3, V6]; xn--mfb73ex6r.xn----5bh589i; ; ; # ݮႪ.-≠
+ﭏ𐹧𝟒≯。‌; אל𐹧4≯.‌; [B1, B3, B4, C1, P1, V6]; xn--4-zhc0by36txt0w.xn--0ug; ; xn--4-zhc0by36txt0w.; [B3, B4, P1, V6] # אל𐹧4≯.
+ﭏ𐹧𝟒≯。‌; אל𐹧4≯.‌; [B1, B3, B4, C1, P1, V6]; xn--4-zhc0by36txt0w.xn--0ug; ; xn--4-zhc0by36txt0w.; [B3, B4, P1, V6] # אל𐹧4≯.
+אל𐹧4≯。‌; אל𐹧4≯.‌; [B1, B3, B4, C1, P1, V6]; xn--4-zhc0by36txt0w.xn--0ug; ; xn--4-zhc0by36txt0w.; [B3, B4, P1, V6] # אל𐹧4≯.
+אל𐹧4≯。‌; אל𐹧4≯.‌; [B1, B3, B4, C1, P1, V6]; xn--4-zhc0by36txt0w.xn--0ug; ; xn--4-zhc0by36txt0w.; [B3, B4, P1, V6] # אל𐹧4≯.
+xn--4-zhc0by36txt0w.; אל𐹧4≯.; [B3, B4, V6]; xn--4-zhc0by36txt0w.; ; ; # אל𐹧4≯.
+xn--4-zhc0by36txt0w.xn--0ug; אל𐹧4≯.‌; [B1, B3, B4, C1, V6]; xn--4-zhc0by36txt0w.xn--0ug; ; ; # אל𐹧4≯.
+𝟎。甯; 0.甯; ; 0.xn--qny; ; ; # 0.甯
+0。甯; 0.甯; ; 0.xn--qny; ; ; # 0.甯
+0.xn--qny; 0.甯; ; 0.xn--qny; ; ; # 0.甯
+0.甯; ; ; 0.xn--qny; ; ; # 0.甯
+-⾆.꫶; -舌.꫶; [V3, V5]; xn----ef8c.xn--2v9a; ; ; # -舌.꫶
+-舌.꫶; ; [V3, V5]; xn----ef8c.xn--2v9a; ; ; # -舌.꫶
+xn----ef8c.xn--2v9a; -舌.꫶; [V3, V5]; xn----ef8c.xn--2v9a; ; ; # -舌.꫶
+-。ᢘ; -.ᢘ; [V3]; -.xn--ibf; ; ; # -.ᢘ
+-。ᢘ; -.ᢘ; [V3]; -.xn--ibf; ; ; # -.ᢘ
+-.xn--ibf; -.ᢘ; [V3]; -.xn--ibf; ; ; # -.ᢘ
+🂴Ⴋ.≮; ; [P1, V6]; xn--jnd1986v.xn--gdh; ; ; # 🂴Ⴋ.≮
+🂴Ⴋ.≮; 🂴Ⴋ.≮; [P1, V6]; xn--jnd1986v.xn--gdh; ; ; # 🂴Ⴋ.≮
+🂴ⴋ.≮; 🂴ⴋ.≮; [P1, V6]; xn--2kj7565l.xn--gdh; ; ; # 🂴ⴋ.≮
+🂴ⴋ.≮; ; [P1, V6]; xn--2kj7565l.xn--gdh; ; ; # 🂴ⴋ.≮
+xn--2kj7565l.xn--gdh; 🂴ⴋ.≮; [V6]; xn--2kj7565l.xn--gdh; ; ; # 🂴ⴋ.≮
+xn--jnd1986v.xn--gdh; 🂴Ⴋ.≮; [V6]; xn--jnd1986v.xn--gdh; ; ; # 🂴Ⴋ.≮
+璼𝨭。‌󠇟; 璼𝨭.‌; [C1]; xn--gky8837e.xn--0ug; ; xn--gky8837e.; [] # 璼𝨭.
+璼𝨭。‌󠇟; 璼𝨭.‌; [C1]; xn--gky8837e.xn--0ug; ; xn--gky8837e.; [] # 璼𝨭.
+xn--gky8837e.; 璼𝨭.; ; xn--gky8837e.; ; ; # 璼𝨭.
+璼𝨭.; ; ; xn--gky8837e.; ; ; # 璼𝨭.
+xn--gky8837e.xn--0ug; 璼𝨭.‌; [C1]; xn--gky8837e.xn--0ug; ; ; # 璼𝨭.
+٩8񂍽。-5🞥; ٩8񂍽.-5🞥; [B1, P1, V3, V6]; xn--8-qqc97891f.xn---5-rp92a; ; ; # ٩8.-5🞥
+٩8񂍽。-5🞥; ٩8񂍽.-5🞥; [B1, P1, V3, V6]; xn--8-qqc97891f.xn---5-rp92a; ; ; # ٩8.-5🞥
+xn--8-qqc97891f.xn---5-rp92a; ٩8񂍽.-5🞥; [B1, V3, V6]; xn--8-qqc97891f.xn---5-rp92a; ; ; # ٩8.-5🞥
+‌.‌; ; [C1]; xn--0ug.xn--0ug; ; .; [A4_2] # .
+xn--0ug.xn--0ug; ‌.‌; [C1]; xn--0ug.xn--0ug; ; ; # .
+‍튛.ܖ; ; [B1, C2]; xn--1ug4441e.xn--gnb; ; xn--157b.xn--gnb; [] # 튛.ܖ
+‍튛.ܖ; ‍튛.ܖ; [B1, C2]; xn--1ug4441e.xn--gnb; ; xn--157b.xn--gnb; [] # 튛.ܖ
+xn--157b.xn--gnb; 튛.ܖ; ; xn--157b.xn--gnb; ; ; # 튛.ܖ
+튛.ܖ; ; ; xn--157b.xn--gnb; ; ; # 튛.ܖ
+튛.ܖ; 튛.ܖ; ; xn--157b.xn--gnb; ; ; # 튛.ܖ
+xn--1ug4441e.xn--gnb; ‍튛.ܖ; [B1, C2]; xn--1ug4441e.xn--gnb; ; ; # 튛.ܖ
+ᡋ𐹰𞽳.ݹⴞ; ; [B2, B3, B5, B6, P1, V6]; xn--b8e0417jocvf.xn--9pb883q; ; ; # ᡋ𐹰.ݹⴞ
+ᡋ𐹰𞽳.ݹႾ; ; [B2, B3, B5, B6, P1, V6]; xn--b8e0417jocvf.xn--9pb068b; ; ; # ᡋ𐹰.ݹႾ
+xn--b8e0417jocvf.xn--9pb068b; ᡋ𐹰𞽳.ݹႾ; [B2, B3, B5, B6, V6]; xn--b8e0417jocvf.xn--9pb068b; ; ; # ᡋ𐹰.ݹႾ
+xn--b8e0417jocvf.xn--9pb883q; ᡋ𐹰𞽳.ݹⴞ; [B2, B3, B5, B6, V6]; xn--b8e0417jocvf.xn--9pb883q; ; ; # ᡋ𐹰.ݹⴞ
+𐷃٢𝅻𝟧.𐹮𐹬Ⴇ; 𐷃٢𝅻5.𐹮𐹬Ⴇ; [B1, B4, P1, V6]; xn--5-cqc8833rhv7f.xn--fnd3401kfa; ; ; # ٢𝅻5.𐹮𐹬Ⴇ
+𐷃٢𝅻5.𐹮𐹬Ⴇ; ; [B1, B4, P1, V6]; xn--5-cqc8833rhv7f.xn--fnd3401kfa; ; ; # ٢𝅻5.𐹮𐹬Ⴇ
+𐷃٢𝅻5.𐹮𐹬ⴇ; ; [B1, B4, P1, V6]; xn--5-cqc8833rhv7f.xn--ykjz523efa; ; ; # ٢𝅻5.𐹮𐹬ⴇ
+xn--5-cqc8833rhv7f.xn--ykjz523efa; 𐷃٢𝅻5.𐹮𐹬ⴇ; [B1, B4, V6]; xn--5-cqc8833rhv7f.xn--ykjz523efa; ; ; # ٢𝅻5.𐹮𐹬ⴇ
+xn--5-cqc8833rhv7f.xn--fnd3401kfa; 𐷃٢𝅻5.𐹮𐹬Ⴇ; [B1, B4, V6]; xn--5-cqc8833rhv7f.xn--fnd3401kfa; ; ; # ٢𝅻5.𐹮𐹬Ⴇ
+𐷃٢𝅻𝟧.𐹮𐹬ⴇ; 𐷃٢𝅻5.𐹮𐹬ⴇ; [B1, B4, P1, V6]; xn--5-cqc8833rhv7f.xn--ykjz523efa; ; ; # ٢𝅻5.𐹮𐹬ⴇ
+Ⴗ.𑄴ׂꦷ񘃨; Ⴗ.𑄴ׂꦷ񘃨; [P1, V5, V6]; xn--vnd.xn--qdb0605f14ycrms3c; ; ; # Ⴗ.𑄴ׂꦷ
+Ⴗ.𑄴ׂꦷ񘃨; Ⴗ.𑄴ׂꦷ񘃨; [P1, V5, V6]; xn--vnd.xn--qdb0605f14ycrms3c; ; ; # Ⴗ.𑄴ׂꦷ
+Ⴗ.𑄴ׂꦷ񘃨; ; [P1, V5, V6]; xn--vnd.xn--qdb0605f14ycrms3c; ; ; # Ⴗ.𑄴ׂꦷ
+ⴗ.𑄴ׂꦷ񘃨; ; [P1, V5, V6]; xn--flj.xn--qdb0605f14ycrms3c; ; ; # ⴗ.𑄴ׂꦷ
+xn--flj.xn--qdb0605f14ycrms3c; ⴗ.𑄴ׂꦷ񘃨; [V5, V6]; xn--flj.xn--qdb0605f14ycrms3c; ; ; # ⴗ.𑄴ׂꦷ
+xn--vnd.xn--qdb0605f14ycrms3c; Ⴗ.𑄴ׂꦷ񘃨; [V5, V6]; xn--vnd.xn--qdb0605f14ycrms3c; ; ; # Ⴗ.𑄴ׂꦷ
+ⴗ.𑄴ׂꦷ񘃨; ⴗ.𑄴ׂꦷ񘃨; [P1, V5, V6]; xn--flj.xn--qdb0605f14ycrms3c; ; ; # ⴗ.𑄴ׂꦷ
+ⴗ.𑄴ׂꦷ񘃨; ⴗ.𑄴ׂꦷ񘃨; [P1, V5, V6]; xn--flj.xn--qdb0605f14ycrms3c; ; ; # ⴗ.𑄴ׂꦷ
+𝟾𾤘.򇕛٬; 8𾤘.򇕛٬; [B1, B5, B6, P1, V6]; xn--8-kh23b.xn--lib78461i; ; ; # 8.٬
+8𾤘.򇕛٬; ; [B1, B5, B6, P1, V6]; xn--8-kh23b.xn--lib78461i; ; ; # 8.٬
+xn--8-kh23b.xn--lib78461i; 8𾤘.򇕛٬; [B1, B5, B6, V6]; xn--8-kh23b.xn--lib78461i; ; ; # 8.٬
+⒈酫︒。ࣖ; ⒈酫︒.ࣖ; [P1, V5, V6]; xn--tsh4490bfe8c.xn--8zb; ; ; # ⒈酫︒.ࣖ
+1.酫。。ࣖ; 1.酫..ࣖ; [V5, X4_2]; 1.xn--8j4a..xn--8zb; [V5, A4_2]; ; # 1.酫..ࣖ
+1.xn--8j4a..xn--8zb; 1.酫..ࣖ; [V5, X4_2]; 1.xn--8j4a..xn--8zb; [V5, A4_2]; ; # 1.酫..ࣖ
+xn--tsh4490bfe8c.xn--8zb; ⒈酫︒.ࣖ; [V5, V6]; xn--tsh4490bfe8c.xn--8zb; ; ; # ⒈酫︒.ࣖ
+ⷣ‌≮ᩫ.‌ฺ; ; [C1, P1, V5, V6]; xn--uof63xk4bf3s.xn--o4c732g; ; xn--uof548an0j.xn--o4c; [P1, V5, V6] # ⷣ≮ᩫ.ฺ
+ⷣ‌≮ᩫ.‌ฺ; ⷣ‌≮ᩫ.‌ฺ; [C1, P1, V5, V6]; xn--uof63xk4bf3s.xn--o4c732g; ; xn--uof548an0j.xn--o4c; [P1, V5, V6] # ⷣ≮ᩫ.ฺ
+xn--uof548an0j.xn--o4c; ⷣ≮ᩫ.ฺ; [V5, V6]; xn--uof548an0j.xn--o4c; ; ; # ⷣ≮ᩫ.ฺ
+xn--uof63xk4bf3s.xn--o4c732g; ⷣ‌≮ᩫ.‌ฺ; [C1, V5, V6]; xn--uof63xk4bf3s.xn--o4c732g; ; ; # ⷣ≮ᩫ.ฺ
+𞪂。ႷႽ¹‍; 𞪂.ႷႽ1‍; [B6, C2, P1, V6]; xn--co6h.xn--1-h1gs597m; ; xn--co6h.xn--1-h1gs; [P1, V6] # .ႷႽ1
+𞪂。ႷႽ1‍; 𞪂.ႷႽ1‍; [B6, C2, P1, V6]; xn--co6h.xn--1-h1gs597m; ; xn--co6h.xn--1-h1gs; [P1, V6] # .ႷႽ1
+𞪂。ⴗⴝ1‍; 𞪂.ⴗⴝ1‍; [B6, C2, P1, V6]; xn--co6h.xn--1-ugn710dya; ; xn--co6h.xn--1-kwssa; [P1, V6] # .ⴗⴝ1
+𞪂。Ⴗⴝ1‍; 𞪂.Ⴗⴝ1‍; [B6, C2, P1, V6]; xn--co6h.xn--1-h1g398iewm; ; xn--co6h.xn--1-h1g429s; [P1, V6] # .Ⴗⴝ1
+xn--co6h.xn--1-h1g429s; 𞪂.Ⴗⴝ1; [V6]; xn--co6h.xn--1-h1g429s; ; ; # .Ⴗⴝ1
+xn--co6h.xn--1-h1g398iewm; 𞪂.Ⴗⴝ1‍; [B6, C2, V6]; xn--co6h.xn--1-h1g398iewm; ; ; # .Ⴗⴝ1
+xn--co6h.xn--1-kwssa; 𞪂.ⴗⴝ1; [V6]; xn--co6h.xn--1-kwssa; ; ; # .ⴗⴝ1
+xn--co6h.xn--1-ugn710dya; 𞪂.ⴗⴝ1‍; [B6, C2, V6]; xn--co6h.xn--1-ugn710dya; ; ; # .ⴗⴝ1
+xn--co6h.xn--1-h1gs; 𞪂.ႷႽ1; [V6]; xn--co6h.xn--1-h1gs; ; ; # .ႷႽ1
+xn--co6h.xn--1-h1gs597m; 𞪂.ႷႽ1‍; [B6, C2, V6]; xn--co6h.xn--1-h1gs597m; ; ; # .ႷႽ1
+𞪂。ⴗⴝ¹‍; 𞪂.ⴗⴝ1‍; [B6, C2, P1, V6]; xn--co6h.xn--1-ugn710dya; ; xn--co6h.xn--1-kwssa; [P1, V6] # .ⴗⴝ1
+𞪂。Ⴗⴝ¹‍; 𞪂.Ⴗⴝ1‍; [B6, C2, P1, V6]; xn--co6h.xn--1-h1g398iewm; ; xn--co6h.xn--1-h1g429s; [P1, V6] # .Ⴗⴝ1
+𑄴𑄳2.𞳿󠀳-; ; [B1, B3, P1, V3, V5, V6]; xn--2-h87ic.xn----s39r33498d; ; ; # 𑄴𑄳2.-
+xn--2-h87ic.xn----s39r33498d; 𑄴𑄳2.𞳿󠀳-; [B1, B3, V3, V5, V6]; xn--2-h87ic.xn----s39r33498d; ; ; # 𑄴𑄳2.-
+󠕲󟶶٥。񀁁𑄳𞤃ܐ; 󠕲󟶶٥.񀁁𑄳𞤥ܐ; [B1, B5, B6, P1, V6]; xn--eib57614py3ea.xn--9mb5737kqnpfzkwr; ; ; # ٥.𑄳𞤥ܐ
+󠕲󟶶٥。񀁁𑄳𞤃ܐ; 󠕲󟶶٥.񀁁𑄳𞤥ܐ; [B1, B5, B6, P1, V6]; xn--eib57614py3ea.xn--9mb5737kqnpfzkwr; ; ; # ٥.𑄳𞤥ܐ
+󠕲󟶶٥。񀁁𑄳𞤥ܐ; 󠕲󟶶٥.񀁁𑄳𞤥ܐ; [B1, B5, B6, P1, V6]; xn--eib57614py3ea.xn--9mb5737kqnpfzkwr; ; ; # ٥.𑄳𞤥ܐ
+xn--eib57614py3ea.xn--9mb5737kqnpfzkwr; 󠕲󟶶٥.񀁁𑄳𞤥ܐ; [B1, B5, B6, V6]; xn--eib57614py3ea.xn--9mb5737kqnpfzkwr; ; ; # ٥.𑄳𞤥ܐ
+󠕲󟶶٥。񀁁𑄳𞤥ܐ; 󠕲󟶶٥.񀁁𑄳𞤥ܐ; [B1, B5, B6, P1, V6]; xn--eib57614py3ea.xn--9mb5737kqnpfzkwr; ; ; # ٥.𑄳𞤥ܐ
+ܠ򲠽𐹢ុ。ςᢈ🝭‌; ܠ򲠽𐹢ុ.ςᢈ🝭‌; [B2, B6, C1, P1, V6]; xn--qnb616fis0qzt36f.xn--3xa057h6ofgl44c; ; xn--qnb616fis0qzt36f.xn--4xa847hli46a; [B2, B6, P1, V6] # ܠ𐹢ុ.ςᢈ🝭
+ܠ򲠽𐹢ុ。ςᢈ🝭‌; ܠ򲠽𐹢ុ.ςᢈ🝭‌; [B2, B6, C1, P1, V6]; xn--qnb616fis0qzt36f.xn--3xa057h6ofgl44c; ; xn--qnb616fis0qzt36f.xn--4xa847hli46a; [B2, B6, P1, V6] # ܠ𐹢ុ.ςᢈ🝭
+ܠ򲠽𐹢ុ。Σᢈ🝭‌; ܠ򲠽𐹢ុ.σᢈ🝭‌; [B2, B6, C1, P1, V6]; xn--qnb616fis0qzt36f.xn--4xa847h6ofgl44c; ; xn--qnb616fis0qzt36f.xn--4xa847hli46a; [B2, B6, P1, V6] # ܠ𐹢ុ.σᢈ🝭
+ܠ򲠽𐹢ុ。σᢈ🝭‌; ܠ򲠽𐹢ុ.σᢈ🝭‌; [B2, B6, C1, P1, V6]; xn--qnb616fis0qzt36f.xn--4xa847h6ofgl44c; ; xn--qnb616fis0qzt36f.xn--4xa847hli46a; [B2, B6, P1, V6] # ܠ𐹢ុ.σᢈ🝭
+xn--qnb616fis0qzt36f.xn--4xa847hli46a; ܠ򲠽𐹢ុ.σᢈ🝭; [B2, B6, V6]; xn--qnb616fis0qzt36f.xn--4xa847hli46a; ; ; # ܠ𐹢ុ.σᢈ🝭
+xn--qnb616fis0qzt36f.xn--4xa847h6ofgl44c; ܠ򲠽𐹢ុ.σᢈ🝭‌; [B2, B6, C1, V6]; xn--qnb616fis0qzt36f.xn--4xa847h6ofgl44c; ; ; # ܠ𐹢ុ.σᢈ🝭
+xn--qnb616fis0qzt36f.xn--3xa057h6ofgl44c; ܠ򲠽𐹢ុ.ςᢈ🝭‌; [B2, B6, C1, V6]; xn--qnb616fis0qzt36f.xn--3xa057h6ofgl44c; ; ; # ܠ𐹢ុ.ςᢈ🝭
+ܠ򲠽𐹢ុ。Σᢈ🝭‌; ܠ򲠽𐹢ុ.σᢈ🝭‌; [B2, B6, C1, P1, V6]; xn--qnb616fis0qzt36f.xn--4xa847h6ofgl44c; ; xn--qnb616fis0qzt36f.xn--4xa847hli46a; [B2, B6, P1, V6] # ܠ𐹢ុ.σᢈ🝭
+ܠ򲠽𐹢ុ。σᢈ🝭‌; ܠ򲠽𐹢ុ.σᢈ🝭‌; [B2, B6, C1, P1, V6]; xn--qnb616fis0qzt36f.xn--4xa847h6ofgl44c; ; xn--qnb616fis0qzt36f.xn--4xa847hli46a; [B2, B6, P1, V6] # ܠ𐹢ុ.σᢈ🝭
+‍--≮。𐹧; ‍--≮.𐹧; [B1, C2, P1, V6]; xn-----l1tz1k.xn--fo0d; ; xn-----ujv.xn--fo0d; [B1, P1, V3, V6] # --≮.𐹧
+‍--≮。𐹧; ‍--≮.𐹧; [B1, C2, P1, V6]; xn-----l1tz1k.xn--fo0d; ; xn-----ujv.xn--fo0d; [B1, P1, V3, V6] # --≮.𐹧
+xn-----ujv.xn--fo0d; --≮.𐹧; [B1, V3, V6]; xn-----ujv.xn--fo0d; ; ; # --≮.𐹧
+xn-----l1tz1k.xn--fo0d; ‍--≮.𐹧; [B1, C2, V6]; xn-----l1tz1k.xn--fo0d; ; ; # --≮.𐹧
+꠆。𻚏ྰ⒕; ꠆.𻚏ྰ⒕; [P1, V5, V6]; xn--l98a.xn--dgd218hhp28d; ; ; # ꠆.ྰ⒕
+꠆。𻚏ྰ14.; ꠆.𻚏ྰ14.; [P1, V5, V6]; xn--l98a.xn--14-jsj57880f.; ; ; # ꠆.ྰ14.
+xn--l98a.xn--14-jsj57880f.; ꠆.𻚏ྰ14.; [V5, V6]; xn--l98a.xn--14-jsj57880f.; ; ; # ꠆.ྰ14.
+xn--l98a.xn--dgd218hhp28d; ꠆.𻚏ྰ⒕; [V5, V6]; xn--l98a.xn--dgd218hhp28d; ; ; # ꠆.ྰ⒕
+򮉂ڼ.𑆺٩; 򮉂ڼ.𑆺٩; [B1, B5, B6, P1, V5, V6]; xn--vkb92243l.xn--iib9797k; ; ; # ڼ.𑆺٩
+򮉂ڼ.𑆺٩; ; [B1, B5, B6, P1, V5, V6]; xn--vkb92243l.xn--iib9797k; ; ; # ڼ.𑆺٩
+xn--vkb92243l.xn--iib9797k; 򮉂ڼ.𑆺٩; [B1, B5, B6, V5, V6]; xn--vkb92243l.xn--iib9797k; ; ; # ڼ.𑆺٩
+󠁎ې-。𞤴; 󠁎ې-.𞤴; [B1, P1, V3, V6]; xn----mwc72685y.xn--se6h; ; ; # ې-.𞤴
+󠁎ې-。𞤒; 󠁎ې-.𞤴; [B1, P1, V3, V6]; xn----mwc72685y.xn--se6h; ; ; # ې-.𞤴
+xn----mwc72685y.xn--se6h; 󠁎ې-.𞤴; [B1, V3, V6]; xn----mwc72685y.xn--se6h; ; ; # ې-.𞤴
+𝟠4󠇗𝈻.‍𐋵⛧‍; 84𝈻.‍𐋵⛧‍; [C2]; xn--84-s850a.xn--1uga573cfq1w; ; xn--84-s850a.xn--59h6326e; [] # 84𝈻.𐋵⛧
+84󠇗𝈻.‍𐋵⛧‍; 84𝈻.‍𐋵⛧‍; [C2]; xn--84-s850a.xn--1uga573cfq1w; ; xn--84-s850a.xn--59h6326e; [] # 84𝈻.𐋵⛧
+xn--84-s850a.xn--59h6326e; 84𝈻.𐋵⛧; ; xn--84-s850a.xn--59h6326e; ; ; # 84𝈻.𐋵⛧
+84𝈻.𐋵⛧; ; ; xn--84-s850a.xn--59h6326e; ; ; # 84𝈻.𐋵⛧
+xn--84-s850a.xn--1uga573cfq1w; 84𝈻.‍𐋵⛧‍; [C2]; xn--84-s850a.xn--1uga573cfq1w; ; ; # 84𝈻.𐋵⛧
+-؁。ᡪ; -؁.ᡪ; [B1, P1, V3, V6]; xn----tkc.xn--68e; ; ; # -.ᡪ
+-؁。ᡪ; -؁.ᡪ; [B1, P1, V3, V6]; xn----tkc.xn--68e; ; ; # -.ᡪ
+xn----tkc.xn--68e; -؁.ᡪ; [B1, V3, V6]; xn----tkc.xn--68e; ; ; # -.ᡪ
+≮𝟕.謖ß≯; ≮7.謖ß≯; [P1, V6]; xn--7-mgo.xn--zca892oly5e; ; xn--7-mgo.xn--ss-xjvv174c; # ≮7.謖ß≯
+≮𝟕.謖ß≯; ≮7.謖ß≯; [P1, V6]; xn--7-mgo.xn--zca892oly5e; ; xn--7-mgo.xn--ss-xjvv174c; # ≮7.謖ß≯
+≮7.謖ß≯; ; [P1, V6]; xn--7-mgo.xn--zca892oly5e; ; xn--7-mgo.xn--ss-xjvv174c; # ≮7.謖ß≯
+≮7.謖ß≯; ≮7.謖ß≯; [P1, V6]; xn--7-mgo.xn--zca892oly5e; ; xn--7-mgo.xn--ss-xjvv174c; # ≮7.謖ß≯
+≮7.謖SS≯; ≮7.謖ss≯; [P1, V6]; xn--7-mgo.xn--ss-xjvv174c; ; ; # ≮7.謖ss≯
+≮7.謖SS≯; ≮7.謖ss≯; [P1, V6]; xn--7-mgo.xn--ss-xjvv174c; ; ; # ≮7.謖ss≯
+≮7.謖ss≯; ; [P1, V6]; xn--7-mgo.xn--ss-xjvv174c; ; ; # ≮7.謖ss≯
+≮7.謖ss≯; ≮7.謖ss≯; [P1, V6]; xn--7-mgo.xn--ss-xjvv174c; ; ; # ≮7.謖ss≯
+≮7.謖Ss≯; ≮7.謖ss≯; [P1, V6]; xn--7-mgo.xn--ss-xjvv174c; ; ; # ≮7.謖ss≯
+≮7.謖Ss≯; ≮7.謖ss≯; [P1, V6]; xn--7-mgo.xn--ss-xjvv174c; ; ; # ≮7.謖ss≯
+xn--7-mgo.xn--ss-xjvv174c; ≮7.謖ss≯; [V6]; xn--7-mgo.xn--ss-xjvv174c; ; ; # ≮7.謖ss≯
+xn--7-mgo.xn--zca892oly5e; ≮7.謖ß≯; [V6]; xn--7-mgo.xn--zca892oly5e; ; ; # ≮7.謖ß≯
+≮𝟕.謖SS≯; ≮7.謖ss≯; [P1, V6]; xn--7-mgo.xn--ss-xjvv174c; ; ; # ≮7.謖ss≯
+≮𝟕.謖SS≯; ≮7.謖ss≯; [P1, V6]; xn--7-mgo.xn--ss-xjvv174c; ; ; # ≮7.謖ss≯
+≮𝟕.謖ss≯; ≮7.謖ss≯; [P1, V6]; xn--7-mgo.xn--ss-xjvv174c; ; ; # ≮7.謖ss≯
+≮𝟕.謖ss≯; ≮7.謖ss≯; [P1, V6]; xn--7-mgo.xn--ss-xjvv174c; ; ; # ≮7.謖ss≯
+≮𝟕.謖Ss≯; ≮7.謖ss≯; [P1, V6]; xn--7-mgo.xn--ss-xjvv174c; ; ; # ≮7.謖ss≯
+≮𝟕.謖Ss≯; ≮7.謖ss≯; [P1, V6]; xn--7-mgo.xn--ss-xjvv174c; ; ; # ≮7.謖ss≯
+朶Ⴉ𞪡.𝨽ࠥ📻-; ; [B1, B5, B6, P1, V3, V5, V6]; xn--hnd7245bd56p.xn----3gd37096apmwa; ; ; # 朶Ⴉ.𝨽ࠥ📻-
+朶ⴉ𞪡.𝨽ࠥ📻-; ; [B1, B5, B6, P1, V3, V5, V6]; xn--0kjz47pd57t.xn----3gd37096apmwa; ; ; # 朶ⴉ.𝨽ࠥ📻-
+xn--0kjz47pd57t.xn----3gd37096apmwa; 朶ⴉ𞪡.𝨽ࠥ📻-; [B1, B5, B6, V3, V5, V6]; xn--0kjz47pd57t.xn----3gd37096apmwa; ; ; # 朶ⴉ.𝨽ࠥ📻-
+xn--hnd7245bd56p.xn----3gd37096apmwa; 朶Ⴉ𞪡.𝨽ࠥ📻-; [B1, B5, B6, V3, V5, V6]; xn--hnd7245bd56p.xn----3gd37096apmwa; ; ; # 朶Ⴉ.𝨽ࠥ📻-
+𐤎。󑿰‌≮‍; 𐤎.󑿰‌≮‍; [B6, C1, C2, P1, V6]; xn--bk9c.xn--0ugc04p2u638c; ; xn--bk9c.xn--gdhx6802k; [B6, P1, V6] # 𐤎.≮
+𐤎。󑿰‌≮‍; 𐤎.󑿰‌≮‍; [B6, C1, C2, P1, V6]; xn--bk9c.xn--0ugc04p2u638c; ; xn--bk9c.xn--gdhx6802k; [B6, P1, V6] # 𐤎.≮
+xn--bk9c.xn--gdhx6802k; 𐤎.󑿰≮; [B6, V6]; xn--bk9c.xn--gdhx6802k; ; ; # 𐤎.≮
+xn--bk9c.xn--0ugc04p2u638c; 𐤎.󑿰‌≮‍; [B6, C1, C2, V6]; xn--bk9c.xn--0ugc04p2u638c; ; ; # 𐤎.≮
+񭜎⒈。‌𝟤; 񭜎⒈.‌2; [C1, P1, V6]; xn--tsh94183d.xn--2-rgn; ; xn--tsh94183d.2; [P1, V6] # ⒈.2
+񭜎1.。‌2; 񭜎1..‌2; [C1, P1, V6, X4_2]; xn--1-ex54e..xn--2-rgn; [C1, P1, V6, A4_2]; xn--1-ex54e..2; [P1, V6, A4_2] # 1..2
+xn--1-ex54e..2; 񭜎1..2; [V6, X4_2]; xn--1-ex54e..2; [V6, A4_2]; ; # 1..2
+xn--1-ex54e..xn--2-rgn; 񭜎1..‌2; [C1, V6, X4_2]; xn--1-ex54e..xn--2-rgn; [C1, V6, A4_2]; ; # 1..2
+xn--tsh94183d.2; 񭜎⒈.2; [V6]; xn--tsh94183d.2; ; ; # ⒈.2
+xn--tsh94183d.xn--2-rgn; 񭜎⒈.‌2; [C1, V6]; xn--tsh94183d.xn--2-rgn; ; ; # ⒈.2
+󠟊𐹤‍.𐹳󙄵𐹶; 󠟊𐹤‍.𐹳󙄵𐹶; [B1, C2, P1, V6]; xn--1ugy994g7k93g.xn--ro0dga22807v; ; xn--co0d98977c.xn--ro0dga22807v; [B1, P1, V6] # 𐹤.𐹳𐹶
+󠟊𐹤‍.𐹳󙄵𐹶; ; [B1, C2, P1, V6]; xn--1ugy994g7k93g.xn--ro0dga22807v; ; xn--co0d98977c.xn--ro0dga22807v; [B1, P1, V6] # 𐹤.𐹳𐹶
+xn--co0d98977c.xn--ro0dga22807v; 󠟊𐹤.𐹳󙄵𐹶; [B1, V6]; xn--co0d98977c.xn--ro0dga22807v; ; ; # 𐹤.𐹳𐹶
+xn--1ugy994g7k93g.xn--ro0dga22807v; 󠟊𐹤‍.𐹳󙄵𐹶; [B1, C2, V6]; xn--1ugy994g7k93g.xn--ro0dga22807v; ; ; # 𐹤.𐹳𐹶
+𞤴𐹻𑓂𐭝.्︇􉛯; 𞤴𐹻𑓂𐭝.्􉛯; [B1, P1, V5, V6]; xn--609c96c09grp2w.xn--n3b28708s; ; ; # 𞤴𐹻𑓂𐭝.्
+𞤴𐹻𑓂𐭝.्︇􉛯; 𞤴𐹻𑓂𐭝.्􉛯; [B1, P1, V5, V6]; xn--609c96c09grp2w.xn--n3b28708s; ; ; # 𞤴𐹻𑓂𐭝.्
+𞤒𐹻𑓂𐭝.्︇􉛯; 𞤴𐹻𑓂𐭝.्􉛯; [B1, P1, V5, V6]; xn--609c96c09grp2w.xn--n3b28708s; ; ; # 𞤴𐹻𑓂𐭝.्
+xn--609c96c09grp2w.xn--n3b28708s; 𞤴𐹻𑓂𐭝.्􉛯; [B1, V5, V6]; xn--609c96c09grp2w.xn--n3b28708s; ; ; # 𞤴𐹻𑓂𐭝.्
+𞤒𐹻𑓂𐭝.्︇􉛯; 𞤴𐹻𑓂𐭝.्􉛯; [B1, P1, V5, V6]; xn--609c96c09grp2w.xn--n3b28708s; ; ; # 𞤴𐹻𑓂𐭝.्
+٨。𐹠𐹽񗮶; ٨.𐹠𐹽񗮶; [B1, P1, V6]; xn--hib.xn--7n0d2bu9196b; ; ; # ٨.𐹠𐹽
+٨。𐹠𐹽񗮶; ٨.𐹠𐹽񗮶; [B1, P1, V6]; xn--hib.xn--7n0d2bu9196b; ; ; # ٨.𐹠𐹽
+xn--hib.xn--7n0d2bu9196b; ٨.𐹠𐹽񗮶; [B1, V6]; xn--hib.xn--7n0d2bu9196b; ; ; # ٨.𐹠𐹽
+ᅠ񍀜.8򶾵ڜ; ; [B1, P1, V6]; xn--psd85033d.xn--8-otc61545t; ; ; # .8ڜ
+xn--psd85033d.xn--8-otc61545t; ᅠ񍀜.8򶾵ڜ; [B1, V6]; xn--psd85033d.xn--8-otc61545t; ; ; # .8ڜ
+‍‌󠆪。ß𑓃; ‍‌.ß𑓃; [C1, C2]; xn--0ugb.xn--zca0732l; ; .xn--ss-bh7o; [A4_2] # .ß𑓃
+‍‌󠆪。ß𑓃; ‍‌.ß𑓃; [C1, C2]; xn--0ugb.xn--zca0732l; ; .xn--ss-bh7o; [A4_2] # .ß𑓃
+‍‌󠆪。SS𑓃; ‍‌.ss𑓃; [C1, C2]; xn--0ugb.xn--ss-bh7o; ; .xn--ss-bh7o; [A4_2] # .ss𑓃
+‍‌󠆪。ss𑓃; ‍‌.ss𑓃; [C1, C2]; xn--0ugb.xn--ss-bh7o; ; .xn--ss-bh7o; [A4_2] # .ss𑓃
+‍‌󠆪。Ss𑓃; ‍‌.ss𑓃; [C1, C2]; xn--0ugb.xn--ss-bh7o; ; .xn--ss-bh7o; [A4_2] # .ss𑓃
+.xn--ss-bh7o; .ss𑓃; [X4_2]; .xn--ss-bh7o; [A4_2]; ; # .ss𑓃
+xn--0ugb.xn--ss-bh7o; ‍‌.ss𑓃; [C1, C2]; xn--0ugb.xn--ss-bh7o; ; ; # .ss𑓃
+xn--0ugb.xn--zca0732l; ‍‌.ß𑓃; [C1, C2]; xn--0ugb.xn--zca0732l; ; ; # .ß𑓃
+‍‌󠆪。SS𑓃; ‍‌.ss𑓃; [C1, C2]; xn--0ugb.xn--ss-bh7o; ; .xn--ss-bh7o; [A4_2] # .ss𑓃
+‍‌󠆪。ss𑓃; ‍‌.ss𑓃; [C1, C2]; xn--0ugb.xn--ss-bh7o; ; .xn--ss-bh7o; [A4_2] # .ss𑓃
+‍‌󠆪。Ss𑓃; ‍‌.ss𑓃; [C1, C2]; xn--0ugb.xn--ss-bh7o; ; .xn--ss-bh7o; [A4_2] # .ss𑓃
+xn--ss-bh7o; ss𑓃; ; xn--ss-bh7o; ; ; # ss𑓃
+ss𑓃; ; ; xn--ss-bh7o; ; ; # ss𑓃
+SS𑓃; ss𑓃; ; xn--ss-bh7o; ; ; # ss𑓃
+Ss𑓃; ss𑓃; ; xn--ss-bh7o; ; ; # ss𑓃
+︒‌ヶ䒩.ꡪ; ; [C1, P1, V6]; xn--0ug287dj0or48o.xn--gd9a; ; xn--qekw60dns9k.xn--gd9a; [P1, V6] # ︒ヶ䒩.ꡪ
+。‌ヶ䒩.ꡪ; .‌ヶ䒩.ꡪ; [C1, X4_2]; .xn--0ug287dj0o.xn--gd9a; [C1, A4_2]; .xn--qekw60d.xn--gd9a; [A4_2] # .ヶ䒩.ꡪ
+.xn--qekw60d.xn--gd9a; .ヶ䒩.ꡪ; [X4_2]; .xn--qekw60d.xn--gd9a; [A4_2]; ; # .ヶ䒩.ꡪ
+.xn--0ug287dj0o.xn--gd9a; .‌ヶ䒩.ꡪ; [C1, X4_2]; .xn--0ug287dj0o.xn--gd9a; [C1, A4_2]; ; # .ヶ䒩.ꡪ
+xn--qekw60dns9k.xn--gd9a; ︒ヶ䒩.ꡪ; [V6]; xn--qekw60dns9k.xn--gd9a; ; ; # ︒ヶ䒩.ꡪ
+xn--0ug287dj0or48o.xn--gd9a; ︒‌ヶ䒩.ꡪ; [C1, V6]; xn--0ug287dj0or48o.xn--gd9a; ; ; # ︒ヶ䒩.ꡪ
+xn--qekw60d.xn--gd9a; ヶ䒩.ꡪ; ; xn--qekw60d.xn--gd9a; ; ; # ヶ䒩.ꡪ
+ヶ䒩.ꡪ; ; ; xn--qekw60d.xn--gd9a; ; ; # ヶ䒩.ꡪ
+‌⒈𤮍.󢓋᩠; ; [C1, P1, V6]; xn--0ug88o7471d.xn--jof45148n; ; xn--tshw462r.xn--jof45148n; [P1, V6] # ⒈𤮍.᩠
+‌1.𤮍.󢓋᩠; ; [C1, P1, V6]; xn--1-rgn.xn--4x6j.xn--jof45148n; ; 1.xn--4x6j.xn--jof45148n; [P1, V6] # 1.𤮍.᩠
+1.xn--4x6j.xn--jof45148n; 1.𤮍.󢓋᩠; [V6]; 1.xn--4x6j.xn--jof45148n; ; ; # 1.𤮍.᩠
+xn--1-rgn.xn--4x6j.xn--jof45148n; ‌1.𤮍.󢓋᩠; [C1, V6]; xn--1-rgn.xn--4x6j.xn--jof45148n; ; ; # 1.𤮍.᩠
+xn--tshw462r.xn--jof45148n; ⒈𤮍.󢓋᩠; [V6]; xn--tshw462r.xn--jof45148n; ; ; # ⒈𤮍.᩠
+xn--0ug88o7471d.xn--jof45148n; ‌⒈𤮍.󢓋᩠; [C1, V6]; xn--0ug88o7471d.xn--jof45148n; ; ; # ⒈𤮍.᩠
+⒈‌𐫓󠀺。᩠񤰵‍; ⒈‌𐫓󠀺.᩠񤰵‍; [B1, C1, C2, P1, V5, V6]; xn--0ug78ol75wzcx4i.xn--jof95xex98m; ; xn--tsh4435fk263g.xn--jofz5294e; [B1, P1, V5, V6] # ⒈𐫓.᩠
+1.‌𐫓󠀺。᩠񤰵‍; 1.‌𐫓󠀺.᩠񤰵‍; [B1, C1, C2, P1, V5, V6]; 1.xn--0ug8853gk263g.xn--jof95xex98m; ; 1.xn--8w9c40377c.xn--jofz5294e; [B1, B3, P1, V5, V6] # 1.𐫓.᩠
+1.xn--8w9c40377c.xn--jofz5294e; 1.𐫓󠀺.᩠񤰵; [B1, B3, V5, V6]; 1.xn--8w9c40377c.xn--jofz5294e; ; ; # 1.𐫓.᩠
+1.xn--0ug8853gk263g.xn--jof95xex98m; 1.‌𐫓󠀺.᩠񤰵‍; [B1, C1, C2, V5, V6]; 1.xn--0ug8853gk263g.xn--jof95xex98m; ; ; # 1.𐫓.᩠
+xn--tsh4435fk263g.xn--jofz5294e; ⒈𐫓󠀺.᩠񤰵; [B1, V5, V6]; xn--tsh4435fk263g.xn--jofz5294e; ; ; # ⒈𐫓.᩠
+xn--0ug78ol75wzcx4i.xn--jof95xex98m; ⒈‌𐫓󠀺.᩠񤰵‍; [B1, C1, C2, V5, V6]; xn--0ug78ol75wzcx4i.xn--jof95xex98m; ; ; # ⒈𐫓.᩠
+𝅵。𝟫𞀈䬺⒈; 𝅵.9𞀈䬺⒈; [P1, V6]; xn--3f1h.xn--9-ecp936non25a; ; ; # .9𞀈䬺⒈
+𝅵。9𞀈䬺1.; 𝅵.9𞀈䬺1.; [P1, V6]; xn--3f1h.xn--91-030c1650n.; ; ; # .9𞀈䬺1.
+xn--3f1h.xn--91-030c1650n.; 𝅵.9𞀈䬺1.; [V6]; xn--3f1h.xn--91-030c1650n.; ; ; # .9𞀈䬺1.
+xn--3f1h.xn--9-ecp936non25a; 𝅵.9𞀈䬺⒈; [V6]; xn--3f1h.xn--9-ecp936non25a; ; ; # .9𞀈䬺⒈
+򡼺≯。盚ص; 򡼺≯.盚ص; [B5, B6, P1, V6]; xn--hdh30181h.xn--0gb7878c; ; ; # ≯.盚ص
+򡼺≯。盚ص; 򡼺≯.盚ص; [B5, B6, P1, V6]; xn--hdh30181h.xn--0gb7878c; ; ; # ≯.盚ص
+xn--hdh30181h.xn--0gb7878c; 򡼺≯.盚ص; [B5, B6, V6]; xn--hdh30181h.xn--0gb7878c; ; ; # ≯.盚ص
+-񿰭ִ。-󠁊𐢸≯; -񿰭ִ.-󠁊𐢸≯; [B1, P1, V3, V6]; xn----fgc06667m.xn----pgoy615he5y4i; ; ; # -ִ.-≯
+-񿰭ִ。-󠁊𐢸≯; -񿰭ִ.-󠁊𐢸≯; [B1, P1, V3, V6]; xn----fgc06667m.xn----pgoy615he5y4i; ; ; # -ִ.-≯
+xn----fgc06667m.xn----pgoy615he5y4i; -񿰭ִ.-󠁊𐢸≯; [B1, V3, V6]; xn----fgc06667m.xn----pgoy615he5y4i; ; ; # -ִ.-≯
+󿭓᭄‌੍.𐭛񳋔; 󿭓᭄‌੍.𐭛񳋔; [B2, B3, B6, P1, V6]; xn--ybc997f6rd2n772c.xn--409c6100y; ; xn--ybc997fb5881a.xn--409c6100y; [B2, B3, P1, V6] # ᭄੍.𐭛
+󿭓᭄‌੍.𐭛񳋔; ; [B2, B3, B6, P1, V6]; xn--ybc997f6rd2n772c.xn--409c6100y; ; xn--ybc997fb5881a.xn--409c6100y; [B2, B3, P1, V6] # ᭄੍.𐭛
+xn--ybc997fb5881a.xn--409c6100y; 󿭓᭄੍.𐭛񳋔; [B2, B3, V6]; xn--ybc997fb5881a.xn--409c6100y; ; ; # ᭄੍.𐭛
+xn--ybc997f6rd2n772c.xn--409c6100y; 󿭓᭄‌੍.𐭛񳋔; [B2, B3, B6, V6]; xn--ybc997f6rd2n772c.xn--409c6100y; ; ; # ᭄੍.𐭛
+⾇.ٽ𞤴ڻ‍; 舛.ٽ𞤴ڻ‍; [B3, C2]; xn--8c1a.xn--2ib8jv19e6413b; ; xn--8c1a.xn--2ib8jn539l; [] # 舛.ٽ𞤴ڻ
+舛.ٽ𞤴ڻ‍; ; [B3, C2]; xn--8c1a.xn--2ib8jv19e6413b; ; xn--8c1a.xn--2ib8jn539l; [] # 舛.ٽ𞤴ڻ
+舛.ٽ𞤒ڻ‍; 舛.ٽ𞤴ڻ‍; [B3, C2]; xn--8c1a.xn--2ib8jv19e6413b; ; xn--8c1a.xn--2ib8jn539l; [] # 舛.ٽ𞤴ڻ
+xn--8c1a.xn--2ib8jn539l; 舛.ٽ𞤴ڻ; ; xn--8c1a.xn--2ib8jn539l; ; ; # 舛.ٽ𞤴ڻ
+舛.ٽ𞤴ڻ; ; ; xn--8c1a.xn--2ib8jn539l; ; ; # 舛.ٽ𞤴ڻ
+舛.ٽ𞤒ڻ; 舛.ٽ𞤴ڻ; ; xn--8c1a.xn--2ib8jn539l; ; ; # 舛.ٽ𞤴ڻ
+xn--8c1a.xn--2ib8jv19e6413b; 舛.ٽ𞤴ڻ‍; [B3, C2]; xn--8c1a.xn--2ib8jv19e6413b; ; ; # 舛.ٽ𞤴ڻ
+⾇.ٽ𞤒ڻ‍; 舛.ٽ𞤴ڻ‍; [B3, C2]; xn--8c1a.xn--2ib8jv19e6413b; ; xn--8c1a.xn--2ib8jn539l; [] # 舛.ٽ𞤴ڻ
+4򭆥。ݧ≯; 4򭆥.ݧ≯; [B1, B3, P1, V6]; xn--4-xn17i.xn--rpb459k; ; ; # 4.ݧ≯
+4򭆥。ݧ≯; 4򭆥.ݧ≯; [B1, B3, P1, V6]; xn--4-xn17i.xn--rpb459k; ; ; # 4.ݧ≯
+xn--4-xn17i.xn--rpb459k; 4򭆥.ݧ≯; [B1, B3, V6]; xn--4-xn17i.xn--rpb459k; ; ; # 4.ݧ≯
+𲔏𞫨񺿂硲.ڭ; 𲔏𞫨񺿂硲.ڭ; [B5, P1, V6]; xn--lcz1610fn78gk609a.xn--gkb; ; ; # 硲.ڭ
+𲔏𞫨񺿂硲.ڭ; ; [B5, P1, V6]; xn--lcz1610fn78gk609a.xn--gkb; ; ; # 硲.ڭ
+xn--lcz1610fn78gk609a.xn--gkb; 𲔏𞫨񺿂硲.ڭ; [B5, V6]; xn--lcz1610fn78gk609a.xn--gkb; ; ; # 硲.ڭ
+‌.︈٦Ⴆ℮; ‌.٦Ⴆ℮; [B1, C1, P1, V6]; xn--0ug.xn--fib263c0yn; ; .xn--fib263c0yn; [B1, P1, V6, A4_2] # .٦Ⴆ℮
+‌.︈٦ⴆ℮; ‌.٦ⴆ℮; [B1, C1]; xn--0ug.xn--fib628k4li; ; .xn--fib628k4li; [B1, A4_2] # .٦ⴆ℮
+.xn--fib628k4li; .٦ⴆ℮; [B1, X4_2]; .xn--fib628k4li; [B1, A4_2]; ; # .٦ⴆ℮
+xn--0ug.xn--fib628k4li; ‌.٦ⴆ℮; [B1, C1]; xn--0ug.xn--fib628k4li; ; ; # .٦ⴆ℮
+.xn--fib263c0yn; .٦Ⴆ℮; [B1, V6, X4_2]; .xn--fib263c0yn; [B1, V6, A4_2]; ; # .٦Ⴆ℮
+xn--0ug.xn--fib263c0yn; ‌.٦Ⴆ℮; [B1, C1, V6]; xn--0ug.xn--fib263c0yn; ; ; # .٦Ⴆ℮
+ڣ.്‍Ϟ; ڣ.്‍ϟ; [B1, V5]; xn--5jb.xn--xya149bpvp; ; xn--5jb.xn--xya149b; # ڣ.്ϟ
+ڣ.്‍Ϟ; ڣ.്‍ϟ; [B1, V5]; xn--5jb.xn--xya149bpvp; ; xn--5jb.xn--xya149b; # ڣ.്ϟ
+ڣ.്‍ϟ; ; [B1, V5]; xn--5jb.xn--xya149bpvp; ; xn--5jb.xn--xya149b; # ڣ.്ϟ
+xn--5jb.xn--xya149b; ڣ.്ϟ; [B1, V5]; xn--5jb.xn--xya149b; ; ; # ڣ.്ϟ
+xn--5jb.xn--xya149bpvp; ڣ.്‍ϟ; [B1, V5]; xn--5jb.xn--xya149bpvp; ; ; # ڣ.്ϟ
+ڣ.്‍ϟ; ڣ.്‍ϟ; [B1, V5]; xn--5jb.xn--xya149bpvp; ; xn--5jb.xn--xya149b; # ڣ.്ϟ
+‌𞸇𑘿。أ𐮂-腍; ‌ح𑘿.أ𐮂-腍; [B1, B2, B3, C1]; xn--sgb953kmi8o.xn----qmc5075grs9e; ; xn--sgb4140l.xn----qmc5075grs9e; [B2, B3] # ح𑘿.أ𐮂-腍
+‌𞸇𑘿。أ𐮂-腍; ‌ح𑘿.أ𐮂-腍; [B1, B2, B3, C1]; xn--sgb953kmi8o.xn----qmc5075grs9e; ; xn--sgb4140l.xn----qmc5075grs9e; [B2, B3] # ح𑘿.أ𐮂-腍
+‌ح𑘿。أ𐮂-腍; ‌ح𑘿.أ𐮂-腍; [B1, B2, B3, C1]; xn--sgb953kmi8o.xn----qmc5075grs9e; ; xn--sgb4140l.xn----qmc5075grs9e; [B2, B3] # ح𑘿.أ𐮂-腍
+‌ح𑘿。أ𐮂-腍; ‌ح𑘿.أ𐮂-腍; [B1, B2, B3, C1]; xn--sgb953kmi8o.xn----qmc5075grs9e; ; xn--sgb4140l.xn----qmc5075grs9e; [B2, B3] # ح𑘿.أ𐮂-腍
+xn--sgb4140l.xn----qmc5075grs9e; ح𑘿.أ𐮂-腍; [B2, B3]; xn--sgb4140l.xn----qmc5075grs9e; ; ; # ح𑘿.أ𐮂-腍
+xn--sgb953kmi8o.xn----qmc5075grs9e; ‌ح𑘿.أ𐮂-腍; [B1, B2, B3, C1]; xn--sgb953kmi8o.xn----qmc5075grs9e; ; ; # ح𑘿.أ𐮂-腍
+-򭷙٫纛。𝟛񭤇🄅; -򭷙٫纛.3񭤇🄅; [B1, P1, V3, V6]; xn----vqc8143g0tt4i.xn--3-os1sn476y; ; ; # -٫纛.3🄅
+-򭷙٫纛。3񭤇4,; -򭷙٫纛.3񭤇4,; [B1, P1, V3, V6]; xn----vqc8143g0tt4i.xn--34,-8787l; ; ; # -٫纛.34,
+xn----vqc8143g0tt4i.xn--34,-8787l; -򭷙٫纛.3񭤇4,; [B1, P1, V3, V6]; xn----vqc8143g0tt4i.xn--34,-8787l; ; ; # -٫纛.34,
+xn----vqc8143g0tt4i.xn--3-os1sn476y; -򭷙٫纛.3񭤇🄅; [B1, V3, V6]; xn----vqc8143g0tt4i.xn--3-os1sn476y; ; ; # -٫纛.3🄅
+🔔.Ⴂߌ்𐋮; 🔔.Ⴂߌ்𐋮; [B1, B5, P1, V6]; xn--nv8h.xn--nsb46r83e8112a; ; ; # 🔔.Ⴂߌ்𐋮
+🔔.Ⴂߌ்𐋮; ; [B1, B5, P1, V6]; xn--nv8h.xn--nsb46r83e8112a; ; ; # 🔔.Ⴂߌ்𐋮
+🔔.ⴂߌ்𐋮; ; [B1, B5]; xn--nv8h.xn--nsb46rvz1b222p; ; ; # 🔔.ⴂߌ்𐋮
+xn--nv8h.xn--nsb46rvz1b222p; 🔔.ⴂߌ்𐋮; [B1, B5]; xn--nv8h.xn--nsb46rvz1b222p; ; ; # 🔔.ⴂߌ்𐋮
+xn--nv8h.xn--nsb46r83e8112a; 🔔.Ⴂߌ்𐋮; [B1, B5, V6]; xn--nv8h.xn--nsb46r83e8112a; ; ; # 🔔.Ⴂߌ்𐋮
+🔔.ⴂߌ்𐋮; 🔔.ⴂߌ்𐋮; [B1, B5]; xn--nv8h.xn--nsb46rvz1b222p; ; ; # 🔔.ⴂߌ்𐋮
+軥ڳ.-𖬵; ; [B1, B5, B6, V3]; xn--mkb5480e.xn----6u5m; ; ; # 軥ڳ.-𖬵
+xn--mkb5480e.xn----6u5m; 軥ڳ.-𖬵; [B1, B5, B6, V3]; xn--mkb5480e.xn----6u5m; ; ; # 軥ڳ.-𖬵
+𐹤ߊڶ.𐨂-; ; [B1, V3, V5]; xn--pkb56cn614d.xn----974i; ; ; # 𐹤ߊڶ.𐨂-
+xn--pkb56cn614d.xn----974i; 𐹤ߊڶ.𐨂-; [B1, V3, V5]; xn--pkb56cn614d.xn----974i; ; ; # 𐹤ߊڶ.𐨂-
+-󠅱0。៏᷽톇십; -0.៏᷽톇십; [V3, V5]; -0.xn--r4e872ah77nghm; ; ; # -0.៏᷽톇십
+-󠅱0。៏᷽톇십; -0.៏᷽톇십; [V3, V5]; -0.xn--r4e872ah77nghm; ; ; # -0.៏᷽톇십
+-󠅱0。៏᷽톇십; -0.៏᷽톇십; [V3, V5]; -0.xn--r4e872ah77nghm; ; ; # -0.៏᷽톇십
+-󠅱0。៏᷽톇십; -0.៏᷽톇십; [V3, V5]; -0.xn--r4e872ah77nghm; ; ; # -0.៏᷽톇십
+-0.xn--r4e872ah77nghm; -0.៏᷽톇십; [V3, V5]; -0.xn--r4e872ah77nghm; ; ; # -0.៏᷽톇십
+ꡰ︒--。៌靈𐹢񘳮; ꡰ︒--.៌靈𐹢񘳮; [B1, B6, P1, V2, V3, V5, V6]; xn-----bk9hu24z.xn--o4e6836dpxudz0v1c; ; ; # ꡰ︒--.៌靈𐹢
+ꡰ。--。៌靈𐹢񘳮; ꡰ.--.៌靈𐹢񘳮; [B1, P1, V3, V5, V6]; xn--md9a.--.xn--o4e6836dpxudz0v1c; ; ; # ꡰ.--.៌靈𐹢
+xn--md9a.--.xn--o4e6836dpxudz0v1c; ꡰ.--.៌靈𐹢񘳮; [B1, V3, V5, V6]; xn--md9a.--.xn--o4e6836dpxudz0v1c; ; ; # ꡰ.--.៌靈𐹢
+xn-----bk9hu24z.xn--o4e6836dpxudz0v1c; ꡰ︒--.៌靈𐹢񘳮; [B1, B6, V2, V3, V5, V6]; xn-----bk9hu24z.xn--o4e6836dpxudz0v1c; ; ; # ꡰ︒--.៌靈𐹢
+ᅟႿႵრ。୍; ᅟႿႵრ.୍; [P1, V5, V6]; xn--tndt4hvw.xn--9ic; ; ; # ႿႵრ.୍
+ᅟႿႵრ。୍; ᅟႿႵრ.୍; [P1, V5, V6]; xn--tndt4hvw.xn--9ic; ; ; # ႿႵრ.୍
+ᅟⴟⴕრ。୍; ᅟⴟⴕრ.୍; [P1, V5, V6]; xn--1od7wz74eeb.xn--9ic; ; ; # ⴟⴕრ.୍
+ᅟႿႵᲠ。୍; ᅟႿႵრ.୍; [P1, V5, V6]; xn--tndt4hvw.xn--9ic; ; ; # ႿႵრ.୍
+xn--tndt4hvw.xn--9ic; ᅟႿႵრ.୍; [V5, V6]; xn--tndt4hvw.xn--9ic; ; ; # ႿႵრ.୍
+xn--1od7wz74eeb.xn--9ic; ᅟⴟⴕრ.୍; [V5, V6]; xn--1od7wz74eeb.xn--9ic; ; ; # ⴟⴕრ.୍
+ᅟⴟⴕრ。୍; ᅟⴟⴕრ.୍; [P1, V5, V6]; xn--1od7wz74eeb.xn--9ic; ; ; # ⴟⴕრ.୍
+ᅟႿႵᲠ。୍; ᅟႿႵრ.୍; [P1, V5, V6]; xn--tndt4hvw.xn--9ic; ; ; # ႿႵრ.୍
+ᅟႿⴕრ。୍; ᅟႿⴕრ.୍; [P1, V5, V6]; xn--3nd0etsm92g.xn--9ic; ; ; # Ⴟⴕრ.୍
+xn--3nd0etsm92g.xn--9ic; ᅟႿⴕრ.୍; [V5, V6]; xn--3nd0etsm92g.xn--9ic; ; ; # Ⴟⴕრ.୍
+ᅟႿⴕრ。୍; ᅟႿⴕრ.୍; [P1, V5, V6]; xn--3nd0etsm92g.xn--9ic; ; ; # Ⴟⴕრ.୍
+🄃𐹠.٤󠅇; 🄃𐹠.٤; [B1, P1, V6]; xn--7n0d1189a.xn--dib; ; ; # 🄃𐹠.٤
+2,𐹠.٤󠅇; 2,𐹠.٤; [B1, P1, V6]; xn--2,-5g3o.xn--dib; ; ; # 2,𐹠.٤
+xn--2,-5g3o.xn--dib; 2,𐹠.٤; [B1, P1, V6]; xn--2,-5g3o.xn--dib; ; ; # 2,𐹠.٤
+xn--7n0d1189a.xn--dib; 🄃𐹠.٤; [B1, V6]; xn--7n0d1189a.xn--dib; ; ; # 🄃𐹠.٤
+򻲼‌ﱛ.ߒࡈ᯳; 򻲼‌ذٰ.ߒࡈ᯳; [B2, B3, B5, B6, C1, P1, V6]; xn--vgb2kq00fl213y.xn--tsb0vz43c; ; xn--vgb2kp1223g.xn--tsb0vz43c; [B2, B3, B5, B6, P1, V6] # ذٰ.ߒࡈ᯳
+򻲼‌ذٰ.ߒࡈ᯳; ; [B2, B3, B5, B6, C1, P1, V6]; xn--vgb2kq00fl213y.xn--tsb0vz43c; ; xn--vgb2kp1223g.xn--tsb0vz43c; [B2, B3, B5, B6, P1, V6] # ذٰ.ߒࡈ᯳
+xn--vgb2kp1223g.xn--tsb0vz43c; 򻲼ذٰ.ߒࡈ᯳; [B2, B3, B5, B6, V6]; xn--vgb2kp1223g.xn--tsb0vz43c; ; ; # ذٰ.ߒࡈ᯳
+xn--vgb2kq00fl213y.xn--tsb0vz43c; 򻲼‌ذٰ.ߒࡈ᯳; [B2, B3, B5, B6, C1, V6]; xn--vgb2kq00fl213y.xn--tsb0vz43c; ; ; # ذٰ.ߒࡈ᯳
+‍‍𞵪‌。ᡘ𑲭឵; ‍‍𞵪‌.ᡘ𑲭឵; [B1, C1, C2, P1, V6]; xn--0ugba05538b.xn--03e93aq365d; ; xn--l96h.xn--03e93aq365d; [P1, V6] # .ᡘ𑲭
+xn--l96h.xn--03e93aq365d; 𞵪.ᡘ𑲭឵; [V6]; xn--l96h.xn--03e93aq365d; ; ; # .ᡘ𑲭
+xn--0ugba05538b.xn--03e93aq365d; ‍‍𞵪‌.ᡘ𑲭឵; [B1, C1, C2, V6]; xn--0ugba05538b.xn--03e93aq365d; ; ; # .ᡘ𑲭
+𞷻。⚄񗑇𑁿; 𞷻.⚄񗑇𑁿; [B1, P1, V6]; xn--qe7h.xn--c7h2966f7so4a; ; ; # .⚄𑁿
+xn--qe7h.xn--c7h2966f7so4a; 𞷻.⚄񗑇𑁿; [B1, V6]; xn--qe7h.xn--c7h2966f7so4a; ; ; # .⚄𑁿
+꣄≠.𞠨٧; ꣄≠.𞠨٧; [B1, P1, V5, V6]; xn--1chy504c.xn--gib1777v; ; ; # ꣄≠.𞠨٧
+꣄≠.𞠨٧; ꣄≠.𞠨٧; [B1, P1, V5, V6]; xn--1chy504c.xn--gib1777v; ; ; # ꣄≠.𞠨٧
+꣄≠.𞠨٧; ; [B1, P1, V5, V6]; xn--1chy504c.xn--gib1777v; ; ; # ꣄≠.𞠨٧
+꣄≠.𞠨٧; ꣄≠.𞠨٧; [B1, P1, V5, V6]; xn--1chy504c.xn--gib1777v; ; ; # ꣄≠.𞠨٧
+xn--1chy504c.xn--gib1777v; ꣄≠.𞠨٧; [B1, V5, V6]; xn--1chy504c.xn--gib1777v; ; ; # ꣄≠.𞠨٧
+𝟛꣄𝆪。꣪-; 3꣄𝆪.꣪-; [V3, V5]; xn--3-sl4eu679e.xn----xn4e; ; ; # 3꣄𝆪.꣪-
+𝟛꣄𝆪。꣪-; 3꣄𝆪.꣪-; [V3, V5]; xn--3-sl4eu679e.xn----xn4e; ; ; # 3꣄𝆪.꣪-
+3꣄𝆪。꣪-; 3꣄𝆪.꣪-; [V3, V5]; xn--3-sl4eu679e.xn----xn4e; ; ; # 3꣄𝆪.꣪-
+xn--3-sl4eu679e.xn----xn4e; 3꣄𝆪.꣪-; [V3, V5]; xn--3-sl4eu679e.xn----xn4e; ; ; # 3꣄𝆪.꣪-
+ݟᮢ်Ⴇ.4; ; [B1, B2, B3, P1, V6]; xn--jpb846bmjw88a.4; ; ; # ݟᮢ်Ⴇ.4
+ݟᮢ်ⴇ.4; ; [B1, B2, B3]; xn--jpb846bjzj7pr.4; ; ; # ݟᮢ်ⴇ.4
+xn--jpb846bjzj7pr.4; ݟᮢ်ⴇ.4; [B1, B2, B3]; xn--jpb846bjzj7pr.4; ; ; # ݟᮢ်ⴇ.4
+xn--jpb846bmjw88a.4; ݟᮢ်Ⴇ.4; [B1, B2, B3, V6]; xn--jpb846bmjw88a.4; ; ; # ݟᮢ်Ⴇ.4
+ᄹ。໊򠯤󠄞; ᄹ.໊򠯤; [P1, V5, V6]; xn--lrd.xn--s8c05302k; ; ; # ᄹ.໊
+ᄹ。໊򠯤󠄞; ᄹ.໊򠯤; [P1, V5, V6]; xn--lrd.xn--s8c05302k; ; ; # ᄹ.໊
+xn--lrd.xn--s8c05302k; ᄹ.໊򠯤; [V5, V6]; xn--lrd.xn--s8c05302k; ; ; # ᄹ.໊
+Ⴆ򻢩.󠆡︉𞤍; Ⴆ򻢩.𞤯; [P1, V6]; xn--end82983m.xn--ne6h; ; ; # Ⴆ.𞤯
+Ⴆ򻢩.󠆡︉𞤍; Ⴆ򻢩.𞤯; [P1, V6]; xn--end82983m.xn--ne6h; ; ; # Ⴆ.𞤯
+ⴆ򻢩.󠆡︉𞤯; ⴆ򻢩.𞤯; [P1, V6]; xn--xkjw3965g.xn--ne6h; ; ; # ⴆ.𞤯
+xn--xkjw3965g.xn--ne6h; ⴆ򻢩.𞤯; [V6]; xn--xkjw3965g.xn--ne6h; ; ; # ⴆ.𞤯
+xn--end82983m.xn--ne6h; Ⴆ򻢩.𞤯; [V6]; xn--end82983m.xn--ne6h; ; ; # Ⴆ.𞤯
+ⴆ򻢩.󠆡︉𞤯; ⴆ򻢩.𞤯; [P1, V6]; xn--xkjw3965g.xn--ne6h; ; ; # ⴆ.𞤯
+ⴆ򻢩.󠆡︉𞤍; ⴆ򻢩.𞤯; [P1, V6]; xn--xkjw3965g.xn--ne6h; ; ; # ⴆ.𞤯
+ⴆ򻢩.󠆡︉𞤍; ⴆ򻢩.𞤯; [P1, V6]; xn--xkjw3965g.xn--ne6h; ; ; # ⴆ.𞤯
+ßࠋ︒ٻ.帼F∬‌; ßࠋ︒ٻ.帼f∫∫‌; [B5, B6, C1, P1, V6]; xn--zca68zj8ac956c.xn--f-sgn48ga6997e; ; xn--ss-k0d31nu121d.xn--f-tcoa9162d; [B5, B6, P1, V6] # ßࠋ︒ٻ.帼f∫∫
+ßࠋ。ٻ.帼F∫∫‌; ßࠋ.ٻ.帼f∫∫‌; [B5, B6, C1]; xn--zca687a.xn--0ib.xn--f-sgn48ga6997e; ; xn--ss-uze.xn--0ib.xn--f-tcoa9162d; [B5, B6] # ßࠋ.ٻ.帼f∫∫
+ßࠋ。ٻ.帼f∫∫‌; ßࠋ.ٻ.帼f∫∫‌; [B5, B6, C1]; xn--zca687a.xn--0ib.xn--f-sgn48ga6997e; ; xn--ss-uze.xn--0ib.xn--f-tcoa9162d; [B5, B6] # ßࠋ.ٻ.帼f∫∫
+SSࠋ。ٻ.帼F∫∫‌; ssࠋ.ٻ.帼f∫∫‌; [B5, B6, C1]; xn--ss-uze.xn--0ib.xn--f-sgn48ga6997e; ; xn--ss-uze.xn--0ib.xn--f-tcoa9162d; [B5, B6] # ssࠋ.ٻ.帼f∫∫
+ssࠋ。ٻ.帼f∫∫‌; ssࠋ.ٻ.帼f∫∫‌; [B5, B6, C1]; xn--ss-uze.xn--0ib.xn--f-sgn48ga6997e; ; xn--ss-uze.xn--0ib.xn--f-tcoa9162d; [B5, B6] # ssࠋ.ٻ.帼f∫∫
+Ssࠋ。ٻ.帼F∫∫‌; ssࠋ.ٻ.帼f∫∫‌; [B5, B6, C1]; xn--ss-uze.xn--0ib.xn--f-sgn48ga6997e; ; xn--ss-uze.xn--0ib.xn--f-tcoa9162d; [B5, B6] # ssࠋ.ٻ.帼f∫∫
+xn--ss-uze.xn--0ib.xn--f-tcoa9162d; ssࠋ.ٻ.帼f∫∫; [B5, B6]; xn--ss-uze.xn--0ib.xn--f-tcoa9162d; ; ; # ssࠋ.ٻ.帼f∫∫
+xn--ss-uze.xn--0ib.xn--f-sgn48ga6997e; ssࠋ.ٻ.帼f∫∫‌; [B5, B6, C1]; xn--ss-uze.xn--0ib.xn--f-sgn48ga6997e; ; ; # ssࠋ.ٻ.帼f∫∫
+xn--zca687a.xn--0ib.xn--f-sgn48ga6997e; ßࠋ.ٻ.帼f∫∫‌; [B5, B6, C1]; xn--zca687a.xn--0ib.xn--f-sgn48ga6997e; ; ; # ßࠋ.ٻ.帼f∫∫
+ßࠋ︒ٻ.帼f∬‌; ßࠋ︒ٻ.帼f∫∫‌; [B5, B6, C1, P1, V6]; xn--zca68zj8ac956c.xn--f-sgn48ga6997e; ; xn--ss-k0d31nu121d.xn--f-tcoa9162d; [B5, B6, P1, V6] # ßࠋ︒ٻ.帼f∫∫
+SSࠋ︒ٻ.帼F∬‌; ssࠋ︒ٻ.帼f∫∫‌; [B5, B6, C1, P1, V6]; xn--ss-k0d31nu121d.xn--f-sgn48ga6997e; ; xn--ss-k0d31nu121d.xn--f-tcoa9162d; [B5, B6, P1, V6] # ssࠋ︒ٻ.帼f∫∫
+ssࠋ︒ٻ.帼f∬‌; ssࠋ︒ٻ.帼f∫∫‌; [B5, B6, C1, P1, V6]; xn--ss-k0d31nu121d.xn--f-sgn48ga6997e; ; xn--ss-k0d31nu121d.xn--f-tcoa9162d; [B5, B6, P1, V6] # ssࠋ︒ٻ.帼f∫∫
+Ssࠋ︒ٻ.帼F∬‌; ssࠋ︒ٻ.帼f∫∫‌; [B5, B6, C1, P1, V6]; xn--ss-k0d31nu121d.xn--f-sgn48ga6997e; ; xn--ss-k0d31nu121d.xn--f-tcoa9162d; [B5, B6, P1, V6] # ssࠋ︒ٻ.帼f∫∫
+xn--ss-k0d31nu121d.xn--f-tcoa9162d; ssࠋ︒ٻ.帼f∫∫; [B5, B6, V6]; xn--ss-k0d31nu121d.xn--f-tcoa9162d; ; ; # ssࠋ︒ٻ.帼f∫∫
+xn--ss-k0d31nu121d.xn--f-sgn48ga6997e; ssࠋ︒ٻ.帼f∫∫‌; [B5, B6, C1, V6]; xn--ss-k0d31nu121d.xn--f-sgn48ga6997e; ; ; # ssࠋ︒ٻ.帼f∫∫
+xn--zca68zj8ac956c.xn--f-sgn48ga6997e; ßࠋ︒ٻ.帼f∫∫‌; [B5, B6, C1, V6]; xn--zca68zj8ac956c.xn--f-sgn48ga6997e; ; ; # ßࠋ︒ٻ.帼f∫∫
+󘪗。𐹴𞨌‍; 󘪗.𐹴𞨌‍; [B1, C2, P1, V6]; xn--8l83e.xn--1ug4105gsxwf; ; xn--8l83e.xn--so0dw168a; [B1, P1, V6] # .𐹴
+󘪗。𐹴𞨌‍; 󘪗.𐹴𞨌‍; [B1, C2, P1, V6]; xn--8l83e.xn--1ug4105gsxwf; ; xn--8l83e.xn--so0dw168a; [B1, P1, V6] # .𐹴
+xn--8l83e.xn--so0dw168a; 󘪗.𐹴𞨌; [B1, V6]; xn--8l83e.xn--so0dw168a; ; ; # .𐹴
+xn--8l83e.xn--1ug4105gsxwf; 󘪗.𐹴𞨌‍; [B1, C2, V6]; xn--8l83e.xn--1ug4105gsxwf; ; ; # .𐹴
+񗛨.򅟢𝟨꣄; 񗛨.򅟢6꣄; [P1, V6]; xn--mi60a.xn--6-sl4es8023c; ; ; # .6꣄
+񗛨.򅟢6꣄; ; [P1, V6]; xn--mi60a.xn--6-sl4es8023c; ; ; # .6꣄
+xn--mi60a.xn--6-sl4es8023c; 񗛨.򅟢6꣄; [V6]; xn--mi60a.xn--6-sl4es8023c; ; ; # .6꣄
+᪲ﶎ。-۹ႱႨ; ᪲مخج.-۹ႱႨ; [B1, P1, V3, V5, V6]; xn--rgbd2e831i.xn----zyc155e9a; ; ; # ᪲مخج.-۹ႱႨ
+᪲مخج。-۹ႱႨ; ᪲مخج.-۹ႱႨ; [B1, P1, V3, V5, V6]; xn--rgbd2e831i.xn----zyc155e9a; ; ; # ᪲مخج.-۹ႱႨ
+᪲مخج。-۹ⴑⴈ; ᪲مخج.-۹ⴑⴈ; [B1, V3, V5]; xn--rgbd2e831i.xn----zyc3430a9a; ; ; # ᪲مخج.-۹ⴑⴈ
+xn--rgbd2e831i.xn----zyc3430a9a; ᪲مخج.-۹ⴑⴈ; [B1, V3, V5]; xn--rgbd2e831i.xn----zyc3430a9a; ; ; # ᪲مخج.-۹ⴑⴈ
+xn--rgbd2e831i.xn----zyc155e9a; ᪲مخج.-۹ႱႨ; [B1, V3, V5, V6]; xn--rgbd2e831i.xn----zyc155e9a; ; ; # ᪲مخج.-۹ႱႨ
+᪲ﶎ。-۹ⴑⴈ; ᪲مخج.-۹ⴑⴈ; [B1, V3, V5]; xn--rgbd2e831i.xn----zyc3430a9a; ; ; # ᪲مخج.-۹ⴑⴈ
+᪲مخج。-۹Ⴑⴈ; ᪲مخج.-۹Ⴑⴈ; [B1, P1, V3, V5, V6]; xn--rgbd2e831i.xn----zyc875efr3a; ; ; # ᪲مخج.-۹Ⴑⴈ
+xn--rgbd2e831i.xn----zyc875efr3a; ᪲مخج.-۹Ⴑⴈ; [B1, V3, V5, V6]; xn--rgbd2e831i.xn----zyc875efr3a; ; ; # ᪲مخج.-۹Ⴑⴈ
+᪲ﶎ。-۹Ⴑⴈ; ᪲مخج.-۹Ⴑⴈ; [B1, P1, V3, V5, V6]; xn--rgbd2e831i.xn----zyc875efr3a; ; ; # ᪲مخج.-۹Ⴑⴈ
+𞤤.-ࢣ︒; 𞤤.-ࢣ︒; [B1, P1, V3, V6]; xn--ce6h.xn----cod7069p; ; ; # 𞤤.-ࢣ︒
+𞤤.-ࢣ。; 𞤤.-ࢣ.; [B1, V3]; xn--ce6h.xn----cod.; ; ; # 𞤤.-ࢣ.
+𞤂.-ࢣ。; 𞤤.-ࢣ.; [B1, V3]; xn--ce6h.xn----cod.; ; ; # 𞤤.-ࢣ.
+xn--ce6h.xn----cod.; 𞤤.-ࢣ.; [B1, V3]; xn--ce6h.xn----cod.; ; ; # 𞤤.-ࢣ.
+𞤂.-ࢣ︒; 𞤤.-ࢣ︒; [B1, P1, V3, V6]; xn--ce6h.xn----cod7069p; ; ; # 𞤤.-ࢣ︒
+xn--ce6h.xn----cod7069p; 𞤤.-ࢣ︒; [B1, V3, V6]; xn--ce6h.xn----cod7069p; ; ; # 𞤤.-ࢣ︒
+‌𐺨.࡙--; ; [B1, C1, V3, V5]; xn--0ug7905g.xn-----h6e; ; xn--9p0d.xn-----h6e; [B1, V3, V5] # 𐺨.࡙--
+xn--9p0d.xn-----h6e; 𐺨.࡙--; [B1, V3, V5]; xn--9p0d.xn-----h6e; ; ; # 𐺨.࡙--
+xn--0ug7905g.xn-----h6e; ‌𐺨.࡙--; [B1, C1, V3, V5]; xn--0ug7905g.xn-----h6e; ; ; # 𐺨.࡙--
+𐋸󮘋Ⴢ.Ⴁ; ; [P1, V6]; xn--6nd5215jr2u0h.xn--8md; ; ; # 𐋸Ⴢ.Ⴁ
+𐋸󮘋ⴢ.ⴁ; ; [P1, V6]; xn--qlj1559dr224h.xn--skj; ; ; # 𐋸ⴢ.ⴁ
+𐋸󮘋Ⴢ.ⴁ; ; [P1, V6]; xn--6nd5215jr2u0h.xn--skj; ; ; # 𐋸Ⴢ.ⴁ
+xn--6nd5215jr2u0h.xn--skj; 𐋸󮘋Ⴢ.ⴁ; [V6]; xn--6nd5215jr2u0h.xn--skj; ; ; # 𐋸Ⴢ.ⴁ
+xn--qlj1559dr224h.xn--skj; 𐋸󮘋ⴢ.ⴁ; [V6]; xn--qlj1559dr224h.xn--skj; ; ; # 𐋸ⴢ.ⴁ
+xn--6nd5215jr2u0h.xn--8md; 𐋸󮘋Ⴢ.Ⴁ; [V6]; xn--6nd5215jr2u0h.xn--8md; ; ; # 𐋸Ⴢ.Ⴁ
+񗑿꠆₄򩞆。𲩧󠒹ς; 񗑿꠆4򩞆.𲩧󠒹ς; [P1, V6]; xn--4-w93ej7463a9io5a.xn--3xa51142bk3f0d; ; xn--4-w93ej7463a9io5a.xn--4xa31142bk3f0d; # ꠆4.ς
+񗑿꠆4򩞆。𲩧󠒹ς; 񗑿꠆4򩞆.𲩧󠒹ς; [P1, V6]; xn--4-w93ej7463a9io5a.xn--3xa51142bk3f0d; ; xn--4-w93ej7463a9io5a.xn--4xa31142bk3f0d; # ꠆4.ς
+񗑿꠆4򩞆。𲩧󠒹Σ; 񗑿꠆4򩞆.𲩧󠒹σ; [P1, V6]; xn--4-w93ej7463a9io5a.xn--4xa31142bk3f0d; ; ; # ꠆4.σ
+񗑿꠆4򩞆。𲩧󠒹σ; 񗑿꠆4򩞆.𲩧󠒹σ; [P1, V6]; xn--4-w93ej7463a9io5a.xn--4xa31142bk3f0d; ; ; # ꠆4.σ
+xn--4-w93ej7463a9io5a.xn--4xa31142bk3f0d; 񗑿꠆4򩞆.𲩧󠒹σ; [V6]; xn--4-w93ej7463a9io5a.xn--4xa31142bk3f0d; ; ; # ꠆4.σ
+xn--4-w93ej7463a9io5a.xn--3xa51142bk3f0d; 񗑿꠆4򩞆.𲩧󠒹ς; [V6]; xn--4-w93ej7463a9io5a.xn--3xa51142bk3f0d; ; ; # ꠆4.ς
+񗑿꠆₄򩞆。𲩧󠒹Σ; 񗑿꠆4򩞆.𲩧󠒹σ; [P1, V6]; xn--4-w93ej7463a9io5a.xn--4xa31142bk3f0d; ; ; # ꠆4.σ
+񗑿꠆₄򩞆。𲩧󠒹σ; 񗑿꠆4򩞆.𲩧󠒹σ; [P1, V6]; xn--4-w93ej7463a9io5a.xn--4xa31142bk3f0d; ; ; # ꠆4.σ
+󠆀ܣ。ᷴݵ; ܣ.ᷴݵ; [B1, V5]; xn--tnb.xn--5pb136i; ; ; # ܣ.ᷴݵ
+xn--tnb.xn--5pb136i; ܣ.ᷴݵ; [B1, V5]; xn--tnb.xn--5pb136i; ; ; # ܣ.ᷴݵ
+𐹱ࡂ𝪨。𬼖Ⴑ‍; 𐹱ࡂ𝪨.𬼖Ⴑ‍; [B1, B6, C2, P1, V6]; xn--0vb1535kdb6e.xn--pnd879eqy33c; ; xn--0vb1535kdb6e.xn--pnd93707a; [B1, P1, V6] # 𐹱ࡂ𝪨.𬼖Ⴑ
+𐹱ࡂ𝪨。𬼖Ⴑ‍; 𐹱ࡂ𝪨.𬼖Ⴑ‍; [B1, B6, C2, P1, V6]; xn--0vb1535kdb6e.xn--pnd879eqy33c; ; xn--0vb1535kdb6e.xn--pnd93707a; [B1, P1, V6] # 𐹱ࡂ𝪨.𬼖Ⴑ
+𐹱ࡂ𝪨。𬼖ⴑ‍; 𐹱ࡂ𝪨.𬼖ⴑ‍; [B1, B6, C2]; xn--0vb1535kdb6e.xn--1ug742c5714c; ; xn--0vb1535kdb6e.xn--8kjz186s; [B1] # 𐹱ࡂ𝪨.𬼖ⴑ
+xn--0vb1535kdb6e.xn--8kjz186s; 𐹱ࡂ𝪨.𬼖ⴑ; [B1]; xn--0vb1535kdb6e.xn--8kjz186s; ; ; # 𐹱ࡂ𝪨.𬼖ⴑ
+xn--0vb1535kdb6e.xn--1ug742c5714c; 𐹱ࡂ𝪨.𬼖ⴑ‍; [B1, B6, C2]; xn--0vb1535kdb6e.xn--1ug742c5714c; ; ; # 𐹱ࡂ𝪨.𬼖ⴑ
+xn--0vb1535kdb6e.xn--pnd93707a; 𐹱ࡂ𝪨.𬼖Ⴑ; [B1, V6]; xn--0vb1535kdb6e.xn--pnd93707a; ; ; # 𐹱ࡂ𝪨.𬼖Ⴑ
+xn--0vb1535kdb6e.xn--pnd879eqy33c; 𐹱ࡂ𝪨.𬼖Ⴑ‍; [B1, B6, C2, V6]; xn--0vb1535kdb6e.xn--pnd879eqy33c; ; ; # 𐹱ࡂ𝪨.𬼖Ⴑ
+𐹱ࡂ𝪨。𬼖ⴑ‍; 𐹱ࡂ𝪨.𬼖ⴑ‍; [B1, B6, C2]; xn--0vb1535kdb6e.xn--1ug742c5714c; ; xn--0vb1535kdb6e.xn--8kjz186s; [B1] # 𐹱ࡂ𝪨.𬼖ⴑ
+᜔𐭪󠙘‍。-𐹴; ᜔𐭪󠙘‍.-𐹴; [B1, C2, P1, V3, V5, V6]; xn--fze807bso0spy14i.xn----c36i; ; xn--fze4126jujt0g.xn----c36i; [B1, P1, V3, V5, V6] # ᜔𐭪.-𐹴
+᜔𐭪󠙘‍。-𐹴; ᜔𐭪󠙘‍.-𐹴; [B1, C2, P1, V3, V5, V6]; xn--fze807bso0spy14i.xn----c36i; ; xn--fze4126jujt0g.xn----c36i; [B1, P1, V3, V5, V6] # ᜔𐭪.-𐹴
+xn--fze4126jujt0g.xn----c36i; ᜔𐭪󠙘.-𐹴; [B1, V3, V5, V6]; xn--fze4126jujt0g.xn----c36i; ; ; # ᜔𐭪.-𐹴
+xn--fze807bso0spy14i.xn----c36i; ᜔𐭪󠙘‍.-𐹴; [B1, C2, V3, V5, V6]; xn--fze807bso0spy14i.xn----c36i; ; ; # ᜔𐭪.-𐹴
+𾢬。ܩ︒쯙𝟧; 𾢬.ܩ︒쯙5; [B2, P1, V6]; xn--t92s.xn--5-p1c0712mm8rb; ; ; # .ܩ︒쯙5
+𾢬。ܩ︒쯙𝟧; 𾢬.ܩ︒쯙5; [B2, P1, V6]; xn--t92s.xn--5-p1c0712mm8rb; ; ; # .ܩ︒쯙5
+𾢬。ܩ。쯙5; 𾢬.ܩ.쯙5; [P1, V6]; xn--t92s.xn--znb.xn--5-y88f; ; ; # .ܩ.쯙5
+𾢬。ܩ。쯙5; 𾢬.ܩ.쯙5; [P1, V6]; xn--t92s.xn--znb.xn--5-y88f; ; ; # .ܩ.쯙5
+xn--t92s.xn--znb.xn--5-y88f; 𾢬.ܩ.쯙5; [V6]; xn--t92s.xn--znb.xn--5-y88f; ; ; # .ܩ.쯙5
+xn--t92s.xn--5-p1c0712mm8rb; 𾢬.ܩ︒쯙5; [B2, V6]; xn--t92s.xn--5-p1c0712mm8rb; ; ; # .ܩ︒쯙5
+𞤟-。ݢ≮뻐; 𞥁-.ݢ≮뻐; [B2, B3, P1, V3, V6]; xn----1j8r.xn--mpb269krv4i; ; ; # 𞥁-.ݢ≮뻐
+𞤟-。ݢ≮뻐; 𞥁-.ݢ≮뻐; [B2, B3, P1, V3, V6]; xn----1j8r.xn--mpb269krv4i; ; ; # 𞥁-.ݢ≮뻐
+𞥁-。ݢ≮뻐; 𞥁-.ݢ≮뻐; [B2, B3, P1, V3, V6]; xn----1j8r.xn--mpb269krv4i; ; ; # 𞥁-.ݢ≮뻐
+𞥁-。ݢ≮뻐; 𞥁-.ݢ≮뻐; [B2, B3, P1, V3, V6]; xn----1j8r.xn--mpb269krv4i; ; ; # 𞥁-.ݢ≮뻐
+xn----1j8r.xn--mpb269krv4i; 𞥁-.ݢ≮뻐; [B2, B3, V3, V6]; xn----1j8r.xn--mpb269krv4i; ; ; # 𞥁-.ݢ≮뻐
+𞥩-򊫠.ࢴ≠; 𞥩-򊫠.ࢴ≠; [B2, B3, P1, V6]; xn----cm8rp3609a.xn--9yb852k; ; ; # -.ࢴ≠
+𞥩-򊫠.ࢴ≠; 𞥩-򊫠.ࢴ≠; [B2, B3, P1, V6]; xn----cm8rp3609a.xn--9yb852k; ; ; # -.ࢴ≠
+𞥩-򊫠.ࢴ≠; ; [B2, B3, P1, V6]; xn----cm8rp3609a.xn--9yb852k; ; ; # -.ࢴ≠
+𞥩-򊫠.ࢴ≠; 𞥩-򊫠.ࢴ≠; [B2, B3, P1, V6]; xn----cm8rp3609a.xn--9yb852k; ; ; # -.ࢴ≠
+xn----cm8rp3609a.xn--9yb852k; 𞥩-򊫠.ࢴ≠; [B2, B3, V6]; xn----cm8rp3609a.xn--9yb852k; ; ; # -.ࢴ≠
+-񅂏ςႼ.١; -񅂏ςႼ.١; [B1, P1, V3, V6]; xn----ymb080hun11i.xn--9hb; ; xn----0mb770hun11i.xn--9hb; # -ςႼ.١
+-񅂏ςႼ.١; ; [B1, P1, V3, V6]; xn----ymb080hun11i.xn--9hb; ; xn----0mb770hun11i.xn--9hb; # -ςႼ.١
+-񅂏ςⴜ.١; ; [B1, P1, V3, V6]; xn----ymb2782aov12f.xn--9hb; ; xn----0mb9682aov12f.xn--9hb; # -ςⴜ.١
+-񅂏ΣႼ.١; -񅂏σႼ.١; [B1, P1, V3, V6]; xn----0mb770hun11i.xn--9hb; ; ; # -σႼ.١
+-񅂏σⴜ.١; ; [B1, P1, V3, V6]; xn----0mb9682aov12f.xn--9hb; ; ; # -σⴜ.١
+-񅂏Σⴜ.١; -񅂏σⴜ.١; [B1, P1, V3, V6]; xn----0mb9682aov12f.xn--9hb; ; ; # -σⴜ.١
+xn----0mb9682aov12f.xn--9hb; -񅂏σⴜ.١; [B1, V3, V6]; xn----0mb9682aov12f.xn--9hb; ; ; # -σⴜ.١
+xn----0mb770hun11i.xn--9hb; -񅂏σႼ.١; [B1, V3, V6]; xn----0mb770hun11i.xn--9hb; ; ; # -σႼ.١
+xn----ymb2782aov12f.xn--9hb; -񅂏ςⴜ.١; [B1, V3, V6]; xn----ymb2782aov12f.xn--9hb; ; ; # -ςⴜ.١
+xn----ymb080hun11i.xn--9hb; -񅂏ςႼ.١; [B1, V3, V6]; xn----ymb080hun11i.xn--9hb; ; ; # -ςႼ.١
+-񅂏ςⴜ.١; -񅂏ςⴜ.١; [B1, P1, V3, V6]; xn----ymb2782aov12f.xn--9hb; ; xn----0mb9682aov12f.xn--9hb; # -ςⴜ.١
+-񅂏ΣႼ.١; -񅂏σႼ.١; [B1, P1, V3, V6]; xn----0mb770hun11i.xn--9hb; ; ; # -σႼ.١
+-񅂏σⴜ.١; -񅂏σⴜ.١; [B1, P1, V3, V6]; xn----0mb9682aov12f.xn--9hb; ; ; # -σⴜ.١
+-񅂏Σⴜ.١; -񅂏σⴜ.١; [B1, P1, V3, V6]; xn----0mb9682aov12f.xn--9hb; ; ; # -σⴜ.١
+៊.‍𝟮𑀿; ៊.‍2𑀿; [C2, V5]; xn--m4e.xn--2-tgnv469h; ; xn--m4e.xn--2-ku7i; [V5] # ៊.2𑀿
+៊.‍2𑀿; ; [C2, V5]; xn--m4e.xn--2-tgnv469h; ; xn--m4e.xn--2-ku7i; [V5] # ៊.2𑀿
+xn--m4e.xn--2-ku7i; ៊.2𑀿; [V5]; xn--m4e.xn--2-ku7i; ; ; # ៊.2𑀿
+xn--m4e.xn--2-tgnv469h; ៊.‍2𑀿; [C2, V5]; xn--m4e.xn--2-tgnv469h; ; ; # ៊.2𑀿
+≯𝟖。᩠𐫓򟇑; ≯8.᩠𐫓򟇑; [B1, P1, V5, V6]; xn--8-ogo.xn--jof5303iv1z5d; ; ; # ≯8.᩠𐫓
+≯𝟖。᩠𐫓򟇑; ≯8.᩠𐫓򟇑; [B1, P1, V5, V6]; xn--8-ogo.xn--jof5303iv1z5d; ; ; # ≯8.᩠𐫓
+≯8。᩠𐫓򟇑; ≯8.᩠𐫓򟇑; [B1, P1, V5, V6]; xn--8-ogo.xn--jof5303iv1z5d; ; ; # ≯8.᩠𐫓
+≯8。᩠𐫓򟇑; ≯8.᩠𐫓򟇑; [B1, P1, V5, V6]; xn--8-ogo.xn--jof5303iv1z5d; ; ; # ≯8.᩠𐫓
+xn--8-ogo.xn--jof5303iv1z5d; ≯8.᩠𐫓򟇑; [B1, V5, V6]; xn--8-ogo.xn--jof5303iv1z5d; ; ; # ≯8.᩠𐫓
+𑲫Ↄ٤。‌; 𑲫Ↄ٤.‌; [B1, C1, P1, V5, V6]; xn--dib999kcy1p.xn--0ug; ; xn--dib999kcy1p.; [B1, P1, V5, V6] # 𑲫Ↄ٤.
+𑲫Ↄ٤。‌; 𑲫Ↄ٤.‌; [B1, C1, P1, V5, V6]; xn--dib999kcy1p.xn--0ug; ; xn--dib999kcy1p.; [B1, P1, V5, V6] # 𑲫Ↄ٤.
+𑲫ↄ٤。‌; 𑲫ↄ٤.‌; [B1, C1, V5]; xn--dib100l8x1p.xn--0ug; ; xn--dib100l8x1p.; [B1, V5] # 𑲫ↄ٤.
+xn--dib100l8x1p.; 𑲫ↄ٤.; [B1, V5]; xn--dib100l8x1p.; ; ; # 𑲫ↄ٤.
+xn--dib100l8x1p.xn--0ug; 𑲫ↄ٤.‌; [B1, C1, V5]; xn--dib100l8x1p.xn--0ug; ; ; # 𑲫ↄ٤.
+xn--dib999kcy1p.; 𑲫Ↄ٤.; [B1, V5, V6]; xn--dib999kcy1p.; ; ; # 𑲫Ↄ٤.
+xn--dib999kcy1p.xn--0ug; 𑲫Ↄ٤.‌; [B1, C1, V5, V6]; xn--dib999kcy1p.xn--0ug; ; ; # 𑲫Ↄ٤.
+𑲫ↄ٤。‌; 𑲫ↄ٤.‌; [B1, C1, V5]; xn--dib100l8x1p.xn--0ug; ; xn--dib100l8x1p.; [B1, V5] # 𑲫ↄ٤.
+ఀ𝟵‍ﲝ.‍ݐ⒈; ఀ9‍بح.‍ݐ⒈; [B1, C2, P1, V5, V6]; xn--9-1mcp570dl51a.xn--3ob977jmfd; ; xn--9-1mcp570d.xn--3ob470m; [B1, P1, V5, V6] # ఀ9بح.ݐ⒈
+ఀ9‍بح.‍ݐ1.; ; [B1, C2, V5]; xn--9-1mcp570dl51a.xn--1-x3c211q.; ; xn--9-1mcp570d.xn--1-x3c.; [B1, V5] # ఀ9بح.ݐ1.
+xn--9-1mcp570d.xn--1-x3c.; ఀ9بح.ݐ1.; [B1, V5]; xn--9-1mcp570d.xn--1-x3c.; ; ; # ఀ9بح.ݐ1.
+xn--9-1mcp570dl51a.xn--1-x3c211q.; ఀ9‍بح.‍ݐ1.; [B1, C2, V5]; xn--9-1mcp570dl51a.xn--1-x3c211q.; ; ; # ఀ9بح.ݐ1.
+xn--9-1mcp570d.xn--3ob470m; ఀ9بح.ݐ⒈; [B1, V5, V6]; xn--9-1mcp570d.xn--3ob470m; ; ; # ఀ9بح.ݐ⒈
+xn--9-1mcp570dl51a.xn--3ob977jmfd; ఀ9‍بح.‍ݐ⒈; [B1, C2, V5, V6]; xn--9-1mcp570dl51a.xn--3ob977jmfd; ; ; # ఀ9بح.ݐ⒈
+꫶。嬶ß葽; ꫶.嬶ß葽; [V5]; xn--2v9a.xn--zca7637b14za; ; xn--2v9a.xn--ss-q40dp97m; # ꫶.嬶ß葽
+꫶。嬶SS葽; ꫶.嬶ss葽; [V5]; xn--2v9a.xn--ss-q40dp97m; ; ; # ꫶.嬶ss葽
+꫶。嬶ss葽; ꫶.嬶ss葽; [V5]; xn--2v9a.xn--ss-q40dp97m; ; ; # ꫶.嬶ss葽
+꫶。嬶Ss葽; ꫶.嬶ss葽; [V5]; xn--2v9a.xn--ss-q40dp97m; ; ; # ꫶.嬶ss葽
+xn--2v9a.xn--ss-q40dp97m; ꫶.嬶ss葽; [V5]; xn--2v9a.xn--ss-q40dp97m; ; ; # ꫶.嬶ss葽
+xn--2v9a.xn--zca7637b14za; ꫶.嬶ß葽; [V5]; xn--2v9a.xn--zca7637b14za; ; ; # ꫶.嬶ß葽
+𑚶⒈。񞻡𐹺; 𑚶⒈.񞻡𐹺; [B5, B6, P1, V5, V6]; xn--tshz969f.xn--yo0d5914s; ; ; # 𑚶⒈.𐹺
+𑚶1.。񞻡𐹺; 𑚶1..񞻡𐹺; [B5, B6, P1, V5, V6, X4_2]; xn--1-3j0j..xn--yo0d5914s; [B5, B6, P1, V5, V6, A4_2]; ; # 𑚶1..𐹺
+xn--1-3j0j..xn--yo0d5914s; 𑚶1..񞻡𐹺; [B5, B6, V5, V6, X4_2]; xn--1-3j0j..xn--yo0d5914s; [B5, B6, V5, V6, A4_2]; ; # 𑚶1..𐹺
+xn--tshz969f.xn--yo0d5914s; 𑚶⒈.񞻡𐹺; [B5, B6, V5, V6]; xn--tshz969f.xn--yo0d5914s; ; ; # 𑚶⒈.𐹺
+𑜤︒≮.񚕽ט𞾩; 𑜤︒≮.񚕽ט𞾩; [B1, B5, B6, P1, V5, V6]; xn--gdh5267fdzpa.xn--deb0091w5q9u; ; ; # 𑜤︒≮.ט
+𑜤︒≮.񚕽ט𞾩; 𑜤︒≮.񚕽ט𞾩; [B1, B5, B6, P1, V5, V6]; xn--gdh5267fdzpa.xn--deb0091w5q9u; ; ; # 𑜤︒≮.ט
+𑜤。≮.񚕽ט𞾩; 𑜤.≮.񚕽ט𞾩; [B1, B3, B5, B6, P1, V5, V6]; xn--ci2d.xn--gdh.xn--deb0091w5q9u; ; ; # 𑜤.≮.ט
+𑜤。≮.񚕽ט𞾩; 𑜤.≮.񚕽ט𞾩; [B1, B3, B5, B6, P1, V5, V6]; xn--ci2d.xn--gdh.xn--deb0091w5q9u; ; ; # 𑜤.≮.ט
+xn--ci2d.xn--gdh.xn--deb0091w5q9u; 𑜤.≮.񚕽ט𞾩; [B1, B3, B5, B6, V5, V6]; xn--ci2d.xn--gdh.xn--deb0091w5q9u; ; ; # 𑜤.≮.ט
+xn--gdh5267fdzpa.xn--deb0091w5q9u; 𑜤︒≮.񚕽ט𞾩; [B1, B5, B6, V5, V6]; xn--gdh5267fdzpa.xn--deb0091w5q9u; ; ; # 𑜤︒≮.ט
+󠆋؃񏦤.⇁ς򏋈򺇥; ؃񏦤.⇁ς򏋈򺇥; [B1, P1, V6]; xn--lfb04106d.xn--3xa174mxv16m8moq; ; xn--lfb04106d.xn--4xa964mxv16m8moq; # .⇁ς
+󠆋؃񏦤.⇁Σ򏋈򺇥; ؃񏦤.⇁σ򏋈򺇥; [B1, P1, V6]; xn--lfb04106d.xn--4xa964mxv16m8moq; ; ; # .⇁σ
+󠆋؃񏦤.⇁σ򏋈򺇥; ؃񏦤.⇁σ򏋈򺇥; [B1, P1, V6]; xn--lfb04106d.xn--4xa964mxv16m8moq; ; ; # .⇁σ
+xn--lfb04106d.xn--4xa964mxv16m8moq; ؃񏦤.⇁σ򏋈򺇥; [B1, V6]; xn--lfb04106d.xn--4xa964mxv16m8moq; ; ; # .⇁σ
+xn--lfb04106d.xn--3xa174mxv16m8moq; ؃񏦤.⇁ς򏋈򺇥; [B1, V6]; xn--lfb04106d.xn--3xa174mxv16m8moq; ; ; # .⇁ς
+ς𑐽𵢈𑜫。𞬩‌𐫄; ς𑐽𵢈𑜫.𞬩‌𐫄; [C1, P1, V6]; xn--3xa4260lk3b8z15g.xn--0ug4653g2xzf; ; xn--4xa2260lk3b8z15g.xn--tw9ct349a; [P1, V6] # ς𑐽𑜫.𐫄
+ς𑐽𵢈𑜫。𞬩‌𐫄; ς𑐽𵢈𑜫.𞬩‌𐫄; [C1, P1, V6]; xn--3xa4260lk3b8z15g.xn--0ug4653g2xzf; ; xn--4xa2260lk3b8z15g.xn--tw9ct349a; [P1, V6] # ς𑐽𑜫.𐫄
+Σ𑐽𵢈𑜫。𞬩‌𐫄; σ𑐽𵢈𑜫.𞬩‌𐫄; [C1, P1, V6]; xn--4xa2260lk3b8z15g.xn--0ug4653g2xzf; ; xn--4xa2260lk3b8z15g.xn--tw9ct349a; [P1, V6] # σ𑐽𑜫.𐫄
+σ𑐽𵢈𑜫。𞬩‌𐫄; σ𑐽𵢈𑜫.𞬩‌𐫄; [C1, P1, V6]; xn--4xa2260lk3b8z15g.xn--0ug4653g2xzf; ; xn--4xa2260lk3b8z15g.xn--tw9ct349a; [P1, V6] # σ𑐽𑜫.𐫄
+xn--4xa2260lk3b8z15g.xn--tw9ct349a; σ𑐽𵢈𑜫.𞬩𐫄; [V6]; xn--4xa2260lk3b8z15g.xn--tw9ct349a; ; ; # σ𑐽𑜫.𐫄
+xn--4xa2260lk3b8z15g.xn--0ug4653g2xzf; σ𑐽𵢈𑜫.𞬩‌𐫄; [C1, V6]; xn--4xa2260lk3b8z15g.xn--0ug4653g2xzf; ; ; # σ𑐽𑜫.𐫄
+xn--3xa4260lk3b8z15g.xn--0ug4653g2xzf; ς𑐽𵢈𑜫.𞬩‌𐫄; [C1, V6]; xn--3xa4260lk3b8z15g.xn--0ug4653g2xzf; ; ; # ς𑐽𑜫.𐫄
+Σ𑐽𵢈𑜫。𞬩‌𐫄; σ𑐽𵢈𑜫.𞬩‌𐫄; [C1, P1, V6]; xn--4xa2260lk3b8z15g.xn--0ug4653g2xzf; ; xn--4xa2260lk3b8z15g.xn--tw9ct349a; [P1, V6] # σ𑐽𑜫.𐫄
+σ𑐽𵢈𑜫。𞬩‌𐫄; σ𑐽𵢈𑜫.𞬩‌𐫄; [C1, P1, V6]; xn--4xa2260lk3b8z15g.xn--0ug4653g2xzf; ; xn--4xa2260lk3b8z15g.xn--tw9ct349a; [P1, V6] # σ𑐽𑜫.𐫄
+-򵏽。-ﱌݛ; -򵏽.-نحݛ; [B1, P1, V3, V6]; xn----o452j.xn----cnc8e38c; ; ; # -.-نحݛ
+-򵏽。-نحݛ; -򵏽.-نحݛ; [B1, P1, V3, V6]; xn----o452j.xn----cnc8e38c; ; ; # -.-نحݛ
+xn----o452j.xn----cnc8e38c; -򵏽.-نحݛ; [B1, V3, V6]; xn----o452j.xn----cnc8e38c; ; ; # -.-نحݛ
+⺢򇺅𝟤。‍🚷; ⺢򇺅2.‍🚷; [C2, P1, V6]; xn--2-4jtr4282f.xn--1ugz946p; ; xn--2-4jtr4282f.xn--m78h; [P1, V6] # ⺢2.🚷
+⺢򇺅2。‍🚷; ⺢򇺅2.‍🚷; [C2, P1, V6]; xn--2-4jtr4282f.xn--1ugz946p; ; xn--2-4jtr4282f.xn--m78h; [P1, V6] # ⺢2.🚷
+xn--2-4jtr4282f.xn--m78h; ⺢򇺅2.🚷; [V6]; xn--2-4jtr4282f.xn--m78h; ; ; # ⺢2.🚷
+xn--2-4jtr4282f.xn--1ugz946p; ⺢򇺅2.‍🚷; [C2, V6]; xn--2-4jtr4282f.xn--1ugz946p; ; ; # ⺢2.🚷
+೸‍ⷾ𐹲。򤐶; ೸‍ⷾ𐹲.򤐶; [B5, B6, C2, P1, V6]; xn--hvc488g69j402t.xn--3e36c; ; xn--hvc220of37m.xn--3e36c; [B5, B6, P1, V6] # ⷾ𐹲.
+೸‍ⷾ𐹲。򤐶; ೸‍ⷾ𐹲.򤐶; [B5, B6, C2, P1, V6]; xn--hvc488g69j402t.xn--3e36c; ; xn--hvc220of37m.xn--3e36c; [B5, B6, P1, V6] # ⷾ𐹲.
+xn--hvc220of37m.xn--3e36c; ೸ⷾ𐹲.򤐶; [B5, B6, V6]; xn--hvc220of37m.xn--3e36c; ; ; # ⷾ𐹲.
+xn--hvc488g69j402t.xn--3e36c; ೸‍ⷾ𐹲.򤐶; [B5, B6, C2, V6]; xn--hvc488g69j402t.xn--3e36c; ; ; # ⷾ𐹲.
+𐹢.Ⴍ₉⁸; 𐹢.Ⴍ98; [B1, P1, V6]; xn--9n0d.xn--98-7ek; ; ; # 𐹢.Ⴍ98
+𐹢.Ⴍ98; ; [B1, P1, V6]; xn--9n0d.xn--98-7ek; ; ; # 𐹢.Ⴍ98
+𐹢.ⴍ98; ; [B1]; xn--9n0d.xn--98-u61a; ; ; # 𐹢.ⴍ98
+xn--9n0d.xn--98-u61a; 𐹢.ⴍ98; [B1]; xn--9n0d.xn--98-u61a; ; ; # 𐹢.ⴍ98
+xn--9n0d.xn--98-7ek; 𐹢.Ⴍ98; [B1, V6]; xn--9n0d.xn--98-7ek; ; ; # 𐹢.Ⴍ98
+𐹢.ⴍ₉⁸; 𐹢.ⴍ98; [B1]; xn--9n0d.xn--98-u61a; ; ; # 𐹢.ⴍ98
+‌͏。ß࣢⒚≯; ‌.ß࣢⒚≯; [B1, B5, B6, C1, P1, V6]; xn--0ug.xn--zca612bx9vo5b; ; .xn--ss-9if872xjjc; [B5, B6, P1, V6, A4_2] # .ß⒚≯
+‌͏。ß࣢⒚≯; ‌.ß࣢⒚≯; [B1, B5, B6, C1, P1, V6]; xn--0ug.xn--zca612bx9vo5b; ; .xn--ss-9if872xjjc; [B5, B6, P1, V6, A4_2] # .ß⒚≯
+‌͏。ß࣢19.≯; ‌.ß࣢19.≯; [B1, B5, C1, P1, V6]; xn--0ug.xn--19-fia813f.xn--hdh; ; .xn--ss19-w0i.xn--hdh; [B1, B5, P1, V6, A4_2] # .ß19.≯
+‌͏。ß࣢19.≯; ‌.ß࣢19.≯; [B1, B5, C1, P1, V6]; xn--0ug.xn--19-fia813f.xn--hdh; ; .xn--ss19-w0i.xn--hdh; [B1, B5, P1, V6, A4_2] # .ß19.≯
+‌͏。SS࣢19.≯; ‌.ss࣢19.≯; [B1, B5, C1, P1, V6]; xn--0ug.xn--ss19-w0i.xn--hdh; ; .xn--ss19-w0i.xn--hdh; [B1, B5, P1, V6, A4_2] # .ss19.≯
+‌͏。SS࣢19.≯; ‌.ss࣢19.≯; [B1, B5, C1, P1, V6]; xn--0ug.xn--ss19-w0i.xn--hdh; ; .xn--ss19-w0i.xn--hdh; [B1, B5, P1, V6, A4_2] # .ss19.≯
+‌͏。ss࣢19.≯; ‌.ss࣢19.≯; [B1, B5, C1, P1, V6]; xn--0ug.xn--ss19-w0i.xn--hdh; ; .xn--ss19-w0i.xn--hdh; [B1, B5, P1, V6, A4_2] # .ss19.≯
+‌͏。ss࣢19.≯; ‌.ss࣢19.≯; [B1, B5, C1, P1, V6]; xn--0ug.xn--ss19-w0i.xn--hdh; ; .xn--ss19-w0i.xn--hdh; [B1, B5, P1, V6, A4_2] # .ss19.≯
+‌͏。Ss࣢19.≯; ‌.ss࣢19.≯; [B1, B5, C1, P1, V6]; xn--0ug.xn--ss19-w0i.xn--hdh; ; .xn--ss19-w0i.xn--hdh; [B1, B5, P1, V6, A4_2] # .ss19.≯
+‌͏。Ss࣢19.≯; ‌.ss࣢19.≯; [B1, B5, C1, P1, V6]; xn--0ug.xn--ss19-w0i.xn--hdh; ; .xn--ss19-w0i.xn--hdh; [B1, B5, P1, V6, A4_2] # .ss19.≯
+.xn--ss19-w0i.xn--hdh; .ss࣢19.≯; [B1, B5, V6, X4_2]; .xn--ss19-w0i.xn--hdh; [B1, B5, V6, A4_2]; ; # .ss19.≯
+xn--0ug.xn--ss19-w0i.xn--hdh; ‌.ss࣢19.≯; [B1, B5, C1, V6]; xn--0ug.xn--ss19-w0i.xn--hdh; ; ; # .ss19.≯
+xn--0ug.xn--19-fia813f.xn--hdh; ‌.ß࣢19.≯; [B1, B5, C1, V6]; xn--0ug.xn--19-fia813f.xn--hdh; ; ; # .ß19.≯
+‌͏。SS࣢⒚≯; ‌.ss࣢⒚≯; [B1, B5, B6, C1, P1, V6]; xn--0ug.xn--ss-9if872xjjc; ; .xn--ss-9if872xjjc; [B5, B6, P1, V6, A4_2] # .ss⒚≯
+‌͏。SS࣢⒚≯; ‌.ss࣢⒚≯; [B1, B5, B6, C1, P1, V6]; xn--0ug.xn--ss-9if872xjjc; ; .xn--ss-9if872xjjc; [B5, B6, P1, V6, A4_2] # .ss⒚≯
+‌͏。ss࣢⒚≯; ‌.ss࣢⒚≯; [B1, B5, B6, C1, P1, V6]; xn--0ug.xn--ss-9if872xjjc; ; .xn--ss-9if872xjjc; [B5, B6, P1, V6, A4_2] # .ss⒚≯
+‌͏。ss࣢⒚≯; ‌.ss࣢⒚≯; [B1, B5, B6, C1, P1, V6]; xn--0ug.xn--ss-9if872xjjc; ; .xn--ss-9if872xjjc; [B5, B6, P1, V6, A4_2] # .ss⒚≯
+‌͏。Ss࣢⒚≯; ‌.ss࣢⒚≯; [B1, B5, B6, C1, P1, V6]; xn--0ug.xn--ss-9if872xjjc; ; .xn--ss-9if872xjjc; [B5, B6, P1, V6, A4_2] # .ss⒚≯
+‌͏。Ss࣢⒚≯; ‌.ss࣢⒚≯; [B1, B5, B6, C1, P1, V6]; xn--0ug.xn--ss-9if872xjjc; ; .xn--ss-9if872xjjc; [B5, B6, P1, V6, A4_2] # .ss⒚≯
+.xn--ss-9if872xjjc; .ss࣢⒚≯; [B5, B6, V6, X4_2]; .xn--ss-9if872xjjc; [B5, B6, V6, A4_2]; ; # .ss⒚≯
+xn--0ug.xn--ss-9if872xjjc; ‌.ss࣢⒚≯; [B1, B5, B6, C1, V6]; xn--0ug.xn--ss-9if872xjjc; ; ; # .ss⒚≯
+xn--0ug.xn--zca612bx9vo5b; ‌.ß࣢⒚≯; [B1, B5, B6, C1, V6]; xn--0ug.xn--zca612bx9vo5b; ; ; # .ß⒚≯
+‌𞥍ᡌ.𣃔; ‌𞥍ᡌ.𣃔; [B1, C1, P1, V6]; xn--c8e180bqz13b.xn--od1j; ; xn--c8e5919u.xn--od1j; [B2, B3, P1, V6] # ᡌ.𣃔
+‌𞥍ᡌ.𣃔; ; [B1, C1, P1, V6]; xn--c8e180bqz13b.xn--od1j; ; xn--c8e5919u.xn--od1j; [B2, B3, P1, V6] # ᡌ.𣃔
+xn--c8e5919u.xn--od1j; 𞥍ᡌ.𣃔; [B2, B3, V6]; xn--c8e5919u.xn--od1j; ; ; # ᡌ.𣃔
+xn--c8e180bqz13b.xn--od1j; ‌𞥍ᡌ.𣃔; [B1, C1, V6]; xn--c8e180bqz13b.xn--od1j; ; ; # ᡌ.𣃔
+ߐ򜬝-񡢬。ྠႻ𞷏𝆬; ߐ򜬝-񡢬.ྠႻ𞷏𝆬; [B1, B2, B3, P1, V5, V6]; xn----8bd11730jefvw.xn--wfd08cd265hgsxa; ; ; # ߐ-.ྠႻ𝆬
+ߐ򜬝-񡢬。ྠⴛ𞷏𝆬; ߐ򜬝-񡢬.ྠⴛ𞷏𝆬; [B1, B2, B3, P1, V5, V6]; xn----8bd11730jefvw.xn--wfd802mpm20agsxa; ; ; # ߐ-.ྠⴛ𝆬
+xn----8bd11730jefvw.xn--wfd802mpm20agsxa; ߐ򜬝-񡢬.ྠⴛ𞷏𝆬; [B1, B2, B3, V5, V6]; xn----8bd11730jefvw.xn--wfd802mpm20agsxa; ; ; # ߐ-.ྠⴛ𝆬
+xn----8bd11730jefvw.xn--wfd08cd265hgsxa; ߐ򜬝-񡢬.ྠႻ𞷏𝆬; [B1, B2, B3, V5, V6]; xn----8bd11730jefvw.xn--wfd08cd265hgsxa; ; ; # ߐ-.ྠႻ𝆬
+𝨥。⫟𑈾; 𝨥.⫟𑈾; [V5]; xn--n82h.xn--63iw010f; ; ; # 𝨥.⫟𑈾
+xn--n82h.xn--63iw010f; 𝨥.⫟𑈾; [V5]; xn--n82h.xn--63iw010f; ; ; # 𝨥.⫟𑈾
+⾛ݓ.Ⴕ𞠬؄‍; 走ݓ.Ⴕ𞠬؄‍; [B5, B6, C2, P1, V6]; xn--6ob9779d.xn--mfb785czmm0y85b; ; xn--6ob9779d.xn--mfb785ck569a; [B5, B6, P1, V6] # 走ݓ.Ⴕ𞠬
+走ݓ.Ⴕ𞠬؄‍; ; [B5, B6, C2, P1, V6]; xn--6ob9779d.xn--mfb785czmm0y85b; ; xn--6ob9779d.xn--mfb785ck569a; [B5, B6, P1, V6] # 走ݓ.Ⴕ𞠬
+走ݓ.ⴕ𞠬؄‍; ; [B5, B6, C2, P1, V6]; xn--6ob9779d.xn--mfb444k5gjt754b; ; xn--6ob9779d.xn--mfb511rxu80a; [B5, B6, P1, V6] # 走ݓ.ⴕ𞠬
+xn--6ob9779d.xn--mfb511rxu80a; 走ݓ.ⴕ𞠬؄; [B5, B6, V6]; xn--6ob9779d.xn--mfb511rxu80a; ; ; # 走ݓ.ⴕ𞠬
+xn--6ob9779d.xn--mfb444k5gjt754b; 走ݓ.ⴕ𞠬؄‍; [B5, B6, C2, V6]; xn--6ob9779d.xn--mfb444k5gjt754b; ; ; # 走ݓ.ⴕ𞠬
+xn--6ob9779d.xn--mfb785ck569a; 走ݓ.Ⴕ𞠬؄; [B5, B6, V6]; xn--6ob9779d.xn--mfb785ck569a; ; ; # 走ݓ.Ⴕ𞠬
+xn--6ob9779d.xn--mfb785czmm0y85b; 走ݓ.Ⴕ𞠬؄‍; [B5, B6, C2, V6]; xn--6ob9779d.xn--mfb785czmm0y85b; ; ; # 走ݓ.Ⴕ𞠬
+⾛ݓ.ⴕ𞠬؄‍; 走ݓ.ⴕ𞠬؄‍; [B5, B6, C2, P1, V6]; xn--6ob9779d.xn--mfb444k5gjt754b; ; xn--6ob9779d.xn--mfb511rxu80a; [B5, B6, P1, V6] # 走ݓ.ⴕ𞠬
+-ᢗ‌🄄.𑜢; ; [C1, P1, V3, V5, V6]; xn----pck312bx563c.xn--9h2d; ; xn----pck1820x.xn--9h2d; [P1, V3, V5, V6] # -ᢗ🄄.𑜢
+-ᢗ‌3,.𑜢; ; [C1, P1, V3, V5, V6]; xn---3,-3eu051c.xn--9h2d; ; xn---3,-3eu.xn--9h2d; [P1, V3, V5, V6] # -ᢗ3,.𑜢
+xn---3,-3eu.xn--9h2d; -ᢗ3,.𑜢; [P1, V3, V5, V6]; xn---3,-3eu.xn--9h2d; ; ; # -ᢗ3,.𑜢
+xn---3,-3eu051c.xn--9h2d; -ᢗ‌3,.𑜢; [C1, P1, V3, V5, V6]; xn---3,-3eu051c.xn--9h2d; ; ; # -ᢗ3,.𑜢
+xn----pck1820x.xn--9h2d; -ᢗ🄄.𑜢; [V3, V5, V6]; xn----pck1820x.xn--9h2d; ; ; # -ᢗ🄄.𑜢
+xn----pck312bx563c.xn--9h2d; -ᢗ‌🄄.𑜢; [C1, V3, V5, V6]; xn----pck312bx563c.xn--9h2d; ; ; # -ᢗ🄄.𑜢
+≠𐸁𹏁‌.Ⴚ򳄠; ; [B1, C1, P1, V6]; xn--0ug83gn618a21ov.xn--ynd49496l; ; xn--1ch2293gv3nr.xn--ynd49496l; [B1, P1, V6] # ≠.Ⴚ
+≠𐸁𹏁‌.Ⴚ򳄠; ≠𐸁𹏁‌.Ⴚ򳄠; [B1, C1, P1, V6]; xn--0ug83gn618a21ov.xn--ynd49496l; ; xn--1ch2293gv3nr.xn--ynd49496l; [B1, P1, V6] # ≠.Ⴚ
+≠𐸁𹏁‌.ⴚ򳄠; ≠𐸁𹏁‌.ⴚ򳄠; [B1, C1, P1, V6]; xn--0ug83gn618a21ov.xn--ilj23531g; ; xn--1ch2293gv3nr.xn--ilj23531g; [B1, P1, V6] # ≠.ⴚ
+≠𐸁𹏁‌.ⴚ򳄠; ; [B1, C1, P1, V6]; xn--0ug83gn618a21ov.xn--ilj23531g; ; xn--1ch2293gv3nr.xn--ilj23531g; [B1, P1, V6] # ≠.ⴚ
+xn--1ch2293gv3nr.xn--ilj23531g; ≠𐸁𹏁.ⴚ򳄠; [B1, V6]; xn--1ch2293gv3nr.xn--ilj23531g; ; ; # ≠.ⴚ
+xn--0ug83gn618a21ov.xn--ilj23531g; ≠𐸁𹏁‌.ⴚ򳄠; [B1, C1, V6]; xn--0ug83gn618a21ov.xn--ilj23531g; ; ; # ≠.ⴚ
+xn--1ch2293gv3nr.xn--ynd49496l; ≠𐸁𹏁.Ⴚ򳄠; [B1, V6]; xn--1ch2293gv3nr.xn--ynd49496l; ; ; # ≠.Ⴚ
+xn--0ug83gn618a21ov.xn--ynd49496l; ≠𐸁𹏁‌.Ⴚ򳄠; [B1, C1, V6]; xn--0ug83gn618a21ov.xn--ynd49496l; ; ; # ≠.Ⴚ
+٩。󠇀𑇊; ٩.𑇊; [B1, B3, B6, V5]; xn--iib.xn--6d1d; ; ; # ٩.𑇊
+٩。󠇀𑇊; ٩.𑇊; [B1, B3, B6, V5]; xn--iib.xn--6d1d; ; ; # ٩.𑇊
+xn--iib.xn--6d1d; ٩.𑇊; [B1, B3, B6, V5]; xn--iib.xn--6d1d; ; ; # ٩.𑇊
+ႆ𞶀≯⒍。-; ႆ𞶀≯⒍.-; [B1, P1, V3, V5, V6]; xn--hmd482gqqb8730g.-; ; ; # ႆ≯⒍.-
+ႆ𞶀≯⒍。-; ႆ𞶀≯⒍.-; [B1, P1, V3, V5, V6]; xn--hmd482gqqb8730g.-; ; ; # ႆ≯⒍.-
+ႆ𞶀≯6.。-; ႆ𞶀≯6..-; [B1, P1, V3, V5, V6, X4_2]; xn--6-oyg968k7h74b..-; [B1, P1, V3, V5, V6, A4_2]; ; # ႆ≯6..-
+ႆ𞶀≯6.。-; ႆ𞶀≯6..-; [B1, P1, V3, V5, V6, X4_2]; xn--6-oyg968k7h74b..-; [B1, P1, V3, V5, V6, A4_2]; ; # ႆ≯6..-
+xn--6-oyg968k7h74b..-; ႆ𞶀≯6..-; [B1, V3, V5, V6, X4_2]; xn--6-oyg968k7h74b..-; [B1, V3, V5, V6, A4_2]; ; # ႆ≯6..-
+xn--hmd482gqqb8730g.-; ႆ𞶀≯⒍.-; [B1, V3, V5, V6]; xn--hmd482gqqb8730g.-; ; ; # ႆ≯⒍.-
+឴.쮇-; ; [P1, V3, V5, V6]; xn--z3e.xn----938f; ; ; # .쮇-
+឴.쮇-; ឴.쮇-; [P1, V3, V5, V6]; xn--z3e.xn----938f; ; ; # .쮇-
+xn--z3e.xn----938f; ឴.쮇-; [V3, V5, V6]; xn--z3e.xn----938f; ; ; # .쮇-
+‌𑓂。⒈-􀪛; ‌𑓂.⒈-􀪛; [C1, P1, V6]; xn--0ugy057g.xn----dcp29674o; ; xn--wz1d.xn----dcp29674o; [P1, V5, V6] # 𑓂.⒈-
+‌𑓂。1.-􀪛; ‌𑓂.1.-􀪛; [C1, P1, V3, V6]; xn--0ugy057g.1.xn----rg03o; ; xn--wz1d.1.xn----rg03o; [P1, V3, V5, V6] # 𑓂.1.-
+xn--wz1d.1.xn----rg03o; 𑓂.1.-􀪛; [V3, V5, V6]; xn--wz1d.1.xn----rg03o; ; ; # 𑓂.1.-
+xn--0ugy057g.1.xn----rg03o; ‌𑓂.1.-􀪛; [C1, V3, V6]; xn--0ugy057g.1.xn----rg03o; ; ; # 𑓂.1.-
+xn--wz1d.xn----dcp29674o; 𑓂.⒈-􀪛; [V5, V6]; xn--wz1d.xn----dcp29674o; ; ; # 𑓂.⒈-
+xn--0ugy057g.xn----dcp29674o; ‌𑓂.⒈-􀪛; [C1, V6]; xn--0ugy057g.xn----dcp29674o; ; ; # 𑓂.⒈-
+⒈ﺮ‌。⃩🖞‌𖬴; ⒈ر‌.⃩🖞‌𖬴; [B1, C1, P1, V5, V6]; xn--wgb253kmfd.xn--0ugz6a8040fty5d; ; xn--wgb746m.xn--c1g6021kg18c; [B1, P1, V5, V6] # ⒈ر.⃩🖞𖬴
+1.ر‌。⃩🖞‌𖬴; 1.ر‌.⃩🖞‌𖬴; [B1, B3, C1, V5]; 1.xn--wgb253k.xn--0ugz6a8040fty5d; ; 1.xn--wgb.xn--c1g6021kg18c; [B1, V5] # 1.ر.⃩🖞𖬴
+1.xn--wgb.xn--c1g6021kg18c; 1.ر.⃩🖞𖬴; [B1, V5]; 1.xn--wgb.xn--c1g6021kg18c; ; ; # 1.ر.⃩🖞𖬴
+1.xn--wgb253k.xn--0ugz6a8040fty5d; 1.ر‌.⃩🖞‌𖬴; [B1, B3, C1, V5]; 1.xn--wgb253k.xn--0ugz6a8040fty5d; ; ; # 1.ر.⃩🖞𖬴
+xn--wgb746m.xn--c1g6021kg18c; ⒈ر.⃩🖞𖬴; [B1, V5, V6]; xn--wgb746m.xn--c1g6021kg18c; ; ; # ⒈ر.⃩🖞𖬴
+xn--wgb253kmfd.xn--0ugz6a8040fty5d; ⒈ر‌.⃩🖞‌𖬴; [B1, C1, V5, V6]; xn--wgb253kmfd.xn--0ugz6a8040fty5d; ; ; # ⒈ر.⃩🖞𖬴
+󌭇。𝟐ᮨߔ; 󌭇.2ᮨߔ; [B1, P1, V6]; xn--xm89d.xn--2-icd143m; ; ; # .2ᮨߔ
+󌭇。2ᮨߔ; 󌭇.2ᮨߔ; [B1, P1, V6]; xn--xm89d.xn--2-icd143m; ; ; # .2ᮨߔ
+xn--xm89d.xn--2-icd143m; 󌭇.2ᮨߔ; [B1, V6]; xn--xm89d.xn--2-icd143m; ; ; # .2ᮨߔ
+ﶏ򫳺.ς‍𐹷; مخم򫳺.ς‍𐹷; [B2, B3, B5, B6, C2, P1, V6]; xn--tgb9bb64691z.xn--3xa006lrp7n; ; xn--tgb9bb64691z.xn--4xa6667k; [B2, B3, B5, B6, P1, V6] # مخم.ς𐹷
+مخم򫳺.ς‍𐹷; ; [B2, B3, B5, B6, C2, P1, V6]; xn--tgb9bb64691z.xn--3xa006lrp7n; ; xn--tgb9bb64691z.xn--4xa6667k; [B2, B3, B5, B6, P1, V6] # مخم.ς𐹷
+مخم򫳺.Σ‍𐹷; مخم򫳺.σ‍𐹷; [B2, B3, B5, B6, C2, P1, V6]; xn--tgb9bb64691z.xn--4xa895lrp7n; ; xn--tgb9bb64691z.xn--4xa6667k; [B2, B3, B5, B6, P1, V6] # مخم.σ𐹷
+مخم򫳺.σ‍𐹷; ; [B2, B3, B5, B6, C2, P1, V6]; xn--tgb9bb64691z.xn--4xa895lrp7n; ; xn--tgb9bb64691z.xn--4xa6667k; [B2, B3, B5, B6, P1, V6] # مخم.σ𐹷
+xn--tgb9bb64691z.xn--4xa6667k; مخم򫳺.σ𐹷; [B2, B3, B5, B6, V6]; xn--tgb9bb64691z.xn--4xa6667k; ; ; # مخم.σ𐹷
+xn--tgb9bb64691z.xn--4xa895lrp7n; مخم򫳺.σ‍𐹷; [B2, B3, B5, B6, C2, V6]; xn--tgb9bb64691z.xn--4xa895lrp7n; ; ; # مخم.σ𐹷
+xn--tgb9bb64691z.xn--3xa006lrp7n; مخم򫳺.ς‍𐹷; [B2, B3, B5, B6, C2, V6]; xn--tgb9bb64691z.xn--3xa006lrp7n; ; ; # مخم.ς𐹷
+ﶏ򫳺.Σ‍𐹷; مخم򫳺.σ‍𐹷; [B2, B3, B5, B6, C2, P1, V6]; xn--tgb9bb64691z.xn--4xa895lrp7n; ; xn--tgb9bb64691z.xn--4xa6667k; [B2, B3, B5, B6, P1, V6] # مخم.σ𐹷
+ﶏ򫳺.σ‍𐹷; مخم򫳺.σ‍𐹷; [B2, B3, B5, B6, C2, P1, V6]; xn--tgb9bb64691z.xn--4xa895lrp7n; ; xn--tgb9bb64691z.xn--4xa6667k; [B2, B3, B5, B6, P1, V6] # مخم.σ𐹷
+⒎ہ؅。꫶۵𐇽; ⒎ہ؅.꫶۵𐇽; [B1, P1, V5, V6]; xn--nfb98ai25e.xn--imb3805fxt8b; ; ; # ⒎ہ.꫶۵𐇽
+7.ہ؅。꫶۵𐇽; 7.ہ؅.꫶۵𐇽; [B1, P1, V5, V6]; 7.xn--nfb98a.xn--imb3805fxt8b; ; ; # 7.ہ.꫶۵𐇽
+7.xn--nfb98a.xn--imb3805fxt8b; 7.ہ؅.꫶۵𐇽; [B1, V5, V6]; 7.xn--nfb98a.xn--imb3805fxt8b; ; ; # 7.ہ.꫶۵𐇽
+xn--nfb98ai25e.xn--imb3805fxt8b; ⒎ہ؅.꫶۵𐇽; [B1, V5, V6]; xn--nfb98ai25e.xn--imb3805fxt8b; ; ; # ⒎ہ.꫶۵𐇽
+-ᡥ᠆󍲭。؅ᩝ𐹡; -ᡥ᠆󍲭.؅ᩝ𐹡; [B1, P1, V3, V6]; xn----f3j6s87156i.xn--nfb035hoo2p; ; ; # -ᡥ᠆.ᩝ𐹡
+xn----f3j6s87156i.xn--nfb035hoo2p; -ᡥ᠆󍲭.؅ᩝ𐹡; [B1, V3, V6]; xn----f3j6s87156i.xn--nfb035hoo2p; ; ; # -ᡥ᠆.ᩝ𐹡
+‍.ڽ٣֖; ; [B1, C2]; xn--1ug.xn--hcb32bni; ; .xn--hcb32bni; [A4_2] # .ڽ٣֖
+.xn--hcb32bni; .ڽ٣֖; [X4_2]; .xn--hcb32bni; [A4_2]; ; # .ڽ٣֖
+xn--1ug.xn--hcb32bni; ‍.ڽ٣֖; [B1, C2]; xn--1ug.xn--hcb32bni; ; ; # .ڽ٣֖
+xn--hcb32bni; ڽ٣֖; ; xn--hcb32bni; ; ; # ڽ٣֖
+ڽ٣֖; ; ; xn--hcb32bni; ; ; # ڽ٣֖
+㒧۱.Ⴚٸ‍; 㒧۱.Ⴚيٴ‍; [B5, B6, C2, P1, V6]; xn--emb715u.xn--mhb8f817ao2p; ; xn--emb715u.xn--mhb8f817a; [B5, B6, P1, V6] # 㒧۱.Ⴚيٴ
+㒧۱.Ⴚيٴ‍; ; [B5, B6, C2, P1, V6]; xn--emb715u.xn--mhb8f817ao2p; ; xn--emb715u.xn--mhb8f817a; [B5, B6, P1, V6] # 㒧۱.Ⴚيٴ
+㒧۱.ⴚيٴ‍; ; [B5, B6, C2]; xn--emb715u.xn--mhb8f960g03l; ; xn--emb715u.xn--mhb8fy26k; [B5, B6] # 㒧۱.ⴚيٴ
+xn--emb715u.xn--mhb8fy26k; 㒧۱.ⴚيٴ; [B5, B6]; xn--emb715u.xn--mhb8fy26k; ; ; # 㒧۱.ⴚيٴ
+xn--emb715u.xn--mhb8f960g03l; 㒧۱.ⴚيٴ‍; [B5, B6, C2]; xn--emb715u.xn--mhb8f960g03l; ; ; # 㒧۱.ⴚيٴ
+xn--emb715u.xn--mhb8f817a; 㒧۱.Ⴚيٴ; [B5, B6, V6]; xn--emb715u.xn--mhb8f817a; ; ; # 㒧۱.Ⴚيٴ
+xn--emb715u.xn--mhb8f817ao2p; 㒧۱.Ⴚيٴ‍; [B5, B6, C2, V6]; xn--emb715u.xn--mhb8f817ao2p; ; ; # 㒧۱.Ⴚيٴ
+㒧۱.ⴚٸ‍; 㒧۱.ⴚيٴ‍; [B5, B6, C2]; xn--emb715u.xn--mhb8f960g03l; ; xn--emb715u.xn--mhb8fy26k; [B5, B6] # 㒧۱.ⴚيٴ
+ྔꡋ-.-𖬴; ྔꡋ-.-𖬴; [V3, V5]; xn----ukg9938i.xn----4u5m; ; ; # ྔꡋ-.-𖬴
+ྔꡋ-.-𖬴; ; [V3, V5]; xn----ukg9938i.xn----4u5m; ; ; # ྔꡋ-.-𖬴
+xn----ukg9938i.xn----4u5m; ྔꡋ-.-𖬴; [V3, V5]; xn----ukg9938i.xn----4u5m; ; ; # ྔꡋ-.-𖬴
+񿒳-⋢‌.标-; 񿒳-⋢‌.标-; [C1, P1, V3, V6]; xn----sgn90kn5663a.xn----qj7b; ; xn----9mo67451g.xn----qj7b; [P1, V3, V6] # -⋢.标-
+񿒳-⋢‌.标-; 񿒳-⋢‌.标-; [C1, P1, V3, V6]; xn----sgn90kn5663a.xn----qj7b; ; xn----9mo67451g.xn----qj7b; [P1, V3, V6] # -⋢.标-
+񿒳-⋢‌.标-; ; [C1, P1, V3, V6]; xn----sgn90kn5663a.xn----qj7b; ; xn----9mo67451g.xn----qj7b; [P1, V3, V6] # -⋢.标-
+񿒳-⋢‌.标-; 񿒳-⋢‌.标-; [C1, P1, V3, V6]; xn----sgn90kn5663a.xn----qj7b; ; xn----9mo67451g.xn----qj7b; [P1, V3, V6] # -⋢.标-
+xn----9mo67451g.xn----qj7b; 񿒳-⋢.标-; [V3, V6]; xn----9mo67451g.xn----qj7b; ; ; # -⋢.标-
+xn----sgn90kn5663a.xn----qj7b; 񿒳-⋢‌.标-; [C1, V3, V6]; xn----sgn90kn5663a.xn----qj7b; ; ; # -⋢.标-
+ٱ.ςߜ; ٱ.ςߜ; [B5, B6]; xn--qib.xn--3xa41s; ; xn--qib.xn--4xa21s; # ٱ.ςߜ
+ٱ.ςߜ; ; [B5, B6]; xn--qib.xn--3xa41s; ; xn--qib.xn--4xa21s; # ٱ.ςߜ
+ٱ.Σߜ; ٱ.σߜ; [B5, B6]; xn--qib.xn--4xa21s; ; ; # ٱ.σߜ
+ٱ.σߜ; ; [B5, B6]; xn--qib.xn--4xa21s; ; ; # ٱ.σߜ
+xn--qib.xn--4xa21s; ٱ.σߜ; [B5, B6]; xn--qib.xn--4xa21s; ; ; # ٱ.σߜ
+xn--qib.xn--3xa41s; ٱ.ςߜ; [B5, B6]; xn--qib.xn--3xa41s; ; ; # ٱ.ςߜ
+ٱ.Σߜ; ٱ.σߜ; [B5, B6]; xn--qib.xn--4xa21s; ; ; # ٱ.σߜ
+ٱ.σߜ; ٱ.σߜ; [B5, B6]; xn--qib.xn--4xa21s; ; ; # ٱ.σߜ
+񼈶؅.ࣁ‍𑑂𱼱; 񼈶؅.ࣁ‍𑑂𱼱; [B2, B3, B5, B6, C2, P1, V6]; xn--nfb17942h.xn--nzb240jv06otevq; ; xn--nfb17942h.xn--nzb6708kx3pn; [B2, B3, B5, B6, P1, V6] # .ࣁ𑑂
+񼈶؅.ࣁ‍𑑂𱼱; ; [B2, B3, B5, B6, C2, P1, V6]; xn--nfb17942h.xn--nzb240jv06otevq; ; xn--nfb17942h.xn--nzb6708kx3pn; [B2, B3, B5, B6, P1, V6] # .ࣁ𑑂
+xn--nfb17942h.xn--nzb6708kx3pn; 񼈶؅.ࣁ𑑂𱼱; [B2, B3, B5, B6, V6]; xn--nfb17942h.xn--nzb6708kx3pn; ; ; # .ࣁ𑑂
+xn--nfb17942h.xn--nzb240jv06otevq; 񼈶؅.ࣁ‍𑑂𱼱; [B2, B3, B5, B6, C2, V6]; xn--nfb17942h.xn--nzb240jv06otevq; ; ; # .ࣁ𑑂
+𐹾𐋩𞵜。᯲; 𐹾𐋩𞵜.᯲; [B1, P1, V5, V6]; xn--d97cn8rn44p.xn--0zf; ; ; # 𐹾𐋩.᯲
+𐹾𐋩𞵜。᯲; 𐹾𐋩𞵜.᯲; [B1, P1, V5, V6]; xn--d97cn8rn44p.xn--0zf; ; ; # 𐹾𐋩.᯲
+xn--d97cn8rn44p.xn--0zf; 𐹾𐋩𞵜.᯲; [B1, V5, V6]; xn--d97cn8rn44p.xn--0zf; ; ; # 𐹾𐋩.᯲
+6ᅠᰳ󠸧.򟜊锰ܬς; ; [B1, B5, P1, V6]; xn--6-5bh476ewr517a.xn--3xa16ohw6pk078g; ; xn--6-5bh476ewr517a.xn--4xa95ohw6pk078g; # 6ᰳ.锰ܬς
+6ᅠᰳ󠸧.򟜊锰ܬΣ; 6ᅠᰳ󠸧.򟜊锰ܬσ; [B1, B5, P1, V6]; xn--6-5bh476ewr517a.xn--4xa95ohw6pk078g; ; ; # 6ᰳ.锰ܬσ
+6ᅠᰳ󠸧.򟜊锰ܬσ; ; [B1, B5, P1, V6]; xn--6-5bh476ewr517a.xn--4xa95ohw6pk078g; ; ; # 6ᰳ.锰ܬσ
+xn--6-5bh476ewr517a.xn--4xa95ohw6pk078g; 6ᅠᰳ󠸧.򟜊锰ܬσ; [B1, B5, V6]; xn--6-5bh476ewr517a.xn--4xa95ohw6pk078g; ; ; # 6ᰳ.锰ܬσ
+xn--6-5bh476ewr517a.xn--3xa16ohw6pk078g; 6ᅠᰳ󠸧.򟜊锰ܬς; [B1, B5, V6]; xn--6-5bh476ewr517a.xn--3xa16ohw6pk078g; ; ; # 6ᰳ.锰ܬς
+ڳ︄񅎦𝟽。𐹽; ڳ񅎦7.𐹽; [B1, B2, P1, V6]; xn--7-yuc34665f.xn--1o0d; ; ; # ڳ7.𐹽
+ڳ︄񅎦7。𐹽; ڳ񅎦7.𐹽; [B1, B2, P1, V6]; xn--7-yuc34665f.xn--1o0d; ; ; # ڳ7.𐹽
+xn--7-yuc34665f.xn--1o0d; ڳ񅎦7.𐹽; [B1, B2, V6]; xn--7-yuc34665f.xn--1o0d; ; ; # ڳ7.𐹽
+𞮧.‌⫞; 𞮧.‌⫞; [B1, C1, P1, V6]; xn--pw6h.xn--0ug283b; ; xn--pw6h.xn--53i; [B1, P1, V6] # .⫞
+𞮧.‌⫞; ; [B1, C1, P1, V6]; xn--pw6h.xn--0ug283b; ; xn--pw6h.xn--53i; [B1, P1, V6] # .⫞
+xn--pw6h.xn--53i; 𞮧.⫞; [B1, V6]; xn--pw6h.xn--53i; ; ; # .⫞
+xn--pw6h.xn--0ug283b; 𞮧.‌⫞; [B1, C1, V6]; xn--pw6h.xn--0ug283b; ; ; # .⫞
+-񕉴.۠ᢚ-; ; [P1, V3, V5, V6]; xn----qi38c.xn----jxc827k; ; ; # -.۠ᢚ-
+xn----qi38c.xn----jxc827k; -񕉴.۠ᢚ-; [V3, V5, V6]; xn----qi38c.xn----jxc827k; ; ; # -.۠ᢚ-
+⌁‍𑄴.‌𝟩٬; ⌁‍𑄴.‌7٬; [B1, C1, C2]; xn--1ug38i2093a.xn--7-xqc297q; ; xn--nhh5394g.xn--7-xqc; [B1] # ⌁𑄴.7٬
+⌁‍𑄴.‌7٬; ; [B1, C1, C2]; xn--1ug38i2093a.xn--7-xqc297q; ; xn--nhh5394g.xn--7-xqc; [B1] # ⌁𑄴.7٬
+xn--nhh5394g.xn--7-xqc; ⌁𑄴.7٬; [B1]; xn--nhh5394g.xn--7-xqc; ; ; # ⌁𑄴.7٬
+xn--1ug38i2093a.xn--7-xqc297q; ⌁‍𑄴.‌7٬; [B1, C1, C2]; xn--1ug38i2093a.xn--7-xqc297q; ; ; # ⌁𑄴.7٬
+︒ﴅืﻼ。岓᯲󠾃ᡂ; ︒صىืلا.岓᯲󠾃ᡂ; [B1, P1, V6]; xn--mgb1a7bt462hf267a.xn--17e10qe61f9r71s; ; ; # ︒صىืلا.岓᯲ᡂ
+。صىืلا。岓᯲󠾃ᡂ; .صىืلا.岓᯲󠾃ᡂ; [P1, V6, X4_2]; .xn--mgb1a7bt462h.xn--17e10qe61f9r71s; [P1, V6, A4_2]; ; # .صىืلا.岓᯲ᡂ
+.xn--mgb1a7bt462h.xn--17e10qe61f9r71s; .صىืلا.岓᯲󠾃ᡂ; [V6, X4_2]; .xn--mgb1a7bt462h.xn--17e10qe61f9r71s; [V6, A4_2]; ; # .صىืلا.岓᯲ᡂ
+xn--mgb1a7bt462hf267a.xn--17e10qe61f9r71s; ︒صىืلا.岓᯲󠾃ᡂ; [B1, V6]; xn--mgb1a7bt462hf267a.xn--17e10qe61f9r71s; ; ; # ︒صىืلا.岓᯲ᡂ
+𐹨。8𑁆; 𐹨.8𑁆; [B1]; xn--go0d.xn--8-yu7i; ; ; # 𐹨.8𑁆
+xn--go0d.xn--8-yu7i; 𐹨.8𑁆; [B1]; xn--go0d.xn--8-yu7i; ; ; # 𐹨.8𑁆
+𞀕ൃ.ꡚࣺ𐹰ൄ; 𞀕ൃ.ꡚࣺ𐹰ൄ; [B1, B3, B5, B6, V5]; xn--mxc5210v.xn--90b01t8u2p1ltd; ; ; # 𞀕ൃ.ꡚࣺ𐹰ൄ
+𞀕ൃ.ꡚࣺ𐹰ൄ; ; [B1, B3, B5, B6, V5]; xn--mxc5210v.xn--90b01t8u2p1ltd; ; ; # 𞀕ൃ.ꡚࣺ𐹰ൄ
+xn--mxc5210v.xn--90b01t8u2p1ltd; 𞀕ൃ.ꡚࣺ𐹰ൄ; [B1, B3, B5, B6, V5]; xn--mxc5210v.xn--90b01t8u2p1ltd; ; ; # 𞀕ൃ.ꡚࣺ𐹰ൄ
+󆩏𐦹̃。󠍅; 󆩏𐦹̃.󠍅; [B1, B5, B6, P1, V6]; xn--nsa1265kp9z9e.xn--xt36e; ; ; # ̃.
+󆩏𐦹̃。󠍅; 󆩏𐦹̃.󠍅; [B1, B5, B6, P1, V6]; xn--nsa1265kp9z9e.xn--xt36e; ; ; # ̃.
+xn--nsa1265kp9z9e.xn--xt36e; 󆩏𐦹̃.󠍅; [B1, B5, B6, V6]; xn--nsa1265kp9z9e.xn--xt36e; ; ; # ̃.
+ᢌ.-࡚; ᢌ.-࡚; [V3]; xn--59e.xn----5jd; ; ; # ᢌ.-࡚
+ᢌ.-࡚; ; [V3]; xn--59e.xn----5jd; ; ; # ᢌ.-࡚
+xn--59e.xn----5jd; ᢌ.-࡚; [V3]; xn--59e.xn----5jd; ; ; # ᢌ.-࡚
+𥛛𑘶。𐹬𐲸்; 𥛛𑘶.𐹬𐲸்; [B1, P1, V6]; xn--jb2dj685c.xn--xmc5562kmcb; ; ; # 𥛛𑘶.𐹬்
+𥛛𑘶。𐹬𐲸்; 𥛛𑘶.𐹬𐲸்; [B1, P1, V6]; xn--jb2dj685c.xn--xmc5562kmcb; ; ; # 𥛛𑘶.𐹬்
+xn--jb2dj685c.xn--xmc5562kmcb; 𥛛𑘶.𐹬𐲸்; [B1, V6]; xn--jb2dj685c.xn--xmc5562kmcb; ; ; # 𥛛𑘶.𐹬்
+Ⴐݿ.‌; Ⴐݿ.‌; [B1, B5, B6, C1, P1, V6]; xn--gqb918b.xn--0ug; ; xn--gqb918b.; [B5, B6, P1, V6] # Ⴐݿ.
+Ⴐݿ.‌; ; [B1, B5, B6, C1, P1, V6]; xn--gqb918b.xn--0ug; ; xn--gqb918b.; [B5, B6, P1, V6] # Ⴐݿ.
+ⴐݿ.‌; ; [B1, B5, B6, C1]; xn--gqb743q.xn--0ug; ; xn--gqb743q.; [B5, B6] # ⴐݿ.
+xn--gqb743q.; ⴐݿ.; [B5, B6]; xn--gqb743q.; ; ; # ⴐݿ.
+xn--gqb743q.xn--0ug; ⴐݿ.‌; [B1, B5, B6, C1]; xn--gqb743q.xn--0ug; ; ; # ⴐݿ.
+xn--gqb918b.; Ⴐݿ.; [B5, B6, V6]; xn--gqb918b.; ; ; # Ⴐݿ.
+xn--gqb918b.xn--0ug; Ⴐݿ.‌; [B1, B5, B6, C1, V6]; xn--gqb918b.xn--0ug; ; ; # Ⴐݿ.
+ⴐݿ.‌; ⴐݿ.‌; [B1, B5, B6, C1]; xn--gqb743q.xn--0ug; ; xn--gqb743q.; [B5, B6] # ⴐݿ.
+🄅𑲞-⒈。‍ᠩڥ; 🄅𑲞-⒈.‍ᠩڥ; [B1, C2, P1, V6]; xn----ecp8796hjtvg.xn--7jb180gexf; ; xn----ecp8796hjtvg.xn--7jb180g; [B1, B5, B6, P1, V6] # 🄅𑲞-⒈.ᠩڥ
+4,𑲞-1.。‍ᠩڥ; 4,𑲞-1..‍ᠩڥ; [B1, C2, P1, V6, X4_2]; xn--4,-1-w401a..xn--7jb180gexf; [B1, C2, P1, V6, A4_2]; xn--4,-1-w401a..xn--7jb180g; [B1, B5, B6, P1, V6, A4_2] # 4,𑲞-1..ᠩڥ
+xn--4,-1-w401a..xn--7jb180g; 4,𑲞-1..ᠩڥ; [B1, B5, B6, P1, V6, X4_2]; xn--4,-1-w401a..xn--7jb180g; [B1, B5, B6, P1, V6, A4_2]; ; # 4,𑲞-1..ᠩڥ
+xn--4,-1-w401a..xn--7jb180gexf; 4,𑲞-1..‍ᠩڥ; [B1, C2, P1, V6, X4_2]; xn--4,-1-w401a..xn--7jb180gexf; [B1, C2, P1, V6, A4_2]; ; # 4,𑲞-1..ᠩڥ
+xn----ecp8796hjtvg.xn--7jb180g; 🄅𑲞-⒈.ᠩڥ; [B1, B5, B6, V6]; xn----ecp8796hjtvg.xn--7jb180g; ; ; # 🄅𑲞-⒈.ᠩڥ
+xn----ecp8796hjtvg.xn--7jb180gexf; 🄅𑲞-⒈.‍ᠩڥ; [B1, C2, V6]; xn----ecp8796hjtvg.xn--7jb180gexf; ; ; # 🄅𑲞-⒈.ᠩڥ
+񗀤。𞤪򮿋; 񗀤.𞤪򮿋; [B2, B3, P1, V6]; xn--4240a.xn--ie6h83808a; ; ; # .𞤪
+񗀤。𞤈򮿋; 񗀤.𞤪򮿋; [B2, B3, P1, V6]; xn--4240a.xn--ie6h83808a; ; ; # .𞤪
+xn--4240a.xn--ie6h83808a; 񗀤.𞤪򮿋; [B2, B3, V6]; xn--4240a.xn--ie6h83808a; ; ; # .𞤪
+ׁ۲。𐮊٬𝨊鄨; ׁ۲.𐮊٬𝨊鄨; [B1, B2, B3, V5]; xn--pdb42d.xn--lib6412enztdwv6h; ; ; # ׁ۲.𐮊٬𝨊鄨
+ׁ۲。𐮊٬𝨊鄨; ׁ۲.𐮊٬𝨊鄨; [B1, B2, B3, V5]; xn--pdb42d.xn--lib6412enztdwv6h; ; ; # ׁ۲.𐮊٬𝨊鄨
+xn--pdb42d.xn--lib6412enztdwv6h; ׁ۲.𐮊٬𝨊鄨; [B1, B2, B3, V5]; xn--pdb42d.xn--lib6412enztdwv6h; ; ; # ׁ۲.𐮊٬𝨊鄨
+𞭳-ꡁ。ᩩ்-; 𞭳-ꡁ.ᩩ்-; [B1, B2, B3, P1, V3, V5, V6]; xn----be4e4276f.xn----lze333i; ; ; # -ꡁ.ᩩ்-
+xn----be4e4276f.xn----lze333i; 𞭳-ꡁ.ᩩ்-; [B1, B2, B3, V3, V5, V6]; xn----be4e4276f.xn----lze333i; ; ; # -ꡁ.ᩩ்-
+္-𚮭🞢.ß; ္-𚮭🞢.ß; [P1, V5, V6]; xn----9tg11172akr8b.xn--zca; ; xn----9tg11172akr8b.ss; # ္-🞢.ß
+္-𚮭🞢.ß; ; [P1, V5, V6]; xn----9tg11172akr8b.xn--zca; ; xn----9tg11172akr8b.ss; # ္-🞢.ß
+္-𚮭🞢.SS; ္-𚮭🞢.ss; [P1, V5, V6]; xn----9tg11172akr8b.ss; ; ; # ္-🞢.ss
+္-𚮭🞢.ss; ; [P1, V5, V6]; xn----9tg11172akr8b.ss; ; ; # ္-🞢.ss
+္-𚮭🞢.Ss; ္-𚮭🞢.ss; [P1, V5, V6]; xn----9tg11172akr8b.ss; ; ; # ္-🞢.ss
+xn----9tg11172akr8b.ss; ္-𚮭🞢.ss; [V5, V6]; xn----9tg11172akr8b.ss; ; ; # ္-🞢.ss
+xn----9tg11172akr8b.xn--zca; ္-𚮭🞢.ß; [V5, V6]; xn----9tg11172akr8b.xn--zca; ; ; # ္-🞢.ß
+္-𚮭🞢.SS; ္-𚮭🞢.ss; [P1, V5, V6]; xn----9tg11172akr8b.ss; ; ; # ္-🞢.ss
+္-𚮭🞢.ss; ္-𚮭🞢.ss; [P1, V5, V6]; xn----9tg11172akr8b.ss; ; ; # ္-🞢.ss
+္-𚮭🞢.Ss; ္-𚮭🞢.ss; [P1, V5, V6]; xn----9tg11172akr8b.ss; ; ; # ္-🞢.ss
+ﳲ-‌。Ⴟ‌␣; ـَّ-‌.Ⴟ‌␣; [B3, B6, C1, P1, V6]; xn----eoc6bm0504a.xn--3nd849e05c; ; xn----eoc6bm.xn--3nd240h; [B3, B6, P1, V3, V6] # ـَّ-.Ⴟ␣
+ـَّ-‌。Ⴟ‌␣; ـَّ-‌.Ⴟ‌␣; [B3, B6, C1, P1, V6]; xn----eoc6bm0504a.xn--3nd849e05c; ; xn----eoc6bm.xn--3nd240h; [B3, B6, P1, V3, V6] # ـَّ-.Ⴟ␣
+ـَّ-‌。ⴟ‌␣; ـَّ-‌.ⴟ‌␣; [B3, B6, C1]; xn----eoc6bm0504a.xn--0ug13nd0j; ; xn----eoc6bm.xn--xph904a; [B3, B6, V3] # ـَّ-.ⴟ␣
+xn----eoc6bm.xn--xph904a; ـَّ-.ⴟ␣; [B3, B6, V3]; xn----eoc6bm.xn--xph904a; ; ; # ـَّ-.ⴟ␣
+xn----eoc6bm0504a.xn--0ug13nd0j; ـَّ-‌.ⴟ‌␣; [B3, B6, C1]; xn----eoc6bm0504a.xn--0ug13nd0j; ; ; # ـَّ-.ⴟ␣
+xn----eoc6bm.xn--3nd240h; ـَّ-.Ⴟ␣; [B3, B6, V3, V6]; xn----eoc6bm.xn--3nd240h; ; ; # ـَّ-.Ⴟ␣
+xn----eoc6bm0504a.xn--3nd849e05c; ـَّ-‌.Ⴟ‌␣; [B3, B6, C1, V6]; xn----eoc6bm0504a.xn--3nd849e05c; ; ; # ـَّ-.Ⴟ␣
+ﳲ-‌。ⴟ‌␣; ـَّ-‌.ⴟ‌␣; [B3, B6, C1]; xn----eoc6bm0504a.xn--0ug13nd0j; ; xn----eoc6bm.xn--xph904a; [B3, B6, V3] # ـَّ-.ⴟ␣
+്-‍‌。񥞧₅≠; ്-‍‌.񥞧5≠; [C1, C2, P1, V5, V6]; xn----jmf215lda.xn--5-ufo50192e; ; xn----jmf.xn--5-ufo50192e; [P1, V3, V5, V6] # ്-.5≠
+്-‍‌。񥞧₅≠; ്-‍‌.񥞧5≠; [C1, C2, P1, V5, V6]; xn----jmf215lda.xn--5-ufo50192e; ; xn----jmf.xn--5-ufo50192e; [P1, V3, V5, V6] # ്-.5≠
+്-‍‌。񥞧5≠; ്-‍‌.񥞧5≠; [C1, C2, P1, V5, V6]; xn----jmf215lda.xn--5-ufo50192e; ; xn----jmf.xn--5-ufo50192e; [P1, V3, V5, V6] # ്-.5≠
+്-‍‌。񥞧5≠; ്-‍‌.񥞧5≠; [C1, C2, P1, V5, V6]; xn----jmf215lda.xn--5-ufo50192e; ; xn----jmf.xn--5-ufo50192e; [P1, V3, V5, V6] # ്-.5≠
+xn----jmf.xn--5-ufo50192e; ്-.񥞧5≠; [V3, V5, V6]; xn----jmf.xn--5-ufo50192e; ; ; # ്-.5≠
+xn----jmf215lda.xn--5-ufo50192e; ്-‍‌.񥞧5≠; [C1, C2, V5, V6]; xn----jmf215lda.xn--5-ufo50192e; ; ; # ്-.5≠
+锣。੍󠘻󠚆; 锣.੍󠘻󠚆; [P1, V5, V6]; xn--gc5a.xn--ybc83044ppga; ; ; # 锣.੍
+xn--gc5a.xn--ybc83044ppga; 锣.੍󠘻󠚆; [V5, V6]; xn--gc5a.xn--ybc83044ppga; ; ; # 锣.੍
+ؽ𑈾.ى‍꤫; ؽ𑈾.ى‍꤫; [B3, C2]; xn--8gb2338k.xn--lhb603k060h; ; xn--8gb2338k.xn--lhb0154f; [] # ؽ𑈾.ى꤫
+ؽ𑈾.ى‍꤫; ; [B3, C2]; xn--8gb2338k.xn--lhb603k060h; ; xn--8gb2338k.xn--lhb0154f; [] # ؽ𑈾.ى꤫
+xn--8gb2338k.xn--lhb0154f; ؽ𑈾.ى꤫; ; xn--8gb2338k.xn--lhb0154f; ; ; # ؽ𑈾.ى꤫
+ؽ𑈾.ى꤫; ; ; xn--8gb2338k.xn--lhb0154f; ; ; # ؽ𑈾.ى꤫
+xn--8gb2338k.xn--lhb603k060h; ؽ𑈾.ى‍꤫; [B3, C2]; xn--8gb2338k.xn--lhb603k060h; ; ; # ؽ𑈾.ى꤫
+٦⁴Ⴅ.ࢽ‌; ٦4Ⴅ.ࢽ‌; [B1, B3, C1, P1, V6]; xn--4-kqc489e.xn--jzb840j; ; xn--4-kqc489e.xn--jzb; [B1, P1, V6] # ٦4Ⴅ.ࢽ
+٦4Ⴅ.ࢽ‌; ; [B1, B3, C1, P1, V6]; xn--4-kqc489e.xn--jzb840j; ; xn--4-kqc489e.xn--jzb; [B1, P1, V6] # ٦4Ⴅ.ࢽ
+٦4ⴅ.ࢽ‌; ; [B1, B3, C1]; xn--4-kqc6770a.xn--jzb840j; ; xn--4-kqc6770a.xn--jzb; [B1] # ٦4ⴅ.ࢽ
+xn--4-kqc6770a.xn--jzb; ٦4ⴅ.ࢽ; [B1]; xn--4-kqc6770a.xn--jzb; ; ; # ٦4ⴅ.ࢽ
+xn--4-kqc6770a.xn--jzb840j; ٦4ⴅ.ࢽ‌; [B1, B3, C1]; xn--4-kqc6770a.xn--jzb840j; ; ; # ٦4ⴅ.ࢽ
+xn--4-kqc489e.xn--jzb; ٦4Ⴅ.ࢽ; [B1, V6]; xn--4-kqc489e.xn--jzb; ; ; # ٦4Ⴅ.ࢽ
+xn--4-kqc489e.xn--jzb840j; ٦4Ⴅ.ࢽ‌; [B1, B3, C1, V6]; xn--4-kqc489e.xn--jzb840j; ; ; # ٦4Ⴅ.ࢽ
+٦⁴ⴅ.ࢽ‌; ٦4ⴅ.ࢽ‌; [B1, B3, C1]; xn--4-kqc6770a.xn--jzb840j; ; xn--4-kqc6770a.xn--jzb; [B1] # ٦4ⴅ.ࢽ
+ჁႱ6̘。ßᬃ; ჁႱ6̘.ßᬃ; [P1, V6]; xn--6-8cb555h2b.xn--zca894k; ; xn--6-8cb555h2b.xn--ss-2vq; # ჁႱ6̘.ßᬃ
+ⴡⴑ6̘。ßᬃ; ⴡⴑ6̘.ßᬃ; ; xn--6-8cb7433a2ba.xn--zca894k; ; xn--6-8cb7433a2ba.xn--ss-2vq; # ⴡⴑ6̘.ßᬃ
+ჁႱ6̘。SSᬃ; ჁႱ6̘.ssᬃ; [P1, V6]; xn--6-8cb555h2b.xn--ss-2vq; ; ; # ჁႱ6̘.ssᬃ
+ⴡⴑ6̘。ssᬃ; ⴡⴑ6̘.ssᬃ; ; xn--6-8cb7433a2ba.xn--ss-2vq; ; ; # ⴡⴑ6̘.ssᬃ
+Ⴡⴑ6̘。Ssᬃ; Ⴡⴑ6̘.ssᬃ; [P1, V6]; xn--6-8cb306hms1a.xn--ss-2vq; ; ; # Ⴡⴑ6̘.ssᬃ
+xn--6-8cb306hms1a.xn--ss-2vq; Ⴡⴑ6̘.ssᬃ; [V6]; xn--6-8cb306hms1a.xn--ss-2vq; ; ; # Ⴡⴑ6̘.ssᬃ
+xn--6-8cb7433a2ba.xn--ss-2vq; ⴡⴑ6̘.ssᬃ; ; xn--6-8cb7433a2ba.xn--ss-2vq; ; ; # ⴡⴑ6̘.ssᬃ
+ⴡⴑ6̘.ssᬃ; ; ; xn--6-8cb7433a2ba.xn--ss-2vq; ; ; # ⴡⴑ6̘.ssᬃ
+ჁႱ6̘.SSᬃ; ჁႱ6̘.ssᬃ; [P1, V6]; xn--6-8cb555h2b.xn--ss-2vq; ; ; # ჁႱ6̘.ssᬃ
+Ⴡⴑ6̘.Ssᬃ; Ⴡⴑ6̘.ssᬃ; [P1, V6]; xn--6-8cb306hms1a.xn--ss-2vq; ; ; # Ⴡⴑ6̘.ssᬃ
+xn--6-8cb555h2b.xn--ss-2vq; ჁႱ6̘.ssᬃ; [V6]; xn--6-8cb555h2b.xn--ss-2vq; ; ; # ჁႱ6̘.ssᬃ
+xn--6-8cb7433a2ba.xn--zca894k; ⴡⴑ6̘.ßᬃ; ; xn--6-8cb7433a2ba.xn--zca894k; ; ; # ⴡⴑ6̘.ßᬃ
+ⴡⴑ6̘.ßᬃ; ; ; xn--6-8cb7433a2ba.xn--zca894k; ; xn--6-8cb7433a2ba.xn--ss-2vq; # ⴡⴑ6̘.ßᬃ
+xn--6-8cb555h2b.xn--zca894k; ჁႱ6̘.ßᬃ; [V6]; xn--6-8cb555h2b.xn--zca894k; ; ; # ჁႱ6̘.ßᬃ
+򋡐。≯𑋪; 򋡐.≯𑋪; [P1, V6]; xn--eo08b.xn--hdh3385g; ; ; # .≯𑋪
+򋡐。≯𑋪; 򋡐.≯𑋪; [P1, V6]; xn--eo08b.xn--hdh3385g; ; ; # .≯𑋪
+򋡐。≯𑋪; 򋡐.≯𑋪; [P1, V6]; xn--eo08b.xn--hdh3385g; ; ; # .≯𑋪
+򋡐。≯𑋪; 򋡐.≯𑋪; [P1, V6]; xn--eo08b.xn--hdh3385g; ; ; # .≯𑋪
+xn--eo08b.xn--hdh3385g; 򋡐.≯𑋪; [V6]; xn--eo08b.xn--hdh3385g; ; ; # .≯𑋪
+ٚ۲。‌-᯳࣢; ٚ۲.‌-᯳࣢; [B1, C1, P1, V5, V6]; xn--2hb81a.xn----xrd657l30d; ; xn--2hb81a.xn----xrd657l; [B1, P1, V3, V5, V6] # ٚ۲.-᯳
+xn--2hb81a.xn----xrd657l; ٚ۲.-᯳࣢; [B1, V3, V5, V6]; xn--2hb81a.xn----xrd657l; ; ; # ٚ۲.-᯳
+xn--2hb81a.xn----xrd657l30d; ٚ۲.‌-᯳࣢; [B1, C1, V5, V6]; xn--2hb81a.xn----xrd657l30d; ; ; # ٚ۲.-᯳
+󠄏𖬴󠲽。ᅠ; 𖬴󠲽.ᅠ; [P1, V5, V6]; xn--619ep9154c.xn--cl7c; ; ; # 𖬴.
+󠄏𖬴󠲽。ᅠ; 𖬴󠲽.ᅠ; [P1, V5, V6]; xn--619ep9154c.xn--psd; ; ; # 𖬴.
+xn--619ep9154c.xn--psd; 𖬴󠲽.ᅠ; [V5, V6]; xn--619ep9154c.xn--psd; ; ; # 𖬴.
+xn--619ep9154c.xn--cl7c; 𖬴󠲽.ᅠ; [V5, V6]; xn--619ep9154c.xn--cl7c; ; ; # 𖬴.
+ß⒈ݠ힮.􉖲󠅄؅򉔯; ß⒈ݠ힮.􉖲؅򉔯; [B5, P1, V6]; xn--zca444a0s1ao12n.xn--nfb09923ifkyyb; ; xn--ss-6ke9690a0g1q.xn--nfb09923ifkyyb; # ß⒈ݠ.
+ß1.ݠ힮.􉖲󠅄؅򉔯; ß1.ݠ힮.􉖲؅򉔯; [B2, B3, B5, P1, V6]; xn--1-pfa.xn--kpb6677h.xn--nfb09923ifkyyb; ; ss1.xn--kpb6677h.xn--nfb09923ifkyyb; # ß1.ݠ.
+SS1.ݠ힮.􉖲󠅄؅򉔯; ss1.ݠ힮.􉖲؅򉔯; [B2, B3, B5, P1, V6]; ss1.xn--kpb6677h.xn--nfb09923ifkyyb; ; ; # ss1.ݠ.
+ss1.ݠ힮.􉖲󠅄؅򉔯; ss1.ݠ힮.􉖲؅򉔯; [B2, B3, B5, P1, V6]; ss1.xn--kpb6677h.xn--nfb09923ifkyyb; ; ; # ss1.ݠ.
+Ss1.ݠ힮.􉖲󠅄؅򉔯; ss1.ݠ힮.􉖲؅򉔯; [B2, B3, B5, P1, V6]; ss1.xn--kpb6677h.xn--nfb09923ifkyyb; ; ; # ss1.ݠ.
+ss1.xn--kpb6677h.xn--nfb09923ifkyyb; ss1.ݠ힮.􉖲؅򉔯; [B2, B3, B5, V6]; ss1.xn--kpb6677h.xn--nfb09923ifkyyb; ; ; # ss1.ݠ.
+xn--1-pfa.xn--kpb6677h.xn--nfb09923ifkyyb; ß1.ݠ힮.􉖲؅򉔯; [B2, B3, B5, V6]; xn--1-pfa.xn--kpb6677h.xn--nfb09923ifkyyb; ; ; # ß1.ݠ.
+SS⒈ݠ힮.􉖲󠅄؅򉔯; ss⒈ݠ힮.􉖲؅򉔯; [B5, P1, V6]; xn--ss-6ke9690a0g1q.xn--nfb09923ifkyyb; ; ; # ss⒈ݠ.
+ss⒈ݠ힮.􉖲󠅄؅򉔯; ss⒈ݠ힮.􉖲؅򉔯; [B5, P1, V6]; xn--ss-6ke9690a0g1q.xn--nfb09923ifkyyb; ; ; # ss⒈ݠ.
+Ss⒈ݠ힮.􉖲󠅄؅򉔯; ss⒈ݠ힮.􉖲؅򉔯; [B5, P1, V6]; xn--ss-6ke9690a0g1q.xn--nfb09923ifkyyb; ; ; # ss⒈ݠ.
+xn--ss-6ke9690a0g1q.xn--nfb09923ifkyyb; ss⒈ݠ힮.􉖲؅򉔯; [B5, V6]; xn--ss-6ke9690a0g1q.xn--nfb09923ifkyyb; ; ; # ss⒈ݠ.
+xn--zca444a0s1ao12n.xn--nfb09923ifkyyb; ß⒈ݠ힮.􉖲؅򉔯; [B5, V6]; xn--zca444a0s1ao12n.xn--nfb09923ifkyyb; ; ; # ß⒈ݠ.
+󠭔.𐋱₂; 󠭔.𐋱2; [P1, V6]; xn--vi56e.xn--2-w91i; ; ; # .𐋱2
+󠭔.𐋱2; ; [P1, V6]; xn--vi56e.xn--2-w91i; ; ; # .𐋱2
+xn--vi56e.xn--2-w91i; 󠭔.𐋱2; [V6]; xn--vi56e.xn--2-w91i; ; ; # .𐋱2
+ܖे。-ßڥ‌; ܖे.-ßڥ‌; [B1, C1, V3]; xn--gnb63i.xn----qfa845bhx4a; ; xn--gnb63i.xn---ss-4ef; [B1, V3] # ܖे.-ßڥ
+ܖे。-SSڥ‌; ܖे.-ssڥ‌; [B1, C1, V3]; xn--gnb63i.xn---ss-4ef9263a; ; xn--gnb63i.xn---ss-4ef; [B1, V3] # ܖे.-ssڥ
+ܖे。-ssڥ‌; ܖे.-ssڥ‌; [B1, C1, V3]; xn--gnb63i.xn---ss-4ef9263a; ; xn--gnb63i.xn---ss-4ef; [B1, V3] # ܖे.-ssڥ
+ܖे。-Ssڥ‌; ܖे.-ssڥ‌; [B1, C1, V3]; xn--gnb63i.xn---ss-4ef9263a; ; xn--gnb63i.xn---ss-4ef; [B1, V3] # ܖे.-ssڥ
+xn--gnb63i.xn---ss-4ef; ܖे.-ssڥ; [B1, V3]; xn--gnb63i.xn---ss-4ef; ; ; # ܖे.-ssڥ
+xn--gnb63i.xn---ss-4ef9263a; ܖे.-ssڥ‌; [B1, C1, V3]; xn--gnb63i.xn---ss-4ef9263a; ; ; # ܖे.-ssڥ
+xn--gnb63i.xn----qfa845bhx4a; ܖे.-ßڥ‌; [B1, C1, V3]; xn--gnb63i.xn----qfa845bhx4a; ; ; # ܖे.-ßڥ
+ᮩ‍ت񡚈.᳕䷉Ⴡ; ᮩ‍ت񡚈.᳕䷉Ⴡ; [B1, C2, P1, V5, V6]; xn--pgb911imgdrw34r.xn--5nd792dgv3b; ; xn--pgb911izv33i.xn--5nd792dgv3b; [B1, P1, V5, V6] # ᮩت.᳕䷉Ⴡ
+ᮩ‍ت񡚈.᳕䷉Ⴡ; ; [B1, C2, P1, V5, V6]; xn--pgb911imgdrw34r.xn--5nd792dgv3b; ; xn--pgb911izv33i.xn--5nd792dgv3b; [B1, P1, V5, V6] # ᮩت.᳕䷉Ⴡ
+ᮩ‍ت񡚈.᳕䷉ⴡ; ; [B1, C2, P1, V5, V6]; xn--pgb911imgdrw34r.xn--i6f270etuy; ; xn--pgb911izv33i.xn--i6f270etuy; [B1, P1, V5, V6] # ᮩت.᳕䷉ⴡ
+xn--pgb911izv33i.xn--i6f270etuy; ᮩت񡚈.᳕䷉ⴡ; [B1, V5, V6]; xn--pgb911izv33i.xn--i6f270etuy; ; ; # ᮩت.᳕䷉ⴡ
+xn--pgb911imgdrw34r.xn--i6f270etuy; ᮩ‍ت񡚈.᳕䷉ⴡ; [B1, C2, V5, V6]; xn--pgb911imgdrw34r.xn--i6f270etuy; ; ; # ᮩت.᳕䷉ⴡ
+xn--pgb911izv33i.xn--5nd792dgv3b; ᮩت񡚈.᳕䷉Ⴡ; [B1, V5, V6]; xn--pgb911izv33i.xn--5nd792dgv3b; ; ; # ᮩت.᳕䷉Ⴡ
+xn--pgb911imgdrw34r.xn--5nd792dgv3b; ᮩ‍ت񡚈.᳕䷉Ⴡ; [B1, C2, V5, V6]; xn--pgb911imgdrw34r.xn--5nd792dgv3b; ; ; # ᮩت.᳕䷉Ⴡ
+ᮩ‍ت񡚈.᳕䷉ⴡ; ᮩ‍ت񡚈.᳕䷉ⴡ; [B1, C2, P1, V5, V6]; xn--pgb911imgdrw34r.xn--i6f270etuy; ; xn--pgb911izv33i.xn--i6f270etuy; [B1, P1, V5, V6] # ᮩت.᳕䷉ⴡ
+⶿.ß‍; ; [C2, P1, V6]; xn--7pj.xn--zca870n; ; xn--7pj.ss; [P1, V6] # .ß
+⶿.SS‍; ⶿.ss‍; [C2, P1, V6]; xn--7pj.xn--ss-n1t; ; xn--7pj.ss; [P1, V6] # .ss
+⶿.ss‍; ; [C2, P1, V6]; xn--7pj.xn--ss-n1t; ; xn--7pj.ss; [P1, V6] # .ss
+⶿.Ss‍; ⶿.ss‍; [C2, P1, V6]; xn--7pj.xn--ss-n1t; ; xn--7pj.ss; [P1, V6] # .ss
+xn--7pj.ss; ⶿.ss; [V6]; xn--7pj.ss; ; ; # .ss
+xn--7pj.xn--ss-n1t; ⶿.ss‍; [C2, V6]; xn--7pj.xn--ss-n1t; ; ; # .ss
+xn--7pj.xn--zca870n; ⶿.ß‍; [C2, V6]; xn--7pj.xn--zca870n; ; ; # .ß
+᯳︒.ت≯ꡂ; ; [B2, B3, B6, P1, V5, V6]; xn--1zf8957g.xn--pgb885lry5g; ; ; # ᯳︒.ت≯ꡂ
+᯳︒.ت≯ꡂ; ᯳︒.ت≯ꡂ; [B2, B3, B6, P1, V5, V6]; xn--1zf8957g.xn--pgb885lry5g; ; ; # ᯳︒.ت≯ꡂ
+᯳。.ت≯ꡂ; ᯳..ت≯ꡂ; [B2, B3, P1, V5, V6, X4_2]; xn--1zf..xn--pgb885lry5g; [B2, B3, P1, V5, V6, A4_2]; ; # ᯳..ت≯ꡂ
+᯳。.ت≯ꡂ; ᯳..ت≯ꡂ; [B2, B3, P1, V5, V6, X4_2]; xn--1zf..xn--pgb885lry5g; [B2, B3, P1, V5, V6, A4_2]; ; # ᯳..ت≯ꡂ
+xn--1zf..xn--pgb885lry5g; ᯳..ت≯ꡂ; [B2, B3, V5, V6, X4_2]; xn--1zf..xn--pgb885lry5g; [B2, B3, V5, V6, A4_2]; ; # ᯳..ت≯ꡂ
+xn--1zf8957g.xn--pgb885lry5g; ᯳︒.ت≯ꡂ; [B2, B3, B6, V5, V6]; xn--1zf8957g.xn--pgb885lry5g; ; ; # ᯳︒.ت≯ꡂ
+≮≠񏻃。-𫠆ڷ𐹪; ≮≠񏻃.-𫠆ڷ𐹪; [B1, P1, V3, V6]; xn--1ch1a29470f.xn----7uc5363rc1rn; ; ; # ≮≠.-𫠆ڷ𐹪
+≮≠񏻃。-𫠆ڷ𐹪; ≮≠񏻃.-𫠆ڷ𐹪; [B1, P1, V3, V6]; xn--1ch1a29470f.xn----7uc5363rc1rn; ; ; # ≮≠.-𫠆ڷ𐹪
+≮≠񏻃。-𫠆ڷ𐹪; ≮≠񏻃.-𫠆ڷ𐹪; [B1, P1, V3, V6]; xn--1ch1a29470f.xn----7uc5363rc1rn; ; ; # ≮≠.-𫠆ڷ𐹪
+≮≠񏻃。-𫠆ڷ𐹪; ≮≠񏻃.-𫠆ڷ𐹪; [B1, P1, V3, V6]; xn--1ch1a29470f.xn----7uc5363rc1rn; ; ; # ≮≠.-𫠆ڷ𐹪
+xn--1ch1a29470f.xn----7uc5363rc1rn; ≮≠񏻃.-𫠆ڷ𐹪; [B1, V3, V6]; xn--1ch1a29470f.xn----7uc5363rc1rn; ; ; # ≮≠.-𫠆ڷ𐹪
+𐹡ݷ。ꡂ; 𐹡ݷ.ꡂ; [B1]; xn--7pb5275k.xn--bc9a; ; ; # 𐹡ݷ.ꡂ
+xn--7pb5275k.xn--bc9a; 𐹡ݷ.ꡂ; [B1]; xn--7pb5275k.xn--bc9a; ; ; # 𐹡ݷ.ꡂ
+Ⴉ𝆅񔻅ؙ.ß𐧦𐹳ݵ; ; [B5, B6, P1, V6]; xn--7fb125cjv87a7xvz.xn--zca684a699vf2d; ; xn--7fb125cjv87a7xvz.xn--ss-zme7575xp0e; # Ⴉؙ𝆅.ß𐧦𐹳ݵ
+ⴉ𝆅񔻅ؙ.ß𐧦𐹳ݵ; ; [B5, B6, P1, V6]; xn--7fb940rwt3z7xvz.xn--zca684a699vf2d; ; xn--7fb940rwt3z7xvz.xn--ss-zme7575xp0e; # ⴉؙ𝆅.ß𐧦𐹳ݵ
+Ⴉ𝆅񔻅ؙ.SS𐧦𐹳ݵ; Ⴉ𝆅񔻅ؙ.ss𐧦𐹳ݵ; [B5, B6, P1, V6]; xn--7fb125cjv87a7xvz.xn--ss-zme7575xp0e; ; ; # Ⴉؙ𝆅.ss𐧦𐹳ݵ
+ⴉ𝆅񔻅ؙ.ss𐧦𐹳ݵ; ; [B5, B6, P1, V6]; xn--7fb940rwt3z7xvz.xn--ss-zme7575xp0e; ; ; # ⴉؙ𝆅.ss𐧦𐹳ݵ
+Ⴉ𝆅񔻅ؙ.Ss𐧦𐹳ݵ; Ⴉ𝆅񔻅ؙ.ss𐧦𐹳ݵ; [B5, B6, P1, V6]; xn--7fb125cjv87a7xvz.xn--ss-zme7575xp0e; ; ; # Ⴉؙ𝆅.ss𐧦𐹳ݵ
+xn--7fb125cjv87a7xvz.xn--ss-zme7575xp0e; Ⴉ𝆅񔻅ؙ.ss𐧦𐹳ݵ; [B5, B6, V6]; xn--7fb125cjv87a7xvz.xn--ss-zme7575xp0e; ; ; # Ⴉؙ𝆅.ss𐧦𐹳ݵ
+xn--7fb940rwt3z7xvz.xn--ss-zme7575xp0e; ⴉ𝆅񔻅ؙ.ss𐧦𐹳ݵ; [B5, B6, V6]; xn--7fb940rwt3z7xvz.xn--ss-zme7575xp0e; ; ; # ⴉؙ𝆅.ss𐧦𐹳ݵ
+xn--7fb940rwt3z7xvz.xn--zca684a699vf2d; ⴉ𝆅񔻅ؙ.ß𐧦𐹳ݵ; [B5, B6, V6]; xn--7fb940rwt3z7xvz.xn--zca684a699vf2d; ; ; # ⴉؙ𝆅.ß𐧦𐹳ݵ
+xn--7fb125cjv87a7xvz.xn--zca684a699vf2d; Ⴉ𝆅񔻅ؙ.ß𐧦𐹳ݵ; [B5, B6, V6]; xn--7fb125cjv87a7xvz.xn--zca684a699vf2d; ; ; # Ⴉؙ𝆅.ß𐧦𐹳ݵ
+‍ك𐧾↙.񊽡; ; [B1, C2, P1, V6]; xn--fhb713k87ag053c.xn--7s4w; ; xn--fhb011lnp8n.xn--7s4w; [B3, P1, V6] # ك𐧾↙.
+xn--fhb011lnp8n.xn--7s4w; ك𐧾↙.񊽡; [B3, V6]; xn--fhb011lnp8n.xn--7s4w; ; ; # ك𐧾↙.
+xn--fhb713k87ag053c.xn--7s4w; ‍ك𐧾↙.񊽡; [B1, C2, V6]; xn--fhb713k87ag053c.xn--7s4w; ; ; # ك𐧾↙.
+梉。‌; 梉.‌; [C1]; xn--7zv.xn--0ug; ; xn--7zv.; [] # 梉.
+xn--7zv.; 梉.; ; xn--7zv.; ; ; # 梉.
+梉.; ; ; xn--7zv.; ; ; # 梉.
+xn--7zv.xn--0ug; 梉.‌; [C1]; xn--7zv.xn--0ug; ; ; # 梉.
+ꡣ-≠.‍𞤗𐅢Ↄ; ꡣ-≠.‍𞤹𐅢Ↄ; [B1, B6, C2, P1, V6]; xn----ufo9661d.xn--1ug79cm620c71sh; ; xn----ufo9661d.xn--q5g0929fhm4f; [B2, B3, B6, P1, V6] # ꡣ-≠.𞤹𐅢Ↄ
+ꡣ-≠.‍𞤗𐅢Ↄ; ꡣ-≠.‍𞤹𐅢Ↄ; [B1, B6, C2, P1, V6]; xn----ufo9661d.xn--1ug79cm620c71sh; ; xn----ufo9661d.xn--q5g0929fhm4f; [B2, B3, B6, P1, V6] # ꡣ-≠.𞤹𐅢Ↄ
+ꡣ-≠.‍𞤹𐅢ↄ; ꡣ-≠.‍𞤹𐅢ↄ; [B1, B6, C2, P1, V6]; xn----ufo9661d.xn--1ug99cj620c71sh; ; xn----ufo9661d.xn--r5gy929fhm4f; [B2, B3, B6, P1, V6] # ꡣ-≠.𞤹𐅢ↄ
+ꡣ-≠.‍𞤹𐅢ↄ; ; [B1, B6, C2, P1, V6]; xn----ufo9661d.xn--1ug99cj620c71sh; ; xn----ufo9661d.xn--r5gy929fhm4f; [B2, B3, B6, P1, V6] # ꡣ-≠.𞤹𐅢ↄ
+ꡣ-≠.‍𞤗𐅢ↄ; ꡣ-≠.‍𞤹𐅢ↄ; [B1, B6, C2, P1, V6]; xn----ufo9661d.xn--1ug99cj620c71sh; ; xn----ufo9661d.xn--r5gy929fhm4f; [B2, B3, B6, P1, V6] # ꡣ-≠.𞤹𐅢ↄ
+ꡣ-≠.‍𞤗𐅢ↄ; ꡣ-≠.‍𞤹𐅢ↄ; [B1, B6, C2, P1, V6]; xn----ufo9661d.xn--1ug99cj620c71sh; ; xn----ufo9661d.xn--r5gy929fhm4f; [B2, B3, B6, P1, V6] # ꡣ-≠.𞤹𐅢ↄ
+xn----ufo9661d.xn--r5gy929fhm4f; ꡣ-≠.𞤹𐅢ↄ; [B2, B3, B6, V6]; xn----ufo9661d.xn--r5gy929fhm4f; ; ; # ꡣ-≠.𞤹𐅢ↄ
+xn----ufo9661d.xn--1ug99cj620c71sh; ꡣ-≠.‍𞤹𐅢ↄ; [B1, B6, C2, V6]; xn----ufo9661d.xn--1ug99cj620c71sh; ; ; # ꡣ-≠.𞤹𐅢ↄ
+xn----ufo9661d.xn--q5g0929fhm4f; ꡣ-≠.𞤹𐅢Ↄ; [B2, B3, B6, V6]; xn----ufo9661d.xn--q5g0929fhm4f; ; ; # ꡣ-≠.𞤹𐅢Ↄ
+xn----ufo9661d.xn--1ug79cm620c71sh; ꡣ-≠.‍𞤹𐅢Ↄ; [B1, B6, C2, V6]; xn----ufo9661d.xn--1ug79cm620c71sh; ; ; # ꡣ-≠.𞤹𐅢Ↄ
+ς⒐𝆫⸵。𐱢🄊𝟳; ς⒐𝆫⸵.𐱢🄊7; [B6, P1, V6]; xn--3xa019nwtghi25b.xn--7-075iy877c; ; xn--4xa809nwtghi25b.xn--7-075iy877c; # ς⒐𝆫⸵.🄊7
+ς9.𝆫⸵。𐱢9,7; ς9.𝆫⸵.𐱢9,7; [B1, P1, V5, V6]; xn--9-xmb.xn--ltj1535k.xn--9,7-r67t; ; xn--9-zmb.xn--ltj1535k.xn--9,7-r67t; # ς9.𝆫⸵.9,7
+Σ9.𝆫⸵。𐱢9,7; σ9.𝆫⸵.𐱢9,7; [B1, P1, V5, V6]; xn--9-zmb.xn--ltj1535k.xn--9,7-r67t; ; ; # σ9.𝆫⸵.9,7
+σ9.𝆫⸵。𐱢9,7; σ9.𝆫⸵.𐱢9,7; [B1, P1, V5, V6]; xn--9-zmb.xn--ltj1535k.xn--9,7-r67t; ; ; # σ9.𝆫⸵.9,7
+xn--9-zmb.xn--ltj1535k.xn--9,7-r67t; σ9.𝆫⸵.𐱢9,7; [B1, P1, V5, V6]; xn--9-zmb.xn--ltj1535k.xn--9,7-r67t; ; ; # σ9.𝆫⸵.9,7
+xn--9-xmb.xn--ltj1535k.xn--9,7-r67t; ς9.𝆫⸵.𐱢9,7; [B1, P1, V5, V6]; xn--9-xmb.xn--ltj1535k.xn--9,7-r67t; ; ; # ς9.𝆫⸵.9,7
+Σ⒐𝆫⸵。𐱢🄊𝟳; σ⒐𝆫⸵.𐱢🄊7; [B6, P1, V6]; xn--4xa809nwtghi25b.xn--7-075iy877c; ; ; # σ⒐𝆫⸵.🄊7
+σ⒐𝆫⸵。𐱢🄊𝟳; σ⒐𝆫⸵.𐱢🄊7; [B6, P1, V6]; xn--4xa809nwtghi25b.xn--7-075iy877c; ; ; # σ⒐𝆫⸵.🄊7
+xn--4xa809nwtghi25b.xn--7-075iy877c; σ⒐𝆫⸵.𐱢🄊7; [B6, V6]; xn--4xa809nwtghi25b.xn--7-075iy877c; ; ; # σ⒐𝆫⸵.🄊7
+xn--3xa019nwtghi25b.xn--7-075iy877c; ς⒐𝆫⸵.𐱢🄊7; [B6, V6]; xn--3xa019nwtghi25b.xn--7-075iy877c; ; ; # ς⒐𝆫⸵.🄊7
+ࡓ.‌ß; ࡓ.‌ß; [B1, C1]; xn--iwb.xn--zca570n; ; xn--iwb.ss; [] # ࡓ.ß
+ࡓ.‌ß; ; [B1, C1]; xn--iwb.xn--zca570n; ; xn--iwb.ss; [] # ࡓ.ß
+ࡓ.‌SS; ࡓ.‌ss; [B1, C1]; xn--iwb.xn--ss-i1t; ; xn--iwb.ss; [] # ࡓ.ss
+ࡓ.‌ss; ; [B1, C1]; xn--iwb.xn--ss-i1t; ; xn--iwb.ss; [] # ࡓ.ss
+xn--iwb.ss; ࡓ.ss; ; xn--iwb.ss; ; ; # ࡓ.ss
+ࡓ.ss; ; ; xn--iwb.ss; ; ; # ࡓ.ss
+ࡓ.SS; ࡓ.ss; ; xn--iwb.ss; ; ; # ࡓ.ss
+xn--iwb.xn--ss-i1t; ࡓ.‌ss; [B1, C1]; xn--iwb.xn--ss-i1t; ; ; # ࡓ.ss
+xn--iwb.xn--zca570n; ࡓ.‌ß; [B1, C1]; xn--iwb.xn--zca570n; ; ; # ࡓ.ß
+ࡓ.‌SS; ࡓ.‌ss; [B1, C1]; xn--iwb.xn--ss-i1t; ; xn--iwb.ss; [] # ࡓ.ss
+ࡓ.‌ss; ࡓ.‌ss; [B1, C1]; xn--iwb.xn--ss-i1t; ; xn--iwb.ss; [] # ࡓ.ss
+ࡓ.‌Ss; ࡓ.‌ss; [B1, C1]; xn--iwb.xn--ss-i1t; ; xn--iwb.ss; [] # ࡓ.ss
+ࡓ.‌Ss; ࡓ.‌ss; [B1, C1]; xn--iwb.xn--ss-i1t; ; xn--iwb.ss; [] # ࡓ.ss
+񯶣-.‍ݎꥍ󠻨; ; [B1, B6, C2, P1, V3, V6]; xn----s116e.xn--1ob387jy90hq459k; ; xn----s116e.xn--1ob6504fmf40i; [B3, B6, P1, V3, V6] # -.ݎꥍ
+xn----s116e.xn--1ob6504fmf40i; 񯶣-.ݎꥍ󠻨; [B3, B6, V3, V6]; xn----s116e.xn--1ob6504fmf40i; ; ; # -.ݎꥍ
+xn----s116e.xn--1ob387jy90hq459k; 񯶣-.‍ݎꥍ󠻨; [B1, B6, C2, V3, V6]; xn----s116e.xn--1ob387jy90hq459k; ; ; # -.ݎꥍ
+䃚蟥-。-񽒘⒈; 䃚蟥-.-񽒘⒈; [P1, V3, V6]; xn----n50a258u.xn----ecp33805f; ; ; # 䃚蟥-.-⒈
+䃚蟥-。-񽒘1.; 䃚蟥-.-񽒘1.; [P1, V3, V6]; xn----n50a258u.xn---1-up07j.; ; ; # 䃚蟥-.-1.
+xn----n50a258u.xn---1-up07j.; 䃚蟥-.-񽒘1.; [V3, V6]; xn----n50a258u.xn---1-up07j.; ; ; # 䃚蟥-.-1.
+xn----n50a258u.xn----ecp33805f; 䃚蟥-.-񽒘⒈; [V3, V6]; xn----n50a258u.xn----ecp33805f; ; ; # 䃚蟥-.-⒈
+𐹸䚵-ꡡ。⺇; 𐹸䚵-ꡡ.⺇; [B1]; xn----bm3an932a1l5d.xn--xvj; ; ; # 𐹸䚵-ꡡ.⺇
+xn----bm3an932a1l5d.xn--xvj; 𐹸䚵-ꡡ.⺇; [B1]; xn----bm3an932a1l5d.xn--xvj; ; ; # 𐹸䚵-ꡡ.⺇
+𑄳。᫜𐹻; 𑄳.᫜𐹻; [B1, B3, B5, B6, P1, V5, V6]; xn--v80d.xn--2rf1154i; ; ; # 𑄳.𐹻
+xn--v80d.xn--2rf1154i; 𑄳.᫜𐹻; [B1, B3, B5, B6, V5, V6]; xn--v80d.xn--2rf1154i; ; ; # 𑄳.𐹻
+≮𐹻.⒎𑂵ں؂; ; [B1, P1, V6]; xn--gdhx904g.xn--kfb18a325efm3s; ; ; # ≮𐹻.⒎𑂵ں
+≮𐹻.⒎𑂵ں؂; ≮𐹻.⒎𑂵ں؂; [B1, P1, V6]; xn--gdhx904g.xn--kfb18a325efm3s; ; ; # ≮𐹻.⒎𑂵ں
+≮𐹻.7.𑂵ں؂; ; [B1, P1, V5, V6]; xn--gdhx904g.7.xn--kfb18an307d; ; ; # ≮𐹻.7.𑂵ں
+≮𐹻.7.𑂵ں؂; ≮𐹻.7.𑂵ں؂; [B1, P1, V5, V6]; xn--gdhx904g.7.xn--kfb18an307d; ; ; # ≮𐹻.7.𑂵ں
+xn--gdhx904g.7.xn--kfb18an307d; ≮𐹻.7.𑂵ں؂; [B1, V5, V6]; xn--gdhx904g.7.xn--kfb18an307d; ; ; # ≮𐹻.7.𑂵ں
+xn--gdhx904g.xn--kfb18a325efm3s; ≮𐹻.⒎𑂵ں؂; [B1, V6]; xn--gdhx904g.xn--kfb18a325efm3s; ; ; # ≮𐹻.⒎𑂵ں
+ᢔ≠􋉂.‍𐋢; ; [C2, P1, V6]; xn--ebf031cf7196a.xn--1ug9540g; ; xn--ebf031cf7196a.xn--587c; [P1, V6] # ᢔ≠.𐋢
+ᢔ≠􋉂.‍𐋢; ᢔ≠􋉂.‍𐋢; [C2, P1, V6]; xn--ebf031cf7196a.xn--1ug9540g; ; xn--ebf031cf7196a.xn--587c; [P1, V6] # ᢔ≠.𐋢
+xn--ebf031cf7196a.xn--587c; ᢔ≠􋉂.𐋢; [V6]; xn--ebf031cf7196a.xn--587c; ; ; # ᢔ≠.𐋢
+xn--ebf031cf7196a.xn--1ug9540g; ᢔ≠􋉂.‍𐋢; [C2, V6]; xn--ebf031cf7196a.xn--1ug9540g; ; ; # ᢔ≠.𐋢
+𐩁≮񣊛≯.٬𞵕⳿; 𐩁≮񣊛≯.٬𞵕⳿; [B1, B2, B3, P1, V6]; xn--gdhc0519o0y27b.xn--lib468q0d21a; ; ; # 𐩁≮≯.٬⳿
+𐩁≮񣊛≯.٬𞵕⳿; 𐩁≮񣊛≯.٬𞵕⳿; [B1, B2, B3, P1, V6]; xn--gdhc0519o0y27b.xn--lib468q0d21a; ; ; # 𐩁≮≯.٬⳿
+𐩁≮񣊛≯.٬𞵕⳿; ; [B1, B2, B3, P1, V6]; xn--gdhc0519o0y27b.xn--lib468q0d21a; ; ; # 𐩁≮≯.٬⳿
+𐩁≮񣊛≯.٬𞵕⳿; 𐩁≮񣊛≯.٬𞵕⳿; [B1, B2, B3, P1, V6]; xn--gdhc0519o0y27b.xn--lib468q0d21a; ; ; # 𐩁≮≯.٬⳿
+xn--gdhc0519o0y27b.xn--lib468q0d21a; 𐩁≮񣊛≯.٬𞵕⳿; [B1, B2, B3, V6]; xn--gdhc0519o0y27b.xn--lib468q0d21a; ; ; # 𐩁≮≯.٬⳿
+-。⺐; -.⺐; [V3]; -.xn--6vj; ; ; # -.⺐
+-。⺐; -.⺐; [V3]; -.xn--6vj; ; ; # -.⺐
+-.xn--6vj; -.⺐; [V3]; -.xn--6vj; ; ; # -.⺐
+󠰩𑲬.ٜ; 󠰩𑲬.ٜ; [P1, V5, V6]; xn--sn3d59267c.xn--4hb; ; ; # 𑲬.ٜ
+󠰩𑲬.ٜ; ; [P1, V5, V6]; xn--sn3d59267c.xn--4hb; ; ; # 𑲬.ٜ
+xn--sn3d59267c.xn--4hb; 󠰩𑲬.ٜ; [V5, V6]; xn--sn3d59267c.xn--4hb; ; ; # 𑲬.ٜ
+𐍺.񚇃‌; ; [C1, P1, V5, V6]; xn--ie8c.xn--0ug03366c; ; xn--ie8c.xn--2g51a; [P1, V5, V6] # 𐍺.
+xn--ie8c.xn--2g51a; 𐍺.񚇃; [V5, V6]; xn--ie8c.xn--2g51a; ; ; # 𐍺.
+xn--ie8c.xn--0ug03366c; 𐍺.񚇃‌; [C1, V5, V6]; xn--ie8c.xn--0ug03366c; ; ; # 𐍺.
+ؽۣ.𐨎; ; [B1, B3, B6, V5]; xn--8gb64a.xn--mr9c; ; ; # ؽۣ.𐨎
+xn--8gb64a.xn--mr9c; ؽۣ.𐨎; [B1, B3, B6, V5]; xn--8gb64a.xn--mr9c; ; ; # ؽۣ.𐨎
+漦Ⴙς.񡻀𐴄; ; [B5, B6, P1, V6]; xn--3xa157d717e.xn--9d0d3162t; ; xn--4xa947d717e.xn--9d0d3162t; # 漦Ⴙς.𐴄
+漦ⴙς.񡻀𐴄; ; [B5, B6, P1, V6]; xn--3xa972sl47b.xn--9d0d3162t; ; xn--4xa772sl47b.xn--9d0d3162t; # 漦ⴙς.𐴄
+漦ႹΣ.񡻀𐴄; 漦Ⴙσ.񡻀𐴄; [B5, B6, P1, V6]; xn--4xa947d717e.xn--9d0d3162t; ; ; # 漦Ⴙσ.𐴄
+漦ⴙσ.񡻀𐴄; ; [B5, B6, P1, V6]; xn--4xa772sl47b.xn--9d0d3162t; ; ; # 漦ⴙσ.𐴄
+漦Ⴙσ.񡻀𐴄; ; [B5, B6, P1, V6]; xn--4xa947d717e.xn--9d0d3162t; ; ; # 漦Ⴙσ.𐴄
+xn--4xa947d717e.xn--9d0d3162t; 漦Ⴙσ.񡻀𐴄; [B5, B6, V6]; xn--4xa947d717e.xn--9d0d3162t; ; ; # 漦Ⴙσ.𐴄
+xn--4xa772sl47b.xn--9d0d3162t; 漦ⴙσ.񡻀𐴄; [B5, B6, V6]; xn--4xa772sl47b.xn--9d0d3162t; ; ; # 漦ⴙσ.𐴄
+xn--3xa972sl47b.xn--9d0d3162t; 漦ⴙς.񡻀𐴄; [B5, B6, V6]; xn--3xa972sl47b.xn--9d0d3162t; ; ; # 漦ⴙς.𐴄
+xn--3xa157d717e.xn--9d0d3162t; 漦Ⴙς.񡻀𐴄; [B5, B6, V6]; xn--3xa157d717e.xn--9d0d3162t; ; ; # 漦Ⴙς.𐴄
+𐹫踧್򫚇.󜀃⒈𝨤; ; [B1, P1, V6]; xn--8tc1437dro0d6q06h.xn--tsh2611ncu71e; ; ; # 𐹫踧್.⒈𝨤
+𐹫踧್򫚇.󜀃1.𝨤; ; [B1, B3, B6, P1, V5, V6]; xn--8tc1437dro0d6q06h.xn--1-p948l.xn--m82h; ; ; # 𐹫踧್.1.𝨤
+xn--8tc1437dro0d6q06h.xn--1-p948l.xn--m82h; 𐹫踧್򫚇.󜀃1.𝨤; [B1, B3, B6, V5, V6]; xn--8tc1437dro0d6q06h.xn--1-p948l.xn--m82h; ; ; # 𐹫踧್.1.𝨤
+xn--8tc1437dro0d6q06h.xn--tsh2611ncu71e; 𐹫踧್򫚇.󜀃⒈𝨤; [B1, V6]; xn--8tc1437dro0d6q06h.xn--tsh2611ncu71e; ; ; # 𐹫踧್.⒈𝨤
+‍≮.󠟪𹫏-; ‍≮.󠟪𹫏-; [C2, P1, V3, V6]; xn--1ug95g.xn----cr99a1w710b; ; xn--gdh.xn----cr99a1w710b; [P1, V3, V6] # ≮.-
+‍≮.󠟪𹫏-; ‍≮.󠟪𹫏-; [C2, P1, V3, V6]; xn--1ug95g.xn----cr99a1w710b; ; xn--gdh.xn----cr99a1w710b; [P1, V3, V6] # ≮.-
+‍≮.󠟪𹫏-; ; [C2, P1, V3, V6]; xn--1ug95g.xn----cr99a1w710b; ; xn--gdh.xn----cr99a1w710b; [P1, V3, V6] # ≮.-
+‍≮.󠟪𹫏-; ‍≮.󠟪𹫏-; [C2, P1, V3, V6]; xn--1ug95g.xn----cr99a1w710b; ; xn--gdh.xn----cr99a1w710b; [P1, V3, V6] # ≮.-
+xn--gdh.xn----cr99a1w710b; ≮.󠟪𹫏-; [V3, V6]; xn--gdh.xn----cr99a1w710b; ; ; # ≮.-
+xn--1ug95g.xn----cr99a1w710b; ‍≮.󠟪𹫏-; [C2, V3, V6]; xn--1ug95g.xn----cr99a1w710b; ; ; # ≮.-
+‍‍襔。Ⴜ5ꡮ񵝏; ‍‍襔.Ⴜ5ꡮ񵝏; [C2, P1, V6]; xn--1uga7691f.xn--5-r1g7167ipfw8d; ; xn--2u2a.xn--5-r1g7167ipfw8d; [P1, V6] # 襔.Ⴜ5ꡮ
+‍‍襔。ⴜ5ꡮ񵝏; ‍‍襔.ⴜ5ꡮ񵝏; [C2, P1, V6]; xn--1uga7691f.xn--5-uws5848bpf44e; ; xn--2u2a.xn--5-uws5848bpf44e; [P1, V6] # 襔.ⴜ5ꡮ
+xn--2u2a.xn--5-uws5848bpf44e; 襔.ⴜ5ꡮ񵝏; [V6]; xn--2u2a.xn--5-uws5848bpf44e; ; ; # 襔.ⴜ5ꡮ
+xn--1uga7691f.xn--5-uws5848bpf44e; ‍‍襔.ⴜ5ꡮ񵝏; [C2, V6]; xn--1uga7691f.xn--5-uws5848bpf44e; ; ; # 襔.ⴜ5ꡮ
+xn--2u2a.xn--5-r1g7167ipfw8d; 襔.Ⴜ5ꡮ񵝏; [V6]; xn--2u2a.xn--5-r1g7167ipfw8d; ; ; # 襔.Ⴜ5ꡮ
+xn--1uga7691f.xn--5-r1g7167ipfw8d; ‍‍襔.Ⴜ5ꡮ񵝏; [C2, V6]; xn--1uga7691f.xn--5-r1g7167ipfw8d; ; ; # 襔.Ⴜ5ꡮ
+𐫜𑌼‍.婀; 𐫜𑌼‍.婀; [B3, C2]; xn--1ugx063g1if.xn--q0s; ; xn--ix9c26l.xn--q0s; [] # 𐫜𑌼.婀
+𐫜𑌼‍.婀; ; [B3, C2]; xn--1ugx063g1if.xn--q0s; ; xn--ix9c26l.xn--q0s; [] # 𐫜𑌼.婀
+xn--ix9c26l.xn--q0s; 𐫜𑌼.婀; ; xn--ix9c26l.xn--q0s; ; ; # 𐫜𑌼.婀
+𐫜𑌼.婀; ; ; xn--ix9c26l.xn--q0s; ; ; # 𐫜𑌼.婀
+xn--1ugx063g1if.xn--q0s; 𐫜𑌼‍.婀; [B3, C2]; xn--1ugx063g1if.xn--q0s; ; ; # 𐫜𑌼.婀
+󠅽︒︒𐹯。⬳᩸; ︒︒𐹯.⬳᩸; [B1, P1, V6]; xn--y86ca186j.xn--7of309e; ; ; # ︒︒𐹯.⬳᩸
+󠅽。。𐹯。⬳᩸; ..𐹯.⬳᩸; [B1, X4_2]; ..xn--no0d.xn--7of309e; [B1, A4_2]; ; # ..𐹯.⬳᩸
+..xn--no0d.xn--7of309e; ..𐹯.⬳᩸; [B1, X4_2]; ..xn--no0d.xn--7of309e; [B1, A4_2]; ; # ..𐹯.⬳᩸
+xn--y86ca186j.xn--7of309e; ︒︒𐹯.⬳᩸; [B1, V6]; xn--y86ca186j.xn--7of309e; ; ; # ︒︒𐹯.⬳᩸
+𝟖ß.󠄐-?Ⴏ; 8ß.-?Ⴏ; [P1, V3, V6]; xn--8-qfa.xn---?-gfk; ; 8ss.xn---?-gfk; # 8ß.-?Ⴏ
+8ß.󠄐-?Ⴏ; 8ß.-?Ⴏ; [P1, V3, V6]; xn--8-qfa.xn---?-gfk; ; 8ss.xn---?-gfk; # 8ß.-?Ⴏ
+8ß.󠄐-?ⴏ; 8ß.-?ⴏ; [P1, V3, V6]; xn--8-qfa.xn---?-261a; ; 8ss.xn---?-261a; # 8ß.-?ⴏ
+8SS.󠄐-?Ⴏ; 8ss.-?Ⴏ; [P1, V3, V6]; 8ss.xn---?-gfk; ; ; # 8ss.-?Ⴏ
+8ss.󠄐-?ⴏ; 8ss.-?ⴏ; [P1, V3, V6]; 8ss.xn---?-261a; ; ; # 8ss.-?ⴏ
+8ss.󠄐-?Ⴏ; 8ss.-?Ⴏ; [P1, V3, V6]; 8ss.xn---?-gfk; ; ; # 8ss.-?Ⴏ
+8ss.xn---?-gfk; 8ss.-?Ⴏ; [P1, V3, V6]; 8ss.xn---?-gfk; ; ; # 8ss.-?Ⴏ
+8ss.xn---?-261a; 8ss.-?ⴏ; [P1, V3, V6]; 8ss.xn---?-261a; ; ; # 8ss.-?ⴏ
+xn--8-qfa.xn---?-261a; 8ß.-?ⴏ; [P1, V3, V6]; xn--8-qfa.xn---?-261a; ; ; # 8ß.-?ⴏ
+xn--8-qfa.xn---?-gfk; 8ß.-?Ⴏ; [P1, V3, V6]; xn--8-qfa.xn---?-gfk; ; ; # 8ß.-?Ⴏ
+𝟖ß.󠄐-?ⴏ; 8ß.-?ⴏ; [P1, V3, V6]; xn--8-qfa.xn---?-261a; ; 8ss.xn---?-261a; # 8ß.-?ⴏ
+𝟖SS.󠄐-?Ⴏ; 8ss.-?Ⴏ; [P1, V3, V6]; 8ss.xn---?-gfk; ; ; # 8ss.-?Ⴏ
+𝟖ss.󠄐-?ⴏ; 8ss.-?ⴏ; [P1, V3, V6]; 8ss.xn---?-261a; ; ; # 8ss.-?ⴏ
+𝟖ss.󠄐-?Ⴏ; 8ss.-?Ⴏ; [P1, V3, V6]; 8ss.xn---?-gfk; ; ; # 8ss.-?Ⴏ
+8ss.-?Ⴏ; ; [P1, V3, V6]; 8ss.xn---?-gfk; ; ; # 8ss.-?Ⴏ
+8ss.-?ⴏ; ; [P1, V3, V6]; 8ss.xn---?-261a; ; ; # 8ss.-?ⴏ
+8SS.-?Ⴏ; 8ss.-?Ⴏ; [P1, V3, V6]; 8ss.xn---?-gfk; ; ; # 8ss.-?Ⴏ
+xn--8-qfa.-?ⴏ; 8ß.-?ⴏ; [P1, V3, V6]; xn--8-qfa.xn---?-261a; ; ; # 8ß.-?ⴏ
+XN--8-QFA.-?Ⴏ; 8ß.-?Ⴏ; [P1, V3, V6]; xn--8-qfa.xn---?-gfk; ; ; # 8ß.-?Ⴏ
+Xn--8-Qfa.-?Ⴏ; 8ß.-?Ⴏ; [P1, V3, V6]; xn--8-qfa.xn---?-gfk; ; ; # 8ß.-?Ⴏ
+xn--8-qfa.-?Ⴏ; 8ß.-?Ⴏ; [P1, V3, V6]; xn--8-qfa.xn---?-gfk; ; ; # 8ß.-?Ⴏ
+𝟖Ss.󠄐-?Ⴏ; 8ss.-?Ⴏ; [P1, V3, V6]; 8ss.xn---?-gfk; ; ; # 8ss.-?Ⴏ
+8Ss.󠄐-?Ⴏ; 8ss.-?Ⴏ; [P1, V3, V6]; 8ss.xn---?-gfk; ; ; # 8ss.-?Ⴏ
+-‍󠋟.‌𐹣Ⴅ; ; [B1, C1, C2, P1, V3, V6]; xn----ugnv7071n.xn--dnd999e4j4p; ; xn----s721m.xn--dnd9201k; [B1, P1, V3, V6] # -.𐹣Ⴅ
+-‍󠋟.‌𐹣ⴅ; ; [B1, C1, C2, P1, V3, V6]; xn----ugnv7071n.xn--0ugz32cgr0p; ; xn----s721m.xn--wkj1423e; [B1, P1, V3, V6] # -.𐹣ⴅ
+xn----s721m.xn--wkj1423e; -󠋟.𐹣ⴅ; [B1, V3, V6]; xn----s721m.xn--wkj1423e; ; ; # -.𐹣ⴅ
+xn----ugnv7071n.xn--0ugz32cgr0p; -‍󠋟.‌𐹣ⴅ; [B1, C1, C2, V3, V6]; xn----ugnv7071n.xn--0ugz32cgr0p; ; ; # -.𐹣ⴅ
+xn----s721m.xn--dnd9201k; -󠋟.𐹣Ⴅ; [B1, V3, V6]; xn----s721m.xn--dnd9201k; ; ; # -.𐹣Ⴅ
+xn----ugnv7071n.xn--dnd999e4j4p; -‍󠋟.‌𐹣Ⴅ; [B1, C1, C2, V3, V6]; xn----ugnv7071n.xn--dnd999e4j4p; ; ; # -.𐹣Ⴅ
+ꦹ‍큷𻶡。₂; ꦹ‍큷𻶡.2; [C2, P1, V5, V6]; xn--1ug1435cfkyaoi04d.2; ; xn--0m9as84e2e21c.2; [P1, V5, V6] # ꦹ큷.2
+ꦹ‍큷𻶡。₂; ꦹ‍큷𻶡.2; [C2, P1, V5, V6]; xn--1ug1435cfkyaoi04d.2; ; xn--0m9as84e2e21c.2; [P1, V5, V6] # ꦹ큷.2
+ꦹ‍큷𻶡。2; ꦹ‍큷𻶡.2; [C2, P1, V5, V6]; xn--1ug1435cfkyaoi04d.2; ; xn--0m9as84e2e21c.2; [P1, V5, V6] # ꦹ큷.2
+ꦹ‍큷𻶡。2; ꦹ‍큷𻶡.2; [C2, P1, V5, V6]; xn--1ug1435cfkyaoi04d.2; ; xn--0m9as84e2e21c.2; [P1, V5, V6] # ꦹ큷.2
+xn--0m9as84e2e21c.2; ꦹ큷𻶡.2; [V5, V6]; xn--0m9as84e2e21c.2; ; ; # ꦹ큷.2
+xn--1ug1435cfkyaoi04d.2; ꦹ‍큷𻶡.2; [C2, V5, V6]; xn--1ug1435cfkyaoi04d.2; ; ; # ꦹ큷.2
+?.🄄𞯘; ; [B1, P1, V6]; ?.xn--3x6hx6f; ; ; # ?.🄄
+?.3,𞯘; ; [B1, P1, V6]; ?.xn--3,-tb22a; ; ; # ?.3,
+?.xn--3,-tb22a; ?.3,𞯘; [B1, P1, V6]; ?.xn--3,-tb22a; ; ; # ?.3,
+?.xn--3x6hx6f; ?.🄄𞯘; [B1, P1, V6]; ?.xn--3x6hx6f; ; ; # ?.🄄
+𝨖𐩙。۝󀡶ꣅ⒈; 𝨖𐩙.۝󀡶ꣅ⒈; [B1, P1, V5, V6]; xn--rt9cl956a.xn--tlb403mxv4g06s9i; ; ; # 𝨖.ꣅ⒈
+𝨖𐩙。۝󀡶ꣅ1.; 𝨖𐩙.۝󀡶ꣅ1.; [B1, P1, V5, V6]; xn--rt9cl956a.xn--1-dxc8545j0693i.; ; ; # 𝨖.ꣅ1.
+xn--rt9cl956a.xn--1-dxc8545j0693i.; 𝨖𐩙.۝󀡶ꣅ1.; [B1, V5, V6]; xn--rt9cl956a.xn--1-dxc8545j0693i.; ; ; # 𝨖.ꣅ1.
+xn--rt9cl956a.xn--tlb403mxv4g06s9i; 𝨖𐩙.۝󀡶ꣅ⒈; [B1, V5, V6]; xn--rt9cl956a.xn--tlb403mxv4g06s9i; ; ; # 𝨖.ꣅ⒈
+򒈣סڸ。Ⴈ‍; 򒈣סڸ.Ⴈ‍; [B5, B6, C2, P1, V6]; xn--meb44b57607c.xn--gnd699e; ; xn--meb44b57607c.xn--gnd; [B5, B6, P1, V6] # סڸ.Ⴈ
+򒈣סڸ。ⴈ‍; 򒈣סڸ.ⴈ‍; [B5, B6, C2, P1, V6]; xn--meb44b57607c.xn--1ug232c; ; xn--meb44b57607c.xn--zkj; [B5, B6, P1, V6] # סڸ.ⴈ
+xn--meb44b57607c.xn--zkj; 򒈣סڸ.ⴈ; [B5, B6, V6]; xn--meb44b57607c.xn--zkj; ; ; # סڸ.ⴈ
+xn--meb44b57607c.xn--1ug232c; 򒈣סڸ.ⴈ‍; [B5, B6, C2, V6]; xn--meb44b57607c.xn--1ug232c; ; ; # סڸ.ⴈ
+xn--meb44b57607c.xn--gnd; 򒈣סڸ.Ⴈ; [B5, B6, V6]; xn--meb44b57607c.xn--gnd; ; ; # סڸ.Ⴈ
+xn--meb44b57607c.xn--gnd699e; 򒈣סڸ.Ⴈ‍; [B5, B6, C2, V6]; xn--meb44b57607c.xn--gnd699e; ; ; # סڸ.Ⴈ
+󀚶𝨱ߦ⒈.𑗝髯‌; 󀚶𝨱ߦ⒈.𑗝髯‌; [B1, B5, C1, P1, V5, V6]; xn--etb477lq931a1f58e.xn--0ugx259bocxd; ; xn--etb477lq931a1f58e.xn--uj6at43v; [B1, B5, P1, V5, V6] # 𝨱ߦ⒈.𑗝髯
+󀚶𝨱ߦ1..𑗝髯‌; ; [B1, B5, C1, P1, V5, V6, X4_2]; xn--1-idd62296a1fr6e..xn--0ugx259bocxd; [B1, B5, C1, P1, V5, V6, A4_2]; xn--1-idd62296a1fr6e..xn--uj6at43v; [B1, B5, P1, V5, V6, A4_2] # 𝨱ߦ1..𑗝髯
+xn--1-idd62296a1fr6e..xn--uj6at43v; 󀚶𝨱ߦ1..𑗝髯; [B1, B5, V5, V6, X4_2]; xn--1-idd62296a1fr6e..xn--uj6at43v; [B1, B5, V5, V6, A4_2]; ; # 𝨱ߦ1..𑗝髯
+xn--1-idd62296a1fr6e..xn--0ugx259bocxd; 󀚶𝨱ߦ1..𑗝髯‌; [B1, B5, C1, V5, V6, X4_2]; xn--1-idd62296a1fr6e..xn--0ugx259bocxd; [B1, B5, C1, V5, V6, A4_2]; ; # 𝨱ߦ1..𑗝髯
+xn--etb477lq931a1f58e.xn--uj6at43v; 󀚶𝨱ߦ⒈.𑗝髯; [B1, B5, V5, V6]; xn--etb477lq931a1f58e.xn--uj6at43v; ; ; # 𝨱ߦ⒈.𑗝髯
+xn--etb477lq931a1f58e.xn--0ugx259bocxd; 󀚶𝨱ߦ⒈.𑗝髯‌; [B1, B5, C1, V5, V6]; xn--etb477lq931a1f58e.xn--0ugx259bocxd; ; ; # 𝨱ߦ⒈.𑗝髯
+𐫀.ډ𑌀; 𐫀.ډ𑌀; ; xn--pw9c.xn--fjb8658k; ; ; # 𐫀.ډ𑌀
+𐫀.ډ𑌀; ; ; xn--pw9c.xn--fjb8658k; ; ; # 𐫀.ډ𑌀
+xn--pw9c.xn--fjb8658k; 𐫀.ډ𑌀; ; xn--pw9c.xn--fjb8658k; ; ; # 𐫀.ډ𑌀
+𑋪.𐳝; 𑋪.𐳝; [B1, B3, B6, V5]; xn--fm1d.xn--5c0d; ; ; # 𑋪.𐳝
+𑋪.𐳝; ; [B1, B3, B6, V5]; xn--fm1d.xn--5c0d; ; ; # 𑋪.𐳝
+𑋪.𐲝; 𑋪.𐳝; [B1, B3, B6, V5]; xn--fm1d.xn--5c0d; ; ; # 𑋪.𐳝
+xn--fm1d.xn--5c0d; 𑋪.𐳝; [B1, B3, B6, V5]; xn--fm1d.xn--5c0d; ; ; # 𑋪.𐳝
+𑋪.𐲝; 𑋪.𐳝; [B1, B3, B6, V5]; xn--fm1d.xn--5c0d; ; ; # 𑋪.𐳝
+≠膣。ྃ; ≠膣.ྃ; [P1, V5, V6]; xn--1chy468a.xn--2ed; ; ; # ≠膣.ྃ
+≠膣。ྃ; ≠膣.ྃ; [P1, V5, V6]; xn--1chy468a.xn--2ed; ; ; # ≠膣.ྃ
+xn--1chy468a.xn--2ed; ≠膣.ྃ; [V5, V6]; xn--1chy468a.xn--2ed; ; ; # ≠膣.ྃ
+񰀎-ݽ。ß; 񰀎-ݽ.ß; [B5, B6, P1, V6]; xn----j6c95618k.xn--zca; ; xn----j6c95618k.ss; # -ݽ.ß
+񰀎-ݽ。ß; 񰀎-ݽ.ß; [B5, B6, P1, V6]; xn----j6c95618k.xn--zca; ; xn----j6c95618k.ss; # -ݽ.ß
+񰀎-ݽ。SS; 񰀎-ݽ.ss; [B5, B6, P1, V6]; xn----j6c95618k.ss; ; ; # -ݽ.ss
+񰀎-ݽ。ss; 񰀎-ݽ.ss; [B5, B6, P1, V6]; xn----j6c95618k.ss; ; ; # -ݽ.ss
+񰀎-ݽ。Ss; 񰀎-ݽ.ss; [B5, B6, P1, V6]; xn----j6c95618k.ss; ; ; # -ݽ.ss
+xn----j6c95618k.ss; 񰀎-ݽ.ss; [B5, B6, V6]; xn----j6c95618k.ss; ; ; # -ݽ.ss
+xn----j6c95618k.xn--zca; 񰀎-ݽ.ß; [B5, B6, V6]; xn----j6c95618k.xn--zca; ; ; # -ݽ.ß
+񰀎-ݽ。SS; 񰀎-ݽ.ss; [B5, B6, P1, V6]; xn----j6c95618k.ss; ; ; # -ݽ.ss
+񰀎-ݽ。ss; 񰀎-ݽ.ss; [B5, B6, P1, V6]; xn----j6c95618k.ss; ; ; # -ݽ.ss
+񰀎-ݽ。Ss; 񰀎-ݽ.ss; [B5, B6, P1, V6]; xn----j6c95618k.ss; ; ; # -ݽ.ss
+ς𐹠ᡚ𑄳.⾭𐹽𽐖𐫜; ς𐹠ᡚ𑄳.靑𐹽𽐖𐫜; [B5, B6, P1, V6]; xn--3xa856hp23pxmc.xn--es5a888tvjc2u15h; ; xn--4xa656hp23pxmc.xn--es5a888tvjc2u15h; # ς𐹠ᡚ𑄳.靑𐹽𐫜
+ς𐹠ᡚ𑄳.靑𐹽𽐖𐫜; ; [B5, B6, P1, V6]; xn--3xa856hp23pxmc.xn--es5a888tvjc2u15h; ; xn--4xa656hp23pxmc.xn--es5a888tvjc2u15h; # ς𐹠ᡚ𑄳.靑𐹽𐫜
+Σ𐹠ᡚ𑄳.靑𐹽𽐖𐫜; σ𐹠ᡚ𑄳.靑𐹽𽐖𐫜; [B5, B6, P1, V6]; xn--4xa656hp23pxmc.xn--es5a888tvjc2u15h; ; ; # σ𐹠ᡚ𑄳.靑𐹽𐫜
+σ𐹠ᡚ𑄳.靑𐹽𽐖𐫜; ; [B5, B6, P1, V6]; xn--4xa656hp23pxmc.xn--es5a888tvjc2u15h; ; ; # σ𐹠ᡚ𑄳.靑𐹽𐫜
+xn--4xa656hp23pxmc.xn--es5a888tvjc2u15h; σ𐹠ᡚ𑄳.靑𐹽𽐖𐫜; [B5, B6, V6]; xn--4xa656hp23pxmc.xn--es5a888tvjc2u15h; ; ; # σ𐹠ᡚ𑄳.靑𐹽𐫜
+xn--3xa856hp23pxmc.xn--es5a888tvjc2u15h; ς𐹠ᡚ𑄳.靑𐹽𽐖𐫜; [B5, B6, V6]; xn--3xa856hp23pxmc.xn--es5a888tvjc2u15h; ; ; # ς𐹠ᡚ𑄳.靑𐹽𐫜
+Σ𐹠ᡚ𑄳.⾭𐹽𽐖𐫜; σ𐹠ᡚ𑄳.靑𐹽𽐖𐫜; [B5, B6, P1, V6]; xn--4xa656hp23pxmc.xn--es5a888tvjc2u15h; ; ; # σ𐹠ᡚ𑄳.靑𐹽𐫜
+σ𐹠ᡚ𑄳.⾭𐹽𽐖𐫜; σ𐹠ᡚ𑄳.靑𐹽𽐖𐫜; [B5, B6, P1, V6]; xn--4xa656hp23pxmc.xn--es5a888tvjc2u15h; ; ; # σ𐹠ᡚ𑄳.靑𐹽𐫜
+𐋷。‍; 𐋷.‍; [C2]; xn--r97c.xn--1ug; ; xn--r97c.; [] # 𐋷.
+xn--r97c.; 𐋷.; ; xn--r97c.; ; ; # 𐋷.
+𐋷.; ; ; xn--r97c.; ; ; # 𐋷.
+xn--r97c.xn--1ug; 𐋷.‍; [C2]; xn--r97c.xn--1ug; ; ; # 𐋷.
+𑰳𑈯。⥪; 𑰳𑈯.⥪; [V5]; xn--2g1d14o.xn--jti; ; ; # 𑰳𑈯.⥪
+xn--2g1d14o.xn--jti; 𑰳𑈯.⥪; [V5]; xn--2g1d14o.xn--jti; ; ; # 𑰳𑈯.⥪
+𑆀䁴񤧣.Ⴕ𝟜‌͈; 𑆀䁴񤧣.Ⴕ4‌͈; [C1, P1, V5, V6]; xn--1mnx647cg3x1b.xn--4-zfb324h32o; ; xn--1mnx647cg3x1b.xn--4-zfb324h; [P1, V5, V6] # 𑆀䁴.Ⴕ4͈
+𑆀䁴񤧣.Ⴕ4‌͈; ; [C1, P1, V5, V6]; xn--1mnx647cg3x1b.xn--4-zfb324h32o; ; xn--1mnx647cg3x1b.xn--4-zfb324h; [P1, V5, V6] # 𑆀䁴.Ⴕ4͈
+𑆀䁴񤧣.ⴕ4‌͈; ; [C1, P1, V5, V6]; xn--1mnx647cg3x1b.xn--4-zfb502tlsl; ; xn--1mnx647cg3x1b.xn--4-zfb5123a; [P1, V5, V6] # 𑆀䁴.ⴕ4͈
+xn--1mnx647cg3x1b.xn--4-zfb5123a; 𑆀䁴񤧣.ⴕ4͈; [V5, V6]; xn--1mnx647cg3x1b.xn--4-zfb5123a; ; ; # 𑆀䁴.ⴕ4͈
+xn--1mnx647cg3x1b.xn--4-zfb502tlsl; 𑆀䁴񤧣.ⴕ4‌͈; [C1, V5, V6]; xn--1mnx647cg3x1b.xn--4-zfb502tlsl; ; ; # 𑆀䁴.ⴕ4͈
+xn--1mnx647cg3x1b.xn--4-zfb324h; 𑆀䁴񤧣.Ⴕ4͈; [V5, V6]; xn--1mnx647cg3x1b.xn--4-zfb324h; ; ; # 𑆀䁴.Ⴕ4͈
+xn--1mnx647cg3x1b.xn--4-zfb324h32o; 𑆀䁴񤧣.Ⴕ4‌͈; [C1, V5, V6]; xn--1mnx647cg3x1b.xn--4-zfb324h32o; ; ; # 𑆀䁴.Ⴕ4͈
+𑆀䁴񤧣.ⴕ𝟜‌͈; 𑆀䁴񤧣.ⴕ4‌͈; [C1, P1, V5, V6]; xn--1mnx647cg3x1b.xn--4-zfb502tlsl; ; xn--1mnx647cg3x1b.xn--4-zfb5123a; [P1, V5, V6] # 𑆀䁴.ⴕ4͈
+憡?‌Ⴔ.𐋮‍≠; ; [C1, C2, P1, V6]; xn--?-c1g798iy27d.xn--1ug73gl146a; ; xn--?-c1g3623d.xn--1chz659f; [P1, V6] # 憡?Ⴔ.𐋮≠
+憡?‌Ⴔ.𐋮‍≠; 憡?‌Ⴔ.𐋮‍≠; [C1, C2, P1, V6]; xn--?-c1g798iy27d.xn--1ug73gl146a; ; xn--?-c1g3623d.xn--1chz659f; [P1, V6] # 憡?Ⴔ.𐋮≠
+憡?‌ⴔ.𐋮‍≠; 憡?‌ⴔ.𐋮‍≠; [C1, C2, P1, V6]; xn--?-sgn310doh5c.xn--1ug73gl146a; ; xn--?-fwsr13r.xn--1chz659f; [P1, V6] # 憡?ⴔ.𐋮≠
+憡?‌ⴔ.𐋮‍≠; ; [C1, C2, P1, V6]; xn--?-sgn310doh5c.xn--1ug73gl146a; ; xn--?-fwsr13r.xn--1chz659f; [P1, V6] # 憡?ⴔ.𐋮≠
+xn--?-fwsr13r.xn--1chz659f; 憡?ⴔ.𐋮≠; [P1, V6]; xn--?-fwsr13r.xn--1chz659f; ; ; # 憡?ⴔ.𐋮≠
+xn--?-sgn310doh5c.xn--1ug73gl146a; 憡?‌ⴔ.𐋮‍≠; [C1, C2, P1, V6]; xn--?-sgn310doh5c.xn--1ug73gl146a; ; ; # 憡?ⴔ.𐋮≠
+xn--?-c1g3623d.xn--1chz659f; 憡?Ⴔ.𐋮≠; [P1, V6]; xn--?-c1g3623d.xn--1chz659f; ; ; # 憡?Ⴔ.𐋮≠
+xn--?-c1g798iy27d.xn--1ug73gl146a; 憡?‌Ⴔ.𐋮‍≠; [C1, C2, P1, V6]; xn--?-c1g798iy27d.xn--1ug73gl146a; ; ; # 憡?Ⴔ.𐋮≠
+憡?ⴔ.xn--1chz659f; 憡?ⴔ.𐋮≠; [P1, V6]; xn--?-fwsr13r.xn--1chz659f; ; ; # 憡?ⴔ.𐋮≠
+憡?Ⴔ.XN--1CHZ659F; 憡?Ⴔ.𐋮≠; [P1, V6]; xn--?-c1g3623d.xn--1chz659f; ; ; # 憡?Ⴔ.𐋮≠
+憡?Ⴔ.xn--1chz659f; 憡?Ⴔ.𐋮≠; [P1, V6]; xn--?-c1g3623d.xn--1chz659f; ; ; # 憡?Ⴔ.𐋮≠
+憡?‌ⴔ.xn--1ug73gl146a; 憡?‌ⴔ.𐋮‍≠; [C1, C2, P1, V6]; xn--?-sgn310doh5c.xn--1ug73gl146a; ; xn--?-fwsr13r.xn--1ug73gl146a; [C2, P1, V6] # 憡?ⴔ.𐋮≠
+憡?‌Ⴔ.XN--1UG73GL146A; 憡?‌Ⴔ.𐋮‍≠; [C1, C2, P1, V6]; xn--?-c1g798iy27d.xn--1ug73gl146a; ; xn--?-c1g3623d.xn--1ug73gl146a; [C2, P1, V6] # 憡?Ⴔ.𐋮≠
+憡?‌Ⴔ.xn--1ug73gl146a; 憡?‌Ⴔ.𐋮‍≠; [C1, C2, P1, V6]; xn--?-c1g798iy27d.xn--1ug73gl146a; ; xn--?-c1g3623d.xn--1ug73gl146a; [C2, P1, V6] # 憡?Ⴔ.𐋮≠
+xn--?-c1g3623d.xn--1ug73gl146a; 憡?Ⴔ.𐋮‍≠; [C2, P1, V6]; xn--?-c1g3623d.xn--1ug73gl146a; ; ; # 憡?Ⴔ.𐋮≠
+xn--?-fwsr13r.xn--1ug73gl146a; 憡?ⴔ.𐋮‍≠; [C2, P1, V6]; xn--?-fwsr13r.xn--1ug73gl146a; ; ; # 憡?ⴔ.𐋮≠
+憡?Ⴔ.xn--1ug73gl146a; 憡?Ⴔ.𐋮‍≠; [C2, P1, V6]; xn--?-c1g3623d.xn--1ug73gl146a; ; ; # 憡?Ⴔ.𐋮≠
+憡?ⴔ.xn--1ug73gl146a; 憡?ⴔ.𐋮‍≠; [C2, P1, V6]; xn--?-fwsr13r.xn--1ug73gl146a; ; ; # 憡?ⴔ.𐋮≠
+憡?Ⴔ.XN--1UG73GL146A; 憡?Ⴔ.𐋮‍≠; [C2, P1, V6]; xn--?-c1g3623d.xn--1ug73gl146a; ; ; # 憡?Ⴔ.𐋮≠
diff --git a/test/lisp/net/puny-tests.el b/test/lisp/net/puny-tests.el
index 3f69b60a3b3..1b0cf56895e 100644
--- a/test/lisp/net/puny-tests.el
+++ b/test/lisp/net/puny-tests.el
@@ -1,6 +1,6 @@
-;;; puny-tests.el --- tests for net/puny.el -*- coding: utf-8; -*-
+;;; puny-tests.el --- tests for net/puny.el -*- coding: utf-8; lexical-binding:t -*-
-;; Copyright (C) 2017 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2022 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -38,4 +38,40 @@
"Test puny decoding."
(should (string= (puny-decode-string "xn--9dbdkw") "חנוך")))
+(ert-deftest puny-test-encode-domain ()
+ (should (string= (puny-encode-domain "åäö.se") "xn--4cab6c.se"))
+ (should (string= (puny-encode-domain "яндекс.рф") "xn--d1acpjx3f.xn--p1ai")))
+
+(ert-deftest puny-test-decode-domain ()
+ (should (string= (puny-decode-domain "xn--4cab6c.se") "åäö.se"))
+ (should (string= (puny-decode-domain "xn--d1acpjx3f.xn--p1ai") "яндекс.рф")))
+
+(ert-deftest puny-highly-restrictive-domain-p ()
+ (should (puny-highly-restrictive-domain-p "foo.bar.org"))
+ (should (puny-highly-restrictive-domain-p "foo.abcåäö.org"))
+ (should (puny-highly-restrictive-domain-p "foo.ர.org"))
+ ;; Disallow unicode character 2044, visually similar to "/".
+ (should-not (puny-highly-restrictive-domain-p "www.yourbank.com⁄login⁄checkUser.jsp?inxs.ch"))
+ ;; Disallow mixing scripts.
+ (should-not (puny-highly-restrictive-domain-p "åர.org"))
+ ;; Only allowed in moderately restrictive.
+ (should-not (puny-highly-restrictive-domain-p "Teχ.org"))
+ (should-not (puny-highly-restrictive-domain-p "HλLF-LIFE.org"))
+ (should-not (puny-highly-restrictive-domain-p "Ωmega.org"))
+ ;; Only allowed in unrestricted.
+ (should-not (puny-highly-restrictive-domain-p "I♥NY.org")))
+
+(ert-deftest puny-normalize ()
+ (should (equal (puny-encode-string (string-glyph-compose "Bä.com"))
+ "xn--b.com-gra"))
+ (should (equal (puny-encode-string "Bä.com")
+ "xn--b.com-gra"))
+ (should (equal (puny-encode-string "Bä.com") "xn--b.com-gra")))
+
+;;; TODO!
+;; puny-resources/IdnaTestV2.txt has a bunch of tests, and they should
+;; be implemented. However, the puny encoding does not fully
+;; implement https://www.unicode.org/reports/tr46/#Conformance yet, so
+;; it'll fail.
+
;;; puny-tests.el ends here
diff --git a/test/lisp/net/rcirc-tests.el b/test/lisp/net/rcirc-tests.el
new file mode 100644
index 00000000000..0ba4f2b86e5
--- /dev/null
+++ b/test/lisp/net/rcirc-tests.el
@@ -0,0 +1,66 @@
+;;; rcirc-tests.el --- Tests for rcirc -*- lexical-binding:t -*-
+
+;; Copyright (C) 2019-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+;;
+;; GNU Emacs is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; GNU Emacs is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'rcirc)
+(require 'cl-lib)
+
+(defun rcirc-tests--parse-server-response (cmd text)
+ (cl-letf* ((received-args nil)
+ ((symbol-function (intern (concat "rcirc-handler-" cmd)))
+ (lambda (_process sender args text)
+ (setq received-args (list sender cmd args text))))
+ (rcirc-receive-message-functions nil)
+ (rcirc-trap-errors-flag nil))
+ (rcirc-process-server-response nil text)
+ received-args))
+
+(defmacro rcirc-tests--server-response-parse-should-be
+ (text expected-sender expected-cmd expected-args)
+ (declare (debug t))
+ (macroexp-let2* nil ((cmd expected-cmd))
+ `(should (equal (rcirc-tests--parse-server-response ,cmd ,text)
+ (list ,expected-sender ,cmd ,expected-args ,text)))))
+
+(ert-deftest rcirc-process-server-response ()
+ (rcirc-tests--server-response-parse-should-be
+ "MODE #cchan +kl a:b :999"
+ nil "MODE" '("#cchan" "+kl" "a:b" "999"))
+ (rcirc-tests--server-response-parse-should-be
+ "MODE #cchan +kl a:b 999"
+ nil "MODE" '("#cchan" "+kl" "a:b" "999"))
+ (rcirc-tests--server-response-parse-should-be
+ "MODE #cchan +kl :a:b"
+ nil "MODE" '("#cchan" "+kl" "a:b")))
+
+(ert-deftest rcirc-rename-nicks ()
+ (should (equal (rcirc--make-new-nick "foo" 16)
+ "foo`"))
+ (should (equal (rcirc--make-new-nick "123456789012345" 16)
+ "123456789012345`"))
+ (should (equal (rcirc--make-new-nick "1234567890123456" 16)
+ "123456789012345`"))
+ (should (equal (rcirc--make-new-nick "123456789012345`" 16)
+ "12345678901234``"))
+ (should (equal (rcirc--make-new-nick "123456789012````" 16)
+ "12345678901`````")))
+
+;;; rcirc-tests.el ends here
diff --git a/test/lisp/net/rfc2104-tests.el b/test/lisp/net/rfc2104-tests.el
new file mode 100644
index 00000000000..9cce2aa4b35
--- /dev/null
+++ b/test/lisp/net/rfc2104-tests.el
@@ -0,0 +1,41 @@
+;;; rfc2104-tests.el --- Tests of RFC2104 hashes -*- lexical-binding:t -*-
+
+;; Copyright (C) 2019-2022 Free Software Foundation, Inc.
+
+;; Author: Lars Ingebrigtsen <larsi@gnus.org>
+
+;; This file is part of GNU Emacs.
+;;
+;; GNU Emacs is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; GNU Emacs is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'rfc2104)
+(require 'sha1)
+(require 'md5)
+
+(ert-deftest dbus-test-sha1 ()
+ (should
+ (equal (rfc2104-hash 'sha1 64 20 "Jefe" "what do ya want for nothing?")
+ "effcdf6ae5eb2fa2d27416d5f184df9c259a7c79")))
+
+(ert-deftest dbus-test-md5 ()
+ (should
+ (equal (rfc2104-hash 'md5 64 16 "Jefe" "what do ya want for nothing?")
+ "750c783e6ab0b503eaa86e310a5db738")))
+
+(provide 'rfc2104-tests)
+
+;;; rfc2104-tests.el ends here
diff --git a/test/lisp/net/sasl-cram-tests.el b/test/lisp/net/sasl-cram-tests.el
new file mode 100644
index 00000000000..e8dbeca0908
--- /dev/null
+++ b/test/lisp/net/sasl-cram-tests.el
@@ -0,0 +1,46 @@
+;;; sasl-cram-tests.el --- tests for sasl-cram.el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+;; Author: Stefan Kangas <stefankangas@gmail.com>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Test case from RFC 2195.
+
+;;; Code:
+
+(require 'ert)
+(require 'sasl)
+(require 'sasl-cram)
+
+(ert-deftest sasl-cram-md5-response-test ()
+ ;; The following strings are taken from section 2 of RFC 2195.
+ (let ((client
+ (sasl-make-client (sasl-find-mechanism '("CRAM-MD5"))
+ "user"
+ "imap"
+ "localhost"))
+ (data (base64-decode-string "PDE4OTYuNjk3MTcwOTUyQHBvc3RvZmZpY2UucmVzdG9uLm1jaS5uZXQ+"))
+ (sasl-read-passphrase
+ (lambda (_prompt) (copy-sequence "tanstaaftanstaaf"))))
+ (should (equal (sasl-cram-md5-response client (vector nil data))
+ "user b913a602c7eda7a495b4e6e7334d3890"))))
+
+(provide 'sasl-cram-tests)
+;;; sasl-cram-tests.el ends here
diff --git a/test/lisp/net/sasl-scram-rfc-tests.el b/test/lisp/net/sasl-scram-rfc-tests.el
index 4fb6f6cfefd..b61b437c75a 100644
--- a/test/lisp/net/sasl-scram-rfc-tests.el
+++ b/test/lisp/net/sasl-scram-rfc-tests.el
@@ -1,9 +1,11 @@
-;;; sasl-scram-rfc-tests.el --- tests for SCRAM-SHA-1 -*- lexical-binding: t; -*-
+;;; sasl-scram-rfc-tests.el --- tests for SCRAM -*- lexical-binding: t; -*-
-;; Copyright (C) 2014-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2022 Free Software Foundation, Inc.
;; Author: Magnus Henoch <magnus.henoch@gmail.com>
+;; This file is part of GNU Emacs.
+
;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
@@ -19,7 +21,7 @@
;;; Commentary:
-;; Test cases from RFC 5802.
+;; Test cases from RFC 5802 and RFC 7677.
;;; Code:
@@ -47,4 +49,26 @@
(sasl-scram-sha-1-authenticate-server client (vector nil "v=rmF9pqV8S7suAoZWja4dJRkFsKQ=
"))))
+(require 'sasl-scram-sha256)
+
+(ert-deftest sasl-scram-sha-256-test ()
+ ;; The following strings are taken from section 3 of RFC 7677.
+ (let ((client
+ (sasl-make-client (sasl-find-mechanism '("SCRAM-SHA-256"))
+ "user"
+ "imap"
+ "localhost"))
+ (data "r=rOprNGfwEbeRWgbNEkqO%hvYDpWUa2RaTCAfuxFIlj)hNlF$k0,s=W22ZaJ0SNY7soEsUEjb6gQ==,i=4096")
+ (c-nonce "rOprNGfwEbeRWgbNEkqO")
+ (sasl-read-passphrase
+ (lambda (_prompt) (copy-sequence "pencil"))))
+ (sasl-client-set-property client 'c-nonce c-nonce)
+ (should
+ (equal
+ (sasl-scram-sha-256-client-final-message client (vector nil data))
+ "c=biws,r=rOprNGfwEbeRWgbNEkqO%hvYDpWUa2RaTCAfuxFIlj)hNlF$k0,p=dHzbZapWIk4jUhN+Ute9ytag9zjfMHgsqmmiz7AndVQ="))
+
+ ;; This should not throw an error:
+ (sasl-scram-sha-256-authenticate-server client (vector nil "v=6rriTRBi23WpRR/wtup+mMhUZUn/dB5nLTJRsjl95G4="))))
+
;;; sasl-scram-rfc-tests.el ends here
diff --git a/test/lisp/net/sasl-tests.el b/test/lisp/net/sasl-tests.el
new file mode 100644
index 00000000000..f0e99e8f09e
--- /dev/null
+++ b/test/lisp/net/sasl-tests.el
@@ -0,0 +1,59 @@
+;;; sasl-tests.el --- tests for sasl.el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+;; Author: Stefan Kangas <stefankangas@gmail.com>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'sasl)
+
+(ert-deftest sasl-test-make-client ()
+ (let ((client (sasl-make-client 'foo 'bar 'baz 'zut)))
+ (should (eq (sasl-client-mechanism client) 'foo))
+ (should (eq (sasl-client-name client) 'bar))
+ (should (eq (sasl-client-service client) 'baz))
+ (should (eq (sasl-client-server client) 'zut))))
+
+(ert-deftest sasl-test-client-set-properties ()
+ (let ((client (sasl-make-client 'foo 'bar 'baz 'zut)))
+ (sasl-client-set-property client 'foo 'bar)
+ (should (eq (sasl-client-property client 'foo) 'bar))))
+
+(ert-deftest sasl-test-step-data ()
+ (let ((step [nil nil]))
+ (sasl-step-set-data step "foo")
+ (should (equal (sasl-step-data step) "foo"))))
+
+(ert-deftest sasl-test-unique-id ()
+ (should (stringp (sasl-unique-id)))
+ (should-not (equal (sasl-unique-id) (sasl-unique-id))))
+
+(ert-deftest sasl-test-find-mechanism ()
+ (should (sasl-find-mechanism '("ANONYMOUS")))
+ (should-not (sasl-find-mechanism '("nonexistent mechanism"))))
+
+(ert-deftest sasl-test-mechanism-name ()
+ (let ((mechanism (sasl-find-mechanism '("ANONYMOUS"))))
+ (should (equal (sasl-mechanism-name mechanism) "ANONYMOUS"))))
+
+(provide 'sasl-tests)
+;;; sasl-tests.el ends here
diff --git a/test/lisp/net/secrets-tests.el b/test/lisp/net/secrets-tests.el
new file mode 100644
index 00000000000..7e66774701c
--- /dev/null
+++ b/test/lisp/net/secrets-tests.el
@@ -0,0 +1,275 @@
+;;; secrets-tests.el --- Tests of Secret Service API -*- lexical-binding: t -*-
+
+;; Copyright (C) 2018-2022 Free Software Foundation, Inc.
+
+;; Author: Michael Albinus <michael.albinus@gmx.de>
+
+;; This file is part of GNU Emacs.
+;;
+;; GNU Emacs is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; GNU Emacs is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'secrets)
+(require 'seq)
+(require 'notifications)
+
+;; We do not want chatty messages.
+(setq secrets-debug nil)
+
+(ert-deftest secrets-test00-availability ()
+ "Test availability of Secret Service API."
+ :expected-result (if secrets-enabled :passed :failed)
+ (should secrets-enabled)
+ (should (dbus-ping :session secrets-service))
+
+ ;; Exit.
+ (secrets--test-close-all-sessions))
+
+(defun secrets--test-get-all-sessions ()
+ "Return all object paths for existing secrets sessions."
+ (let ((session-path (concat secrets-path "/session")))
+ (delete
+ session-path
+ (dbus-introspect-get-all-nodes :session secrets-service session-path))))
+
+(defun secrets--test-close-all-sessions ()
+ "Close all secrets sessions which are bound to this Emacs."
+ (secrets-close-session)
+ ;; We loop over all other sessions. If a session does not belong to
+ ;; us, a `dbus-error' is fired, which we ignore.
+ (dolist (path (secrets--test-get-all-sessions))
+ (dbus-ignore-errors
+ (dbus-call-method
+ :session secrets-service path secrets-interface-session "Close"))))
+
+(defun secrets--test-delete-all-session-items ()
+ "Delete all items of collection \"session\" bound to this Emacs."
+ ;; If the "session" collection does not exist, a `dbus-error' is
+ ;; fired, which we ignore.
+ (dbus-ignore-errors
+ (dolist (item (secrets-list-items "session"))
+ (secrets-delete-item "session" item))))
+
+(ert-deftest secrets-test01-sessions ()
+ "Test opening / closing a secrets session."
+ (skip-unless secrets-enabled)
+ (skip-unless (secrets-empty-path secrets-session-path))
+
+ (unwind-protect
+ (progn
+ ;; Simple opening / closing of a session.
+ (should (secrets-open-session))
+ (should-not (secrets-empty-path secrets-session-path))
+ (should (secrets-close-session))
+ (should (secrets-empty-path secrets-session-path))
+
+ ;; Reopening a new session.
+ (should (string-equal (secrets-open-session) (secrets-open-session)))
+ (should (string-equal secrets-session-path (secrets-open-session)))
+ (should-not
+ (string-equal (secrets-open-session) (secrets-open-session 'reopen)))
+ (should-not
+ (string-equal secrets-session-path (secrets-open-session 'reopen))))
+
+ ;; Exit.
+ (should (secrets-close-session))
+ (secrets--test-close-all-sessions)))
+
+(ert-deftest secrets-test02-collections ()
+ "Test creation / deletion a secrets collections."
+ (skip-unless secrets-enabled)
+ (skip-unless (secrets-empty-path secrets-session-path))
+
+ (unwind-protect
+ (progn
+ (should (secrets-open-session))
+ (skip-unless (member "session" (secrets-list-collections)))
+
+ ;; Create a random collection. This asks for a password
+ ;; outside our control, so we make it in the interactive case
+ ;; only.
+ (unless noninteractive
+ (let ((collection (md5 (concat (prin1-to-string process-environment)
+ (current-time-string))))
+ (alias (secrets-get-alias "default")))
+ (notifications-notify
+ :title (symbol-name (ert-test-name (ert-running-test)))
+ :body "Please enter the password \"secret\" twice")
+ ;; The optional argument ALIAS does not seem to work.
+ (should (secrets-create-collection collection))
+ (should (member collection (secrets-list-collections)))
+
+ ;; We reset the alias. The temporary collection "session"
+ ;; is not accepted.
+ (secrets-set-alias collection "default")
+ (should (string-equal (secrets-get-alias "default") collection))
+
+ ;; Delete alias.
+ (secrets-delete-alias "default")
+ (should-not (secrets-get-alias "default"))
+
+ ;; Lock / unlock the collection.
+ (secrets-lock-collection collection)
+ (should
+ (secrets-get-collection-property
+ (secrets-collection-path collection) "Locked"))
+ (notifications-notify
+ :title (symbol-name (ert-test-name (ert-running-test)))
+ :body "Please enter the password \"secret\"")
+ (secrets-unlock-collection collection)
+ (should-not
+ (secrets-get-collection-property
+ (secrets-collection-path collection) "Locked"))
+
+ ;; Delete the collection. The alias disappears as well.
+ (secrets-set-alias collection "default")
+ (secrets-delete-collection collection)
+ (should-not (secrets-get-alias "default"))
+
+ ;; Reset alias.
+ (when alias
+ (secrets-set-alias alias "default")
+ (should (string-equal (secrets-get-alias "default") alias))))))
+
+ ;; Exit.
+ (should (secrets-close-session))
+ (secrets--test-close-all-sessions)))
+
+(ert-deftest secrets-test03-items ()
+ "Test creation / deletion a secret item."
+ (skip-unless secrets-enabled)
+ (skip-unless (secrets-empty-path secrets-session-path))
+
+ (unwind-protect
+ (let (item-path)
+ (should (secrets-open-session))
+ (skip-unless (member "session" (secrets-list-collections)))
+
+ ;; Cleanup. There could be items in the "session" collection.
+ (secrets--test-delete-all-session-items)
+
+ ;; There shall be no items in the "session" collection.
+ (should-not (secrets-list-items "session"))
+
+ ;; Create a new item.
+ (should (setq item-path (secrets-create-item "session" "foo" "secret")))
+ (dolist (item `("foo" ,item-path))
+ (should (string-equal (secrets-get-secret "session" item) "secret")))
+
+ ;; Create another item with same label.
+ (should (secrets-create-item "session" "foo" "geheim"))
+ (should (equal (secrets-list-items "session") '("foo" "foo")))
+
+ ;; Create an item with attributes.
+ (should
+ (setq item-path
+ (secrets-create-item
+ "session" "bar" "secret"
+ :method "sudo" :user "joe" :host "remote-host")))
+ (dolist (item `("bar" ,item-path))
+ (should
+ (string-equal (secrets-get-attribute "session" item :method) "sudo"))
+ ;; The attribute :xdg:schema is added silently.
+ (should
+ (seq-set-equal-p
+ (secrets-get-attributes "session" item)
+ '((:xdg:schema . "org.freedesktop.Secret.Generic")
+ (:host . "remote-host") (:user . "joe") (:method . "sudo")))))
+
+ ;; Create an item with another schema.
+ (should
+ (setq item-path
+ (secrets-create-item
+ "session" "baz" "secret" :xdg:schema "org.gnu.Emacs.foo")))
+ (dolist (item `("baz" ,item-path))
+ (should
+ (equal
+ (secrets-get-attributes "session" item)
+ '((:xdg:schema . "org.gnu.Emacs.foo")))))
+
+ ;; Delete them.
+ (dolist (item (secrets-list-items "session"))
+ (secrets-delete-item "session" item))
+ (should-not (secrets-list-items "session")))
+
+ ;; Exit.
+ (secrets--test-delete-all-session-items)
+ (should (secrets-close-session))
+ (secrets--test-close-all-sessions)))
+
+(ert-deftest secrets-test04-search ()
+ "Test searching of secret items."
+ (skip-unless secrets-enabled)
+ (skip-unless (secrets-empty-path secrets-session-path))
+
+ (unwind-protect
+ (progn
+ (should (secrets-open-session))
+ (skip-unless (member "session" (secrets-list-collections)))
+
+ ;; Cleanup. There could be items in the "session" collection.
+ (secrets--test-delete-all-session-items)
+
+ ;; There shall be no items in the "session" collection.
+ (should-not (secrets-list-items "session"))
+
+ ;; Create some items.
+ (should
+ (secrets-create-item
+ "session" "foo" "secret"
+ :method "sudo" :user "joe" :host "remote-host"))
+ (should
+ (secrets-create-item
+ "session" "bar" "secret"
+ :method "sudo" :user "smith" :host "remote-host"))
+ (should
+ (secrets-create-item
+ "session" "baz" "secret"
+ :method "ssh" :user "joe" :host "other-host"))
+
+ ;; Search the items. `secrets-search-items' uses
+ ;; `secrets-search-item-paths' internally, it is sufficient to
+ ;; test only one of them.
+ (should-not (secrets-search-item-paths "session" :user "john"))
+ (should-not (secrets-search-items "session" :user "john"))
+ (should-not
+ (secrets-search-items "session" :xdg:schema "org.gnu.Emacs.foo"))
+ (should
+ (equal
+ (sort (secrets-search-items "session" :user "joe") #'string-lessp)
+ '("baz" "foo")))
+ (should
+ (equal
+ (secrets-search-items "session":method "sudo" :user "joe") '("foo")))
+ (should
+ (equal
+ (sort (secrets-search-items "session") #'string-lessp)
+ '("bar" "baz" "foo"))))
+
+ ;; Exit.
+ (secrets--test-delete-all-session-items)
+ (should (secrets-close-session))
+ (secrets--test-close-all-sessions)))
+
+(defun secrets-test-all (&optional interactive)
+ "Run all tests for \\[secrets]."
+ (interactive "p")
+ (funcall
+ (if interactive #'ert-run-tests-interactively #'ert-run-tests-batch)
+ "^secrets"))
+
+(provide 'secrets-tests)
+;;; secrets-tests.el ends here
diff --git a/test/data/shr/div-div.html b/test/lisp/net/shr-resources/div-div.html
index 1c191ae44d8..1c191ae44d8 100644
--- a/test/data/shr/div-div.html
+++ b/test/lisp/net/shr-resources/div-div.html
diff --git a/test/data/shr/div-div.txt b/test/lisp/net/shr-resources/div-div.txt
index 62715e12513..62715e12513 100644
--- a/test/data/shr/div-div.txt
+++ b/test/lisp/net/shr-resources/div-div.txt
diff --git a/test/data/shr/div-p.html b/test/lisp/net/shr-resources/div-p.html
index fcbdfc43293..fcbdfc43293 100644
--- a/test/data/shr/div-p.html
+++ b/test/lisp/net/shr-resources/div-p.html
diff --git a/test/data/shr/div-p.txt b/test/lisp/net/shr-resources/div-p.txt
index 859d731da89..859d731da89 100644
--- a/test/data/shr/div-p.txt
+++ b/test/lisp/net/shr-resources/div-p.txt
diff --git a/test/data/shr/li-div.html b/test/lisp/net/shr-resources/li-div.html
index eca3c511bd9..eca3c511bd9 100644
--- a/test/data/shr/li-div.html
+++ b/test/lisp/net/shr-resources/li-div.html
diff --git a/test/data/shr/li-div.txt b/test/lisp/net/shr-resources/li-div.txt
index 9fc54f2bdc6..9fc54f2bdc6 100644
--- a/test/data/shr/li-div.txt
+++ b/test/lisp/net/shr-resources/li-div.txt
diff --git a/test/data/shr/li-empty.html b/test/lisp/net/shr-resources/li-empty.html
index 05cfee7bdd4..05cfee7bdd4 100644
--- a/test/data/shr/li-empty.html
+++ b/test/lisp/net/shr-resources/li-empty.html
diff --git a/test/data/shr/li-empty.txt b/test/lisp/net/shr-resources/li-empty.txt
index 906fd8df8b3..906fd8df8b3 100644
--- a/test/data/shr/li-empty.txt
+++ b/test/lisp/net/shr-resources/li-empty.txt
diff --git a/test/data/shr/nonbr.html b/test/lisp/net/shr-resources/nonbr.html
index 56282cf4ca5..56282cf4ca5 100644
--- a/test/data/shr/nonbr.html
+++ b/test/lisp/net/shr-resources/nonbr.html
diff --git a/test/data/shr/nonbr.txt b/test/lisp/net/shr-resources/nonbr.txt
index 0c3cffa93f9..0c3cffa93f9 100644
--- a/test/data/shr/nonbr.txt
+++ b/test/lisp/net/shr-resources/nonbr.txt
diff --git a/test/lisp/net/shr-resources/ol.html b/test/lisp/net/shr-resources/ol.html
new file mode 100644
index 00000000000..f9a15f26409
--- /dev/null
+++ b/test/lisp/net/shr-resources/ol.html
@@ -0,0 +1,29 @@
+<ol>
+ <li>one</li>
+ <li>two</li>
+ <li>three</li>
+</ol>
+
+<ol start="10">
+ <li>ten</li>
+ <li>eleven</li>
+ <li>twelve</li>
+</ol>
+
+<ol start="0">
+ <li>zero</li>
+ <li>one</li>
+ <li>two</li>
+</ol>
+
+<ol start="-5">
+ <li>minus five</li>
+ <li>minus four</li>
+ <li>minus three</li>
+</ol>
+
+<ol start="notanumber">
+ <li>one</li>
+ <li>two</li>
+ <li>three</li>
+</ol>
diff --git a/test/lisp/net/shr-resources/ol.txt b/test/lisp/net/shr-resources/ol.txt
new file mode 100644
index 00000000000..0d46e2a8ddb
--- /dev/null
+++ b/test/lisp/net/shr-resources/ol.txt
@@ -0,0 +1,19 @@
+1 one
+2 two
+3 three
+
+10 ten
+11 eleven
+12 twelve
+
+0 zero
+1 one
+2 two
+
+-5 minus five
+-4 minus four
+-3 minus three
+
+1 one
+2 two
+3 three
diff --git a/test/data/shr/ul-empty.html b/test/lisp/net/shr-resources/ul-empty.html
index e5a75ab9216..e5a75ab9216 100644
--- a/test/data/shr/ul-empty.html
+++ b/test/lisp/net/shr-resources/ul-empty.html
diff --git a/test/data/shr/ul-empty.txt b/test/lisp/net/shr-resources/ul-empty.txt
index 8993555425b..8993555425b 100644
--- a/test/data/shr/ul-empty.txt
+++ b/test/lisp/net/shr-resources/ul-empty.txt
diff --git a/test/lisp/net/shr-tests.el b/test/lisp/net/shr-tests.el
index 3a30141668f..2254f9bc860 100644
--- a/test/lisp/net/shr-tests.el
+++ b/test/lisp/net/shr-tests.el
@@ -1,6 +1,6 @@
-;;; network-stream-tests.el --- tests for network processes -*- lexical-binding: t; -*-
+;;; shr-tests.el --- tests for shr.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2016-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2022 Free Software Foundation, Inc.
;; Author: Lars Ingebrigtsen <larsi@gnus.org>
@@ -23,14 +23,15 @@
;;; Code:
+(require 'ert)
+(require 'ert-x)
(require 'shr)
-(defconst shr-tests--datadir
- (expand-file-name "test/data/shr" source-directory))
+(declare-function libxml-parse-html-region "xml.c")
(defun shr-test (name)
(with-temp-buffer
- (insert-file-contents (format (concat shr-tests--datadir "/%s.html") name))
+ (insert-file-contents (format (concat (ert-resource-directory) "/%s.html") name))
(let ((dom (libxml-parse-html-region (point-min) (point-max)))
(shr-width 80)
(shr-use-fonts nil))
@@ -39,7 +40,7 @@
(cons (buffer-substring-no-properties (point-min) (point-max))
(with-temp-buffer
(insert-file-contents
- (format (concat shr-tests--datadir "/%s.txt") name))
+ (format (concat (ert-resource-directory) "/%s.txt") name))
(while (re-search-forward "%\\([0-9A-F][0-9A-F]\\)" nil t)
(replace-match (string (string-to-number (match-string 1) 16))
t t))
@@ -47,12 +48,40 @@
(ert-deftest rendering ()
(skip-unless (fboundp 'libxml-parse-html-region))
- (dolist (file (directory-files shr-tests--datadir nil "\\.html\\'"))
+ (dolist (file (directory-files (ert-resource-directory) nil "\\.html\\'"))
(let* ((name (replace-regexp-in-string "\\.html\\'" "" file))
(result (shr-test name)))
(unless (equal (car result) (cdr result))
(should (not (list name (car result) (cdr result))))))))
+(ert-deftest use-cookies ()
+ (let ((shr-cookie-policy 'same-origin))
+ (should
+ (shr--use-cookies-p "http://images.fsf.org" '("http://www.fsf.org")))
+ (should
+ (shr--use-cookies-p "http://www.fsf.org" '("https://www.fsf.org")))
+ (should
+ (shr--use-cookies-p "http://www.fsf.org" '("https://www.fsf.org")))
+ (should
+ (shr--use-cookies-p "http://www.fsf.org" '("http://fsf.org")))
+ (should-not
+ (shr--use-cookies-p "http://www.gnu.org" '("http://www.fsf.org")))))
+
+(ert-deftest shr-srcset ()
+ (should (equal (shr--parse-srcset "") nil))
+
+ (should (equal (shr--parse-srcset "a 10w, b 20w")
+ '(("b" 20) ("a" 10))))
+
+ (should (equal (shr--parse-srcset "a 10w b 20w")
+ '(("a" 10))))
+
+ (should (equal (shr--parse-srcset "https://example.org/1\n\n 10w , https://example.org/2 20w ")
+ '(("https://example.org/2" 20) ("https://example.org/1" 10))))
+
+ (should (equal (shr--parse-srcset "https://example.org/1,2\n\n 10w , https://example.org/2 20w ")
+ '(("https://example.org/2" 20) ("https://example.org/1,2" 10)))))
+
(require 'shr)
-;;; shr-stream-tests.el ends here
+;;; shr-tests.el ends here
diff --git a/test/lisp/net/socks-tests.el b/test/lisp/net/socks-tests.el
new file mode 100644
index 00000000000..461796bdf99
--- /dev/null
+++ b/test/lisp/net/socks-tests.el
@@ -0,0 +1,284 @@
+;;; socks-tests.el --- tests for SOCKS -*- coding: utf-8; lexical-binding: t; -*-
+
+;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'socks)
+(require 'url-http)
+
+(ert-deftest socks-tests-auth-registration-and-suite-offer ()
+ (ert-info ("Default favors user/pass auth")
+ (should (equal socks-authentication-methods
+ '((2 "Username/Password" . socks-username/password-auth)
+ (0 "No authentication" . identity))))
+ (should (equal "\2\0\2" (socks-build-auth-list)))) ; length [offer ...]
+ (let (socks-authentication-methods)
+ (ert-info ("Empty selection/no methods offered")
+ (should (equal "\0" (socks-build-auth-list))))
+ (ert-info ("Simulate library defaults")
+ (socks-register-authentication-method 0 "No authentication"
+ 'identity)
+ (should (equal socks-authentication-methods
+ '((0 "No authentication" . identity))))
+ (should (equal "\1\0" (socks-build-auth-list)))
+ (socks-register-authentication-method 2 "Username/Password"
+ 'socks-username/password-auth)
+ (should (equal socks-authentication-methods
+ '((2 "Username/Password" . socks-username/password-auth)
+ (0 "No authentication" . identity))))
+ (should (equal "\2\0\2" (socks-build-auth-list))))
+ (ert-info ("Removal")
+ (socks-unregister-authentication-method 2)
+ (should (equal socks-authentication-methods
+ '((0 "No authentication" . identity))))
+ (should (equal "\1\0" (socks-build-auth-list)))
+ (socks-unregister-authentication-method 0)
+ (should-not socks-authentication-methods)
+ (should (equal "\0" (socks-build-auth-list))))))
+
+(ert-deftest socks-tests-filter-response-parsing-v4 ()
+ "Ensure new chunks added on right (Bug#45162)."
+ (let* ((buf (generate-new-buffer "*test-socks-filter*"))
+ (proc (start-process "test-socks-filter" buf "sleep" "1")))
+ (process-put proc 'socks t)
+ (process-put proc 'socks-state socks-state-waiting)
+ (process-put proc 'socks-server-protocol 4)
+ (ert-info ("Receive initial incomplete segment")
+ (socks-filter proc (concat [0 90 0 0 93 184 216]))
+ ;; From example.com: OK status ^ ^ msg start
+ (ert-info ("State still set to waiting")
+ (should (eq (process-get proc 'socks-state) socks-state-waiting)))
+ (ert-info ("Response field is nil because processing incomplete")
+ (should-not (process-get proc 'socks-response)))
+ (ert-info ("Scratch field holds stashed partial payload")
+ (should (string= (concat [0 90 0 0 93 184 216])
+ (process-get proc 'socks-scratch)))))
+ (ert-info ("Last part arrives")
+ (socks-filter proc "\42") ; ?\" 34
+ (ert-info ("State transitions to complete (length check passes)")
+ (should (eq (process-get proc 'socks-state) socks-state-connected)))
+ (ert-info ("Scratch and response fields hold stash w. last chunk")
+ (should (string= (concat [0 90 0 0 93 184 216 34])
+ (process-get proc 'socks-response)))
+ (should (string= (process-get proc 'socks-response)
+ (process-get proc 'socks-scratch)))))
+ (delete-process proc)
+ (kill-buffer buf)))
+
+(ert-deftest socks-tests-filter-response-parsing-v5 ()
+ "Ensure new chunks added on right (Bug#45162)."
+ (let* ((buf (generate-new-buffer "*test-socks-filter*"))
+ (proc (start-process "test-socks-filter" buf "sleep" "1")))
+ (process-put proc 'socks t)
+ (process-put proc 'socks-state socks-state-waiting)
+ (process-put proc 'socks-server-protocol 5)
+ (ert-info ("Receive initial incomplete segment")
+ ;; From fedora.org: 2605:bc80:3010:600:dead:beef:cafe:fed9
+ ;; 5004 ~~> Version Status (OK) NOOP Addr-Type (4 -> IPv6)
+ (socks-filter proc "\5\0\0\4\x26\x05\xbc\x80\x30\x10\x00\x60")
+ (ert-info ("State still waiting and response empty")
+ (should (eq (process-get proc 'socks-state) socks-state-waiting))
+ (should-not (process-get proc 'socks-response)))
+ (ert-info ("Scratch field holds partial payload of pending msg")
+ (should (string= "\5\0\0\4\x26\x05\xbc\x80\x30\x10\x00\x60"
+ (process-get proc 'socks-scratch)))))
+ (ert-info ("Middle chunk arrives")
+ (socks-filter proc "\xde\xad\xbe\xef\xca\xfe\xfe\xd9")
+ (ert-info ("State and response fields still untouched")
+ (should (eq (process-get proc 'socks-state) socks-state-waiting))
+ (should-not (process-get proc 'socks-response)))
+ (ert-info ("Scratch contains new arrival appended (on RHS)")
+ (should (string= (concat "\5\0\0\4"
+ "\x26\x05\xbc\x80\x30\x10\x00\x60"
+ "\xde\xad\xbe\xef\xca\xfe\xfe\xd9")
+ (process-get proc 'socks-scratch)))))
+ (ert-info ("Final part arrives (port number)")
+ (socks-filter proc "\0\0")
+ (ert-info ("State transitions to complete")
+ (should (eq (process-get proc 'socks-state) socks-state-connected)))
+ (ert-info ("Scratch and response fields show last chunk appended")
+ (should (string= (concat "\5\0\0\4"
+ "\x26\x05\xbc\x80\x30\x10\x00\x60"
+ "\xde\xad\xbe\xef\xca\xfe\xfe\xd9"
+ "\0\0")
+ (process-get proc 'socks-scratch)))
+ (should (string= (process-get proc 'socks-response)
+ (process-get proc 'socks-scratch)))))
+ (delete-process proc)
+ (kill-buffer buf)))
+
+(defvar socks-tests-canned-server-patterns nil
+ "Alist containing request/response cons pairs to be tried in order.
+Vectors must match verbatim. Strings are considered regex patterns.")
+
+(defun socks-tests-canned-server-create ()
+ "Create and return a fake SOCKS server."
+ (let* ((port (nth 2 socks-server))
+ (name (format "socks-server:%d" port))
+ (pats socks-tests-canned-server-patterns)
+ (filt (lambda (proc line)
+ (pcase-let ((`(,pat . ,resp) (pop pats)))
+ (unless (or (and (vectorp pat) (equal pat (vconcat line)))
+ (string-match-p pat line))
+ (error "Unknown request: %s" line))
+ (let ((print-escape-control-characters t))
+ (message "[%s] <- %s" name (prin1-to-string line))
+ (message "[%s] -> %s" name (prin1-to-string resp)))
+ (process-send-string proc (concat resp)))))
+ (serv (make-network-process :server 1
+ :buffer (get-buffer-create name)
+ :filter filt
+ :name name
+ :family 'ipv4
+ :host 'local
+ :coding 'binary
+ :service port)))
+ (set-process-query-on-exit-flag serv nil)
+ serv))
+
+(defvar socks-tests--hello-world-http-request-pattern
+ (cons "^GET /" (concat "HTTP/1.1 200 OK\r\n"
+ "Content-Type: text/plain\r\n"
+ "Content-Length: 13\r\n\r\n"
+ "Hello World!\n")))
+
+(defun socks-tests-perform-hello-world-http-request ()
+ "Start canned server, validate hello-world response, and finalize."
+ (let* ((url-gateway-method 'socks)
+ (url (url-generic-parse-url "http://example.com"))
+ (server (socks-tests-canned-server-create))
+ ;;
+ done
+ ;;
+ (cb (lambda (&rest _r)
+ (goto-char (point-min))
+ (should (search-forward "Hello World" nil t))
+ (setq done t)))
+ (inhibit-message noninteractive)
+ (buf (url-http url cb '(nil)))
+ (proc (get-buffer-process buf))
+ (attempts 10))
+ (while (and (not done) (< 0 (cl-decf attempts)))
+ (sleep-for 0.1))
+ (should done)
+ (delete-process server)
+ (delete-process proc) ; otherwise seems client proc is sometimes reused
+ (kill-buffer (process-buffer server))
+ (kill-buffer buf)
+ (ignore url-gateway-method)))
+
+;; Unlike curl, socks.el includes the ID field (but otherwise matches):
+;; $ curl --proxy socks4://127.0.0.1:1080 example.com
+
+(ert-deftest socks-tests-v4-basic ()
+ "Show correct preparation of SOCKS4 connect command (Bug#46342)."
+ (let ((socks-server '("server" "127.0.0.1" 10079 4))
+ (url-user-agent "Test/4-basic")
+ (socks-tests-canned-server-patterns
+ `(([4 1 0 80 93 184 216 34 ?f ?o ?o 0] . [0 90 0 0 0 0 0 0])
+ ,socks-tests--hello-world-http-request-pattern))
+ socks-nslookup-program)
+ (ert-info ("Make HTTP request over SOCKS4")
+ (cl-letf (((symbol-function 'socks-nslookup-host)
+ (lambda (host)
+ (should (equal host "example.com"))
+ (list 93 184 216 34)))
+ ((symbol-function 'user-full-name)
+ (lambda (&optional _) "foo")))
+ (socks-tests-perform-hello-world-http-request)))))
+
+;; Replace first pattern below with ([5 3 0 1 2] . [5 2]) to validate
+;; against curl 7.71 with the following options:
+;; $ curl --verbose -U foo:bar --proxy socks5h://127.0.0.1:10080 example.com
+
+(ert-deftest socks-tests-v5-auth-user-pass ()
+ "Verify correct handling of SOCKS5 user/pass authentication."
+ (should (assq 2 socks-authentication-methods))
+ (let ((socks-server '("server" "127.0.0.1" 10080 5))
+ (socks-username "foo")
+ (socks-password "bar")
+ (url-user-agent "Test/auth-user-pass")
+ (socks-tests-canned-server-patterns
+ `(([5 2 0 2] . [5 2])
+ ([1 3 ?f ?o ?o 3 ?b ?a ?r] . [1 0])
+ ([5 1 0 3 11 ?e ?x ?a ?m ?p ?l ?e ?. ?c ?o ?m 0 80]
+ . [5 0 0 1 0 0 0 0 0 0])
+ ,socks-tests--hello-world-http-request-pattern)))
+ (ert-info ("Make HTTP request over SOCKS5 with USER/PASS auth method")
+ (socks-tests-perform-hello-world-http-request))))
+
+;; Services (like Tor) may be configured without auth but for some
+;; reason still prefer the user/pass method over none when offered both.
+;; Given this library's defaults, the scenario below is possible.
+;;
+;; FYI: RFC 1929 doesn't say that a username or password is required
+;; but notes that the length of both fields should be at least one.
+;; However, both socks.el and curl send zero-length fields (though
+;; curl drops the user part too when the password is empty).
+;;
+;; From Tor's docs /socks-extensions.txt, 1.1 Extent of support:
+;; > We allow username/password fields of this message to be empty ...
+;; line 41 in blob 5fd1f828f3e9d014f7b65fa3bd1d33c39e4129e2
+;; https://gitweb.torproject.org/torspec.git/tree/socks-extensions.txt
+;;
+;; To verify against curl 7.71, swap out the first two pattern pairs
+;; with ([5 3 0 1 2] . [5 2]) and ([1 0 0] . [1 0]), then run:
+;; $ curl verbose -U "foo:" --proxy socks5h://127.0.0.1:10081 example.com
+
+(ert-deftest socks-tests-v5-auth-user-pass-blank ()
+ "Verify correct SOCKS5 user/pass authentication with empty pass."
+ (should (assq 2 socks-authentication-methods))
+ (let ((socks-server '("server" "127.0.0.1" 10081 5))
+ (socks-username "foo") ; defaults to (user-login-name)
+ (socks-password "") ; simulate user hitting enter when prompted
+ (url-user-agent "Test/auth-user-pass-blank")
+ (socks-tests-canned-server-patterns
+ `(([5 2 0 2] . [5 2])
+ ([1 3 ?f ?o ?o 0] . [1 0])
+ ([5 1 0 3 11 ?e ?x ?a ?m ?p ?l ?e ?. ?c ?o ?m 0 80]
+ . [5 0 0 1 0 0 0 0 0 0])
+ ,socks-tests--hello-world-http-request-pattern)))
+ (ert-info ("Make HTTP request over SOCKS5 with USER/PASS auth method")
+ (socks-tests-perform-hello-world-http-request))))
+
+;; Swap out ([5 2 0 1] . [5 0]) with the first pattern below to validate
+;; against curl 7.71 with the following options:
+;; $ curl --verbose --proxy socks5h://127.0.0.1:10082 example.com
+
+(ert-deftest socks-tests-v5-auth-none ()
+ "Verify correct handling of SOCKS5 when auth method 0 requested."
+ (let ((socks-server '("server" "127.0.0.1" 10082 5))
+ (socks-authentication-methods (append socks-authentication-methods
+ nil))
+ (url-user-agent "Test/auth-none")
+ (socks-tests-canned-server-patterns
+ `(([5 1 0] . [5 0])
+ ([5 1 0 3 11 ?e ?x ?a ?m ?p ?l ?e ?. ?c ?o ?m 0 80]
+ . [5 0 0 1 0 0 0 0 0 0])
+ ,socks-tests--hello-world-http-request-pattern)))
+ (socks-unregister-authentication-method 2)
+ (should-not (assq 2 socks-authentication-methods))
+ (ert-info ("Make HTTP request over SOCKS5 with no auth method")
+ (socks-tests-perform-hello-world-http-request)))
+ (should (assq 2 socks-authentication-methods)))
+
+;;; socks-tests.el ends here
diff --git a/test/lisp/net/tramp-archive-resources/foo.iso/foo b/test/lisp/net/tramp-archive-resources/foo.iso/foo
new file mode 100644
index 00000000000..257cc5642cb
--- /dev/null
+++ b/test/lisp/net/tramp-archive-resources/foo.iso/foo
@@ -0,0 +1 @@
+foo
diff --git a/test/lisp/net/tramp-archive-resources/foo.tar.gz b/test/lisp/net/tramp-archive-resources/foo.tar.gz
new file mode 100644
index 00000000000..0d2e9878dd7
--- /dev/null
+++ b/test/lisp/net/tramp-archive-resources/foo.tar.gz
Binary files differ
diff --git a/test/lisp/net/tramp-archive-tests.el b/test/lisp/net/tramp-archive-tests.el
new file mode 100644
index 00000000000..f8a0aa03e32
--- /dev/null
+++ b/test/lisp/net/tramp-archive-tests.el
@@ -0,0 +1,1045 @@
+;;; tramp-archive-tests.el --- Tests of file archive access -*- lexical-binding:t -*-
+
+;; Copyright (C) 2017-2022 Free Software Foundation, Inc.
+
+;; Author: Michael Albinus <michael.albinus@gmx.de>
+
+;; This file is part of GNU Emacs.
+;;
+;; GNU Emacs is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; GNU Emacs is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; A testsuite for testing file archives.
+
+;;; Code:
+
+;; The `tramp-archive-testnn-*' tests correspond to the respective
+;; tests in tramp-tests.el.
+
+(require 'ert)
+(require 'ert-x)
+(require 'tramp-archive)
+(defvar tramp-persistency-file-name)
+
+;; `ert-resource-file' was introduced in Emacs 28.1.
+(unless (macrop 'ert-resource-file)
+ (eval-and-compile
+ (defvar ert-resource-directory-format "%s-resources/"
+ "Format for `ert-resource-directory'.")
+ (defvar ert-resource-directory-trim-left-regexp ""
+ "Regexp for `string-trim' (left) used by `ert-resource-directory'.")
+ (defvar ert-resource-directory-trim-right-regexp
+ (rx (? "-test" (? "s")) ".el")
+ "Regexp for `string-trim' (right) used by `ert-resource-directory'.")
+
+ (defmacro ert-resource-directory ()
+ "Return absolute file name of the resource directory for this file.
+
+The path to the resource directory is the \"resources\" directory
+in the same directory as the test file.
+
+If that directory doesn't exist, use the directory named like the
+test file but formatted by `ert-resource-directory-format' and trimmed
+using `string-trim' with arguments
+`ert-resource-directory-trim-left-regexp' and
+`ert-resource-directory-trim-right-regexp'. The default values mean
+that if called from a test file named \"foo-tests.el\", return
+the absolute file name for \"foo-resources\"."
+ `(let* ((testfile ,(or (bound-and-true-p byte-compile-current-file)
+ (and load-in-progress load-file-name)
+ buffer-file-name))
+ (default-directory (file-name-directory testfile)))
+ (file-truename
+ (if (file-accessible-directory-p "resources/")
+ (expand-file-name "resources/")
+ (expand-file-name
+ (format
+ ert-resource-directory-format
+ (string-trim testfile
+ ert-resource-directory-trim-left-regexp
+ ert-resource-directory-trim-right-regexp)))))))
+
+ (defmacro ert-resource-file (file)
+ "Return file name of resource file named FILE.
+A resource file is in the resource directory as per
+`ert-resource-directory'."
+ `(expand-file-name ,file (ert-resource-directory)))))
+
+(defconst tramp-archive-test-file-archive (ert-resource-file "foo.tar.gz")
+ "The test file archive.")
+
+(defun tramp-archive-test-file-archive-hexlified ()
+ "Return hexlified `tramp-archive-test-file-archive'.
+Do not hexlify \"/\". This hexlified string is used in `file:///' URLs."
+ (let* ((url-unreserved-chars (cons ?/ url-unreserved-chars)))
+ (url-hexify-string tramp-archive-test-file-archive)))
+
+(defconst tramp-archive-test-archive
+ (file-name-as-directory tramp-archive-test-file-archive)
+ "The test archive.")
+
+(defconst tramp-archive-test-directory
+ (file-truename (ert-resource-file "foo.iso"))
+ "A directory file name, which looks like an archive.")
+
+(setq password-cache-expiry nil
+ tramp-cache-read-persistent-data t ;; For auth-sources.
+ tramp-persistency-file-name nil
+ tramp-verbose 0)
+
+(defun tramp-archive--test-make-temp-name ()
+ "Return a temporary file name for test.
+The temporary file is not created."
+ (expand-file-name
+ (make-temp-name "tramp-archive-test") temporary-file-directory))
+
+(defun tramp-archive--test-delete (tmpfile)
+ "Delete temporary file or directory TMPFILE.
+This needs special support, because archive file names, which are
+the origin of the temporary TMPFILE, have no write permissions."
+ (unless (file-writable-p (file-name-directory tmpfile))
+ (set-file-modes
+ (file-name-directory tmpfile)
+ (logior (file-modes (file-name-directory tmpfile)) #o0700)))
+ (set-file-modes tmpfile #o0700)
+ (if (file-regular-p tmpfile)
+ (delete-file tmpfile)
+ (mapc
+ #'tramp-archive--test-delete
+ (directory-files tmpfile 'full directory-files-no-dot-files-regexp))
+ (delete-directory tmpfile)))
+
+(defun tramp-archive--test-emacs27-p ()
+ "Check for Emacs version >= 27.1.
+Some semantics has been changed for there, w/o new functions or
+variables, so we check the Emacs version directly."
+ (>= emacs-major-version 27))
+
+(ert-deftest tramp-archive-test00-availability ()
+ "Test availability of archive file name functions."
+ :expected-result (if tramp-archive-enabled :passed :failed)
+ (should
+ (and
+ tramp-archive-enabled
+ (file-exists-p tramp-archive-test-file-archive)
+ (tramp-archive-file-name-p tramp-archive-test-archive))))
+
+(ert-deftest tramp-archive-test01-file-name-syntax ()
+ "Check archive file name syntax."
+ (should-not (tramp-archive-file-name-p tramp-archive-test-file-archive))
+ (should (tramp-archive-file-name-p tramp-archive-test-archive))
+ (should
+ (string-equal
+ (tramp-archive-file-name-archive tramp-archive-test-archive)
+ tramp-archive-test-file-archive))
+ (should
+ (string-equal
+ (tramp-archive-file-name-localname tramp-archive-test-archive) "/"))
+ (should (tramp-archive-file-name-p (concat tramp-archive-test-archive "foo")))
+ (should
+ (string-equal
+ (tramp-archive-file-name-localname
+ (concat tramp-archive-test-archive "foo"))
+ "/foo"))
+ (should
+ (tramp-archive-file-name-p (concat tramp-archive-test-archive "foo/bar")))
+ (should
+ (string-equal
+ (tramp-archive-file-name-localname
+ (concat tramp-archive-test-archive "foo/bar"))
+ "/foo/bar"))
+ ;; A file archive inside a file archive.
+ (should
+ (tramp-archive-file-name-p (concat tramp-archive-test-archive "baz.tar")))
+ (should
+ (string-equal
+ (tramp-archive-file-name-archive
+ (concat tramp-archive-test-archive "baz.tar"))
+ tramp-archive-test-file-archive))
+ (should
+ (string-equal
+ (tramp-archive-file-name-localname
+ (concat tramp-archive-test-archive "baz.tar"))
+ "/baz.tar"))
+ (should
+ (tramp-archive-file-name-p (concat tramp-archive-test-archive "baz.tar/")))
+ (should
+ (string-equal
+ (tramp-archive-file-name-archive
+ (concat tramp-archive-test-archive "baz.tar/"))
+ (concat tramp-archive-test-archive "baz.tar")))
+ (should
+ (string-equal
+ (tramp-archive-file-name-localname
+ (concat tramp-archive-test-archive "baz.tar/"))
+ "/")))
+
+(ert-deftest tramp-archive-test02-file-name-dissect ()
+ "Check archive file name components."
+ (skip-unless tramp-archive-enabled)
+
+ ;; Suppress method name check.
+ (let ((non-essential t))
+ (with-parsed-tramp-archive-file-name tramp-archive-test-archive nil
+ (should (string-equal method tramp-archive-method))
+ (should-not user)
+ (should-not domain)
+ (should
+ (string-equal
+ host
+ (file-remote-p
+ (tramp-archive-gvfs-file-name tramp-archive-test-archive) 'host)))
+ (should
+ (string-equal
+ host
+ (url-hexify-string
+ (concat "file://" (tramp-archive-test-file-archive-hexlified)))))
+ (should-not port)
+ (should (string-equal localname "/"))
+ (should (string-equal archive tramp-archive-test-file-archive)))
+
+ ;; Localname.
+ (with-parsed-tramp-archive-file-name
+ (concat tramp-archive-test-archive "foo") nil
+ (should (string-equal method tramp-archive-method))
+ (should-not user)
+ (should-not domain)
+ (should
+ (string-equal
+ host
+ (file-remote-p
+ (tramp-archive-gvfs-file-name tramp-archive-test-archive) 'host)))
+ (should
+ (string-equal
+ host
+ (url-hexify-string
+ (concat "file://" (tramp-archive-test-file-archive-hexlified)))))
+ (should-not port)
+ (should (string-equal localname "/foo"))
+ (should (string-equal archive tramp-archive-test-file-archive)))
+
+ ;; File archive in file archive.
+ (let* ((tramp-archive-test-file-archive
+ (concat tramp-archive-test-archive "baz.tar"))
+ (tramp-archive-test-archive
+ (file-name-as-directory tramp-archive-test-file-archive))
+ (tramp-methods (cons `(,tramp-archive-method) tramp-methods))
+ (tramp-gvfs-methods tramp-archive-all-gvfs-methods))
+ (unwind-protect
+ (with-parsed-tramp-archive-file-name
+ (expand-file-name "bar" tramp-archive-test-archive) nil
+ (should (string-equal method tramp-archive-method))
+ (should-not user)
+ (should-not domain)
+ (should
+ (string-equal
+ host
+ (file-remote-p
+ (tramp-archive-gvfs-file-name tramp-archive-test-archive)
+ 'host)))
+ ;; We reimplement the logic of tramp-archive.el here.
+ ;; Don't know, whether it is worth the test.
+ (should
+ (string-equal
+ host
+ (url-hexify-string
+ (concat
+ (tramp-gvfs-url-file-name
+ (tramp-make-tramp-file-name
+ (make-tramp-file-name
+ :method tramp-archive-method
+ :host
+ (url-hexify-string
+ (concat
+ "file://"
+ ;; `directory-file-name' does not leave file
+ ;; archive boundaries. So we must cut the
+ ;; trailing slash ourselves.
+ (substring
+ (file-name-directory
+ (tramp-archive-test-file-archive-hexlified))
+ 0 -1)))
+ :localname "/")))
+ (file-name-nondirectory tramp-archive-test-file-archive)))))
+ (should-not port)
+ (should (string-equal localname "/bar"))
+ (should (string-equal archive tramp-archive-test-file-archive)))
+
+ ;; Cleanup.
+ (tramp-archive-cleanup-hash)))))
+
+(ert-deftest tramp-archive-test05-expand-file-name ()
+ "Check `expand-file-name'."
+ (should
+ (string-equal
+ (expand-file-name (concat tramp-archive-test-archive "path/./file"))
+ (concat tramp-archive-test-archive "path/file")))
+ (should
+ (string-equal
+ (expand-file-name (concat tramp-archive-test-archive "path/../file"))
+ (concat tramp-archive-test-archive "file")))
+ ;; `expand-file-name' does not care "~/" in archive file names.
+ (should
+ (string-equal
+ (expand-file-name (concat tramp-archive-test-archive "~/file"))
+ (concat tramp-archive-test-archive "~/file")))
+ ;; `expand-file-name' does not care file archive boundaries.
+ (should
+ (string-equal
+ (expand-file-name (concat tramp-archive-test-archive "./file"))
+ (concat tramp-archive-test-archive "file")))
+ (should
+ (string-equal
+ (expand-file-name (concat tramp-archive-test-archive "../file"))
+ (concat (ert-resource-directory) "file"))))
+
+;; This test is inspired by Bug#30293.
+(ert-deftest tramp-archive-test05-expand-file-name-non-archive-directory ()
+ "Check existing directories with archive file name syntax.
+They shall still be supported"
+ (should (file-directory-p tramp-archive-test-directory))
+ ;; `tramp-archive-file-name-p' tests only for file name syntax. It
+ ;; doesn't test, whether it is really a file archive.
+ (should
+ (tramp-archive-file-name-p
+ (file-name-as-directory tramp-archive-test-directory)))
+ (should
+ (file-directory-p (file-name-as-directory tramp-archive-test-directory)))
+ (should
+ (file-exists-p (expand-file-name "foo" tramp-archive-test-directory))))
+
+(ert-deftest tramp-archive-test06-directory-file-name ()
+ "Check `directory-file-name'.
+This checks also `file-name-as-directory', `file-name-directory',
+`file-name-nondirectory' and `unhandled-file-name-directory'."
+ (skip-unless tramp-archive-enabled)
+
+ (should
+ (string-equal
+ (directory-file-name (concat tramp-archive-test-archive "path/to/file"))
+ (concat tramp-archive-test-archive "path/to/file")))
+ (should
+ (string-equal
+ (directory-file-name (concat tramp-archive-test-archive "path/to/file/"))
+ (concat tramp-archive-test-archive "path/to/file")))
+ ;; `directory-file-name' does not leave file archive boundaries.
+ (should
+ (string-equal
+ (directory-file-name tramp-archive-test-archive) tramp-archive-test-archive))
+
+ (should
+ (string-equal
+ (file-name-as-directory (concat tramp-archive-test-archive "path/to/file"))
+ (concat tramp-archive-test-archive "path/to/file/")))
+ (should
+ (string-equal
+ (file-name-as-directory (concat tramp-archive-test-archive "path/to/file/"))
+ (concat tramp-archive-test-archive "path/to/file/")))
+ (should
+ (string-equal
+ (file-name-as-directory tramp-archive-test-archive)
+ tramp-archive-test-archive))
+ (should
+ (string-equal
+ (file-name-as-directory tramp-archive-test-file-archive)
+ tramp-archive-test-archive))
+
+ (should
+ (string-equal
+ (file-name-directory (concat tramp-archive-test-archive "path/to/file"))
+ (concat tramp-archive-test-archive "path/to/")))
+ (should
+ (string-equal
+ (file-name-directory (concat tramp-archive-test-archive "path/to/file/"))
+ (concat tramp-archive-test-archive "path/to/file/")))
+ (should
+ (string-equal
+ (file-name-directory tramp-archive-test-archive) tramp-archive-test-archive))
+
+ (should
+ (string-equal
+ (file-name-nondirectory (concat tramp-archive-test-archive "path/to/file"))
+ "file"))
+ (should
+ (string-equal
+ (file-name-nondirectory (concat tramp-archive-test-archive "path/to/file/"))
+ ""))
+ (should (string-equal (file-name-nondirectory tramp-archive-test-archive) ""))
+
+ (should-not
+ (unhandled-file-name-directory
+ (concat tramp-archive-test-archive "path/to/file"))))
+
+(ert-deftest tramp-archive-test07-file-exists-p ()
+ "Check `file-exist-p', `write-region' and `delete-file'."
+ :tags '(:expensive-test)
+ (skip-unless tramp-archive-enabled)
+
+ (unwind-protect
+ (let ((default-directory tramp-archive-test-archive))
+ (should (file-exists-p tramp-archive-test-file-archive))
+ (should (file-exists-p tramp-archive-test-archive))
+ (should (file-exists-p "foo.txt"))
+ (should (file-exists-p "foo.lnk"))
+ (should (file-exists-p "bar"))
+ (should (file-exists-p "bar/bar"))
+ (should-error
+ (write-region "foo" nil "baz")
+ :type 'file-error)
+ (should-error
+ (delete-file "baz")
+ :type 'file-error))
+
+ ;; Cleanup.
+ (tramp-archive-cleanup-hash)))
+
+(ert-deftest tramp-archive-test08-file-local-copy ()
+ "Check `file-local-copy'."
+ :tags '(:expensive-test)
+ (skip-unless tramp-archive-enabled)
+
+ (let (tmp-name)
+ (unwind-protect
+ (progn
+ (should
+ (setq tmp-name
+ (file-local-copy
+ (expand-file-name "bar/bar" tramp-archive-test-archive))))
+ (with-temp-buffer
+ (insert-file-contents tmp-name)
+ (should (string-equal (buffer-string) "bar\n")))
+ ;; Error case.
+ (tramp-archive--test-delete tmp-name)
+ (should-error
+ (setq tmp-name
+ (file-local-copy
+ (expand-file-name "what" tramp-archive-test-archive)))
+ :type 'file-missing))
+
+ ;; Cleanup.
+ (ignore-errors (tramp-archive--test-delete tmp-name))
+ (tramp-archive-cleanup-hash))))
+
+(ert-deftest tramp-archive-test09-insert-file-contents ()
+ "Check `insert-file-contents'."
+ :tags '(:expensive-test)
+ (skip-unless tramp-archive-enabled)
+
+ (let ((tmp-name (expand-file-name "bar/bar" tramp-archive-test-archive)))
+ (unwind-protect
+ (with-temp-buffer
+ (insert-file-contents tmp-name)
+ (should (string-equal (buffer-string) "bar\n"))
+ (insert-file-contents tmp-name)
+ (should (string-equal (buffer-string) "bar\nbar\n"))
+ ;; Insert partly.
+ (insert-file-contents tmp-name nil 1 3)
+ (should (string-equal (buffer-string) "arbar\nbar\n"))
+ ;; Replace.
+ (insert-file-contents tmp-name nil nil nil 'replace)
+ (should (string-equal (buffer-string) "bar\n"))
+ ;; Error case.
+ (should-error
+ (insert-file-contents
+ (expand-file-name "what" tramp-archive-test-archive))
+ :type 'file-missing))
+
+ ;; Cleanup.
+ (tramp-archive-cleanup-hash))))
+
+(ert-deftest tramp-archive-test11-copy-file ()
+ "Check `copy-file'."
+ :tags '(:expensive-test)
+ (skip-unless tramp-archive-enabled)
+
+ ;; Copy simple file.
+ (let ((tmp-name1 (expand-file-name "bar/bar" tramp-archive-test-archive))
+ (tmp-name2 (tramp-archive--test-make-temp-name)))
+ (unwind-protect
+ (progn
+ (copy-file tmp-name1 tmp-name2)
+ (should (file-exists-p tmp-name2))
+ (with-temp-buffer
+ (insert-file-contents tmp-name2)
+ (should (string-equal (buffer-string) "bar\n")))
+ (should-error
+ (copy-file tmp-name1 tmp-name2)
+ :type 'file-already-exists)
+ (copy-file tmp-name1 tmp-name2 'ok)
+ ;; The file archive is not writable.
+ (should-error
+ (copy-file tmp-name2 tmp-name1 'ok)
+ :type 'file-error))
+
+ ;; Cleanup.
+ (ignore-errors (tramp-archive--test-delete tmp-name2))
+ (tramp-archive-cleanup-hash)))
+
+ ;; Copy directory to existing directory.
+ (let ((tmp-name1 (expand-file-name "bar" tramp-archive-test-archive))
+ (tmp-name2 (tramp-archive--test-make-temp-name)))
+ (unwind-protect
+ (progn
+ (make-directory tmp-name2)
+ (should (file-directory-p tmp-name2))
+ ;; Directory `tmp-name2' exists already, so we must use
+ ;; `file-name-as-directory'.
+ (copy-file tmp-name1 (file-name-as-directory tmp-name2))
+ (should
+ (file-exists-p
+ (expand-file-name
+ (concat (file-name-nondirectory tmp-name1) "/bar") tmp-name2))))
+
+ ;; Cleanup.
+ (ignore-errors (tramp-archive--test-delete tmp-name2))
+ (tramp-archive-cleanup-hash)))
+
+ ;; Copy directory/file to non-existing directory.
+ (let ((tmp-name1 (expand-file-name "bar" tramp-archive-test-archive))
+ (tmp-name2 (tramp-archive--test-make-temp-name)))
+ (unwind-protect
+ (progn
+ (make-directory tmp-name2)
+ (should (file-directory-p tmp-name2))
+ (copy-file
+ tmp-name1
+ (expand-file-name (file-name-nondirectory tmp-name1) tmp-name2))
+ (should
+ (file-exists-p
+ (expand-file-name
+ (concat (file-name-nondirectory tmp-name1) "/bar") tmp-name2))))
+
+ ;; Cleanup.
+ (ignore-errors (tramp-archive--test-delete tmp-name2))
+ (tramp-archive-cleanup-hash))))
+
+(ert-deftest tramp-archive-test15-copy-directory ()
+ "Check `copy-directory'."
+ :tags '(:expensive-test)
+ (skip-unless tramp-archive-enabled)
+
+ (let* ((tmp-name1 (expand-file-name "bar" tramp-archive-test-archive))
+ (tmp-name2 (tramp-archive--test-make-temp-name))
+ (tmp-name3 (expand-file-name
+ (file-name-nondirectory tmp-name1) tmp-name2))
+ (tmp-name4 (expand-file-name "bar" tmp-name2))
+ (tmp-name5 (expand-file-name "bar" tmp-name3)))
+
+ ;; Copy complete directory.
+ (unwind-protect
+ (progn
+ ;; Copy empty directory.
+ (copy-directory tmp-name1 tmp-name2)
+ (should (file-directory-p tmp-name2))
+ (should (file-exists-p tmp-name4))
+ ;; Target directory does exist already.
+ (should-error
+ (copy-directory tmp-name1 tmp-name2)
+ :type 'file-error)
+ (tramp-archive--test-delete tmp-name4)
+ (copy-directory tmp-name1 (file-name-as-directory tmp-name2))
+ (should (file-directory-p tmp-name3))
+ (should (file-exists-p tmp-name5)))
+
+ ;; Cleanup.
+ (ignore-errors (tramp-archive--test-delete tmp-name2))
+ (tramp-archive-cleanup-hash))
+
+ ;; Copy directory contents.
+ (unwind-protect
+ (progn
+ ;; Copy empty directory.
+ (copy-directory tmp-name1 tmp-name2 nil 'parents 'contents)
+ (should (file-directory-p tmp-name2))
+ (should (file-exists-p tmp-name4))
+ ;; Target directory does exist already.
+ (tramp-archive--test-delete tmp-name4)
+ (copy-directory
+ tmp-name1 (file-name-as-directory tmp-name2)
+ nil 'parents 'contents)
+ (should (file-directory-p tmp-name2))
+ (should (file-exists-p tmp-name4))
+ (should-not (file-directory-p tmp-name3))
+ (should-not (file-exists-p tmp-name5)))
+
+ ;; Cleanup.
+ (ignore-errors (tramp-archive--test-delete tmp-name2))
+ (tramp-archive-cleanup-hash))))
+
+(ert-deftest tramp-archive-test16-directory-files ()
+ "Check `directory-files'."
+ :tags '(:expensive-test)
+ (skip-unless tramp-archive-enabled)
+
+ (let ((tmp-name tramp-archive-test-archive)
+ (files '("." ".." "bar" "baz.tar" "foo.hrd" "foo.lnk" "foo.txt")))
+ (unwind-protect
+ (progn
+ (should (file-directory-p tmp-name))
+ (should (equal (directory-files tmp-name) files))
+ (should (equal (directory-files tmp-name 'full)
+ (mapcar (lambda (x) (concat tmp-name x)) files)))
+ (should (equal (directory-files
+ tmp-name nil directory-files-no-dot-files-regexp)
+ (delete "." (delete ".." files))))
+ (should (equal (directory-files
+ tmp-name 'full directory-files-no-dot-files-regexp)
+ (mapcar (lambda (x) (concat tmp-name x))
+ (delete "." (delete ".." files))))))
+
+ ;; Cleanup.
+ (tramp-archive-cleanup-hash))))
+
+(ert-deftest tramp-archive-test17-insert-directory ()
+ "Check `insert-directory'."
+ :tags '(:expensive-test)
+ (skip-unless tramp-archive-enabled)
+
+ (let (;; We test for the summary line. Keyword "total" could be localized.
+ (process-environment
+ (append '("LANG=C" "LANGUAGE=C" "LC_ALL=C") process-environment)))
+ (unwind-protect
+ (progn
+ (with-temp-buffer
+ (insert-directory tramp-archive-test-archive nil)
+ (goto-char (point-min))
+ (should
+ (looking-at-p
+ (tramp-compat-rx (literal tramp-archive-test-archive)))))
+ (with-temp-buffer
+ (insert-directory tramp-archive-test-archive "-al")
+ (goto-char (point-min))
+ (should
+ (looking-at-p
+ (tramp-compat-rx
+ bol (+ nonl) blank (literal tramp-archive-test-archive) eol))))
+ (with-temp-buffer
+ (insert-directory
+ (file-name-as-directory tramp-archive-test-archive)
+ "-al" nil 'full-directory-p)
+ (goto-char (point-min))
+ (should
+ (looking-at-p
+ (rx-to-string
+ `(:
+ ;; There might be a summary line.
+ (? "total" (+ nonl) (+ digit) (? blank)
+ (? (any "EGKMPTYZk")) (? "i") (? "B") "\n")
+ ;; We don't know in which order the files appear.
+ (= ,(length (directory-files tramp-archive-test-archive))
+ (+ nonl) blank
+ (regexp
+ ,(regexp-opt (directory-files tramp-archive-test-archive)))
+ (? " ->" (+ nonl)) "\n"))))))
+ ;; Check error case.
+ (with-temp-buffer
+ (should-error
+ (insert-directory
+ (expand-file-name "baz" tramp-archive-test-archive) nil)
+ :type 'file-missing)))
+
+ ;; Cleanup.
+ (tramp-archive-cleanup-hash))))
+
+(ert-deftest tramp-archive-test18-file-attributes ()
+ "Check `file-attributes'.
+This tests also `access-file', `file-readable-p' and `file-regular-p'."
+ :tags '(:expensive-test)
+ (skip-unless tramp-archive-enabled)
+
+ (let ((tmp-name1 (expand-file-name "foo.txt" tramp-archive-test-archive))
+ (tmp-name2 (expand-file-name "foo.lnk" tramp-archive-test-archive))
+ (tmp-name3 (expand-file-name "bar" tramp-archive-test-archive))
+ (tmp-name4 (expand-file-name "baz" tramp-archive-test-archive))
+ attr)
+ (unwind-protect
+ (progn
+ (should (file-exists-p tmp-name1))
+ (should (file-readable-p tmp-name1))
+ (should (file-regular-p tmp-name1))
+ (should-not (access-file tmp-name1 "error"))
+
+ ;; We do not test inodes and device numbers.
+ (setq attr (file-attributes tmp-name1))
+ (should (consp attr))
+ (should (null (car attr)))
+ (should (numberp (nth 1 attr))) ;; Link.
+ (should (numberp (nth 2 attr))) ;; Uid.
+ (should (numberp (nth 3 attr))) ;; Gid.
+ ;; Last access time.
+ (should (stringp (current-time-string (nth 4 attr))))
+ ;; Last modification time.
+ (should (stringp (current-time-string (nth 5 attr))))
+ ;; Last status change time.
+ (should (stringp (current-time-string (nth 6 attr))))
+ (should (numberp (nth 7 attr))) ;; Size.
+ (should (stringp (nth 8 attr))) ;; Modes.
+
+ (setq attr (file-attributes tmp-name1 'string))
+ (should (stringp (nth 2 attr))) ;; Uid.
+ (should (stringp (nth 3 attr))) ;; Gid.
+
+ ;; Symlink.
+ (should (file-exists-p tmp-name2))
+ (should (file-symlink-p tmp-name2))
+ (setq attr (file-attributes tmp-name2))
+ (should (string-equal (car attr) (file-name-nondirectory tmp-name1)))
+
+ ;; Directory.
+ (should (file-exists-p tmp-name3))
+ (should (file-readable-p tmp-name3))
+ (should-not (file-regular-p tmp-name3))
+ (setq attr (file-attributes tmp-name3))
+ (should (eq (car attr) t))
+ (should-not (access-file tmp-name3 "error"))
+
+ ;; Check error case.
+ (should-error
+ (access-file tmp-name4 "error")
+ :type 'file-missing))
+
+ ;; Cleanup.
+ (tramp-archive-cleanup-hash))))
+
+(ert-deftest tramp-archive-test19-directory-files-and-attributes ()
+ "Check `directory-files-and-attributes'."
+ :tags '(:expensive-test)
+ (skip-unless tramp-archive-enabled)
+
+ (let ((tmp-name (expand-file-name "bar" tramp-archive-test-archive))
+ attr)
+ (unwind-protect
+ (progn
+ (should (file-directory-p tmp-name))
+ (setq attr (directory-files-and-attributes tmp-name))
+ (should (consp attr))
+ (dolist (elt attr)
+ (should
+ (equal (file-attributes (expand-file-name (car elt) tmp-name))
+ (cdr elt))))
+ (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 (rx bos "b")))
+ (should (equal (mapcar #'car attr) '("bar"))))
+
+ ;; Cleanup.
+ (tramp-archive-cleanup-hash))))
+
+(ert-deftest tramp-archive-test20-file-modes ()
+ "Check `file-modes'.
+This tests also `file-executable-p', `file-writable-p' and `set-file-modes'."
+ :tags '(:expensive-test)
+ (skip-unless tramp-archive-enabled)
+
+ (let ((tmp-name1 (expand-file-name "foo.txt" tramp-archive-test-archive))
+ (tmp-name2 (expand-file-name "bar" tramp-archive-test-archive)))
+ (unwind-protect
+ (progn
+ (should (file-exists-p tmp-name1))
+ ;; `set-file-modes' is not implemented.
+ (should-error
+ (set-file-modes tmp-name1 #o777)
+ :type 'file-error)
+ (should (= (file-modes tmp-name1) #o400))
+ (should-not (file-executable-p tmp-name1))
+ (should-not (file-writable-p tmp-name1))
+
+ (should (file-exists-p tmp-name2))
+ ;; `set-file-modes' is not implemented.
+ (should-error
+ (set-file-modes tmp-name2 #o777)
+ :type 'file-error)
+ (should (= (file-modes tmp-name2) #o500))
+ (should (file-executable-p tmp-name2))
+ (should-not (file-writable-p tmp-name2)))
+
+ ;; Cleanup.
+ (tramp-archive-cleanup-hash))))
+
+(ert-deftest tramp-archive-test21-file-links ()
+ "Check `file-symlink-p' and `file-truename'"
+ :tags '(:expensive-test)
+ (skip-unless tramp-archive-enabled)
+
+ ;; We must use `file-truename' for the file archive, because it
+ ;; could be located on a symlinked directory. This would let the
+ ;; test fail.
+ (let* ((tramp-archive-test-archive (file-truename tramp-archive-test-archive))
+ (tmp-name1 (expand-file-name "foo.txt" tramp-archive-test-archive))
+ (tmp-name2 (expand-file-name "foo.lnk" tramp-archive-test-archive)))
+
+ (unwind-protect
+ (progn
+ (should (file-exists-p tmp-name1))
+ (should (string-equal tmp-name1 (file-truename tmp-name1)))
+ ;; `make-symbolic-link' is not implemented.
+ (should-error
+ (make-symbolic-link tmp-name1 tmp-name2)
+ :type 'file-error)
+ (should (file-symlink-p tmp-name2))
+ (should
+ (string-equal
+ ;; This is "/foo.txt".
+ (with-parsed-tramp-archive-file-name tmp-name1 nil localname)
+ ;; `file-symlink-p' returns "foo.txt". Wer must expand, therefore.
+ (with-parsed-tramp-archive-file-name
+ (expand-file-name
+ (file-symlink-p tmp-name2) tramp-archive-test-archive)
+ nil
+ localname)))
+ (should-not (string-equal tmp-name2 (file-truename tmp-name2)))
+ (should
+ (string-equal (file-truename tmp-name1) (file-truename tmp-name2)))
+ (should (file-equal-p tmp-name1 tmp-name2)))
+
+ ;; Cleanup.
+ (tramp-archive-cleanup-hash))))
+
+(ert-deftest tramp-archive-test26-file-name-completion ()
+ "Check `file-name-completion' and `file-name-all-completions'."
+ :tags '(:expensive-test)
+ (skip-unless tramp-archive-enabled)
+
+ (let ((tmp-name tramp-archive-test-archive))
+ (unwind-protect
+ (progn
+ ;; Local files.
+ (should (equal (file-name-completion "fo" tmp-name) "foo."))
+ (should (equal (file-name-completion "foo.txt" tmp-name) t))
+ (should (equal (file-name-completion "b" tmp-name) "ba"))
+ (should-not (file-name-completion "a" tmp-name))
+ (should
+ (equal
+ (file-name-completion "b" tmp-name #'file-directory-p) "bar/"))
+ (should
+ (equal
+ (sort (file-name-all-completions "fo" tmp-name) #'string-lessp)
+ '("foo.hrd" "foo.lnk" "foo.txt")))
+ (should
+ (equal
+ (sort (file-name-all-completions "b" tmp-name) #'string-lessp)
+ '("bar/" "baz.tar")))
+ (should-not (file-name-all-completions "a" tmp-name))
+ ;; `completion-regexp-list' restricts the completion to
+ ;; files which match all expressions in this list.
+ (let ((completion-regexp-list
+ `(,directory-files-no-dot-files-regexp "b")))
+ (should
+ (equal (file-name-completion "" tmp-name) "ba"))
+ (should
+ (equal
+ (sort (file-name-all-completions "" tmp-name) #'string-lessp)
+ '("bar/" "baz.tar")))))
+
+ ;; Cleanup.
+ (tramp-archive-cleanup-hash))))
+
+(ert-deftest tramp-archive-test40-make-nearby-temp-file ()
+ "Check `make-nearby-temp-file' and `temporary-file-directory'."
+ (skip-unless tramp-archive-enabled)
+
+ (let ((default-directory tramp-archive-test-archive)
+ tmp-file)
+ ;; The file archive shall know a temporary file directory. It is
+ ;; not in the archive itself.
+ (should (stringp (temporary-file-directory)))
+ (should-not (tramp-archive-file-name-p (temporary-file-directory)))
+
+ ;; A temporary file or directory shall not be located in the
+ ;; archive itself.
+ (setq tmp-file (make-nearby-temp-file "tramp-archive-test"))
+ (should (file-exists-p tmp-file))
+ (should (file-regular-p tmp-file))
+ (should-not (tramp-archive-file-name-p tmp-file))
+ (delete-file tmp-file)
+ (should-not (file-exists-p tmp-file))
+
+ (setq tmp-file (make-nearby-temp-file "tramp-archive-test" 'dir))
+ (should (file-exists-p tmp-file))
+ (should (file-directory-p tmp-file))
+ (should-not (tramp-archive-file-name-p tmp-file))
+ (delete-directory tmp-file)
+ (should-not (file-exists-p tmp-file))))
+
+(ert-deftest tramp-archive-test43-file-system-info ()
+ "Check that `file-system-info' returns proper values."
+ (skip-unless tramp-archive-enabled)
+ ;; Since Emacs 27.1.
+ (skip-unless (fboundp 'file-system-info))
+
+ ;; `file-system-info' exists since Emacs 27. We don't want to see
+ ;; compiler warnings for older Emacsen.
+ (let ((fsi (with-no-warnings (file-system-info tramp-archive-test-archive))))
+ (skip-unless fsi)
+ (should (and (consp fsi)
+ (= (length fsi) 3)
+ (numberp (nth 0 fsi))
+ ;; FREE and AVAIL are always 0.
+ (zerop (nth 1 fsi))
+ (zerop (nth 2 fsi))))))
+
+(ert-deftest tramp-archive-test47-auto-load ()
+ "Check that `tramp-archive' autoloads properly."
+ :tags '(:expensive-test)
+ (skip-unless tramp-archive-enabled)
+ ;; Autoloading tramp-archive works since Emacs 27.1.
+ (skip-unless (tramp-archive--test-emacs27-p))
+
+ ;; tramp-archive is neither loaded at Emacs startup, nor when
+ ;; loading a file like "/mock::foo" (which loads Tramp).
+ (let ((code
+ "(progn \
+ (message \"tramp-archive loaded: %%s\" \
+ (featurep 'tramp-archive)) \
+ (let ((inhibit-message t)) \
+ (file-attributes %S \"/\")) \
+ (message \"tramp-archive loaded: %%s\" \
+ (featurep 'tramp-archive))))"))
+ (dolist (enabled '(t nil))
+ (dolist (default-directory
+ `(,temporary-file-directory
+ ;; Starting Emacs in a directory which has
+ ;; `tramp-archive-file-name-regexp' syntax is
+ ;; supported only with Emacs > 27.2 (sigh!).
+ ;; (Bug#48476)
+ ,(file-name-as-directory tramp-archive-test-directory)))
+ (dolist (file `("/mock::foo" ,(concat tramp-archive-test-archive "foo")))
+ (should
+ (string-match
+ (tramp-compat-rx
+ "tramp-archive loaded: "
+ (literal (symbol-name
+ (tramp-archive-file-name-p default-directory)))
+ (+ ascii)
+ "tramp-archive loaded: "
+ (literal (symbol-name
+ (or (tramp-archive-file-name-p default-directory)
+ (and enabled (tramp-archive-file-name-p file))))))
+ (shell-command-to-string
+ (format
+ "%s -batch -Q -L %s --eval %s --eval %s"
+ (shell-quote-argument
+ (expand-file-name invocation-name invocation-directory))
+ (mapconcat #'shell-quote-argument load-path " -L ")
+ (shell-quote-argument
+ (format "(setq tramp-archive-enabled %s)" enabled))
+ (shell-quote-argument (format code file)))))))))))
+
+(ert-deftest tramp-archive-test47-delay-load ()
+ "Check that `tramp-archive' is loaded lazily, only when needed."
+ :tags '(:expensive-test)
+ (skip-unless tramp-archive-enabled)
+ ;; Autoloading tramp-archive works since Emacs 27.1.
+ (skip-unless (tramp-archive--test-emacs27-p))
+
+ ;; tramp-archive is neither loaded at Emacs startup, nor when
+ ;; loading a file like "/foo.tar". It is loaded only when
+ ;; `tramp-archive-enabled' is t.
+ (let ((default-directory (expand-file-name temporary-file-directory))
+ (code
+ "(progn \
+ (setq tramp-archive-enabled %s) \
+ (message \"tramp-archive loaded: %%s\" \
+ (featurep 'tramp-archive)) \
+ (file-attributes %S \"/\") \
+ (message \"tramp-archive loaded: %%s\" \
+ (featurep 'tramp-archive)) \
+ (file-attributes %S \"/\") \
+ (message \"tramp-archive loaded: %%s\" \
+ (featurep 'tramp-archive)))"))
+ ;; tramp-archive doesn't load when `tramp-archive-enabled' is nil.
+ (dolist (tae '(t nil))
+ (should
+ (string-match
+ (tramp-compat-rx
+ "tramp-archive loaded: nil" (+ ascii)
+ "tramp-archive loaded: nil" (+ ascii)
+ "tramp-archive loaded: " (literal (symbol-name tae)))
+ (shell-command-to-string
+ (format
+ "%s -batch -Q -L %s --eval %s"
+ (shell-quote-argument
+ (expand-file-name invocation-name invocation-directory))
+ (mapconcat #'shell-quote-argument load-path " -L ")
+ (shell-quote-argument
+ (format
+ code tae tramp-archive-test-file-archive
+ (concat tramp-archive-test-archive "foo"))))))))))
+
+(ert-deftest tramp-archive-test99-libarchive-tests ()
+ "Run tests of libarchive test files."
+ :tags '(:expensive-test :unstable)
+ (skip-unless tramp-archive-enabled)
+ ;; We do not want to run unless chosen explicitly. This test makes
+ ;; sense only in my local environment. Michael Albinus.
+ (skip-unless
+ (equal
+ (ert--stats-selector ert--current-run-stats)
+ (ert-test-name (ert-running-test))))
+
+ (url-handler-mode)
+ (unwind-protect
+ (dolist (dir
+ '("~/Downloads" "/sftp::~/Downloads" "/ssh::~/Downloads"
+ "http://ftp.debian.org/debian/pool/main/c/coreutils"))
+ (dolist
+ (file
+ '("coreutils_8.26-3_amd64.deb"
+ "coreutils_8.26-3ubuntu3_amd64.deb"))
+ (setq file (expand-file-name file dir))
+ (when (file-exists-p file)
+ (setq file (expand-file-name "control.tar.gz/control" file))
+ (message "%s" file)
+ (should (file-attributes (file-name-as-directory file))))))
+
+ ;; Cleanup.
+ (tramp-archive-cleanup-hash))
+
+ (unwind-protect
+ (dolist (dir '("" "/sftp::" "/ssh::"))
+ (dolist
+ (file
+ (apply
+ 'append
+ (mapcar
+ (lambda (x)
+ (directory-files (concat dir x) 'full (rx "uu" eos) 'sort))
+ '("~/src/libarchive-3.2.2/libarchive/test"
+ "~/src/libarchive-3.2.2/cpio/test"
+ "~/src/libarchive-3.2.2/tar/test"))))
+ (setq file (file-name-as-directory file))
+ (cond
+ ((not (tramp-archive-file-name-p file))
+ (message "skipped: %s" file))
+ ((file-attributes file)
+ (message "%s" file))
+ (t (message "failed: %s" file)))
+ (tramp-archive-cleanup-hash)))
+
+ ;; Cleanup.
+ (tramp-archive-cleanup-hash)))
+
+(defun tramp-archive-test-all (&optional interactive)
+ "Run all tests for \\[tramp-archive].
+If INTERACTIVE is non-nil, the tests are run interactively."
+ (interactive "p")
+ (funcall
+ (if interactive #'ert-run-tests-interactively #'ert-run-tests-batch)
+ "^tramp-archive"))
+
+(provide 'tramp-archive-tests)
+
+;;; tramp-archive-tests.el ends here
diff --git a/test/lisp/net/tramp-resources/foo.tar.gz b/test/lisp/net/tramp-resources/foo.tar.gz
new file mode 100644
index 00000000000..0d2e9878dd7
--- /dev/null
+++ b/test/lisp/net/tramp-resources/foo.tar.gz
Binary files differ
diff --git a/test/lisp/net/tramp-tests.el b/test/lisp/net/tramp-tests.el
index d430caec8aa..2db44494388 100644
--- a/test/lisp/net/tramp-tests.el
+++ b/test/lisp/net/tramp-tests.el
@@ -1,26 +1,26 @@
;;; tramp-tests.el --- Tests of remote file access -*- lexical-binding:t -*-
-;; Copyright (C) 2013-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2022 Free Software Foundation, Inc.
;; Author: Michael Albinus <michael.albinus@gmx.de>
-;; This program is free software: you can redistribute it and/or
+;; This file is part of GNU Emacs.
+;;
+;; GNU Emacs is free software: you can redistribute it and/or
;; modify it under the terms of the GNU General Public License as
;; published by the Free Software Foundation, either version 3 of the
;; License, or (at your option) any later version.
;;
-;; This program is distributed in the hope that it will be useful, but
+;; GNU Emacs is distributed in the hope that it will be useful, but
;; WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
;; General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
-;; along with this program. If not, see `https://www.gnu.org/licenses/'.
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
-;; The tests require a recent ert.el from Emacs 24.4.
-
;; Some of the tests require access to a remote host files. Since
;; this could be problematic, a mock-up connection method "mock" is
;; used. Emulating a remote connection, it simply calls "sh -i".
@@ -33,67 +33,156 @@
;; remote host, set this environment variable to "/dev/null" or
;; whatever is appropriate on your system.
+;; For slow remote connections, `tramp-test44-asynchronous-requests'
+;; might be too heavy. Setting $REMOTE_PARALLEL_PROCESSES to a proper
+;; value less than 10 could help.
+
;; A whole test run can be performed calling the command `tramp-test-all'.
;;; Code:
+(require 'cl-lib)
(require 'dired)
-(require 'ert)
+(require 'dired-aux)
(require 'tramp)
+(require 'ert-x)
+(require 'seq) ; For `seq-random-elt', autoloaded since Emacs 28.1
+(require 'tar-mode)
+(require 'trace)
(require 'vc)
(require 'vc-bzr)
(require 'vc-git)
(require 'vc-hg)
+(declare-function tramp-check-remote-uname "tramp-sh")
(declare-function tramp-find-executable "tramp-sh")
+(declare-function tramp-get-remote-chmod-h "tramp-sh")
(declare-function tramp-get-remote-path "tramp-sh")
-(declare-function tramp-get-remote-stat "tramp-sh")
(declare-function tramp-get-remote-perl "tramp-sh")
-(defvar auto-save-file-name-transforms)
+(declare-function tramp-get-remote-stat "tramp-sh")
+(declare-function tramp-list-tramp-buffers "tramp-cmds")
+(declare-function tramp-method-out-of-band-p "tramp-sh")
+(declare-function tramp-smb-get-localname "tramp-smb")
+(defvar ange-ftp-make-backup-files)
+(defvar tramp-connection-properties)
(defvar tramp-copy-size-limit)
+(defvar tramp-display-escape-sequence-regexp)
+(defvar tramp-fuse-remove-hidden-files)
+(defvar tramp-fuse-unmount-on-cleanup)
+(defvar tramp-inline-compress-start-size)
(defvar tramp-persistency-file-name)
+(defvar tramp-remote-path)
(defvar tramp-remote-process-environment)
-;; Suppress nasty messages.
-(fset 'shell-command-sentinel 'ignore)
-
-;; There is no default value on w32 systems, which could work out of the box.
-(defconst tramp-test-temporary-file-directory
- (cond
- ((getenv "REMOTE_TEMPORARY_FILE_DIRECTORY"))
- ((eq system-type 'windows-nt) null-device)
- (t (add-to-list
- 'tramp-methods
- '("mock"
- (tramp-login-program "sh")
- (tramp-login-args (("-i")))
- (tramp-remote-shell "/bin/sh")
- (tramp-remote-shell-args ("-c"))
- (tramp-connection-timeout 10)))
- (add-to-list
- 'tramp-default-host-alist
- `("\\`mock\\'" nil ,(system-name)))
- ;; Emacs' Makefile sets $HOME to a nonexistent value. Needed in
- ;; batch mode only, therefore.
- (unless (and (null noninteractive) (file-directory-p "~/"))
- (setenv "HOME" temporary-file-directory))
- (format "/mock::%s" temporary-file-directory)))
- "Temporary directory for Tramp tests.")
-
-(setq password-cache-expiry nil
- tramp-verbose 0
+
+;; Needed for Emacs 26.
+(declare-function with-connection-local-variables "files-x")
+;; Needed for Emacs 27.
+(defvar lock-file-name-transforms)
+(defvar process-file-return-signal-string)
+(defvar remote-file-name-inhibit-locks)
+(defvar shell-command-dont-erase-buffer)
+;; Needed for Emacs 28.
+(defvar dired-copy-dereference)
+
+;; `ert-resource-file' was introduced in Emacs 28.1.
+(unless (macrop 'ert-resource-file)
+ (eval-and-compile
+ (defvar ert-resource-directory-format "%s-resources/"
+ "Format for `ert-resource-directory'.")
+ (defvar ert-resource-directory-trim-left-regexp ""
+ "Regexp for `string-trim' (left) used by `ert-resource-directory'.")
+ (defvar ert-resource-directory-trim-right-regexp
+ (rx (? "-test" (? "s")) ".el")
+ "Regexp for `string-trim' (right) used by `ert-resource-directory'.")
+
+ (defmacro ert-resource-directory ()
+ "Return absolute file name of the resource directory for this file.
+
+The path to the resource directory is the \"resources\" directory
+in the same directory as the test file.
+
+If that directory doesn't exist, use the directory named like the
+test file but formatted by `ert-resource-directory-format' and trimmed
+using `string-trim' with arguments
+`ert-resource-directory-trim-left-regexp' and
+`ert-resource-directory-trim-right-regexp'. The default values mean
+that if called from a test file named \"foo-tests.el\", return
+the absolute file name for \"foo-resources\"."
+ `(let* ((testfile ,(or (bound-and-true-p byte-compile-current-file)
+ (and load-in-progress load-file-name)
+ buffer-file-name))
+ (default-directory (file-name-directory testfile)))
+ (file-truename
+ (if (file-accessible-directory-p "resources/")
+ (expand-file-name "resources/")
+ (expand-file-name
+ (format
+ ert-resource-directory-format
+ (string-trim testfile
+ ert-resource-directory-trim-left-regexp
+ ert-resource-directory-trim-right-regexp)))))))
+
+ (defmacro ert-resource-file (file)
+ "Return file name of resource file named FILE.
+A resource file is in the resource directory as per
+`ert-resource-directory'."
+ `(expand-file-name ,file (ert-resource-directory)))))
+
+;; `ert-remote-temporary-file-directory' was introduced in Emacs 29.1.
+;; Adapting `tramp-remote-path' happens also there.
+(unless (boundp 'ert-remote-temporary-file-directory)
+ (eval-and-compile
+ ;; There is no default value on w32 systems, which could work out
+ ;; of the box.
+ (defconst ert-remote-temporary-file-directory
+ (cond
+ ((getenv "REMOTE_TEMPORARY_FILE_DIRECTORY"))
+ ((eq system-type 'windows-nt) null-device)
+ (t (add-to-list
+ 'tramp-methods
+ '("mock"
+ (tramp-login-program "sh")
+ (tramp-login-args (("-i")))
+ (tramp-remote-shell "/bin/sh")
+ (tramp-remote-shell-args ("-c"))
+ (tramp-connection-timeout 10)))
+ (add-to-list
+ 'tramp-default-host-alist
+ `("\\`mock\\'" nil ,(system-name)))
+ ;; Emacs's Makefile sets $HOME to a nonexistent value.
+ ;; Needed in batch mode only, therefore.
+ (unless (and (null noninteractive) (file-directory-p "~/"))
+ (setenv "HOME" temporary-file-directory))
+ (format "/mock::%s" temporary-file-directory)))
+ "Temporary directory for remote file tests.")
+
+ ;; This should happen on hydra only.
+ (when (getenv "EMACS_HYDRA_CI")
+ (add-to-list 'tramp-remote-path 'tramp-own-remote-path))))
+
+;; Beautify batch mode.
+(when noninteractive
+ ;; Suppress nasty messages.
+ (fset #'shell-command-sentinel #'ignore)
+ ;; We do not want to be interrupted.
+ (eval-after-load 'tramp-gvfs
+ '(fset 'tramp-gvfs-handler-askquestion
+ (lambda (_message _choices) '(t nil 0)))))
+
+(defconst tramp-test-vec
+ (and (file-remote-p ert-remote-temporary-file-directory)
+ (tramp-dissect-file-name ert-remote-temporary-file-directory))
+ "The used `tramp-file-name' structure.")
+
+(setq auth-source-save-behavior nil
+ password-cache-expiry nil
+ remote-file-name-inhibit-cache nil
+ tramp-allow-unsafe-temporary-files t
tramp-cache-read-persistent-data t ;; For auth-sources.
tramp-copy-size-limit nil
- tramp-message-show-message nil
- tramp-persistency-file-name nil)
-
-;; This should happen on hydra only.
-(when (getenv "EMACS_HYDRA_CI")
- (add-to-list 'tramp-remote-path 'tramp-own-remote-path))
-
-(defvar tramp--test-expensive-test
- (null
- (string-equal (getenv "SELECTOR") "(quote (not (tag :expensive-test)))"))
- "Whether expensive tests are run.")
+ tramp-error-show-message-timeout nil
+ tramp-persistency-file-name nil
+ tramp-verbose 0)
(defvar tramp--test-enabled-checked nil
"Cached result of `tramp--test-enabled'.
@@ -108,16 +197,22 @@ being the result.")
(cons
t (ignore-errors
(and
- (file-remote-p tramp-test-temporary-file-directory)
- (file-directory-p tramp-test-temporary-file-directory)
- (file-writable-p tramp-test-temporary-file-directory))))))
+ (file-remote-p ert-remote-temporary-file-directory)
+ (file-directory-p ert-remote-temporary-file-directory)
+ (file-writable-p ert-remote-temporary-file-directory))))))
(when (cdr tramp--test-enabled-checked)
+ ;; Remove old test files.
+ (dolist (dir `(,temporary-file-directory
+ ,ert-remote-temporary-file-directory))
+ (dolist (file (directory-files dir 'full (rx bos (? ".#") "tramp-test")))
+ (ignore-errors
+ (if (file-directory-p file)
+ (delete-directory file 'recursive)
+ (delete-file file)))))
;; Cleanup connection.
(ignore-errors
- (tramp-cleanup-connection
- (tramp-dissect-file-name tramp-test-temporary-file-directory)
- nil 'keep-password)))
+ (tramp-cleanup-connection tramp-test-vec nil 'keep-password)))
;; Return result.
(cdr tramp--test-enabled-checked))
@@ -128,124 +223,185 @@ If LOCAL is non-nil, a local file name is returned.
If QUOTED is non-nil, the local part of the file name is quoted.
The temporary file is not created."
(funcall
- (if quoted 'tramp-compat-file-name-quote 'identity)
+ (if quoted #'tramp-compat-file-name-quote #'identity)
(expand-file-name
(make-temp-name "tramp-test")
- (if local temporary-file-directory tramp-test-temporary-file-directory))))
+ (if local temporary-file-directory ert-remote-temporary-file-directory))))
+
+;; Method "smb" supports `make-symbolic-link' only if the remote host
+;; has CIFS capabilities. tramp-adb.el, tramp-gvfs.el, tramp-rclone.el
+;; and tramp-sshfs.el do not support symbolic links at all.
+(defmacro tramp--test-ignore-make-symbolic-link-error (&rest body)
+ "Run BODY, ignoring \"make-symbolic-link not supported\" file error."
+ (declare (indent defun) (debug (body)))
+ `(condition-case err
+ (progn ,@body)
+ (file-error
+ (unless (string-equal (error-message-string err)
+ "make-symbolic-link not supported")
+ (signal (car err) (cdr err))))))
;; Don't print messages in nested `tramp--test-instrument-test-case' calls.
(defvar tramp--test-instrument-test-case-p nil
"Whether `tramp--test-instrument-test-case' run.
This shall used dynamically bound only.")
+;; When `tramp-verbose' is greater than 10, and you want to trace
+;; other functions as well, do something like
+;; (let ((tramp-trace-functions '(file-name-non-special)))
+;; (tramp--test-instrument-test-case 11
+;; ...))
(defmacro tramp--test-instrument-test-case (verbose &rest body)
"Run BODY with `tramp-verbose' equal VERBOSE.
-Print the the content of the Tramp debug buffer, if BODY does not
-eval properly in `should' or `should-not'. `should-error' is not
-handled properly. BODY shall not contain a timeout."
+Print the content of the Tramp connection and debug buffers, if
+`tramp-verbose' is greater than 3. Print traces if `tramp-verbose'
+is greater than 10.
+`should-error' is not handled properly. BODY shall not contain a timeout."
(declare (indent 1) (debug (natnump body)))
- `(let ((tramp-verbose (max (or ,verbose 0) (or tramp-verbose 0)))
- (tramp-message-show-message t)
- (tramp-debug-on-error t)
- (debug-ignored-errors
- (cons "^make-symbolic-link not supported$" debug-ignored-errors))
- inhibit-message)
+ `(let* ((tramp-verbose (max (or ,verbose 0) (or tramp-verbose 0)))
+ (trace-buffer (tramp-trace-buffer-name tramp-test-vec))
+ (debug-ignored-errors
+ (append
+ '("^make-symbolic-link not supported$"
+ "^error with add-name-to-file")
+ debug-ignored-errors))
+ inhibit-message)
(unwind-protect
(let ((tramp--test-instrument-test-case-p t)) ,@body)
;; Unwind forms.
(when (and (null tramp--test-instrument-test-case-p) (> tramp-verbose 3))
- (with-parsed-tramp-file-name tramp-test-temporary-file-directory nil
- (with-current-buffer (tramp-get-connection-buffer v)
- (message "%s" (buffer-string)))
- (with-current-buffer (tramp-get-debug-buffer v)
- (message "%s" (buffer-string))))))))
+ (untrace-all)
+ (dolist (buf (tramp-list-tramp-buffers))
+ (message ";; %s\n%s" buf (tramp-get-buffer-string buf))
+ (kill-buffer buf))))))
(defsubst tramp--test-message (fmt-string &rest arguments)
"Emit a message into ERT *Messages*."
(tramp--test-instrument-test-case 0
- (apply
- 'tramp-message
- (tramp-dissect-file-name tramp-test-temporary-file-directory) 0
- fmt-string arguments)))
+ (apply #'tramp-message tramp-test-vec 0 fmt-string arguments)))
(defsubst tramp--test-backtrace ()
"Dump a backtrace into ERT *Messages*."
(tramp--test-instrument-test-case 10
- (tramp-backtrace
- (tramp-dissect-file-name tramp-test-temporary-file-directory))))
+ (tramp-backtrace tramp-test-vec)))
+
+(defmacro tramp--test-print-duration (message &rest body)
+ "Run BODY and print a message with duration, prompted by MESSAGE."
+ (declare (indent 1) (debug (stringp body)))
+ `(let ((start (current-time)))
+ (unwind-protect
+ (progn ,@body)
+ (tramp--test-message
+ "%s %f sec" ,message (float-time (time-subtract nil start))))))
+
+;; `always' is introduced with Emacs 28.1.
+(defalias 'tramp--test-always
+ (if (fboundp 'always)
+ #'always
+ (lambda (&rest _arguments)
+ "Do nothing and return t.
+This function accepts any number of ARGUMENTS, but ignores them.
+Also see `ignore'."
+ t)))
(ert-deftest tramp-test00-availability ()
"Test availability of Tramp functions."
:expected-result (if (tramp--test-enabled) :passed :failed)
(tramp--test-message
- "Remote directory: `%s'" tramp-test-temporary-file-directory)
+ "Remote directory: `%s'" ert-remote-temporary-file-directory)
(should (ignore-errors
(and
- (file-remote-p tramp-test-temporary-file-directory)
- (file-directory-p tramp-test-temporary-file-directory)
- (file-writable-p tramp-test-temporary-file-directory)))))
+ (file-remote-p ert-remote-temporary-file-directory)
+ (file-directory-p ert-remote-temporary-file-directory)
+ (file-writable-p ert-remote-temporary-file-directory)))))
(ert-deftest tramp-test01-file-name-syntax ()
"Check remote file name syntax."
- ;; Simple cases.
- (should (tramp-tramp-file-p "/method::"))
- (should (tramp-tramp-file-p "/method:host:"))
- (should (tramp-tramp-file-p "/method:user@:"))
- (should (tramp-tramp-file-p "/method:user@host:"))
- (should (tramp-tramp-file-p "/method:user@email@host:"))
-
- ;; Using a port.
- (should (tramp-tramp-file-p "/method:host#1234:"))
- (should (tramp-tramp-file-p "/method:user@host#1234:"))
-
- ;; Using an IPv4 address.
- (should (tramp-tramp-file-p "/method:1.2.3.4:"))
- (should (tramp-tramp-file-p "/method:user@1.2.3.4:"))
-
- ;; Using an IPv6 address.
- (should (tramp-tramp-file-p "/method:[::1]:"))
- (should (tramp-tramp-file-p "/method:user@[::1]:"))
-
- ;; Local file name part.
- (should (tramp-tramp-file-p "/method:::"))
- (should (tramp-tramp-file-p "/method::/:"))
- (should (tramp-tramp-file-p "/method::/path/to/file"))
- (should (tramp-tramp-file-p "/method::/:/path/to/file"))
- (should (tramp-tramp-file-p "/method::file"))
- (should (tramp-tramp-file-p "/method::/:file"))
-
- ;; Multihop.
- (should (tramp-tramp-file-p "/method1:|method2::"))
- (should (tramp-tramp-file-p "/method1:host1|method2:host2:"))
- (should (tramp-tramp-file-p "/method1:user1@host1|method2:user2@host2:"))
- (should (tramp-tramp-file-p
- "/method1:user1@host1|method2:user2@host2|method3:user3@host3:"))
-
- ;; No strings.
- (should-not (tramp-tramp-file-p nil))
- (should-not (tramp-tramp-file-p 'symbol))
- ;; Ange-ftp syntax.
- (should-not (tramp-tramp-file-p "/host:"))
- (should-not (tramp-tramp-file-p "/user@host:"))
- (should-not (tramp-tramp-file-p "/1.2.3.4:"))
- (should-not (tramp-tramp-file-p "/[]:"))
- (should-not (tramp-tramp-file-p "/[::1]:"))
- (should-not (tramp-tramp-file-p "/host:/:"))
- (should-not (tramp-tramp-file-p "/host1|host2:"))
- (should-not (tramp-tramp-file-p "/user1@host1|user2@host2:"))
- ;; Quote with "/:" suppresses file name handlers.
- (should-not (tramp-tramp-file-p "/::"))
- (should-not (tramp-tramp-file-p "/:@:"))
- (should-not (tramp-tramp-file-p "/:[]:"))
- ;; Methods shall be at least two characters on MS Windows, except
- ;; the default method.
- (let ((system-type 'windows-nt))
- (should-not (tramp-tramp-file-p "/c:/path/to/file"))
- (should-not (tramp-tramp-file-p "/c::/path/to/file"))
- (should (tramp-tramp-file-p "/-::/path/to/file")))
- (let ((system-type 'gnu/linux))
- (should (tramp-tramp-file-p "/-:h:/path/to/file"))
- (should (tramp-tramp-file-p "/m::/path/to/file"))))
+ (let ((syntax tramp-syntax))
+ (unwind-protect
+ (progn
+ (tramp-change-syntax 'default)
+ ;; Simple cases.
+ (should (tramp-tramp-file-p "/method::"))
+ (should (tramp-tramp-file-p "/method:host:"))
+ (should (tramp-tramp-file-p "/method:user@:"))
+ (should (tramp-tramp-file-p "/method:user@host:"))
+ (should (tramp-tramp-file-p "/method:user@email@host:"))
+
+ ;; Using a port.
+ (should (tramp-tramp-file-p "/method:host#1234:"))
+ (should (tramp-tramp-file-p "/method:user@host#1234:"))
+
+ ;; Using an IPv4 address.
+ (should (tramp-tramp-file-p "/method:1.2.3.4:"))
+ (should (tramp-tramp-file-p "/method:user@1.2.3.4:"))
+
+ ;; Using an IPv6 address.
+ (should (tramp-tramp-file-p "/method:[::1]:"))
+ (should (tramp-tramp-file-p "/method:user@[::1]:"))
+
+ ;; Using an IPv4 mapped IPv6 address.
+ (should (tramp-tramp-file-p "/method:[::ffff:1.2.3.4]:"))
+ (should (tramp-tramp-file-p "/method:user@[::ffff:1.2.3.4]:"))
+
+ ;; Local file name part.
+ (should (tramp-tramp-file-p "/method:::"))
+ (should (tramp-tramp-file-p "/method::/:"))
+ (should (tramp-tramp-file-p "/method::/path/to/file"))
+ (should (tramp-tramp-file-p "/method::/:/path/to/file"))
+ (should (tramp-tramp-file-p "/method::file"))
+ (should (tramp-tramp-file-p "/method::/:file"))
+
+ ;; Multihop.
+ (should (tramp-tramp-file-p "/method1:|method2::"))
+ (should
+ (tramp-tramp-file-p "/method1:host1|method2:host2:"))
+ (should
+ (tramp-tramp-file-p "/method1:user1@host1|method2:user2@host2:"))
+ (should
+ (tramp-tramp-file-p
+ "/method1:user1@host1|method2:user2@host2|method3:user3@host3:"))
+
+ ;; No strings.
+ (should-not (tramp-tramp-file-p nil))
+ (should-not (tramp-tramp-file-p 'symbol))
+ ;; No newline or linefeed.
+ (should-not (tramp-tramp-file-p "/method::file\nname"))
+ (should-not (tramp-tramp-file-p "/method::file\rname"))
+ ;; Ange-FTP syntax.
+ (should-not (tramp-tramp-file-p "/host:"))
+ (should-not (tramp-tramp-file-p "/user@host:"))
+ (should-not (tramp-tramp-file-p "/1.2.3.4:"))
+ (should-not (tramp-tramp-file-p "/[]:"))
+ (should-not (tramp-tramp-file-p "/[::1]:"))
+ (should-not (tramp-tramp-file-p "/[::ffff:1.2.3.4]:"))
+ (should-not (tramp-tramp-file-p "/host:/:"))
+ (should-not (tramp-tramp-file-p "/host1|host2:"))
+ (should-not (tramp-tramp-file-p "/user1@host1|user2@host2:"))
+ ;; Quote with "/:" suppresses file name handlers.
+ (should-not (tramp-tramp-file-p "/::"))
+ (should-not (tramp-tramp-file-p "/:@:"))
+ (should-not (tramp-tramp-file-p "/:[]:"))
+ ;; When `tramp-mode' is nil, Tramp is not activated.
+ (let (tramp-mode)
+ (should-not (tramp-tramp-file-p "/method:user@host:")))
+ ;; `tramp-ignored-file-name-regexp' suppresses Tramp.
+ (let ((tramp-ignored-file-name-regexp "^/method:user@host:"))
+ (should-not (tramp-tramp-file-p "/method:user@host:")))
+ ;; Methods shall be at least two characters, except the
+ ;; default method.
+ (let ((system-type 'windows-nt))
+ (should-not (tramp-tramp-file-p "/c:/path/to/file"))
+ (should-not (tramp-tramp-file-p "/c::/path/to/file"))
+ (should (tramp-tramp-file-p "/-::/path/to/file"))
+ (should (tramp-tramp-file-p "/mm::/path/to/file")))
+ (let ((system-type 'gnu/linux))
+ (should-not (tramp-tramp-file-p "/m::/path/to/file"))
+ (should (tramp-tramp-file-p "/-:h:/path/to/file"))
+ (should (tramp-tramp-file-p "/mm::/path/to/file"))))
+
+ ;; Exit.
+ (tramp-change-syntax syntax))))
(ert-deftest tramp-test01-file-name-syntax-simplified ()
"Check simplified file name syntax."
@@ -272,6 +428,10 @@ handled properly. BODY shall not contain a timeout."
(should (tramp-tramp-file-p "/[::1]:"))
(should (tramp-tramp-file-p "/user@[::1]:"))
+ ;; Using an IPv4 mapped IPv6 address.
+ (should (tramp-tramp-file-p "/[::ffff:1.2.3.4]:"))
+ (should (tramp-tramp-file-p "/user@[::ffff:1.2.3.4]:"))
+
;; Local file name part.
(should (tramp-tramp-file-p "/host::"))
(should (tramp-tramp-file-p "/host:/:"))
@@ -322,6 +482,10 @@ handled properly. BODY shall not contain a timeout."
(should (tramp-tramp-file-p "/[method/::1]"))
(should (tramp-tramp-file-p "/[method/user@::1]"))
+ ;; Using an IPv4 mapped IPv6 address.
+ (should (tramp-tramp-file-p "/[method/::ffff:1.2.3.4]"))
+ (should (tramp-tramp-file-p "/[method/user@::ffff:1.2.3.4]"))
+
;; Local file name part.
(should (tramp-tramp-file-p "/[method/]"))
(should (tramp-tramp-file-p "/[method/]/:"))
@@ -343,7 +507,7 @@ handled properly. BODY shall not contain a timeout."
;; No strings.
(should-not (tramp-tramp-file-p nil))
(should-not (tramp-tramp-file-p 'symbol))
- ;; Ange-ftp syntax.
+ ;; Ange-FTP syntax.
(should-not (tramp-tramp-file-p "/host:"))
(should-not (tramp-tramp-file-p "/user@host:"))
(should-not (tramp-tramp-file-p "/1.2.3.4:"))
@@ -360,357 +524,487 @@ handled properly. BODY shall not contain a timeout."
"Check remote file name components."
(let ((tramp-default-method "default-method")
(tramp-default-user "default-user")
- (tramp-default-host "default-host"))
- ;; Expand `tramp-default-user' and `tramp-default-host'.
- (should (string-equal
- (file-remote-p "/method::")
- (format "/%s:%s@%s:" "method" "default-user" "default-host")))
- (should (string-equal (file-remote-p "/method::" 'method) "method"))
- (should (string-equal (file-remote-p "/method::" 'user) "default-user"))
- (should (string-equal (file-remote-p "/method::" 'host) "default-host"))
- (should (string-equal (file-remote-p "/method::" 'localname) ""))
- (should (string-equal (file-remote-p "/method::" 'hop) nil))
-
- ;; Expand `tramp-default-method' and `tramp-default-user'.
- (should (string-equal
- (file-remote-p "/-:host:")
- (format "/%s:%s@%s:" "default-method" "default-user" "host")))
- (should (string-equal (file-remote-p "/-:host:" 'method) "default-method"))
- (should (string-equal (file-remote-p "/-:host:" 'user) "default-user"))
- (should (string-equal (file-remote-p "/-:host:" 'host) "host"))
- (should (string-equal (file-remote-p "/-:host:" 'localname) ""))
- (should (string-equal (file-remote-p "/-:host:" 'hop) nil))
-
- ;; Expand `tramp-default-method' and `tramp-default-host'.
- (should (string-equal
- (file-remote-p "/-:user@:")
- (format "/%s:%s@%s:" "default-method" "user" "default-host")))
- (should (string-equal (file-remote-p "/-:user@:" 'method) "default-method"))
- (should (string-equal (file-remote-p "/-:user@:" 'user) "user"))
- (should (string-equal (file-remote-p "/-:user@:" 'host) "default-host"))
- (should (string-equal (file-remote-p "/-:user@:" 'localname) ""))
- (should (string-equal (file-remote-p "/-:user@:" 'hop) nil))
-
- ;; Expand `tramp-default-method'.
- (should (string-equal
- (file-remote-p "/-:user@host:")
- (format "/%s:%s@%s:" "default-method" "user" "host")))
- (should (string-equal
- (file-remote-p "/-:user@host:" 'method) "default-method"))
- (should (string-equal (file-remote-p "/-:user@host:" 'user) "user"))
- (should (string-equal (file-remote-p "/-:user@host:" 'host) "host"))
- (should (string-equal (file-remote-p "/-:user@host:" 'localname) ""))
- (should (string-equal (file-remote-p "/-:user@host:" 'hop) nil))
-
- ;; Expand `tramp-default-user'.
- (should (string-equal
- (file-remote-p "/method:host:")
- (format "/%s:%s@%s:" "method" "default-user" "host")))
- (should (string-equal (file-remote-p "/method:host:" 'method) "method"))
- (should (string-equal (file-remote-p "/method:host:" 'user) "default-user"))
- (should (string-equal (file-remote-p "/method:host:" 'host) "host"))
- (should (string-equal (file-remote-p "/method:host:" 'localname) ""))
- (should (string-equal (file-remote-p "/method:host:" 'hop) nil))
-
- ;; Expand `tramp-default-host'.
- (should (string-equal
- (file-remote-p "/method:user@:")
- (format "/%s:%s@%s:" "method" "user" "default-host")))
- (should (string-equal (file-remote-p "/method:user@:" 'method) "method"))
- (should (string-equal (file-remote-p "/method:user@:" 'user) "user"))
- (should (string-equal (file-remote-p "/method:user@:" 'host)
- "default-host"))
- (should (string-equal (file-remote-p "/method:user@:" 'localname) ""))
- (should (string-equal (file-remote-p "/method:user@:" 'hop) nil))
-
- ;; No expansion.
- (should (string-equal
- (file-remote-p "/method:user@host:")
- (format "/%s:%s@%s:" "method" "user" "host")))
- (should (string-equal
- (file-remote-p "/method:user@host:" 'method) "method"))
- (should (string-equal (file-remote-p "/method:user@host:" 'user) "user"))
- (should (string-equal (file-remote-p "/method:user@host:" 'host) "host"))
- (should (string-equal (file-remote-p "/method:user@host:" 'localname) ""))
- (should (string-equal (file-remote-p "/method:user@host:" 'hop) nil))
-
- ;; No expansion.
- (should (string-equal
- (file-remote-p "/method:user@email@host:")
- (format "/%s:%s@%s:" "method" "user@email" "host")))
- (should (string-equal
- (file-remote-p "/method:user@email@host:" 'method) "method"))
- (should (string-equal
- (file-remote-p "/method:user@email@host:" 'user) "user@email"))
- (should (string-equal
- (file-remote-p "/method:user@email@host:" 'host) "host"))
- (should (string-equal
- (file-remote-p "/method:user@email@host:" 'localname) ""))
- (should (string-equal
- (file-remote-p "/method:user@email@host:" 'hop) nil))
-
- ;; Expand `tramp-default-method' and `tramp-default-user'.
- (should (string-equal
- (file-remote-p "/-:host#1234:")
- (format "/%s:%s@%s:" "default-method" "default-user" "host#1234")))
- (should (string-equal
- (file-remote-p "/-:host#1234:" 'method) "default-method"))
- (should (string-equal (file-remote-p "/-:host#1234:" 'user) "default-user"))
- (should (string-equal (file-remote-p "/-:host#1234:" 'host) "host#1234"))
- (should (string-equal (file-remote-p "/-:host#1234:" 'localname) ""))
- (should (string-equal (file-remote-p "/-:host#1234:" 'hop) nil))
-
- ;; Expand `tramp-default-method'.
- (should (string-equal
- (file-remote-p "/-:user@host#1234:")
- (format "/%s:%s@%s:" "default-method" "user" "host#1234")))
- (should (string-equal
- (file-remote-p "/-:user@host#1234:" 'method) "default-method"))
- (should (string-equal (file-remote-p "/-:user@host#1234:" 'user) "user"))
- (should (string-equal (file-remote-p "/-:user@host#1234:" 'host) "host#1234"))
- (should (string-equal (file-remote-p "/-:user@host#1234:" 'localname) ""))
- (should (string-equal (file-remote-p "/-:user@host#1234:" 'hop) nil))
-
- ;; Expand `tramp-default-user'.
- (should (string-equal
- (file-remote-p "/method:host#1234:")
- (format "/%s:%s@%s:" "method" "default-user" "host#1234")))
- (should (string-equal
- (file-remote-p "/method:host#1234:" 'method) "method"))
- (should (string-equal
- (file-remote-p "/method:host#1234:" 'user) "default-user"))
- (should (string-equal
- (file-remote-p "/method:host#1234:" 'host) "host#1234"))
- (should (string-equal (file-remote-p "/method:host#1234:" 'localname) ""))
- (should (string-equal (file-remote-p "/method:host#1234:" 'hop) nil))
-
- ;; No expansion.
- (should (string-equal
- (file-remote-p "/method:user@host#1234:")
- (format "/%s:%s@%s:" "method" "user" "host#1234")))
- (should (string-equal
- (file-remote-p "/method:user@host#1234:" 'method) "method"))
- (should (string-equal
- (file-remote-p "/method:user@host#1234:" 'user) "user"))
- (should (string-equal
- (file-remote-p "/method:user@host#1234:" 'host) "host#1234"))
- (should (string-equal
- (file-remote-p "/method:user@host#1234:" 'localname) ""))
- (should (string-equal
- (file-remote-p "/method:user@host#1234:" 'hop) nil))
-
- ;; Expand `tramp-default-method' and `tramp-default-user'.
- (should (string-equal
- (file-remote-p "/-:1.2.3.4:")
- (format "/%s:%s@%s:" "default-method" "default-user" "1.2.3.4")))
- (should (string-equal (file-remote-p "/-:1.2.3.4:" 'method) "default-method"))
- (should (string-equal (file-remote-p "/-:1.2.3.4:" 'user) "default-user"))
- (should (string-equal (file-remote-p "/-:1.2.3.4:" 'host) "1.2.3.4"))
- (should (string-equal (file-remote-p "/-:1.2.3.4:" 'localname) ""))
- (should (string-equal (file-remote-p "/-:1.2.3.4:" 'hop) nil))
-
- ;; Expand `tramp-default-method'.
- (should (string-equal
- (file-remote-p "/-:user@1.2.3.4:")
- (format "/%s:%s@%s:" "default-method" "user" "1.2.3.4")))
- (should (string-equal
- (file-remote-p "/-:user@1.2.3.4:" 'method) "default-method"))
- (should (string-equal (file-remote-p "/-:user@1.2.3.4:" 'user) "user"))
- (should (string-equal (file-remote-p "/-:user@1.2.3.4:" 'host) "1.2.3.4"))
- (should (string-equal (file-remote-p "/-:user@1.2.3.4:" 'localname) ""))
- (should (string-equal (file-remote-p "/-:user@1.2.3.4:" 'hop) nil))
-
- ;; Expand `tramp-default-user'.
- (should (string-equal
- (file-remote-p "/method:1.2.3.4:")
- (format "/%s:%s@%s:" "method" "default-user" "1.2.3.4")))
- (should (string-equal (file-remote-p "/method:1.2.3.4:" 'method) "method"))
- (should (string-equal
- (file-remote-p "/method:1.2.3.4:" 'user) "default-user"))
- (should (string-equal (file-remote-p "/method:1.2.3.4:" 'host) "1.2.3.4"))
- (should (string-equal (file-remote-p "/method:1.2.3.4:" 'localname) ""))
- (should (string-equal (file-remote-p "/method:1.2.3.4:" 'hop) nil))
-
- ;; No expansion.
- (should (string-equal
- (file-remote-p "/method:user@1.2.3.4:")
- (format "/%s:%s@%s:" "method" "user" "1.2.3.4")))
- (should (string-equal
- (file-remote-p "/method:user@1.2.3.4:" 'method) "method"))
- (should (string-equal (file-remote-p "/method:user@1.2.3.4:" 'user) "user"))
- (should (string-equal
- (file-remote-p "/method:user@1.2.3.4:" 'host) "1.2.3.4"))
- (should (string-equal
- (file-remote-p "/method:user@1.2.3.4:" 'localname) ""))
- (should (string-equal
- (file-remote-p "/method:user@1.2.3.4:" 'hop) nil))
-
- ;; Expand `tramp-default-method', `tramp-default-user' and
- ;; `tramp-default-host'.
- (should (string-equal
- (file-remote-p "/-:[]:")
- (format
- "/%s:%s@%s:" "default-method" "default-user" "default-host")))
- (should (string-equal (file-remote-p "/-:[]:" 'method) "default-method"))
- (should (string-equal (file-remote-p "/-:[]:" 'user) "default-user"))
- (should (string-equal (file-remote-p "/-:[]:" 'host) "default-host"))
- (should (string-equal (file-remote-p "/-:[]:" 'localname) ""))
- (should (string-equal (file-remote-p "/-:[]:" 'hop) nil))
-
- ;; Expand `tramp-default-method' and `tramp-default-user'.
- (let ((tramp-default-host "::1"))
- (should (string-equal
- (file-remote-p "/-:[]:")
- (format "/%s:%s@%s:" "default-method" "default-user" "[::1]")))
- (should (string-equal (file-remote-p "/-:[]:" 'method) "default-method"))
- (should (string-equal (file-remote-p "/-:[]:" 'user) "default-user"))
- (should (string-equal (file-remote-p "/-:[]:" 'host) "::1"))
- (should (string-equal (file-remote-p "/-:[]:" 'localname) ""))
- (should (string-equal (file-remote-p "/-:[]:" 'hop) nil)))
-
- ;; Expand `tramp-default-method' and `tramp-default-user'.
- (should (string-equal
- (file-remote-p "/-:[::1]:")
- (format "/%s:%s@%s:" "default-method" "default-user" "[::1]")))
- (should (string-equal (file-remote-p "/-:[::1]:" 'method) "default-method"))
- (should (string-equal (file-remote-p "/-:[::1]:" 'user) "default-user"))
- (should (string-equal (file-remote-p "/-:[::1]:" 'host) "::1"))
- (should (string-equal (file-remote-p "/-:[::1]:" 'localname) ""))
- (should (string-equal (file-remote-p "/-:[::1]:" 'hop) nil))
-
- ;; Expand `tramp-default-method'.
- (should (string-equal
- (file-remote-p "/-:user@[::1]:")
- (format "/%s:%s@%s:" "default-method" "user" "[::1]")))
- (should (string-equal
- (file-remote-p "/-:user@[::1]:" 'method) "default-method"))
- (should (string-equal (file-remote-p "/-:user@[::1]:" 'user) "user"))
- (should (string-equal (file-remote-p "/-:user@[::1]:" 'host) "::1"))
- (should (string-equal (file-remote-p "/-:user@[::1]:" 'localname) ""))
- (should (string-equal (file-remote-p "/-:user@[::1]:" 'hop) nil))
-
- ;; Expand `tramp-default-user'.
- (should (string-equal
- (file-remote-p "/method:[::1]:")
- (format "/%s:%s@%s:" "method" "default-user" "[::1]")))
- (should (string-equal (file-remote-p "/method:[::1]:" 'method) "method"))
- (should (string-equal
- (file-remote-p "/method:[::1]:" 'user) "default-user"))
- (should (string-equal (file-remote-p "/method:[::1]:" 'host) "::1"))
- (should (string-equal (file-remote-p "/method:[::1]:" 'localname) ""))
- (should (string-equal (file-remote-p "/method:[::1]:" 'hop) nil))
-
- ;; No expansion.
- (should (string-equal
- (file-remote-p "/method:user@[::1]:")
- (format "/%s:%s@%s:" "method" "user" "[::1]")))
- (should (string-equal
- (file-remote-p "/method:user@[::1]:" 'method) "method"))
- (should (string-equal (file-remote-p "/method:user@[::1]:" 'user) "user"))
- (should (string-equal (file-remote-p "/method:user@[::1]:" 'host) "::1"))
- (should (string-equal
- (file-remote-p "/method:user@[::1]:" 'localname) ""))
- (should (string-equal (file-remote-p "/method:user@[::1]:" 'hop) nil))
-
- ;; Local file name part.
- (should (string-equal (file-remote-p "/-:host:/:" 'localname) "/:"))
- (should (string-equal (file-remote-p "/method:::" 'localname) ":"))
- (should (string-equal (file-remote-p "/method:: " 'localname) " "))
- (should (string-equal (file-remote-p "/method::file" 'localname) "file"))
- (should (string-equal
- (file-remote-p "/method::/path/to/file" 'localname)
- "/path/to/file"))
-
- ;; Multihop.
- (should
- (string-equal
- (file-remote-p "/method1:user1@host1|method2:user2@host2:/path/to/file")
- (format "/%s:%s@%s|%s:%s@%s:"
- "method1" "user1" "host1" "method2" "user2" "host2")))
- (should
- (string-equal
- (file-remote-p
- "/method1:user1@host1|method2:user2@host2:/path/to/file" 'method)
- "method2"))
- (should
- (string-equal
- (file-remote-p
- "/method1:user1@host1|method2:user2@host2:/path/to/file" 'user)
- "user2"))
- (should
- (string-equal
- (file-remote-p
- "/method1:user1@host1|method2:user2@host2:/path/to/file" 'host)
- "host2"))
- (should
- (string-equal
- (file-remote-p
- "/method1:user1@host1|method2:user2@host2:/path/to/file" 'localname)
- "/path/to/file"))
- (should
- (string-equal
- (file-remote-p
- "/method1:user1@host1|method2:user2@host2:/path/to/file" 'hop)
- (format "%s:%s@%s|"
- "method1" "user1" "host1")))
+ (tramp-default-host "default-host")
+ tramp-default-method-alist
+ tramp-default-user-alist
+ tramp-default-host-alist
+ ;; Suppress method name check.
+ (non-essential t)
+ ;; Suppress check for multihops.
+ (tramp-cache-data (make-hash-table :test #'equal))
+ (tramp-connection-properties '((nil "login-program" t)))
+ (syntax tramp-syntax))
+ (unwind-protect
+ (progn
+ (tramp-change-syntax 'default)
+ ;; An unknown method shall raise an error.
+ (let (non-essential)
+ (should-error
+ (expand-file-name "/method:user@host:")
+ :type 'user-error))
- (should
- (string-equal
- (file-remote-p
- (concat
- "/method1:user1@host1"
- "|method2:user2@host2"
- "|method3:user3@host3:/path/to/file"))
- (format "/%s:%s@%s|%s:%s@%s|%s:%s@%s:"
- "method1" "user1" "host1"
- "method2" "user2" "host2"
- "method3" "user3" "host3")))
- (should
- (string-equal
- (file-remote-p
- (concat
- "/method1:user1@host1"
- "|method2:user2@host2"
- "|method3:user3@host3:/path/to/file")
- 'method)
- "method3"))
- (should
- (string-equal
- (file-remote-p
- (concat
- "/method1:user1@host1"
- "|method2:user2@host2"
- "|method3:user3@host3:/path/to/file")
- 'user)
- "user3"))
- (should
- (string-equal
- (file-remote-p
- (concat
- "/method1:user1@host1"
- "|method2:user2@host2"
- "|method3:user3@host3:/path/to/file")
- 'host)
- "host3"))
- (should
- (string-equal
- (file-remote-p
- (concat
- "/method1:user1@host1"
- "|method2:user2@host2"
- "|method3:user3@host3:/path/to/file")
- 'localname)
- "/path/to/file"))
- (should
- (string-equal
- (file-remote-p
- (concat
- "/method1:user1@host1"
- "|method2:user2@host2"
- "|method3:user3@host3:/path/to/file")
- 'hop)
- (format "%s:%s@%s|%s:%s@%s|"
- "method1" "user1" "host1" "method2" "user2" "host2")))))
+ ;; Expand `tramp-default-user' and `tramp-default-host'.
+ (should
+ (string-equal
+ (file-remote-p "/method::")
+ (format "/%s:%s@%s:" "method" "default-user" "default-host")))
+ (should (string-equal (file-remote-p "/method::" 'method) "method"))
+ (should
+ (string-equal (file-remote-p "/method::" 'user) "default-user"))
+ (should
+ (string-equal (file-remote-p "/method::" 'host) "default-host"))
+ (should (string-equal (file-remote-p "/method::" 'localname) ""))
+ (should (string-equal (file-remote-p "/method::" 'hop) nil))
+
+ ;; Expand `tramp-default-method' and `tramp-default-user'.
+ (should
+ (string-equal
+ (file-remote-p "/-:host:")
+ (format "/%s:%s@%s:" "default-method" "default-user" "host")))
+ (should
+ (string-equal (file-remote-p "/-:host:" 'method) "default-method"))
+ (should
+ (string-equal (file-remote-p "/-:host:" 'user) "default-user"))
+ (should (string-equal (file-remote-p "/-:host:" 'host) "host"))
+ (should (string-equal (file-remote-p "/-:host:" 'localname) ""))
+ (should (string-equal (file-remote-p "/-:host:" 'hop) nil))
+
+ ;; Expand `tramp-default-method' and `tramp-default-host'.
+ (should
+ (string-equal
+ (file-remote-p "/-:user@:")
+ (format "/%s:%s@%s:" "default-method" "user" "default-host")))
+ (should
+ (string-equal (file-remote-p "/-:user@:" 'method) "default-method"))
+ (should (string-equal (file-remote-p "/-:user@:" 'user) "user"))
+ (should
+ (string-equal (file-remote-p "/-:user@:" 'host) "default-host"))
+ (should (string-equal (file-remote-p "/-:user@:" 'localname) ""))
+ (should (string-equal (file-remote-p "/-:user@:" 'hop) nil))
+
+ ;; Expand `tramp-default-method'.
+ (should (string-equal
+ (file-remote-p "/-:user@host:")
+ (format "/%s:%s@%s:" "default-method" "user" "host")))
+ (should (string-equal
+ (file-remote-p "/-:user@host:" 'method) "default-method"))
+ (should (string-equal (file-remote-p "/-:user@host:" 'user) "user"))
+ (should (string-equal (file-remote-p "/-:user@host:" 'host) "host"))
+ (should (string-equal (file-remote-p "/-:user@host:" 'localname) ""))
+ (should (string-equal (file-remote-p "/-:user@host:" 'hop) nil))
+
+ ;; Expand `tramp-default-user'.
+ (should (string-equal
+ (file-remote-p "/method:host:")
+ (format "/%s:%s@%s:" "method" "default-user" "host")))
+ (should
+ (string-equal (file-remote-p "/method:host:" 'method) "method"))
+ (should
+ (string-equal (file-remote-p "/method:host:" 'user) "default-user"))
+ (should (string-equal (file-remote-p "/method:host:" 'host) "host"))
+ (should (string-equal (file-remote-p "/method:host:" 'localname) ""))
+ (should (string-equal (file-remote-p "/method:host:" 'hop) nil))
+
+ ;; Expand `tramp-default-host'.
+ (should
+ (string-equal
+ (file-remote-p "/method:user@:")
+ (format "/%s:%s@%s:" "method" "user" "default-host")))
+ (should
+ (string-equal (file-remote-p "/method:user@:" 'method) "method"))
+ (should (string-equal (file-remote-p "/method:user@:" 'user) "user"))
+ (should
+ (string-equal (file-remote-p "/method:user@:" 'host) "default-host"))
+ (should (string-equal (file-remote-p "/method:user@:" 'localname) ""))
+ (should (string-equal (file-remote-p "/method:user@:" 'hop) nil))
+
+ ;; No expansion.
+ (should (string-equal
+ (file-remote-p "/method:user@host:")
+ (format "/%s:%s@%s:" "method" "user" "host")))
+ (should (string-equal
+ (file-remote-p "/method:user@host:" 'method) "method"))
+ (should
+ (string-equal (file-remote-p "/method:user@host:" 'user) "user"))
+ (should
+ (string-equal (file-remote-p "/method:user@host:" 'host) "host"))
+ (should
+ (string-equal (file-remote-p "/method:user@host:" 'localname) ""))
+ (should (string-equal (file-remote-p "/method:user@host:" 'hop) nil))
+
+ ;; No expansion.
+ (should (string-equal
+ (file-remote-p "/method:user@email@host:")
+ (format "/%s:%s@%s:" "method" "user@email" "host")))
+ (should (string-equal
+ (file-remote-p "/method:user@email@host:" 'method) "method"))
+ (should
+ (string-equal
+ (file-remote-p "/method:user@email@host:" 'user) "user@email"))
+ (should (string-equal
+ (file-remote-p "/method:user@email@host:" 'host) "host"))
+ (should (string-equal
+ (file-remote-p "/method:user@email@host:" 'localname) ""))
+ (should (string-equal
+ (file-remote-p "/method:user@email@host:" 'hop) nil))
+
+ ;; Expand `tramp-default-method' and `tramp-default-user'.
+ (should
+ (string-equal
+ (file-remote-p "/-:host#1234:")
+ (format "/%s:%s@%s:" "default-method" "default-user" "host#1234")))
+ (should (string-equal
+ (file-remote-p "/-:host#1234:" 'method) "default-method"))
+ (should
+ (string-equal (file-remote-p "/-:host#1234:" 'user) "default-user"))
+ (should
+ (string-equal (file-remote-p "/-:host#1234:" 'host) "host#1234"))
+ (should (string-equal (file-remote-p "/-:host#1234:" 'localname) ""))
+ (should (string-equal (file-remote-p "/-:host#1234:" 'hop) nil))
+
+ ;; Expand `tramp-default-method'.
+ (should (string-equal
+ (file-remote-p "/-:user@host#1234:")
+ (format "/%s:%s@%s:" "default-method" "user" "host#1234")))
+ (should
+ (string-equal
+ (file-remote-p "/-:user@host#1234:" 'method) "default-method"))
+ (should
+ (string-equal (file-remote-p "/-:user@host#1234:" 'user) "user"))
+ (should
+ (string-equal
+ (file-remote-p "/-:user@host#1234:" 'host) "host#1234"))
+ (should
+ (string-equal (file-remote-p "/-:user@host#1234:" 'localname) ""))
+ (should (string-equal (file-remote-p "/-:user@host#1234:" 'hop) nil))
+
+ ;; Expand `tramp-default-user'.
+ (should (string-equal
+ (file-remote-p "/method:host#1234:")
+ (format "/%s:%s@%s:" "method" "default-user" "host#1234")))
+ (should (string-equal
+ (file-remote-p "/method:host#1234:" 'method) "method"))
+ (should (string-equal
+ (file-remote-p "/method:host#1234:" 'user) "default-user"))
+ (should (string-equal
+ (file-remote-p "/method:host#1234:" 'host) "host#1234"))
+ (should
+ (string-equal (file-remote-p "/method:host#1234:" 'localname) ""))
+ (should (string-equal (file-remote-p "/method:host#1234:" 'hop) nil))
+
+ ;; No expansion.
+ (should (string-equal
+ (file-remote-p "/method:user@host#1234:")
+ (format "/%s:%s@%s:" "method" "user" "host#1234")))
+ (should (string-equal
+ (file-remote-p "/method:user@host#1234:" 'method) "method"))
+ (should (string-equal
+ (file-remote-p "/method:user@host#1234:" 'user) "user"))
+ (should (string-equal
+ (file-remote-p "/method:user@host#1234:" 'host) "host#1234"))
+ (should (string-equal
+ (file-remote-p "/method:user@host#1234:" 'localname) ""))
+ (should (string-equal
+ (file-remote-p "/method:user@host#1234:" 'hop) nil))
+
+ ;; Expand `tramp-default-method' and `tramp-default-user'.
+ (should
+ (string-equal
+ (file-remote-p "/-:1.2.3.4:")
+ (format "/%s:%s@%s:" "default-method" "default-user" "1.2.3.4")))
+ (should
+ (string-equal
+ (file-remote-p "/-:1.2.3.4:" 'method) "default-method"))
+ (should
+ (string-equal (file-remote-p "/-:1.2.3.4:" 'user) "default-user"))
+ (should (string-equal (file-remote-p "/-:1.2.3.4:" 'host) "1.2.3.4"))
+ (should (string-equal (file-remote-p "/-:1.2.3.4:" 'localname) ""))
+ (should (string-equal (file-remote-p "/-:1.2.3.4:" 'hop) nil))
+
+ ;; Expand `tramp-default-method'.
+ (should (string-equal
+ (file-remote-p "/-:user@1.2.3.4:")
+ (format "/%s:%s@%s:" "default-method" "user" "1.2.3.4")))
+ (should (string-equal
+ (file-remote-p "/-:user@1.2.3.4:" 'method) "default-method"))
+ (should
+ (string-equal (file-remote-p "/-:user@1.2.3.4:" 'user) "user"))
+ (should
+ (string-equal (file-remote-p "/-:user@1.2.3.4:" 'host) "1.2.3.4"))
+ (should
+ (string-equal (file-remote-p "/-:user@1.2.3.4:" 'localname) ""))
+ (should
+ (string-equal (file-remote-p "/-:user@1.2.3.4:" 'hop) nil))
+
+ ;; Expand `tramp-default-user'.
+ (should (string-equal
+ (file-remote-p "/method:1.2.3.4:")
+ (format "/%s:%s@%s:" "method" "default-user" "1.2.3.4")))
+ (should
+ (string-equal (file-remote-p "/method:1.2.3.4:" 'method) "method"))
+ (should (string-equal
+ (file-remote-p "/method:1.2.3.4:" 'user) "default-user"))
+ (should
+ (string-equal (file-remote-p "/method:1.2.3.4:" 'host) "1.2.3.4"))
+ (should
+ (string-equal (file-remote-p "/method:1.2.3.4:" 'localname) ""))
+ (should (string-equal (file-remote-p "/method:1.2.3.4:" 'hop) nil))
+
+ ;; No expansion.
+ (should (string-equal
+ (file-remote-p "/method:user@1.2.3.4:")
+ (format "/%s:%s@%s:" "method" "user" "1.2.3.4")))
+ (should (string-equal
+ (file-remote-p "/method:user@1.2.3.4:" 'method) "method"))
+ (should
+ (string-equal (file-remote-p "/method:user@1.2.3.4:" 'user) "user"))
+ (should (string-equal
+ (file-remote-p "/method:user@1.2.3.4:" 'host) "1.2.3.4"))
+ (should (string-equal
+ (file-remote-p "/method:user@1.2.3.4:" 'localname) ""))
+ (should (string-equal
+ (file-remote-p "/method:user@1.2.3.4:" 'hop) nil))
+
+ ;; Expand `tramp-default-method', `tramp-default-user' and
+ ;; `tramp-default-host'.
+ (should
+ (string-equal
+ (file-remote-p "/-:[]:")
+ (format
+ "/%s:%s@%s:" "default-method" "default-user" "default-host")))
+ (should
+ (string-equal (file-remote-p "/-:[]:" 'method) "default-method"))
+ (should (string-equal (file-remote-p "/-:[]:" 'user) "default-user"))
+ (should (string-equal (file-remote-p "/-:[]:" 'host) "default-host"))
+ (should (string-equal (file-remote-p "/-:[]:" 'localname) ""))
+ (should (string-equal (file-remote-p "/-:[]:" 'hop) nil))
+
+ ;; Expand `tramp-default-method' and `tramp-default-user'.
+ (let ((tramp-default-host "::1"))
+ (should
+ (string-equal
+ (file-remote-p "/-:[]:")
+ (format "/%s:%s@%s:" "default-method" "default-user" "[::1]")))
+ (should
+ (string-equal (file-remote-p "/-:[]:" 'method) "default-method"))
+ (should
+ (string-equal (file-remote-p "/-:[]:" 'user) "default-user"))
+ (should (string-equal (file-remote-p "/-:[]:" 'host) "::1"))
+ (should (string-equal (file-remote-p "/-:[]:" 'localname) ""))
+ (should (string-equal (file-remote-p "/-:[]:" 'hop) nil)))
+
+ ;; Expand `tramp-default-method' and `tramp-default-user'.
+ (should
+ (string-equal
+ (file-remote-p "/-:[::1]:")
+ (format "/%s:%s@%s:" "default-method" "default-user" "[::1]")))
+ (should
+ (string-equal (file-remote-p "/-:[::1]:" 'method) "default-method"))
+ (should
+ (string-equal (file-remote-p "/-:[::1]:" 'user) "default-user"))
+ (should (string-equal (file-remote-p "/-:[::1]:" 'host) "::1"))
+ (should (string-equal (file-remote-p "/-:[::1]:" 'localname) ""))
+ (should (string-equal (file-remote-p "/-:[::1]:" 'hop) nil))
+
+ ;; Expand `tramp-default-method'.
+ (should (string-equal
+ (file-remote-p "/-:user@[::1]:")
+ (format "/%s:%s@%s:" "default-method" "user" "[::1]")))
+ (should (string-equal
+ (file-remote-p "/-:user@[::1]:" 'method) "default-method"))
+ (should (string-equal (file-remote-p "/-:user@[::1]:" 'user) "user"))
+ (should (string-equal (file-remote-p "/-:user@[::1]:" 'host) "::1"))
+ (should (string-equal (file-remote-p "/-:user@[::1]:" 'localname) ""))
+ (should (string-equal (file-remote-p "/-:user@[::1]:" 'hop) nil))
+
+ ;; Expand `tramp-default-user'.
+ (should (string-equal
+ (file-remote-p "/method:[::1]:")
+ (format "/%s:%s@%s:" "method" "default-user" "[::1]")))
+ (should
+ (string-equal (file-remote-p "/method:[::1]:" 'method) "method"))
+ (should (string-equal
+ (file-remote-p "/method:[::1]:" 'user) "default-user"))
+ (should (string-equal (file-remote-p "/method:[::1]:" 'host) "::1"))
+ (should (string-equal (file-remote-p "/method:[::1]:" 'localname) ""))
+ (should (string-equal (file-remote-p "/method:[::1]:" 'hop) nil))
+
+ ;; No expansion.
+ (should (string-equal
+ (file-remote-p "/method:user@[::1]:")
+ (format "/%s:%s@%s:" "method" "user" "[::1]")))
+ (should (string-equal
+ (file-remote-p "/method:user@[::1]:" 'method) "method"))
+ (should
+ (string-equal (file-remote-p "/method:user@[::1]:" 'user) "user"))
+ (should
+ (string-equal (file-remote-p "/method:user@[::1]:" 'host) "::1"))
+ (should (string-equal
+ (file-remote-p "/method:user@[::1]:" 'localname) ""))
+ (should (string-equal (file-remote-p "/method:user@[::1]:" 'hop) nil))
+
+ ;; Local file name part.
+ (should (string-equal (file-remote-p "/-:host:/:" 'localname) "/:"))
+ (should (string-equal (file-remote-p "/method:::" 'localname) ":"))
+ (should (string-equal (file-remote-p "/method:: " 'localname) " "))
+ (should
+ (string-equal (file-remote-p "/method::file" 'localname) "file"))
+ (should (string-equal
+ (file-remote-p "/method::/path/to/file" 'localname)
+ "/path/to/file"))
+
+ ;; Multihop.
+ (should
+ (string-equal
+ (file-remote-p
+ "/method1:user1@host1|method2:user2@host2:/path/to/file")
+ "/method2:user2@host2:"))
+ (should
+ (string-equal
+ (file-remote-p
+ "/method1:user1@host1|method2:user2@host2:/path/to/file" 'method)
+ "method2"))
+ (should
+ (string-equal
+ (file-remote-p
+ "/method1:user1@host1|method2:user2@host2:/path/to/file" 'user)
+ "user2"))
+ (should
+ (string-equal
+ (file-remote-p
+ "/method1:user1@host1|method2:user2@host2:/path/to/file" 'host)
+ "host2"))
+ (should
+ (string-equal
+ (file-remote-p
+ "/method1:user1@host1|method2:user2@host2:/path/to/file"
+ 'localname)
+ "/path/to/file"))
+ (should
+ (string-equal
+ (file-remote-p
+ "/method1:user1@host1|method2:user2@host2:/path/to/file" 'hop)
+ (format "%s:%s@%s|"
+ "method1" "user1" "host1")))
+
+ (should
+ (string-equal
+ (file-remote-p
+ (concat
+ "/method1:user1@host1"
+ "|method2:user2@host2"
+ "|method3:user3@host3:/path/to/file"))
+ "/method3:user3@host3:"))
+ (should
+ (string-equal
+ (file-remote-p
+ (concat
+ "/method1:user1@host1"
+ "|method2:user2@host2"
+ "|method3:user3@host3:/path/to/file")
+ 'method)
+ "method3"))
+ (should
+ (string-equal
+ (file-remote-p
+ (concat
+ "/method1:user1@host1"
+ "|method2:user2@host2"
+ "|method3:user3@host3:/path/to/file")
+ 'user)
+ "user3"))
+ (should
+ (string-equal
+ (file-remote-p
+ (concat
+ "/method1:user1@host1"
+ "|method2:user2@host2"
+ "|method3:user3@host3:/path/to/file")
+ 'host)
+ "host3"))
+ (should
+ (string-equal
+ (file-remote-p
+ (concat
+ "/method1:user1@host1"
+ "|method2:user2@host2"
+ "|method3:user3@host3:/path/to/file")
+ 'localname)
+ "/path/to/file"))
+ (should
+ (string-equal
+ (file-remote-p
+ (concat
+ "/method1:user1@host1"
+ "|method2:user2@host2"
+ "|method3:user3@host3:/path/to/file")
+ 'hop)
+ (format "%s:%s@%s|%s:%s@%s|"
+ "method1" "user1" "host1" "method2" "user2" "host2")))
+
+ ;; Expand `tramp-default-method-alist'.
+ (add-to-list 'tramp-default-method-alist '("host1" "user1" "method1"))
+ (add-to-list 'tramp-default-method-alist '("host2" "user2" "method2"))
+ (add-to-list 'tramp-default-method-alist '("host3" "user3" "method3"))
+ (should
+ (string-equal
+ (file-remote-p
+ (concat
+ "/-:user1@host1"
+ "|-:user2@host2"
+ "|-:user3@host3:/path/to/file"))
+ "/method3:user3@host3:"))
+
+ ;; Expand `tramp-default-user-alist'.
+ (add-to-list 'tramp-default-user-alist '("method1" "host1" "user1"))
+ (add-to-list 'tramp-default-user-alist '("method2" "host2" "user2"))
+ (add-to-list 'tramp-default-user-alist '("method3" "host3" "user3"))
+ (should
+ (string-equal
+ (file-remote-p
+ (concat
+ "/method1:host1"
+ "|method2:host2"
+ "|method3:host3:/path/to/file"))
+ "/method3:user3@host3:"))
+
+ ;; Expand `tramp-default-host-alist'.
+ (add-to-list 'tramp-default-host-alist '("method1" "user1" "host1"))
+ (add-to-list 'tramp-default-host-alist '("method2" "user2" "host2"))
+ (add-to-list 'tramp-default-host-alist '("method3" "user3" "host3"))
+ (should
+ (string-equal
+ (file-remote-p
+ (concat
+ "/method1:user1@"
+ "|method2:user2@"
+ "|method3:user3@:/path/to/file"))
+ "/method3:user3@host3:"))
+
+ ;; Ad-hoc user name and host name expansion.
+ (setq tramp-default-method-alist nil
+ tramp-default-user-alist nil
+ tramp-default-host-alist nil)
+ (should
+ (string-equal
+ (file-remote-p
+ (concat
+ "/method1:user1@host1"
+ "|method2:user2@"
+ "|method3:user3@:/path/to/file"))
+ "/method3:user3@host1:"))
+ (should
+ (string-equal
+ (file-remote-p
+ (concat
+ "/method1:%u@%h"
+ "|method2:user2@host2"
+ "|method3:%u@%h"
+ "|method4:user4%domain4@host4#1234:/path/to/file"))
+ "/method4:user4%domain4@host4#1234:")))
+
+ ;; Exit.
+ (tramp-change-syntax syntax))))
(ert-deftest tramp-test02-file-name-dissect-simplified ()
"Check simplified file name components."
@@ -718,10 +1012,23 @@ handled properly. BODY shall not contain a timeout."
(let ((tramp-default-method "default-method")
(tramp-default-user "default-user")
(tramp-default-host "default-host")
+ tramp-default-user-alist
+ tramp-default-host-alist
+ ;; Suppress method name check.
+ (non-essential t)
+ ;; Suppress check for multihops.
+ (tramp-cache-data (make-hash-table :test #'equal))
+ (tramp-connection-properties '((nil "login-program" t)))
(syntax tramp-syntax))
(unwind-protect
(progn
(tramp-change-syntax 'simplified)
+ ;; An unknown default method shall raise an error.
+ (let (non-essential)
+ (should-error
+ (expand-file-name "/user@host:")
+ :type 'user-error))
+
;; Expand `tramp-default-method' and `tramp-default-user'.
(should (string-equal
(file-remote-p "/host:")
@@ -760,8 +1067,7 @@ handled properly. BODY shall not contain a timeout."
(file-remote-p "/user@email@host:")
(format "/%s@%s:" "user@email" "host")))
(should (string-equal
- (file-remote-p
- "/user@email@host:" 'method) "default-method"))
+ (file-remote-p "/user@email@host:" 'method) "default-method"))
(should (string-equal
(file-remote-p "/user@email@host:" 'user) "user@email"))
(should (string-equal
@@ -882,7 +1188,7 @@ handled properly. BODY shall not contain a timeout."
(should
(string-equal
(file-remote-p "/user1@host1|user2@host2:/path/to/file")
- (format "/%s@%s|%s@%s:" "user1" "host1" "user2" "host2")))
+ "/user2@host2:"))
(should
(string-equal
(file-remote-p
@@ -916,10 +1222,7 @@ handled properly. BODY shall not contain a timeout."
"/user1@host1"
"|user2@host2"
"|user3@host3:/path/to/file"))
- (format "/%s@%s|%s@%s|%s@%s:"
- "user1" "host1"
- "user2" "host2"
- "user3" "host3")))
+ "/user3@host3:"))
(should
(string-equal
(file-remote-p
@@ -965,7 +1268,54 @@ handled properly. BODY shall not contain a timeout."
"|user3@host3:/path/to/file")
'hop)
(format "%s@%s|%s@%s|"
- "user1" "host1" "user2" "host2"))))
+ "user1" "host1" "user2" "host2")))
+
+ ;; Expand `tramp-default-user-alist'.
+ (add-to-list 'tramp-default-user-alist '(nil "host1" "user1"))
+ (add-to-list 'tramp-default-user-alist '(nil "host2" "user2"))
+ (add-to-list 'tramp-default-user-alist '(nil "host3" "user3"))
+ (should
+ (string-equal
+ (file-remote-p
+ (concat
+ "/host1"
+ "|host2"
+ "|host3:/path/to/file"))
+ "/user3@host3:"))
+
+ ;; Expand `tramp-default-host-alist'.
+ (add-to-list 'tramp-default-host-alist '(nil "user1" "host1"))
+ (add-to-list 'tramp-default-host-alist '(nil "user2" "host2"))
+ (add-to-list 'tramp-default-host-alist '(nil "user3" "host3"))
+ (should
+ (string-equal
+ (file-remote-p
+ (concat
+ "/user1@"
+ "|user2@"
+ "|user3@:/path/to/file"))
+ "/user3@host3:"))
+
+ ;; Ad-hoc user name and host name expansion.
+ (setq tramp-default-user-alist nil
+ tramp-default-host-alist nil)
+ (should
+ (string-equal
+ (file-remote-p
+ (concat
+ "/user1@host1"
+ "|user2@"
+ "|user3@:/path/to/file"))
+ "/user3@host1:"))
+ (should
+ (string-equal
+ (file-remote-p
+ (concat
+ "/%u@%h"
+ "|user2@host2"
+ "|%u@%h"
+ "|user4%domain4@host4#1234:/path/to/file"))
+ "/user4%domain4@host4#1234:")))
;; Exit.
(tramp-change-syntax syntax))))
@@ -976,10 +1326,24 @@ handled properly. BODY shall not contain a timeout."
(let ((tramp-default-method "default-method")
(tramp-default-user "default-user")
(tramp-default-host "default-host")
+ tramp-default-method-alist
+ tramp-default-user-alist
+ tramp-default-host-alist
+ ;; Suppress method name check.
+ (non-essential t)
+ ;; Suppress check for multihops.
+ (tramp-cache-data (make-hash-table :test #'equal))
+ (tramp-connection-properties '((nil "login-program" t)))
(syntax tramp-syntax))
(unwind-protect
(progn
(tramp-change-syntax 'separate)
+ ;; An unknown method shall raise an error.
+ (let (non-essential)
+ (should-error
+ (expand-file-name "/[method/user@host]")
+ :type 'user-error))
+
;; Expand `tramp-default-user' and `tramp-default-host'.
(should (string-equal
(file-remote-p "/[method/]")
@@ -1112,11 +1476,10 @@ handled properly. BODY shall not contain a timeout."
(file-remote-p "/[method/user@email@host]")
(format "/[%s/%s@%s]" "method" "user@email" "host")))
(should (string-equal
- (file-remote-p
- "/[method/user@email@host]" 'method) "method"))
+ (file-remote-p "/[method/user@email@host]" 'method) "method"))
(should (string-equal
- (file-remote-p
- "/[method/user@email@host]" 'user) "user@email"))
+ (file-remote-p "/[method/user@email@host]" 'user)
+ "user@email"))
(should (string-equal
(file-remote-p "/[method/user@email@host]" 'host) "host"))
(should (string-equal
@@ -1143,11 +1506,10 @@ handled properly. BODY shall not contain a timeout."
(file-remote-p "/[/user@host#1234]")
(format "/[%s/%s@%s]" "default-method" "user" "host#1234")))
(should (string-equal
- (file-remote-p
- "/[/user@host#1234]" 'method) "default-method"))
+ (file-remote-p "/[/user@host#1234]" 'method)
+ "default-method"))
(should (string-equal
- (file-remote-p
- "/[/user@host#1234]" 'user) "user"))
+ (file-remote-p "/[/user@host#1234]" 'user) "user"))
(should (string-equal
(file-remote-p "/[/user@host#1234]" 'host) "host#1234"))
(should (string-equal
@@ -1173,11 +1535,10 @@ handled properly. BODY shall not contain a timeout."
(file-remote-p "/[-/user@host#1234]")
(format "/[%s/%s@%s]" "default-method" "user" "host#1234")))
(should (string-equal
- (file-remote-p
- "/[-/user@host#1234]" 'method) "default-method"))
+ (file-remote-p "/[-/user@host#1234]" 'method)
+ "default-method"))
(should (string-equal
- (file-remote-p
- "/[-/user@host#1234]" 'user) "user"))
+ (file-remote-p "/[-/user@host#1234]" 'user) "user"))
(should (string-equal
(file-remote-p "/[-/user@host#1234]" 'host) "host#1234"))
(should (string-equal
@@ -1207,8 +1568,7 @@ handled properly. BODY shall not contain a timeout."
(should (string-equal
(file-remote-p "/[method/user@host#1234]" 'user) "user"))
(should (string-equal
- (file-remote-p
- "/[method/user@host#1234]" 'host) "host#1234"))
+ (file-remote-p "/[method/user@host#1234]" 'host) "host#1234"))
(should (string-equal
(file-remote-p "/[method/user@host#1234]" 'localname) ""))
(should (string-equal
@@ -1233,8 +1593,7 @@ handled properly. BODY shall not contain a timeout."
(file-remote-p "/[/user@1.2.3.4]")
(format "/[%s/%s@%s]" "default-method" "user" "1.2.3.4")))
(should (string-equal
- (file-remote-p
- "/[/user@1.2.3.4]" 'method) "default-method"))
+ (file-remote-p "/[/user@1.2.3.4]" 'method) "default-method"))
(should (string-equal
(file-remote-p "/[/user@1.2.3.4]" 'user) "user"))
(should (string-equal
@@ -1262,8 +1621,7 @@ handled properly. BODY shall not contain a timeout."
(file-remote-p "/[-/user@1.2.3.4]")
(format "/[%s/%s@%s]" "default-method" "user" "1.2.3.4")))
(should (string-equal
- (file-remote-p
- "/[-/user@1.2.3.4]" 'method) "default-method"))
+ (file-remote-p "/[-/user@1.2.3.4]" 'method) "default-method"))
(should (string-equal
(file-remote-p "/[-/user@1.2.3.4]" 'user) "user"))
(should (string-equal
@@ -1447,8 +1805,7 @@ handled properly. BODY shall not contain a timeout."
(string-equal
(file-remote-p
"/[method1/user1@host1|method2/user2@host2]/path/to/file")
- (format "/[%s/%s@%s|%s/%s@%s]"
- "method1" "user1" "host1" "method2" "user2" "host2")))
+ "/[method2/user2@host2]"))
(should
(string-equal
(file-remote-p
@@ -1484,10 +1841,7 @@ handled properly. BODY shall not contain a timeout."
"/[method1/user1@host1"
"|method2/user2@host2"
"|method3/user3@host3]/path/to/file"))
- (format "/[%s/%s@%s|%s/%s@%s|%s/%s@%s]"
- "method1" "user1" "host1"
- "method2" "user2" "host2"
- "method3" "user3" "host3")))
+ "/[method3/user3@host3]"))
(should
(string-equal
(file-remote-p
@@ -1533,220 +1887,475 @@ handled properly. BODY shall not contain a timeout."
"|method3/user3@host3]/path/to/file")
'hop)
(format "%s/%s@%s|%s/%s@%s|"
- "method1" "user1" "host1" "method2" "user2" "host2"))))
+ "method1" "user1" "host1" "method2" "user2" "host2")))
+
+ ;; Expand `tramp-default-method-alist'.
+ (add-to-list 'tramp-default-method-alist '("host1" "user1" "method1"))
+ (add-to-list 'tramp-default-method-alist '("host2" "user2" "method2"))
+ (add-to-list 'tramp-default-method-alist '("host3" "user3" "method3"))
+ (should
+ (string-equal
+ (file-remote-p
+ (concat
+ "/[/user1@host1"
+ "|/user2@host2"
+ "|/user3@host3]/path/to/file"))
+ "/[method3/user3@host3]"))
+
+ ;; Expand `tramp-default-user-alist'.
+ (add-to-list 'tramp-default-user-alist '("method1" "host1" "user1"))
+ (add-to-list 'tramp-default-user-alist '("method2" "host2" "user2"))
+ (add-to-list 'tramp-default-user-alist '("method3" "host3" "user3"))
+ (should
+ (string-equal
+ (file-remote-p
+ (concat
+ "/[method1/host1"
+ "|method2/host2"
+ "|method3/host3]/path/to/file"))
+ "/[method3/user3@host3]"))
+
+ ;; Expand `tramp-default-host-alist'.
+ (add-to-list 'tramp-default-host-alist '("method1" "user1" "host1"))
+ (add-to-list 'tramp-default-host-alist '("method2" "user2" "host2"))
+ (add-to-list 'tramp-default-host-alist '("method3" "user3" "host3"))
+ (should
+ (string-equal
+ (file-remote-p
+ (concat
+ "/[method1/user1@"
+ "|method2/user2@"
+ "|method3/user3@]/path/to/file"))
+ "/[method3/user3@host3]"))
+
+ ;; Ad-hoc user name and host name expansion.
+ (setq tramp-default-method-alist nil
+ tramp-default-user-alist nil
+ tramp-default-host-alist nil)
+ (should
+ (string-equal
+ (file-remote-p
+ (concat
+ "/[method1/user1@host1"
+ "|method2/user2@"
+ "|method3/user3@]/path/to/file"))
+ "/[method3/user3@host1]"))
+ (should
+ (string-equal
+ (file-remote-p
+ (concat
+ "/[method1/%u@%h"
+ "|method2/user2@host2"
+ "|method3/%u@%h"
+ "|method4/user4%domain4@host4#1234]/path/to/file"))
+ "/[method4/user4%domain4@host4#1234]")))
;; Exit.
(tramp-change-syntax syntax))))
(ert-deftest tramp-test03-file-name-defaults ()
"Check default values for some methods."
+ (skip-unless (eq tramp-syntax 'default))
+
;; Default values in tramp-adb.el.
- (should (string-equal (file-remote-p "/adb::" 'host) ""))
+ (when (assoc "adb" tramp-methods)
+ (should (string-equal (file-remote-p "/adb::" 'host) "")))
;; Default values in tramp-ftp.el.
- (should (string-equal (file-remote-p "/-:ftp.host:" 'method) "ftp"))
- (dolist (u '("ftp" "anonymous"))
- (should (string-equal (file-remote-p (format "/-:%s@:" u) 'method) "ftp")))
- ;; Default values in tramp-gvfs.el.
- (when (and (load "tramp-gvfs" 'noerror 'nomessage)
- (symbol-value 'tramp-gvfs-enabled))
- (should (string-equal (file-remote-p "/synce::" 'user) nil)))
- ;; Default values in tramp-sh.el.
- (dolist (h `("127.0.0.1" "[::1]" "localhost" "localhost6" ,(system-name)))
- (should
- (string-equal (file-remote-p (format "/-:root@%s:" h) 'method) "su")))
- (dolist (m '("su" "sudo" "ksu"))
- (should (string-equal (file-remote-p (format "/%s::" m) 'user) "root")))
- (dolist (m '("rcp" "remcp" "rsh" "telnet" "krlogin" "fcp"))
- (should
- (string-equal (file-remote-p (format "/%s::" m) 'user) (user-login-name))))
+ (when (assoc "ftp" tramp-methods)
+ (should (string-equal (file-remote-p "/-:ftp.host:" 'method) "ftp"))
+ (dolist (u '("ftp" "anonymous"))
+ (should
+ (string-equal (file-remote-p (format "/-:%s@:" u) 'method) "ftp"))))
+ ;; Default values in tramp-sh.el and tramp-sudoedit.el.
+ (when (assoc "su" tramp-methods)
+ (dolist (h `("127.0.0.1" "[::1]" "localhost" "localhost6" ,(system-name)))
+ (should
+ (string-equal (file-remote-p (format "/-:root@%s:" h) 'method) "su")))
+ (dolist (m '("su" "sudo" "ksu" "doas" "sudoedit"))
+ (should (string-equal (file-remote-p (format "/%s::" m) 'user) "root"))
+ (should
+ (string-equal (file-remote-p (format "/%s::" m) 'host) (system-name))))
+ (dolist (m '("rcp" "remcp" "rsh" "telnet" "krlogin" "fcp" "nc"))
+ (should
+ (string-equal
+ (file-remote-p (format "/%s::" m) 'user) (user-login-name)))))
;; Default values in tramp-smb.el.
- (should (string-equal (file-remote-p "/smb::" 'user) nil)))
+ (when (assoc "smb" tramp-methods)
+ (should (string-equal (file-remote-p "/smb::" 'user) nil))))
+
+;; The following test is inspired by Bug#30946.
+(ert-deftest tramp-test03-file-name-host-rules ()
+ "Check host name rules for host-less methods."
+ (skip-unless (eq tramp-syntax 'default))
+ (skip-unless (tramp--test-enabled))
+ (skip-unless (tramp--test-sh-p))
+
+ ;; Host names must match rules in case the command template of a
+ ;; method doesn't use them.
+ (dolist (m '("su" "sg" "sudo" "doas" "ksu"))
+ (let (tramp-connection-properties tramp-default-proxies-alist)
+ (ignore-errors
+ (tramp-cleanup-connection tramp-test-vec nil 'keep-password))
+ ;; Single hop. The host name must match `tramp-local-host-regexp'.
+ (should-error
+ (find-file (format "/%s:foo:" m))
+ :type 'user-error)
+ ;; Multi hop. The host name must match the previous hop.
+ (should-error
+ (find-file
+ (format
+ "%s|%s:foo:"
+ (substring (file-remote-p ert-remote-temporary-file-directory) 0 -1)
+ m))
+ :type 'user-error))))
+
+(ert-deftest tramp-test03-file-name-method-rules ()
+ "Check file name rules for some methods."
+ (skip-unless (eq tramp-syntax 'default))
+ (skip-unless (tramp--test-enabled))
+
+ ;; Multi hops are allowed for inline methods only.
+ (let (non-essential)
+ (should-error
+ (expand-file-name "/ssh:user1@host1|method:user2@host2:/path/to/file")
+ :type 'user-error)
+ (should-error
+ (expand-file-name "/method:user1@host1|ssh:user2@host2:/path/to/file")
+ :type 'user-error)))
(ert-deftest tramp-test04-substitute-in-file-name ()
"Check `substitute-in-file-name'."
- (should (string-equal (substitute-in-file-name "/method:host://foo") "/foo"))
- (should
- (string-equal
- (substitute-in-file-name "/method:host:/path//foo") "/method:host:/foo"))
- (should
- (string-equal (substitute-in-file-name "/method:host:/path///foo") "/foo"))
- ;; Quoting local part.
- (should
- (string-equal
- (substitute-in-file-name "/method:host:/://foo") "/method:host:/://foo"))
- (should
- (string-equal
- (substitute-in-file-name "/method:host:/:/path//foo")
- "/method:host:/:/path//foo"))
- (should
- (string-equal
- (substitute-in-file-name "/method:host:/:/path///foo")
- "/method:host:/:/path///foo"))
-
- (should
- (string-equal
- (substitute-in-file-name "/method:host:/path/~/foo") "/method:host:~/foo"))
- (should
- (string-equal (substitute-in-file-name "/method:host:/path//~/foo") "~/foo"))
- ;; Quoting local part.
- (should
- (string-equal
- (substitute-in-file-name "/method:host:/:/path/~/foo")
- "/method:host:/:/path/~/foo"))
- (should
- (string-equal
- (substitute-in-file-name "/method:host:/:/path//~/foo")
- "/method:host:/:/path//~/foo"))
+ (skip-unless (eq tramp-syntax 'default))
+
+ ;; Suppress method name check. We cannot use the string "foo" as
+ ;; user name, because (substitute-in-string "/~foo") returns
+ ;; different values depending on the existence of user "foo" (see
+ ;; Bug#43052).
+ (let ((tramp-methods (cons '("method") tramp-methods))
+ (foo (downcase (md5 (current-time-string)))))
+ (should
+ (string-equal (substitute-in-file-name "/method:host:///foo") "/foo"))
+ (should
+ (string-equal
+ (substitute-in-file-name "/method:host://foo") "/method:host:/foo"))
+ (should
+ (string-equal (substitute-in-file-name "/method:host:/path///foo") "/foo"))
+ (should
+ (string-equal
+ (substitute-in-file-name "/method:host:/path//foo") "/method:host:/foo"))
+ ;; Quoting local part.
+ (should
+ (string-equal
+ (substitute-in-file-name "/method:host:/:///foo")
+ "/method:host:/:///foo"))
+ (should
+ (string-equal
+ (substitute-in-file-name "/method:host:/://foo") "/method:host:/://foo"))
+ (should
+ (string-equal
+ (substitute-in-file-name "/method:host:/:/path///foo")
+ "/method:host:/:/path///foo"))
+ (should
+ (string-equal
+ (substitute-in-file-name "/method:host:/:/path//foo")
+ "/method:host:/:/path//foo"))
- (let (process-environment)
(should
(string-equal
- (substitute-in-file-name "/method:host:/path/$FOO")
- "/method:host:/path/$FOO"))
- (setenv "FOO" "bla")
+ (substitute-in-file-name (concat "/method:host://~" foo))
+ (concat "/~" foo)))
(should
(string-equal
- (substitute-in-file-name "/method:host:/path/$FOO")
- "/method:host:/path/bla"))
+ (substitute-in-file-name (concat "/method:host:/~" foo))
+ (concat "/method:host:/~" foo)))
(should
(string-equal
- (substitute-in-file-name "/method:host:/path/$$FOO")
- "/method:host:/path/$FOO"))
+ (substitute-in-file-name (concat "/method:host:/path//~" foo))
+ (concat "/~" foo)))
+ ;; (substitute-in-file-name "/path/~foo") expands only for a local
+ ;; user "foo" to "/~foo"". Otherwise, it doesn't expand.
+ (should
+ (string-equal
+ (substitute-in-file-name (concat "/method:host:/path/~" foo))
+ (concat "/method:host:/path/~" foo)))
;; Quoting local part.
(should
(string-equal
- (substitute-in-file-name "/method:host:/:/path/$FOO")
- "/method:host:/:/path/$FOO"))
- (setenv "FOO" "bla")
+ (substitute-in-file-name (concat "/method:host:/://~" foo))
+ (concat "/method:host:/://~" foo)))
(should
(string-equal
- (substitute-in-file-name "/method:host:/:/path/$FOO")
- "/method:host:/:/path/$FOO"))
+ (substitute-in-file-name (concat "/method:host:/:/~" foo))
+ (concat "/method:host:/:/~" foo)))
(should
(string-equal
- (substitute-in-file-name "/method:host:/:/path/$$FOO")
- "/method:host:/:/path/$$FOO"))))
+ (substitute-in-file-name (concat "/method:host:/:/path//~" foo))
+ (concat "/method:host:/:/path//~" foo)))
+ (should
+ (string-equal
+ (substitute-in-file-name (concat "/method:host:/:/path/~" foo))
+ (concat "/method:host:/:/path/~" foo)))
+
+ (let (process-environment)
+ (should
+ (string-equal
+ (substitute-in-file-name "/method:host:/path/$FOO")
+ "/method:host:/path/$FOO"))
+ (setenv "FOO" "bla")
+ (should
+ (string-equal
+ (substitute-in-file-name "/method:host:/path/$FOO")
+ "/method:host:/path/bla"))
+ (should
+ (string-equal
+ (substitute-in-file-name "/method:host:/path/$$FOO")
+ "/method:host:/path/$FOO"))
+ ;; Quoting local part.
+ (should
+ (string-equal
+ (substitute-in-file-name "/method:host:/:/path/$FOO")
+ "/method:host:/:/path/$FOO"))
+ (setenv "FOO" "bla")
+ (should
+ (string-equal
+ (substitute-in-file-name "/method:host:/:/path/$FOO")
+ "/method:host:/:/path/$FOO"))
+ (should
+ (string-equal
+ (substitute-in-file-name "/method:host:/:/path/$$FOO")
+ "/method:host:/:/path/$$FOO")))))
(ert-deftest tramp-test05-expand-file-name ()
"Check `expand-file-name'."
- (should
- (string-equal
- (expand-file-name "/method:host:/path/./file") "/method:host:/path/file"))
- (should
- (string-equal
- (expand-file-name "/method:host:/path/../file") "/method:host:/file"))
- ;; Quoting local part.
- (should
- (string-equal
- (expand-file-name "/method:host:/:/path/./file")
- "/method:host:/:/path/file"))
- (should
- (string-equal
- (expand-file-name "/method:host:/:/path/../file") "/method:host:/:/file"))
- (should
- (string-equal
- (expand-file-name "/method:host:/:/~/path/./file")
- "/method:host:/:/~/path/file")))
+ (skip-unless (eq tramp-syntax 'default))
-;; The following test is inspired by Bug#26911. It is rather a bug in
-;; `expand-file-name', and it fails for all Emacs versions. Test
-;; added for later, when it is fixed.
+ ;; Suppress method name check.
+ (let ((tramp-methods (cons '("method") tramp-methods)))
+ (should
+ (string-equal
+ (expand-file-name "/method:host:/path/./file") "/method:host:/path/file"))
+ (should
+ (string-equal
+ (expand-file-name "/method:host:/path/../file") "/method:host:/file"))
+ (should
+ (string-equal
+ (expand-file-name "/method:host:/path/.") "/method:host:/path"))
+ (should
+ (string-equal
+ (expand-file-name "/method:host:/path/..") "/method:host:/"))
+ (should
+ (string-equal
+ (expand-file-name "." "/method:host:/path/") "/method:host:/path"))
+ (should
+ (string-equal
+ (expand-file-name "" "/method:host:/path/") "/method:host:/path"))
+ ;; Quoting local part.
+ (should
+ (string-equal
+ (expand-file-name "/method:host:/:/path/./file")
+ "/method:host:/:/path/file"))
+ (should
+ (string-equal
+ (expand-file-name "/method:host:/:/path/../file") "/method:host:/:/file"))
+ (should
+ (string-equal
+ (expand-file-name "/method:host:/:/~/path/./file")
+ "/method:host:/:/~/path/file"))))
+
+;; The following test is inspired by Bug#26911 and Bug#34834. They
+;; were bugs in `expand-file-name'.
(ert-deftest tramp-test05-expand-file-name-relative ()
"Check `expand-file-name'."
- ;; Mark as failed until bug has been fixed.
- :expected-result :failed
(skip-unless (tramp--test-enabled))
- ;; These are the methods the test doesn't fail.
- (when (or (tramp--test-adb-p) (tramp--test-gvfs-p)
- (tramp-smb-file-name-p tramp-test-temporary-file-directory))
- (setf (ert-test-expected-result-type
- (ert-get-test 'tramp-test05-expand-file-name-relative))
- :passed))
+ ;; Methods with a share do not expand "/path/..".
+ (skip-unless (not (tramp--test-share-p)))
+ ;; The bugs are fixed in Emacs 28.1.
+ (skip-unless (tramp--test-emacs28-p))
(should
(string-equal
(let ((default-directory
(concat
- (file-remote-p tramp-test-temporary-file-directory) "/path")))
+ (file-remote-p ert-remote-temporary-file-directory) "/path")))
(expand-file-name ".." "./"))
- (concat (file-remote-p tramp-test-temporary-file-directory) "/"))))
+ (concat (file-remote-p ert-remote-temporary-file-directory) "/"))))
+
+(ert-deftest tramp-test05-expand-file-name-top ()
+ "Check `expand-file-name'."
+ (skip-unless (tramp--test-enabled))
+ (skip-unless (not (tramp--test-ange-ftp-p)))
+
+ (let ((dir (concat (file-remote-p ert-remote-temporary-file-directory) "/")))
+ (dolist (local '("." ".."))
+ (should (string-equal (expand-file-name local dir) dir))
+ (should (string-equal (expand-file-name (concat dir local)) dir)))))
(ert-deftest tramp-test06-directory-file-name ()
"Check `directory-file-name'.
This checks also `file-name-as-directory', `file-name-directory',
`file-name-nondirectory' and `unhandled-file-name-directory'."
- (should
- (string-equal
- (directory-file-name "/method:host:/path/to/file")
- "/method:host:/path/to/file"))
- (should
- (string-equal
- (directory-file-name "/method:host:/path/to/file/")
- "/method:host:/path/to/file"))
- (should
- (string-equal
- (file-name-as-directory "/method:host:/path/to/file")
- "/method:host:/path/to/file/"))
- (should
- (string-equal
- (file-name-as-directory "/method:host:/path/to/file/")
- "/method:host:/path/to/file/"))
- (should
- (string-equal
- (file-name-directory "/method:host:/path/to/file")
- "/method:host:/path/to/"))
- (should
- (string-equal
- (file-name-directory "/method:host:/path/to/file/")
- "/method:host:/path/to/file/"))
- (should
- (string-equal (file-name-nondirectory "/method:host:/path/to/file") "file"))
- (should
- (string-equal (file-name-nondirectory "/method:host:/path/to/file/") ""))
- (should-not
- (unhandled-file-name-directory "/method:host:/path/to/file"))
+ (skip-unless (eq tramp-syntax 'default))
+
+ ;; Suppress method name check.
+ (let ((tramp-methods (cons '("method") tramp-methods)))
+ (should
+ (string-equal
+ (directory-file-name "/method:host:/path/to/file")
+ "/method:host:/path/to/file"))
+ (should
+ (string-equal
+ (directory-file-name "/method:host:/path/to/file/")
+ "/method:host:/path/to/file"))
+ (should
+ (string-equal
+ (directory-file-name "/method:host:/path/to/file//")
+ "/method:host:/path/to/file"))
+ (should
+ (string-equal
+ (file-name-as-directory "/method:host:/path/to/file")
+ "/method:host:/path/to/file/"))
+ (should
+ (string-equal
+ (file-name-as-directory "/method:host:/path/to/file/")
+ "/method:host:/path/to/file/"))
+ (should
+ (string-equal
+ (file-name-directory "/method:host:/path/to/file")
+ "/method:host:/path/to/"))
+ (should
+ (string-equal
+ (file-name-directory "/method:host:/path/to/file/")
+ "/method:host:/path/to/file/"))
+ (should
+ (string-equal (file-name-directory "/method:host:file") "/method:host:"))
+ (should
+ (string-equal
+ (file-name-directory "/method:host:path/") "/method:host:path/"))
+ (should
+ (string-equal
+ (file-name-directory "/method:host:path/to") "/method:host:path/"))
+ (should
+ (string-equal
+ (file-name-nondirectory "/method:host:/path/to/file") "file"))
+ (should
+ (string-equal (file-name-nondirectory "/method:host:/path/to/file/") ""))
+ (should-not
+ (unhandled-file-name-directory "/method:host:/path/to/file")))
;; Bug#10085.
(when (tramp--test-enabled) ;; Packages like tramp-gvfs.el might be disabled.
- (dolist (n-e '(nil t))
+ (dolist (non-essential '(nil t))
;; We must clear `tramp-default-method'. On hydra, it is "ftp",
;; which ruins the tests.
- (let ((non-essential n-e)
- tramp-default-method)
+ (let ((tramp-default-method
+ (file-remote-p ert-remote-temporary-file-directory 'method))
+ (host (file-remote-p ert-remote-temporary-file-directory 'host)))
(dolist
(file
- `(,(format
- "/%s::"
- (file-remote-p tramp-test-temporary-file-directory 'method))
+ `(,(format "/%s::" tramp-default-method)
,(format
- "/-:%s:"
- (file-remote-p tramp-test-temporary-file-directory 'host))))
+ "/-:%s:"
+ (if (string-match-p tramp-ipv6-regexp host)
+ (concat
+ tramp-prefix-ipv6-format host tramp-postfix-ipv6-format)
+ host))))
(should (string-equal (directory-file-name file) file))
(should
(string-equal
(file-name-as-directory file)
- (if (tramp-completion-mode-p)
- file (concat file "./"))))
+ (if non-essential
+ file (concat file (if (tramp--test-ange-ftp-p) "/" "./")))))
(should (string-equal (file-name-directory file) file))
(should (string-equal (file-name-nondirectory file) "")))))))
+(ert-deftest tramp-test07-abbreviate-file-name ()
+ "Check that Tramp abbreviates file names correctly."
+ (skip-unless (tramp--test-enabled))
+ (skip-unless (not (tramp--test-ange-ftp-p)))
+ ;; `abbreviate-file-name' is supported since Emacs 29.1.
+ (skip-unless (tramp--test-emacs29-p))
+
+ ;; We must refill the cache. `file-truename' does it.
+ (file-truename ert-remote-temporary-file-directory)
+ (let* ((remote-host (file-remote-p ert-remote-temporary-file-directory))
+ (remote-host-nohop
+ (tramp-make-tramp-file-name (tramp-dissect-file-name remote-host)))
+ ;; Not all methods can expand "~".
+ (home-dir (ignore-errors (expand-file-name (concat remote-host "~"))))
+ home-dir-nohop)
+ (skip-unless home-dir)
+
+ ;; Check home-dir abbreviation.
+ (unless (string-suffix-p "~" home-dir)
+ (should (equal (abbreviate-file-name (concat home-dir "/foo/bar"))
+ (concat remote-host-nohop "~/foo/bar")))
+ (should (equal (abbreviate-file-name
+ (concat remote-host "/nowhere/special"))
+ (concat remote-host-nohop "/nowhere/special"))))
+
+ ;; Check `directory-abbrev-alist' abbreviation.
+ (let ((directory-abbrev-alist
+ `((,(tramp-compat-rx bos (literal home-dir) "/foo")
+ . ,(concat home-dir "/f"))
+ (,(tramp-compat-rx bos (literal remote-host) "/nowhere")
+ . ,(concat remote-host "/nw")))))
+ (should (equal (abbreviate-file-name (concat home-dir "/foo/bar"))
+ (concat remote-host-nohop "~/f/bar")))
+ (should (equal (abbreviate-file-name
+ (concat remote-host "/nowhere/special"))
+ (concat remote-host-nohop "/nw/special"))))
+
+ ;; Check that home-dir abbreviation doesn't occur when home-dir is just "/".
+ (setq home-dir (concat remote-host "/")
+ home-dir-nohop
+ (tramp-make-tramp-file-name (tramp-dissect-file-name home-dir)))
+ ;; The remote home directory is kept in the connection property "~".
+ ;; We fake this setting.
+ (tramp-set-connection-property tramp-test-vec "~" (file-local-name home-dir))
+ (should (equal (abbreviate-file-name (concat home-dir "foo/bar"))
+ (concat home-dir-nohop "foo/bar")))
+ (tramp-flush-connection-property tramp-test-vec "~")))
+
(ert-deftest tramp-test07-file-exists-p ()
"Check `file-exist-p', `write-region' and `delete-file'."
(skip-unless (tramp--test-enabled))
- (dolist (quoted (if tramp--test-expensive-test '(nil t) '(nil)))
+ (dolist (quoted (if (tramp--test-expensive-test-p) '(nil t) '(nil)))
(let ((tmp-name (tramp--test-make-temp-name nil quoted)))
(should-not (file-exists-p tmp-name))
(write-region "foo" nil tmp-name)
(should (file-exists-p tmp-name))
(delete-file tmp-name)
- (should-not (file-exists-p tmp-name)))))
+ (should-not (file-exists-p tmp-name))
+
+ ;; Trashing files doesn't work when `system-move-file-to-trash'
+ ;; is defined (on MS-Windows and macOS), and for encrypted
+ ;; remote files.
+ (unless (or (fboundp 'system-move-file-to-trash) (tramp--test-crypt-p))
+ (let ((trash-directory (tramp--test-make-temp-name 'local quoted))
+ (delete-by-moving-to-trash t))
+ (make-directory trash-directory)
+ (should-not (file-exists-p tmp-name))
+ (write-region "foo" nil tmp-name)
+ (should (file-exists-p tmp-name))
+ (delete-file tmp-name 'trash)
+ (should-not (file-exists-p tmp-name))
+ (should
+ (or (file-exists-p
+ (expand-file-name
+ (file-name-nondirectory tmp-name) trash-directory))
+ ;; Gdrive.
+ (file-symlink-p
+ (expand-file-name
+ (file-name-nondirectory tmp-name) trash-directory))))
+ (delete-directory trash-directory 'recursive)
+ (should-not (file-exists-p trash-directory)))))))
(ert-deftest tramp-test08-file-local-copy ()
"Check `file-local-copy'."
(skip-unless (tramp--test-enabled))
- (dolist (quoted (if tramp--test-expensive-test '(nil t) '(nil)))
+ (dolist (quoted (if (tramp--test-expensive-test-p) '(nil t) '(nil)))
(let ((tmp-name1 (tramp--test-make-temp-name nil quoted))
tmp-name2)
(unwind-protect
@@ -1757,7 +2366,7 @@ This checks also `file-name-as-directory', `file-name-directory',
(insert-file-contents tmp-name2)
(should (string-equal (buffer-string) "foo")))
;; Check also that a file transfer with compression works.
- (let ((default-directory tramp-test-temporary-file-directory)
+ (let ((default-directory ert-remote-temporary-file-directory)
(tramp-copy-size-limit 4)
(tramp-inline-compress-start-size 2))
(delete-file tmp-name2)
@@ -1767,7 +2376,7 @@ This checks also `file-name-as-directory', `file-name-directory',
(delete-file tmp-name2)
(should-error
(setq tmp-name2 (file-local-copy tmp-name1))
- :type tramp-file-missing))
+ :type 'file-missing))
;; Cleanup.
(ignore-errors
@@ -1778,26 +2387,35 @@ This checks also `file-name-as-directory', `file-name-directory',
"Check `insert-file-contents'."
(skip-unless (tramp--test-enabled))
- (dolist (quoted (if tramp--test-expensive-test '(nil t) '(nil)))
+ (dolist (quoted (if (tramp--test-expensive-test-p) '(nil t) '(nil)))
(let ((tmp-name (tramp--test-make-temp-name nil quoted)))
(unwind-protect
(with-temp-buffer
(write-region "foo" nil tmp-name)
- (insert-file-contents tmp-name)
- (should (string-equal (buffer-string) "foo"))
- (insert-file-contents tmp-name)
- (should (string-equal (buffer-string) "foofoo"))
+ (let ((point (point)))
+ (insert-file-contents tmp-name)
+ (should (string-equal (buffer-string) "foo"))
+ (should (= point (point))))
+ (goto-char (1+ (point)))
+ (let ((point (point)))
+ (insert-file-contents tmp-name)
+ (should (string-equal (buffer-string) "ffoooo"))
+ (should (= point (point))))
;; Insert partly.
- (insert-file-contents tmp-name nil 1 3)
- (should (string-equal (buffer-string) "oofoofoo"))
+ (let ((point (point)))
+ (insert-file-contents tmp-name nil 1 3)
+ (should (string-equal (buffer-string) "foofoooo"))
+ (should (= point (point))))
;; Replace.
- (insert-file-contents tmp-name nil nil nil 'replace)
- (should (string-equal (buffer-string) "foo"))
+ (let ((point (point)))
+ (insert-file-contents tmp-name nil nil nil 'replace)
+ (should (string-equal (buffer-string) "foo"))
+ (should (= point (point))))
;; Error case.
(delete-file tmp-name)
(should-error
(insert-file-contents tmp-name)
- :type tramp-file-missing))
+ :type 'file-missing))
;; Cleanup.
(ignore-errors (delete-file tmp-name))))))
@@ -1806,8 +2424,9 @@ This checks also `file-name-as-directory', `file-name-directory',
"Check `write-region'."
(skip-unless (tramp--test-enabled))
- (dolist (quoted (if tramp--test-expensive-test '(nil t) '(nil)))
- (let ((tmp-name (tramp--test-make-temp-name nil quoted)))
+ (dolist (quoted (if (tramp--test-expensive-test-p) '(nil t) '(nil)))
+ (let ((tmp-name (tramp--test-make-temp-name nil quoted))
+ (inhibit-message t))
(unwind-protect
(progn
;; Write buffer. Use absolute and relative file name.
@@ -1831,18 +2450,26 @@ This checks also `file-name-as-directory', `file-name-directory',
(should (string-equal (buffer-string) "foo")))
;; Append.
- (with-temp-buffer
- (insert "bla")
- (write-region nil nil tmp-name 'append))
- (with-temp-buffer
- (insert-file-contents tmp-name)
- (should (string-equal (buffer-string) "foobla")))
- (with-temp-buffer
- (insert "baz")
- (write-region nil nil tmp-name 3))
- (with-temp-buffer
- (insert-file-contents tmp-name)
- (should (string-equal (buffer-string) "foobaz")))
+ (unless (tramp--test-ange-ftp-p)
+ (with-temp-buffer
+ (insert "bla")
+ (write-region nil nil tmp-name 'append))
+ (with-temp-buffer
+ (insert-file-contents tmp-name)
+ (should (string-equal (buffer-string) "foobla")))
+ (with-temp-buffer
+ (insert "baz")
+ (write-region nil nil tmp-name 3))
+ (with-temp-buffer
+ (insert-file-contents tmp-name)
+ (should (string-equal (buffer-string) "foobaz")))
+ (delete-file tmp-name)
+ (with-temp-buffer
+ (insert "foo")
+ (write-region nil nil tmp-name 'append))
+ (with-temp-buffer
+ (insert-file-contents tmp-name)
+ (should (string-equal (buffer-string) "foo"))))
;; Write string.
(write-region "foo" nil tmp-name)
@@ -1850,6 +2477,19 @@ This checks also `file-name-as-directory', `file-name-directory',
(insert-file-contents tmp-name)
(should (string-equal (buffer-string) "foo")))
+ ;; Write empty string. Used for creation of temporary files.
+ ;; Since Emacs 27.1.
+ (when (fboundp 'make-empty-file)
+ (with-no-warnings
+ (should-error
+ (make-empty-file tmp-name)
+ :type 'file-already-exists)
+ (delete-file tmp-name)
+ (make-empty-file tmp-name)
+ (with-temp-buffer
+ (insert-file-contents tmp-name)
+ (should (string-equal (buffer-string) "")))))
+
;; Write partly.
(with-temp-buffer
(insert "123456789")
@@ -1858,254 +2498,394 @@ This checks also `file-name-as-directory', `file-name-directory',
(insert-file-contents tmp-name)
(should (string-equal (buffer-string) "34")))
+ ;; Check message.
+ (let (inhibit-message)
+ (dolist (noninteractive (unless (tramp--test-ange-ftp-p) '(nil t)))
+ (dolist (visit '(nil t "string" no-message))
+ (ert-with-message-capture tramp--test-messages
+ (write-region "foo" nil tmp-name nil visit)
+ ;; We must check the last line. There could be
+ ;; other messages from the progress reporter.
+ (should
+ (string-match-p
+ (if (and (null noninteractive)
+ (or (eq visit t) (null visit) (stringp visit)))
+ (tramp-compat-rx
+ bol "Wrote " (literal tmp-name) "\n" eos)
+ (rx bos))
+ tramp--test-messages))))))
+
+ ;; We do not test lockname here. See
+ ;; `tramp-test39-make-lock-file-name'.
+
;; Do not overwrite if excluded.
- (cl-letf (((symbol-function 'y-or-n-p) (lambda (_prompt) t)))
+ (cl-letf (((symbol-function #'y-or-n-p) #'tramp--test-always)
+ ;; Ange-FTP.
+ ((symbol-function 'yes-or-no-p) #'tramp--test-always))
(write-region "foo" nil tmp-name nil nil nil 'mustbenew))
- ;; `mustbenew' is passed to Tramp since Emacs 26.1.
- (when (tramp--test-emacs26-p)
- (should-error
- (cl-letf (((symbol-function 'y-or-n-p) 'ignore))
- (write-region "foo" nil tmp-name nil nil nil 'mustbenew))
- :type 'file-already-exists)
- (should-error
- (write-region "foo" nil tmp-name nil nil nil 'excl)
- :type 'file-already-exists)))
+ (should-error
+ (cl-letf (((symbol-function #'y-or-n-p) #'ignore)
+ ;; Ange-FTP.
+ ((symbol-function #'yes-or-no-p) #'ignore))
+ (write-region "foo" nil tmp-name nil nil nil 'mustbenew))
+ :type 'file-already-exists)
+ (should-error
+ (write-region "foo" nil tmp-name nil nil nil 'excl)
+ :type 'file-already-exists))
;; Cleanup.
(ignore-errors (delete-file tmp-name))))))
-(ert-deftest tramp-test11-copy-file ()
- "Check `copy-file'."
+;; The following test is inspired by Bug#35497.
+(ert-deftest tramp-test10-write-region-file-precious-flag ()
+ "Check that `file-precious-flag' is respected with Tramp in use."
(skip-unless (tramp--test-enabled))
+ (skip-unless (tramp--test-sh-p))
+ ;; The bug is fixed in Emacs 27.1.
+ (skip-unless (tramp--test-emacs27-p))
- ;; TODO: The quoted case does not work.
- ;;(dolist (quoted (if tramp--test-expensive-test '(nil t) '(nil)))
- (let (quoted)
- (let ((tmp-name1 (tramp--test-make-temp-name nil quoted))
- (tmp-name2 (tramp--test-make-temp-name nil quoted))
- (tmp-name3 (tramp--test-make-temp-name nil quoted))
- (tmp-name4 (tramp--test-make-temp-name 'local quoted))
- (tmp-name5 (tramp--test-make-temp-name 'local quoted)))
+ (let* ((tmp-name (tramp--test-make-temp-name))
+ (inhibit-message t)
+ written-files
+ (advice (lambda (_start _end filename &rest _r)
+ (push filename written-files))))
- ;; Copy on remote side.
- (unwind-protect
- (progn
- (write-region "foo" nil tmp-name1)
- (copy-file tmp-name1 tmp-name2)
- (should (file-exists-p tmp-name2))
- (with-temp-buffer
- (insert-file-contents tmp-name2)
- (should (string-equal (buffer-string) "foo")))
- (should-error
- (copy-file tmp-name1 tmp-name2)
- :type 'file-already-exists)
- (copy-file tmp-name1 tmp-name2 'ok)
- (make-directory tmp-name3)
- ;; This has been changed in Emacs 26.1.
- (when (tramp--test-emacs26-p)
- (should-error
- (copy-file tmp-name1 tmp-name3)
- :type 'file-already-exists))
- (copy-file tmp-name1 (file-name-as-directory tmp-name3))
- (should
- (file-exists-p
- (expand-file-name (file-name-nondirectory tmp-name1) tmp-name3))))
+ (unwind-protect
+ (with-current-buffer (find-file-noselect tmp-name)
+ ;; Write initial contents. Adapt `visited-file-modtime'
+ ;; in order to suppress confirmation.
+ (insert "foo")
+ (write-region nil nil tmp-name)
+ (set-visited-file-modtime)
+ ;; Run the test.
+ (advice-add 'write-region :before advice)
+ (setq-local file-precious-flag t)
+ (setq-local backup-inhibited t)
+ (insert "bar")
+ (should (buffer-modified-p))
+ (should (null (save-buffer)))
+ (should (not (buffer-modified-p)))
+ (should-not (cl-member tmp-name written-files :test #'string=)))
- ;; Cleanup.
- (ignore-errors (delete-file tmp-name1))
- (ignore-errors (delete-file tmp-name2))
- (ignore-errors (delete-directory tmp-name3 'recursive)))
+ ;; Cleanup.
+ (ignore-errors (advice-remove 'write-region advice))
+ (ignore-errors (delete-file tmp-name)))))
- ;; Copy from remote side to local side.
- (unwind-protect
- (progn
- (write-region "foo" nil tmp-name1)
- (copy-file tmp-name1 tmp-name4)
- (should (file-exists-p tmp-name4))
- (with-temp-buffer
- (insert-file-contents tmp-name4)
- (should (string-equal (buffer-string) "foo")))
- (should-error
- (copy-file tmp-name1 tmp-name4)
- :type 'file-already-exists)
- (copy-file tmp-name1 tmp-name4 'ok)
- (make-directory tmp-name5)
- ;; This has been changed in Emacs 26.1.
- (when (tramp--test-emacs26-p)
- (should-error
- (copy-file tmp-name1 tmp-name5)
- :type 'file-already-exists))
- (copy-file tmp-name1 (file-name-as-directory tmp-name5))
- (should
- (file-exists-p
- (expand-file-name (file-name-nondirectory tmp-name1) tmp-name5))))
+;; The following test is inspired by Bug#55166.
+(ert-deftest tramp-test10-write-region-other-file-name-handler ()
+ "Check that another file name handler in VISIT is acknowledged."
+ (skip-unless (tramp--test-enabled))
+ (skip-unless (not (tramp--test-ange-ftp-p)))
+ (skip-unless (executable-find "gzip"))
+ ;; The function was introduced in Emacs 28.1.
+ (skip-unless (boundp 'tar-goto-file))
+
+ (let* ((default-directory ert-remote-temporary-file-directory)
+ (archive (ert-resource-file "foo.tar.gz"))
+ (tmp-file (expand-file-name (file-name-nondirectory archive)))
+ (require-final-newline t)
+ (inhibit-message t)
+ (backup-inhibited t)
+ create-lockfiles buffer1 buffer2)
+ (unwind-protect
+ (progn
+ (copy-file archive tmp-file 'ok)
+ ;; Read archive. Check contents of foo.txt, and modify it. Save.
+ (with-current-buffer (setq buffer1 (find-file-noselect tmp-file))
+ ;; The function was introduced in Emacs 28.1.
+ (with-no-warnings (should (tar-goto-file "foo.txt")))
+ (save-current-buffer
+ (setq buffer2 (tar-extract))
+ (should (string-equal (buffer-string) "foo\n"))
+ (goto-char (point-max))
+ (insert "bar")
+ (should (buffer-modified-p))
+ (should (null (save-buffer)))
+ (should-not (buffer-modified-p)))
+ (should (buffer-modified-p))
+ (should (null (save-buffer)))
+ (should-not (buffer-modified-p)))
+
+ (kill-buffer buffer1)
+ (kill-buffer buffer2)
+ ;; Read archive. Check contents of modified foo.txt.
+ (with-current-buffer (setq buffer1 (find-file-noselect tmp-file))
+ ;; The function was introduced in Emacs 28.1.
+ (with-no-warnings (should (tar-goto-file "foo.txt")))
+ (save-current-buffer
+ (setq buffer2 (tar-extract))
+ (should (string-equal (buffer-string) "foo\nbar\n")))))
- ;; Cleanup.
- (ignore-errors (delete-file tmp-name1))
- (ignore-errors (delete-file tmp-name4))
- (ignore-errors (delete-directory tmp-name5 'recursive)))
+ ;; Cleanup.
+ (ignore-errors (kill-buffer buffer1))
+ (ignore-errors (kill-buffer buffer2))
+ (ignore-errors (delete-file tmp-file)))))
- ;; Copy from local side to remote side.
- (unwind-protect
- (progn
- (write-region "foo" nil tmp-name4 nil 'nomessage)
- (copy-file tmp-name4 tmp-name1)
- (should (file-exists-p tmp-name1))
- (with-temp-buffer
- (insert-file-contents tmp-name1)
- (should (string-equal (buffer-string) "foo")))
- (should-error
- (copy-file tmp-name4 tmp-name1)
- :type 'file-already-exists)
- (copy-file tmp-name4 tmp-name1 'ok)
- (make-directory tmp-name3)
- ;; This has been changed in Emacs 26.1.
- (when (tramp--test-emacs26-p)
- (should-error
- (copy-file tmp-name4 tmp-name3)
- :type 'file-already-exists))
- (copy-file tmp-name4 (file-name-as-directory tmp-name3))
- (should
- (file-exists-p
- (expand-file-name (file-name-nondirectory tmp-name4) tmp-name3))))
+(ert-deftest tramp-test11-copy-file ()
+ "Check `copy-file'."
+ (skip-unless (tramp--test-enabled))
- ;; Cleanup.
- (ignore-errors (delete-file tmp-name1))
- (ignore-errors (delete-file tmp-name4))
- (ignore-errors (delete-directory tmp-name3 'recursive))))))
+ ;; `filename-non-special' has been fixed in Emacs 27.1, see Bug#29579.
+ (dolist (quoted
+ (if (and (tramp--test-expensive-test-p) (tramp--test-emacs27-p))
+ '(nil t) '(nil)))
+ (let ((tmp-name1 (tramp--test-make-temp-name nil quoted))
+ (tmp-name2 (tramp--test-make-temp-name nil quoted))
+ (tmp-name3 (tramp--test-make-temp-name 'local quoted)))
+ (dolist (source-target
+ `(;; Copy on remote side.
+ (,tmp-name1 . ,tmp-name2)
+ ;; Copy from remote side to local side.
+ (,tmp-name1 . ,tmp-name3)
+ ;; Copy from local side to remote side.
+ (,tmp-name3 . ,tmp-name1)))
+ (let ((source (car source-target))
+ (target (cdr source-target)))
+
+ ;; Copy simple file.
+ (unwind-protect
+ (progn
+ (should-error
+ (copy-file source target)
+ :type 'file-missing)
+ (write-region "foo" nil source)
+ (should (file-exists-p source))
+ (copy-file source target)
+ (should (file-exists-p target))
+ (with-temp-buffer
+ (insert-file-contents target)
+ (should (string-equal (buffer-string) "foo")))
+ (when (tramp--test-expensive-test-p)
+ (should-error
+ (copy-file source target)
+ :type 'file-already-exists))
+ (copy-file source target 'ok))
+
+ ;; Cleanup.
+ (ignore-errors (delete-file source))
+ (ignore-errors (delete-file target)))
+
+ ;; Copy file to directory.
+ (unwind-protect
+ ;; This doesn't work on FTP.
+ (unless (tramp--test-ange-ftp-p)
+ (write-region "foo" nil source)
+ (should (file-exists-p source))
+ (make-directory target)
+ (should (file-directory-p target))
+ (when (tramp--test-expensive-test-p)
+ (should-error
+ (copy-file source target)
+ :type 'file-already-exists)
+ (should-error
+ (copy-file source target 'ok)
+ :type 'file-error))
+ (copy-file source (file-name-as-directory target))
+ (should
+ (file-exists-p
+ (expand-file-name (file-name-nondirectory source) target))))
+
+ ;; Cleanup.
+ (ignore-errors (delete-file source))
+ (ignore-errors (delete-directory target 'recursive)))
+
+ ;; Copy directory to existing directory.
+ (unwind-protect
+ ;; This doesn't work on FTP.
+ (unless (tramp--test-ange-ftp-p)
+ (make-directory source)
+ (should (file-directory-p source))
+ (write-region "foo" nil (expand-file-name "foo" source))
+ (should (file-exists-p (expand-file-name "foo" source)))
+ (make-directory target)
+ (should (file-directory-p target))
+ ;; Directory `target' exists already, so we must use
+ ;; `file-name-as-directory'.
+ (copy-file source (file-name-as-directory target))
+ (should
+ (file-exists-p
+ (expand-file-name
+ (concat (file-name-nondirectory source) "/foo") target))))
+
+ ;; Cleanup.
+ (ignore-errors (delete-directory source 'recursive))
+ (ignore-errors (delete-directory target 'recursive)))
+
+ ;; Copy directory/file to non-existing directory.
+ (unwind-protect
+ ;; This doesn't work on FTP.
+ (unless (tramp--test-ange-ftp-p)
+ (make-directory source)
+ (should (file-directory-p source))
+ (write-region "foo" nil (expand-file-name "foo" source))
+ (should (file-exists-p (expand-file-name "foo" source)))
+ (make-directory target)
+ (should (file-directory-p target))
+ (copy-file
+ source
+ (expand-file-name (file-name-nondirectory source) target))
+ (should
+ (file-exists-p
+ (expand-file-name
+ (concat (file-name-nondirectory source) "/foo") target))))
+
+ ;; Cleanup.
+ (ignore-errors (delete-directory source 'recursive))
+ (ignore-errors (delete-directory target 'recursive))))))))
(ert-deftest tramp-test12-rename-file ()
"Check `rename-file'."
(skip-unless (tramp--test-enabled))
- ;; TODO: The quoted case does not work.
- ;;(dolist (quoted (if tramp--test-expensive-test '(nil t) '(nil)))
- (let (quoted)
+ ;; `filename-non-special' has been fixed in Emacs 27.1, see Bug#29579.
+ (dolist (quoted
+ (if (and (tramp--test-expensive-test-p) (tramp--test-emacs27-p))
+ '(nil t) '(nil)))
(let ((tmp-name1 (tramp--test-make-temp-name nil quoted))
(tmp-name2 (tramp--test-make-temp-name nil quoted))
- (tmp-name3 (tramp--test-make-temp-name nil quoted))
- (tmp-name4 (tramp--test-make-temp-name 'local quoted))
- (tmp-name5 (tramp--test-make-temp-name 'local quoted)))
-
- ;; Rename on remote side.
- (unwind-protect
- (progn
- (write-region "foo" nil tmp-name1)
- (rename-file tmp-name1 tmp-name2)
- (should-not (file-exists-p tmp-name1))
- (should (file-exists-p tmp-name2))
- (with-temp-buffer
- (insert-file-contents tmp-name2)
- (should (string-equal (buffer-string) "foo")))
- (write-region "foo" nil tmp-name1)
- (should-error
- (rename-file tmp-name1 tmp-name2)
- :type 'file-already-exists)
- (rename-file tmp-name1 tmp-name2 'ok)
- (should-not (file-exists-p tmp-name1))
- (write-region "foo" nil tmp-name1)
- (make-directory tmp-name3)
- ;; This has been changed in Emacs 26.1.
- (when (tramp--test-emacs26-p)
- (should-error
- (rename-file tmp-name1 tmp-name3)
- :type 'file-already-exists))
- (rename-file tmp-name1 (file-name-as-directory tmp-name3))
- (should-not (file-exists-p tmp-name1))
- (should
- (file-exists-p
- (expand-file-name (file-name-nondirectory tmp-name1) tmp-name3))))
-
- ;; Cleanup.
- (ignore-errors (delete-file tmp-name1))
- (ignore-errors (delete-file tmp-name2))
- (ignore-errors (delete-directory tmp-name3 'recursive)))
-
- ;; Rename from remote side to local side.
- (unwind-protect
- (progn
- (write-region "foo" nil tmp-name1)
- (rename-file tmp-name1 tmp-name4)
- (should-not (file-exists-p tmp-name1))
- (should (file-exists-p tmp-name4))
- (with-temp-buffer
- (insert-file-contents tmp-name4)
- (should (string-equal (buffer-string) "foo")))
- (write-region "foo" nil tmp-name1)
- (should-error
- (rename-file tmp-name1 tmp-name4)
- :type 'file-already-exists)
- (rename-file tmp-name1 tmp-name4 'ok)
- (should-not (file-exists-p tmp-name1))
- (write-region "foo" nil tmp-name1)
- (make-directory tmp-name5)
- ;; This has been changed in Emacs 26.1.
- (when (tramp--test-emacs26-p)
- (should-error
- (rename-file tmp-name1 tmp-name5)
- :type 'file-already-exists))
- (rename-file tmp-name1 (file-name-as-directory tmp-name5))
- (should-not (file-exists-p tmp-name1))
- (should
- (file-exists-p
- (expand-file-name (file-name-nondirectory tmp-name1) tmp-name5))))
-
- ;; Cleanup.
- (ignore-errors (delete-file tmp-name1))
- (ignore-errors (delete-file tmp-name4))
- (ignore-errors (delete-directory tmp-name5 'recursive)))
-
- ;; Rename from local side to remote side.
- (unwind-protect
- (progn
- (write-region "foo" nil tmp-name4 nil 'nomessage)
- (rename-file tmp-name4 tmp-name1)
- (should-not (file-exists-p tmp-name4))
- (should (file-exists-p tmp-name1))
- (with-temp-buffer
- (insert-file-contents tmp-name1)
- (should (string-equal (buffer-string) "foo")))
- (write-region "foo" nil tmp-name4 nil 'nomessage)
- (should-error
- (rename-file tmp-name4 tmp-name1)
- :type 'file-already-exists)
- (rename-file tmp-name4 tmp-name1 'ok)
- (should-not (file-exists-p tmp-name4))
- (write-region "foo" nil tmp-name4 nil 'nomessage)
- (make-directory tmp-name3)
- ;; This has been changed in Emacs 26.1.
- (when (tramp--test-emacs26-p)
- (should-error
- (rename-file tmp-name4 tmp-name3)
- :type 'file-already-exists))
- (rename-file tmp-name4 (file-name-as-directory tmp-name3))
- (should-not (file-exists-p tmp-name4))
- (should
- (file-exists-p
- (expand-file-name (file-name-nondirectory tmp-name4) tmp-name3))))
+ (tmp-name3 (tramp--test-make-temp-name 'local quoted)))
+ (dolist (source-target
+ `(;; Rename on remote side.
+ (,tmp-name1 . ,tmp-name2)
+ ;; Rename from remote side to local side.
+ (,tmp-name1 . ,tmp-name3)
+ ;; Rename from local side to remote side.
+ (,tmp-name3 . ,tmp-name1)))
+ (let ((source (car source-target))
+ (target (cdr source-target)))
+
+ ;; Rename simple file.
+ (unwind-protect
+ (progn
+ (should-error
+ (rename-file source target)
+ :type 'file-missing)
+ (write-region "foo" nil source)
+ (should (file-exists-p source))
+ (rename-file source target)
+ (should-not (file-exists-p source))
+ (should (file-exists-p target))
+ (with-temp-buffer
+ (insert-file-contents target)
+ (should (string-equal (buffer-string) "foo")))
+ (write-region "foo" nil source)
+ (should (file-exists-p source))
+ (when (tramp--test-expensive-test-p)
+ (should-error
+ (rename-file source target)
+ :type 'file-already-exists))
+ (rename-file source target 'ok)
+ (should-not (file-exists-p source)))
+
+ ;; Cleanup.
+ (ignore-errors (delete-file source))
+ (ignore-errors (delete-file target)))
+
+ ;; Rename file to directory.
+ (unwind-protect
+ (progn
+ (write-region "foo" nil source)
+ (should (file-exists-p source))
+ (make-directory target)
+ (should (file-directory-p target))
+ (when (tramp--test-expensive-test-p)
+ (should-error
+ (rename-file source target)
+ :type 'file-already-exists)
+ (should-error
+ (rename-file source target 'ok)
+ :type 'file-error))
+ (rename-file source (file-name-as-directory target))
+ (should-not (file-exists-p source))
+ (should
+ (file-exists-p
+ (expand-file-name (file-name-nondirectory source) target))))
+
+ ;; Cleanup.
+ (ignore-errors (delete-file source))
+ (ignore-errors (delete-directory target 'recursive)))
+
+ ;; Rename directory to existing directory.
+ (unwind-protect
+ ;; This doesn't work on FTP.
+ (unless (tramp--test-ange-ftp-p)
+ (make-directory source)
+ (should (file-directory-p source))
+ (write-region "foo" nil (expand-file-name "foo" source))
+ (should (file-exists-p (expand-file-name "foo" source)))
+ (make-directory target)
+ (should (file-directory-p target))
+ ;; Directory `target' exists already, so we must use
+ ;; `file-name-as-directory'.
+ (rename-file source (file-name-as-directory target))
+ (should-not (file-exists-p source))
+ (should
+ (file-exists-p
+ (expand-file-name
+ (concat (file-name-nondirectory source) "/foo") target))))
+
+ ;; Cleanup.
+ (ignore-errors (delete-directory source 'recursive))
+ (ignore-errors (delete-directory target 'recursive)))
+
+ ;; Rename directory/file to non-existing directory.
+ (unwind-protect
+ ;; This doesn't work on FTP.
+ (unless (tramp--test-ange-ftp-p)
+ (make-directory source)
+ (should (file-directory-p source))
+ (write-region "foo" nil (expand-file-name "foo" source))
+ (should (file-exists-p (expand-file-name "foo" source)))
+ (make-directory target)
+ (should (file-directory-p target))
+ (rename-file
+ source
+ (expand-file-name (file-name-nondirectory source) target))
+ (should-not (file-exists-p source))
+ (should
+ (file-exists-p
+ (expand-file-name
+ (concat (file-name-nondirectory source) "/foo") target))))
- ;; Cleanup.
- (ignore-errors (delete-file tmp-name1))
- (ignore-errors (delete-file tmp-name4))
- (ignore-errors (delete-directory tmp-name3 'recursive))))))
+ ;; Cleanup.
+ (ignore-errors (delete-directory source 'recursive))
+ (ignore-errors (delete-directory target 'recursive))))))))
(ert-deftest tramp-test13-make-directory ()
"Check `make-directory'.
This tests also `file-directory-p' and `file-accessible-directory-p'."
(skip-unless (tramp--test-enabled))
- (dolist (quoted (if tramp--test-expensive-test '(nil t) '(nil)))
+ (dolist (quoted (if (tramp--test-expensive-test-p) '(nil t) '(nil)))
(let* ((tmp-name1 (tramp--test-make-temp-name nil quoted))
- (tmp-name2 (expand-file-name "foo/bar" tmp-name1)))
+ (tmp-name2 (expand-file-name "foo/bar" tmp-name1))
+ (unusual-file-mode-1 #o740)
+ (unusual-file-mode-2 #o710))
(unwind-protect
(progn
- (make-directory tmp-name1)
+ (with-file-modes unusual-file-mode-1
+ (make-directory tmp-name1))
+ (should-error
+ (make-directory tmp-name1)
+ :type 'file-already-exists)
(should (file-directory-p tmp-name1))
(should (file-accessible-directory-p tmp-name1))
- (should-error (make-directory tmp-name2) :type 'file-error)
- (make-directory tmp-name2 'parents)
+ (when (tramp--test-supports-set-file-modes-p)
+ (should (equal (format "%#o" unusual-file-mode-1)
+ (format "%#o" (file-modes tmp-name1)))))
+ (should-error
+ (make-directory tmp-name2)
+ :type 'file-error)
+ (with-file-modes unusual-file-mode-2
+ (make-directory tmp-name2 'parents))
(should (file-directory-p tmp-name2))
- (should (file-accessible-directory-p tmp-name2)))
+ (should (file-accessible-directory-p tmp-name2))
+ (when (tramp--test-supports-set-file-modes-p)
+ (should (equal (format "%#o" unusual-file-mode-2)
+ (format "%#o" (file-modes tmp-name2)))))
+ ;; If PARENTS is non-nil, `make-directory' shall not
+ ;; signal an error when DIR exists already.
+ (make-directory tmp-name2 'parents))
;; Cleanup.
(ignore-errors (delete-directory tmp-name1 'recursive))))))
@@ -2114,38 +2894,99 @@ This tests also `file-directory-p' and `file-accessible-directory-p'."
"Check `delete-directory'."
(skip-unless (tramp--test-enabled))
- (dolist (quoted (if tramp--test-expensive-test '(nil t) '(nil)))
- (let ((tmp-name (tramp--test-make-temp-name nil quoted)))
+ (dolist (quoted (if (tramp--test-expensive-test-p) '(nil t) '(nil)))
+ (let* ((tmp-name1 (tramp--test-make-temp-name nil quoted))
+ (tmp-name2 (expand-file-name "foo" tmp-name1)))
;; Delete empty directory.
- (make-directory tmp-name)
- (should (file-directory-p tmp-name))
- (delete-directory tmp-name)
- (should-not (file-directory-p tmp-name))
+ (make-directory tmp-name1)
+ (should (file-directory-p tmp-name1))
+ (delete-directory tmp-name1)
+ (should-not (file-directory-p tmp-name1))
;; Delete non-empty directory.
- (make-directory tmp-name)
- (should (file-directory-p tmp-name))
- (write-region "foo" nil (expand-file-name "bla" tmp-name))
- (should (file-exists-p (expand-file-name "bla" tmp-name)))
- (should-error (delete-directory tmp-name) :type 'file-error)
- (delete-directory tmp-name 'recursive)
- (should-not (file-directory-p tmp-name)))))
+ (make-directory tmp-name1)
+ (should (file-directory-p tmp-name1))
+ (write-region "foo" nil (expand-file-name "bla" tmp-name1))
+ (should (file-exists-p (expand-file-name "bla" tmp-name1)))
+ (make-directory tmp-name2)
+ (should (file-directory-p tmp-name2))
+ (write-region "foo" nil (expand-file-name "bla" tmp-name2))
+ (should (file-exists-p (expand-file-name "bla" tmp-name2)))
+ (should-error
+ (delete-directory tmp-name1)
+ :type 'file-error)
+ (delete-directory tmp-name1 'recursive)
+ (should-not (file-directory-p tmp-name1))
+
+ ;; Trashing directories works only since Emacs 27.1. It doesn't
+ ;; work when `system-move-file-to-trash' is defined (on MS
+ ;; Windows and macOS), for encrypted remote directories and for
+ ;; ange-ftp.
+ (when (and (not (fboundp 'system-move-file-to-trash))
+ (not (tramp--test-crypt-p)) (not (tramp--test-ftp-p))
+ (tramp--test-emacs27-p))
+ (let ((trash-directory (tramp--test-make-temp-name 'local quoted))
+ (delete-by-moving-to-trash t))
+ (make-directory trash-directory)
+ ;; Delete empty directory.
+ (make-directory tmp-name1)
+ (should (file-directory-p tmp-name1))
+ (delete-directory tmp-name1 nil 'trash)
+ (should-not (file-directory-p tmp-name1))
+ (should
+ (file-exists-p
+ (expand-file-name
+ (file-name-nondirectory tmp-name1) trash-directory)))
+ (delete-directory trash-directory 'recursive)
+ (should-not (file-exists-p trash-directory))
+ ;; Delete non-empty directory.
+ (make-directory tmp-name1)
+ (should (file-directory-p tmp-name1))
+ (write-region "foo" nil (expand-file-name "bla" tmp-name1))
+ (should (file-exists-p (expand-file-name "bla" tmp-name1)))
+ (make-directory tmp-name2)
+ (should (file-directory-p tmp-name2))
+ (write-region "foo" nil (expand-file-name "bla" tmp-name2))
+ (should (file-exists-p (expand-file-name "bla" tmp-name2)))
+ (should-error
+ (delete-directory tmp-name1 nil 'trash)
+ ;; tramp-rclone.el and tramp-sshfs.el call the local
+ ;; `delete-directory'. This raises another error.
+ :type (if (tramp--test-fuse-p) 'error 'file-error))
+ (delete-directory tmp-name1 'recursive 'trash)
+ (should-not (file-directory-p tmp-name1))
+ (should
+ (file-exists-p
+ (format
+ "%s/%s/bla" trash-directory (file-name-nondirectory tmp-name1))))
+ (should
+ (file-exists-p
+ (format
+ "%s/%s/%s/bla" trash-directory (file-name-nondirectory tmp-name1)
+ (file-name-nondirectory tmp-name2))))
+ (delete-directory trash-directory 'recursive)
+ (should-not (file-exists-p trash-directory)))))))
(ert-deftest tramp-test15-copy-directory ()
"Check `copy-directory'."
(skip-unless (tramp--test-enabled))
+ (skip-unless (not (tramp--test-rclone-p)))
- (dolist (quoted (if tramp--test-expensive-test '(nil t) '(nil)))
+ (dolist (quoted (if (tramp--test-expensive-test-p) '(nil t) '(nil)))
(let* ((tmp-name1 (tramp--test-make-temp-name nil quoted))
(tmp-name2 (tramp--test-make-temp-name nil quoted))
(tmp-name3 (expand-file-name
(file-name-nondirectory tmp-name1) tmp-name2))
(tmp-name4 (expand-file-name "foo" tmp-name1))
(tmp-name5 (expand-file-name "foo" tmp-name2))
- (tmp-name6 (expand-file-name "foo" tmp-name3)))
+ (tmp-name6 (expand-file-name "foo" tmp-name3))
+ (tmp-name7 (tramp--test-make-temp-name nil quoted)))
;; Copy complete directory.
(unwind-protect
(progn
+ (should-error
+ (copy-directory tmp-name1 tmp-name2)
+ :type 'file-missing)
;; Copy empty directory.
(make-directory tmp-name1)
(write-region "foo" nil tmp-name4)
@@ -2155,11 +2996,9 @@ This tests also `file-directory-p' and `file-accessible-directory-p'."
(should (file-directory-p tmp-name2))
(should (file-exists-p tmp-name5))
;; Target directory does exist already.
- ;; This has been changed in Emacs 26.1.
- (when (tramp--test-emacs26-p)
- (should-error
- (copy-directory tmp-name1 tmp-name2)
- :type 'file-error))
+ (should-error
+ (copy-directory tmp-name1 tmp-name2)
+ :type 'file-already-exists)
(copy-directory tmp-name1 (file-name-as-directory tmp-name2))
(should (file-directory-p tmp-name3))
(should (file-exists-p tmp-name6)))
@@ -2194,18 +3033,63 @@ This tests also `file-directory-p' and `file-accessible-directory-p'."
;; Cleanup.
(ignore-errors
(delete-directory tmp-name1 'recursive)
- (delete-directory tmp-name2 'recursive))))))
+ (delete-directory tmp-name2 'recursive)))
+
+ ;; Copy symlink to directory. Implemented since Emacs 28.1.
+ (when (boundp 'copy-directory-create-symlink)
+ (dolist (copy-directory-create-symlink '(nil t))
+ (unwind-protect
+ (tramp--test-ignore-make-symbolic-link-error
+ ;; Copy to file name.
+ (make-directory tmp-name1)
+ (write-region "foo" nil tmp-name4)
+ (make-symbolic-link tmp-name1 tmp-name7)
+ (should (file-directory-p tmp-name1))
+ (should (file-exists-p tmp-name4))
+ (should (file-symlink-p tmp-name7))
+ (copy-directory tmp-name7 tmp-name2)
+ (if copy-directory-create-symlink
+ (should
+ (string-equal
+ (file-symlink-p tmp-name2) (file-symlink-p tmp-name7)))
+ (should (file-directory-p tmp-name2)))
+ ;; Copy to directory name.
+ (delete-directory tmp-name2 'recursive)
+ (make-directory tmp-name2)
+ (should (file-directory-p tmp-name2))
+ (copy-directory tmp-name7 (file-name-as-directory tmp-name2))
+ (if copy-directory-create-symlink
+ (should
+ (string-equal
+ (file-symlink-p
+ (expand-file-name
+ (file-name-nondirectory tmp-name7) tmp-name2))
+ (file-symlink-p tmp-name7)))
+ (should
+ (file-directory-p
+ (expand-file-name
+ (file-name-nondirectory tmp-name7) tmp-name2)))))
+
+ ;; Cleanup.
+ (ignore-errors
+ (delete-directory tmp-name1 'recursive)
+ (delete-directory tmp-name2 'recursive)
+ (delete-directory tmp-name7 'recursive))))))))
(ert-deftest tramp-test16-directory-files ()
"Check `directory-files'."
(skip-unless (tramp--test-enabled))
- (dolist (quoted (if tramp--test-expensive-test '(nil t) '(nil)))
- (let* ((tmp-name1 (tramp--test-make-temp-name nil quoted))
+ (dolist (quoted (if (tramp--test-expensive-test-p) '(nil t) '(nil)))
+ (let* ((tramp-fuse-remove-hidden-files t)
+ (tmp-name1 (tramp--test-make-temp-name nil quoted))
(tmp-name2 (expand-file-name "bla" tmp-name1))
(tmp-name3 (expand-file-name "foo" tmp-name1)))
(unwind-protect
(progn
+ (should-error
+ (directory-files tmp-name1)
+ :type 'file-missing)
(make-directory tmp-name1)
(write-region "foo" nil tmp-name2)
(write-region "bla" nil tmp-name3)
@@ -2222,7 +3106,15 @@ This tests also `file-directory-p' and `file-accessible-directory-p'."
'("bla" "foo")))
(should (equal (directory-files
tmp-name1 'full directory-files-no-dot-files-regexp)
- `(,tmp-name2 ,tmp-name3))))
+ `(,tmp-name2 ,tmp-name3)))
+ ;; Check the COUNT arg. It exists since Emacs 28.
+ (when (tramp--test-emacs28-p)
+ (with-no-warnings
+ (should
+ (equal
+ (directory-files
+ tmp-name1 nil directory-files-no-dot-files-regexp nil 1)
+ '("bla"))))))
;; Cleanup.
(ignore-errors (delete-directory tmp-name1 'recursive))))))
@@ -2233,8 +3125,9 @@ This tests also `file-directory-p' and `file-accessible-directory-p'."
"Check `file-expand-wildcards'."
(skip-unless (tramp--test-enabled))
- (dolist (quoted (if tramp--test-expensive-test '(nil t) '(nil)))
- (let* ((tmp-name1 (tramp--test-make-temp-name nil quoted))
+ (dolist (quoted (if (tramp--test-expensive-test-p) '(nil t) '(nil)))
+ (let* ((tramp-fuse-remove-hidden-files t)
+ (tmp-name1 (tramp--test-make-temp-name nil quoted))
(tmp-name2 (expand-file-name "foo" tmp-name1))
(tmp-name3 (expand-file-name "bar" tmp-name1))
(tmp-name4 (expand-file-name "baz" tmp-name1))
@@ -2290,14 +3183,20 @@ This tests also `file-directory-p' and `file-accessible-directory-p'."
(sort (copy-sequence `(,tmp-name3 ,tmp-name4)) 'string<))))
;; Cleanup.
- (ignore-errors
- (delete-directory tmp-name1))))))
+ (ignore-errors (delete-directory tmp-name1 'recursive))))))
(ert-deftest tramp-test17-insert-directory ()
"Check `insert-directory'."
(skip-unless (tramp--test-enabled))
-
- (dolist (quoted (if tramp--test-expensive-test '(nil t) '(nil)))
+ ;; Ange-FTP is very special. It does not include the header line
+ ;; (this is performed by `dired'). If FULL is nil, it shows just
+ ;; one file. So we refrain from testing.
+ (skip-unless (not (tramp--test-ange-ftp-p)))
+ ;; `insert-directory' of encrypted remote directories works only
+ ;; since Emacs 27.1.
+ (skip-unless (or (not (tramp--test-crypt-p)) (tramp--test-emacs27-p)))
+
+ (dolist (quoted (if (tramp--test-expensive-test-p) '(nil t) '(nil)))
(let* ((tmp-name1
(expand-file-name (tramp--test-make-temp-name nil quoted)))
(tmp-name2 (expand-file-name "foo" tmp-name1))
@@ -2313,50 +3212,88 @@ This tests also `file-directory-p' and `file-accessible-directory-p'."
(with-temp-buffer
(insert-directory tmp-name1 nil)
(goto-char (point-min))
- (should (looking-at-p (regexp-quote tmp-name1))))
+ (should (looking-at-p (tramp-compat-rx (literal tmp-name1)))))
+ (with-temp-buffer
+ (insert-directory (file-name-as-directory tmp-name1) nil)
+ (goto-char (point-min))
+ (should
+ (looking-at-p
+ (tramp-compat-rx (literal (file-name-as-directory tmp-name1))))))
(with-temp-buffer
(insert-directory tmp-name1 "-al")
(goto-char (point-min))
(should
- (looking-at-p (format "^.+ %s$" (regexp-quote tmp-name1)))))
+ (looking-at-p
+ (tramp-compat-rx bol (+ nonl) blank (literal tmp-name1) eol))))
(with-temp-buffer
(insert-directory (file-name-as-directory tmp-name1) "-al")
(goto-char (point-min))
(should
- (looking-at-p (format "^.+ %s/$" (regexp-quote tmp-name1)))))
+ (looking-at-p
+ (tramp-compat-rx
+ bol (+ nonl) blank (literal tmp-name1) "/" eol))))
(with-temp-buffer
(insert-directory
(file-name-as-directory tmp-name1) "-al" nil 'full-directory-p)
(goto-char (point-min))
(should
(looking-at-p
- (concat
- ;; There might be a summary line.
- "\\(total.+[[:digit:]]+\n\\)?"
- ;; We don't know in which order ".", ".." and "foo" appear.
- "\\(.+ \\(\\.?\\.\\|foo\\)\n\\)\\{3\\}")))))
+ (rx-to-string
+ `(:
+ ;; There might be a summary line.
+ (? "total" (+ nonl) (+ digit) (? blank)
+ (? (any "EGKMPTYZk")) (? "i") (? "B") "\n")
+ ;; We don't know in which order ".", ".." and "foo" appear.
+ (= ,(length (directory-files tmp-name1))
+ (+ nonl) blank
+ (regexp ,(regexp-opt (directory-files tmp-name1)))
+ (? " ->" (+ nonl)) "\n"))))))
+
+ ;; Check error cases.
+ (when (and (tramp--test-supports-set-file-modes-p)
+ ;; With "sshfs", directories with zero file
+ ;; modes are still "accessible".
+ (not (tramp--test-sshfs-p))
+ ;; A directory is always accessible for user "root".
+ (not (zerop (file-attribute-user-id
+ (file-attributes tmp-name1)))))
+ (set-file-modes tmp-name1 0)
+ (with-temp-buffer
+ (should-error
+ (insert-directory tmp-name1 nil)
+ :type 'file-error))
+ (set-file-modes tmp-name1 #o777))
+ (delete-directory tmp-name1 'recursive)
+ (with-temp-buffer
+ (should-error
+ (insert-directory tmp-name1 nil)
+ :type 'file-missing)))
;; Cleanup.
(ignore-errors (delete-directory tmp-name1 'recursive))))))
(ert-deftest tramp-test17-dired-with-wildcards ()
"Check `dired' with wildcards."
+ ;; `separate' syntax and IPv6 host name syntax do not work.
+ (skip-unless
+ (not (string-match-p (rx "[") ert-remote-temporary-file-directory)))
(skip-unless (tramp--test-enabled))
(skip-unless (tramp--test-sh-p))
- ;; Since Emacs 26.1.
- (skip-unless (fboundp 'insert-directory-wildcard-in-dir-p))
+ (skip-unless (not (tramp--test-rsync-p)))
+ ;; Wildcards are not supported in tramp-crypt.el.
+ (skip-unless (not (tramp--test-crypt-p)))
- (dolist (quoted (if tramp--test-expensive-test '(nil t) '(nil)))
+ (dolist (quoted (if (tramp--test-expensive-test-p) '(nil t) '(nil)))
(let* ((tmp-name1
(expand-file-name (tramp--test-make-temp-name nil quoted)))
(tmp-name2
(expand-file-name (tramp--test-make-temp-name nil quoted)))
(tmp-name3 (expand-file-name "foo" tmp-name1))
(tmp-name4 (expand-file-name "bar" tmp-name2))
- (tramp-test-temporary-file-directory
+ (ert-remote-temporary-file-directory
(funcall
- (if quoted 'tramp-compat-file-name-quote 'identity)
- tramp-test-temporary-file-directory))
+ (if quoted #'tramp-compat-file-name-quote #'identity)
+ ert-remote-temporary-file-directory))
buffer)
(unwind-protect
(progn
@@ -2374,19 +3311,21 @@ This tests also `file-directory-p' and `file-accessible-directory-p'."
(setq buffer
(dired-noselect
(expand-file-name
- "tramp-test*" tramp-test-temporary-file-directory)))
+ "tramp-test*" ert-remote-temporary-file-directory)))
(goto-char (point-min))
(should
(re-search-forward
- (regexp-quote
- (file-relative-name
- tmp-name1 tramp-test-temporary-file-directory))))
+ (tramp-compat-rx
+ (literal
+ (file-relative-name
+ tmp-name1 ert-remote-temporary-file-directory)))))
(goto-char (point-min))
(should
(re-search-forward
- (regexp-quote
- (file-relative-name
- tmp-name2 tramp-test-temporary-file-directory)))))
+ (tramp-compat-rx
+ (literal
+ (file-relative-name
+ tmp-name2 ert-remote-temporary-file-directory))))))
(kill-buffer buffer)
;; Check for expanded directory and file names.
@@ -2394,20 +3333,22 @@ This tests also `file-directory-p' and `file-accessible-directory-p'."
(setq buffer
(dired-noselect
(expand-file-name
- "tramp-test*/*" tramp-test-temporary-file-directory)))
+ "tramp-test*/*" ert-remote-temporary-file-directory)))
(goto-char (point-min))
(should
(re-search-forward
- (regexp-quote
- (file-relative-name
- tmp-name3 tramp-test-temporary-file-directory))))
+ (tramp-compat-rx
+ (literal
+ (file-relative-name
+ tmp-name3 ert-remote-temporary-file-directory)))))
(goto-char (point-min))
(should
(re-search-forward
- (regexp-quote
- (file-relative-name
- tmp-name4
- tramp-test-temporary-file-directory)))))
+ (tramp-compat-rx
+ (literal
+ (file-relative-name
+ tmp-name4
+ ert-remote-temporary-file-directory))))))
(kill-buffer buffer)
;; Check for special characters.
@@ -2422,20 +3363,22 @@ This tests also `file-directory-p' and `file-accessible-directory-p'."
(setq buffer
(dired-noselect
(expand-file-name
- "tramp-test*/*" tramp-test-temporary-file-directory)))
+ "tramp-test*/*" ert-remote-temporary-file-directory)))
(goto-char (point-min))
(should
(re-search-forward
- (regexp-quote
- (file-relative-name
- tmp-name3 tramp-test-temporary-file-directory))))
+ (tramp-compat-rx
+ (literal
+ (file-relative-name
+ tmp-name3 ert-remote-temporary-file-directory)))))
(goto-char (point-min))
(should
(re-search-forward
- (regexp-quote
- (file-relative-name
- tmp-name4
- tramp-test-temporary-file-directory)))))
+ (tramp-compat-rx
+ (literal
+ (file-relative-name
+ tmp-name4
+ ert-remote-temporary-file-directory))))))
(kill-buffer buffer))
;; Cleanup.
@@ -2443,32 +3386,73 @@ This tests also `file-directory-p' and `file-accessible-directory-p'."
(ignore-errors (delete-directory tmp-name1 'recursive))
(ignore-errors (delete-directory tmp-name2 'recursive))))))
-;; Method "smb" supports `make-symbolic-link' only if the remote host
-;; has CIFS capabilities. tramp-adb.el and tramp-gvfs.el do not
-;; support symbolic links at all.
-(defmacro tramp--test-ignore-make-symbolic-link-error (&rest body)
- "Run BODY, ignoring \"make-symbolic-link not supported\" file error."
- (declare (indent defun) (debug t))
- `(condition-case err
- (progn ,@body)
- ((error quit debug)
- (unless (and (eq (car err) 'file-error)
- (string-equal (error-message-string err)
- "make-symbolic-link not supported"))
- (signal (car err) (cdr err))))))
+;; The following test is inspired by Bug#45691.
+(ert-deftest tramp-test17-insert-directory-one-file ()
+ "Check `insert-directory' inside directory listing."
+ (skip-unless (tramp--test-enabled))
+ ;; Relative file names in dired are not supported in tramp-crypt.el.
+ (skip-unless (not (tramp--test-crypt-p)))
+
+ (dolist (quoted (if (tramp--test-expensive-test-p) '(nil t) '(nil)))
+ (let* ((tmp-name1
+ (expand-file-name (tramp--test-make-temp-name nil quoted)))
+ (tmp-name2 (expand-file-name "foo" tmp-name1))
+ (tmp-name3 (expand-file-name "bar" tmp-name1))
+ (dired-copy-preserve-time t)
+ (dired-recursive-copies 'top)
+ dired-copy-dereference
+ buffer)
+ (unwind-protect
+ (progn
+ (make-directory tmp-name1)
+ (write-region "foo" nil tmp-name2)
+ (should (file-directory-p tmp-name1))
+ (should (file-exists-p tmp-name2))
+
+ ;; Check, that `insert-directory' works properly.
+ (with-current-buffer
+ (setq buffer (dired-noselect tmp-name1 "--dired -al"))
+ (read-only-mode -1)
+ (goto-char (point-min))
+ (while (not (or (eobp)
+ (string-equal
+ (dired-get-filename 'no-dir 'no-error)
+ (file-name-nondirectory tmp-name2))))
+ (forward-line 1))
+ (should-not (eobp))
+ (copy-file tmp-name2 tmp-name3)
+ (insert-directory
+ (file-name-nondirectory tmp-name3) "--dired -al -d")
+ ;; Point shall still be the recent file.
+ (should
+ (string-equal
+ (dired-get-filename 'no-dir 'no-error)
+ (file-name-nondirectory tmp-name2)))
+ (should-not (search-forward "dired" nil t))
+ ;; The copied file has been inserted the line before.
+ (forward-line -1)
+ (should
+ (string-equal
+ (dired-get-filename 'no-dir 'no-error)
+ (file-name-nondirectory tmp-name3))))
+ (kill-buffer buffer))
+
+ ;; Cleanup.
+ (ignore-errors (kill-buffer buffer))
+ (ignore-errors (delete-directory tmp-name1 'recursive))))))
(ert-deftest tramp-test18-file-attributes ()
"Check `file-attributes'.
-This tests also `file-readable-p', `file-regular-p' and
-`file-ownership-preserved-p'."
+This tests also `access-file', `file-readable-p',
+`file-regular-p' and `file-ownership-preserved-p'."
(skip-unless (tramp--test-enabled))
- (dolist (quoted (if tramp--test-expensive-test '(nil t) '(nil)))
+ (dolist (quoted (if (tramp--test-expensive-test-p) '(nil t) '(nil)))
;; We must use `file-truename' for the temporary directory,
;; because it could be located on a symlinked directory. This
;; would let the test fail.
- (let* ((tramp-test-temporary-file-directory
- (file-truename tramp-test-temporary-file-directory))
+ (let* ((ert-remote-temporary-file-directory
+ (file-truename ert-remote-temporary-file-directory))
(tmp-name1 (tramp--test-make-temp-name nil quoted))
(tmp-name2 (tramp--test-make-temp-name nil quoted))
;; File name with "//".
@@ -2478,60 +3462,96 @@ This tests also `file-readable-p', `file-regular-p' and
(file-remote-p tmp-name1)
(replace-regexp-in-string
"/" "//" (file-remote-p tmp-name1 'localname))))
+ ;; `file-ownership-preserved-p' is implemented only in tramp-sh.el.
+ (test-file-ownership-preserved-p (tramp--test-sh-p))
attr)
(unwind-protect
(progn
+ ;; A sticky bit could damage the `file-ownership-preserved-p' test.
+ (when
+ (and test-file-ownership-preserved-p
+ (zerop (logand
+ #o1000
+ (file-modes ert-remote-temporary-file-directory))))
+ (write-region "foo" nil tmp-name1)
+ (setq test-file-ownership-preserved-p
+ (= (file-attribute-group-id (file-attributes tmp-name1))
+ (tramp-get-remote-gid tramp-test-vec 'integer)))
+ (delete-file tmp-name1))
+
+ (when (tramp--test-supports-set-file-modes-p)
+ (write-region "foo" nil tmp-name1)
+ ;; A file is always accessible for user "root".
+ (unless
+ (zerop (file-attribute-user-id (file-attributes tmp-name1)))
+ (set-file-modes tmp-name1 0)
+ (should-error
+ (access-file tmp-name1 "error")
+ :type tramp-permission-denied)
+ (set-file-modes tmp-name1 #o777))
+ (delete-file tmp-name1))
+ (should-error
+ (access-file tmp-name1 "error")
+ :type 'file-missing)
+
;; `file-ownership-preserved-p' should return t for
- ;; non-existing files. It is implemented only in tramp-sh.el.
- (when (tramp--test-sh-p)
+ ;; non-existing files.
+ (when test-file-ownership-preserved-p
(should (file-ownership-preserved-p tmp-name1 'group)))
(write-region "foo" nil tmp-name1)
(should (file-exists-p tmp-name1))
(should (file-readable-p tmp-name1))
(should (file-regular-p tmp-name1))
- (when (tramp--test-sh-p)
+ (should-not (access-file tmp-name1 "error"))
+ (when test-file-ownership-preserved-p
(should (file-ownership-preserved-p tmp-name1 'group)))
;; We do not test inodes and device numbers.
(setq attr (file-attributes tmp-name1))
(should (consp attr))
- (should (null (car attr)))
- (should (numberp (nth 1 attr))) ;; Link.
- (should (numberp (nth 2 attr))) ;; Uid.
- (should (numberp (nth 3 attr))) ;; Gid.
- ;; Last access time.
- (should (stringp (current-time-string (nth 4 attr))))
- ;; Last modification time.
- (should (stringp (current-time-string (nth 5 attr))))
- ;; Last status change time.
- (should (stringp (current-time-string (nth 6 attr))))
- (should (numberp (nth 7 attr))) ;; Size.
- (should (stringp (nth 8 attr))) ;; Modes.
+ (should (null (file-attribute-type attr)))
+ (should (numberp (file-attribute-link-number attr)))
+ (should (numberp (file-attribute-user-id attr)))
+ (should (numberp (file-attribute-group-id attr)))
+ (should
+ (stringp (current-time-string (file-attribute-access-time attr))))
+ (should
+ (stringp
+ (current-time-string (file-attribute-modification-time attr))))
+ (should
+ (stringp
+ (current-time-string (file-attribute-status-change-time attr))))
+ (should (numberp (file-attribute-size attr)))
+ (should (stringp (file-attribute-modes attr)))
(setq attr (file-attributes tmp-name1 'string))
- (should (stringp (nth 2 attr))) ;; Uid.
- (should (stringp (nth 3 attr))) ;; Gid.
+ (should (stringp (file-attribute-user-id attr)))
+ (should (stringp (file-attribute-group-id attr)))
(tramp--test-ignore-make-symbolic-link-error
- (when (tramp--test-sh-p)
+ (should-error
+ (access-file tmp-name2 "error")
+ :type 'file-missing)
+ (when test-file-ownership-preserved-p
(should (file-ownership-preserved-p tmp-name2 'group)))
(make-symbolic-link tmp-name1 tmp-name2)
(should (file-exists-p tmp-name2))
(should (file-symlink-p tmp-name2))
- (when (tramp--test-sh-p)
+ (should-not (access-file tmp-name2 "error"))
+ (when test-file-ownership-preserved-p
(should (file-ownership-preserved-p tmp-name2 'group)))
(setq attr (file-attributes tmp-name2))
(should
(string-equal
(funcall
- (if quoted 'tramp-compat-file-name-quote 'identity)
- (car attr))
+ (if quoted #'tramp-compat-file-name-quote #'identity)
+ (file-attribute-type attr))
(file-remote-p (file-truename tmp-name1) 'localname)))
(delete-file tmp-name2))
;; Check, that "//" in symlinks are handled properly.
(with-temp-buffer
- (let ((default-directory tramp-test-temporary-file-directory))
+ (let ((default-directory ert-remote-temporary-file-directory))
(shell-command
(format
"ln -s %s %s"
@@ -2544,33 +3564,189 @@ This tests also `file-readable-p', `file-regular-p' and
(setq attr (file-attributes tmp-name2))
(should
(string-equal
- (car attr)
- (tramp-file-name-localname
- (tramp-dissect-file-name tmp-name3))))
+ (file-attribute-type attr)
+ (funcall
+ (if (tramp--test-sshfs-p) #'file-name-nondirectory #'identity)
+ (tramp-file-name-localname
+ (tramp-dissect-file-name tmp-name3)))))
(delete-file tmp-name2))
- (when (tramp--test-sh-p)
+ (when test-file-ownership-preserved-p
(should (file-ownership-preserved-p tmp-name1 'group)))
(delete-file tmp-name1)
(make-directory tmp-name1)
(should (file-exists-p tmp-name1))
(should (file-readable-p tmp-name1))
(should-not (file-regular-p tmp-name1))
- (when (tramp--test-sh-p)
+ (should-not (access-file tmp-name1 ""))
+ (when test-file-ownership-preserved-p
(should (file-ownership-preserved-p tmp-name1 'group)))
(setq attr (file-attributes tmp-name1))
- (should (eq (car attr) t)))
+ (should (eq (file-attribute-type attr) t)))
;; Cleanup.
(ignore-errors (delete-directory tmp-name1))
(ignore-errors (delete-file tmp-name1))
(ignore-errors (delete-file tmp-name2))))))
+(defmacro tramp--test-deftest-with-stat (test)
+ "Define ert `TEST-with-stat'."
+ (declare (indent 1))
+ `(ert-deftest ,(intern (concat (symbol-name test) "-with-stat")) ()
+ ;; This is the docstring. However, it must be expanded to a
+ ;; string inside the macro. No idea.
+ ;; (concat (ert-test-documentation (get ',test 'ert--test))
+ ;; "\nUse the \"stat\" command.")
+ :tags '(:expensive-test)
+ (skip-unless (tramp--test-enabled))
+ (skip-unless (tramp--test-sh-p))
+ (skip-unless (tramp-get-remote-stat tramp-test-vec))
+ (if-let ((default-directory ert-remote-temporary-file-directory)
+ (ert-test (ert-get-test ',test))
+ (result (ert-test-most-recent-result ert-test))
+ (tramp-connection-properties
+ (cons '(nil "perl" nil)
+ tramp-connection-properties)))
+ (progn
+ ;; `ert-test-result-duration' exists since Emacs 27. It
+ ;; doesn't hurt to call it unconditionally, because
+ ;; `skip-unless' hides the error.
+ (skip-unless (< (ert-test-result-duration result) 300))
+ (funcall (ert-test-body ert-test)))
+ (ert-skip (format "Test `%s' must run before" ',test)))))
+
+(defmacro tramp--test-deftest-with-perl (test)
+ "Define ert `TEST-with-perl'."
+ (declare (indent 1))
+ `(ert-deftest ,(intern (concat (symbol-name test) "-with-perl")) ()
+ ;; This is the docstring. However, it must be expanded to a
+ ;; string inside the macro. No idea.
+ ;; (concat (ert-test-documentation (get ',test 'ert--test))
+ ;; "\nUse the \"perl\" command.")
+ :tags '(:expensive-test)
+ (skip-unless (tramp--test-enabled))
+ (skip-unless (tramp--test-sh-p))
+ (skip-unless (tramp-get-remote-perl tramp-test-vec))
+ (if-let ((default-directory ert-remote-temporary-file-directory)
+ (ert-test (ert-get-test ',test))
+ (result (ert-test-most-recent-result ert-test))
+ (tramp-connection-properties
+ (append
+ '((nil "stat" nil)
+ ;; See `tramp-sh-handle-file-truename'.
+ (nil "readlink" nil)
+ ;; See `tramp-sh-handle-get-remote-*'.
+ (nil "id" nil))
+ tramp-connection-properties)))
+ (progn
+ ;; `ert-test-result-duration' exists since Emacs 27. It
+ ;; doesn't hurt to call it unconditionally, because
+ ;; `skip-unless' hides the error.
+ (skip-unless (< (ert-test-result-duration result) 300))
+ (funcall (ert-test-body ert-test)))
+ (ert-skip (format "Test `%s' must run before" ',test)))))
+
+(defmacro tramp--test-deftest-with-ls (test)
+ "Define ert `TEST-with-ls'."
+ (declare (indent 1))
+ `(ert-deftest ,(intern (concat (symbol-name test) "-with-ls")) ()
+ ;; This is the docstring. However, it must be expanded to a
+ ;; string inside the macro. No idea.
+ ;; (concat (ert-test-documentation (get ',test 'ert--test))
+ ;; "\nUse the \"ls\" command.")
+ :tags '(:expensive-test)
+ (skip-unless (tramp--test-enabled))
+ (skip-unless (tramp--test-sh-p))
+ (if-let ((default-directory ert-remote-temporary-file-directory)
+ (ert-test (ert-get-test ',test))
+ (result (ert-test-most-recent-result ert-test))
+ (tramp-connection-properties
+ (append
+ '((nil "perl" nil)
+ (nil "stat" nil)
+ ;; See `tramp-sh-handle-file-truename'.
+ (nil "readlink" nil))
+ tramp-connection-properties)))
+ (progn
+ ;; `ert-test-result-duration' exists since Emacs 27. It
+ ;; doesn't hurt to call it unconditionally, because
+ ;; `skip-unless' hides the error.
+ (skip-unless (< (ert-test-result-duration result) 300))
+ (funcall (ert-test-body ert-test)))
+ (ert-skip (format "Test `%s' must run before" ',test)))))
+
+(tramp--test-deftest-with-stat tramp-test18-file-attributes)
+
+(tramp--test-deftest-with-perl tramp-test18-file-attributes)
+
+(tramp--test-deftest-with-ls tramp-test18-file-attributes)
+
+(defvar tramp--test-start-time nil
+ "Keep the start time of the current test, a float number.")
+
+(defsubst tramp--test-file-attributes-equal-p (attr1 attr2)
+ "Check, whether file attributes ATTR1 and ATTR2 are equal.
+They might differ only in time attributes or directory size."
+ (let ((attr1 (copy-sequence attr1))
+ (attr2 (copy-sequence attr2))
+ (start-time (- tramp--test-start-time 10)))
+ ;; Link number. For directories, it includes the number of
+ ;; subdirectories. Set it to 1.
+ (when (eq (file-attribute-type attr1) t)
+ (setcar (nthcdr 1 attr1) 1))
+ (when (eq (file-attribute-type attr2) t)
+ (setcar (nthcdr 1 attr2) 1))
+ ;; Access time.
+ (setcar (nthcdr 4 attr1) tramp-time-dont-know)
+ (setcar (nthcdr 4 attr2) tramp-time-dont-know)
+ ;; Modification time. If any of the time values is "don't know",
+ ;; we cannot compare, and we normalize the time stamps. If the
+ ;; time value is newer than the test start time, normalize it,
+ ;; because due to caching the time stamps could differ slightly (a
+ ;; few seconds). We use a test start time minus 10 seconds, in
+ ;; order to compensate a possible timestamp resolution higher than
+ ;; a second on the remote machine.
+ (when (or (tramp-compat-time-equal-p
+ (file-attribute-modification-time attr1) tramp-time-dont-know)
+ (tramp-compat-time-equal-p
+ (file-attribute-modification-time attr2) tramp-time-dont-know))
+ (setcar (nthcdr 5 attr1) tramp-time-dont-know)
+ (setcar (nthcdr 5 attr2) tramp-time-dont-know))
+ (when (< start-time
+ (float-time (file-attribute-modification-time attr1)))
+ (setcar (nthcdr 5 attr1) tramp-time-dont-know))
+ (when (< start-time
+ (float-time (file-attribute-modification-time attr2)))
+ (setcar (nthcdr 5 attr2) tramp-time-dont-know))
+ ;; Status change time. Ditto.
+ (when (or (tramp-compat-time-equal-p
+ (file-attribute-status-change-time attr1) tramp-time-dont-know)
+ (tramp-compat-time-equal-p
+ (file-attribute-status-change-time attr2) tramp-time-dont-know))
+ (setcar (nthcdr 6 attr1) tramp-time-dont-know)
+ (setcar (nthcdr 6 attr2) tramp-time-dont-know))
+ (when (< start-time (float-time (file-attribute-status-change-time attr1)))
+ (setcar (nthcdr 6 attr1) tramp-time-dont-know))
+ (when (< start-time (float-time (file-attribute-status-change-time attr2)))
+ (setcar (nthcdr 6 attr2) tramp-time-dont-know))
+ ;; Size. Set it to 0 for directories, because it might have
+ ;; changed. For example the upper directory "../".
+ (when (eq (file-attribute-type attr1) t)
+ (setcar (nthcdr 7 attr1) 0))
+ (when (eq (file-attribute-type attr2) t)
+ (setcar (nthcdr 7 attr2) 0))
+ ;; The check.
+ (unless (equal attr1 attr2) (tramp--test-message "%S\n%S" attr1 attr2))
+ (equal attr1 attr2)))
+
+;; This isn't 100% correct, but better than no explainer at all.
+(put #'tramp--test-file-attributes-equal-p 'ert-explainer #'ert--explain-equal)
+
(ert-deftest tramp-test19-directory-files-and-attributes ()
"Check `directory-files-and-attributes'."
(skip-unless (tramp--test-enabled))
- (dolist (quoted (if tramp--test-expensive-test '(nil t) '(nil)))
+ (dolist (quoted (if (tramp--test-expensive-test-p) '(nil t) '(nil)))
;; `directory-files-and-attributes' contains also values for
;; "../". Ensure that this doesn't change during tests, for
;; example due to handling temporary files.
@@ -2579,83 +3755,172 @@ This tests also `file-readable-p', `file-regular-p' and
attr)
(unwind-protect
(progn
+ (should-error
+ (directory-files-and-attributes tmp-name1)
+ :type 'file-missing)
(make-directory tmp-name1)
(should (file-directory-p tmp-name1))
+ (setq tramp--test-start-time
+ (float-time
+ (file-attribute-modification-time
+ (file-attributes tmp-name1))))
(make-directory tmp-name2)
(should (file-directory-p tmp-name2))
(write-region "foo" nil (expand-file-name "foo" tmp-name2))
(write-region "bar" nil (expand-file-name "bar" tmp-name2))
(write-region "boz" nil (expand-file-name "boz" tmp-name2))
+
(setq attr (directory-files-and-attributes tmp-name2))
(should (consp attr))
- ;; Dumb remote shells without perl(1) or stat(1) are not
- ;; able to return the date correctly. They say "don't know".
(dolist (elt attr)
- (unless
- (equal
- (nth
- 5 (file-attributes (expand-file-name (car elt) tmp-name2)))
- '(0 0))
- (should
- (equal (file-attributes (expand-file-name (car elt) tmp-name2))
- (cdr elt)))))
+ (should
+ (tramp--test-file-attributes-equal-p
+ (file-attributes (expand-file-name (car elt) tmp-name2))
+ (cdr elt))))
+
(setq attr (directory-files-and-attributes tmp-name2 'full))
+ (should (consp attr))
(dolist (elt attr)
- (unless (equal (nth 5 (file-attributes (car elt))) '(0 0))
- (should
- (equal (file-attributes (car elt)) (cdr elt)))))
- (setq attr (directory-files-and-attributes tmp-name2 nil "^b"))
- (should (equal (mapcar 'car attr) '("bar" "boz"))))
+ (should
+ (tramp--test-file-attributes-equal-p
+ (file-attributes (car elt)) (cdr elt))))
+
+ (setq attr (directory-files-and-attributes
+ tmp-name2 nil (rx bos "b")))
+ (should (equal (mapcar #'car attr) '("bar" "boz")))
+
+ ;; Check the COUNT arg. It exists since Emacs 28.
+ (when (tramp--test-emacs28-p)
+ (with-no-warnings
+ (setq attr (directory-files-and-attributes
+ tmp-name2 nil (rx bos "b") nil nil 1))
+ (should (equal (mapcar #'car attr) '("bar"))))))
;; Cleanup.
(ignore-errors (delete-directory tmp-name1 'recursive))))))
+(tramp--test-deftest-with-stat tramp-test19-directory-files-and-attributes)
+
+(tramp--test-deftest-with-perl tramp-test19-directory-files-and-attributes)
+
+(tramp--test-deftest-with-ls tramp-test19-directory-files-and-attributes)
+
(ert-deftest tramp-test20-file-modes ()
"Check `file-modes'.
This tests also `file-executable-p', `file-writable-p' and `set-file-modes'."
(skip-unless (tramp--test-enabled))
- (skip-unless (tramp--test-sh-p))
+ (skip-unless (tramp--test-supports-set-file-modes-p))
+
+ (dolist (quoted (if (tramp--test-expensive-test-p) '(nil t) '(nil)))
+ (let ((tmp-name1 (tramp--test-make-temp-name nil quoted))
+ (tmp-name2 (tramp--test-make-temp-name nil quoted)))
- (dolist (quoted (if tramp--test-expensive-test '(nil t) '(nil)))
- (let ((tmp-name (tramp--test-make-temp-name nil quoted)))
(unwind-protect
(progn
- (write-region "foo" nil tmp-name)
- (should (file-exists-p tmp-name))
- (set-file-modes tmp-name #o777)
- (should (= (file-modes tmp-name) #o777))
- (should (file-executable-p tmp-name))
- (should (file-writable-p tmp-name))
- (set-file-modes tmp-name #o444)
- (should (= (file-modes tmp-name) #o444))
- (should-not (file-executable-p tmp-name))
+ (write-region "foo" nil tmp-name1)
+ (should (file-exists-p tmp-name1))
+ (set-file-modes tmp-name1 #o777)
+ (should (= (file-modes tmp-name1) #o777))
+ (should (file-executable-p tmp-name1))
+ (should (file-writable-p tmp-name1))
+ (set-file-modes tmp-name1 #o444)
+ (should (= (file-modes tmp-name1) #o444))
+ (should-not (file-executable-p tmp-name1))
;; A file is always writable for user "root".
- (unless (zerop (nth 2 (file-attributes tmp-name)))
- (should-not (file-writable-p tmp-name))))
+ (unless
+ (or (zerop (file-attribute-user-id (file-attributes tmp-name1)))
+ (tramp--test-sshfs-p))
+ (should-not (file-writable-p tmp-name1)))
+ ;; Check the NOFOLLOW arg. It exists since Emacs 28. For
+ ;; regular files, there shouldn't be a difference.
+ (when (tramp--test-emacs28-p)
+ (with-no-warnings
+ (set-file-modes tmp-name1 #o222 'nofollow)
+ (should (= (file-modes tmp-name1 'nofollow) #o222))))
+ ;; Setting the mode for not existing files shall fail.
+ (should-error
+ (set-file-modes tmp-name2 #o777)
+ :type 'file-missing))
;; Cleanup.
- (ignore-errors (delete-file tmp-name))))))
+ (ignore-errors (delete-file tmp-name1)))
+
+ ;; Check the NOFOLLOW arg. It exists since Emacs 28. It is
+ ;; implemented for tramp-gvfs.el and tramp-sh.el. However,
+ ;; tramp-gvfs,el does not support creating symbolic links. And
+ ;; in tramp-sh.el, we must ensure that the remote chmod command
+ ;; supports the "-h" argument.
+ (when (and (tramp--test-emacs28-p) (tramp--test-sh-p)
+ (tramp-get-remote-chmod-h tramp-test-vec))
+ (unwind-protect
+ (with-no-warnings
+ (write-region "foo" nil tmp-name1)
+ (should (file-exists-p tmp-name1))
+ (make-symbolic-link tmp-name1 tmp-name2)
+ (should
+ (string-equal
+ (funcall
+ (if quoted #'tramp-compat-file-name-unquote #'identity)
+ (file-remote-p tmp-name1 'localname))
+ (file-symlink-p tmp-name2)))
+ ;; Both report the modes of `tmp-name1'.
+ (should
+ (= (file-modes tmp-name1) (file-modes tmp-name2)))
+ ;; `tmp-name1' is a regular file. NOFOLLOW doesn't matter.
+ (should
+ (= (file-modes tmp-name1) (file-modes tmp-name1 'nofollow)))
+ ;; `tmp-name2' is a symbolic link. It has different permissions.
+ (should-not
+ (= (file-modes tmp-name2) (file-modes tmp-name2 'nofollow)))
+ (should-not
+ (= (file-modes tmp-name1 'nofollow)
+ (file-modes tmp-name2 'nofollow)))
+ ;; Change permissions.
+ (set-file-modes tmp-name1 #o200)
+ (set-file-modes tmp-name2 #o200)
+ (should
+ (= (file-modes tmp-name1) (file-modes tmp-name2) #o200))
+ ;; Change permissions with NOFOLLOW.
+ (set-file-modes tmp-name1 #o300 'nofollow)
+ (set-file-modes tmp-name2 #o300 'nofollow)
+ (should
+ (= (file-modes tmp-name1 'nofollow)
+ (file-modes tmp-name2 'nofollow)))
+ (should-not (= (file-modes tmp-name1) (file-modes tmp-name2))))
+
+ ;; Cleanup.
+ (ignore-errors (delete-file tmp-name1))
+ (ignore-errors (delete-file tmp-name2)))))))
+
+;; Method "smb" could run into "NT_STATUS_REVISION_MISMATCH" error.
+(defmacro tramp--test-ignore-add-name-to-file-error (&rest body)
+ "Run BODY, ignoring \"error with add-name-to-file\" file error."
+ (declare (indent defun) (debug (body)))
+ `(condition-case err
+ (progn ,@body)
+ (file-error
+ (unless (string-prefix-p "error with add-name-to-file"
+ (error-message-string err))
+ (signal (car err) (cdr err))))))
(ert-deftest tramp-test21-file-links ()
"Check `file-symlink-p'.
This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
(skip-unless (tramp--test-enabled))
- ;; The semantics has changed heavily in Emacs 26.1. We cannot test
- ;; older Emacsen, therefore.
- (skip-unless (tramp--test-emacs26-p))
- (dolist (quoted (if tramp--test-expensive-test '(nil t) '(nil)))
+ (dolist (quoted (if (tramp--test-expensive-test-p) '(nil t) '(nil)))
;; We must use `file-truename' for the temporary directory,
;; because it could be located on a symlinked directory. This
;; would let the test fail.
- (let* ((tramp-test-temporary-file-directory
- (file-truename tramp-test-temporary-file-directory))
+ (let* ((ert-remote-temporary-file-directory
+ (file-truename ert-remote-temporary-file-directory))
(tmp-name1 (tramp--test-make-temp-name nil quoted))
(tmp-name2 (tramp--test-make-temp-name nil quoted))
(tmp-name3 (tramp--test-make-temp-name 'local quoted))
(tmp-name4 (tramp--test-make-temp-name nil quoted))
(tmp-name5
- (expand-file-name (file-name-nondirectory tmp-name1) tmp-name4)))
+ (expand-file-name (file-name-nondirectory tmp-name1) tmp-name4))
+ (tmp-name6 (tramp--test-make-temp-name nil quoted)))
;; Check `make-symbolic-link'.
(unwind-protect
(tramp--test-ignore-make-symbolic-link-error
@@ -2665,30 +3930,32 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
(should
(string-equal
(funcall
- (if quoted 'tramp-compat-file-name-unquote 'identity)
+ (if quoted #'tramp-compat-file-name-unquote #'identity)
(file-remote-p tmp-name1 'localname))
(file-symlink-p tmp-name2)))
- (should-error
- (make-symbolic-link tmp-name1 tmp-name2)
- :type 'file-already-exists)
- ;; number means interactive case.
- (cl-letf (((symbol-function 'yes-or-no-p) 'ignore))
+ (when (tramp--test-expensive-test-p)
(should-error
- (make-symbolic-link tmp-name1 tmp-name2 0)
+ (make-symbolic-link tmp-name1 tmp-name2)
:type 'file-already-exists))
- (cl-letf (((symbol-function 'yes-or-no-p) (lambda (_prompt) t)))
+ (when (tramp--test-expensive-test-p)
+ ;; A number means interactive case.
+ (cl-letf (((symbol-function #'yes-or-no-p) #'ignore))
+ (should-error
+ (make-symbolic-link tmp-name1 tmp-name2 0)
+ :type 'file-already-exists)))
+ (cl-letf (((symbol-function #'yes-or-no-p) #'tramp--test-always))
(make-symbolic-link tmp-name1 tmp-name2 0)
(should
(string-equal
(funcall
- (if quoted 'tramp-compat-file-name-unquote 'identity)
+ (if quoted #'tramp-compat-file-name-unquote #'identity)
(file-remote-p tmp-name1 'localname))
(file-symlink-p tmp-name2))))
(make-symbolic-link tmp-name1 tmp-name2 'ok-if-already-exists)
(should
(string-equal
(funcall
- (if quoted 'tramp-compat-file-name-unquote 'identity)
+ (if quoted #'tramp-compat-file-name-unquote #'identity)
(file-remote-p tmp-name1 'localname))
(file-symlink-p tmp-name2)))
;; If we use the local part of `tmp-name1', it shall still work.
@@ -2698,72 +3965,80 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
(should
(string-equal
(funcall
- (if quoted 'tramp-compat-file-name-unquote 'identity)
+ (if quoted #'tramp-compat-file-name-unquote #'identity)
(file-remote-p tmp-name1 'localname))
(file-symlink-p tmp-name2)))
;; `tmp-name3' is a local file name. Therefore, the link
;; target remains unchanged, even if quoted.
- (make-symbolic-link tmp-name1 tmp-name3)
- (should
- (string-equal tmp-name1 (file-symlink-p tmp-name3)))
+ ;; `make-symbolic-link' might not be permitted on w32 systems.
+ (unless (tramp--test-windows-nt-p)
+ (make-symbolic-link tmp-name1 tmp-name3)
+ (should
+ (string-equal tmp-name1 (file-symlink-p tmp-name3))))
;; Check directory as newname.
(make-directory tmp-name4)
- (should-error
- (make-symbolic-link tmp-name1 tmp-name4)
- :type 'file-already-exists)
+ (when (tramp--test-expensive-test-p)
+ (should-error
+ (make-symbolic-link tmp-name1 tmp-name4)
+ :type 'file-already-exists))
(make-symbolic-link tmp-name1 (file-name-as-directory tmp-name4))
(should
(string-equal
(funcall
- (if quoted 'tramp-compat-file-name-unquote 'identity)
+ (if quoted #'tramp-compat-file-name-unquote #'identity)
(file-remote-p tmp-name1 'localname))
(file-symlink-p tmp-name5)))
- ;; `smbclient' does not show symlinks in directories, so
- ;; we cannot delete a non-empty directory. We delete the
- ;; file explicitly.
- (delete-file tmp-name5))
+ ;; Check, that files in symlinked directories still work.
+ (make-symbolic-link tmp-name4 tmp-name6)
+ (write-region "foo" nil (expand-file-name "foo" tmp-name6))
+ (delete-file (expand-file-name "foo" tmp-name6))
+ (should-not (file-exists-p (expand-file-name "foo" tmp-name4)))
+ (should-not (file-exists-p (expand-file-name "foo" tmp-name6))))
;; Cleanup.
- (ignore-errors
- (delete-file tmp-name1)
- (delete-file tmp-name2)
- (delete-file tmp-name3)
- (delete-directory tmp-name4 'recursive)))
+ (ignore-errors (delete-file tmp-name1))
+ (ignore-errors (delete-file tmp-name2))
+ (ignore-errors (delete-file tmp-name3))
+ (ignore-errors (delete-file tmp-name5))
+ (ignore-errors (delete-file tmp-name6))
+ (ignore-errors (delete-directory tmp-name4 'recursive)))
;; Check `add-name-to-file'.
(unwind-protect
- (progn
- (write-region "foo" nil tmp-name1)
- (should (file-exists-p tmp-name1))
- (add-name-to-file tmp-name1 tmp-name2)
- (should (file-regular-p tmp-name2))
- (should-error
+ (when (tramp--test-expensive-test-p)
+ (tramp--test-ignore-add-name-to-file-error
+ (write-region "foo" nil tmp-name1)
+ (should (file-exists-p tmp-name1))
(add-name-to-file tmp-name1 tmp-name2)
- :type 'file-already-exists)
- ;; A number means interactive case.
- (cl-letf (((symbol-function 'yes-or-no-p) 'ignore))
- (should-error
- (add-name-to-file tmp-name1 tmp-name2 0)
- :type 'file-already-exists))
- (cl-letf (((symbol-function 'yes-or-no-p) (lambda (_prompt) t)))
+ (should (file-regular-p tmp-name2))
+ (should-error
+ (add-name-to-file tmp-name1 tmp-name2)
+ :type 'file-already-exists)
+ ;; A number means interactive case.
+ (cl-letf (((symbol-function #'yes-or-no-p) #'ignore))
+ (should-error
+ (add-name-to-file tmp-name1 tmp-name2 0)
+ :type 'file-already-exists))
+ (cl-letf (((symbol-function #'yes-or-no-p) #'tramp--test-always))
(add-name-to-file tmp-name1 tmp-name2 0)
(should (file-regular-p tmp-name2)))
- (add-name-to-file tmp-name1 tmp-name2 'ok-if-already-exists)
- (should-not (file-symlink-p tmp-name2))
- (should (file-regular-p tmp-name2))
- ;; `tmp-name3' is a local file name.
- (should-error
- (add-name-to-file tmp-name1 tmp-name3)
- :type 'file-error)
- ;; Check directory as newname.
- (make-directory tmp-name4)
- (should-error
- (add-name-to-file tmp-name1 tmp-name4)
- :type 'file-already-exists)
- (add-name-to-file tmp-name1 (file-name-as-directory tmp-name4))
- (should
- (file-regular-p
- (expand-file-name (file-name-nondirectory tmp-name1) tmp-name4))))
+ (add-name-to-file tmp-name1 tmp-name2 'ok-if-already-exists)
+ (should-not (file-symlink-p tmp-name2))
+ (should (file-regular-p tmp-name2))
+ ;; `tmp-name3' is a local file name.
+ (should-error
+ (add-name-to-file tmp-name1 tmp-name3)
+ :type 'file-error)
+ ;; Check directory as newname.
+ (make-directory tmp-name4)
+ (should-error
+ (add-name-to-file tmp-name1 tmp-name4)
+ :type 'file-already-exists)
+ (add-name-to-file tmp-name1 (file-name-as-directory tmp-name4))
+ (should
+ (file-regular-p
+ (expand-file-name
+ (file-name-nondirectory tmp-name1) tmp-name4)))))
;; Cleanup.
(ignore-errors
@@ -2783,26 +4058,43 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
(should
(string-equal (file-truename tmp-name1) (file-truename tmp-name2)))
(should (file-equal-p tmp-name1 tmp-name2))
- ;; Symbolic links could look like a remote file name.
- ;; They must be quoted then.
+ ;; Check relative symlink file name.
(delete-file tmp-name2)
- (make-symbolic-link "/penguin:motd:" tmp-name2)
+ (let ((default-directory ert-remote-temporary-file-directory))
+ (make-symbolic-link (file-name-nondirectory tmp-name1) tmp-name2))
(should (file-symlink-p tmp-name2))
+ (should-not (string-equal tmp-name2 (file-truename tmp-name2)))
(should
- (string-equal
- (file-truename tmp-name2)
- (tramp-compat-file-name-quote
- (concat (file-remote-p tmp-name2) "/penguin:motd:"))))
+ (string-equal (file-truename tmp-name1) (file-truename tmp-name2)))
+ (should (file-equal-p tmp-name1 tmp-name2))
+ ;; Symbolic links could look like a remote file name.
+ ;; They must be quoted then.
+ (let ((penguin
+ (if (eq tramp-syntax 'separate)
+ "/[penguin/motd]" "/penguin:motd:")))
+ (delete-file tmp-name2)
+ (make-symbolic-link
+ (funcall
+ (if quoted #'tramp-compat-file-name-unquote #'identity) penguin)
+ tmp-name2)
+ (should (file-symlink-p tmp-name2))
+ (should
+ (string-equal
+ (file-truename tmp-name2)
+ (tramp-compat-file-name-quote
+ (concat (file-remote-p tmp-name2) penguin)))))
;; `tmp-name3' is a local file name.
- (make-symbolic-link tmp-name1 tmp-name3)
- (should (file-symlink-p tmp-name3))
- (should-not (string-equal tmp-name3 (file-truename tmp-name3)))
- ;; `file-truename' returns a quoted file name for `tmp-name3'.
- ;; We must unquote it.
- (should
- (string-equal
- (file-truename tmp-name1)
- (tramp-compat-file-name-unquote (file-truename tmp-name3)))))
+ ;; `make-symbolic-link' might not be permitted on w32 systems.
+ (unless (tramp--test-windows-nt-p)
+ (make-symbolic-link tmp-name1 tmp-name3)
+ (should (file-symlink-p tmp-name3))
+ (should-not (string-equal tmp-name3 (file-truename tmp-name3)))
+ ;; `file-truename' returns a quoted file name for `tmp-name3'.
+ ;; We must unquote it.
+ (should
+ (string-equal
+ (file-truename tmp-name1)
+ (tramp-compat-file-name-unquote (file-truename tmp-name3))))))
;; Cleanup.
(ignore-errors
@@ -2815,7 +4107,7 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
(tramp--test-ignore-make-symbolic-link-error
(make-directory tmp-name1)
(should (file-directory-p tmp-name1))
- (let* ((tramp-test-temporary-file-directory
+ (let* ((ert-remote-temporary-file-directory
(file-truename tmp-name1))
(tmp-name2 (tramp--test-make-temp-name nil quoted))
(tmp-name3 tmp-name2)
@@ -2828,12 +4120,14 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
(string-equal
(file-truename tmp-name2)
(file-truename tmp-name3)))
- (should-error
- (with-temp-buffer (insert-file-contents tmp-name2))
- :type tramp-file-missing)
- (should-error
- (with-temp-buffer (insert-file-contents tmp-name3))
- :type tramp-file-missing)
+ (when (tramp--test-expensive-test-p)
+ (should-error
+ (with-temp-buffer (insert-file-contents tmp-name2))
+ :type 'file-missing))
+ (when (tramp--test-expensive-test-p)
+ (should-error
+ (with-temp-buffer (insert-file-contents tmp-name3))
+ :type 'file-missing))
;; `directory-files' does not show symlinks to
;; non-existing targets in the "smb" case. So we remove
;; the symlinks manually.
@@ -2842,36 +4136,51 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
(setq tmp-name3 (concat (file-remote-p tmp-name3) tmp-name2)))))
;; Cleanup.
+ (ignore-errors (delete-file tmp-name2))
+ (ignore-errors (delete-file tmp-name3))
(ignore-errors (delete-directory tmp-name1 'recursive)))
;; Detect cyclic symbolic links.
(unwind-protect
- (tramp--test-ignore-make-symbolic-link-error
- (make-symbolic-link tmp-name2 tmp-name1)
- (should (file-symlink-p tmp-name1))
- (make-symbolic-link tmp-name1 tmp-name2)
- (should (file-symlink-p tmp-name2))
- (should-error (file-truename tmp-name1) :type 'file-error))
+ (when (tramp--test-expensive-test-p)
+ (tramp--test-ignore-make-symbolic-link-error
+ (make-symbolic-link tmp-name2 tmp-name1)
+ (should (file-symlink-p tmp-name1))
+ (if (tramp--test-smb-p)
+ ;; The symlink command of "smbclient" detects the
+ ;; cycle already.
+ (should-error
+ (make-symbolic-link tmp-name1 tmp-name2)
+ :type 'file-error)
+ (make-symbolic-link tmp-name1 tmp-name2)
+ (should (file-symlink-p tmp-name2))
+ (should-error
+ (file-truename tmp-name1)
+ :type 'file-error))))
;; Cleanup.
(ignore-errors
(delete-file tmp-name1)
(delete-file tmp-name2)))
- ;; `file-truename' shall preserve trailing link of directories.
- (unless (file-symlink-p tramp-test-temporary-file-directory)
- (let* ((dir1 (directory-file-name tramp-test-temporary-file-directory))
- (dir2 (file-name-as-directory dir1)))
- (should (string-equal (file-truename dir1) (expand-file-name dir1)))
- (should
- (string-equal (file-truename dir2) (expand-file-name dir2))))))))
+ ;; `file-truename' shall preserve trailing slash of directories.
+ (let* ((dir1
+ (directory-file-name
+ (funcall
+ (if quoted #'tramp-compat-file-name-quote #'identity)
+ ert-remote-temporary-file-directory)))
+ (dir2 (file-name-as-directory dir1)))
+ (should (string-equal (file-truename dir1) (expand-file-name dir1)))
+ (should (string-equal (file-truename dir2) (expand-file-name dir2)))))))
(ert-deftest tramp-test22-file-times ()
"Check `set-file-times' and `file-newer-than-file-p'."
(skip-unless (tramp--test-enabled))
- (skip-unless (or (tramp--test-adb-p) (tramp--test-sh-p)))
+ (skip-unless
+ (or (tramp--test-adb-p) (tramp--test-gvfs-p)
+ (tramp--test-sh-p) (tramp--test-sudoedit-p)))
- (dolist (quoted (if tramp--test-expensive-test '(nil t) '(nil)))
+ (dolist (quoted (if (tramp--test-expensive-test-p) '(nil t) '(nil)))
(let ((tmp-name1 (tramp--test-make-temp-name nil quoted))
(tmp-name2 (tramp--test-make-temp-name nil quoted))
(tmp-name3 (tramp--test-make-temp-name nil quoted)))
@@ -2879,22 +4188,42 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
(progn
(write-region "foo" nil tmp-name1)
(should (file-exists-p tmp-name1))
- (should (consp (nth 5 (file-attributes tmp-name1))))
- ;; '(0 0) means don't know, and will be replaced by
- ;; `current-time'. Therefore, we use '(0 1). We skip the
- ;; test, if the remote handler is not able to set the
- ;; correct time.
- (skip-unless (set-file-times tmp-name1 '(0 1)))
+ (should (consp (file-attribute-modification-time
+ (file-attributes tmp-name1))))
+ ;; Skip the test, if the remote handler is not able to set
+ ;; the correct time.
+ ;; Some remote machines cannot resolve seconds. So we use a minute.
+ (skip-unless (set-file-times tmp-name1 (seconds-to-time 60)))
;; Dumb remote shells without perl(1) or stat(1) are not
;; able to return the date correctly. They say "don't know".
- (unless (equal (nth 5 (file-attributes tmp-name1)) '(0 0))
- (should (equal (nth 5 (file-attributes tmp-name1)) '(0 1)))
+ (unless (tramp-compat-time-equal-p
+ (file-attribute-modification-time
+ (file-attributes tmp-name1))
+ tramp-time-dont-know)
+ (should
+ (tramp-compat-time-equal-p
+ (file-attribute-modification-time (file-attributes tmp-name1))
+ (seconds-to-time 60)))
+ ;; Setting the time for not existing files shall fail.
+ (should-error
+ (set-file-times tmp-name2)
+ :type 'file-missing)
(write-region "bla" nil tmp-name2)
(should (file-exists-p tmp-name2))
(should (file-newer-than-file-p tmp-name2 tmp-name1))
;; `tmp-name3' does not exist.
(should (file-newer-than-file-p tmp-name2 tmp-name3))
- (should-not (file-newer-than-file-p tmp-name3 tmp-name1))))
+ (should-not (file-newer-than-file-p tmp-name3 tmp-name1))
+ ;; Check the NOFOLLOW arg. It exists since Emacs 28. For
+ ;; regular files, there shouldn't be a difference.
+ (when (tramp--test-emacs28-p)
+ (with-no-warnings
+ (set-file-times tmp-name1 (seconds-to-time 60) 'nofollow)
+ (should
+ (tramp-compat-time-equal-p
+ (file-attribute-modification-time
+ (file-attributes tmp-name1))
+ (seconds-to-time 60)))))))
;; Cleanup.
(ignore-errors
@@ -2905,7 +4234,7 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
"Check `set-visited-file-modtime' and `verify-visited-file-modtime'."
(skip-unless (tramp--test-enabled))
- (dolist (quoted (if tramp--test-expensive-test '(nil t) '(nil)))
+ (dolist (quoted (if (tramp--test-expensive-test-p) '(nil t) '(nil)))
(let ((tmp-name (tramp--test-make-temp-name nil quoted)))
(unwind-protect
(progn
@@ -2914,22 +4243,253 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
(with-temp-buffer
(insert-file-contents tmp-name)
(should (verify-visited-file-modtime))
- (set-visited-file-modtime '(0 1))
+ (set-visited-file-modtime (seconds-to-time 1))
+ (should (verify-visited-file-modtime))
+ (should (= 1 (float-time (visited-file-modtime))))
+
+ ;; Checks with deleted file.
+ (delete-file tmp-name)
+ (dired-uncache tmp-name)
+ (should (verify-visited-file-modtime))
+ (set-visited-file-modtime (seconds-to-time 1))
(should (verify-visited-file-modtime))
- (should (equal (visited-file-modtime) '(0 1 0 0)))))
+ (should (= 1 (float-time (visited-file-modtime))))))
;; Cleanup.
(ignore-errors (delete-file tmp-name))))))
-(ert-deftest tramp-test24-file-name-completion ()
+;; This test is inspired by Bug#29149.
+(ert-deftest tramp-test24-file-acl ()
+ "Check that `file-acl' and `set-file-acl' work proper."
+ (skip-unless (tramp--test-enabled))
+ ;; The following test checks also whether `set-file-modes' will work.
+ (skip-unless (file-acl ert-remote-temporary-file-directory))
+ (skip-unless (not (tramp--test-crypt-p)))
+
+ ;; `filename-non-special' has been fixed in Emacs 27.1, see Bug#29579.
+ (dolist (quoted
+ (if (and (tramp--test-expensive-test-p) (tramp--test-emacs27-p))
+ '(nil t) '(nil)))
+ (let ((tmp-name1 (tramp--test-make-temp-name nil quoted))
+ (tmp-name2 (tramp--test-make-temp-name nil quoted))
+ (tmp-name3 (tramp--test-make-temp-name 'local quoted)))
+ ;; Both files are remote.
+ (unwind-protect
+ (progn
+ ;; Two files with same ACLs.
+ (write-region "foo" nil tmp-name1)
+ (should (file-exists-p tmp-name1))
+ (should (file-acl tmp-name1))
+ (copy-file tmp-name1 tmp-name2 nil nil nil 'preserve-permissions)
+ (should (file-acl tmp-name2))
+ (should (string-equal (file-acl tmp-name1) (file-acl tmp-name2)))
+ ;; Different permissions mean different ACLs.
+ (unless (tramp--test-windows-nt-or-smb-p)
+ (set-file-modes tmp-name1 #o777)
+ (set-file-modes tmp-name2 #o444)
+ (should-not
+ (string-equal (file-acl tmp-name1) (file-acl tmp-name2))))
+ ;; Copy ACL. Not all remote handlers support it, so we test.
+ (when (set-file-acl tmp-name2 (file-acl tmp-name1))
+ (should (string-equal (file-acl tmp-name1) (file-acl tmp-name2))))
+ ;; An invalid ACL does not harm.
+ (should-not (set-file-acl tmp-name2 "foo")))
+
+ ;; Cleanup.
+ (ignore-errors (delete-file tmp-name1))
+ (ignore-errors (delete-file tmp-name2)))
+
+ ;; Remote and local file.
+ (unwind-protect
+ (when (and (file-acl temporary-file-directory)
+ (not (tramp--test-windows-nt-or-smb-p)))
+ ;; Two files with same ACLs.
+ (write-region "foo" nil tmp-name1)
+ (should (file-exists-p tmp-name1))
+ (should (file-acl tmp-name1))
+ (copy-file tmp-name1 tmp-name3 nil nil nil 'preserve-permissions)
+ (should (file-acl tmp-name3))
+ (should (string-equal (file-acl tmp-name1) (file-acl tmp-name3)))
+ ;; Different permissions mean different ACLs.
+ (set-file-modes tmp-name1 #o777)
+ (set-file-modes tmp-name3 #o444)
+ (should-not
+ (string-equal (file-acl tmp-name1) (file-acl tmp-name3)))
+ ;; Copy ACL. Since we don't know whether Emacs is built
+ ;; with local ACL support, we must check it.
+ (when (set-file-acl tmp-name3 (file-acl tmp-name1))
+ (should (string-equal (file-acl tmp-name1) (file-acl tmp-name3))))
+
+ ;; Two files with same ACLs.
+ (delete-file tmp-name1)
+ (copy-file tmp-name3 tmp-name1 nil nil nil 'preserve-permissions)
+ (should (file-acl tmp-name1))
+ (should (string-equal (file-acl tmp-name1) (file-acl tmp-name3)))
+ ;; Different permissions mean different ACLs.
+ (set-file-modes tmp-name1 #o777)
+ (set-file-modes tmp-name3 #o444)
+ (should-not
+ (string-equal (file-acl tmp-name1) (file-acl tmp-name3)))
+ ;; Copy ACL.
+ (set-file-acl tmp-name1 (file-acl tmp-name3))
+ (should (string-equal (file-acl tmp-name1) (file-acl tmp-name3))))
+
+ ;; Cleanup.
+ (ignore-errors (delete-file tmp-name1))
+ (ignore-errors (delete-file tmp-name3))))))
+
+(ert-deftest tramp-test25-file-selinux ()
+ "Check `file-selinux-context' and `set-file-selinux-context'."
+ (skip-unless (tramp--test-enabled))
+ (skip-unless
+ (not (equal (file-selinux-context ert-remote-temporary-file-directory)
+ '(nil nil nil nil))))
+ (skip-unless (not (tramp--test-crypt-p)))
+
+ ;; `filename-non-special' has been fixed in Emacs 27.1, see Bug#29579.
+ (dolist (quoted
+ (if (and (tramp--test-expensive-test-p) (tramp--test-emacs27-p))
+ '(nil t) '(nil)))
+ (let ((tmp-name1 (tramp--test-make-temp-name nil quoted))
+ (tmp-name2 (tramp--test-make-temp-name nil quoted))
+ (tmp-name3 (tramp--test-make-temp-name 'local quoted)))
+ ;; Both files are remote.
+ (unwind-protect
+ (progn
+ ;; Two files with same SELinux context.
+ (write-region "foo" nil tmp-name1)
+ (should (file-exists-p tmp-name1))
+ (should (file-selinux-context tmp-name1))
+ (copy-file tmp-name1 tmp-name2 nil nil nil 'preserve-permissions)
+ (should (file-selinux-context tmp-name2))
+ (should
+ (equal
+ (file-selinux-context tmp-name1)
+ (file-selinux-context tmp-name2)))
+ ;; Check different SELinux context. We cannot support
+ ;; different ranges in this test; let's assume the most
+ ;; likely one.
+ (let ((context (file-selinux-context tmp-name1)))
+ (when (and (string-equal (nth 3 context) "s0")
+ (setcar (nthcdr 3 context) "s0:c0")
+ (set-file-selinux-context tmp-name1 context))
+ (should-not
+ (equal
+ (file-selinux-context tmp-name1)
+ (file-selinux-context tmp-name2)))))
+ ;; Copy SELinux context.
+ (should
+ (set-file-selinux-context
+ tmp-name2 (file-selinux-context tmp-name1)))
+ (should
+ (equal
+ (file-selinux-context tmp-name1)
+ (file-selinux-context tmp-name2)))
+ ;; An invalid SELinux context does not harm.
+ (should-not (set-file-selinux-context tmp-name2 "foo")))
+
+ ;; Cleanup.
+ (ignore-errors (delete-file tmp-name1))
+ (ignore-errors (delete-file tmp-name2)))
+
+ ;; Remote and local file.
+ (unwind-protect
+ (when (and (not
+ (or (equal (file-selinux-context temporary-file-directory)
+ '(nil nil nil nil))
+ (tramp--test-windows-nt-or-smb-p)))
+ ;; Both users shall use the same SELinux context.
+ (string-equal
+ (let ((default-directory temporary-file-directory))
+ (shell-command-to-string "id -Z"))
+ (let ((default-directory
+ ert-remote-temporary-file-directory))
+ (shell-command-to-string "id -Z"))))
+
+ ;; Two files with same SELinux context.
+ (write-region "foo" nil tmp-name1)
+ (should (file-exists-p tmp-name1))
+ (should (file-selinux-context tmp-name1))
+ (copy-file tmp-name1 tmp-name3)
+ (should (file-selinux-context tmp-name3))
+ ;; We cannot expect that copying over file system
+ ;; boundaries keeps SELinux context. So we copy it
+ ;; explicitly.
+ (should
+ (set-file-selinux-context
+ tmp-name3 (file-selinux-context tmp-name1)))
+ (should
+ (equal
+ (file-selinux-context tmp-name1)
+ (file-selinux-context tmp-name3)))
+ ;; Check different SELinux context. We cannot support
+ ;; different ranges in this test; let's assume the most
+ ;; likely one.
+ (let ((context (file-selinux-context tmp-name1)))
+ (when (and (string-equal (nth 3 context) "s0")
+ (setcar (nthcdr 3 context) "s0:c0")
+ (set-file-selinux-context tmp-name1 context))
+ (should-not
+ (equal
+ (file-selinux-context tmp-name1)
+ (file-selinux-context tmp-name3)))))
+ ;; Copy SELinux context.
+ (should
+ (set-file-selinux-context
+ tmp-name3 (file-selinux-context tmp-name1)))
+ (should
+ (equal
+ (file-selinux-context tmp-name1)
+ (file-selinux-context tmp-name3)))
+
+ ;; Two files with same SELinux context.
+ (delete-file tmp-name1)
+ (copy-file tmp-name3 tmp-name1)
+ (should (file-selinux-context tmp-name1))
+ ;; We cannot expect that copying over file system
+ ;; boundaries keeps SELinux context. So we copy it
+ ;; explicitly.
+ (should
+ (set-file-selinux-context
+ tmp-name1 (file-selinux-context tmp-name3)))
+ (should
+ (equal
+ (file-selinux-context tmp-name1)
+ (file-selinux-context tmp-name3)))
+ ;; Check different SELinux context. We cannot support
+ ;; different ranges in this test; let's assume the most
+ ;; likely one.
+ (let ((context (file-selinux-context tmp-name3)))
+ (when (and (string-equal (nth 3 context) "s0")
+ (setcar (nthcdr 3 context) "s0:c0")
+ (set-file-selinux-context tmp-name3 context))
+ (should-not
+ (equal
+ (file-selinux-context tmp-name1)
+ (file-selinux-context tmp-name3)))))
+ ;; Copy SELinux context.
+ (should
+ (set-file-selinux-context
+ tmp-name1 (file-selinux-context tmp-name3)))
+ (should
+ (equal
+ (file-selinux-context tmp-name1)
+ (file-selinux-context tmp-name3))))
+
+ ;; Cleanup.
+ (ignore-errors (delete-file tmp-name1))
+ (ignore-errors (delete-file tmp-name3))))))
+
+(ert-deftest tramp-test26-file-name-completion ()
"Check `file-name-completion' and `file-name-all-completions'."
(skip-unless (tramp--test-enabled))
;; Method and host name in completion mode. This kind of completion
;; does not work on MS Windows.
- (when (not (memq system-type '(cygwin windows-nt)))
- (let ((method (file-remote-p tramp-test-temporary-file-directory 'method))
- (host (file-remote-p tramp-test-temporary-file-directory 'host))
+ (unless (memq system-type '(cygwin windows-nt))
+ (let ((tramp-fuse-remove-hidden-files t)
+ (method (file-remote-p ert-remote-temporary-file-directory 'method))
+ (host (file-remote-p ert-remote-temporary-file-directory 'host))
(orig-syntax tramp-syntax))
(when (and (stringp host) (string-match tramp-host-with-port-regexp host))
(setq host (match-string 1 host)))
@@ -2937,15 +4497,22 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
(unwind-protect
(dolist
(syntax
- (if tramp--test-expensive-test
+ (if (tramp--test-expensive-test-p)
(tramp-syntax-values) `(,orig-syntax)))
(tramp-change-syntax syntax)
- (let ;; This is needed for the `simplified' syntax.
- ((method-marker
- (if (zerop (length tramp-method-regexp))
- "" tramp-default-method-marker))
- ;; This is needed for the `separate' syntax.
- (prefix-format (substring tramp-prefix-format 1)))
+ ;; This has cleaned up all connection data, which are used
+ ;; for completion. We must refill the cache.
+ (tramp-set-connection-property tramp-test-vec "property" nil)
+
+ (let ;; This is needed for the `separate' syntax.
+ ((prefix-format (substring tramp-prefix-format 1))
+ ;; This is needed for the IPv6 host name syntax.
+ (ipv6-prefix
+ (and (string-match-p tramp-ipv6-regexp host)
+ tramp-prefix-ipv6-format))
+ (ipv6-postfix
+ (and (string-match-p tramp-ipv6-regexp host)
+ tramp-postfix-ipv6-format)))
;; Complete method name.
(unless (or (zerop (length method))
(zerop (length tramp-method-regexp)))
@@ -2954,22 +4521,6 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
(concat prefix-format method tramp-postfix-method-format)
(file-name-all-completions
(concat prefix-format (substring method 0 1)) "/"))))
- ;; Complete host name for default method. With gvfs
- ;; based methods, host name will be determined as
- ;; host.local, so we omit the test.
- (let ((tramp-default-method (or method tramp-default-method)))
- (unless (or (zerop (length host))
- (tramp--test-gvfs-p tramp-default-method))
- (should
- (member
- (concat
- prefix-format method-marker tramp-postfix-method-format
- host tramp-postfix-host-format)
- (file-name-all-completions
- (concat
- prefix-format method-marker tramp-postfix-method-format
- (substring host 0 1))
- "/")))))
;; Complete host name.
(unless (or (zerop (length method))
(zerop (length tramp-method-regexp))
@@ -2979,7 +4530,7 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
(member
(concat
prefix-format method tramp-postfix-method-format
- host tramp-postfix-host-format)
+ ipv6-prefix host ipv6-postfix tramp-postfix-host-format)
(file-name-all-completions
(concat prefix-format method tramp-postfix-method-format)
"/"))))))
@@ -2987,9 +4538,9 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
;; Cleanup.
(tramp-change-syntax orig-syntax))))
- (dolist (n-e '(nil t))
- (dolist (quoted (if tramp--test-expensive-test '(nil t) '(nil)))
- (let ((non-essential n-e)
+ (dolist (non-essential '(nil t))
+ (dolist (quoted (if (tramp--test-expensive-test-p) '(nil t) '(nil)))
+ (let ((tramp-fuse-remove-hidden-files t)
(tmp-name (tramp--test-make-temp-name nil quoted)))
(unwind-protect
@@ -3007,26 +4558,32 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
(should (equal (file-name-completion "foo" tmp-name) t))
(should (equal (file-name-completion "b" tmp-name) "bo"))
(should-not (file-name-completion "a" tmp-name))
- (should
- (equal
- (file-name-completion "b" tmp-name 'file-directory-p) "boz/"))
+ ;; Ange-FTP does not support predicates.
+ (unless (tramp--test-ange-ftp-p)
+ (should
+ (equal
+ (file-name-completion "b" tmp-name #'file-directory-p)
+ "boz/")))
(should
(equal (file-name-all-completions "fo" tmp-name) '("foo")))
(should
(equal
- (sort (file-name-all-completions "b" tmp-name) 'string-lessp)
+ (sort (file-name-all-completions "b" tmp-name) #'string-lessp)
'("bold" "boz/")))
(should-not (file-name-all-completions "a" tmp-name))
;; `completion-regexp-list' restricts the completion to
;; files which match all expressions in this list.
- (let ((completion-regexp-list
- `(,directory-files-no-dot-files-regexp "b")))
- (should
- (equal (file-name-completion "" tmp-name) "bo"))
- (should
- (equal
- (sort (file-name-all-completions "" tmp-name) 'string-lessp)
- '("bold" "boz/"))))
+ ;; Ange-FTP does not complete "".
+ (unless (tramp--test-ange-ftp-p)
+ (let ((completion-regexp-list
+ `(,directory-files-no-dot-files-regexp "b")))
+ (should
+ (equal (file-name-completion "" tmp-name) "bo"))
+ (should
+ (equal
+ (sort
+ (file-name-all-completions "" tmp-name) #'string-lessp)
+ '("bold" "boz/")))))
;; `file-name-completion' ignores file names that end in
;; any string in `completion-ignored-extensions'.
(let ((completion-ignored-extensions '(".ext")))
@@ -3040,21 +4597,23 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
;; `file-name-all-completions' is not affected.
(should
(equal
- (sort (file-name-all-completions "" tmp-name) 'string-lessp)
+ (sort (file-name-all-completions "" tmp-name) #'string-lessp)
'("../" "./" "bold" "boz/" "foo" "foo.ext")))))
;; Cleanup.
(ignore-errors (delete-directory tmp-name 'recursive)))))))
-(ert-deftest tramp-test25-load ()
+(ert-deftest tramp-test27-load ()
"Check `load'."
(skip-unless (tramp--test-enabled))
- (dolist (quoted (if tramp--test-expensive-test '(nil t) '(nil)))
+ (dolist (quoted (if (tramp--test-expensive-test-p) '(nil t) '(nil)))
(let ((tmp-name (tramp--test-make-temp-name nil quoted)))
(unwind-protect
(progn
- (load tmp-name 'noerror 'nomessage)
+ ;; Ange-FTP does not tolerate a missing file, even with `noerror'.
+ (unless (tramp--test-ange-ftp-p)
+ (load tmp-name 'noerror 'nomessage))
(should-not (featurep 'tramp-test-load))
(write-region "(provide 'tramp-test-load)" nil tmp-name)
;; `load' in lread.c does not pass `must-suffix'. Why?
@@ -3069,16 +4628,24 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
(and (featurep 'tramp-test-load) (unload-feature 'tramp-test-load))
(delete-file tmp-name))))))
-(ert-deftest tramp-test26-process-file ()
+(defun tramp--test-shell-file-name ()
+ "Return default remote shell."
+ (if (file-exists-p
+ (concat
+ (file-remote-p ert-remote-temporary-file-directory) "/system/bin/sh"))
+ "/system/bin/sh" "/bin/sh"))
+
+(ert-deftest tramp-test28-process-file ()
"Check `process-file'."
:tags '(:expensive-test)
(skip-unless (tramp--test-enabled))
- (skip-unless (or (tramp--test-adb-p) (tramp--test-sh-p)))
+ (skip-unless (tramp--test-supports-processes-p))
- (dolist (quoted (if tramp--test-expensive-test '(nil t) '(nil)))
+ (dolist (quoted (if (tramp--test-expensive-test-p) '(nil t) '(nil)))
(let* ((tmp-name (tramp--test-make-temp-name nil quoted))
(fnnd (file-name-nondirectory tmp-name))
- (default-directory tramp-test-temporary-file-directory)
+ (default-directory ert-remote-temporary-file-directory)
+ (buffer (get-buffer-create "*tramp-tests*"))
kill-buffer-query-functions)
(unwind-protect
(progn
@@ -3087,321 +4654,1096 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
(should (zerop (process-file "true")))
(should-not (zerop (process-file "false")))
(should-not (zerop (process-file "binary-does-not-exist")))
- (with-temp-buffer
- (write-region "foo" nil tmp-name)
- (should (file-exists-p tmp-name))
- (should (zerop (process-file "ls" nil t nil fnnd)))
- ;; `ls' could produce colorized output.
- (goto-char (point-min))
- (while
- (re-search-forward tramp-display-escape-sequence-regexp nil t)
- (replace-match "" nil nil))
- (should (string-equal (format "%s\n" fnnd) (buffer-string)))
- (should-not (get-buffer-window (current-buffer) t))
+ ;; Return exit code.
+ (should (= 42 (process-file
+ (tramp--test-shell-file-name)
+ nil nil nil "-c" "exit 42")))
+ ;; Return exit code in case the process is interrupted,
+ ;; and there's no indication for a signal describing string.
+ (unless (tramp--test-sshfs-p)
+ (let (process-file-return-signal-string)
+ (should
+ (= (+ 128 2)
+ (process-file
+ (tramp--test-shell-file-name)
+ nil nil nil "-c" "kill -2 $$")))))
+ ;; Return string in case the process is interrupted and
+ ;; there's an indication for a signal describing string.
+ (unless (tramp--test-sshfs-p)
+ (let ((process-file-return-signal-string t))
+ (should
+ (string-match-p
+ (rx (| "Interrupt" "Signal 2"))
+ (process-file
+ (tramp--test-shell-file-name)
+ nil nil nil "-c" "kill -2 $$")))))
+
+ ;; Check DESTINATION.
+ (dolist (destination `(nil t ,buffer))
+ (when (bufferp destination)
+ (with-current-buffer destination
+ (delete-region (point-min) (point-max))))
+ (with-temp-buffer
+ (write-region "foo" nil tmp-name)
+ (should (file-exists-p tmp-name))
+ (should (zerop (process-file "ls" nil destination nil fnnd)))
+ (with-current-buffer
+ (if (bufferp destination) destination (current-buffer))
+ ;; "ls" could produce colorized output.
+ (goto-char (point-min))
+ (while (re-search-forward
+ tramp-display-escape-sequence-regexp nil t)
+ (replace-match "" nil nil))
+ (should
+ (string-equal (if destination (format "%s\n" fnnd) "")
+ (buffer-string)))
+ (should-not (get-buffer-window (current-buffer) t))
+ (goto-char (point-max)))
+
+ ;; Second run. The output must be appended.
+ (should (zerop (process-file "ls" nil destination t fnnd)))
+ (with-current-buffer
+ (if (bufferp destination) destination (current-buffer))
+ ;; "ls" could produce colorized output.
+ (goto-char (point-min))
+ (while (re-search-forward
+ tramp-display-escape-sequence-regexp nil t)
+ (replace-match "" nil nil))
+ (should
+ (string-equal
+ (if destination (format "%s\n%s\n" fnnd fnnd) "")
+ (buffer-string))))
- ;; Second run. The output must be appended.
- (goto-char (point-max))
- (should (zerop (process-file "ls" nil t t fnnd)))
- ;; `ls' could produce colorized output.
- (goto-char (point-min))
- (while
- (re-search-forward tramp-display-escape-sequence-regexp nil t)
- (replace-match "" nil nil))
- (should
- (string-equal (format "%s\n%s\n" fnnd fnnd) (buffer-string)))
- ;; A non-nil DISPLAY must not raise the buffer.
- (should-not (get-buffer-window (current-buffer) t))))
+ (unless (eq destination t)
+ (should (string-empty-p (buffer-string))))
+ ;; A non-nil DISPLAY must not raise the buffer.
+ (should-not (get-buffer-window (current-buffer) t))
+ (delete-file tmp-name)))
+
+ ;; Check remote and local INFILE.
+ (dolist (local '(nil t))
+ (with-temp-buffer
+ (setq tmp-name (tramp--test-make-temp-name local quoted))
+ (write-region "foo" nil tmp-name)
+ (should (file-exists-p tmp-name))
+ (should (zerop (process-file "cat" tmp-name t)))
+ (should (string-equal "foo" (buffer-string)))
+ (should-not (get-buffer-window (current-buffer) t))
+ (delete-file tmp-name)))
+
+ ;; Check remote and local DESTNATION file. This isn't
+ ;; implemented yet ina all file name handler backends.
+ ;; (dolist (local '(nil t))
+ ;; (setq tmp-name (tramp--test-make-temp-name local quoted))
+ ;; (should
+ ;; (zerop (process-file "echo" nil `(:file ,tmp-name) nil "foo")))
+ ;; (with-temp-buffer
+ ;; (insert-file-contents tmp-name)
+ ;; (should (string-equal "foo" (buffer-string)))
+ ;; (should-not (get-buffer-window (current-buffer) t))
+ ;; (delete-file tmp-name)))
+
+ ;; Check remote and local STDERR.
+ (dolist (local '(nil t))
+ (setq tmp-name (tramp--test-make-temp-name local quoted))
+ (should-not
+ (zerop
+ (process-file "cat" nil `(t ,tmp-name) nil "/does-not-exist")))
+ (with-temp-buffer
+ (insert-file-contents tmp-name)
+ (should
+ (string-match-p
+ (rx "cat:" (* nonl) " No such file or directory")
+ (buffer-string)))
+ (should-not (get-buffer-window (current-buffer) t))
+ (delete-file tmp-name))))
;; Cleanup.
+ (ignore-errors (kill-buffer buffer))
(ignore-errors (delete-file tmp-name))))))
-(ert-deftest tramp-test27-start-file-process ()
+;; Must be a command, because used as `sigusr1' handler.
+(defun tramp--test-timeout-handler (&rest _ignore)
+ "Timeout handler, reporting a failed test."
+ (interactive)
+ (let ((proc (get-buffer-process (current-buffer))))
+ (when (processp proc)
+ (tramp--test-message
+ "cmd: %s\nbuf:\n%s\n---" (process-command proc) (buffer-string))))
+ (ert-fail (format "`%s' timed out" (ert-test-name (ert-running-test)))))
+
+(ert-deftest tramp-test29-start-file-process ()
"Check `start-file-process'."
- :tags '(:expensive-test)
+ :tags '(:expensive-test :tramp-asynchronous-processes)
(skip-unless (tramp--test-enabled))
- (skip-unless (tramp--test-sh-p))
+ (skip-unless (tramp--test-supports-processes-p))
- (dolist (quoted (if tramp--test-expensive-test '(nil t) '(nil)))
- (let ((default-directory tramp-test-temporary-file-directory)
+ (dolist (quoted (if (tramp--test-expensive-test-p) '(nil t) '(nil)))
+ (let ((default-directory ert-remote-temporary-file-directory)
(tmp-name (tramp--test-make-temp-name nil quoted))
- kill-buffer-query-functions proc)
+ kill-buffer-query-functions command proc)
+
+ ;; Simple process.
(unwind-protect
(with-temp-buffer
- (setq proc (start-file-process "test1" (current-buffer) "cat"))
+ (setq command '("cat")
+ proc
+ (apply #'start-file-process "test1" (current-buffer) command))
(should (processp proc))
(should (equal (process-status proc) 'run))
- (process-send-string proc "foo")
+ (should (equal (process-get proc 'remote-command) command))
+ (process-send-string proc "foo\n")
(process-send-eof proc)
;; Read output.
- (with-timeout (10 (ert-fail "`start-file-process' timed out"))
+ (with-timeout (10 (tramp--test-timeout-handler))
(while (< (- (point-max) (point-min)) (length "foo"))
- (accept-process-output proc 0.1)))
- (should (string-equal (buffer-string) "foo")))
+ (while (accept-process-output proc 0 nil t))))
+ (should (string-match-p "foo" (buffer-string))))
;; Cleanup.
(ignore-errors (delete-process proc)))
+ ;; Simple process using a file.
(unwind-protect
(with-temp-buffer
(write-region "foo" nil tmp-name)
(should (file-exists-p tmp-name))
- (setq proc
- (start-file-process
- "test2" (current-buffer)
- "cat" (file-name-nondirectory tmp-name)))
+ (setq command `("cat" ,(file-name-nondirectory tmp-name))
+ proc
+ (apply #'start-file-process "test2" (current-buffer) command))
(should (processp proc))
+ (should (equal (process-get proc 'remote-command) command))
;; Read output.
- (with-timeout (10 (ert-fail "`start-file-process' timed out"))
+ (with-timeout (10 (tramp--test-timeout-handler))
(while (< (- (point-max) (point-min)) (length "foo"))
- (accept-process-output proc 0.1)))
- (should (string-equal (buffer-string) "foo")))
+ (while (accept-process-output proc 0 nil t))))
+ (should (string-match-p "foo" (buffer-string))))
;; Cleanup.
(ignore-errors
(delete-process proc)
(delete-file tmp-name)))
+ ;; Process filter.
(unwind-protect
(with-temp-buffer
- (setq proc (start-file-process "test3" (current-buffer) "cat"))
+ (setq command '("cat")
+ proc
+ (apply #'start-file-process "test3" (current-buffer) command))
(should (processp proc))
(should (equal (process-status proc) 'run))
+ (should (equal (process-get proc 'remote-command) command))
(set-process-filter
proc
(lambda (p s) (with-current-buffer (process-buffer p) (insert s))))
- (process-send-string proc "foo")
+ (process-send-string proc "foo\n")
(process-send-eof proc)
;; Read output.
- (with-timeout (10 (ert-fail "`start-file-process' timed out"))
+ (with-timeout (10 (tramp--test-timeout-handler))
(while (< (- (point-max) (point-min)) (length "foo"))
- (accept-process-output proc 0.1)))
- (should (string-equal (buffer-string) "foo")))
+ (while (accept-process-output proc 0 nil t))))
+ (should (string-match-p "foo" (buffer-string))))
+
+ ;; Cleanup.
+ (ignore-errors (delete-process proc)))
+
+ ;; Disabled process filter. "sshfs" does not cooperate.
+ (unless (tramp--test-sshfs-p)
+ (unwind-protect
+ (with-temp-buffer
+ (setq command '("cat")
+ proc
+ (apply #'start-file-process "test4" (current-buffer) command))
+ (should (processp proc))
+ (should (equal (process-status proc) 'run))
+ (should (equal (process-get proc 'remote-command) command))
+ (set-process-filter proc t)
+ (process-send-string proc "foo\n")
+ (process-send-eof proc)
+ ;; Read output. There shouldn't be any.
+ (with-timeout (10)
+ (while (process-live-p proc)
+ (while (accept-process-output proc 0 nil t))))
+ ;; No output due to process filter.
+ (should (= (point-min) (point-max))))
+
+ ;; Cleanup.
+ (ignore-errors (delete-process proc))))
+
+ ;; Process connection type.
+ (when (and (tramp--test-sh-p)
+ (not (tramp-direct-async-process-p))
+ ;; `executable-find' has changed the number of
+ ;; parameters in Emacs 27.1, so we use `apply' for
+ ;; older Emacsen.
+ (ignore-errors
+ (with-no-warnings
+ (apply #'executable-find '("hexdump" remote)))))
+ (dolist (process-connection-type '(nil pipe t pty))
+ (unwind-protect
+ (with-temp-buffer
+ (setq command '("hexdump" "-v" "-e" "/1 \"%02X\n\"")
+ proc
+ (apply #'start-file-process
+ (format "test5-%s" process-connection-type)
+ (current-buffer) command))
+ (should (processp proc))
+ (should (equal (process-status proc) 'run))
+ (should (equal (process-get proc 'remote-command) command))
+ (process-send-string proc "foo\r\n")
+ (process-send-eof proc)
+ ;; Read output.
+ (with-timeout (10 (tramp--test-timeout-handler))
+ (while (< (- (point-max) (point-min))
+ (length "66\n6F\n6F\n0D\n0A\n"))
+ (while (accept-process-output proc 0 nil t))))
+ (should
+ (string-match-p
+ (if (and (memq process-connection-type '(nil pipe))
+ (not (tramp--test-macos-p)))
+ ;; On macOS, there is always newline conversion.
+ ;; "telnet" converts \r to <CR><NUL> if `crlf'
+ ;; flag is FALSE. See telnet(1) man page.
+ (rx "66\n6F\n6F\n0D" (? "\n00") "\n0A\n")
+ (rx "66\n6F\n6F\n0A" (? "\n00") "\n0A\n"))
+ (buffer-string))))
+
+ ;; Cleanup.
+ (ignore-errors (delete-process proc)))))
+
+ ;; PTY.
+ (unwind-protect
+ (with-temp-buffer
+ ;; It works only for tramp-sh.el, and not direct async processes.
+ (if (or (not (tramp--test-sh-p)) (tramp-direct-async-process-p))
+ (should-error
+ (start-file-process "test6" (current-buffer) nil)
+ :type 'wrong-type-argument)
+
+ (setq proc (start-file-process "test6" (current-buffer) nil))
+ (should (processp proc))
+ (should (equal (process-status proc) 'run))
+ (should-not (process-get proc 'remote-command))
+ ;; On MS Windows, `process-tty-name' returns nil.
+ (unless (tramp--test-windows-nt-p)
+ (should (stringp (process-tty-name proc))))))
;; Cleanup.
(ignore-errors (delete-process proc))))))
-(ert-deftest tramp-test28-interrupt-process ()
+(defmacro tramp--test-deftest-direct-async-process (test &optional unstable)
+ "Define ert test `TEST-direct-async' for direct async processes.
+If UNSTABLE is non-nil, the test is tagged as `:unstable'."
+ (declare (indent 1))
+ ;; `make-process' supports file name handlers since Emacs 27. We
+ ;; cannot use `tramp--test-always' during compilation of the macro.
+ (when (let ((file-name-handler-alist '(("" . (lambda (&rest _) t)))))
+ (ignore-errors (make-process :file-handler t)))
+ `(ert-deftest ,(intern (concat (symbol-name test) "-direct-async")) ()
+ ;; This is the docstring. However, it must be expanded to a
+ ;; string inside the macro. No idea.
+ ;; (concat (ert-test-documentation (get ',test 'ert--test))
+ ;; "\nUse direct async process.")
+ :tags (append '(:expensive-test :tramp-asynchronous-processes)
+ (and ,unstable '(:unstable)))
+ (skip-unless (tramp--test-enabled))
+ (let ((default-directory ert-remote-temporary-file-directory)
+ (ert-test (ert-get-test ',test))
+ (tramp-connection-properties
+ (cons '(nil "direct-async-process" t)
+ tramp-connection-properties)))
+ (skip-unless (tramp-direct-async-process-p))
+ ;; We do expect an established connection already,
+ ;; `file-truename' does it by side-effect. Suppress
+ ;; `tramp--test-enabled', in order to keep the connection.
+ ;; Suppress "Process ... finished" messages.
+ (cl-letf (((symbol-function #'tramp--test-enabled) #'tramp--test-always)
+ ((symbol-function #'internal-default-process-sentinel)
+ #'ignore))
+ (file-truename ert-remote-temporary-file-directory)
+ (funcall (ert-test-body ert-test)))))))
+
+(tramp--test-deftest-direct-async-process tramp-test29-start-file-process)
+
+(ert-deftest tramp-test30-make-process ()
+ "Check `make-process'."
+ :tags (append '(:expensive-test :tramp-asynchronous-processes)
+ (and (getenv "EMACS_EMBA_CI")
+ '(:unstable)))
+ (skip-unless (tramp--test-enabled))
+ (skip-unless (tramp--test-supports-processes-p))
+ ;; `make-process' supports file name handlers since Emacs 27.
+ (skip-unless (tramp--test-emacs27-p))
+
+ (dolist (quoted (if (tramp--test-expensive-test-p) '(nil t) '(nil)))
+ (let ((default-directory ert-remote-temporary-file-directory)
+ (tmp-name (tramp--test-make-temp-name nil quoted))
+ kill-buffer-query-functions command proc)
+ (with-no-warnings (should-not (make-process)))
+
+ ;; Simple process.
+ (unwind-protect
+ (with-temp-buffer
+ (setq command '("cat")
+ proc
+ (with-no-warnings
+ (make-process
+ :name "test1" :buffer (current-buffer) :command command
+ :file-handler t)))
+ (should (processp proc))
+ (should (equal (process-status proc) 'run))
+ (should (equal (process-get proc 'remote-command) command))
+ (process-send-string proc "foo\n")
+ (process-send-eof proc)
+ ;; Read output.
+ (with-timeout (10 (tramp--test-timeout-handler))
+ (while (< (- (point-max) (point-min)) (length "foo"))
+ (while (accept-process-output proc 0 nil t))))
+ (should (string-match-p "foo" (buffer-string))))
+
+ ;; Cleanup.
+ (ignore-errors (delete-process proc)))
+
+ ;; Simple process using a file.
+ (unwind-protect
+ (with-temp-buffer
+ (write-region "foo" nil tmp-name)
+ (should (file-exists-p tmp-name))
+ (setq command `("cat" ,(file-name-nondirectory tmp-name))
+ proc
+ (with-no-warnings
+ (make-process
+ :name "test2" :buffer (current-buffer) :command command
+ :file-handler t)))
+ (should (processp proc))
+ (should (equal (process-get proc 'remote-command) command))
+ ;; Read output.
+ (with-timeout (10 (tramp--test-timeout-handler))
+ (while (< (- (point-max) (point-min)) (length "foo"))
+ (while (accept-process-output proc 0 nil t))))
+ (should (string-match-p "foo" (buffer-string))))
+
+ ;; Cleanup.
+ (ignore-errors
+ (delete-process proc)
+ (delete-file tmp-name)))
+
+ ;; Process filter.
+ (unwind-protect
+ (with-temp-buffer
+ (setq command '("cat")
+ proc
+ (with-no-warnings
+ (make-process
+ :name "test3" :buffer (current-buffer) :command command
+ :filter
+ (lambda (p s)
+ (with-current-buffer (process-buffer p) (insert s)))
+ :file-handler t)))
+ (should (processp proc))
+ (should (equal (process-status proc) 'run))
+ (should (equal (process-get proc 'remote-command) command))
+ (process-send-string proc "foo\n")
+ (process-send-eof proc)
+ ;; Read output.
+ (with-timeout (10 (tramp--test-timeout-handler))
+ (while (not (string-match-p "foo" (buffer-string)))
+ (while (accept-process-output proc 0 nil t))))
+ (should (string-match-p "foo" (buffer-string))))
+
+ ;; Cleanup.
+ (ignore-errors (delete-process proc)))
+
+ ;; Disabled process filter. "sshfs" does not cooperate.
+ (unless (tramp--test-sshfs-p)
+ (unwind-protect
+ (with-temp-buffer
+ (setq command '("cat")
+ proc
+ (with-no-warnings
+ (make-process
+ :name "test4" :buffer (current-buffer) :command command
+ :filter t
+ :file-handler t)))
+ (should (processp proc))
+ (should (equal (process-status proc) 'run))
+ (should (equal (process-get proc 'remote-command) command))
+ (process-send-string proc "foo\n")
+ (process-send-eof proc)
+ ;; Read output. There shouldn't be any.
+ (with-timeout (10)
+ (while (process-live-p proc)
+ (while (accept-process-output proc 0 nil t))))
+ ;; No output due to process filter.
+ (should (= (point-min) (point-max))))
+
+ ;; Cleanup.
+ (ignore-errors (delete-process proc))))
+
+ ;; Process sentinel.
+ (unwind-protect
+ (with-temp-buffer
+ (setq command '("cat")
+ proc
+ (with-no-warnings
+ (make-process
+ :name "test5" :buffer (current-buffer) :command command
+ :sentinel
+ (lambda (p s)
+ (with-current-buffer (process-buffer p) (insert s)))
+ :file-handler t)))
+ (should (processp proc))
+ (should (equal (process-status proc) 'run))
+ (should (equal (process-get proc 'remote-command) command))
+ (process-send-string proc "foo\n")
+ (process-send-eof proc)
+ (delete-process proc)
+ ;; Read output.
+ (with-timeout (10 (tramp--test-timeout-handler))
+ (while (accept-process-output proc 0 nil t)))
+ ;; On some MS Windows systems, it returns "unknown signal".
+ (should
+ (string-match-p
+ (rx (| "unknown signal" "killed")) (buffer-string))))
+
+ ;; Cleanup.
+ (ignore-errors (delete-process proc)))
+
+ ;; Process with stderr buffer. "telnet" does not cooperate with
+ ;; three processes.
+ (unless (or (tramp--test-telnet-p) (tramp-direct-async-process-p))
+ (let ((stderr (generate-new-buffer "*stderr*")))
+ (unwind-protect
+ (with-temp-buffer
+ (setq command '("cat" "/does-not-exist")
+ proc
+ (with-no-warnings
+ (make-process
+ :name "test6" :buffer (current-buffer) :command command
+ :stderr stderr
+ :file-handler t)))
+ (should (processp proc))
+ (should (equal (process-get proc 'remote-command) command))
+ ;; Read output.
+ (with-timeout (10 (tramp--test-timeout-handler))
+ (while (accept-process-output proc 0 nil t)))
+ ;; Read stderr.
+ (with-current-buffer stderr
+ (with-timeout (10 (tramp--test-timeout-handler))
+ (while (not (string-match-p
+ "No such file or directory" (buffer-string)))
+ (while (accept-process-output
+ (get-buffer-process stderr) 0 nil t))))
+ (delete-process proc)
+ (should
+ (string-match-p
+ (rx "cat:" (* nonl) " No such file or directory")
+ (buffer-string)))))
+
+ ;; Cleanup.
+ (ignore-errors (delete-process proc))
+ (ignore-errors (kill-buffer stderr)))))
+
+ ;; Process with stderr file.
+ (unless (tramp-direct-async-process-p)
+ (unwind-protect
+ (with-temp-buffer
+ (setq command '("cat" "/does-not-exist")
+ proc
+ (with-no-warnings
+ (make-process
+ :name "test7" :buffer (current-buffer) :command command
+ :stderr tmp-name
+ :file-handler t)))
+ (should (processp proc))
+ (should (equal (process-get proc 'remote-command) command))
+ ;; Read stderr.
+ (with-timeout (10 (tramp--test-timeout-handler))
+ (while (accept-process-output proc nil nil t)))
+ (delete-process proc)
+ (with-temp-buffer
+ (insert-file-contents tmp-name)
+ (should
+ (string-match-p
+ (rx "cat:" (* nonl) " No such file or directory")
+ (buffer-string)))))
+
+ ;; Cleanup.
+ (ignore-errors (delete-process proc))
+ (ignore-errors (delete-file tmp-name))))
+
+ ;; Process connection type.
+ (when (and (tramp--test-sh-p)
+ (not (tramp-direct-async-process-p))
+ ;; `executable-find' has changed the number of
+ ;; parameters in Emacs 27.1, so we use `apply' for
+ ;; older Emacsen.
+ (ignore-errors
+ (with-no-warnings
+ (apply #'executable-find '("hexdump" remote)))))
+ (dolist (connection-type '(nil pipe t pty))
+ ;; `process-connection-type' is taken when
+ ;; `:connection-type' is nil.
+ (dolist (process-connection-type
+ (unless connection-type '(nil pipe t pty)))
+ (unwind-protect
+ (with-temp-buffer
+ (setq command '("hexdump" "-v" "-e" "/1 \"%02X\n\"")
+ proc
+ (with-no-warnings
+ (make-process
+ :name
+ (format "test8-%s-%s"
+ connection-type process-connection-type)
+ :buffer (current-buffer)
+ :connection-type connection-type
+ :command command
+ :file-handler t)))
+ (should (processp proc))
+ (should (equal (process-status proc) 'run))
+ (should (equal (process-get proc 'remote-command) command))
+ (process-send-string proc "foo\r\n")
+ (process-send-eof proc)
+ ;; Read output.
+ (with-timeout (10 (tramp--test-timeout-handler))
+ (while (< (- (point-max) (point-min))
+ (length "66\n6F\n6F\n0D\n0A\n"))
+ (while (accept-process-output proc 0 nil t))))
+ (should
+ (string-match-p
+ (if (and (memq (or connection-type process-connection-type)
+ '(nil pipe))
+ (not (tramp--test-macos-p)))
+ ;; On macOS, there is always newline conversion.
+ ;; "telnet" converts \r to <CR><NUL> if `crlf'
+ ;; flag is FALSE. See telnet(1) man page.
+ (rx "66\n6F\n6F\n0D" (? "\n00") "\n0A\n")
+ (rx "66\n6F\n6F\n0A" (? "\n00") "\n0A\n"))
+ (buffer-string))))
+
+ ;; Cleanup.
+ (ignore-errors (delete-process proc)))))))))
+
+(tramp--test-deftest-direct-async-process tramp-test30-make-process)
+
+(ert-deftest tramp-test31-interrupt-process ()
"Check `interrupt-process'."
- :tags '(:expensive-test)
+ ;; The final `process-live-p' check does not run sufficiently.
+ :tags '(:expensive-test :tramp-asynchronous-processes :unstable)
(skip-unless (tramp--test-enabled))
(skip-unless (tramp--test-sh-p))
- ;; Since Emacs 26.1.
- (skip-unless (boundp 'interrupt-process-functions))
-
- (let ((default-directory tramp-test-temporary-file-directory)
- kill-buffer-query-functions proc)
+ (skip-unless (not (tramp--test-windows-nt-p)))
+ (skip-unless (not (tramp--test-crypt-p)))
+ ;; Since Emacs 27.1.
+ (skip-unless (macrop 'with-connection-local-variables))
+
+ ;; We must use `file-truename' for the temporary directory, in
+ ;; order to establish the connection prior running an asynchronous
+ ;; process.
+ (let ((default-directory (file-truename ert-remote-temporary-file-directory))
+ (delete-exited-processes t)
+ kill-buffer-query-functions command proc)
(unwind-protect
(with-temp-buffer
- (setq proc (start-file-process "test" (current-buffer) "sleep" "10"))
+ (setq command "trap 'echo boom; exit 1' 2; sleep 100"
+ proc (start-file-process-shell-command
+ "test" (current-buffer) command))
(should (processp proc))
(should (process-live-p proc))
(should (equal (process-status proc) 'run))
(should (numberp (process-get proc 'remote-pid)))
+ (should (equal (process-get proc 'remote-command)
+ (with-connection-local-variables
+ `(,shell-file-name ,shell-command-switch ,command))))
(should (interrupt-process proc))
;; Let the process accept the interrupt.
- (accept-process-output proc 1 nil 0)
+ (with-timeout (10 (tramp--test-timeout-handler))
+ (while (process-live-p proc)
+ (while (accept-process-output proc 0 nil t))))
(should-not (process-live-p proc))
;; An interrupted process cannot be interrupted, again.
- (should-error (interrupt-process proc) :type 'error))
+ (should-error
+ (interrupt-process proc)
+ :type 'error))
;; Cleanup.
(ignore-errors (delete-process proc)))))
-(ert-deftest tramp-test29-shell-command ()
- "Check `shell-command'."
- :tags '(:expensive-test)
+(ert-deftest tramp-test31-signal-process ()
+ "Check `signal-process'."
+ ;; The final `process-live-p' check does not run sufficiently.
+ :tags '(:expensive-test :tramp-asynchronous-processes :unstable)
(skip-unless (tramp--test-enabled))
(skip-unless (tramp--test-sh-p))
-
- (dolist (quoted (if tramp--test-expensive-test '(nil t) '(nil)))
- (let ((tmp-name (tramp--test-make-temp-name nil quoted))
- (default-directory tramp-test-temporary-file-directory)
- ;; Suppress nasty messages.
- (inhibit-message t)
- kill-buffer-query-functions)
+ (skip-unless (not (tramp--test-windows-nt-p)))
+ (skip-unless (not (tramp--test-crypt-p)))
+ ;; Since Emacs 27.1.
+ (skip-unless (macrop 'with-connection-local-variables))
+ ;; Since Emacs 29.1.
+ (skip-unless (boundp 'signal-process-functions))
+
+ ;; We must use `file-truename' for the temporary directory, in
+ ;; order to establish the connection prior running an asynchronous
+ ;; process.
+ (let ((default-directory (file-truename ert-remote-temporary-file-directory))
+ (delete-exited-processes t)
+ kill-buffer-query-functions command proc)
+
+ (dolist (sigcode '(2 INT))
(unwind-protect
(with-temp-buffer
- (write-region "foo" nil tmp-name)
- (should (file-exists-p tmp-name))
- (shell-command
- (format "ls %s" (file-name-nondirectory tmp-name))
- (current-buffer))
- ;; `ls' could produce colorized output.
- (goto-char (point-min))
- (while
- (re-search-forward tramp-display-escape-sequence-regexp nil t)
- (replace-match "" nil nil))
- (should
- (string-equal
- (format "%s\n" (file-name-nondirectory tmp-name))
- (buffer-string))))
+ (setq command "trap 'echo boom; exit 1' 2; sleep 100"
+ proc (start-file-process-shell-command
+ (format "test1%s" sigcode) (current-buffer) command))
+ (should (processp proc))
+ (should (process-live-p proc))
+ (should (equal (process-status proc) 'run))
+ (should (numberp (process-get proc 'remote-pid)))
+ (should (equal (process-get proc 'remote-command)
+ (with-connection-local-variables
+ `(,shell-file-name ,shell-command-switch ,command))))
+ (should (zerop (signal-process proc sigcode)))
+ ;; Let the process accept the signal.
+ (with-timeout (10 (tramp--test-timeout-handler))
+ (while (accept-process-output proc 0 nil t)))
+ (should-not (process-live-p proc)))
- ;; Cleanup.
- (ignore-errors (delete-file tmp-name)))
+ ;; Cleanup.
+ (ignore-errors (kill-process proc))
+ (ignore-errors (delete-process proc)))
(unwind-protect
(with-temp-buffer
- (write-region "foo" nil tmp-name)
- (should (file-exists-p tmp-name))
- (async-shell-command
- (format "ls %s" (file-name-nondirectory tmp-name))
- (current-buffer))
- ;; Read output.
- (with-timeout (10 (ert-fail "`async-shell-command' timed out"))
- (while (< (- (point-max) (point-min))
- (1+ (length (file-name-nondirectory tmp-name))))
- (accept-process-output
- (get-buffer-process (current-buffer)) 0.1)))
- ;; `ls' could produce colorized output.
- (goto-char (point-min))
- (while
- (re-search-forward tramp-display-escape-sequence-regexp nil t)
- (replace-match "" nil nil))
- ;; There might be a nasty "Process *Async Shell* finished" message.
- (goto-char (point-min))
- (forward-line)
- (narrow-to-region (point-min) (point))
- (should
- (string-equal
- (format "%s\n" (file-name-nondirectory tmp-name))
- (buffer-string))))
+ (setq command "trap 'echo boom; exit 1' 2; sleep 100"
+ proc (start-file-process-shell-command
+ (format "test2%s" sigcode) (current-buffer) command))
+ (should (processp proc))
+ (should (process-live-p proc))
+ (should (equal (process-status proc) 'run))
+ (should (numberp (process-get proc 'remote-pid)))
+ (should (equal (process-get proc 'remote-command)
+ (with-connection-local-variables
+ `(,shell-file-name ,shell-command-switch ,command))))
+ ;; `signal-process' has argument REMOTE since Emacs 29.
+ (with-no-warnings
+ (should
+ (zerop
+ (signal-process
+ (process-get proc 'remote-pid) sigcode default-directory))))
+ ;; Let the process accept the signal.
+ (with-timeout (10 (tramp--test-timeout-handler))
+ (while (accept-process-output proc 0 nil t)))
+ (should-not (process-live-p proc)))
- ;; Cleanup.
- (ignore-errors (delete-file tmp-name)))
+ ;; Cleanup.
+ (ignore-errors (kill-process proc))
+ (ignore-errors (delete-process proc))))))
- (unwind-protect
- (with-temp-buffer
- (write-region "foo" nil tmp-name)
- (should (file-exists-p tmp-name))
- (async-shell-command "read line; ls $line" (current-buffer))
- (process-send-string
- (get-buffer-process (current-buffer))
- (format "%s\n" (file-name-nondirectory tmp-name)))
- ;; Read output.
- (with-timeout (10 (ert-fail "`async-shell-command' timed out"))
- (while (< (- (point-max) (point-min))
- (1+ (length (file-name-nondirectory tmp-name))))
- (accept-process-output
- (get-buffer-process (current-buffer)) 0.1)))
- ;; `ls' could produce colorized output.
- (goto-char (point-min))
- (while
- (re-search-forward tramp-display-escape-sequence-regexp nil t)
- (replace-match "" nil nil))
- ;; There might be a nasty "Process *Async Shell* finished" message.
- (goto-char (point-min))
- (forward-line)
- (narrow-to-region (point-min) (point))
- (should
- (string-equal
- (format "%s\n" (file-name-nondirectory tmp-name))
- (buffer-string))))
+(ert-deftest tramp-test31-list-system-processes ()
+ "Check `list-system-processes'."
+ :tags '(:expensive-test)
+ (skip-unless (tramp--test-enabled))
+ (skip-unless (tramp--test-supports-processes-p))
+ ;; `list-system-processes' is supported since Emacs 29.1.
+ (skip-unless (tramp--test-emacs29-p))
+
+ (let ((default-directory ert-remote-temporary-file-directory))
+ (skip-unless (consp (list-system-processes)))
+ (should (not (equal (list-system-processes)
+ (let ((default-directory temporary-file-directory))
+ (list-system-processes)))))))
+
+(ert-deftest tramp-test31-process-attributes ()
+ "Check `process-attributes'."
+ :tags '(:expensive-test :tramp-asynchronous-processes)
+ (skip-unless (tramp--test-enabled))
+ (skip-unless (tramp--test-supports-processes-p))
+ ;; `process-attributes' is supported since Emacs 29.1.
+ (skip-unless (tramp--test-emacs29-p))
+
+ ;; We must use `file-truename' for the temporary directory, in
+ ;; order to establish the connection prior running an asynchronous
+ ;; process.
+ (let ((default-directory (file-truename ert-remote-temporary-file-directory))
+ (delete-exited-processes t)
+ kill-buffer-query-functions command proc)
+ (skip-unless (consp (list-system-processes)))
- ;; Cleanup.
- (ignore-errors (delete-file tmp-name))))))
+ (unwind-protect
+ (progn
+ (setq command '("sleep" "100")
+ proc (apply #'start-file-process "test" nil command))
+ (while (accept-process-output proc 0))
+ (when-let ((pid (process-get proc 'remote-pid))
+ (attributes (process-attributes pid)))
+ ;; (tramp--test-message "%s" attributes)
+ (should (equal (cdr (assq 'comm attributes)) (car command)))
+ (should (equal (cdr (assq 'args attributes))
+ (mapconcat #'identity command " ")))))
+
+ ;; Cleanup.
+ (ignore-errors (delete-process proc)))))
+
+(defun tramp--test-async-shell-command
+ (command output-buffer &optional error-buffer input)
+ "Like `async-shell-command', reading the output.
+INPUT, if non-nil, is a string sent to the process."
+ (let ((proc (async-shell-command command output-buffer error-buffer))
+ (delete-exited-processes t))
+ ;; Since Emacs 27.1.
+ (when (macrop 'with-connection-local-variables)
+ (should (equal (process-get proc 'remote-command)
+ (with-connection-local-variables
+ `(,shell-file-name ,shell-command-switch ,command)))))
+ (cl-letf (((symbol-function #'shell-command-sentinel) #'ignore))
+ (when (stringp input)
+ (process-send-string proc input))
+ (with-timeout
+ ((if (getenv "EMACS_EMBA_CI") 30 10) (tramp--test-timeout-handler))
+ (while
+ (or (accept-process-output proc nil nil t) (process-live-p proc))))
+ (accept-process-output proc nil nil t))))
(defun tramp--test-shell-command-to-string-asynchronously (command)
"Like `shell-command-to-string', but for asynchronous processes."
(with-temp-buffer
- (async-shell-command command (current-buffer))
- (with-timeout (10)
- (while (get-buffer-process (current-buffer))
- (accept-process-output (get-buffer-process (current-buffer)) 0.1)))
- (accept-process-output nil 0.1)
+ (tramp--test-async-shell-command command (current-buffer))
(buffer-substring-no-properties (point-min) (point-max))))
+(ert-deftest tramp-test32-shell-command ()
+ "Check `shell-command'."
+ :tags '(:expensive-test)
+ (skip-unless (tramp--test-enabled))
+ (skip-unless (tramp--test-supports-processes-p))
+ ;; Prior Emacs 27, `shell-file-name' was hard coded as "/bin/sh" for
+ ;; remote processes in Emacs. That doesn't work for tramp-adb.el.
+ (when (tramp--test-adb-p)
+ (skip-unless (tramp--test-emacs27-p)))
+
+ (dolist (quoted (if (tramp--test-expensive-test-p) '(nil t) '(nil)))
+ (let ((tmp-name (tramp--test-make-temp-name nil quoted))
+ (default-directory ert-remote-temporary-file-directory)
+ ;; Suppress nasty messages.
+ (inhibit-message t)
+ kill-buffer-query-functions)
+
+ (dolist (this-shell-command
+ (append
+ ;; Synchronously.
+ '(shell-command)
+ ;; Asynchronously.
+ (and (tramp--test-asynchronous-processes-p)
+ '(tramp--test-async-shell-command))))
+
+ ;; Test ordinary `{async-}shell-command'.
+ (unwind-protect
+ (with-temp-buffer
+ (write-region "foo" nil tmp-name)
+ (should (file-exists-p tmp-name))
+ (funcall
+ this-shell-command
+ (format "ls %s" (file-name-nondirectory tmp-name))
+ (current-buffer))
+ ;; "ls" could produce colorized output.
+ (goto-char (point-min))
+ (while
+ (re-search-forward tramp-display-escape-sequence-regexp nil t)
+ (replace-match "" nil nil))
+ (should
+ (string-equal
+ (format "%s\n" (file-name-nondirectory tmp-name))
+ (buffer-string))))
+
+ ;; Cleanup.
+ (ignore-errors (delete-file tmp-name)))
+
+ ;; Test `{async-}shell-command' with error buffer.
+ (unless (tramp-direct-async-process-p)
+ (let ((stderr (generate-new-buffer "*stderr*")))
+ (unwind-protect
+ (with-temp-buffer
+ (funcall
+ this-shell-command
+ "echo foo >&2; echo bar" (current-buffer) stderr)
+ (should (string-equal "bar\n" (buffer-string)))
+ ;; Check stderr.
+ (should
+ (string-equal "foo\n" (tramp-get-buffer-string stderr))))
+
+ ;; Cleanup.
+ (ignore-errors (kill-buffer stderr))))))
+
+ ;; Test sending string to `async-shell-command'.
+ (when (tramp--test-asynchronous-processes-p)
+ (unwind-protect
+ (with-temp-buffer
+ (write-region "foo" nil tmp-name)
+ (should (file-exists-p tmp-name))
+ (tramp--test-async-shell-command
+ "read line; ls $line" (current-buffer) nil
+ ;; String to be sent.
+ (format "%s\n" (file-name-nondirectory tmp-name)))
+ (should
+ (string-equal
+ ;; tramp-adb.el echoes, so we must add the string.
+ (if (and (tramp--test-adb-p)
+ (not (tramp-direct-async-process-p)))
+ (format
+ "%s\n%s\n"
+ (file-name-nondirectory tmp-name)
+ (file-name-nondirectory tmp-name))
+ (format "%s\n" (file-name-nondirectory tmp-name)))
+ (buffer-string))))
+
+ ;; Cleanup.
+ (ignore-errors (delete-file tmp-name))))))
+
+ ;; Test `async-shell-command-width'. It exists since Emacs 26.1,
+ ;; but seems to work since Emacs 27.1 only.
+ (when (and (tramp--test-asynchronous-processes-p)
+ (tramp--test-sh-p) (tramp--test-emacs27-p))
+ (let* ((async-shell-command-width 1024)
+ (default-directory ert-remote-temporary-file-directory)
+ (cols (ignore-errors
+ (read (tramp--test-shell-command-to-string-asynchronously
+ "tput cols")))))
+ (when (natnump cols)
+ (should (= cols async-shell-command-width))))))
+
+(tramp--test-deftest-direct-async-process tramp-test32-shell-command 'unstable)
+
+;; This test is inspired by Bug#39067.
+(ert-deftest tramp-test32-shell-command-dont-erase-buffer ()
+ "Check `shell-command-dont-erase-buffer'."
+ ;; As long as Bug#40896 is not solved both in simple.el and Tramp,
+ ;; this test cannot run properly.
+ :tags '(:expensive-test :unstable)
+ (skip-unless (tramp--test-enabled))
+ (skip-unless nil)
+ (skip-unless (tramp--test-supports-processes-p))
+ ;; Prior Emacs 27, `shell-command-dont-erase-buffer' wasn't working properly.
+ (skip-unless (tramp--test-emacs27-p))
+
+ ;; (message " s-c-d-e-b current-buffer buffer-string point")
+ ;; (message "===============================================")
+
+ ;; s-c-d-e-b current-buffer buffer-string point
+ ;; ===============================================
+ ;; nil t foobazzbar 4 x
+ ;; nil nil bazz 5
+ ;; -----------------------------------------------
+ ;; erase t bazz 1 x
+ ;; erase nil bazz 5
+ ;; -----------------------------------------------
+ ;; beg-last-out t foobazzbar 4 x
+ ;; beg-last-out nil foobarbazz 7
+ ;; -----------------------------------------------
+ ;; end-last-out t foobazzbar 4
+ ;; end-last-out nil foobazzbar 11
+ ;; -----------------------------------------------
+ ;; save-point t foobazzbar 4 x
+ ;; save-point nil foobarbazz 4 x
+ ;; -----------------------------------------------
+ ;; random t foobazzbar 4
+ ;; random nil foobazzbar 11
+ ;; -----------------------------------------------
+
+ (let (;; Suppress nasty messages.
+ (inhibit-message t)
+ buffer kill-buffer-query-functions)
+ ;; We check both the local and remote case, in order to guarantee
+ ;; that they behave similar.
+ (dolist (default-directory
+ `(,temporary-file-directory ,ert-remote-temporary-file-directory))
+ ;; These are the possible values of `shell-command-dont-erase-buffer'.
+ ;; `random' is taken as non-nil value without special meaning.
+ (dolist (shell-command-dont-erase-buffer
+ '(nil erase beg-last-out end-last-out save-point random))
+ ;; `shell-command' might work over the current buffer, or not.
+ (dolist (current '(t nil))
+ (with-temp-buffer
+ ;; We insert the string "foobar" into an empty buffer.
+ ;; Point is set between "foo" and "bar".
+ (setq buffer (current-buffer))
+ (insert "foobar")
+ (goto-char (- (point) 3))
+ (should (string-equal "foobar" (buffer-string)))
+ (should (string-equal "foo" (buffer-substring (point-min) (point))))
+ (should (string-equal "bar" (buffer-substring (point) (point-max))))
+
+ ;; Apply `shell-command'. It shall output the string
+ ;; "bazz". Messages in the *Messages* buffer are
+ ;; suppressed.
+ (let (message-log-max)
+ (if current
+ (shell-command "echo -n bazz" (current-buffer))
+ (with-temp-buffer (shell-command "echo -n bazz" buffer))))
+
+ ;; (message
+ ;; "%12s %14s %13s %5d"
+ ;; shell-command-dont-erase-buffer current (buffer-string) (point))))
+ ;; (message "-----------------------------------------------")))))
+
+ ;; Check result.
+ (cond
+ (current
+ ;; String is inserted at point, and point is preserved
+ ;; unless dictated otherwise.
+ (cond
+ ((null shell-command-dont-erase-buffer)
+ (should (string-equal "foobazzbar" (buffer-string)))
+ (should (= 4 (point))))
+ ((eq shell-command-dont-erase-buffer 'erase)
+ (should (string-equal "bazz" (buffer-string)))
+ (should (= 1 (point))))
+ ((eq shell-command-dont-erase-buffer 'beg-last-out)
+ (should (string-equal "foobazzbar" (buffer-string)))
+ (should (= 4 (point))))
+ ;; Bug#40896
+ ;; ((eq shell-command-dont-erase-buffer 'end-last-out)
+ ;; (should (string-equal "foobazzbar" (buffer-string)))
+ ;; (should (= 7 (point))))
+ ((eq shell-command-dont-erase-buffer 'save-point)
+ (should (string-equal "foobazzbar" (buffer-string)))
+ (should (= 4 (point))))
+ ;; Bug#40896
+ ;; ((eq shell-command-dont-erase-buffer 'random)
+ ;; (should (string-equal "foobazzbar" (buffer-string)))
+ ;; (should (= 7 (point))))))
+ ))
+
+ (t ;; not current buffer
+ ;; String is appended, and point is at point-max unless
+ ;; dictated otherwise.
+ (cond
+ ((null shell-command-dont-erase-buffer)
+ (should (string-equal "bazz" (buffer-string)))
+ (should (= 5 (point))))
+ ((eq shell-command-dont-erase-buffer 'erase)
+ (should (string-equal "bazz" (buffer-string)))
+ (should (= 5 (point))))
+ ((eq shell-command-dont-erase-buffer 'beg-last-out)
+ (should (string-equal "foobarbazz" (buffer-string)))
+ (should (= 7 (point))))
+ ;; ;; Bug#40896
+ ;; ((eq shell-command-dont-erase-buffer 'end-last-out)
+ ;; (should (string-equal "foobarbazz" (buffer-string)))
+ ;; (should (= 11 (point))))
+ ((eq shell-command-dont-erase-buffer 'save-point)
+ (should (string-equal "foobarbazz" (buffer-string)))
+ (should (= 4 (point))))
+ ;; ;; Bug#40896
+ ;; ((eq shell-command-dont-erase-buffer 'random)
+ ;; (should (string-equal "foobarbazz" (buffer-string)))
+ ;; (should (= 11 (point)))))))))))))
+ )))))))))
+
;; This test is inspired by Bug#23952.
-(ert-deftest tramp-test30-environment-variables ()
+(ert-deftest tramp-test33-environment-variables ()
"Check that remote processes set / unset environment variables properly."
:tags '(:expensive-test)
(skip-unless (tramp--test-enabled))
(skip-unless (tramp--test-sh-p))
+ (skip-unless (not (tramp--test-crypt-p)))
(dolist (this-shell-command-to-string
- '(;; Synchronously.
- shell-command-to-string
- ;; Asynchronously.
- tramp--test-shell-command-to-string-asynchronously))
-
- (let ((default-directory tramp-test-temporary-file-directory)
+ (append
+ ;; Synchronously.
+ '(shell-command-to-string)
+ ;; Asynchronously.
+ (and (tramp--test-asynchronous-processes-p)
+ '(tramp--test-shell-command-to-string-asynchronously))))
+
+ (let ((default-directory ert-remote-temporary-file-directory)
(shell-file-name "/bin/sh")
(envvar (concat "VAR_" (upcase (md5 (current-time-string)))))
kill-buffer-query-functions)
- (unwind-protect
- ;; Set a value.
- (let ((process-environment
- (cons (concat envvar "=foo") process-environment)))
- ;; Default value.
- (should
- (string-match
- "foo"
- (funcall
- this-shell-command-to-string
- (format "echo -n ${%s:?bla}" envvar))))))
-
- (unwind-protect
- ;; Set the empty value.
- (let ((process-environment
- (cons (concat envvar "=") process-environment)))
- ;; Value is null.
+ ;; Check INSIDE_EMACS.
+ (setenv "INSIDE_EMACS")
+ (should
+ (string-equal
+ (format "%s,tramp:%s\n" emacs-version tramp-version)
+ (funcall this-shell-command-to-string "echo \"${INSIDE_EMACS:-bla}\"")))
+ (let ((process-environment
+ (cons (format "INSIDE_EMACS=%s,foo" emacs-version)
+ process-environment)))
+ (should
+ (string-equal
+ (format "%s,foo,tramp:%s\n" emacs-version tramp-version)
+ (funcall
+ this-shell-command-to-string "echo \"${INSIDE_EMACS:-bla}\""))))
+
+ ;; Set a value.
+ (let ((process-environment
+ (cons (concat envvar "=foo") process-environment)))
+ ;; Default value.
+ (should
+ (string-match-p
+ "foo"
+ (funcall
+ this-shell-command-to-string
+ (format "echo \"${%s:-bla}\"" envvar)))))
+
+ ;; Set the empty value.
+ (let ((process-environment
+ (cons (concat envvar "=") process-environment)))
+ ;; Value is null.
+ (should
+ (string-match-p
+ "bla"
+ (funcall
+ this-shell-command-to-string (format "echo \"${%s:-bla}\"" envvar))))
+ ;; Variable is set.
+ (should
+ (string-match-p
+ (tramp-compat-rx (literal envvar))
+ (funcall this-shell-command-to-string "set"))))
+
+ (unless (tramp-direct-async-process-p)
+ ;; We force a reconnect, in order to have a clean environment.
+ (tramp-cleanup-connection tramp-test-vec 'keep-debug 'keep-password)
+ ;; Unset the variable.
+ (let ((tramp-remote-process-environment
+ (cons (concat envvar "=foo") tramp-remote-process-environment)))
+ ;; Set the initial value, we want to unset below.
+ (should
+ (string-match-p
+ "foo"
+ (funcall
+ this-shell-command-to-string
+ (format "echo \"${%s:-bla}\"" envvar))))
+ (let ((process-environment (cons envvar process-environment)))
+ ;; Variable is unset.
(should
- (string-match
+ (string-match-p
"bla"
(funcall
this-shell-command-to-string
- (format "echo -n ${%s:?bla}" envvar))))
- ;; Variable is set.
- (should
- (string-match
- (regexp-quote envvar)
- (funcall this-shell-command-to-string "set")))))
-
- ;; We force a reconnect, in order to have a clean environment.
- (tramp-cleanup-connection
- (tramp-dissect-file-name tramp-test-temporary-file-directory)
- 'keep-debug 'keep-password)
- (unwind-protect
- ;; Unset the variable.
- (let ((tramp-remote-process-environment
- (cons (concat envvar "=foo")
- tramp-remote-process-environment)))
- ;; Set the initial value, we want to unset below.
- (should
- (string-match
- "foo"
+ (format "echo \"${%s:-bla}\"" envvar))))
+ ;; Variable is unset.
+ (should-not
+ (string-match-p
+ (tramp-compat-rx (literal envvar))
+ ;; We must remove PS1, the output is truncated otherwise.
+ ;; We must suppress "_=VAR...".
(funcall
this-shell-command-to-string
- (format "echo -n ${%s:?bla}" envvar))))
- (let ((process-environment
- (cons envvar process-environment)))
- ;; Variable is unset.
- (should
- (string-match
- "bla"
- (funcall
- this-shell-command-to-string
- (format "echo -n ${%s:?bla}" envvar))))
- ;; Variable is unset.
- (should-not
- (string-match
- (regexp-quote envvar)
- (funcall this-shell-command-to-string "set")))))))))
+ "printenv | grep -v PS1 | grep -v _=")))))))))
+
+(tramp--test-deftest-direct-async-process tramp-test33-environment-variables)
;; This test is inspired by Bug#27009.
-(ert-deftest tramp-test30-environment-variables-and-port-numbers ()
+(ert-deftest tramp-test33-environment-variables-and-port-numbers ()
"Check that two connections with separate ports are different."
(skip-unless (tramp--test-enabled))
;; We test it only for the mock-up connection; otherwise there might
;; be problems with the used ports.
- (skip-unless
- (and
- (eq tramp-syntax 'default)
- (string-equal
- "mock" (file-remote-p tramp-test-temporary-file-directory 'method))))
+ (skip-unless (and (eq tramp-syntax 'default) (tramp--test-mock-p)))
+ (skip-unless (not (tramp--test-crypt-p)))
;; We force a reconnect, in order to have a clean environment.
- (dolist (dir `(,tramp-test-temporary-file-directory
+ (dolist (dir `(,ert-remote-temporary-file-directory
"/mock:localhost#11111:" "/mock:localhost#22222:"))
(tramp-cleanup-connection
(tramp-dissect-file-name dir) 'keep-debug 'keep-password))
@@ -3419,91 +5761,278 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
(format "%s=%d" envvar port)
tramp-remote-process-environment)))
(should
- (string-equal
+ (string-match-p
(number-to-string port)
- (shell-command-to-string (format "echo -n $%s" envvar))))))
+ (shell-command-to-string (format "echo $%s" envvar))))))
;; Cleanup.
(dolist (dir '("/mock:localhost#11111:" "/mock:localhost#22222:"))
(tramp-cleanup-connection (tramp-dissect-file-name dir)))))
-;; The functions were introduced in Emacs 26.1.
-(ert-deftest tramp-test31-explicit-shell-file-name ()
- "Check that connection-local `explicit-shell-file-name' is set."
+;; Connection-local variables are enabled per default since Emacs 27.1.
+(ert-deftest tramp-test34-connection-local-variables ()
+ "Check that connection-local variables are enabled."
:tags '(:expensive-test)
(skip-unless (tramp--test-enabled))
- (skip-unless (tramp--test-sh-p))
- ;; Since Emacs 26.1.
- (skip-unless (and (fboundp 'connection-local-set-profile-variables)
- (fboundp 'connection-local-set-profiles)))
-
- ;; `connection-local-set-profile-variables' and
- ;; `connection-local-set-profiles' exists since Emacs 26. We don't
- ;; want to see compiler warnings for older Emacsen.
- (let ((default-directory tramp-test-temporary-file-directory)
- explicit-shell-file-name kill-buffer-query-functions)
+ ;; Since Emacs 27.1.
+ (skip-unless (macrop 'with-connection-local-variables))
+
+ (let* ((default-directory ert-remote-temporary-file-directory)
+ (tmp-name1 (tramp--test-make-temp-name))
+ (tmp-name2 (expand-file-name "foo" tmp-name1))
+ (enable-local-variables :all)
+ (enable-remote-dir-locals t)
+ (inhibit-message t)
+ kill-buffer-query-functions
+ connection-local-profile-alist connection-local-criteria-alist)
+ (unwind-protect
+ (progn
+ (make-directory tmp-name1)
+ (should (file-directory-p tmp-name1))
+
+ ;; `local-variable' is buffer-local due to explicit setting.
+ ;; We need `with-no-warnings', because `defvar-local' is not
+ ;; called at toplevel.
+ (with-no-warnings
+ (defvar-local local-variable 'buffer))
+ (with-temp-buffer
+ (should (eq local-variable 'buffer)))
+
+ ;; `local-variable' is connection-local due to Tramp.
+ (write-region "foo" nil tmp-name2)
+ (should (file-exists-p tmp-name2))
+ (connection-local-set-profile-variables
+ 'local-variable-profile
+ '((local-variable . connect)))
+ (connection-local-set-profiles
+ `(:application tramp
+ :protocol ,(file-remote-p default-directory 'method)
+ :user ,(file-remote-p default-directory 'user)
+ :machine ,(file-remote-p default-directory 'host))
+ 'local-variable-profile)
+ (with-current-buffer (find-file-noselect tmp-name2)
+ (should (eq local-variable 'connect))
+ (kill-buffer (current-buffer)))
+
+ ;; `local-variable' is dir-local due to existence of .dir-locals.el.
+ (write-region
+ "((nil . ((local-variable . dir))))" nil
+ (expand-file-name ".dir-locals.el" tmp-name1))
+ (should (file-exists-p (expand-file-name ".dir-locals.el" tmp-name1)))
+ (with-current-buffer (find-file-noselect tmp-name2)
+ (should (eq local-variable 'dir))
+ (kill-buffer (current-buffer)))
+
+ ;; `local-variable' is file-local due to specifying as file variable.
+ (write-region
+ "-*- mode: comint; local-variable: file; -*-" nil tmp-name2)
+ (should (file-exists-p tmp-name2))
+ (with-current-buffer (find-file-noselect tmp-name2)
+ (should (eq local-variable 'file))
+ (kill-buffer (current-buffer))))
+
+ ;; Cleanup.
+ (ignore-errors (delete-directory tmp-name1 'recursive)))))
+
+(ert-deftest tramp-test34-explicit-shell-file-name ()
+ "Check that connection-local `explicit-shell-file-name' is set."
+ :tags '(:expensive-test :tramp-asynchronous-processes)
+ (skip-unless (tramp--test-enabled))
+ (skip-unless (tramp--test-supports-processes-p))
+ ;; Prior Emacs 27, `shell-file-name' was hard coded as "/bin/sh" for
+ ;; remote processes in Emacs. That doesn't work for tramp-adb.el.
+ (when (tramp--test-adb-p)
+ (skip-unless (tramp--test-emacs27-p)))
+
+ (let ((default-directory ert-remote-temporary-file-directory)
+ explicit-shell-file-name kill-buffer-query-functions
+ connection-local-profile-alist connection-local-criteria-alist)
(unwind-protect
(progn
;; `shell-mode' would ruin our test, because it deletes all
- ;; buffer local variables.
+ ;; buffer local variables. Not needed in Emacs 27.1.
(put 'explicit-shell-file-name 'permanent-local t)
- ;; Declare connection-local variable `explicit-shell-file-name'.
- (with-no-warnings
- (connection-local-set-profile-variables
- 'remote-sh
- '((explicit-shell-file-name . "/bin/sh")
- (explicit-sh-args . ("-i"))))
- (connection-local-set-profiles
- `(:application tramp
- :protocol ,(file-remote-p default-directory 'method)
- :user ,(file-remote-p default-directory 'user)
- :machine ,(file-remote-p default-directory 'host))
- 'remote-sh))
-
- ;; Run interactive shell. Since the default directory is
- ;; remote, `explicit-shell-file-name' shall be set in order
- ;; to avoid a question.
+ (connection-local-set-profile-variables
+ 'remote-sh
+ `((explicit-shell-file-name . ,(tramp--test-shell-file-name))
+ (explicit-sh-args . ("-c" "echo foo"))))
+ (connection-local-set-profiles
+ `(:application tramp
+ :protocol ,(file-remote-p default-directory 'method)
+ :user ,(file-remote-p default-directory 'user)
+ :machine ,(file-remote-p default-directory 'host))
+ 'remote-sh)
+ (put 'explicit-shell-file-name 'safe-local-variable #'identity)
+ (put 'explicit-sh-args 'safe-local-variable #'identity)
+
+ ;; Run `shell' interactively. Since the default directory
+ ;; is remote, `explicit-shell-file-name' shall be set in
+ ;; order to avoid a question. `explicit-sh-args' echoes the
+ ;; test data.
(with-current-buffer (get-buffer-create "*shell*")
- (ignore-errors (kill-process (current-buffer)))
+ (ignore-errors (kill-process (get-buffer-process (current-buffer))))
(should-not explicit-shell-file-name)
- (call-interactively 'shell)
- (should explicit-shell-file-name)))
+ (call-interactively #'shell)
+ (with-timeout (10)
+ (while (accept-process-output
+ (get-buffer-process (current-buffer)) nil nil t)))
+ (should (string-match-p (rx bol "foo" eol) (buffer-string)))))
+ ;; Cleanup.
(put 'explicit-shell-file-name 'permanent-local nil)
(kill-buffer "*shell*"))))
-(ert-deftest tramp-test32-vc-registered ()
+;; `exec-path' was introduced in Emacs 27.1. `executable-find' has
+;; changed the number of parameters, so we use `apply' for older
+;; Emacsen.
+(ert-deftest tramp-test35-exec-path ()
+ "Check `exec-path' and `executable-find'."
+ (skip-unless (tramp--test-enabled))
+ (skip-unless (tramp--test-supports-processes-p))
+ (skip-unless (tramp--test-supports-set-file-modes-p))
+ ;; Since Emacs 27.1.
+ (skip-unless (fboundp 'exec-path))
+
+ (let ((tmp-name (tramp--test-make-temp-name))
+ (default-directory ert-remote-temporary-file-directory))
+ (unwind-protect
+ (progn
+ (should (consp (with-no-warnings (exec-path))))
+ ;; Last element is the `exec-directory'.
+ (should
+ (string-equal
+ (car (last (with-no-warnings (exec-path))))
+ (file-remote-p default-directory 'localname)))
+ ;; The shell "sh" shall always exist.
+ (should (apply #'executable-find '("sh" remote)))
+ ;; Since the last element in `exec-path' is the current
+ ;; directory, an executable file in that directory will be
+ ;; found.
+ (write-region "foo" nil tmp-name)
+ (should (file-exists-p tmp-name))
+
+ (set-file-modes tmp-name #o777)
+ (should (file-executable-p tmp-name))
+ (should
+ (string-equal
+ (apply
+ #'executable-find `(,(file-name-nondirectory tmp-name) remote))
+ (file-remote-p tmp-name 'localname)))
+ (should-not
+ (apply
+ #'executable-find
+ `(,(concat (file-name-nondirectory tmp-name) "foo") remote))))
+
+ ;; Cleanup.
+ (ignore-errors (delete-file tmp-name)))))
+
+;; This test is inspired by Bug#33781.
+;; `exec-path' was introduced in Emacs 27.1. `executable-find' has
+;; changed the number of parameters, so we use `apply' for older
+;; Emacsen.
+(ert-deftest tramp-test35-remote-path ()
+ "Check loooong `tramp-remote-path'."
+ (skip-unless (tramp--test-enabled))
+ (skip-unless (tramp--test-sh-p))
+ (skip-unless (not (tramp--test-crypt-p)))
+ ;; Since Emacs 27.1.
+ (skip-unless (fboundp 'exec-path))
+
+ (let* ((tmp-name (tramp--test-make-temp-name))
+ (default-directory ert-remote-temporary-file-directory)
+ (orig-exec-path (with-no-warnings (exec-path)))
+ (tramp-remote-path tramp-remote-path)
+ (orig-tramp-remote-path tramp-remote-path)
+ path)
+ (unwind-protect
+ (progn
+ ;; Non existing directories are removed.
+ (setq tramp-remote-path
+ (cons (file-remote-p tmp-name 'localname) tramp-remote-path))
+ (tramp-cleanup-connection tramp-test-vec 'keep-debug 'keep-password)
+ (should (equal (with-no-warnings (exec-path)) orig-exec-path))
+ (setq tramp-remote-path orig-tramp-remote-path)
+
+ ;; Double entries are removed.
+ (setq tramp-remote-path (append '("/" "/") tramp-remote-path))
+ (tramp-cleanup-connection tramp-test-vec 'keep-debug 'keep-password)
+ (should
+ (equal (with-no-warnings (exec-path)) (cons "/" orig-exec-path)))
+ (setq tramp-remote-path orig-tramp-remote-path)
+
+ ;; We make a super long `tramp-remote-path'.
+ (make-directory tmp-name)
+ (should (file-directory-p tmp-name))
+ (while (< (length (mapconcat #'identity orig-exec-path ":")) 5000)
+ (let ((dir (make-temp-file (file-name-as-directory tmp-name) 'dir)))
+ (should (file-directory-p dir))
+ (setq tramp-remote-path
+ (append
+ tramp-remote-path `(,(file-remote-p dir 'localname)))
+ orig-exec-path
+ (append
+ (butlast orig-exec-path)
+ `(,(file-remote-p dir 'localname))
+ (last orig-exec-path)))))
+ (tramp-cleanup-connection tramp-test-vec 'keep-debug 'keep-password)
+ (should (equal (with-no-warnings (exec-path)) orig-exec-path))
+ ;; Ignore trailing newline.
+ (setq path (substring (shell-command-to-string "echo $PATH") nil -1))
+ ;; The shell doesn't handle such long strings.
+ (when (<= (length path)
+ (tramp-get-connection-property
+ tramp-test-vec "pipe-buf" 4096))
+ ;; The last element of `exec-path' is `exec-directory'.
+ (should
+ (string-equal
+ path (mapconcat #'identity (butlast orig-exec-path) ":"))))
+ ;; The shell "sh" shall always exist.
+ (should (apply #'executable-find '("sh" remote))))
+
+ ;; Cleanup.
+ (tramp-cleanup-connection tramp-test-vec 'keep-debug 'keep-password)
+ (setq tramp-remote-path orig-tramp-remote-path)
+ (ignore-errors (delete-directory tmp-name 'recursive)))))
+
+(ert-deftest tramp-test36-vc-registered ()
"Check `vc-registered'."
:tags '(:expensive-test)
(skip-unless (tramp--test-enabled))
(skip-unless (tramp--test-sh-p))
-
- (dolist (quoted (if tramp--test-expensive-test '(nil t) '(nil)))
- (let* ((default-directory tramp-test-temporary-file-directory)
+ (skip-unless (not (tramp--test-crypt-p)))
+
+ (dolist (quoted (if (tramp--test-expensive-test-p) '(nil t) '(nil)))
+ ;; We must use `file-truename' for the temporary directory, in
+ ;; order to establish the connection prior running an asynchronous
+ ;; process.
+ (let* ((default-directory
+ (file-truename ert-remote-temporary-file-directory))
(tmp-name1 (tramp--test-make-temp-name nil quoted))
(tmp-name2 (expand-file-name "foo" tmp-name1))
(tramp-remote-process-environment tramp-remote-process-environment)
+ (inhibit-message t)
(vc-handled-backends
- (with-parsed-tramp-file-name tramp-test-temporary-file-directory nil
- (cond
- ((tramp-find-executable
- v vc-git-program (tramp-get-remote-path v))
- '(Git))
- ((tramp-find-executable
- v vc-hg-program (tramp-get-remote-path v))
- '(Hg))
- ((tramp-find-executable
- v vc-bzr-program (tramp-get-remote-path v))
- (setq tramp-remote-process-environment
- (cons (format "BZR_HOME=%s"
- (file-remote-p tmp-name1 'localname))
- tramp-remote-process-environment))
- ;; We must force a reconnect, in order to activate $BZR_HOME.
- (tramp-cleanup-connection
- (tramp-dissect-file-name tramp-test-temporary-file-directory)
- 'keep-debug 'keep-password)
- '(Bzr))
- (t nil))))
+ (cond
+ ((tramp-find-executable
+ tramp-test-vec vc-git-program
+ (tramp-get-remote-path tramp-test-vec))
+ '(Git))
+ ((tramp-find-executable
+ tramp-test-vec vc-hg-program
+ (tramp-get-remote-path tramp-test-vec))
+ '(Hg))
+ ((tramp-find-executable
+ tramp-test-vec vc-bzr-program
+ (tramp-get-remote-path tramp-test-vec))
+ (setq tramp-remote-process-environment
+ (cons (format "BZR_HOME=%s"
+ (file-remote-p tmp-name1 'localname))
+ tramp-remote-process-environment))
+ ;; We must force a reconnect, in order to activate $BZR_HOME.
+ (tramp-cleanup-connection
+ tramp-test-vec 'keep-debug 'keep-password)
+ '(Bzr))
+ (t nil)))
;; Suppress nasty messages.
(inhibit-message t))
(skip-unless vc-handled-backends)
@@ -3524,18 +6053,12 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
;; skip the test then.
(condition-case nil
(vc-create-repo (car vc-handled-backends))
- (error (skip-unless nil)))
+ (error (ert-skip "`vc-create-repo' not supported")))
;; The structure of VC-FILESET is not documented. Let's
;; hope it won't change.
- (condition-case nil
- (vc-register
- (list (car vc-handled-backends)
- (list (file-name-nondirectory tmp-name2))))
- ;; `vc-register' has changed its arguments in Emacs 25.1.
- (error
- (vc-register
- nil (list (car vc-handled-backends)
- (list (file-name-nondirectory tmp-name2))))))
+ (vc-register
+ (list (car vc-handled-backends)
+ (list (file-name-nondirectory tmp-name2))))
;; vc-git uses an own process sentinel, Tramp's sentinel
;; for flushing the cache isn't used.
(dired-uncache (concat (file-remote-p default-directory) "/"))
@@ -3544,34 +6067,37 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
;; Cleanup.
(ignore-errors (delete-directory tmp-name1 'recursive))))))
-(ert-deftest tramp-test33-make-auto-save-file-name ()
+(ert-deftest tramp-test37-make-auto-save-file-name ()
"Check `make-auto-save-file-name'."
(skip-unless (tramp--test-enabled))
- (dolist (quoted (if tramp--test-expensive-test '(nil t) '(nil)))
+ (dolist (quoted (if (tramp--test-expensive-test-p) '(nil t) '(nil)))
(let ((tmp-name1 (tramp--test-make-temp-name nil quoted))
- (tmp-name2 (tramp--test-make-temp-name nil quoted)))
+ (tmp-name2 (tramp--test-make-temp-name nil quoted))
+ tramp-allow-unsafe-temporary-files)
(unwind-protect
(progn
;; Use default `auto-save-file-name-transforms' mechanism.
- (let (tramp-auto-save-directory)
- (with-temp-buffer
- (setq buffer-file-name tmp-name1)
- (should
- (string-equal
- (make-auto-save-file-name)
- ;; This is taken from original `make-auto-save-file-name'.
- ;; We call `convert-standard-filename', because on
- ;; MS Windows the (local) colons must be replaced by
- ;; exclamation marks.
- (convert-standard-filename
- (expand-file-name
- (format
- "#%s#"
- (subst-char-in-string
- ?/ ?! (replace-regexp-in-string "!" "!!" tmp-name1)))
- temporary-file-directory))))))
+ ;; It isn't prepared for `separate' syntax.
+ (unless (eq tramp-syntax 'separate)
+ (let (tramp-auto-save-directory)
+ (with-temp-buffer
+ (setq buffer-file-name tmp-name1)
+ (should
+ (string-equal
+ (make-auto-save-file-name)
+ ;; This is taken from original `make-auto-save-file-name'.
+ ;; We call `convert-standard-filename', because on
+ ;; MS Windows the (local) colons must be replaced by
+ ;; exclamation marks.
+ (convert-standard-filename
+ (expand-file-name
+ (format
+ "#%s#"
+ (subst-char-in-string
+ ?/ ?! (replace-regexp-in-string "!" "!!" tmp-name1)))
+ temporary-file-directory)))))))
;; No mapping.
(let (tramp-auto-save-directory auto-save-file-name-transforms)
@@ -3581,85 +6107,460 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
(string-equal
(make-auto-save-file-name)
(funcall
- (if quoted 'tramp-compat-file-name-quote 'identity)
+ (if quoted #'tramp-compat-file-name-quote #'identity)
(expand-file-name
(format "#%s#" (file-name-nondirectory tmp-name1))
- tramp-test-temporary-file-directory))))))
+ ert-remote-temporary-file-directory))))))
- ;; TODO: The following two cases don't work yet.
- (when nil
;; Use default `tramp-auto-save-directory' mechanism.
- (let ((tramp-auto-save-directory tmp-name2))
- (with-temp-buffer
- (setq buffer-file-name tmp-name1)
- (should
- (string-equal
- (make-auto-save-file-name)
- ;; This is taken from Tramp.
+ ;; Ange-FTP doesn't care.
+ (unless (tramp--test-ange-ftp-p)
+ (let ((tramp-auto-save-directory tmp-name2))
+ (with-temp-buffer
+ (setq buffer-file-name tmp-name1)
+ (should
+ (string-equal
+ (make-auto-save-file-name)
+ ;; This is taken from Tramp.
+ (expand-file-name
+ (format
+ "#%s#"
+ (tramp-subst-strs-in-string
+ '(("_" . "|")
+ ("/" . "_a")
+ (":" . "_b")
+ ("|" . "__")
+ ("[" . "_l")
+ ("]" . "_r"))
+ (tramp-compat-file-name-unquote tmp-name1)))
+ tmp-name2)))
+ (should (file-directory-p tmp-name2)))))
+
+ ;; Relative file names shall work, too. Ange-FTP doesn't care.
+ (unless (tramp--test-ange-ftp-p)
+ (let ((tramp-auto-save-directory "."))
+ (with-temp-buffer
+ (setq buffer-file-name tmp-name1
+ default-directory tmp-name2)
+ (should
+ (string-equal
+ (make-auto-save-file-name)
+ ;; This is taken from Tramp.
+ (expand-file-name
+ (format
+ "#%s#"
+ (tramp-subst-strs-in-string
+ '(("_" . "|")
+ ("/" . "_a")
+ (":" . "_b")
+ ("|" . "__")
+ ("[" . "_l")
+ ("]" . "_r"))
+ (tramp-compat-file-name-unquote tmp-name1)))
+ tmp-name2)))
+ (should (file-directory-p tmp-name2)))))
+
+ ;; Create temporary file. This shall check for sensible
+ ;; files, owned by root.
+ (let ((tramp-auto-save-directory temporary-file-directory))
+ (write-region "foo" nil tmp-name1)
+ (when (zerop (or (file-attribute-user-id
+ (file-attributes tmp-name1))
+ tramp-unknown-id-integer))
+ (with-temp-buffer
+ (setq buffer-file-name tmp-name1)
+ (tramp-cleanup-connection
+ tramp-test-vec 'keep-debug 'keep-password)
+ (let ((tramp-allow-unsafe-temporary-files t))
+ (should (stringp (make-auto-save-file-name))))
+ (tramp-cleanup-connection
+ tramp-test-vec 'keep-debug 'keep-password)
+ (cl-letf (((symbol-function #'yes-or-no-p) #'ignore))
+ (should-error
+ (make-auto-save-file-name)
+ :type 'file-error))
+ (tramp-cleanup-connection
+ tramp-test-vec 'keep-debug 'keep-password)
+ (cl-letf (((symbol-function #'yes-or-no-p)
+ #'tramp--test-always))
+ (should (stringp (make-auto-save-file-name))))))))
+
+ ;; Cleanup.
+ (ignore-errors (delete-file tmp-name1))
+ (ignore-errors (delete-directory tmp-name2 'recursive))
+ (tramp-cleanup-connection tramp-test-vec 'keep-debug 'keep-password)))))
+
+(ert-deftest tramp-test38-find-backup-file-name ()
+ "Check `find-backup-file-name'."
+ (skip-unless (tramp--test-enabled))
+
+ (dolist (quoted (if (tramp--test-expensive-test-p) '(nil t) '(nil)))
+ (let ((tmp-name1 (tramp--test-make-temp-name nil quoted))
+ (tmp-name2 (tramp--test-make-temp-name nil quoted))
+ (ange-ftp-make-backup-files t)
+ tramp-allow-unsafe-temporary-files
+ ;; These settings are not used by Tramp, so we ignore them.
+ version-control delete-old-versions
+ (kept-old-versions (default-toplevel-value 'kept-old-versions))
+ (kept-new-versions (default-toplevel-value 'kept-new-versions)))
+
+ (unwind-protect
+ ;; Use default `backup-directory-alist' mechanism.
+ (let (backup-directory-alist tramp-backup-directory-alist)
+ (should
+ (equal
+ (find-backup-file-name tmp-name1)
+ (list
+ (funcall
+ (if quoted #'tramp-compat-file-name-quote #'identity)
+ (expand-file-name
+ (format "%s~" (file-name-nondirectory tmp-name1))
+ ert-remote-temporary-file-directory)))))))
+
+ (unwind-protect
+ ;; Map `backup-directory-alist'.
+ (let ((backup-directory-alist `(("." . ,tmp-name2)))
+ tramp-backup-directory-alist)
+ (should
+ (equal
+ (find-backup-file-name tmp-name1)
+ (list
+ (funcall
+ (if quoted #'tramp-compat-file-name-quote #'identity)
+ (expand-file-name
+ (format
+ "%s~"
+ ;; This is taken from `make-backup-file-name-1'. We
+ ;; call `convert-standard-filename', because on MS
+ ;; Windows the (local) colons must be replaced by
+ ;; exclamation marks.
+ (subst-char-in-string
+ ?/ ?!
+ (replace-regexp-in-string
+ "!" "!!" (convert-standard-filename tmp-name1))))
+ tmp-name2)))))
+ ;; The backup directory is created.
+ (should (file-directory-p tmp-name2)))
+
+ ;; Cleanup.
+ (ignore-errors (delete-directory tmp-name2 'recursive)))
+
+ (unwind-protect
+ ;; Map `tramp-backup-directory-alist'. Ange-FTP doesn't care.
+ (unless (tramp--test-ange-ftp-p)
+ (let ((tramp-backup-directory-alist `(("." . ,tmp-name2)))
+ backup-directory-alist)
+ (should
+ (equal
+ (find-backup-file-name tmp-name1)
+ (list
+ (funcall
+ (if quoted #'tramp-compat-file-name-quote #'identity)
(expand-file-name
(format
- "#%s#"
- (tramp-subst-strs-in-string
- '(("_" . "|")
- ("/" . "_a")
- (":" . "_b")
- ("|" . "__")
- ("[" . "_l")
- ("]" . "_r"))
- (tramp-compat-file-name-unquote tmp-name1)))
- tmp-name2)))
- (should (file-directory-p tmp-name2))))
-
- ;; Relative file names shall work, too.
- (let ((tramp-auto-save-directory "."))
- (with-temp-buffer
- (setq buffer-file-name tmp-name1
- default-directory tmp-name2)
- (should
- (string-equal
- (make-auto-save-file-name)
- ;; This is taken from Tramp.
+ "%s~"
+ ;; This is taken from `make-backup-file-name-1'.
+ ;; We call `convert-standard-filename', because on
+ ;; MS Windows the (local) colons must be replaced
+ ;; by exclamation marks.
+ (subst-char-in-string
+ ?/ ?!
+ (replace-regexp-in-string
+ "!" "!!" (convert-standard-filename tmp-name1))))
+ tmp-name2)))))
+ ;; The backup directory is created.
+ (should (file-directory-p tmp-name2))))
+
+ ;; Cleanup.
+ (ignore-errors (delete-directory tmp-name2 'recursive)))
+
+ (unwind-protect
+ ;; Map `tramp-backup-directory-alist' with local file name.
+ ;; Ange-FTP doesn't care.
+ (unless (tramp--test-ange-ftp-p)
+ (let ((tramp-backup-directory-alist
+ `(("." . ,(file-remote-p tmp-name2 'localname))))
+ backup-directory-alist)
+ (should
+ (equal
+ (find-backup-file-name tmp-name1)
+ (list
+ (funcall
+ (if quoted #'tramp-compat-file-name-quote #'identity)
(expand-file-name
(format
- "#%s#"
- (tramp-subst-strs-in-string
- '(("_" . "|")
- ("/" . "_a")
- (":" . "_b")
- ("|" . "__")
- ("[" . "_l")
- ("]" . "_r"))
- (tramp-compat-file-name-unquote tmp-name1)))
- tmp-name2)))
- (should (file-directory-p tmp-name2)))))
- ) ;; TODO
+ "%s~"
+ ;; This is taken from `make-backup-file-name-1'.
+ ;; We call `convert-standard-filename', because on
+ ;; MS Windows the (local) colons must be replaced
+ ;; by exclamation marks.
+ (subst-char-in-string
+ ?/ ?!
+ (replace-regexp-in-string
+ "!" "!!" (convert-standard-filename tmp-name1))))
+ tmp-name2)))))
+ ;; The backup directory is created.
+ (should (file-directory-p tmp-name2))))
+
+ ;; Cleanup.
+ (ignore-errors (delete-directory tmp-name2 'recursive)))
+
+ (unwind-protect
+ ;; Create temporary file. This shall check for sensible
+ ;; files, owned by root.
+ (let ((backup-directory-alist `(("." . ,temporary-file-directory)))
+ tramp-backup-directory-alist)
+ (write-region "foo" nil tmp-name1)
+ (when (zerop (or (file-attribute-user-id (file-attributes tmp-name1))
+ tramp-unknown-id-integer))
+ (tramp-cleanup-connection
+ tramp-test-vec 'keep-debug 'keep-password)
+ (let ((tramp-allow-unsafe-temporary-files t))
+ (should (stringp (car (find-backup-file-name tmp-name1)))))
+ (tramp-cleanup-connection
+ tramp-test-vec 'keep-debug 'keep-password)
+ (cl-letf (((symbol-function #'yes-or-no-p) #'ignore))
+ (should-error
+ (find-backup-file-name tmp-name1)
+ :type 'file-error))
+ (tramp-cleanup-connection
+ tramp-test-vec 'keep-debug 'keep-password)
+ (cl-letf (((symbol-function #'yes-or-no-p)
+ #'tramp--test-always))
+ (should (stringp (car (find-backup-file-name tmp-name1)))))))
;; Cleanup.
(ignore-errors (delete-file tmp-name1))
- (ignore-errors (delete-directory tmp-name2 'recursive))))))
+ (tramp-cleanup-connection tramp-test-vec 'keep-debug 'keep-password)))))
+
+;; The functions were introduced in Emacs 28.1.
+(ert-deftest tramp-test39-make-lock-file-name ()
+ "Check `make-lock-file-name', `lock-file', `unlock-file' and `file-locked-p'."
+ (skip-unless (tramp--test-enabled))
+ (skip-unless (not (tramp--test-ange-ftp-p)))
+ ;; Since Emacs 28.1.
+ (skip-unless (and (fboundp 'lock-file) (fboundp 'unlock-file)))
+ (skip-unless (and (fboundp 'file-locked-p) (fboundp 'make-lock-file-name)))
+
+ ;; `lock-file', `unlock-file', `file-locked-p' and
+ ;; `make-lock-file-name' exists since Emacs 28.1. We don't want to
+ ;; see compiler warnings for older Emacsen.
+ (dolist (quoted (if (tramp--test-expensive-test-p) '(nil t) '(nil)))
+ (let ((tmp-name1 (tramp--test-make-temp-name nil quoted))
+ (tmp-name2 (tramp--test-make-temp-name nil quoted))
+ (remote-file-name-inhibit-cache t)
+ (remote-file-name-inhibit-locks nil)
+ (create-lockfiles t)
+ tramp-allow-unsafe-temporary-files
+ (inhibit-message t)
+ ;; tramp-rclone.el and tramp-sshfs.el cache the mounted files.
+ (tramp-fuse-unmount-on-cleanup t)
+ auto-save-default
+ noninteractive)
+
+ (unwind-protect
+ (progn
+ ;; A simple file lock.
+ (should-not (with-no-warnings (file-locked-p tmp-name1)))
+ (with-no-warnings (lock-file tmp-name1))
+ (should (eq (with-no-warnings (file-locked-p tmp-name1)) t))
+
+ ;; If it is locked already, nothing changes.
+ (with-no-warnings (lock-file tmp-name1))
+ (should (eq (with-no-warnings (file-locked-p tmp-name1)) t))
+
+ ;; `save-buffer' removes the lock.
+ (with-temp-buffer
+ (set-visited-file-name tmp-name1)
+ (insert "foo")
+ (should (buffer-modified-p))
+ (save-buffer)
+ (should-not (buffer-modified-p)))
+ (should-not (with-no-warnings (file-locked-p tmp-name1)))
+ (with-no-warnings (lock-file tmp-name1))
+ (should (eq (with-no-warnings (file-locked-p tmp-name1)) t))
+
+ ;; A new connection changes process id, and also the
+ ;; lockname contents.
+ (tramp-cleanup-connection tramp-test-vec 'keep-debug 'keep-password)
+ (should (stringp (with-no-warnings (file-locked-p tmp-name1))))
+
+ ;; When `remote-file-name-inhibit-locks' is set, nothing happens.
+ (tramp-cleanup-connection tramp-test-vec 'keep-debug 'keep-password)
+ (let ((remote-file-name-inhibit-locks t))
+ (with-no-warnings (lock-file tmp-name1))
+ (should-not (with-no-warnings (file-locked-p tmp-name1))))
+
+ ;; When `lock-file-name-transforms' is set, another lock
+ ;; file is used.
+ (tramp-cleanup-connection tramp-test-vec 'keep-debug 'keep-password)
+ (let ((lock-file-name-transforms `((,(rx (* nonl)) ,tmp-name2))))
+ (should
+ (string-equal
+ (with-no-warnings (make-lock-file-name tmp-name1))
+ (with-no-warnings (make-lock-file-name tmp-name2))))
+ (with-no-warnings (lock-file tmp-name1))
+ (should (eq (with-no-warnings (file-locked-p tmp-name1)) t))
+ (with-no-warnings (unlock-file tmp-name1))
+ (should-not (with-no-warnings (file-locked-p tmp-name1))))
+
+ ;; Steal the file lock.
+ (tramp-cleanup-connection tramp-test-vec 'keep-debug 'keep-password)
+ (cl-letf (((symbol-function #'read-char) (lambda (&rest _args) ?s)))
+ (with-no-warnings (lock-file tmp-name1)))
+ (should (eq (with-no-warnings (file-locked-p tmp-name1)) t))
+
+ ;; Ignore the file lock.
+ (tramp-cleanup-connection tramp-test-vec 'keep-debug 'keep-password)
+ (cl-letf (((symbol-function #'read-char) (lambda (&rest _args) ?p)))
+ (with-no-warnings (lock-file tmp-name1)))
+ (should (stringp (with-no-warnings (file-locked-p tmp-name1))))
+
+ ;; Quit the file lock machinery.
+ (tramp-cleanup-connection tramp-test-vec 'keep-debug 'keep-password)
+ (cl-letf (((symbol-function #'read-char) (lambda (&rest _args) ?q)))
+ (with-no-warnings
+ (should-error
+ (lock-file tmp-name1)
+ :type 'file-locked))
+ ;; The same for `write-region'.
+ (should-error
+ (write-region "foo" nil tmp-name1)
+ :type 'file-locked)
+ (should-error
+ (write-region "foo" nil tmp-name1 nil nil tmp-name1)
+ :type 'file-locked)
+ ;; The same for `set-visited-file-name'.
+ (with-temp-buffer
+ (should-error
+ (set-visited-file-name tmp-name1)
+ :type 'file-locked)))
+ (should (stringp (with-no-warnings (file-locked-p tmp-name1)))))
+
+ ;; Cleanup.
+ (ignore-errors (delete-file tmp-name1))
+ (with-no-warnings (unlock-file tmp-name1))
+ (with-no-warnings (unlock-file tmp-name2))
+ (should-not (with-no-warnings (file-locked-p tmp-name1)))
+ (should-not (with-no-warnings (file-locked-p tmp-name2))))
+
+ (unwind-protect
+ ;; Create temporary file. This shall check for sensible
+ ;; files, owned by root.
+ (let ((lock-file-name-transforms auto-save-file-name-transforms))
+ (write-region "foo" nil tmp-name1)
+ (when (zerop (or (file-attribute-user-id (file-attributes tmp-name1))
+ tramp-unknown-id-integer))
+ (tramp-cleanup-connection
+ tramp-test-vec 'keep-debug 'keep-password)
+ (cl-letf (((symbol-function #'yes-or-no-p) #'ignore))
+ (should-error
+ (write-region "foo" nil tmp-name1)
+ :type 'file-error))
+ (tramp-cleanup-connection
+ tramp-test-vec 'keep-debug 'keep-password)
+ (cl-letf (((symbol-function #'yes-or-no-p)
+ #'tramp--test-always))
+ (write-region "foo" nil tmp-name1))))
+
+ ;; Cleanup.
+ (ignore-errors (delete-file tmp-name1))
+ (tramp-cleanup-connection tramp-test-vec 'keep-debug 'keep-password)))))
+
+;; The functions were introduced in Emacs 28.1.
+(ert-deftest tramp-test39-detect-external-change ()
+ "Check that an external file modification is reported."
+ (skip-unless (tramp--test-enabled))
+ (skip-unless (not (tramp--test-ange-ftp-p)))
+ ;; Since Emacs 28.1.
+ (skip-unless (and (fboundp 'lock-file) (fboundp 'file-locked-p)))
+
+ (dolist (quoted (if (tramp--test-expensive-test-p) '(nil t) '(nil)))
+ (dolist (create-lockfiles '(nil t))
+ (let ((tmp-name (tramp--test-make-temp-name nil quoted))
+ (remote-file-name-inhibit-cache t)
+ (remote-file-name-inhibit-locks nil)
+ tramp-allow-unsafe-temporary-files
+ (inhibit-message t)
+ ;; tramp-rclone.el and tramp-sshfs.el cache the mounted files.
+ (tramp-fuse-unmount-on-cleanup t)
+ auto-save-default
+ (backup-inhibited t)
+ noninteractive)
+ (with-temp-buffer
+ (unwind-protect
+ (progn
+ (setq buffer-file-name tmp-name
+ buffer-file-truename tmp-name)
+ (insert "foo")
+ ;; Bug#53207: with `create-lockfiles' nil, saving the
+ ;; buffer results in a prompt.
+ (cl-letf (((symbol-function 'yes-or-no-p)
+ (lambda (_) (ert-fail "Test failed unexpectedly"))))
+ (should (buffer-modified-p))
+ (save-buffer)
+ (should-not (buffer-modified-p)))
+ (should-not (file-locked-p tmp-name))
+
+ ;; For local files, just changing the file
+ ;; modification on disk doesn't hurt, because file
+ ;; contents in buffer and on disk are equal. For
+ ;; remote files, file contents is not compared. We
+ ;; mock an older modification time in buffer, because
+ ;; Tramp regards modification times equal if they
+ ;; differ for less than 2 seconds.
+ (set-visited-file-modtime (time-add (current-time) -60))
+ ;; Some Tramp methods cannot check the file
+ ;; modification time properly, for them it doesn't
+ ;; make sense to test.
+ (when (not (verify-visited-file-modtime))
+ (cl-letf (((symbol-function 'read-char-choice)
+ (lambda (prompt &rest _) (message "%s" prompt) ?y)))
+ (ert-with-message-capture captured-messages
+ (insert "bar")
+ (when create-lockfiles
+ (should (string-match-p
+ (rx-to-string
+ `(: bol
+ ,(if (tramp--test-crypt-p)
+ '(+ nonl)
+ (file-name-nondirectory tmp-name))
+ " changed on disk; really edit the buffer?"))
+ captured-messages))
+ (should (file-locked-p tmp-name)))))
+
+ ;; `save-buffer' removes the file lock.
+ (cl-letf (((symbol-function 'yes-or-no-p) #'tramp--test-always)
+ ((symbol-function 'read-char-choice)
+ (lambda (&rest _) ?y)))
+ (should (buffer-modified-p))
+ (save-buffer)
+ (should-not (buffer-modified-p)))
+ (should-not (file-locked-p tmp-name))))
+
+ ;; Cleanup.
+ (set-buffer-modified-p nil)
+ (ignore-errors (delete-file tmp-name))
+ (tramp-cleanup-connection
+ tramp-test-vec 'keep-debug 'keep-password)))))))
;; The functions were introduced in Emacs 26.1.
-(ert-deftest tramp-test34-make-nearby-temp-file ()
+(ert-deftest tramp-test40-make-nearby-temp-file ()
"Check `make-nearby-temp-file' and `temporary-file-directory'."
(skip-unless (tramp--test-enabled))
- ;; Since Emacs 26.1.
- (skip-unless
- (and (fboundp 'make-nearby-temp-file) (fboundp 'temporary-file-directory)))
+ (skip-unless (not (tramp--test-ange-ftp-p)))
- ;; `make-nearby-temp-file' and `temporary-file-directory' exists
- ;; since Emacs 26. We don't want to see compiler warnings for older
- ;; Emacsen.
- (let ((default-directory tramp-test-temporary-file-directory)
+ (let ((default-directory ert-remote-temporary-file-directory)
tmp-file)
;; The remote host shall know a temporary file directory.
- (should (stringp (with-no-warnings (temporary-file-directory))))
+ (should (stringp (temporary-file-directory)))
(should
(string-equal
(file-remote-p default-directory)
- (file-remote-p (with-no-warnings (temporary-file-directory)))))
+ (file-remote-p (temporary-file-directory))))
;; The temporary file shall be located on the remote host.
- (setq tmp-file (with-no-warnings (make-nearby-temp-file "tramp-test")))
+ (setq tmp-file (make-nearby-temp-file "tramp-test"))
(should (file-exists-p tmp-file))
(should (file-regular-p tmp-file))
(should
@@ -3669,101 +6570,241 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
(delete-file tmp-file)
(should-not (file-exists-p tmp-file))
- (setq tmp-file (with-no-warnings (make-nearby-temp-file "tramp-test" 'dir)))
+ (setq tmp-file (make-nearby-temp-file "tramp-test" 'dir))
(should (file-exists-p tmp-file))
(should (file-directory-p tmp-file))
(delete-directory tmp-file)
(should-not (file-exists-p tmp-file))))
-(defun tramp--test-emacs26-p ()
- "Check for Emacs version >= 26.1.
+(defun tramp--test-emacs27-p ()
+ "Check for Emacs version >= 27.1.
+Some semantics has been changed for there, w/o new functions or
+variables, so we check the Emacs version directly."
+ (>= emacs-major-version 27))
+
+(defun tramp--test-emacs28-p ()
+ "Check for Emacs version >= 28.1.
Some semantics has been changed for there, w/o new functions or
-variables, so we check function Emacs version directly."
- (>= emacs-major-version 26))
+variables, so we check the Emacs version directly."
+ (>= emacs-major-version 28))
+
+(defun tramp--test-emacs29-p ()
+ "Check for Emacs version >= 29.1.
+Some semantics has been changed for there, w/o new functions or
+variables, so we check the Emacs version directly."
+ (>= emacs-major-version 29))
(defun tramp--test-adb-p ()
"Check, whether the remote host runs Android.
This requires restrictions of file name syntax."
- (tramp-adb-file-name-p tramp-test-temporary-file-directory))
+ (tramp-adb-file-name-p ert-remote-temporary-file-directory))
+
+(defun tramp--test-ange-ftp-p ()
+ "Check, whether Ange-FTP is used."
+ (eq
+ (tramp-find-foreign-file-name-handler tramp-test-vec)
+ 'tramp-ftp-file-name-handler))
+
+(defun tramp--test-asynchronous-processes-p ()
+ "Whether asynchronous processes tests are run.
+This is used in tests which we don't want to tag
+`:tramp-asynchronous-processes' completely."
+ (and
+ (ert-select-tests
+ (ert--stats-selector ert--current-run-stats)
+ (list (make-ert-test :name (ert-test-name (ert-running-test))
+ :body nil :tags '(:tramp-asynchronous-processes))))
+ ;; tramp-adb.el cannot apply multi-byte commands.
+ (not (and (tramp--test-adb-p)
+ (string-match-p (tramp-compat-rx multibyte) default-directory)))))
+
+(defun tramp--test-crypt-p ()
+ "Check, whether the remote directory is encrypted."
+ (tramp-crypt-file-name-p ert-remote-temporary-file-directory))
(defun tramp--test-docker-p ()
"Check, whether the docker method is used.
This does not support some special file names."
(string-equal
- "docker" (file-remote-p tramp-test-temporary-file-directory 'method)))
+ "docker" (file-remote-p ert-remote-temporary-file-directory 'method)))
+
+(defun tramp--test-expensive-test-p ()
+ "Whether expensive tests are run.
+This is used in tests which we don't want to tag `:expensive'
+completely."
+ (ert-select-tests
+ (ert--stats-selector ert--current-run-stats)
+ (list (make-ert-test :name (ert-test-name (ert-running-test))
+ :body nil :tags '(:expensive-test)))))
(defun tramp--test-ftp-p ()
"Check, whether an FTP-like method is used.
This does not support globbing characters in file names (yet)."
;; Globbing characters are ??, ?* and ?\[.
- (string-match
- "ftp$" (file-remote-p tramp-test-temporary-file-directory 'method)))
+ (string-suffix-p
+ "ftp" (file-remote-p ert-remote-temporary-file-directory 'method)))
+
+(defun tramp--test-fuse-p ()
+ "Check, whether an FUSE file system isused."
+ (or (tramp--test-rclone-p) (tramp--test-sshfs-p)))
+
+(defun tramp--test-gdrive-p ()
+ "Check, whether the gdrive method is used."
+ (string-equal
+ "gdrive" (file-remote-p ert-remote-temporary-file-directory 'method)))
(defun tramp--test-gvfs-p (&optional method)
"Check, whether the remote host runs a GVFS based method.
-This requires restrictions of file name syntax."
+This requires restrictions of file name syntax.
+If optional METHOD is given, it is checked first."
(or (member method tramp-gvfs-methods)
- (tramp-gvfs-file-name-p tramp-test-temporary-file-directory)))
+ (tramp-gvfs-file-name-p ert-remote-temporary-file-directory)))
(defun tramp--test-hpux-p ()
"Check, whether the remote host runs HP-UX.
Several special characters do not work properly there."
;; We must refill the cache. `file-truename' does it.
- (with-parsed-tramp-file-name
- (file-truename tramp-test-temporary-file-directory) nil
- (string-match "^HP-UX" (tramp-get-connection-property v "uname" ""))))
+ (file-truename ert-remote-temporary-file-directory)
+ (ignore-errors (tramp-check-remote-uname tramp-test-vec (rx bol "HP-UX"))))
+
+(defun tramp--test-ksh-p ()
+ "Check, whether the remote shell is ksh.
+ksh93 makes some strange conversions of non-latin characters into
+a $'' syntax."
+ ;; We must refill the cache. `file-truename' does it.
+ (file-truename ert-remote-temporary-file-directory)
+ (string-suffix-p
+ "ksh"
+ (tramp-get-connection-property tramp-test-vec "remote-shell" "")))
+
+(defun tramp--test-macos-p ()
+ "Check, whether the remote host runs macOS."
+ ;; We must refill the cache. `file-truename' does it.
+ (file-truename ert-remote-temporary-file-directory)
+ (ignore-errors (tramp-check-remote-uname tramp-test-vec "Darwin")))
+
+(defun tramp--test-mock-p ()
+ "Check, whether the mock method is used.
+This does not support external Emacs calls."
+ (string-equal
+ "mock" (file-remote-p ert-remote-temporary-file-directory 'method)))
+
+(defun tramp--test-out-of-band-p ()
+ "Check, whether an out-of-band method is used."
+ (tramp-method-out-of-band-p tramp-test-vec 1))
+
+(defun tramp--test-rclone-p ()
+ "Check, whether the remote host is offered by rclone.
+This requires restrictions of file name syntax."
+ (tramp-rclone-file-name-p ert-remote-temporary-file-directory))
(defun tramp--test-rsync-p ()
"Check, whether the rsync method is used.
This does not support special file names."
(string-equal
- "rsync" (file-remote-p tramp-test-temporary-file-directory 'method)))
+ "rsync" (file-remote-p ert-remote-temporary-file-directory 'method)))
(defun tramp--test-sh-p ()
"Check, whether the remote host runs a based method from tramp-sh.el."
- (eq
- (tramp-find-foreign-file-name-handler tramp-test-temporary-file-directory)
- 'tramp-sh-file-name-handler))
+ (tramp-sh-file-name-handler-p tramp-test-vec))
+
+(defun tramp--test-sh-no-ls--dired-p ()
+ "Check, whether the remote host runs a based method from tramp-sh.el.
+Additionally, ls does not support \"--dired\"."
+ (and (tramp--test-sh-p)
+ (with-temp-buffer
+ ;; We must refill the cache. `insert-directory' does it.
+ ;; This fails for tramp-crypt.el, so we ignore that.
+ (ignore-errors
+ (insert-directory ert-remote-temporary-file-directory "-al"))
+ (not (tramp-get-connection-property tramp-test-vec "ls--dired")))))
+
+(defun tramp--test-share-p ()
+ "Check, whether the method needs a share."
+ (and (tramp--test-gvfs-p)
+ (string-match-p
+ (rx bol (| "afp" (: "dav" (? "s")) "smb") eol)
+ (file-remote-p ert-remote-temporary-file-directory 'method))))
+
+(defun tramp--test-sshfs-p ()
+ "Check, whether the remote host is offered by sshfs.
+This requires restrictions of file name syntax."
+ (tramp-sshfs-file-name-p ert-remote-temporary-file-directory))
+
+(defun tramp--test-sudoedit-p ()
+ "Check, whether the sudoedit method is used."
+ (tramp-sudoedit-file-name-p ert-remote-temporary-file-directory))
+
+(defun tramp--test-telnet-p ()
+ "Check, whether the telnet method is used.
+This does not support special file names."
+ (string-equal
+ "telnet" (file-remote-p ert-remote-temporary-file-directory 'method)))
-(defun tramp--test-windows-nt-and-batch ()
- "Check, whether the locale host runs MS Windows in batch mode.
-This does not support special characters."
- (and (eq system-type 'windows-nt) noninteractive))
+(defun tramp--test-windows-nt-p ()
+ "Check, whether the locale host runs MS Windows."
+ (eq system-type 'windows-nt))
-(defun tramp--test-windows-nt-and-pscp-psftp-p ()
- "Check, whether the locale host runs MS Windows, and ps{cp,ftp} is used.
+(defun tramp--test-windows-nt-and-out-of-band-p ()
+ "Check, whether the locale host runs MS Windows and an out-of-band method.
This does not support utf8 based file transfer."
- (and (eq system-type 'windows-nt)
- (string-match
- (regexp-opt '("pscp" "psftp"))
- (file-remote-p tramp-test-temporary-file-directory 'method))))
+ (and (tramp--test-windows-nt-p)
+ (tramp--test-out-of-band-p)))
(defun tramp--test-windows-nt-or-smb-p ()
"Check, whether the locale or remote host runs MS Windows.
This requires restrictions of file name syntax."
- (or (eq system-type 'windows-nt)
- (tramp-smb-file-name-p tramp-test-temporary-file-directory)))
+ (or (tramp--test-windows-nt-p)
+ (tramp--test-smb-p)))
+
+(defun tramp--test-smb-p ()
+ "Check, whether the locale or remote host runs MS Windows.
+This requires restrictions of file name syntax."
+ (tramp-smb-file-name-p ert-remote-temporary-file-directory))
+
+(defun tramp--test-supports-processes-p ()
+ "Return whether the method under test supports external processes."
+ (and (or (tramp--test-adb-p) (tramp--test-sh-p) (tramp--test-sshfs-p))
+ (not (tramp--test-crypt-p))))
+
+(defun tramp--test-supports-set-file-modes-p ()
+ "Return whether the method under test supports setting file modes."
+ ;; "smb" does not unless the SMB server supports "posix" extensions.
+ ;; "adb" does not unless the Android device is rooted.
+ (or (tramp--test-sh-p) (tramp--test-sshfs-p) (tramp--test-sudoedit-p)
+ ;; Not all tramp-gvfs.el methods support changing the file mode.
+ (and
+ (tramp--test-gvfs-p)
+ (string-suffix-p
+ "ftp" (file-remote-p ert-remote-temporary-file-directory 'method)))))
(defun tramp--test-check-files (&rest files)
"Run a simple but comprehensive test over every file in FILES."
- ;; TODO: The quoted case does not work.
- ;;(dolist (quoted (if tramp--test-expensive-test '(nil t) '(nil)))
- (let (quoted)
+ ;; `filename-non-special' has been fixed in Emacs 27.1, see Bug#29579.
+ (dolist (quoted
+ (if (and (tramp--test-expensive-test-p) (tramp--test-emacs27-p))
+ '(nil t) '(nil)))
;; We must use `file-truename' for the temporary directory,
;; because it could be located on a symlinked directory. This
;; would let the test fail.
- (let* ((tramp-test-temporary-file-directory
- (file-truename tramp-test-temporary-file-directory))
+ (let* ((ert-remote-temporary-file-directory
+ (file-truename ert-remote-temporary-file-directory))
+ (tramp-fuse-remove-hidden-files t)
(tmp-name1 (tramp--test-make-temp-name nil quoted))
(tmp-name2 (tramp--test-make-temp-name 'local quoted))
- (files (delq nil files))
- (process-environment process-environment))
+ (files
+ (delq
+ nil (mapcar (lambda (x) (unless (string-empty-p x) x)) files)))
+ (process-environment process-environment)
+ (sorted-files (sort (copy-sequence files) #'string-lessp))
+ buffer)
(unwind-protect
(progn
(make-directory tmp-name1)
(make-directory tmp-name2)
(dolist (elt files)
+ ;(tramp--test-message "'%s'" elt)
(let* ((file1 (expand-file-name elt tmp-name1))
(file2 (expand-file-name elt tmp-name2))
(file3 (expand-file-name (concat elt "foo") tmp-name1)))
@@ -3792,8 +6833,8 @@ This requires restrictions of file name syntax."
(should
(string-equal
(funcall
- (if quoted 'tramp-compat-file-name-quote 'identity)
- (car (file-attributes file3)))
+ (if quoted #'tramp-compat-file-name-quote #'identity)
+ (file-attribute-type (file-attributes file3)))
(file-remote-p (file-truename file1) 'localname)))
;; Check file contents.
(with-temp-buffer
@@ -3804,15 +6845,37 @@ This requires restrictions of file name syntax."
;; Check file names.
(should (equal (directory-files
tmp-name1 nil directory-files-no-dot-files-regexp)
- (sort (copy-sequence files) 'string-lessp)))
+ sorted-files))
(should (equal (directory-files
tmp-name2 nil directory-files-no-dot-files-regexp)
- (sort (copy-sequence files) 'string-lessp)))
+ sorted-files))
+ (should (equal (mapcar
+ #'car
+ (directory-files-and-attributes
+ tmp-name1 nil directory-files-no-dot-files-regexp))
+ sorted-files))
+ (should (equal (mapcar
+ #'car
+ (directory-files-and-attributes
+ tmp-name2 nil directory-files-no-dot-files-regexp))
+ sorted-files))
+
+ ;; Check, that `insert-directory' works properly.
+ (with-current-buffer
+ (setq buffer (dired-noselect tmp-name1 "--dired -al"))
+ (goto-char (point-min))
+ (while (not (eobp))
+ (when-let ((name (dired-get-filename 'no-dir 'no-error)))
+ (unless
+ (string-match-p name directory-files-no-dot-files-regexp)
+ (should (member name files))))
+ (forward-line 1)))
+ (kill-buffer buffer)
;; `substitute-in-file-name' could return different
- ;; values. For `adb', there could be strange file
+ ;; values. For "adb", there could be strange file
;; permissions preventing overwriting a file. We don't
- ;; care in this testcase.
+ ;; care in this test case.
(dolist (elt files)
(let ((file1
(substitute-in-file-name (expand-file-name elt tmp-name1)))
@@ -3855,169 +6918,165 @@ This requires restrictions of file name syntax."
;; It does not work in the "smb" case, only relative
;; symlinks to existing files are shown there.
(tramp--test-ignore-make-symbolic-link-error
- (unless
- (tramp-smb-file-name-p tramp-test-temporary-file-directory)
+ (unless (tramp--test-smb-p)
(make-symbolic-link file2 file3)
(should (file-symlink-p file3))
(should
(string-equal
(caar (directory-files-and-attributes
- file1 nil (regexp-quote elt1)))
+ file1 nil (tramp-compat-rx (literal elt1))))
elt1))
(should
(string-equal
(funcall
- (if quoted 'tramp-compat-file-name-quote 'identity)
+ (if quoted #'tramp-compat-file-name-quote #'identity)
(cadr (car (directory-files-and-attributes
- file1 nil (regexp-quote elt1)))))
+ file1 nil (tramp-compat-rx (literal elt1))))))
(file-remote-p (file-truename file2) 'localname)))
(delete-file file3)
(should-not (file-exists-p file3))))
+ ;; Check, that a process runs on a remote
+ ;; `default-directory' with special characters. See
+ ;; Bug#53846.
+ (when (and (tramp--test-expensive-test-p)
+ (tramp--test-supports-processes-p)
+ ;; Prior Emacs 27, `shell-file-name' was
+ ;; hard coded as "/bin/sh" for remote
+ ;; processes in Emacs. That doesn't work
+ ;; for tramp-adb.el. tramp-sshfs.el times
+ ;; out for older Emacsen, reason unknown.
+ (or (and (not (tramp--test-adb-p))
+ (not (tramp--test-sshfs-p)))
+ (tramp--test-emacs27-p)))
+ (let ((default-directory file1))
+ (dolist (this-shell-command
+ (append
+ ;; Synchronously.
+ '(shell-command)
+ ;; Asynchronously.
+ (and (tramp--test-asynchronous-processes-p)
+ '(tramp--test-async-shell-command))))
+ (with-temp-buffer
+ (funcall this-shell-command "cat -- *" (current-buffer))
+ (should (string-equal elt (buffer-string)))))))
+
(delete-file file2)
(should-not (file-exists-p file2))
- (delete-directory file1)
+ (delete-directory file1 'recursive)
(should-not (file-exists-p file1))))
;; Check, that environment variables are set correctly.
- (when (and tramp--test-expensive-test (tramp--test-sh-p))
+ ;; We do not run on macOS due to encoding problems. See
+ ;; Bug#36940.
+ (when (and (tramp--test-expensive-test-p) (tramp--test-sh-p)
+ (not (tramp--test-crypt-p))
+ (not (eq system-type 'darwin)))
(dolist (elt files)
(let ((envvar (concat "VAR_" (upcase (md5 elt))))
- (default-directory tramp-test-temporary-file-directory)
+ (elt (encode-coding-string elt coding-system-for-read))
+ (default-directory ert-remote-temporary-file-directory)
(process-environment process-environment))
(setenv envvar elt)
;; The value of PS1 could confuse Tramp's detection
;; of process output. So we unset it temporarily.
(setenv "PS1")
(with-temp-buffer
- (should (zerop (process-file "env" nil t nil)))
+ (should (zerop (process-file "printenv" nil t nil)))
(goto-char (point-min))
(should
(re-search-forward
- (format
- "^%s=%s$"
- (regexp-quote envvar)
- (regexp-quote (getenv envvar))))))))))
+ (tramp-compat-rx
+ bol (literal envvar)
+ "=" (literal (getenv envvar)) eol))))))))
;; Cleanup.
+ (ignore-errors (kill-buffer buffer))
(ignore-errors (delete-directory tmp-name1 'recursive))
(ignore-errors (delete-directory tmp-name2 'recursive))))))
-(defun tramp--test-special-characters ()
- "Perform the test in `tramp-test35-special-characters*'."
+;; These tests are inspired by Bug#17238.
+(ert-deftest tramp-test41-special-characters ()
+ "Check special characters in file names."
+ (skip-unless (tramp--test-enabled))
+ (skip-unless (not (getenv "EMACS_HYDRA_CI"))) ; SLOW ~ 245s
+ (skip-unless (not (tramp--test-rsync-p)))
+ (skip-unless (not (tramp--test-rclone-p)))
+
;; Newlines, slashes and backslashes in file names are not
;; supported. So we don't test. And we don't test the tab
;; character on Windows or Cygwin, because the backslash is
;; interpreted as a path separator, preventing "\t" from being
;; expanded to <TAB>.
- (tramp--test-check-files
- (if (or (tramp--test-gvfs-p) (tramp--test-windows-nt-or-smb-p))
- "foo bar baz"
- (if (or (tramp--test-adb-p)
- (tramp--test-docker-p)
- (eq system-type 'cygwin))
- " foo bar baz "
- " foo\tbar baz\t"))
- "$foo$bar$$baz$"
- "-foo-bar-baz-"
- "%foo%bar%baz%"
- "&foo&bar&baz&"
- (unless (or (tramp--test-ftp-p)
- (tramp--test-gvfs-p)
- (tramp--test-windows-nt-or-smb-p))
- "?foo?bar?baz?")
- (unless (or (tramp--test-ftp-p)
- (tramp--test-gvfs-p)
- (tramp--test-windows-nt-or-smb-p))
- "*foo*bar*baz*")
- (if (or (tramp--test-gvfs-p) (tramp--test-windows-nt-or-smb-p))
- "'foo'bar'baz'"
- "'foo\"bar'baz\"")
- "#foo~bar#baz~"
- (if (or (tramp--test-gvfs-p) (tramp--test-windows-nt-or-smb-p))
- "!foo!bar!baz!"
- "!foo|bar!baz|")
- (if (or (tramp--test-gvfs-p) (tramp--test-windows-nt-or-smb-p))
- ";foo;bar;baz;"
- ":foo;bar:baz;")
- (unless (or (tramp--test-gvfs-p) (tramp--test-windows-nt-or-smb-p))
- "<foo>bar<baz>")
- "(foo)bar(baz)"
- (unless (or (tramp--test-ftp-p) (tramp--test-gvfs-p)) "[foo]bar[baz]")
- "{foo}bar{baz}"))
-
-;; These tests are inspired by Bug#17238.
-(ert-deftest tramp-test35-special-characters ()
- "Check special characters in file names."
+ (let ((files
+ (list
+ (cond ((or (tramp--test-ange-ftp-p)
+ (tramp--test-docker-p)
+ (tramp--test-gvfs-p)
+ (tramp--test-rclone-p)
+ (tramp--test-sudoedit-p)
+ (tramp--test-windows-nt-or-smb-p))
+ "foo bar baz")
+ ((or (tramp--test-adb-p)
+ (eq system-type 'cygwin))
+ " foo bar baz ")
+ ((tramp--test-sh-no-ls--dired-p)
+ "\tfoo bar baz\t")
+ (t " foo\tbar baz\t"))
+ "@foo@bar@baz@"
+ (unless (tramp--test-windows-nt-and-out-of-band-p) "$foo$bar$$baz$")
+ "-foo-bar-baz-"
+ (unless (tramp--test-windows-nt-and-out-of-band-p) "%foo%bar%baz%")
+ "&foo&bar&baz&"
+ (unless (or (tramp--test-ftp-p)
+ (tramp--test-gvfs-p)
+ (tramp--test-windows-nt-or-smb-p))
+ "?foo?bar?baz?")
+ (unless (or (tramp--test-ftp-p)
+ (tramp--test-gvfs-p)
+ (tramp--test-windows-nt-or-smb-p))
+ "*foo+bar*baz+")
+ (if (or (tramp--test-gvfs-p) (tramp--test-windows-nt-or-smb-p))
+ "'foo'bar'baz'"
+ "'foo\"bar'baz\"")
+ "#foo~bar#baz~"
+ (unless (tramp--test-windows-nt-and-out-of-band-p)
+ (if (or (tramp--test-gvfs-p) (tramp--test-windows-nt-or-smb-p))
+ "!foo!bar!baz!"
+ "!foo|bar!baz|"))
+ (if (or (tramp--test-gvfs-p)
+ (tramp--test-rclone-p)
+ (tramp--test-windows-nt-or-smb-p))
+ ";foo;bar;baz;"
+ ":foo;bar:baz;")
+ (unless (or (tramp--test-gvfs-p) (tramp--test-windows-nt-or-smb-p))
+ "<foo>bar<baz>")
+ "(foo)bar(baz)"
+ (unless (or (tramp--test-ftp-p) (tramp--test-gvfs-p)) "[foo]bar[baz]")
+ "{foo}bar{baz}")))
+ ;; Simplify test in order to speed up.
+ (apply #'tramp--test-check-files
+ (if (tramp--test-expensive-test-p)
+ files (list (mapconcat #'identity files ""))))))
+
+(tramp--test-deftest-with-stat tramp-test41-special-characters)
+
+(tramp--test-deftest-with-perl tramp-test41-special-characters)
+
+(tramp--test-deftest-with-ls tramp-test41-special-characters)
+
+(ert-deftest tramp-test42-utf8 ()
+ "Check UTF8 encoding in file names and file contents."
(skip-unless (tramp--test-enabled))
+ (skip-unless (not (getenv "EMACS_HYDRA_CI"))) ; SLOW ~ 620s
+ (skip-unless (not (tramp--test-docker-p)))
(skip-unless (not (tramp--test-rsync-p)))
- (skip-unless (not (tramp--test-windows-nt-and-pscp-psftp-p)))
+ (skip-unless (not (tramp--test-windows-nt-and-out-of-band-p)))
+ (skip-unless (not (tramp--test-ksh-p)))
+ (skip-unless (not (tramp--test-gdrive-p)))
+ (skip-unless (not (tramp--test-crypt-p)))
+ (skip-unless (not (tramp--test-rclone-p)))
- (tramp--test-special-characters))
-
-(ert-deftest tramp-test35-special-characters-with-stat ()
- "Check special characters in file names.
-Use the `stat' command."
- :tags '(:expensive-test)
- (skip-unless (tramp--test-enabled))
- (skip-unless (tramp--test-sh-p))
- (skip-unless (not (tramp--test-rsync-p)))
- (skip-unless (not (tramp--test-windows-nt-and-pscp-psftp-p)))
- (with-parsed-tramp-file-name tramp-test-temporary-file-directory nil
- (skip-unless (tramp-get-remote-stat v)))
-
- (let ((tramp-connection-properties
- (append
- `((,(regexp-quote (file-remote-p tramp-test-temporary-file-directory))
- "perl" nil))
- tramp-connection-properties)))
- (tramp--test-special-characters)))
-
-(ert-deftest tramp-test35-special-characters-with-perl ()
- "Check special characters in file names.
-Use the `perl' command."
- :tags '(:expensive-test)
- (skip-unless (tramp--test-enabled))
- (skip-unless (tramp--test-sh-p))
- (skip-unless (not (tramp--test-rsync-p)))
- (skip-unless (not (tramp--test-windows-nt-and-pscp-psftp-p)))
- (with-parsed-tramp-file-name tramp-test-temporary-file-directory nil
- (skip-unless (tramp-get-remote-perl v)))
-
- (let ((tramp-connection-properties
- (append
- `((,(regexp-quote (file-remote-p tramp-test-temporary-file-directory))
- "stat" nil)
- ;; See `tramp-sh-handle-file-truename'.
- (,(regexp-quote (file-remote-p tramp-test-temporary-file-directory))
- "readlink" nil))
- tramp-connection-properties)))
- (tramp--test-special-characters)))
-
-(ert-deftest tramp-test35-special-characters-with-ls ()
- "Check special characters in file names.
-Use the `ls' command."
- :tags '(:expensive-test)
- (skip-unless (tramp--test-enabled))
- (skip-unless (tramp--test-sh-p))
- (skip-unless (not (tramp--test-rsync-p)))
- (skip-unless (not (tramp--test-windows-nt-and-batch)))
- (skip-unless (not (tramp--test-windows-nt-and-pscp-psftp-p)))
-
- (let ((tramp-connection-properties
- (append
- `((,(regexp-quote (file-remote-p tramp-test-temporary-file-directory))
- "perl" nil)
- (,(regexp-quote (file-remote-p tramp-test-temporary-file-directory))
- "stat" nil)
- ;; See `tramp-sh-handle-file-truename'.
- (,(regexp-quote (file-remote-p tramp-test-temporary-file-directory))
- "readlink" nil))
- tramp-connection-properties)))
- (tramp--test-special-characters)))
-
-(defun tramp--test-utf8 ()
- "Perform the test in `tramp-test36-utf8*'."
(let* ((utf8 (if (and (eq system-type 'darwin)
(memq 'utf-8-hfs (coding-system-list)))
'utf-8-hfs 'utf-8))
@@ -4025,113 +7084,138 @@ Use the `ls' command."
(coding-system-for-write utf8)
(file-name-coding-system
(coding-system-change-eol-conversion utf8 'unix)))
- (tramp--test-check-files
- (unless (tramp--test-hpux-p) "Γυρίστε το Γαλαξία με Ώτο Στοπ")
- (unless (tramp--test-hpux-p)
- "أصبح بوسعك الآن تنزيل نسخة كاملة من موسوعة ويكيبيديا العربية لتصفحها بلا اتصال بالإنترنت")
- "银河系漫游指南系列"
- "Автостопом по гала́ктике")))
-
-(ert-deftest tramp-test36-utf8 ()
- "Check UTF8 encoding in file names and file contents."
- (skip-unless (tramp--test-enabled))
- (skip-unless (not (tramp--test-docker-p)))
- (skip-unless (not (tramp--test-rsync-p)))
- (skip-unless (not (tramp--test-windows-nt-and-batch)))
- (skip-unless (not (tramp--test-windows-nt-and-pscp-psftp-p)))
-
- (tramp--test-utf8))
-
-(ert-deftest tramp-test36-utf8-with-stat ()
- "Check UTF8 encoding in file names and file contents.
-Use the `stat' command."
- :tags '(:expensive-test)
- (skip-unless (tramp--test-enabled))
- (skip-unless (tramp--test-sh-p))
- (skip-unless (not (tramp--test-docker-p)))
- (skip-unless (not (tramp--test-rsync-p)))
- (skip-unless (not (tramp--test-windows-nt-and-batch)))
- (skip-unless (not (tramp--test-windows-nt-and-pscp-psftp-p)))
- (with-parsed-tramp-file-name tramp-test-temporary-file-directory nil
- (skip-unless (tramp-get-remote-stat v)))
-
- (let ((tramp-connection-properties
- (append
- `((,(regexp-quote (file-remote-p tramp-test-temporary-file-directory))
- "perl" nil))
- tramp-connection-properties)))
- (tramp--test-utf8)))
-
-(ert-deftest tramp-test36-utf8-with-perl ()
- "Check UTF8 encoding in file names and file contents.
-Use the `perl' command."
- :tags '(:expensive-test)
- (skip-unless (tramp--test-enabled))
- (skip-unless (tramp--test-sh-p))
- (skip-unless (not (tramp--test-docker-p)))
- (skip-unless (not (tramp--test-rsync-p)))
- (skip-unless (not (tramp--test-windows-nt-and-batch)))
- (skip-unless (not (tramp--test-windows-nt-and-pscp-psftp-p)))
- (with-parsed-tramp-file-name tramp-test-temporary-file-directory nil
- (skip-unless (tramp-get-remote-perl v)))
-
- (let ((tramp-connection-properties
- (append
- `((,(regexp-quote (file-remote-p tramp-test-temporary-file-directory))
- "stat" nil)
- ;; See `tramp-sh-handle-file-truename'.
- (,(regexp-quote (file-remote-p tramp-test-temporary-file-directory))
- "readlink" nil))
- tramp-connection-properties)))
- (tramp--test-utf8)))
-
-(ert-deftest tramp-test36-utf8-with-ls ()
- "Check UTF8 encoding in file names and file contents.
-Use the `ls' command."
- :tags '(:expensive-test)
+ (apply
+ #'tramp--test-check-files
+ (append
+ (list
+ (unless (tramp--test-hpux-p) "Γυρίστε το Γαλαξία με Ώτο Στοπ")
+ (unless (tramp--test-hpux-p)
+ "أصبح بوسعك الآن تنزيل نسخة كاملة من موسوعة ويكيبيديا العربية لتصفحها بلا اتصال بالإنترنت")
+ "银河系漫游指南系列"
+ "Автостопом по гала́ктике"
+ ;; Use codepoints without a name. See Bug#31272.
+ ;; Works on some Android systems only.
+ (unless (tramp--test-adb-p) "™›šbung")
+ ;; Use codepoints from Supplementary Multilingual Plane (U+10000
+ ;; to U+1FFFF).
+ "🌈🍒👋")
+
+ (when (tramp--test-expensive-test-p)
+ (delete-dups
+ (mapcar
+ ;; Use all available language specific snippets.
+ (lambda (x)
+ (and
+ (stringp (setq x (eval (get-language-info (car x) 'sample-text) t)))
+ ;; Filter out strings which use unencodable characters.
+ (not (and (or (tramp--test-gvfs-p) (tramp--test-smb-p))
+ (unencodable-char-position
+ 0 (length x) file-name-coding-system nil x)))
+ ;; Filter out not displayable characters.
+ (setq x (mapconcat
+ (lambda (y)
+ (and (char-displayable-p y) (char-to-string y)))
+ x ""))
+ (not (string-empty-p x))
+ ;; ?\n and ?/ shouldn't be part of any file name. ?\t,
+ ;; ?. and ?? do not work for "smb" method. " " does not
+ ;; work at begin or end of the string for MS Windows.
+ (replace-regexp-in-string (rx (any " \t\n/.?")) "" x)))
+ language-info-alist)))))))
+
+(tramp--test-deftest-with-stat tramp-test42-utf8)
+
+(tramp--test-deftest-with-perl tramp-test42-utf8)
+
+(tramp--test-deftest-with-ls tramp-test42-utf8)
+
+(ert-deftest tramp-test43-file-system-info ()
+ "Check that `file-system-info' returns proper values."
(skip-unless (tramp--test-enabled))
- (skip-unless (tramp--test-sh-p))
- (skip-unless (not (tramp--test-docker-p)))
- (skip-unless (not (tramp--test-rsync-p)))
- (skip-unless (not (tramp--test-windows-nt-and-batch)))
- (skip-unless (not (tramp--test-windows-nt-and-pscp-psftp-p)))
-
- (let ((tramp-connection-properties
- (append
- `((,(regexp-quote (file-remote-p tramp-test-temporary-file-directory))
- "perl" nil)
- (,(regexp-quote (file-remote-p tramp-test-temporary-file-directory))
- "stat" nil)
- ;; See `tramp-sh-handle-file-truename'.
- (,(regexp-quote (file-remote-p tramp-test-temporary-file-directory))
- "readlink" nil))
- tramp-connection-properties)))
- (tramp--test-utf8)))
-
-(defun tramp--test-timeout-handler ()
- (interactive)
- (ert-fail (format "`%s' timed out" (ert-test-name (ert-running-test)))))
+ ;; Since Emacs 27.1.
+ (skip-unless (fboundp 'file-system-info))
+
+ ;; `file-system-info' exists since Emacs 27.1. We don't want to see
+ ;; compiler warnings for older Emacsen.
+ (when-let ((fsi (with-no-warnings
+ (file-system-info ert-remote-temporary-file-directory))))
+ (should (consp fsi))
+ (should (= (length fsi) 3))
+ (dotimes (i (length fsi))
+ (should (natnump (or (nth i fsi) 0))))))
+
+;; `tramp-test44-asynchronous-requests' could be blocked. So we set a
+;; timeout of 300 seconds, and we send a SIGUSR1 signal after 300
+;; seconds. Similar check is performed in the timer function.
+(defconst tramp--test-asynchronous-requests-timeout 300
+ "Timeout for `tramp-test44-asynchronous-requests'.")
+
+(defmacro tramp--test-with-proper-process-name-and-buffer (proc &rest body)
+ "Set \"process-name\" and \"process-buffer\" connection properties.
+The values are derived from PROC. Run BODY.
+This is needed in timer functions as well as process filters and sentinels."
+ ;; FIXME: For tramp-sshfs.el, `processp' does not work.
+ (declare (indent 1) (debug (processp body)))
+ `(let* ((v (tramp-get-connection-property ,proc "vector"))
+ (pname (tramp-get-connection-property v "process-name"))
+ (pbuffer (tramp-get-connection-property v "process-buffer")))
+ (tramp--test-message
+ "tramp--test-with-proper-process-name-and-buffer before %s %s"
+ (tramp-get-connection-property v "process-name")
+ (tramp-get-connection-property v "process-buffer"))
+ (if (process-name ,proc)
+ (tramp-set-connection-property v "process-name" (process-name ,proc))
+ (tramp-flush-connection-property v "process-name"))
+ (if (process-buffer ,proc)
+ (tramp-set-connection-property
+ v "process-buffer" (process-buffer ,proc))
+ (tramp-flush-connection-property v "process-buffer"))
+ (tramp--test-message
+ "tramp--test-with-proper-process-name-and-buffer changed %s %s"
+ (tramp-get-connection-property v "process-name")
+ (tramp-get-connection-property v "process-buffer"))
+ (unwind-protect
+ (progn ,@body)
+ (if pname
+ (tramp-set-connection-property v "process-name" pname)
+ (tramp-flush-connection-property v "process-name"))
+ (if pbuffer
+ (tramp-set-connection-property v "process-buffer" pbuffer)
+ (tramp-flush-connection-property v "process-buffer")))))
;; This test is inspired by Bug#16928.
-(ert-deftest tramp-test37-asynchronous-requests ()
+(ert-deftest tramp-test44-asynchronous-requests ()
"Check parallel asynchronous requests.
Such requests could arrive from timers, process filters and
process sentinels. They shall not disturb each other."
- :tags '(:expensive-test)
+ :tags (append '(:expensive-test :tramp-asynchronous-processes)
+ (and (or (getenv "EMACS_HYDRA_CI")
+ (getenv "EMACS_EMBA_CI"))
+ '(:unstable)))
(skip-unless (tramp--test-enabled))
- (skip-unless (tramp--test-sh-p))
+ (skip-unless (tramp--test-supports-processes-p))
+ ;; Prior Emacs 27, `shell-file-name' was hard coded as "/bin/sh" for
+ ;; remote processes in Emacs. That doesn't work for tramp-adb.el.
+ (when (tramp--test-adb-p)
+ (skip-unless (tramp--test-emacs27-p)))
+ (skip-unless (not (tramp--test-docker-p)))
+ (skip-unless (not (tramp--test-telnet-p)))
+ (skip-unless (not (tramp--test-sshfs-p)))
+ (skip-unless (not (tramp--test-windows-nt-p)))
- ;; This test could be blocked on hydra. So we set a timeout of 300
- ;; seconds, and we send a SIGUSR1 signal after 300 seconds.
- (with-timeout (300 (tramp--test-timeout-handler))
- (define-key special-event-map [sigusr1] 'tramp--test-timeout-handler)
- (tramp--test-instrument-test-case (if (getenv "EMACS_HYDRA_CI") 10 0)
+ (with-timeout
+ (tramp--test-asynchronous-requests-timeout (tramp--test-timeout-handler))
+ (define-key special-event-map [sigusr1] #'tramp--test-timeout-handler)
(let* (;; For the watchdog.
(default-directory (expand-file-name temporary-file-directory))
+ (shell-file-name (tramp--test-shell-file-name))
+ ;; It doesn't work on w32 systems.
(watchdog
- (start-process
- "*watchdog*" nil shell-file-name shell-command-switch
- (format "sleep 300; kill -USR1 %d" (emacs-pid))))
+ (start-process-shell-command
+ "*watchdog*" nil
+ (format
+ "sleep %d; kill -USR1 %d"
+ tramp--test-asynchronous-requests-timeout (emacs-pid))))
(tmp-name (tramp--test-make-temp-name))
(default-directory tmp-name)
;; Do not cache Tramp properties.
@@ -4141,19 +7225,22 @@ process sentinels. They shall not disturb each other."
(inhibit-message t)
;; Do not run delayed timers.
(timer-max-repeats 0)
- ;; Number of asynchronous processes for test.
- (number-proc 10)
+ ;; Number of asynchronous processes for test. Tests on
+ ;; some machines handle less parallel processes.
+ (number-proc
+ (cond
+ ((ignore-errors
+ (string-to-number (getenv "REMOTE_PARALLEL_PROCESSES"))))
+ ((getenv "EMACS_HYDRA_CI") 5)
+ (t 10)))
;; On hydra, timings are bad.
(timer-repeat
(cond
((getenv "EMACS_HYDRA_CI") 10)
(t 1)))
- ;; We must distinguish due to performance reasons.
- (timer-operation
- (cond
- ((string-equal "mock" (file-remote-p tmp-name 'method))
- 'vc-registered)
- (t 'file-attributes)))
+ ;; This is when all timers start. We check inside the
+ ;; timer function, that we don't exceed timeout.
+ (timer-start (current-time))
timer buffers kill-buffer-query-functions)
(unwind-protect
@@ -4168,21 +7255,31 @@ process sentinels. They shall not disturb each other."
(run-at-time
0 timer-repeat
(lambda ()
- (when buffers
- (let ((time (float-time))
- (default-directory tmp-name)
- (file
- (buffer-name (nth (random (length buffers)) buffers))))
- (tramp--test-message
- "Start timer %s %s" file (current-time-string))
- (funcall timer-operation file)
- ;; Adjust timer if it takes too much time.
- (when (> (- (float-time) time) timer-repeat)
- (setq timer-repeat (* 1.5 timer-repeat))
- (setf (timer--repeat-delay timer) timer-repeat)
- (tramp--test-message "Increase timer %s" timer-repeat))
- (tramp--test-message
- "Stop timer %s %s" file (current-time-string)))))))
+ (tramp--test-with-proper-process-name-and-buffer
+ (get-buffer-process (tramp-get-buffer tramp-test-vec))
+ (when (> (- (time-to-seconds) (time-to-seconds timer-start))
+ tramp--test-asynchronous-requests-timeout)
+ (tramp--test-timeout-handler))
+ (when buffers
+ (let ((time (float-time))
+ (default-directory tmp-name)
+ (file (buffer-name (seq-random-elt buffers)))
+ ;; A remote operation in a timer could
+ ;; confuse Tramp heavily. So we ignore this
+ ;; error here.
+ (debug-ignored-errors
+ (cons 'remote-file-error debug-ignored-errors)))
+ (tramp--test-message
+ "Start timer %s %s" file (current-time-string))
+ (vc-registered file)
+ (tramp--test-message
+ "Stop timer %s %s" file (current-time-string))
+ ;; Adjust timer if it takes too much time.
+ (when (> (- (float-time) time) timer-repeat)
+ (setq timer-repeat (* 1.1 timer-repeat))
+ (setf (timer--repeat-delay timer) timer-repeat)
+ (tramp--test-message
+ "Increase timer %s" timer-repeat))))))))
;; Create temporary buffers. The number of buffers
;; corresponds to the number of processes; it could be
@@ -4198,9 +7295,9 @@ process sentinels. They shall not disturb each other."
(start-file-process-shell-command
(buffer-name buf) buf
(concat
- "(read line && echo $line >$line);"
- "(read line && cat $line);"
- "(read line && rm $line)")))
+ "(read line && echo $line >$line && echo $line);"
+ "(read line && cat $line);"
+ "(read line && rm -f $line)")))
(file (expand-file-name (buffer-name buf))))
;; Remember the file name. Add counter.
(process-put proc 'foo file)
@@ -4209,38 +7306,46 @@ process sentinels. They shall not disturb each other."
(set-process-filter
proc
(lambda (proc string)
- (with-current-buffer (process-buffer proc)
- (insert string))
- (unless (zerop (length string))
- (should (file-attributes (process-get proc 'foo))))))
- ;; Add process sentinel.
+ (tramp--test-with-proper-process-name-and-buffer proc
+ (tramp--test-message
+ "Process filter %s %s %s"
+ proc string (current-time-string))
+ (with-current-buffer (process-buffer proc)
+ (insert string))
+ (when (< (process-get proc 'bar) 2)
+ (dired-uncache (process-get proc 'foo))
+ (should (file-attributes (process-get proc 'foo)))))))
+ ;; Add process sentinel. It shall not perform remote
+ ;; operations, triggering Tramp processes. This blocks.
(set-process-sentinel
proc
(lambda (proc _state)
- (should-not (file-attributes (process-get proc 'foo)))))))
+ (tramp--test-with-proper-process-name-and-buffer proc
+ (tramp--test-message
+ "Process sentinel %s %s" proc (current-time-string)))))))
- ;; Send a string. Use a random order of the buffers. Mix
- ;; with regular operation.
+ ;; Send a string to the processes. Use a random order of
+ ;; the buffers. Mix with regular operation.
(let ((buffers (copy-sequence buffers)))
(while buffers
- ;; Activate timer.
- (sit-for 0.01 'nodisp)
- (let* ((buf (nth (random (length buffers)) buffers))
+ (let* ((buf (seq-random-elt buffers))
(proc (get-buffer-process buf))
(file (process-get proc 'foo))
(count (process-get proc 'bar)))
(tramp--test-message
"Start action %d %s %s" count buf (current-time-string))
;; Regular operation prior process action.
+ (dired-uncache file)
(if (= count 0)
(should-not (file-attributes file))
(should (file-attributes file)))
;; Send string to process.
(process-send-string proc (format "%s\n" (buffer-name buf)))
- (accept-process-output proc 0.1 nil 0)
- ;; Give the watchdog a chance.
- (read-event nil nil 0.01)
+ (while (accept-process-output nil 0))
+ (tramp--test-message
+ "Continue action %d %s %s" count buf (current-time-string))
;; Regular operation post process action.
+ (dired-uncache file)
(if (= count 2)
(should-not (file-attributes file))
(should (file-attributes file)))
@@ -4256,21 +7361,188 @@ process sentinels. They shall not disturb each other."
(tramp--test-message "Check %s" (current-time-string))
(dolist (buf buffers)
(with-current-buffer buf
- (should (string-equal (format "%s\n" buf) (buffer-string)))))
+ (should
+ (string-equal
+ ;; tramp-adb.el echoes, so we must add the three strings.
+ (if (tramp--test-adb-p)
+ (format "%s\n%s\n%s\n%s\n%s\n" buf buf buf buf buf)
+ (format "%s\n%s\n" buf buf))
+ (buffer-string)))))
(should-not
(directory-files
tmp-name nil directory-files-no-dot-files-regexp)))
;; Cleanup.
- (define-key special-event-map [sigusr1] 'ignore)
+ (define-key special-event-map [sigusr1] #'ignore)
(ignore-errors (quit-process watchdog))
(dolist (buf buffers)
(ignore-errors (delete-process (get-buffer-process buf)))
(ignore-errors (kill-buffer buf)))
(ignore-errors (cancel-timer timer))
- (ignore-errors (delete-directory tmp-name 'recursive)))))))
+ (ignore-errors (delete-directory tmp-name 'recursive))))))
+
+;; (tramp--test-deftest-direct-async-process tramp-test44-asynchronous-requests
+;; 'unstable)
+
+(ert-deftest tramp-test45-dired-compress-file ()
+ "Check that Tramp (un)compresses normal files."
+ (skip-unless (tramp--test-enabled))
+ (skip-unless (tramp--test-sh-p))
+ (skip-unless (not (tramp--test-crypt-p)))
+ ;; Starting with Emacs 29.1, `dired-compress-file' is performed by
+ ;; default handler.
+ (skip-unless (not (tramp--test-emacs29-p)))
+
+ (let ((default-directory ert-remote-temporary-file-directory)
+ (tmp-name (tramp--test-make-temp-name)))
+ (write-region "foo" nil tmp-name)
+ (dired default-directory)
+ (dired-revert)
+ (dired-goto-file tmp-name)
+ (should-not (dired-compress))
+ (should (string= (concat tmp-name ".gz") (dired-get-filename)))
+ (should-not (dired-compress))
+ (should (string= tmp-name (dired-get-filename)))
+ (delete-file tmp-name)))
+
+(ert-deftest tramp-test45-dired-compress-dir ()
+ "Check that Tramp (un)compresses directories."
+ (skip-unless (tramp--test-enabled))
+ (skip-unless (tramp--test-sh-p))
+ (skip-unless (not (tramp--test-crypt-p)))
+ ;; Starting with Emacs 29.1, `dired-compress-file' is performed by
+ ;; default handler.
+ (skip-unless (not (tramp--test-emacs29-p)))
+
+ (let ((default-directory ert-remote-temporary-file-directory)
+ (tmp-name (tramp--test-make-temp-name)))
+ (make-directory tmp-name)
+ (dired default-directory)
+ (dired-revert)
+ (dired-goto-file tmp-name)
+ (should-not (dired-compress))
+ (should (string= (concat tmp-name ".tar.gz") (dired-get-filename)))
+ (should-not (dired-compress))
+ (should (string= tmp-name (dired-get-filename)))
+ (delete-directory tmp-name)
+ (delete-file (concat tmp-name ".tar.gz"))))
+
+(ert-deftest tramp-test46-read-password ()
+ "Check Tramp password handling."
+ :tags '(:expensive-test)
+ (skip-unless (tramp--test-enabled))
+ (skip-unless (tramp--test-mock-p))
+ ;; Not all read commands understand argument "-s" or "-p".
+ (skip-unless
+ (string-empty-p
+ (let ((shell-file-name "sh"))
+ (shell-command-to-string "read -s -p Password: pass"))))
+
+ (let ((pass "secret")
+ (mock-entry (copy-sequence (assoc "mock" tramp-methods)))
+ mocked-input tramp-methods)
+ ;; We must mock `read-string', in order to avoid interactive
+ ;; arguments.
+ (cl-letf* (((symbol-function #'read-string)
+ (lambda (&rest _args) (pop mocked-input))))
+ (setcdr
+ (assq 'tramp-login-args mock-entry)
+ `((("-c")
+ (,(tramp-shell-quote-argument
+ (concat
+ "read -s -p 'Password: ' pass; echo; "
+ "(test \"pass$pass\" != \"pass" pass "\" && "
+ "echo \"Login incorrect\" || sh -i)"))))))
+ (setq tramp-methods `(,mock-entry))
+
+ ;; Reading password from stdin works.
+ (tramp-cleanup-connection tramp-test-vec 'keep-debug)
+ ;; We don't want to invalidate the password.
+ (setq mocked-input `(,(copy-sequence pass)))
+ (should (file-exists-p ert-remote-temporary-file-directory))
+
+ ;; Don't entering a password returns in error.
+ (tramp-cleanup-connection tramp-test-vec 'keep-debug)
+ (setq mocked-input nil)
+ (should-error (file-exists-p ert-remote-temporary-file-directory))
+
+ ;; A wrong password doesn't work either.
+ (tramp-cleanup-connection tramp-test-vec 'keep-debug)
+ (setq mocked-input `(,(concat pass pass)))
+ (should-error (file-exists-p ert-remote-temporary-file-directory))
+
+ ;; Reading password from auth-source works. We use the netrc
+ ;; backend; the other backends shall behave similar.
+ ;; Macro `ert-with-temp-file' was introduced in Emacs 29.1.
+ (with-no-warnings (when (symbol-plist 'ert-with-temp-file)
+ (tramp-cleanup-connection tramp-test-vec 'keep-debug)
+ (setq mocked-input nil)
+ (auth-source-forget-all-cached)
+ (ert-with-temp-file netrc-file
+ :prefix "tramp-test" :suffix ""
+ :text (format
+ "machine %s port mock password %s"
+ (file-remote-p ert-remote-temporary-file-directory 'host) pass)
+ (let ((auth-sources `(,netrc-file)))
+ (should (file-exists-p ert-remote-temporary-file-directory)))))))))
+
+;; This test is inspired by Bug#29163.
+(ert-deftest tramp-test47-auto-load ()
+ "Check that Tramp autoloads properly."
+ ;; If we use another syntax but `default', Tramp is already loaded
+ ;; due to the `tramp-change-syntax' call.
+ (skip-unless (eq tramp-syntax 'default))
+ (skip-unless (tramp--test-enabled))
-(ert-deftest tramp-test38-recursive-load ()
+ (let ((default-directory (expand-file-name temporary-file-directory))
+ (code
+ (format
+ ;; Suppress method name check.
+ "(let ((non-essential t)) \
+ (message \"Tramp loaded: %%s\" (and (file-remote-p %S) t)))"
+ ert-remote-temporary-file-directory)))
+ (should
+ (string-match-p
+ (rx "Tramp loaded: t" (+ (any "\n\r")))
+ (shell-command-to-string
+ (format
+ "%s -batch -Q -L %s --eval %s"
+ (shell-quote-argument
+ (expand-file-name invocation-name invocation-directory))
+ (mapconcat #'shell-quote-argument load-path " -L ")
+ (shell-quote-argument code)))))))
+
+(ert-deftest tramp-test47-delay-load ()
+ "Check that Tramp is loaded lazily, only when needed."
+ ;; Tramp is neither loaded at Emacs startup, nor when completing a
+ ;; non-Tramp file name like "/foo". Completing a Tramp-alike file
+ ;; name like "/foo:" autoloads Tramp, when `tramp-mode' is t.
+ (let ((default-directory (expand-file-name temporary-file-directory))
+ (code
+ "(progn \
+ (setq tramp-mode %s) \
+ (message \"Tramp loaded: %%s\" (featurep 'tramp)) \
+ (file-name-all-completions \"/foo\" \"/\") \
+ (message \"Tramp loaded: %%s\" (featurep 'tramp)) \
+ (file-name-all-completions \"/foo:\" \"/\") \
+ (message \"Tramp loaded: %%s\" (featurep 'tramp)))"))
+ ;; Tramp doesn't load when `tramp-mode' is nil.
+ (dolist (tm '(t nil))
+ (should
+ (string-match-p
+ (tramp-compat-rx
+ "Tramp loaded: nil" (+ (any "\n\r"))
+ "Tramp loaded: nil" (+ (any "\n\r"))
+ "Tramp loaded: " (literal (symbol-name tm)) (+ (any "\n\r")))
+ (shell-command-to-string
+ (format
+ "%s -batch -Q -L %s --eval %s"
+ (shell-quote-argument
+ (expand-file-name invocation-name invocation-directory))
+ (mapconcat #'shell-quote-argument load-path " -L ")
+ (shell-quote-argument (format code tm)))))))))
+
+(ert-deftest tramp-test47-recursive-load ()
"Check that Tramp does not fail due to recursive load."
(skip-unless (tramp--test-enabled))
@@ -4278,22 +7550,23 @@ process sentinels. They shall not disturb each other."
(dolist (code
(list
(format
- "(expand-file-name %S)" tramp-test-temporary-file-directory)
+ "(expand-file-name %S)" ert-remote-temporary-file-directory)
(format
"(let ((default-directory %S)) (expand-file-name %S))"
- tramp-test-temporary-file-directory
+ ert-remote-temporary-file-directory
temporary-file-directory)))
(should-not
- (string-match
+ (string-match-p
"Recursive load"
(shell-command-to-string
(format
"%s -batch -Q -L %s --eval %s"
- (expand-file-name invocation-name invocation-directory)
- (mapconcat 'shell-quote-argument load-path " -L ")
+ (shell-quote-argument
+ (expand-file-name invocation-name invocation-directory))
+ (mapconcat #'shell-quote-argument load-path " -L ")
(shell-quote-argument code))))))))
-(ert-deftest tramp-test39-remote-load-path ()
+(ert-deftest tramp-test47-remote-load-path ()
"Check that Tramp autoloads its packages with remote `load-path'."
;; `tramp-cleanup-all-connections' is autoloaded from tramp-cmds.el.
;; It shall still work, when a remote file name is in the
@@ -4304,83 +7577,128 @@ process sentinels. They shall not disturb each other."
(load-path (cons \"/foo:bar:\" load-path))) \
(tramp-cleanup-all-connections))"))
(should
- (string-match
- (format
- "Loading %s"
- (expand-file-name
- "tramp-cmds" (file-name-directory (locate-library "tramp"))))
+ (string-match-p
+ (tramp-compat-rx
+ "Loading "
+ (literal
+ (expand-file-name
+ "tramp-cmds" (file-name-directory (locate-library "tramp")))))
(shell-command-to-string
(format
"%s -batch -Q -L %s -l tramp-sh --eval %s"
- (expand-file-name invocation-name invocation-directory)
- (mapconcat 'shell-quote-argument load-path " -L ")
+ (shell-quote-argument
+ (expand-file-name invocation-name invocation-directory))
+ (mapconcat #'shell-quote-argument load-path " -L ")
(shell-quote-argument code)))))))
-(ert-deftest tramp-test40-unload ()
+(ert-deftest tramp-test48-unload ()
"Check that Tramp and its subpackages unload completely.
Since it unloads Tramp, it shall be the last test to run."
:tags '(:expensive-test)
- (skip-unless noninteractive)
-
- (when (featurep 'tramp)
- (unload-feature 'tramp 'force)
- ;; No Tramp feature must be left.
- (should-not (featurep 'tramp))
- (should-not (all-completions "tramp" (delq 'tramp-tests features)))
- ;; `file-name-handler-alist' must be clean.
- (should-not (all-completions "tramp" (mapcar 'cdr file-name-handler-alist)))
- ;; There shouldn't be left a bound symbol, except buffer-local
- ;; variables, and autoload functions. We do not regard our test
- ;; symbols, and the Tramp unload hooks.
- (mapatoms
- (lambda (x)
- (and (or (and (boundp x) (null (local-variable-if-set-p x)))
- (and (functionp x) (null (autoloadp (symbol-function x)))))
- (string-match "^tramp" (symbol-name x))
- (not (string-match "^tramp--?test" (symbol-name x)))
- (not (string-match "unload-hook$" (symbol-name x)))
- (ert-fail (format "`%s' still bound" x)))))
- ;; The defstruct `tramp-file-name' and all its internal functions
- ;; shall be purged.
- (should-not (cl--find-class 'tramp-file-name))
- (mapatoms
- (lambda (x)
- (and (functionp x)
- (string-match "tramp-file-name" (symbol-name x))
- (ert-fail (format "Structure function `%s' still exists" x)))))
- ;; There shouldn't be left a hook function containing a Tramp
- ;; function. We do not regard the Tramp unload hooks.
- (mapatoms
- (lambda (x)
- (and (boundp x)
- (string-match "-\\(hook\\|function\\)s?$" (symbol-name x))
- (not (string-match "unload-hook$" (symbol-name x)))
- (consp (symbol-value x))
- (ignore-errors (all-completions "tramp" (symbol-value x)))
- (ert-fail (format "Hook `%s' still contains Tramp function" x)))))))
+ ;; We have autoloaded objects from tramp.el and tramp-archive.el.
+ ;; In order to remove them, we first need to load both packages.
+ (require 'tramp)
+ (require 'tramp-archive)
+ (should (featurep 'tramp))
+ (should (featurep 'tramp-archive))
+ ;; This unloads also tramp-archive.el and tramp-theme.el if needed.
+ (unload-feature 'tramp 'force)
+
+ ;; No Tramp feature must be left except the test packages.
+ (should-not (featurep 'tramp))
+ (should-not (featurep 'tramp-archive))
+ (should-not (featurep 'tramp-theme))
+ (should-not
+ (all-completions
+ "tramp" (delq 'tramp-tests (delq 'tramp-archive-tests features))))
+
+ ;; `file-name-handler-alist' must be clean.
+ (should-not (all-completions "tramp" (mapcar #'cdr file-name-handler-alist)))
+
+ ;; There shouldn't be left a bound symbol, except buffer-local
+ ;; variables, and autoloaded functions. We do not regard our test
+ ;; symbols, and the Tramp unload hooks.
+ (mapatoms
+ (lambda (x)
+ (and (or (and (boundp x) (null (local-variable-if-set-p x)))
+ (and (functionp x) (null (autoloadp (symbol-function x))))
+ (macrop x))
+ (string-prefix-p "tramp" (symbol-name x))
+ ;; `tramp-completion-mode' is autoloaded in Emacs < 28.1.
+ (not (eq 'tramp-completion-mode x))
+ (not (string-match-p
+ (rx bol "tramp" (? "-archive") (** 1 2 "-") "test")
+ (symbol-name x)))
+ (not (string-suffix-p "unload-hook" (symbol-name x)))
+ (not (get x 'tramp-autoload))
+ (ert-fail (format "`%s' still bound" x)))))
+
+ ;; The defstruct `tramp-file-name' and all its internal functions
+ ;; shall be purged.
+ (should-not (cl--find-class 'tramp-file-name))
+ (mapatoms
+ (lambda (x)
+ (and (functionp x) (null (autoloadp (symbol-function x)))
+ (string-prefix-p "tramp-file-name" (symbol-name x))
+ (ert-fail (format "Structure function `%s' still exists" x)))))
+
+ ;; There shouldn't be left a hook function containing a Tramp
+ ;; function. We do not regard the Tramp unload hooks.
+ (mapatoms
+ (lambda (x)
+ (and (boundp x)
+ (string-match-p
+ (rx "-" (| "hook" "function") (? "s") eol) (symbol-name x))
+ (not (string-suffix-p "unload-hook" (symbol-name x)))
+ (consp (symbol-value x))
+ (ignore-errors (all-completions "tramp" (symbol-value x)))
+ (ert-fail (format "Hook `%s' still contains Tramp function" x)))))
+
+ ;; There shouldn't be left an advice function from Tramp.
+ (mapatoms
+ (lambda (x)
+ (and (functionp x)
+ (advice-mapc
+ (lambda (fun _symbol)
+ (and (string-prefix-p "tramp" (symbol-name fun))
+ (ert-fail
+ (format "Function `%s' still contains Tramp advice" x))))
+ x))))
+
+ ;; Reload.
+ (require 'tramp)
+ (require 'tramp-archive)
+ (should (featurep 'tramp))
+ (should (featurep 'tramp-archive)))
+
+(defun tramp-test-all (&optional interactive)
+ "Run all tests for \\[tramp].
+If INTERACTIVE is non-nil, the tests are run interactively."
+ (interactive "p")
+ (funcall
+ (if interactive #'ert-run-tests-interactively #'ert-run-tests-batch)
+ (rx bol "tramp")))
;; TODO:
-;; * dired-compress-file
-;; * dired-uncache
-;; * file-acl
+;; * dired-uncache (partly done in other test functions)
+;; * file-equal-p (partly done in `tramp-test21-file-links')
+;; * file-in-directory-p
;; * file-name-case-insensitive-p
-;; * file-selinux-context
-;; * find-backup-file-name
-;; * set-file-acl
-;; * set-file-selinux-context
+;; * tramp-get-remote-gid
+;; * tramp-get-remote-groups
+;; * tramp-get-remote-uid
+;; * tramp-set-file-uid-gid
;; * Work on skipped tests. Make a comment, when it is impossible.
-;; * Fix `tramp-test05-expand-file-name-relative' in `expand-file-name'.
-;; * Fix `tramp-test06-directory-file-name' for `ftp'.
-;; * Fix `tramp-test27-start-file-process' on MS Windows (`process-send-eof'?).
-;; * Fix Bug#16928 in `tramp-test37-asynchronous-requests'.
-
-(defun tramp-test-all (&optional interactive)
- "Run all tests for \\[tramp]."
- (interactive "p")
- (funcall
- (if interactive 'ert-run-tests-interactively 'ert-run-tests-batch) "^tramp"))
+;; * Revisit expensive tests, once problems in `tramp-error' are solved.
+;; * Fix `tramp-test06-directory-file-name' for "ftp".
+;; * Implement `tramp-test31-interrupt-process' and
+;; `tramp-test31-signal-process' for "adb", "sshfs" and for direct
+;; async processes. Check, why they don't run stable.
+;; * Check, why direct async processes do not work for
+;; `tramp-test44-asynchronous-requests'.
(provide 'tramp-tests)
+
;;; tramp-tests.el ends here
diff --git a/test/lisp/net/webjump-tests.el b/test/lisp/net/webjump-tests.el
new file mode 100644
index 00000000000..457e4659914
--- /dev/null
+++ b/test/lisp/net/webjump-tests.el
@@ -0,0 +1,73 @@
+;;; webjump-tests.el --- Tests for webjump.el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+;; Author: Simen Heggestøyl <simenheg@gmail.com>
+;; Keywords:
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;
+
+;;; Code:
+
+(require 'ert)
+(require 'webjump)
+
+(ert-deftest webjump-tests-builtin ()
+ (should (equal (webjump-builtin '[name] "gnu.org") "gnu.org")))
+
+(ert-deftest webjump-tests-builtin-check-args ()
+ (should (webjump-builtin-check-args [1 2 3] "Foo" 2))
+ (should-error (webjump-builtin-check-args [1 2 3] "Foo" 3)))
+
+(ert-deftest webjump-tests-mirror-default ()
+ (should (equal (webjump-mirror-default
+ '("https://ftp.gnu.org/pub/gnu/"
+ "https://ftpmirror.gnu.org"))
+ "https://ftp.gnu.org/pub/gnu/")))
+
+(ert-deftest webjump-tests-null-or-blank-string-p ()
+ (should (webjump-null-or-blank-string-p nil))
+ (should (webjump-null-or-blank-string-p ""))
+ (should (webjump-null-or-blank-string-p " "))
+ (should-not (webjump-null-or-blank-string-p " . ")))
+
+(ert-deftest webjump-tests-url-encode ()
+ (should (equal (webjump-url-encode "") ""))
+ (should (equal (webjump-url-encode "a b c") "a+b+c"))
+ (should (equal (webjump-url-encode "foo?") "foo%3F"))
+ (should (equal (webjump-url-encode "/foo\\") "/foo%5C"))
+ (should (equal (webjump-url-encode "f&o") "f%26o")))
+
+(ert-deftest webjump-tests-url-fix ()
+ (should (equal (webjump-url-fix nil) ""))
+ (should (equal (webjump-url-fix "/tmp/") "file:///tmp/"))
+ (should (equal (webjump-url-fix "gnu.org") "http://gnu.org/"))
+ (should (equal (webjump-url-fix "ftp.x.org") "ftp://ftp.x.org/"))
+ (should (equal (webjump-url-fix "https://gnu.org")
+ "https://gnu.org/")))
+
+(ert-deftest webjump-tests-url-fix-trailing-slash ()
+ (should (equal (webjump-url-fix-trailing-slash "https://gnu.org")
+ "https://gnu.org/"))
+ (should (equal (webjump-url-fix-trailing-slash "https://gnu.org/")
+ "https://gnu.org/")))
+
+(provide 'webjump-tests)
+;;; webjump-tests.el ends here
diff --git a/test/lisp/newcomment-tests.el b/test/lisp/newcomment-tests.el
new file mode 100644
index 00000000000..a4e28471411
--- /dev/null
+++ b/test/lisp/newcomment-tests.el
@@ -0,0 +1,39 @@
+;;; newcomment-tests.el --- Tests for newcomment.el -*- lexical-binding:t -*-
+
+;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+
+(ert-deftest test-uncomment-space-comment-continue ()
+ (let ((comment-style 'multi-line)
+ (comment-continue " ")
+ (text " a\n b"))
+ (should
+ (equal text
+ (with-temp-buffer
+ (c-mode)
+ (insert text)
+ (comment-region (point-min) (point-max))
+ (uncomment-region (point-min) (point-max))
+ (buffer-string))))))
+
+;;; newcomment-tests.el ends here
diff --git a/test/lisp/nxml/nxml-mode-tests.el b/test/lisp/nxml/nxml-mode-tests.el
new file mode 100644
index 00000000000..04346e0f4f9
--- /dev/null
+++ b/test/lisp/nxml/nxml-mode-tests.el
@@ -0,0 +1,159 @@
+;;; nxml-mode-tests.el --- Test NXML Mode -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2019-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'nxml-mode)
+
+(defun nxml-mode-tests-correctly-indented-string (str)
+ (with-temp-buffer
+ (nxml-mode)
+ (insert str)
+ (indent-region (point-min) (point-max))
+ (equal (buffer-string) str)))
+
+(ert-deftest nxml-indent-line-after-attribute ()
+ (should (nxml-mode-tests-correctly-indented-string "
+<settings
+ xmlns=\"http://maven.apache.org/SETTINGS/1.0.0\"
+ xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"
+ xsi:schemaLocation=\"http://maven.apache.org/SETTINGS/1.0.0
+ https://maven.apache.org/xsd/settings-1.0.0.xsd\">
+ <mirrors>
+ ...
+ </mirrors>
+</settings>
+"))
+ (should (nxml-mode-tests-correctly-indented-string "\
+<x>
+ <abc xx=\"x/x/x/x/x/x/x/
+ y/y/y/y/y/y/
+ \">
+ <zzz/>
+ </abc>
+ <nl>&#10;</nl>
+</x>
+")))
+
+(ert-deftest nxml-balanced-close-start-tag-inline ()
+ (with-temp-buffer
+ (nxml-mode)
+ (insert "<a><b c=\"\"</a>")
+ (search-backward "</a>")
+ (nxml-balanced-close-start-tag-inline)
+ (should (equal (buffer-string) "<a><b c=\"\"></b></a>"))))
+
+(ert-deftest nxml-mode-font-lock-quotes ()
+ (with-temp-buffer
+ (nxml-mode)
+ (insert "<x a=\"dquote attr\" b='squote attr'>\"dquote text\"'squote text'</x>")
+ (font-lock-ensure)
+ (let ((squote-txt-pos (search-backward "squote text"))
+ (dquote-txt-pos (search-backward "dquote text"))
+ (squote-att-pos (search-backward "squote attr"))
+ (dquote-att-pos (search-backward "dquote attr")))
+ ;; Just make sure that each quote uses the same face for quoted
+ ;; attribute values, and a different face for quoted text
+ ;; outside tags. Don't test `font-lock-string-face' vs
+ ;; `nxml-attribute-value' here.
+ (should (equal (get-text-property squote-att-pos 'face)
+ (get-text-property dquote-att-pos 'face)))
+ (should (equal (get-text-property squote-txt-pos 'face)
+ (get-text-property dquote-txt-pos 'face)))
+ (should-not (equal (get-text-property squote-txt-pos 'face)
+ (get-text-property dquote-att-pos 'face))))))
+
+(ert-deftest nxml-mode-doctype-and-quote-syntax ()
+ (with-temp-buffer
+ (insert "<!DOCTYPE t [\n<!ENTITY f SYSTEM \"f.xml\">\n]>\n<t>'</t>")
+ (nxml-mode)
+ ;; Check that last tag is parsed as a tag.
+ (should (= 1 (car (syntax-ppss (1- (point-max))))))
+ (should (= 0 (car (syntax-ppss (point-max)))))))
+
+(ert-deftest nxml-mode-prolog-comment ()
+ (with-temp-buffer
+ (insert "<?xml version=\"1.0\" encoding=\"utf-8\"?><!-- comment1 -->
+<t><!-- comment2 --></t><!-- comment3 -->")
+ (nxml-mode)
+ ;; Check that all comments are parsed as comments
+ (goto-char (point-min))
+ (search-forward "comment1")
+ (should (nth 4 (syntax-ppss)))
+ (search-forward "comment2")
+ (should (nth 4 (syntax-ppss)))
+ (search-forward "comment3")))
+
+(ert-deftest nxml-mode->-after-quote ()
+ "Reduction from Bug#36092."
+ (with-temp-buffer
+ (insert "<root>\n"
+ (make-string 1794 ?a) "\n"
+ "'>"
+ (make-string 196 ?a) "\n"
+ "</root>")
+ (nxml-mode)
+ (syntax-propertize 2001)
+ (syntax-propertize (point-max)) ; Triggered an assert failure.
+ ;; Check that last tag is parsed as a tag.
+ (should (= 1 (- (car (syntax-ppss (1- (point-max))))
+ (car (syntax-ppss (point-max))))))))
+
+(ert-deftest nxml-mode-edit-prolog ()
+ "Test for Bug#23668."
+ (with-temp-buffer
+ (insert "
+ <t>
+ <sub/>
+</t>")
+ (nxml-mode)
+ ;; The leading "\n " before "<t>" is the prolog, indenting will
+ ;; delete the space hence changing the prolog size. If that is
+ ;; not taken into account, then the <sub/> tag won't be indented
+ ;; correctly.
+ (indent-region (point-min) (point-max))
+ (should (equal (buffer-string) "
+<t>
+ <sub/>
+</t>"))))
+
+(ert-deftest nxml-mode-test-comment-bug-17264 ()
+ "Test for Bug#17264."
+ (with-temp-buffer
+ (nxml-mode)
+ (let ((data "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
+<spocosy version=\"1.0\" responsetime=\"2011-03-15 13:53:12\" exec=\"0.171\">
+ <!--
+ <query-response requestid=\"\" service=\"objectquery\">
+ <sport name=\"Soccer\" enetSportCode=\"s\" del=\"no\" n=\"1\" ut=\"2009-12-29
+ 15:36:24\" id=\"1\">
+ </sport>
+ </query-response>
+ -->
+</spocosy>
+"))
+ (insert data)
+ (goto-char (point-min))
+ (search-forward "<query-response")
+ ;; Inside comment
+ (should (eq (nth 4 (syntax-ppss)) t)))))
+
+(provide 'nxml-mode-tests)
+;;; nxml-mode-tests.el ends here
diff --git a/test/lisp/nxml/xsd-regexp-tests.el b/test/lisp/nxml/xsd-regexp-tests.el
new file mode 100644
index 00000000000..bd43889a5ae
--- /dev/null
+++ b/test/lisp/nxml/xsd-regexp-tests.el
@@ -0,0 +1,32 @@
+;;; xsd-regexp-tests.el --- Test NXML Mode -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2019-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'xsd-regexp)
+
+(ert-deftest xsdre-matches ()
+ (should (equal (string-match (xsdre-translate "\\p{Pd}") "a-b") 1))
+ ;; this fails:
+ (should (equal (string-match (xsdre-translate "\\p{P}") "a-b") 1)))
+
+(provide 'xsd-regexp-tests)
+
+;;; xsd-regexp-tests.el ends here
diff --git a/test/lisp/obarray-tests.el b/test/lisp/obarray-tests.el
index dca7c856783..f34109af242 100644
--- a/test/lisp/obarray-tests.el
+++ b/test/lisp/obarray-tests.el
@@ -1,6 +1,6 @@
;;; obarray-tests.el --- Tests for obarray -*- lexical-binding: t; -*-
-;; Copyright (C) 2015-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2022 Free Software Foundation, Inc.
;; Author: Przemysław Wojnowski <esperanto@cumego.com>
diff --git a/test/lisp/obsolete/cl-tests.el b/test/lisp/obsolete/cl-tests.el
new file mode 100644
index 00000000000..5a701a1e550
--- /dev/null
+++ b/test/lisp/obsolete/cl-tests.el
@@ -0,0 +1,35 @@
+;;; cl-tests.el --- tests for emacs-lisp/cl.el -*- lexical-binding:t -*-
+
+;; Copyright (C) 2018-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(with-no-warnings
+ (require 'cl))
+(require 'ert)
+
+(ert-deftest labels-function-quoting ()
+ "Test that #'foo does the right thing in `labels'." ; Bug#31792.
+ (with-suppressed-warnings ((obsolete labels))
+ (should (eq (funcall (labels ((foo () t))
+ #'foo))
+ t))))
+
+;;; cl-tests.el ends here
diff --git a/test/lisp/obsolete/inversion-tests.el b/test/lisp/obsolete/inversion-tests.el
new file mode 100644
index 00000000000..8af91d7d147
--- /dev/null
+++ b/test/lisp/obsolete/inversion-tests.el
@@ -0,0 +1,80 @@
+;;; inversion-tests.el --- Tests for inversion.el -*- lexical-binding:t -*-
+
+;; Copyright (C) 2008-2022 Free Software Foundation, Inc.
+
+;; Author: Eric M. Ludlam <zappo@gnu.org>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Moved here from test/manual/cedet/cedet-utests.el
+
+;;; Code:
+
+(require 'inversion)
+(require 'ert)
+
+(ert-deftest inversion-unit-test ()
+ "Test inversion to make sure it can identify different version strings."
+ (let ((c1 (inversion-package-version 'inversion))
+ (c1i (inversion-package-incompatibility-version 'inversion))
+ (c2 (inversion-decode-version "1.3alpha2"))
+ (c3 (inversion-decode-version "1.3beta4"))
+ (c4 (inversion-decode-version "1.3 beta5"))
+ (c5 (inversion-decode-version "1.3.4"))
+ (c6 (inversion-decode-version "2.3alpha"))
+ (c7 (inversion-decode-version "1.3"))
+ (c8 (inversion-decode-version "1.3pre1"))
+ (c9 (inversion-decode-version "2.4 (patch 2)"))
+ (c10 (inversion-decode-version "2.4 (patch 3)"))
+ (c11 (inversion-decode-version "2.4.2.1"))
+ (c12 (inversion-decode-version "2.4.2.2")))
+ (should (inversion-= c1 c1))
+ (should (inversion-< c1i c1))
+ (should (inversion-< c2 c3))
+ (should (inversion-< c3 c4))
+ (should (inversion-< c4 c5))
+ (should (inversion-< c5 c6))
+ (should (inversion-< c2 c4))
+ (should (inversion-< c2 c5))
+ (should (inversion-< c2 c6))
+ (should (inversion-< c3 c5))
+ (should (inversion-< c3 c6))
+ (should (inversion-< c7 c6))
+ (should (inversion-< c4 c7))
+ (should (inversion-< c2 c7))
+ (should (inversion-< c8 c6))
+ (should (inversion-< c8 c7))
+ (should (inversion-< c4 c8))
+ (should (inversion-< c2 c8))
+ (should (inversion-< c9 c10))
+ (should (inversion-< c10 c11))
+ (should (inversion-< c11 c12))
+ ;; Negatives
+ (should-not (inversion-< c3 c2))
+ (should-not (inversion-< c4 c3))
+ (should-not (inversion-< c5 c4))
+ (should-not (inversion-< c6 c5))
+ (should-not (inversion-< c7 c2))
+ (should-not (inversion-< c7 c8))
+ (should-not (inversion-< c12 c11))
+ ;; Test the tester on inversion
+ (should-not (inversion-test 'inversion inversion-version))
+ (should (stringp (inversion-test 'inversion "0.0.0")))
+ (should (stringp (inversion-test 'inversion "1000.0")))))
+
+;;; inversion-tests.el ends here
diff --git a/test/lisp/obsolete/makesum-tests.el b/test/lisp/obsolete/makesum-tests.el
new file mode 100644
index 00000000000..e5317be847b
--- /dev/null
+++ b/test/lisp/obsolete/makesum-tests.el
@@ -0,0 +1,58 @@
+;;; makesum-tests.el --- Tests for makesum.el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2019-2022 Free Software Foundation, Inc.
+
+;; Author: Simen Heggestøyl <simenheg@gmail.com>
+;; Keywords:
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;
+
+;;; Code:
+
+(require 'ert)
+(require 'makesum)
+
+(ert-deftest makesum-tests-double-column-even-lines ()
+ (with-temp-buffer
+ (insert "a\nb\nc\nd\ne\nf")
+ (double-column (point-min) (point-max))
+ (should (string-match-p "a[ \t]+d\nb[ \t]+e\nc[ \t]+f" (buffer-string)))))
+
+(ert-deftest makesum-tests-double-column-odd-lines ()
+ (with-temp-buffer
+ (insert "a\nb\nc\nd\ne")
+ (double-column (point-min) (point-max))
+ (should (string-match-p "a[ \t]+d\nb[ \t]+e\nc" (buffer-string)))))
+
+(ert-deftest makesum-tests-double-column-noop ()
+ (with-temp-buffer
+ (insert "foo")
+ (let ((prev-buffer-string (buffer-string)))
+ (double-column (point-min) (point-max))
+ (should (equal prev-buffer-string (buffer-string))))))
+
+(ert-deftest makesum-tests-double-column-partial ()
+ (with-temp-buffer
+ (insert "a\nb\nc\nd\ne\nf")
+ (double-column 3 10)
+ (should (string-match-p "a\nb[ \t]+d\nc[ \t]+e\nf" (buffer-string)))))
+
+(provide 'makesum-tests)
+;;; makesum-tests.el ends here
diff --git a/test/lisp/obsolete/rfc2368-tests.el b/test/lisp/obsolete/rfc2368-tests.el
new file mode 100644
index 00000000000..28fac3785cd
--- /dev/null
+++ b/test/lisp/obsolete/rfc2368-tests.el
@@ -0,0 +1,39 @@
+;;; rfc2368-tests.el --- Tests for rfc2368.el -*- lexical-binding:t -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'rfc2368)
+
+(ert-deftest rfc2368-unhexify-string ()
+ (should (equal (rfc2368-unhexify-string "hello%20there") "hello there")))
+
+(ert-deftest rfc2368-parse-mailto-url ()
+ (should (equal (rfc2368-parse-mailto-url "mailto:foo@example.org?subject=Foo&bar=baz")
+ '(("To" . "foo@example.org") ("Subject" . "Foo") ("Bar" . "baz"))))
+ (should (equal (rfc2368-parse-mailto-url "mailto:foo@bar.com?to=bar@example.org")
+ '(("To" . "foo@bar.com, bar@example.org"))))
+ (should (equal (rfc2368-parse-mailto-url "mailto:foo@bar.com?subject=bar%20baz")
+ '(("To" . "foo@bar.com") ("Subject" . "bar baz")))))
+
+(provide 'rfc2368-tests)
+;;; rfc2368-tests.el ends here
diff --git a/test/lisp/obsolete/thumbs-tests.el b/test/lisp/obsolete/thumbs-tests.el
new file mode 100644
index 00000000000..a8972394fa5
--- /dev/null
+++ b/test/lisp/obsolete/thumbs-tests.el
@@ -0,0 +1,32 @@
+;;; thumbs-tests.el --- tests for thumbs.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'ert-x)
+(require 'thumbs)
+
+(ert-deftest thumbs-tests-thumbsdir/create-if-missing ()
+ (ert-with-temp-directory thumbs-thumbsdir
+ (delete-directory thumbs-thumbsdir)
+ (should (file-directory-p (thumbs-thumbsdir)))))
+
+(provide 'thumbs-tests)
+;;; thumbs-tests.el ends here
diff --git a/test/lisp/org/org-tests.el b/test/lisp/org/org-tests.el
new file mode 100644
index 00000000000..91c8ffc48de
--- /dev/null
+++ b/test/lisp/org/org-tests.el
@@ -0,0 +1,33 @@
+;;; org-tests.el --- tests for org/org.el -*- lexical-binding:t -*-
+
+;; Copyright (C) 2018-2022 Free Software Foundation, Inc.
+
+;; Maintainer: emacs-devel@gnu.org
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(ert-deftest org-package-version ()
+ "Test Version: header is present and correct.
+Ref <https://debbugs.gnu.org/30310>."
+ (should (require 'org-version nil t))
+ (should (equal (version-to-list (org-release))
+ (cdr (assq 'org package--builtin-versions)))))
+
+;;; org-tests.el ends here
diff --git a/test/lisp/osc-tests.el b/test/lisp/osc-tests.el
new file mode 100644
index 00000000000..d53bab08d3d
--- /dev/null
+++ b/test/lisp/osc-tests.el
@@ -0,0 +1,57 @@
+;;; osc-tests.el --- Tests for osc.el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; Author: Matthias Meulien <orontee@gmail.com>
+;; Keywords:
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;
+
+;;; Code:
+
+(require 'osc)
+(require 'ert)
+
+(defvar osc-tests--strings
+ `(
+ ("Hello World" "Hello World")
+
+ ;; window title
+ ("Buffer \e]2;A window title\e\\content" "Buffer content")
+
+ ;; window title
+ ("Unfinished \e]2;window title" "Unfinished \e]2;window title")
+
+ ;; current directory
+ ("\e]7;file://127.0.0.1/tmp\e\\user@host$ " "user@host$ ")
+
+ ;; hyperlink
+ ("\e]8;;http://example.com\e\\This is a link\e]8;;\e\\" "This is a link")
+ ))
+;; Don't output those strings to stdout since they may have
+;; side-effects on the environment
+
+(ert-deftest osc-tests-apply-region-no-handlers ()
+ (let ((osc-handlers nil))
+ (pcase-dolist (`(,input ,text) osc-tests--strings)
+ (with-temp-buffer
+ (insert input)
+ (osc-apply-on-region (point-min) (point-max))
+ (should (equal (buffer-string) text))))))
diff --git a/test/lisp/paren-tests.el b/test/lisp/paren-tests.el
new file mode 100644
index 00000000000..baf5590cb94
--- /dev/null
+++ b/test/lisp/paren-tests.el
@@ -0,0 +1,152 @@
+;;; paren-tests.el --- Tests for paren.el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2019-2022 Free Software Foundation, Inc.
+
+;; Author: Simen Heggestøyl <simenheg@gmail.com>
+;; Keywords:
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;
+
+;;; Code:
+
+(require 'ert)
+(require 'paren)
+
+(ert-deftest paren-tests-unescaped-p ()
+ (with-temp-buffer
+ (insert "(insert)")
+ (backward-char)
+ (should (show-paren--unescaped-p (point)))
+ (insert "\\")
+ (should-not (show-paren--unescaped-p (point)))))
+
+(ert-deftest paren-tests-categorize-paren ()
+ (with-temp-buffer
+ (insert "(insert)")
+ (backward-char)
+ (should (equal (show-paren--categorize-paren (point))
+ (cons -1 (+ (point) 1))))
+ (goto-char (point-min))
+ (should (equal (show-paren--categorize-paren (point))
+ (cons 1 (point))))))
+
+(ert-deftest paren-tests-locate-near-paren ()
+ (with-temp-buffer
+ (let ((show-paren-when-point-inside-paren nil)
+ (show-paren-when-point-in-periphery nil))
+ (insert "(insert)")
+ (should (equal (show-paren--locate-near-paren)
+ (cons -1 (point))))
+ (backward-char)
+ (should-not (show-paren--locate-near-paren))
+ (goto-char (point-min))
+ (should (equal (show-paren--locate-near-paren)
+ (cons 1 (point-min))))
+ (forward-char)
+ (should-not (show-paren--locate-near-paren)))))
+
+(ert-deftest paren-tests-locate-near-paren-inside ()
+ (with-temp-buffer
+ (let ((show-paren-when-point-inside-paren t)
+ (show-paren-when-point-in-periphery nil))
+ (insert "(insert)")
+ (should (equal (show-paren--locate-near-paren)
+ (cons -1 (point))))
+ (backward-char)
+ (should (equal (show-paren--locate-near-paren)
+ (cons -1 (+ (point) 1))))
+ (goto-char (point-min))
+ (should (equal (show-paren--locate-near-paren)
+ (cons 1 (point-min))))
+ (forward-char)
+ (should (equal (show-paren--locate-near-paren)
+ (cons 1 (point-min)))))))
+
+(ert-deftest paren-tests-locate-near-paren-in-periphery ()
+ (with-temp-buffer
+ (let ((show-paren-when-point-inside-paren nil)
+ (show-paren-when-point-in-periphery t))
+ (insert " (insert) ")
+ (should (equal (show-paren--locate-near-paren)
+ (cons -1 (- (point) 1))))
+ (backward-char 2)
+ (should-not (show-paren--locate-near-paren))
+ (goto-char (point-min))
+ (should (equal (show-paren--locate-near-paren)
+ (cons 1 (+ (point) 1))))
+ (forward-char)
+ (should (equal (show-paren--locate-near-paren)
+ (cons 1 (point))))
+ (forward-char)
+ (should-not (show-paren--locate-near-paren)))))
+
+(ert-deftest paren-tests-default ()
+ (with-temp-buffer
+ (insert "(insert")
+ (goto-char (point-min))
+ (should (equal (show-paren--default)
+ (list (point) (+ (point) 1)
+ nil nil
+ t)))
+ (goto-char (point-max))
+ (insert ")")
+ (should (equal (show-paren--default)
+ (list (- (point) 1) (point)
+ (point-min) (+ (point-min) 1)
+ nil)))
+ (goto-char (point-min))
+ (should (equal (show-paren--default)
+ (list (point) (+ (point) 1)
+ (- (point-max) 1) (point-max)
+ nil)))))
+
+(ert-deftest paren-tests-open-paren-line ()
+ (cl-flet ((open-paren-line ()
+ (let* ((data (show-paren--default))
+ (here-beg (nth 0 data))
+ (there-beg (nth 2 data)))
+ (blink-paren-open-paren-line-string
+ (min here-beg there-beg)))))
+ ;; Lisp-like
+ (with-temp-buffer
+ (insert "(defun foo ()
+ (dummy))")
+ (goto-char (point-max))
+ (should (string= "(defun foo ()" (open-paren-line))))
+
+ ;; C-like
+ (with-temp-buffer
+ (insert "int foo() {
+ int blah;
+ }")
+ (goto-char (point-max))
+ (should (string= "int foo() {" (open-paren-line))))
+
+ ;; C-like with hanging {
+ (with-temp-buffer
+ (insert "int foo()
+ {
+ int blah;
+ }")
+ (goto-char (point-max))
+ (should (string= "int foo()...{" (open-paren-line))))))
+
+(provide 'paren-tests)
+;;; paren-tests.el ends here
diff --git a/test/lisp/password-cache-tests.el b/test/lisp/password-cache-tests.el
new file mode 100644
index 00000000000..ca760c2fb3c
--- /dev/null
+++ b/test/lisp/password-cache-tests.el
@@ -0,0 +1,75 @@
+;;; password-cache-tests.el --- Tests for password-cache.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2019-2022 Free Software Foundation, Inc.
+
+;; Author: Stefan Kangas <stefankangas@gmail.com>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'password-cache)
+
+(ert-deftest password-cache-tests-add-and-remove ()
+ (let ((password-data (copy-hash-table password-data)))
+ (password-cache-add "foo" (copy-sequence "bar"))
+ (should (eq (password-in-cache-p "foo") t))
+ (password-cache-remove "foo")
+ (should (not (password-in-cache-p "foo")))))
+
+(ert-deftest password-cache-tests-read-from-cache ()
+ (let ((password-data (copy-hash-table password-data)))
+ (password-cache-add "foo" (copy-sequence "bar"))
+ (should (equal (password-read-from-cache "foo") "bar"))
+ (should (not (password-read-from-cache nil)))))
+
+(ert-deftest password-cache-tests-in-cache-p ()
+ (let ((password-data (copy-hash-table password-data)))
+ (password-cache-add "foo" (copy-sequence "bar"))
+ (should (password-in-cache-p "foo"))
+ (should (not (password-read-from-cache nil)))))
+
+(ert-deftest password-cache-tests-read ()
+ (let ((password-data (copy-hash-table password-data)))
+ (password-cache-add "foo" (copy-sequence "bar"))
+ (should (equal (password-read nil "foo") "bar"))))
+
+(ert-deftest password-cache-tests-reset ()
+ (let ((password-data (copy-hash-table password-data)))
+ (password-cache-add "foo" (copy-sequence "bar"))
+ (password-reset)
+ (should (not (password-in-cache-p "foo")))))
+
+(ert-deftest password-cache-tests-add/expires-key ()
+ :tags '(:expensive-test)
+ (let ((password-data (copy-hash-table password-data))
+ (password-cache-expiry 0.01))
+ (password-cache-add "foo" (copy-sequence "bar"))
+ (sit-for 0.1)
+ (should (not (password-in-cache-p "foo")))))
+
+(ert-deftest password-cache-tests-no-password-cache ()
+ (let ((password-data (copy-hash-table password-data))
+ (password-cache nil))
+ (password-cache-add "foo" (copy-sequence "bar"))
+ (should (not (password-in-cache-p "foo")))
+ (should (not (password-read-from-cache "foo")))))
+
+(provide 'password-cache-tests)
+;;; password-cache-tests.el ends here
diff --git a/test/lisp/pcmpl-linux-resources/fs/ext4/.keep b/test/lisp/pcmpl-linux-resources/fs/ext4/.keep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/test/lisp/pcmpl-linux-resources/fs/ext4/.keep
diff --git a/test/lisp/pcmpl-linux-resources/mtab b/test/lisp/pcmpl-linux-resources/mtab
new file mode 100644
index 00000000000..ea33abd7b0a
--- /dev/null
+++ b/test/lisp/pcmpl-linux-resources/mtab
@@ -0,0 +1,11 @@
+/dev/sdb1 / ext3 rw,relatime,errors=remount-ro 0 0
+proc /proc proc rw,noexec,nosuid,nodev 0 0
+/sys /sys sysfs rw,noexec,nosuid,nodev 0 0
+varrun /var/run tmpfs rw,noexec,nosuid,nodev,mode=0755 0 0
+varlock /var/lock tmpfs rw,noexec,nosuid,nodev,mode=1777 0 0
+udev /dev tmpfs rw,mode=0755 0 0
+devshm /dev/shm tmpfs rw 0 0
+devpts /dev/pts devpts rw,gid=5,mode=620 0 0
+lrm /lib/modules/2.6.24-16-generic/volatile tmpfs rw 0 0
+securityfs /sys/kernel/security securityfs rw 0 0
+gvfs-fuse-daemon /home/alice/.gvfs fuse.gvfs-fuse-daemon rw,nosuid,nodev,user=alice 0 0
diff --git a/test/lisp/pcmpl-linux-tests.el b/test/lisp/pcmpl-linux-tests.el
new file mode 100644
index 00000000000..a02c535fd5a
--- /dev/null
+++ b/test/lisp/pcmpl-linux-tests.el
@@ -0,0 +1,43 @@
+;;; pcmpl-linux-tests.el --- Tests for pcmpl-linux.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'ert-x)
+(require 'pcmpl-linux)
+
+(ert-deftest pcmpl-linux-test-fs-types ()
+ (let ((pcmpl-linux-fs-modules-path-format (ert-resource-file "fs")))
+ ;; FIXME: Shouldn't return "." and ".."
+ (should (equal (pcmpl-linux-fs-types)
+ '("." ".." "ext4")))))
+
+(ert-deftest pcmpl-linux-test-mounted-directories ()
+ (let ((pcmpl-linux-mtab-file (ert-resource-file "mtab")))
+ (should (equal (pcmpl-linux-mounted-directories)
+ '("/" "/dev" "/dev/pts" "/dev/shm" "/home/alice/.gvfs"
+ "/lib/modules/2.6.24-16-generic/volatile" "/proc" "/sys"
+ "/sys/kernel/security" "/var/lock" "/var/run")))))
+
+(provide 'pcmpl-linux-tests)
+
+;;; pcmpl-linux-tests.el ends here
diff --git a/test/lisp/pcomplete-tests.el b/test/lisp/pcomplete-tests.el
new file mode 100644
index 00000000000..00a82502f30
--- /dev/null
+++ b/test/lisp/pcomplete-tests.el
@@ -0,0 +1,100 @@
+;;; pcomplete-tests.el --- Tests for pcomplete.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'pcomplete)
+
+(ert-deftest pcomplete-test-parse-gpg-help ()
+ (cl-letf ((pcomplete-from-help (make-hash-table :test #'equal))
+ ((symbol-function 'call-process)
+ (lambda (&rest _) (insert "\
+gpg (GnuPG) 2.3.7
+
+Commands:
+
+ -s, --sign make a signature
+ --clear-sign make a clear text signature
+ -b, --detach-sign make a detached signature
+ --tofu-policy VALUE set the TOFU policy for a key
+
+Options to specify keys:
+ -r, --recipient USER-ID encrypt for USER-ID
+ -u, --local-user USER-ID use USER-ID to sign or decrypt
+
+(See the man page for a complete listing of all commands and options)
+
+Examples:
+
+ -se -r Bob [file] sign and encrypt for user Bob
+ --clear-sign [file] make a clear text signature
+"))))
+ (should
+ (equal-including-properties
+ (pcomplete-from-help "gpg --help" :narrow-end "^ -se")
+ '(#("-s" 0 1 (pcomplete-help "make a signature"))
+ #("--sign" 0 1 (pcomplete-help "make a signature"))
+ #("--clear-sign" 0 1 (pcomplete-help "make a clear text signature"))
+ #("-b" 0 1 (pcomplete-help "make a detached signature"))
+ #("--detach-sign" 0 1 (pcomplete-help "make a detached signature"))
+ #("--tofu-policy" 0 1
+ (pcomplete-help "set the TOFU policy for a key" pcomplete-annotation " VALUE"))
+ #("-r" 0 1 (pcomplete-help "encrypt for USER-ID"))
+ #("--recipient" 0 1
+ (pcomplete-help "encrypt for USER-ID" pcomplete-annotation " USER-ID"))
+ #("-u" 0 1
+ (pcomplete-help "use USER-ID to sign or decrypt"))
+ #("--local-user" 0 1
+ (pcomplete-help "use USER-ID to sign or decrypt" pcomplete-annotation " USER-ID")))))))
+
+(ert-deftest pcomplete-test-parse-git-help ()
+ (cl-letf ((pcomplete-from-help (make-hash-table :test #'equal))
+ ((symbol-function 'call-process)
+ (lambda (&rest _) (insert "\
+usage: git [-v | --version] [-h | --help] [-C <path>] [-c <name>=<value>]
+ [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]
+ [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--bare]
+ [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]
+ [--super-prefix=<path>] [--config-env=<name>=<envvar>]
+ <command> [<args>]
+"))))
+ (should
+ (equal-including-properties
+ (pcomplete-from-help "git help"
+ :margin "\\(\\[\\)-"
+ :separator " | "
+ :description "\\`")
+ '("-v" "--version" "-h" "--help"
+ #("-C" 0 1 (pcomplete-annotation " <path>"))
+ #("-c" 0 1 (pcomplete-annotation " <name>"))
+ #("--exec-path" 0 1 (pcomplete-annotation "[=<path>]"))
+ "--html-path" "--man-path" "--info-path"
+ "-p" "--paginate" "-P" "--no-pager"
+ "--no-replace-objects" "--bare"
+ #("--git-dir=" 0 1 (pcomplete-annotation "<path>"))
+ #("--work-tree=" 0 1 (pcomplete-annotation "<path>"))
+ #("--namespace=" 0 1 (pcomplete-annotation "<name>"))
+ #("--super-prefix=" 0 1 (pcomplete-annotation "<path>"))
+ #("--config-env=" 0 1 (pcomplete-annotation "<name>")))))))
+
+(provide 'pcomplete-tests)
+;;; pcomplete-tests.el ends here
diff --git a/test/lisp/play/animate-tests.el b/test/lisp/play/animate-tests.el
new file mode 100644
index 00000000000..1c7bb0f0819
--- /dev/null
+++ b/test/lisp/play/animate-tests.el
@@ -0,0 +1,56 @@
+;;; animate-tests.el --- Tests for animate.el -*- lexical-binding:t -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'animate)
+
+(ert-deftest animate-test-birthday-present ()
+ (unwind-protect
+ (save-window-excursion
+ (cl-letf (((symbol-function 'sit-for) (lambda (_) nil)))
+ (animate-birthday-present "foo")
+ (should (equal (buffer-string)
+ "
+
+
+
+
+
+ Happy Birthday,
+ Foo
+
+
+ You are my sunshine,
+ My only sunshine.
+ I'm awful sad that
+ You've moved away.
+
+ Let's talk together
+ And love more deeply.
+ Please bring back
+ my sunshine
+ to stay!"))))
+ (kill-buffer "*A-Present-for-Foo*")))
+
+(provide 'animate-tests)
+;;; animate-tests.el ends here
diff --git a/test/lisp/play/cookie1-resources/cookies b/test/lisp/play/cookie1-resources/cookies
new file mode 100644
index 00000000000..7bf569fa7d6
--- /dev/null
+++ b/test/lisp/play/cookie1-resources/cookies
@@ -0,0 +1,8 @@
+This fortune intentionally left blank.
+%
+This fortune intentionally not included.
+%
+This fortune intentionally says nothing.
+%
+This fortune is false.
+%
diff --git a/test/lisp/play/cookie1-tests.el b/test/lisp/play/cookie1-tests.el
new file mode 100644
index 00000000000..5f3ad6d8f8c
--- /dev/null
+++ b/test/lisp/play/cookie1-tests.el
@@ -0,0 +1,40 @@
+;;; cookie1-tests.el --- Tests for cookie1.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'ert-x)
+(require 'cookie1)
+
+(ert-deftest cookie1-tests-cookie ()
+ (let ((fortune-file (ert-resource-file "cookies")))
+ (should (string-match "\\`This fortune"
+ (cookie fortune-file)))))
+
+(ert-deftest cookie1-testss-cookie-apropos ()
+ (let ((fortune-file (ert-resource-file "cookies")))
+ (should (string-match "\\`This fortune"
+ (car (cookie-apropos "false" fortune-file))))
+ (should (= (length (cookie-apropos "false" fortune-file)) 1))))
+
+(provide 'fortune-tests)
+;;; cookie1-tests.el ends here
diff --git a/test/lisp/play/dissociate-tests.el b/test/lisp/play/dissociate-tests.el
new file mode 100644
index 00000000000..7af7e425c47
--- /dev/null
+++ b/test/lisp/play/dissociate-tests.el
@@ -0,0 +1,38 @@
+;;; dissociate-tests.el --- Tests for dissociate.el -*- lexical-binding:t -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'dissociate)
+
+(ert-deftest dissociate-tests-dissociated-press ()
+ (cl-letf (((symbol-function 'y-or-n-p) (lambda (_) nil))
+ ((symbol-function 'random) (lambda (_) 10)))
+ (save-window-excursion
+ (with-temp-buffer
+ (insert "Lorem ipsum dolor sit amet")
+ (dissociated-press)
+ (should (string-match-p "dolor sit ametdolor sit amdolor sit amdolor sit am"
+ (buffer-string)))))))
+
+(provide 'dissociate-tests)
+;;; dissociate-tests.el ends here
diff --git a/test/lisp/play/fortune-resources/fortunes b/test/lisp/play/fortune-resources/fortunes
new file mode 100644
index 00000000000..f1ddc512d00
--- /dev/null
+++ b/test/lisp/play/fortune-resources/fortunes
@@ -0,0 +1,11 @@
+Embarrassed
+Manual-Writer
+Accused of
+Communist
+Subversion
+%
+Embarrassingly
+Mundane
+Advertising
+Cuts
+Sales
diff --git a/test/lisp/play/fortune-tests.el b/test/lisp/play/fortune-tests.el
new file mode 100644
index 00000000000..b79b1f27010
--- /dev/null
+++ b/test/lisp/play/fortune-tests.el
@@ -0,0 +1,41 @@
+;;; fortune-tests.el --- Tests for fortune.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'ert-x)
+(require 'fortune)
+
+(defvar fortune-tests--regexp
+ (rx (| "Embarrassed" "Embarrassingly")))
+
+(ert-deftest test-fortune ()
+ (skip-unless (executable-find "fortune"))
+ (unwind-protect
+ (let ((fortune-file (ert-resource-file "fortunes")))
+ (fortune)
+ (goto-char (point-min))
+ (should (looking-at fortune-tests--regexp)))
+ (kill-buffer fortune-buffer-name)))
+
+(provide 'fortune-tests)
+;;; fortune-tests.el ends here
diff --git a/test/lisp/play/life-tests.el b/test/lisp/play/life-tests.el
new file mode 100644
index 00000000000..c1dcc9d40f5
--- /dev/null
+++ b/test/lisp/play/life-tests.el
@@ -0,0 +1,80 @@
+;;; life-tests.el --- Tests for life.el -*- lexical-binding:t -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+;; Author: Stefan Kangas <stefankangas@gmail.com>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'life)
+
+(ert-deftest test-life ()
+ (let ((life--max-width 5)
+ (life--max-height 3)
+ (life-patterns [(" @ "
+ " @"
+ "@@@")])
+ (generations '("
+
+ @
+ @
+ @@@
+" "
+
+
+ @ @
+ @@
+ @
+" "
+
+
+ @
+ @ @
+ @@
+" "
+
+
+ @
+ @@
+ @@
+" "
+
+
+ @
+ @
+ @@@
+"
+)))
+ (life-setup)
+ ;; Test initial state.
+ (goto-char (point-min))
+ (dolist (generation generations)
+ ;; Hack to test buffer contents without trailing whitespace,
+ ;; while also not modifying the "*Life*" buffer.
+ (let ((str (buffer-string))
+ (delete-trailing-lines t))
+ (with-temp-buffer
+ (insert str)
+ (delete-trailing-whitespace)
+ (should (equal (buffer-string) generation))))
+ (life--tick))))
+
+(provide 'life-tests)
+
+;;; life-tests.el ends here
diff --git a/test/lisp/play/morse-tests.el b/test/lisp/play/morse-tests.el
new file mode 100644
index 00000000000..82ac9101005
--- /dev/null
+++ b/test/lisp/play/morse-tests.el
@@ -0,0 +1,60 @@
+;;; morse-tests.el --- Tests for morse.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2019-2022 Free Software Foundation, Inc.
+
+;; Author: Stefan Kangas <stefankangas@gmail.com>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'morse)
+
+(ert-deftest morse-tests-morse-region ()
+ (with-temp-buffer
+ (insert "Morse encoded")
+ (morse-region (point-min) (point-max))
+ (should (equal (buffer-string)
+ "--/---/.-./.../. ./-./-.-./---/-.././-.."))))
+
+(ert-deftest morse-tests-unmorse-region ()
+ (with-temp-buffer
+ (insert "--/---/.-./.../. ./-./-.-./---/-.././-..")
+ (unmorse-region (point-min) (point-max))
+ (should (equal (buffer-string) "morse encoded"))))
+
+(ert-deftest morse-tests-nato-region ()
+ (with-temp-buffer
+ (insert "Nato encoded")
+ (nato-region (point-min) (point-max))
+ (should (equal (buffer-string)
+ (concat
+ "November-Alfa-Tango-Oscar Echo-November"
+ "-Charlie-Oscar-Delta-Echo-Delta")))))
+
+(ert-deftest morse-tests-unnato-region ()
+ (with-temp-buffer
+ (insert (concat
+ "November-Alfa-Tango-Oscar Echo-November"
+ "-Charlie-Oscar-Delta-Echo-Delta"))
+ (denato-region (point-min) (point-max))
+ (should (equal (buffer-string) "nato encoded"))))
+
+(provide 'morse-tests)
+;;; morse-tests.el ends here
diff --git a/test/lisp/play/studly-tests.el b/test/lisp/play/studly-tests.el
new file mode 100644
index 00000000000..ea241bfbe8d
--- /dev/null
+++ b/test/lisp/play/studly-tests.el
@@ -0,0 +1,52 @@
+;;; studly-tests.el --- Tests for studly.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2019-2022 Free Software Foundation, Inc.
+
+;; Author: Stefan Kangas <stefankangas@gmail.com>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'studly)
+
+(ert-deftest studly-tests-studlify-region ()
+ (with-temp-buffer
+ (insert "Studlify this string of text")
+ (studlify-region (point-min) (point-max))
+ (should (equal (buffer-string)
+ "StudliFy this StrinG of tExt"))))
+
+(ert-deftest studly-tests-studlify-word ()
+ (with-temp-buffer
+ (insert "normal studlified normal")
+ (goto-char 8)
+ (studlify-word 1)
+ (should (equal (buffer-string)
+ "normal stUdlIfIed normal"))))
+
+(ert-deftest studly-tests-nato-region ()
+ (with-temp-buffer
+ (insert "Studlify\n this\n buffer")
+ (studlify-buffer)
+ (should (equal (buffer-string)
+ "STuDlify\n This\n buffer"))))
+
+(provide 'studly-tests)
+;;; studly-tests.el ends here
diff --git a/test/lisp/progmodes/asm-mode-tests.el b/test/lisp/progmodes/asm-mode-tests.el
new file mode 100644
index 00000000000..e321224c543
--- /dev/null
+++ b/test/lisp/progmodes/asm-mode-tests.el
@@ -0,0 +1,82 @@
+;;; asm-mode-tests.el --- Tests for asm-mode.el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2019-2022 Free Software Foundation, Inc.
+
+;; Author: Simen Heggestøyl <simenheg@gmail.com>
+;; Keywords:
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;
+
+;;; Code:
+
+(require 'asm-mode)
+(require 'ert)
+
+(defmacro asm-mode-tests--with-temp-buffer (&rest body)
+ "Create a temporary Asm mode buffer and evaluate BODY there."
+ (declare (indent 0))
+ `(with-temp-buffer
+ (let ((asm-comment-char ?\;))
+ (asm-mode)
+ ,@body)))
+
+(ert-deftest asm-mode-tests-colon ()
+ (asm-mode-tests--with-temp-buffer
+ (let ((indent-tabs-mode t))
+ (insert "\t label")
+ (let ((last-command-event ?:))
+ (asm-colon))
+ (should (equal (buffer-string) "label:\t")))))
+
+(ert-deftest asm-mode-tests-colon-inside-comment ()
+ (asm-mode-tests--with-temp-buffer
+ (insert ";comment")
+ (let ((last-command-event ?:))
+ (asm-colon))
+ (should (equal (buffer-string) ";comment:"))))
+
+(ert-deftest asm-mode-tests-comment ()
+ (asm-mode-tests--with-temp-buffer
+ (insert "label:")
+ (goto-char (point-min))
+ ;; First invocation
+ (asm-comment)
+ (should (string-match-p "label:[ \t]+;" (buffer-string)))
+ (should (= (current-column) (+ comment-column 1)))
+ ;; Second invocation
+ (asm-comment)
+ (should (string-match-p "[ \t]+;; \nlabel:" (buffer-string)))
+ (should (= (current-column) (+ tab-width 3)))
+ ;; Third invocation
+ (asm-comment)
+ (should (string-match-p ";;; \nlabel:" (buffer-string)))
+ (should (= (current-column) 4))))
+
+(ert-deftest asm-mode-tests-fill-comment ()
+ (asm-mode-tests--with-temp-buffer
+ (call-interactively #'comment-dwim)
+ (insert "Pellentesque condimentum, magna ut suscipit hendrerit, \
+ipsum augue ornare nulla, non luctus diam neque sit amet urna.")
+ (call-interactively #'fill-paragraph)
+ (should (equal (buffer-string) "\t;; Pellentesque condimentum, \
+magna ut suscipit hendrerit,\n\t;; ipsum augue ornare nulla, non \
+luctus diam neque sit amet\n\t;; urna."))))
+
+;;; asm-mode-tests.el ends here
diff --git a/test/lisp/progmodes/autoconf-tests.el b/test/lisp/progmodes/autoconf-tests.el
new file mode 100644
index 00000000000..7c609f3c2a7
--- /dev/null
+++ b/test/lisp/progmodes/autoconf-tests.el
@@ -0,0 +1,55 @@
+;;; autoconf-tests.el --- Tests for autoconf.el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+;; Author: Simen Heggestøyl <simenheg@gmail.com>
+;; Keywords:
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;
+
+;;; Code:
+
+(require 'autoconf)
+(require 'ert)
+
+(ert-deftest autoconf-tests-current-defun-function-define ()
+ (with-temp-buffer
+ (insert "AC_DEFINE([HAVE_RSVG], [1], [Define to 1 if using librsvg.])")
+ (goto-char (point-min))
+ (should-not (autoconf-current-defun-function))
+ (forward-char 11)
+ (should (equal (autoconf-current-defun-function) "HAVE_RSVG"))))
+
+(ert-deftest autoconf-tests-current-defun-function-subst ()
+ (with-temp-buffer
+ (insert "AC_SUBST([srcdir])")
+ (goto-char (point-min))
+ (should-not (autoconf-current-defun-function))
+ (forward-char 10)
+ (should (equal (autoconf-current-defun-function) "srcdir"))))
+
+(ert-deftest autoconf-tests-autoconf-mode-comment-syntax ()
+ (with-temp-buffer
+ (autoconf-mode)
+ (insert "dnl Autoconf script for GNU Emacs")
+ (should (nth 4 (syntax-ppss)))))
+
+(provide 'autoconf-tests)
+;;; autoconf-tests.el ends here
diff --git a/test/lisp/progmodes/bat-mode-tests.el b/test/lisp/progmodes/bat-mode-tests.el
index 71660ca437a..5ef4158ec94 100644
--- a/test/lisp/progmodes/bat-mode-tests.el
+++ b/test/lisp/progmodes/bat-mode-tests.el
@@ -1,6 +1,6 @@
;;; bat-mode-tests.el --- Tests for bat-mode.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2017 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2022 Free Software Foundation, Inc.
;; Author: Vladimir Panteleev <vladimir@thecybershadow.net>
;; Keywords:
@@ -63,10 +63,11 @@
"Test fontification of iteration variables."
(should
(equal
- (bat-test-fontify "echo %%a\necho %%~dp1\necho %%~$PATH:I")
+ (bat-test-fontify "echo %%a\necho %%~dp1\necho %%~$PATH:I\necho %%~1")
"<span class=\"builtin\">echo</span> %%<span class=\"variable-name\">a</span>
<span class=\"builtin\">echo</span> %%~dp<span class=\"variable-name\">1</span>
-<span class=\"builtin\">echo</span> %%~$<span class=\"variable-name\">PATH</span>:<span class=\"variable-name\">I</span>")))
+<span class=\"builtin\">echo</span> %%~$<span class=\"variable-name\">PATH</span>:<span class=\"variable-name\">I</span>
+<span class=\"builtin\">echo</span> %%~<span class=\"variable-name\">1</span>")))
(defun bat-test-fill-paragraph (str)
"Return the result of invoking `fill-paragraph' on STR in a `bat-mode' buffer."
diff --git a/test/lisp/progmodes/bug-reference-tests.el b/test/lisp/progmodes/bug-reference-tests.el
new file mode 100644
index 00000000000..fa06d7a1cd0
--- /dev/null
+++ b/test/lisp/progmodes/bug-reference-tests.el
@@ -0,0 +1,128 @@
+;;; bug-reference-tests.el --- Tests for bug-reference.el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;
+
+;;; Code:
+
+(require 'bug-reference)
+(require 'ert)
+
+(defun test--get-github-entry (url)
+ (and (string-match
+ (car (bug-reference--build-forge-setup-entry
+ "github.com" 'github "https"))
+ url)
+ (match-string 1 url)))
+
+(defun test--get-gitlab-entry (url)
+ (and (string-match
+ (car (bug-reference--build-forge-setup-entry
+ "gitlab.com" 'gitlab "https"))
+ url)
+ (match-string 1 url)))
+
+(defun test--get-gitea-entry (url)
+ (and (string-match
+ (car (bug-reference--build-forge-setup-entry
+ "gitea.com" 'gitea "https"))
+ url)
+ (match-string 1 url)))
+
+(ert-deftest test-github-entry ()
+ (should
+ (equal
+ (test--get-github-entry "git@github.com:larsmagne/csid.git")
+ "larsmagne/csid"))
+ (should
+ (equal
+ (test--get-github-entry "git@github.com:larsmagne/csid")
+ "larsmagne/csid"))
+ (should
+ (equal
+ (test--get-github-entry "https://github.com/magit/magit.git")
+ "magit/magit"))
+ (should
+ (equal
+ (test--get-github-entry "https://github.com/magit/magit.git/")
+ "magit/magit"))
+ (should
+ (equal
+ (test--get-github-entry "https://github.com/magit/magit")
+ "magit/magit"))
+ (should
+ (equal
+ (test--get-github-entry "https://github.com/magit/magit/")
+ "magit/magit")))
+
+(ert-deftest test-gitlab-entry ()
+ (should
+ (equal
+ (test--get-gitlab-entry "git@gitlab.com:larsmagne/csid.git")
+ "larsmagne/csid"))
+ (should
+ (equal
+ (test--get-gitlab-entry "git@gitlab.com:larsmagne/csid")
+ "larsmagne/csid"))
+ (should
+ (equal
+ (test--get-gitlab-entry "https://gitlab.com/magit/magit.git")
+ "magit/magit"))
+ (should
+ (equal
+ (test--get-gitlab-entry "https://gitlab.com/magit/magit.git/")
+ "magit/magit"))
+ (should
+ (equal
+ (test--get-gitlab-entry "https://gitlab.com/magit/magit")
+ "magit/magit"))
+ (should
+ (equal
+ (test--get-gitlab-entry "https://gitlab.com/magit/magit/")
+ "magit/magit")))
+
+(ert-deftest test-gitea-entry ()
+ (should
+ (equal
+ (test--get-gitea-entry "git@gitea.com:larsmagne/csid.git")
+ "larsmagne/csid"))
+ (should
+ (equal
+ (test--get-gitea-entry "git@gitea.com:larsmagne/csid")
+ "larsmagne/csid"))
+ (should
+ (equal
+ (test--get-gitea-entry "https://gitea.com/magit/magit.git")
+ "magit/magit"))
+ (should
+ (equal
+ (test--get-gitea-entry "https://gitea.com/magit/magit.git/")
+ "magit/magit"))
+ (should
+ (equal
+ (test--get-gitea-entry "https://gitea.com/magit/magit")
+ "magit/magit"))
+ (should
+ (equal
+ (test--get-gitea-entry "https://gitea.com/magit/magit/")
+ "magit/magit")))
+
+;;; bug-reference-tests.el ends here
diff --git a/test/lisp/progmodes/cc-mode-tests.el b/test/lisp/progmodes/cc-mode-tests.el
index 402bf47dfab..2220721ccf6 100644
--- a/test/lisp/progmodes/cc-mode-tests.el
+++ b/test/lisp/progmodes/cc-mode-tests.el
@@ -1,6 +1,6 @@
;;; cc-mode-tests.el --- Test suite for cc-mode. -*- lexical-binding: t; -*-
-;; Copyright (C) 2016-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2022 Free Software Foundation, Inc.
;; Author: Michal Nazarewicz <mina86@mina86.com>
;; Keywords: internal
@@ -40,7 +40,7 @@
(insert content)
(setq mode nil)
(c-or-c++-mode)
- (unless(eq expected mode)
+ (unless (eq expected mode)
(ert-fail
(format "expected %s but got %s when testing '%s'"
expected mode content)))))
@@ -53,11 +53,18 @@
(funcall do-test (concat " * " content) 'c-mode))
'("using \t namespace \t std;"
"using \t std::string;"
+ "using Foo = Bar;"
"namespace \t {"
"namespace \t foo \t {"
- "class \t Blah_42 \t {"
+ "namespace \t foo::bar \t {"
+ "inline namespace \t foo \t {"
+ "inline namespace \t foo::bar \t {"
"class \t Blah_42 \t \n"
+ "class \t Blah_42;"
+ "class \t Blah_42 \t final {"
+ "struct \t Blah_42 \t final {"
"class \t _42_Blah:public Foo {"
+ "struct \t _42_Blah:public Foo {"
"template \t < class T >"
"template< class T >"
"#include <string>"
@@ -67,6 +74,37 @@
(mapc (lambda (content) (funcall do-test content 'c-mode))
'("struct \t Blah_42 \t {"
"struct template {"
+ "struct Blah;"
"#include <string.h>")))))
+(ert-deftest c-mode-macro-comment ()
+ "Test for bug#36484."
+ (dolist (macro-string '("#define /***/f"
+ "#define x /***/5"
+ "#define a(x)get/***/x/***/id())"))
+ (with-temp-buffer
+ (insert macro-string)
+ (c-mode))))
+
+(ert-deftest c-lineup-ternary-bodies ()
+ "Test for c-lineup-ternary-bodies function"
+ (with-temp-buffer
+ (c-mode)
+ (let* ((common-prefix "int value = condition ")
+ (expected-column (length common-prefix)))
+ (dolist (test '(("? a : \n b" . nil)
+ ("? a \n ::b" . nil)
+ ("a \n : b" . nil)
+ ("? a \n : b" . t)
+ ("? ::a \n : b" . t)
+ ("? (p ? q : r) \n : b" . t)
+ ("? p ?: q \n : b" . t)
+ ("? p ? : q \n : b" . t)
+ ("? p ? q : r \n : b" . t)))
+ (delete-region (point-min) (point-max))
+ (insert common-prefix (car test))
+ (should (equal
+ (and (cdr test) (vector expected-column))
+ (c-lineup-ternary-bodies '(statement-cont . 1))))))))
+
;;; cc-mode-tests.el ends here
diff --git a/test/lisp/progmodes/compile-tests.el b/test/lisp/progmodes/compile-tests.el
index 2de52daeea2..36bdbe4c91b 100644
--- a/test/lisp/progmodes/compile-tests.el
+++ b/test/lisp/progmodes/compile-tests.el
@@ -1,6 +1,6 @@
;;; compile-tests.el --- Test suite for compile.el. -*- lexical-binding: t; -*-
-;; Copyright (C) 2011-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2022 Free Software Foundation, Inc.
;; Author: Chong Yidong <cyd@stupidchicken.com>
;; Keywords: internal
@@ -30,290 +30,366 @@
(require 'ert)
(require 'compile)
-(defvar compile-tests--test-regexps-data
- ;; The computed column numbers are zero-indexed, so subtract 1 from
- ;; what's reported in the string. The end column numbers are for
- ;; the character after, so it matches what's reported in the string.
+(defconst compile-tests--test-regexps-data
'(;; absoft
- ("Error on line 3 of t.f: Execution error unclassifiable statement"
+ (absoft
+ "Error on line 3 of t.f: Execution error unclassifiable statement"
1 nil 3 "t.f")
- ("Line 45 of \"foo.c\": bloofle undefined"
+ (absoft "Line 45 of \"foo.c\": bloofle undefined"
1 nil 45 "foo.c")
- ("error on line 19 of fplot.f: spelling error?"
+ (absoft "error on line 19 of fplot.f: spelling error?"
1 nil 19 "fplot.f")
- ("warning on line 17 of fplot.f: data type is undefined for variable d"
+ (absoft
+ "warning on line 17 of fplot.f: data type is undefined for variable d"
1 nil 17 "fplot.f")
;; Ada & Mpatrol
- ("foo.adb:61:11: [...] in call to size declared at foo.ads:11"
+ (gnu "foo.adb:61:11: [...] in call to size declared at foo.ads:11"
1 11 61 "foo.adb")
- ("foo.adb:61:11: [...] in call to size declared at foo.ads:11"
+ (ada "foo.adb:61:11: [...] in call to size declared at foo.ads:11"
52 nil 11 "foo.ads")
- (" 0x8008621 main+16 at error.c:17"
+ (ada " 0x8008621 main+16 at error.c:17"
23 nil 17 "error.c")
;; aix
- ("****** Error number 140 in line 8 of file errors.c ******"
+ (aix "****** Error number 140 in line 8 of file errors.c ******"
25 nil 8 "errors.c")
;; ant
- ("[javac] /src/DataBaseTestCase.java:27: unreported exception ..."
- 13 nil 27 "/src/DataBaseTestCase.java")
- ("[javac] /src/DataBaseTestCase.java:49: warning: finally clause cannot complete normally"
- 13 nil 49 "/src/DataBaseTestCase.java")
- ("[jikes] foo.java:3:5:7:9: blah blah"
- 14 (5 . 10) (3 . 7) "foo.java")
+ (ant "[javac] /src/DataBaseTestCase.java:27: unreported exception ..."
+ 13 nil 27 "/src/DataBaseTestCase.java" 2)
+ (ant "[javac] /src/DataBaseTestCase.java:49: warning: finally clause cannot complete normally"
+ 13 nil 49 "/src/DataBaseTestCase.java" 1)
+ (ant "[jikes] foo.java:3:5:7:9: blah blah"
+ 14 (5 . 9) (3 . 7) "foo.java" 2)
+ (ant "[javac] c:/cygwin/Test.java:12: error: foo: bar"
+ 9 nil 12 "c:/cygwin/Test.java" 2)
+ (ant "[javac] c:\\cygwin\\Test.java:87: error: foo: bar"
+ 9 nil 87 "c:\\cygwin\\Test.java" 2)
+ ;; Checkstyle error, but ant reports a warning (note additional
+ ;; severity level after task name)
+ (ant "[checkstyle] [ERROR] /src/Test.java:38: warning: foo"
+ 22 nil 38 "/src/Test.java" 1)
;; bash
- ("a.sh: line 1: ls-l: command not found"
+ (bash "a.sh: line 1: ls-l: command not found"
1 nil 1 "a.sh")
;; borland
- ("Error ping.c 15: Unable to open include file 'sys/types.h'"
+ (borland "Error ping.c 15: Unable to open include file 'sys/types.h'"
1 nil 15 "ping.c")
- ("Warning pong.c 68: Call to function 'func' with no prototype"
+ (borland "Warning pong.c 68: Call to function 'func' with no prototype"
1 nil 68 "pong.c")
- ("Error E2010 ping.c 15: Unable to open include file 'sys/types.h'"
+ (borland "Error E2010 ping.c 15: Unable to open include file 'sys/types.h'"
1 nil 15 "ping.c")
- ("Warning W1022 pong.c 68: Call to function 'func' with no prototype"
+ (borland
+ "Warning W1022 pong.c 68: Call to function 'func' with no prototype"
1 nil 68 "pong.c")
;; caml
- ("File \"foobar.ml\", lines 5-8, characters 20-155: blah blah"
- 1 (20 . 156) (5 . 8) "foobar.ml")
- ("File \"F:\\ocaml\\sorting.ml\", line 65, characters 2-145:\nWarning 26: unused variable equ."
- 1 (2 . 146) 65 "F:\\ocaml\\sorting.ml")
- ("File \"/usr/share/gdesklets/display/TargetGauge.py\", line 41, in add_children"
+ (python-tracebacks-and-caml
+ "File \"foobar.ml\", lines 5-8, characters 20-155: blah blah"
+ 1 (20 . 155) (5 . 8) "foobar.ml")
+ (python-tracebacks-and-caml
+ "File \"F:\\ocaml\\sorting.ml\", line 65, characters 2-145:\nWarning 26: unused variable equ."
+ 1 (2 . 145) 65 "F:\\ocaml\\sorting.ml")
+ (python-tracebacks-and-caml
+ "File \"/usr/share/gdesklets/display/TargetGauge.py\", line 41, in add_children"
1 nil 41 "/usr/share/gdesklets/display/TargetGauge.py")
- ("File \\lib\\python\\Products\\PythonScripts\\PythonScript.py, line 302, in _exec"
+ (python-tracebacks-and-caml
+ "File \\lib\\python\\Products\\PythonScripts\\PythonScript.py, line 302, in _exec"
1 nil 302 "\\lib\\python\\Products\\PythonScripts\\PythonScript.py")
- ("File \"/tmp/foo.py\", line 10"
+ (python-tracebacks-and-caml
+ "File \"/tmp/foo.py\", line 10"
1 nil 10 "/tmp/foo.py")
;; clang-include
- ("In file included from foo.cpp:2:"
+ (clang-include "In file included from foo.cpp:2:"
1 nil 2 "foo.cpp" 0)
;; cmake cmake-info
- ("CMake Error at CMakeLists.txt:23 (hurz):"
+ (cmake "CMake Error at CMakeLists.txt:23 (hurz):"
1 nil 23 "CMakeLists.txt")
- ("CMake Warning at cmake/modules/UseUG.cmake:73 (find_package):"
+ (cmake "CMake Warning at cmake/modules/UseUG.cmake:73 (find_package):"
1 nil 73 "cmake/modules/UseUG.cmake")
- (" cmake/modules/DuneGridMacros.cmake:19 (include)"
+ (cmake-info " cmake/modules/DuneGridMacros.cmake:19 (include)"
1 nil 19 "cmake/modules/DuneGridMacros.cmake")
;; comma
- ("\"foo.f\", line 3: Error: syntax error near end of statement"
+ (comma "\"foo.f\", line 3: Error: syntax error near end of statement"
1 nil 3 "foo.f")
- ("\"vvouch.c\", line 19.5: 1506-046 (S) Syntax error."
+ (comma "\"vvouch.c\", line 19.5: 1506-046 (S) Syntax error."
1 5 19 "vvouch.c")
- ("\"foo.c\", line 32 pos 1; (E) syntax error; unexpected symbol: \"lossage\""
+ (comma "\"foo.c\", line 32 pos 1; (E) syntax error; unexpected symbol: \"lossage\""
1 1 32 "foo.c")
- ("\"foo.adb\", line 2(11): warning: file name does not match ..."
+ (comma "\"foo.adb\", line 2(11): warning: file name does not match ..."
1 11 2 "foo.adb")
- ("\"src/swapping.c\", line 30.34: 1506-342 (W) \"/*\" detected in comment."
+ (comma
+ "\"src/swapping.c\", line 30.34: 1506-342 (W) \"/*\" detected in comment."
1 34 30 "src/swapping.c")
;; cucumber
- ("Scenario: undefined step # features/cucumber.feature:3"
+ (cucumber "Scenario: undefined step # features/cucumber.feature:3"
29 nil 3 "features/cucumber.feature")
- (" /home/gusev/.rvm/foo/bar.rb:500:in `_wrap_assertion'"
+ ;; This rule is actually handled by the `cucumber' pattern but when
+ ;; `omake' is included, then `gnu' matches it first.
+ (gnu " /home/gusev/.rvm/foo/bar.rb:500:in `_wrap_assertion'"
1 nil 500 "/home/gusev/.rvm/foo/bar.rb")
;; edg-1 edg-2
- ("build/intel/debug/../../../struct.cpp(42): error: identifier \"foo\" is undefined"
+ (edg-1 "build/intel/debug/../../../struct.cpp(42): error: identifier \"foo\" is undefined"
1 nil 42 "build/intel/debug/../../../struct.cpp")
- ("build/intel/debug/struct.cpp(44): warning #1011: missing return statement at end of"
+ (edg-1 "build/intel/debug/struct.cpp(44): warning #1011: missing return statement at end of"
1 nil 44 "build/intel/debug/struct.cpp")
- ("build/intel/debug/iptr.h(302): remark #981: operands are evaluated in unspecified order"
+ (edg-1 "build/intel/debug/iptr.h(302): remark #981: operands are evaluated in unspecified order"
1 nil 302 "build/intel/debug/iptr.h")
- (" detected during ... at line 62 of \"build/intel/debug/../../../trace.h\""
+ (edg-2 " detected during ... at line 62 of \"build/intel/debug/../../../trace.h\""
31 nil 62 "build/intel/debug/../../../trace.h")
;; epc
- ("Error 24 at (2:progran.f90) : syntax error"
+ (epc "Error 24 at (2:progran.f90) : syntax error"
1 nil 2 "progran.f90")
;; ftnchek
- (" Dummy arg W in module SUBA line 8 file arrayclash.f is array"
+ (ftnchek " Dummy arg W in module SUBA line 8 file arrayclash.f is array"
32 nil 8 "arrayclash.f")
- (" L4 used at line 55 file test/assign.f; never set"
+ (ftnchek " L4 used at line 55 file test/assign.f; never set"
16 nil 55 "test/assign.f")
- ("Warning near line 10 file arrayclash.f: Module contains no executable"
+ (ftnchek
+ "Warning near line 10 file arrayclash.f: Module contains no executable"
1 nil 10 "arrayclash.f")
- ("Nonportable usage near line 31 col 9 file assign.f: mixed default and explicit"
+ (ftnchek "Nonportable usage near line 31 col 9 file assign.f: mixed default and explicit"
24 9 31 "assign.f")
;; iar
- ("\"foo.c\",3 Error[32]: Error message"
+ (iar "\"foo.c\",3 Error[32]: Error message"
1 nil 3 "foo.c")
- ("\"foo.c\",3 Warning[32]: Error message"
+ (iar "\"foo.c\",3 Warning[32]: Error message"
1 nil 3 "foo.c")
;; ibm
- ("foo.c(2:0) : informational EDC0804: Function foo is not referenced."
+ (ibm "foo.c(2:0) : informational EDC0804: Function foo is not referenced."
1 0 2 "foo.c")
- ("foo.c(3:8) : warning EDC0833: Implicit return statement encountered."
+ (ibm "foo.c(3:8) : warning EDC0833: Implicit return statement encountered."
1 8 3 "foo.c")
- ("foo.c(5:5) : error EDC0350: Syntax error."
+ (ibm "foo.c(5:5) : error EDC0350: Syntax error."
1 5 5 "foo.c")
;; irix
- ("ccom: Error: foo.c, line 2: syntax error"
+ (irix "ccom: Error: foo.c, line 2: syntax error"
1 nil 2 "foo.c")
- ("cc: Severe: /src/Python-2.3.3/Modules/_curses_panel.c, line 17: Cannot find file <panel.h> ..."
+ (irix "cc: Severe: /src/Python-2.3.3/Modules/_curses_panel.c, line 17: Cannot find file <panel.h> ..."
1 nil 17 "/src/Python-2.3.3/Modules/_curses_panel.c")
- ("cc: Info: foo.c, line 27: ..."
+ (irix "cc: Info: foo.c, line 27: ..."
1 nil 27 "foo.c")
- ("cfe: Warning 712: foo.c, line 2: illegal combination of pointer and ..."
+ (irix
+ "cfe: Warning 712: foo.c, line 2: illegal combination of pointer and ..."
1 nil 2 "foo.c")
- ("cfe: Warning 600: xfe.c: 170: Not in a conditional directive while ..."
+ (irix
+ "cfe: Warning 600: xfe.c: 170: Not in a conditional directive while ..."
1 nil 170 "xfe.c")
- ("/usr/lib/cmplrs/cc/cfe: Error: foo.c: 1: blah blah"
+ (irix "/usr/lib/cmplrs/cc/cfe: Error: foo.c: 1: blah blah"
1 nil 1 "foo.c")
- ("/usr/lib/cmplrs/cc/cfe: warning: foo.c: 1: blah blah"
+ (irix "/usr/lib/cmplrs/cc/cfe: warning: foo.c: 1: blah blah"
1 nil 1 "foo.c")
- ("foo bar: baz.f, line 27: ..."
+ (irix "foo bar: baz.f, line 27: ..."
1 nil 27 "baz.f")
;; java
- ("\tat org.foo.ComponentGateway.doGet(ComponentGateway.java:172)"
+ (java "\tat org.foo.ComponentGateway.doGet(ComponentGateway.java:172)"
5 nil 172 "ComponentGateway.java")
- ("\tat javax.servlet.http.HttpServlet.service(HttpServlet.java:740)"
+ (java "\tat javax.servlet.http.HttpServlet.service(HttpServlet.java:740)"
5 nil 740 "HttpServlet.java")
- ("==1332== at 0x4040743C: System::getErrorString() (../src/Lib/System.cpp:217)"
+ (java "==1332== at 0x4040743C: System::getErrorString() (../src/Lib/System.cpp:217)"
13 nil 217 "../src/Lib/System.cpp")
- ("==1332== by 0x8008621: main (vtest.c:180)"
+ (java "==1332== by 0x8008621: main (vtest.c:180)"
13 nil 180 "vtest.c")
+ ;; javac
+ (javac
+ "/src/Test.java:5: ';' expected\n foo foo\n ^\n"
+ 1 16 5 "/src/Test.java" 2)
+ (javac
+ "e:\\src\\Test.java:7: warning: ';' expected\n foo foo\n ^\n"
+ 1 11 7 "e:\\src\\Test.java" 1)
;; jikes-file jikes-line
- ("Found 2 semantic errors compiling \"../javax/swing/BorderFactory.java\":"
+ (jikes-file
+ "Found 2 semantic errors compiling \"../javax/swing/BorderFactory.java\":"
1 nil nil "../javax/swing/BorderFactory.java")
- ("Issued 1 semantic warning compiling \"java/awt/Toolkit.java\":"
+ (jikes-file "Issued 1 semantic warning compiling \"java/awt/Toolkit.java\":"
1 nil nil "java/awt/Toolkit.java")
;; gcc-include
- ("In file included from /usr/include/c++/3.3/backward/warn.h:4,"
+ (gcc-include "In file included from /usr/include/c++/3.3/backward/warn.h:4,"
1 nil 4 "/usr/include/c++/3.3/backward/warn.h")
- (" from /usr/include/c++/3.3/backward/iostream.h:31:0,"
+ (gcc-include
+ " from /usr/include/c++/3.3/backward/iostream.h:31:0,"
1 0 31 "/usr/include/c++/3.3/backward/iostream.h")
- (" from test_clt.cc:1:"
+ (gcc-include " from test_clt.cc:1:"
1 nil 1 "test_clt.cc")
+ ;; gmake
+ (gmake "make: *** [Makefile:20: all] Error 2" 12 nil 20 "Makefile" 0)
+ (gmake "make[4]: *** [sub/make.mk:19: all] Error 127" 15 nil 19
+ "sub/make.mk" 0)
+ (gmake "gmake[4]: *** [sub/make.mk:19: all] Error 2" 16 nil 19
+ "sub/make.mk" 0)
+ (gmake "gmake-4.3[4]: *** [make.mk:1119: all] Error 2" 20 nil 1119
+ "make.mk" 0)
+ (gmake "Make-4.3: *** [make.INC:1119: dir/all] Error 2" 16 nil 1119
+ "make.INC" 0)
;; gnu
- ("foo.c:8: message" 1 nil 8 "foo.c")
- ("../foo.c:8: W: message" 1 nil 8 "../foo.c")
- ("/tmp/foo.c:8:warning message" 1 nil 8 "/tmp/foo.c")
- ("foo/bar.py:8: FutureWarning message" 1 nil 8 "foo/bar.py")
- ("foo.py:8: RuntimeWarning message" 1 nil 8 "foo.py")
- ("foo.c:8:I: message" 1 nil 8 "foo.c")
- ("foo.c:8.23: note: message" 1 23 8 "foo.c")
- ("foo.c:8.23: info: message" 1 23 8 "foo.c")
- ("foo.c:8:23:information: message" 1 23 8 "foo.c")
- ("foo.c:8.23-45: Informational: message" 1 (23 . 46) (8 . nil) "foo.c")
- ("foo.c:8-23: message" 1 nil (8 . 23) "foo.c")
+ (gnu "foo.c:8: message" 1 nil 8 "foo.c")
+ (gnu "../foo.c:8: W: message" 1 nil 8 "../foo.c")
+ (gnu "/tmp/foo.c:8:warning message" 1 nil 8 "/tmp/foo.c")
+ (gnu "foo/bar.py:8: FutureWarning message" 1 nil 8 "foo/bar.py")
+ (gnu "foo.py:8: RuntimeWarning message" 1 nil 8 "foo.py")
+ (gnu "foo.c:8:I: message" 1 nil 8 "foo.c")
+ (gnu "foo.c:8.23: note: message" 1 23 8 "foo.c")
+ (gnu "foo.c:8.23: info: message" 1 23 8 "foo.c")
+ (gnu "foo.c:8:23:information: message" 1 23 8 "foo.c")
+ (gnu "foo.c:8.23-45: Informational: message" 1 (23 . 45) (8 . nil) "foo.c")
+ (gnu "foo.c:8-23: message" 1 nil (8 . 23) "foo.c")
+ (gnu " |foo.c:8: message" 1 nil 8 "foo.c")
;; The next one is not in the GNU standards AFAICS.
;; Here we seem to interpret it as LINE1-LINE2.COL2.
- ("foo.c:8-45.3: message" 1 (nil . 4) (8 . 45) "foo.c")
- ("foo.c:8.23-9.1: message" 1 (23 . 2) (8 . 9) "foo.c")
- ("jade:dbcommon.dsl:133:17:E: missing argument for function call"
+ (gnu "foo.c:8-45.3: message" 1 (nil . 3) (8 . 45) "foo.c")
+ (gnu "foo.c:8.23-9.1: message" 1 (23 . 1) (8 . 9) "foo.c")
+ (gnu "jade:dbcommon.dsl:133:17:E: missing argument for function call"
1 17 133 "dbcommon.dsl")
- ("G:/cygwin/dev/build-myproj.xml:54: Compiler Adapter 'javac' can't be found."
+ (gnu "G:/cygwin/dev/build-myproj.xml:54: Compiler Adapter 'javac' can't be found."
1 nil 54 "G:/cygwin/dev/build-myproj.xml")
- ("file:G:/cygwin/dev/build-myproj.xml:54: Compiler Adapter 'javac' can't be found."
+ (gnu "file:G:/cygwin/dev/build-myproj.xml:54: Compiler Adapter 'javac' can't be found."
1 nil 54 "G:/cygwin/dev/build-myproj.xml")
- ("{standard input}:27041: Warning: end of file not at end of a line; newline inserted"
+ (gnu "{standard input}:27041: Warning: end of file not at end of a line; newline inserted"
1 nil 27041 "{standard input}")
+ (gnu "boost/container/detail/flat_tree.hpp:589:25: [ skipping 5 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]"
+ 1 25 589 "boost/container/detail/flat_tree.hpp" 0)
+ ;; gradle-kotlin
+ (gradle-kotlin
+ "e: /src/Test.kt: (34, 15): foo: bar" 4 15 34 "/src/Test.kt" 2)
+ (gradle-kotlin
+ "w: /src/Test.kt: (11, 98): foo: bar" 4 98 11 "/src/Test.kt" 1)
+ (gradle-kotlin
+ "e: e:/cygwin/src/Test.kt: (34, 15): foo: bar"
+ 4 15 34 "e:/cygwin/src/Test.kt" 2)
+ (gradle-kotlin
+ "w: e:/cygwin/src/Test.kt: (11, 98): foo: bar"
+ 4 98 11 "e:/cygwin/src/Test.kt" 1)
+ (gradle-kotlin
+ "e: e:\\src\\Test.kt: (34, 15): foo: bar" 4 15 34 "e:\\src\\Test.kt" 2)
+ (gradle-kotlin
+ "w: e:\\src\\Test.kt: (11, 98): foo: bar" 4 98 11 "e:\\src\\Test.kt" 1)
+ (gradle-android
+ " ERROR:/Users/salutis/src/AndroidSchemeExperiment/app/build/intermediates/incremental/debug/mergeDebugResources/stripped.dir/layout/item.xml:3: AAPT: error: '16dpw' is incompatible with attribute padding (attr) dimension."
+ 1 nil 3 "/Users/salutis/src/AndroidSchemeExperiment/app/build/intermediates/incremental/debug/mergeDebugResources/stripped.dir/layout/item.xml" 2)
;; Guile
- ("In foo.scm:\n" 1 nil nil "foo.scm")
- (" 63:4 [call-with-prompt prompt0 ...]" 1 4 63 nil)
- ("1038: 1 [main (\"gud-break.scm\")]" 1 1 1038 nil)
+ (guile-file "In foo.scm:\n" 1 nil nil "foo.scm")
+ (guile-line " 63:4 [call-with-prompt prompt0 ...]" 1 4 63 nil)
+ (guile-line "1038: 1 [main (\"gud-break.scm\")]" 1 1 1038 nil)
;; lcc
- ("E, file.cc(35,52) Illegal operation on pointers" 1 52 35 "file.cc")
- ("W, file.cc(36,52) blah blah" 1 52 36 "file.cc")
+ (lcc "E, file.cc(35,52) Illegal operation on pointers" 1 52 35 "file.cc")
+ (lcc "W, file.cc(36,52) blah blah" 1 52 36 "file.cc")
;; makepp
- ("makepp: Scanning `/foo/bar.c'" 19 nil nil "/foo/bar.c")
- ("makepp: warning: bla bla `/foo/bar.c' and `/foo/bar.h'" 27 nil nil "/foo/bar.c")
- ("makepp: bla bla `/foo/Makeppfile:12' bla" 18 nil 12 "/foo/Makeppfile")
- ("makepp: bla bla `/foo/bar.c' and `/foo/bar.h'" 35 nil nil "/foo/bar.h")
+ (makepp "makepp: Scanning `/foo/bar.c'" 19 nil nil "/foo/bar.c")
+ (makepp "makepp: warning: bla bla `/foo/bar.c' and `/foo/bar.h'"
+ 27 nil nil "/foo/bar.c")
+ (makepp "makepp: bla bla `/foo/Makeppfile:12' bla"
+ 18 nil 12 "/foo/Makeppfile")
+ (nil "makepp: bla bla `/foo/bar.c' and `/foo/bar.h'"
+ 35 nil nil "/foo/bar.h")
;; maven
- ("FooBar.java:[111,53] no interface expected here"
+ (maven "FooBar.java:[111,53] no interface expected here"
1 53 111 "FooBar.java" 2)
- (" [ERROR] /Users/cinsk/hello.java:[651,96] ';' expected"
+ (maven "[ERROR] /Users/cinsk/hello.java:[651,96] ';' expected"
15 96 651 "/Users/cinsk/hello.java" 2) ;Bug#11517.
- ("[WARNING] /foo/bar/Test.java:[27,43] unchecked conversion"
+ (maven "[WARNING] /foo/bar/Test.java:[27,43] unchecked conversion"
11 43 27 "/foo/bar/Test.java" 1) ;Bug#20556
;; mips-1 mips-2
- ("TrimMask (255) in solomon.c may be indistinguishable from TrimMasks (93) in solomo.c due to truncation"
+ (mips-1 "TrimMask (255) in solomon.c may be indistinguishable from TrimMasks (93) in solomo.c due to truncation"
11 nil 255 "solomon.c")
- ("TrimMask (255) in solomon.c may be indistinguishable from TrimMasks (93) in solomo.c due to truncation"
+ (mips-1 "TrimMask (255) in solomon.c may be indistinguishable from TrimMasks (93) in solomo.c due to truncation"
70 nil 93 "solomo.c")
- ("name defined but never used: LinInt in cmap_calc.c(199)"
+ (mips-2 "name defined but never used: LinInt in cmap_calc.c(199)"
40 nil 199 "cmap_calc.c")
;; msft
- ("keyboard handler.c(537) : warning C4005: 'min' : macro redefinition"
+ (msft "keyboard handler.c(537) : warning C4005: 'min' : macro redefinition"
1 nil 537 "keyboard handler.c")
- ("d:\\tmp\\test.c(23) : error C2143: syntax error : missing ';' before 'if'"
+ (msft
+ "d:\\tmp\\test.c(23) : error C2143: syntax error : missing ';' before 'if'"
1 nil 23 "d:\\tmp\\test.c")
- ("d:\\tmp\\test.c(1145) : see declaration of 'nsRefPtr'"
+ (msft "d:\\tmp\\test.c(1145) : see declaration of 'nsRefPtr'"
1 nil 1145 "d:\\tmp\\test.c")
- ("1>test_main.cpp(29): error C2144: syntax error : 'int' should be preceded by ';'"
+ (msft "1>test_main.cpp(29): error C2144: syntax error : 'int' should be preceded by ';'"
3 nil 29 "test_main.cpp")
- ("1>test_main.cpp(29): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int"
+ (msft "1>test_main.cpp(29): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int"
3 nil 29 "test_main.cpp")
+ (msft "C:\\tmp\\test.cpp(101,11): error C4101: 'bias0123': unreferenced local variable [C:\\tmp\\project.vcxproj]"
+ 1 11 101 "C:\\tmp\\test.cpp")
;; watcom
- ("..\\src\\ctrl\\lister.c(109): Error! E1009: Expecting ';' but found '{'"
+ (watcom
+ "..\\src\\ctrl\\lister.c(109): Error! E1009: Expecting ';' but found '{'"
1 nil 109 "..\\src\\ctrl\\lister.c")
- ("..\\src\\ctrl\\lister.c(120): Warning! W201: Unreachable code"
+ (watcom "..\\src\\ctrl\\lister.c(120): Warning! W201: Unreachable code"
1 nil 120 "..\\src\\ctrl\\lister.c")
+ ;; omake
+ ;; FIXME: This doesn't actually test the omake rule.
+ (gnu " alpha.c:5:15: error: expected ';' after expression"
+ 1 15 5 "alpha.c")
;; oracle
- ("Semantic error at line 528, column 5, file erosacqdb.pc:"
+ (oracle "Semantic error at line 528, column 5, file erosacqdb.pc:"
1 5 528 "erosacqdb.pc")
- ("Error at line 41, column 10 in file /usr/src/sb/ODBI_BHP.hpp"
+ (oracle "Error at line 41, column 10 in file /usr/src/sb/ODBI_BHP.hpp"
1 10 41 "/usr/src/sb/ODBI_BHP.hpp")
- ("PCC-02150: error at line 49, column 27 in file /usr/src/sb/ODBI_dxfgh.pc"
+ (oracle
+ "PCC-02150: error at line 49, column 27 in file /usr/src/sb/ODBI_dxfgh.pc"
1 27 49 "/usr/src/sb/ODBI_dxfgh.pc")
- ("PCC-00003: invalid SQL Identifier at column name in line 12 of file /usr/src/sb/ODBI_BHP.hpp"
+ (oracle "PCC-00003: invalid SQL Identifier at column name in line 12 of file /usr/src/sb/ODBI_BHP.hpp"
1 nil 12 "/usr/src/sb/ODBI_BHP.hpp")
- ("PCC-00004: mismatched IF/ELSE/ENDIF block at line 27 in file /usr/src/sb/ODBI_BHP.hpp"
+ (oracle "PCC-00004: mismatched IF/ELSE/ENDIF block at line 27 in file /usr/src/sb/ODBI_BHP.hpp"
1 nil 27 "/usr/src/sb/ODBI_BHP.hpp")
- ("PCC-02151: line 21 column 40 file /usr/src/sb/ODBI_BHP.hpp:"
+ (oracle "PCC-02151: line 21 column 40 file /usr/src/sb/ODBI_BHP.hpp:"
1 40 21 "/usr/src/sb/ODBI_BHP.hpp")
;; perl
- ("syntax error at automake line 922, near \"':'\""
+ (perl "syntax error at automake line 922, near \"':'\""
14 nil 922 "automake")
- ("Died at test.pl line 27."
+ (perl "Died at test.pl line 27."
6 nil 27 "test.pl")
- ("store::odrecall('File_A', 'x2') called at store.pm line 90"
+ (perl "store::odrecall('File_A', 'x2') called at store.pm line 90"
40 nil 90 "store.pm")
- ("\t(in cleanup) something bad at foo.pl line 3 during global destruction."
+ (perl
+ "\t(in cleanup) something bad at foo.pl line 3 during global destruction."
29 nil 3 "foo.pl")
- ("GLib-GObject-WARNING **: /build/buildd/glib2.0-2.14.5/gobject/gsignal.c:1741: instance `0x8206790' has no handler with id `1234' at t-compilation-perl-gtk.pl line 3."
+ (perl "GLib-GObject-WARNING **: /build/buildd/glib2.0-2.14.5/gobject/gsignal.c:1741: instance `0x8206790' has no handler with id `1234' at t-compilation-perl-gtk.pl line 3."
130 nil 3 "t-compilation-perl-gtk.pl")
;; php
- ("Parse error: parse error, unexpected $ in main.php on line 59"
+ (php "Parse error: parse error, unexpected $ in main.php on line 59"
1 nil 59 "main.php")
- ("Fatal error: Call to undefined function: mysql_pconnect() in db.inc on line 66"
+ (php "Fatal error: Call to undefined function: mysql_pconnect() in db.inc on line 66"
1 nil 66 "db.inc")
- ;; ruby
- ("plain-exception.rb:7:in `fun': unhandled exception"
+ ;; ruby (uses gnu)
+ (gnu "plain-exception.rb:7:in `fun': unhandled exception"
1 nil 7 "plain-exception.rb")
- ("\tfrom plain-exception.rb:3:in `proxy'" 2 nil 3 "plain-exception.rb")
- ("\tfrom plain-exception.rb:12" 2 nil 12 "plain-exception.rb")
+ (gcc-include
+ "\tfrom plain-exception.rb:3:in `proxy'" 2 nil 3 "plain-exception.rb")
+ (gcc-include "\tfrom plain-exception.rb:12" 2 nil 12 "plain-exception.rb")
;; ruby-Test::Unit
;; FIXME
- (" [examples/test-unit.rb:28:in `here_is_a_deep_assert'"
+ (ruby-Test::Unit " [examples/test-unit.rb:28:in `here_is_a_deep_assert'"
5 nil 28 "examples/test-unit.rb")
- (" examples/test-unit.rb:19:in `test_a_deep_assert']:"
+ (ruby-Test::Unit " examples/test-unit.rb:19:in `test_a_deep_assert']:"
6 nil 19 "examples/test-unit.rb")
- ("examples/test-unit.rb:10:in `test_assert_raise'"
+ (gnu "examples/test-unit.rb:10:in `test_assert_raise'"
1 nil 10 "examples/test-unit.rb")
;; rxp
- ("Error: Mismatched end tag: expected </geroup>, got </group>\nin unnamed entity at line 71 char 8 of file:///home/reto/test/group.xml"
+ (rxp "Error: Mismatched end tag: expected </geroup>, got </group>\nin unnamed entity at line 71 char 8 of file:///home/reto/test/group.xml"
1 8 71 "/home/reto/test/group.xml")
- ("Warning: Start tag for undeclared element geroup\nin unnamed entity at line 4 char 8 of file:///home/reto/test/group.xml"
+ (rxp "Warning: Start tag for undeclared element geroup\nin unnamed entity at line 4 char 8 of file:///home/reto/test/group.xml"
1 8 4 "/home/reto/test/group.xml")
+ ;; shellcheck
+ (shellcheck "In autogen.sh line 48:"
+ 1 nil 48 "autogen.sh")
;; sparc-pascal-file sparc-pascal-line sparc-pascal-example
- ("Thu May 14 10:46:12 1992 mom3.p:"
+ (sparc-pascal-file "Thu May 14 10:46:12 1992 mom3.p:"
1 nil nil "mom3.p")
;; sun
- ("cc-1020 CC: REMARK File = CUI_App.h, Line = 735"
+ (sun "cc-1020 CC: REMARK File = CUI_App.h, Line = 735"
13 nil 735 "CUI_App.h")
- ("cc-1070 cc: WARNING File = linkl.c, Line = 38"
+ (sun "cc-1070 cc: WARNING File = linkl.c, Line = 38"
13 nil 38 "linkl.c")
- ("cf90-113 f90comp: ERROR NSE, File = Hoved.f90, Line = 16, Column = 3"
+ (sun "cf90-113 f90comp: ERROR NSE, File = Hoved.f90, Line = 16, Column = 3"
18 3 16 "Hoved.f90")
;; sun-ada
- ("/home3/xdhar/rcds_rc/main.a, line 361, char 6:syntax error: \",\" inserted"
+ (sun-ada "/home3/xdhar/rcds_rc/main.a, line 361, char 6:syntax error: \",\" inserted"
1 6 361 "/home3/xdhar/rcds_rc/main.a")
;; 4bsd
- ("/usr/src/foo/foo.c(8): warning: w may be used before set"
+ (edg-1 "/usr/src/foo/foo.c(8): warning: w may be used before set"
1 nil 8 "/usr/src/foo/foo.c")
- ("/usr/src/foo/foo.c(9): error: w is used before set"
+ (edg-1 "/usr/src/foo/foo.c(9): error: w is used before set"
1 nil 9 "/usr/src/foo/foo.c")
- ("strcmp: variable # of args. llib-lc(359) :: /usr/src/foo/foo.c(8)"
+ (4bsd "strcmp: variable # of args. llib-lc(359) :: /usr/src/foo/foo.c(8)"
44 nil 8 "/usr/src/foo/foo.c")
- ("bloofle defined( /users/wolfgang/foo.c(4) ), but never used"
+ (4bsd "bloofle defined( /users/wolfgang/foo.c(4) ), but never used"
18 nil 4 "/users/wolfgang/foo.c")
;; perl--Pod::Checker
;; FIXME
@@ -321,21 +397,21 @@
;; *** ERROR: =over on line 37 without closing =back at line EOF in file bar.pm
;; *** ERROR: =over on line 1 without closing =back (at head1) at line 3 in file x.pod
;; perl--Test
- ("# Failed test 1 in foo.t at line 6"
+ (perl--Test "# Failed test 1 in foo.t at line 6"
1 nil 6 "foo.t")
;; perl--Test::Harness
- ("NOK 1# Test 1 got: \"1234\" (t/foo.t at line 46)"
+ (perl--Test2 "NOK 1# Test 1 got: \"1234\" (t/foo.t at line 46)"
1 nil 46 "t/foo.t")
;; weblint
- ("index.html (13:1) Unknown element <fdjsk>"
+ (weblint "index.html (13:1) Unknown element <fdjsk>"
1 1 13 "index.html"))
"List of tests for `compilation-error-regexp-alist'.
-Each element has the form (STR POS COLUMN LINE FILENAME [TYPE]),
-where STR is an error string, POS is the position of the error in
-STR, COLUMN and LINE are the reported column and line numbers (or
-nil) for that error, FILENAME is the reported filename, and TYPE
-is 0 for an information message, 1 for a warning, and 2 for an
-error.
+Each element has the form (RULE STR POS COLUMN LINE FILENAME
+[TYPE]), where RULE is the rule (as a symbol), STR is an error
+string, POS is the position of the error in STR, COLUMN and LINE
+are the reported column and line numbers (or nil) for that error,
+FILENAME is the reported filename, and TYPE is 0 for an
+information message, 1 for a warning, and 2 for an error.
LINE can also be of the form (LINE . END-LINE) meaning a range of
lines. COLUMN can also be of the form (COLUMN . END-COLUMN)
@@ -343,40 +419,131 @@ meaning a range of columns starting on LINE and ending on
END-LINE, if that matched. TYPE can be left out, in which case
any message type is accepted.")
+(defconst compile-tests--grep-regexp-testcases
+ ;; Bug#32051.
+ '((nil
+ "c:/Users/my.name/src/project\\src\\kbhit.hpp\0\ 29:#include <termios.h>"
+ 1 nil 29 "c:/Users/my.name/src/project\\src\\kbhit.hpp")
+ (nil
+ "d:/gnu/emacs/branch/src/callproc.c\0\ 214:#ifdef DOS_NT"
+ 1 nil 214 "d:/gnu/emacs/branch/src/callproc.c")
+ (nil
+ "/gnu/emacs/branch/src/callproc.c\0\ 214:#ifdef DOS_NT"
+ 1 nil 214 "/gnu/emacs/branch/src/callproc.c"))
+ "List of tests for `grep-regexp-list'.
+The format is the same as `compile-tests--test-regexps-data', but
+the match is expected to be the same when NUL bytes are replaced
+with colon.")
+
+(defconst compile-tests--grep-regexp-tricky-testcases
+ ;; Bug#7378.
+ '((nil
+ "./x11-libs---nx/3.4.0:0:C.30253.1289557929.792611.C/nx-3.4.0.exheres-0\0\ 42:some text"
+ 1 nil 42 "./x11-libs---nx/3.4.0:0:C.30253.1289557929.792611.C/nx-3.4.0.exheres-0")
+ (nil
+ "2011-08-31_11:57:03_1\0\ 7:Date: Wed, 31 Aug 2011 11:57:03 +0000"
+ 1 nil 7 "2011-08-31_11:57:03_1"))
+ "List of tricky tests for `grep-regexp-list'.
+Same as `compile-tests--grep-regexp-testcases', but these cases
+can only work with the NUL byte to disambiguate colons.")
+
(defun compile--test-error-line (test)
- (erase-buffer)
- (setq compilation-locs (make-hash-table))
- (insert (car test))
- (compilation-parse-errors (point-min) (point-max))
- (let ((msg (get-text-property (nth 1 test) 'compilation-message)))
- (should msg)
- (let ((loc (compilation--message->loc msg))
- (col (nth 2 test))
- (line (nth 3 test))
- (file (nth 4 test))
- (type (nth 5 test))
- end-col end-line)
- (if (consp col)
- (setq end-col (cdr col) col (car col)))
- (if (consp line)
- (setq end-line (cdr line) line (car line)))
- (should (equal (compilation--loc->col loc) col))
- (should (equal (compilation--loc->line loc) line))
- (when file
- (should (equal (caar (compilation--loc->file-struct loc)) file)))
- (when end-col
- (should (equal (car (cadr (nth 2 (compilation--loc->file-struct loc))))
- end-col)))
- (should (equal (car (nth 2 (compilation--loc->file-struct loc)))
- (or end-line line)))
- (when type
- (should (equal type (compilation--message->type msg)))))))
+ (ert-info ((format "%S" test) :prefix "testcase: ")
+ (erase-buffer)
+ (setq compilation-locs (make-hash-table))
+ (let ((rule (nth 0 test))
+ (str (nth 1 test))
+ (pos (nth 2 test))
+ (col (nth 3 test))
+ (line (nth 4 test))
+ (file (nth 5 test))
+ (type (nth 6 test)))
+ (insert str)
+ (compilation-parse-errors (point-min) (point-max))
+ (let ((msg (get-text-property pos 'compilation-message)))
+ (should msg)
+ (let ((loc (compilation--message->loc msg))
+ end-col end-line)
+ (if (consp col)
+ (setq end-col (cdr col) col (car col)))
+ (if (consp line)
+ (setq end-line (cdr line) line (car line)))
+ (should (equal (compilation--loc->col loc) col))
+ (should (equal (compilation--loc->line loc) line))
+ (when file
+ (should (equal (caar (compilation--loc->file-struct loc)) file)))
+ (when end-col
+ ;; The computed END-COL is exclusive; subtract one to get the
+ ;; number in the error message.
+ (should (equal
+ (1- (car (cadr
+ (nth 2 (compilation--loc->file-struct loc)))))
+ end-col)))
+ (should (equal (car (nth 2 (compilation--loc->file-struct loc)))
+ (or end-line line)))
+ (when type
+ (should (equal type (compilation--message->type msg))))
+ (should (equal rule (compilation--message->rule msg))))
+ msg))))
(ert-deftest compile-test-error-regexps ()
"Test the `compilation-error-regexp-alist' regexps.
The test data is in `compile-tests--test-regexps-data'."
(with-temp-buffer
(font-lock-mode -1)
- (mapc #'compile--test-error-line compile-tests--test-regexps-data)))
+ (let ((compilation-num-errors-found 0)
+ (compilation-num-warnings-found 0)
+ (compilation-num-infos-found 0))
+ (mapc #'compile--test-error-line compile-tests--test-regexps-data)
+ (should (eq compilation-num-errors-found 98))
+ (should (eq compilation-num-warnings-found 35))
+ (should (eq compilation-num-infos-found 28)))))
+
+(ert-deftest compile-test-grep-regexps ()
+ "Test the `grep-regexp-alist' regexps.
+The test data is in `compile-tests--grep-regexp-testcases'."
+ (with-temp-buffer
+ (grep-mode)
+ (setq buffer-read-only nil)
+ (font-lock-mode -1)
+ (dolist (testcase compile-tests--grep-regexp-testcases)
+ (let (msg1 msg2)
+ (setq msg1 (compile--test-error-line testcase))
+ ;; Make sure replacing the NUL character with a colon still matches.
+ (let ((testcase2 (copy-sequence testcase)))
+ (setf (nth 1 testcase2)
+ (string-replace "\0" ":" (nth 1 testcase2)))
+ (setq msg2 (compile--test-error-line testcase2)))
+ (should (equal msg1 msg2))))
+ (dolist (testcase compile-tests--grep-regexp-tricky-testcases)
+ (compile--test-error-line testcase))
+ (should (eq compilation-num-errors-found 8))))
+
+(ert-deftest compile-test-functions ()
+ "Test rules using functions instead of regexp group numbers."
+ (let* ((file-fun (lambda () '("my-file")))
+ (line-start-fun (lambda () 123))
+ (line-end-fun (lambda () 134))
+ (col-start-fun (lambda () 39))
+ (col-end-fun (lambda () 24))
+ (compilation-error-regexp-alist-alist
+ `((my-rule
+ ,(rx bol "My error message")
+ ,file-fun
+ (,line-start-fun . ,line-end-fun)
+ (,col-start-fun . ,col-end-fun))))
+ (compilation-error-regexp-alist '(my-rule)))
+ (with-temp-buffer
+ (font-lock-mode -1)
+ (let ((compilation-num-errors-found 0)
+ (compilation-num-warnings-found 0)
+ (compilation-num-infos-found 0))
+ (compile--test-error-line
+ '(my-rule
+ "My error message"
+ 1 (39 . 24) (123 . 134) "my-file" 2))
+ (should (eq compilation-num-errors-found 1))
+ (should (eq compilation-num-warnings-found 0))
+ (should (eq compilation-num-infos-found 0))))))
;;; compile-tests.el ends here
diff --git a/test/lisp/progmodes/cperl-mode-resources/cperl-bug-11996.pl b/test/lisp/progmodes/cperl-mode-resources/cperl-bug-11996.pl
new file mode 100644
index 00000000000..566b7e7550f
--- /dev/null
+++ b/test/lisp/progmodes/cperl-mode-resources/cperl-bug-11996.pl
@@ -0,0 +1,8 @@
+{
+ my @zzzz=(\%seen_couchrequsts, \%seen_people );
+ my @zzzz=\(%seen_couchrequsts, %seen_people );
+ my @zzzz=(\%seen_couchrequsts, \%seen_people );
+}
+
+print "\"Watch out\"";
+$ref = \"howdy";
diff --git a/test/lisp/progmodes/cperl-mode-resources/cperl-bug-19709.pl b/test/lisp/progmodes/cperl-mode-resources/cperl-bug-19709.pl
new file mode 100644
index 00000000000..f7c51a2ce57
--- /dev/null
+++ b/test/lisp/progmodes/cperl-mode-resources/cperl-bug-19709.pl
@@ -0,0 +1,25 @@
+# -------- bug#19709: input --------
+my $a = func1(
+ Module::test()
+ );
+
+my $b = func2(
+ test()
+);
+
+my $c = func3(
+ Module::test(),
+);
+# -------- bug#19709: expected output --------
+my $a = func1(
+ Module::test()
+);
+
+my $b = func2(
+ test()
+);
+
+my $c = func3(
+ Module::test(),
+);
+# -------- bug#19709: end --------
diff --git a/test/lisp/progmodes/cperl-mode-resources/cperl-bug-22355.pl b/test/lisp/progmodes/cperl-mode-resources/cperl-bug-22355.pl
new file mode 100644
index 00000000000..f54d55241df
--- /dev/null
+++ b/test/lisp/progmodes/cperl-mode-resources/cperl-bug-22355.pl
@@ -0,0 +1,14 @@
+# The source file contains non-ASCII characters, supposed to be saved
+# in UTF-8 encoding. Tell Perl about that, just in case.
+use utf8;
+
+# Following code is the example from the report Bug#22355 which needed
+# attention in perl-mode.
+
+printf qq
+{<?xml version="1.0" encoding="UTF-8"?>
+<kml xmlns="http://www.opengis.net/kml/2.2">
+ <Document>
+ <Folder><name>台灣 %s 廣播電台</name>
+ <description><![CDATA[http://radioscanningtw.wikia.com/wiki/台描:地圖 %d-%02d-%02d]]></description>
+}, uc( substr( $ARGV[0], 0, 2 ) ), $year + 1900, $mon + 1, $mday;
diff --git a/test/lisp/progmodes/cperl-mode-resources/cperl-bug-23992.pl b/test/lisp/progmodes/cperl-mode-resources/cperl-bug-23992.pl
new file mode 100644
index 00000000000..1db639c6aa2
--- /dev/null
+++ b/test/lisp/progmodes/cperl-mode-resources/cperl-bug-23992.pl
@@ -0,0 +1,10 @@
+# Test file for Bug#23992
+#
+# The "||" case is directly from the report,
+# the "&&" case has been added for symmetry.
+
+s/LEFT/L/g || s/RIGHT/R/g || s/aVALUE\D+//g;
+s/LEFT/L/g||s/RIGHT/R/g||s/aVALUE\D+//g;
+
+s/LEFT/L/g && s/RIGHT/R/g && s/aVALUE\D+//g;
+s/LEFT/L/g&&s/RIGHT/R/g&&s/aVALUE\D+//g;
diff --git a/test/lisp/progmodes/cperl-mode-resources/cperl-bug-25098.pl b/test/lisp/progmodes/cperl-mode-resources/cperl-bug-25098.pl
new file mode 100644
index 00000000000..0987b4e02c0
--- /dev/null
+++ b/test/lisp/progmodes/cperl-mode-resources/cperl-bug-25098.pl
@@ -0,0 +1,21 @@
+# Code from the bug report Bug#25098
+
+my $good = XML::LibXML->load_xml( string => q{<div class="clearfix">});
+my $bad = XML::LibXML->load_xml( string =>q{<div class="clearfix">});
+
+# Related: Method calls are no quotelike operators. That's why you
+# can't just add '>' to the character class.
+
+my $method_call = $object->q(argument);
+
+# Also related, still not fontified correctly:
+#
+# my $method_call = $object -> q (argument);
+#
+# perl-mode interprets the method call as a quotelike op (because it
+# is preceded by a space).
+# cperl-mode gets the argument right, but marks q as a quotelike op.
+#
+# my $greater = 2>q/1/;
+#
+# perl-mode doesn't identify this as a quotelike op.
diff --git a/test/lisp/progmodes/cperl-mode-resources/cperl-bug-26850.pl b/test/lisp/progmodes/cperl-mode-resources/cperl-bug-26850.pl
new file mode 100644
index 00000000000..a02ea29fe9d
--- /dev/null
+++ b/test/lisp/progmodes/cperl-mode-resources/cperl-bug-26850.pl
@@ -0,0 +1,16 @@
+sub interesting {
+ $_ = shift;
+ return
+ />Today is .+\'s birthday\.</
+ || / like[ds]? your post in </
+ || /like[ds] your new subscription\. </
+ || / likes? that you're interested in </
+ || /> likes? your comment: /
+ || /&amp;birthdays=.*birthdays?\.<\/a>/;
+}
+
+sub boring {
+ return
+ / likes? your post in </
+ || / likes? that you're interested in </
+}
diff --git a/test/lisp/progmodes/cperl-mode-resources/cperl-bug-30393.pl b/test/lisp/progmodes/cperl-mode-resources/cperl-bug-30393.pl
new file mode 100644
index 00000000000..01db7b5206c
--- /dev/null
+++ b/test/lisp/progmodes/cperl-mode-resources/cperl-bug-30393.pl
@@ -0,0 +1,19 @@
+# -------- bug#30393: input --------
+#
+ my $sql = "insert into jobs (id, priority) values (1, 2);";
+ my $sth = $dbh->prepare($sql) or die "bother";
+
+ my $sql = "insert into jobs
+(id, priority)
+values (1, 2);";
+ my $sth = $dbh->prepare($sql) or die "bother";
+# -------- bug#30393: expected output --------
+#
+my $sql = "insert into jobs (id, priority) values (1, 2);";
+my $sth = $dbh->prepare($sql) or die "bother";
+
+my $sql = "insert into jobs
+(id, priority)
+values (1, 2);";
+my $sth = $dbh->prepare($sql) or die "bother";
+# -------- bug#30393: end --------
diff --git a/test/lisp/progmodes/cperl-mode-resources/cperl-indent-exp.pl b/test/lisp/progmodes/cperl-mode-resources/cperl-indent-exp.pl
new file mode 100644
index 00000000000..8c1883a10f1
--- /dev/null
+++ b/test/lisp/progmodes/cperl-mode-resources/cperl-indent-exp.pl
@@ -0,0 +1,52 @@
+#!/usr/bin/env perl
+use strict;
+use warnings;
+use 5.020;
+
+# This file contains test input and expected output for the tests in
+# cperl-mode-tests.el, cperl-mode-test-indent-exp. The code is
+# syntactically valid, but doesn't make much sense.
+
+# -------- for loop: input --------
+for my $foo (@ARGV)
+{
+...;
+}
+# -------- for loop: expected output --------
+for my $foo (@ARGV) {
+ ...;
+}
+# -------- for loop: end --------
+
+# -------- while loop: input --------
+{
+while (1)
+{
+say "boring loop";
+}
+continue
+{
+last;
+}
+}
+# -------- while loop: expected output --------
+{
+ while (1) {
+ say "boring loop";
+ } continue {
+ last;
+ }
+}
+# -------- while loop: end --------
+
+# -------- if-then-else: input --------
+if (my $foo) { bar() } elsif (quux()) { baz() } else { quuux }
+# -------- if-then-else: expected output --------
+if (my $foo) {
+ bar();
+} elsif (quux()) {
+ baz();
+} else {
+ quuux;
+}
+# -------- if-then-else: end --------
diff --git a/test/lisp/progmodes/cperl-mode-resources/cperl-indent-styles.pl b/test/lisp/progmodes/cperl-mode-resources/cperl-indent-styles.pl
new file mode 100644
index 00000000000..371b19b7309
--- /dev/null
+++ b/test/lisp/progmodes/cperl-mode-resources/cperl-indent-styles.pl
@@ -0,0 +1,54 @@
+#!/usr/bin/env perl
+use strict;
+use warnings;
+use 5.020;
+
+# This file contains test input and expected output for the tests in
+# cperl-mode-tests.el, cperl-mode-test-indent-exp. The code is
+# syntactically valid, but doesn't make much sense.
+
+# -------- PBP indent: input --------
+for my $foo (@ARGV)
+{
+...;
+}
+# -------- PBP indent: expected output --------
+for my $foo (@ARGV) {
+ ...;
+}
+# -------- PBP indent: end --------
+
+# -------- PBP uncuddle else: input --------
+{
+if (1 < 2)
+{
+say "Seems ok";
+} elsif (1 == 2) {
+say "Strange things are happening";
+} else {
+die "This world is backwards";
+}
+}
+# -------- PBP uncuddle else: expected output --------
+{
+ if (1 < 2) {
+ say "Seems ok";
+ }
+ elsif (1 == 2) {
+ say "Strange things are happening";
+ }
+ else {
+ die "This world is backwards";
+ }
+}
+# -------- PBP uncuddle else: end --------
+
+# -------- PBP closing paren offset: input --------
+my $a = func1(
+ Module::test()
+ );
+# -------- PBP closing paren offset: expected output --------
+my $a = func1(
+ Module::test()
+);
+# -------- PBP closing paren offset: end --------
diff --git a/test/lisp/progmodes/cperl-mode-resources/cperl-indents.erts b/test/lisp/progmodes/cperl-mode-resources/cperl-indents.erts
new file mode 100644
index 00000000000..6b874ffaa1f
--- /dev/null
+++ b/test/lisp/progmodes/cperl-mode-resources/cperl-indents.erts
@@ -0,0 +1,26 @@
+Code:
+ (lambda ()
+ (cperl-mode)
+ (indent-region (point-min) (point-max)))
+
+Name: cperl-indent1
+
+=-=
+{
+ print "",
+ "",
+ foo::bar(),
+ "";
+}
+=-=-=
+
+Name: cperl-indents1
+
+=-=
+{
+ print "",
+ "",
+ foobar(),
+ "";
+}
+=-=-=
diff --git a/test/lisp/progmodes/cperl-mode-resources/fontify-punctuation-vars.pl b/test/lisp/progmodes/cperl-mode-resources/fontify-punctuation-vars.pl
new file mode 100644
index 00000000000..fa328438cb1
--- /dev/null
+++ b/test/lisp/progmodes/cperl-mode-resources/fontify-punctuation-vars.pl
@@ -0,0 +1,20 @@
+# The following Perl punctiation variables contain characters which
+# are classified as string delimiters in the syntax table. The mode
+# should not be confused by these.
+# The corresponding tests check that two consecutive '#' characters
+# are seen as comments, not as strings.
+my $pre = $`; ## $PREMATCH, use another ` # to balance out
+my $pos = $'; ## $POSTMATCH, use another ' # to balance out
+my $lsp = $"; ## $LIST_SEPARATOR use another " # to balance out
+
+# In the second level, we use the reference constructor \ on these
+# variables. The backslash is an escape character *only* in strings.
+my $ref = \$`; ## \$PREMATCH, use another ` # to balance out
+my $rif = \$'; ## \$POSTMATCH, use another ' # to balance out
+my $raf = \$"; ## \$LIST_SEPARATOR use another " # to balance out
+
+my $opt::s = 0; ## s is no substitution here
+my $opt_s = 0; ## s is no substitution here
+my %opt = (s => 0); ## s is no substitution here
+$opt{s} = 0; ## s is no substitution here
+$opt_s =~ /\s+.../ ## s is no substitution here
diff --git a/test/lisp/progmodes/cperl-mode-resources/grammar.pl b/test/lisp/progmodes/cperl-mode-resources/grammar.pl
new file mode 100644
index 00000000000..96a86993082
--- /dev/null
+++ b/test/lisp/progmodes/cperl-mode-resources/grammar.pl
@@ -0,0 +1,172 @@
+use 5.024;
+use strict;
+use warnings;
+use utf8;
+
+sub outside {
+ say "Line @{[__LINE__]}: package '@{[__PACKAGE__]}'";
+}
+
+package Package;
+
+=head1 NAME
+
+grammar - A Test resource for regular expressions
+
+=head1 SYNOPSIS
+
+A Perl file showing a variety of declarations
+
+=head1 DESCRIPTION
+
+This file offers several syntactical constructs for packages,
+subroutines, and POD to test the imenu capabilities of CPerl mode.
+
+Perl offers syntactical variations for package and subroutine
+declarations. Packages may, or may not, have a version and may, or
+may not, have a block of code attached to them. Subroutines can have
+old-style prototypes, attributes, and signatures which are still
+experimental but widely accepted.
+
+Various Extensions and future Perl versions will probably add new
+keywords for "class" and "method", both with syntactical extras of
+their own.
+
+This test file tries to keep up with them.
+
+=head2 Details
+
+The code is supposed to identify and exclude false positives,
+e.g. declarations in a string or in POD, as well as POD in a string.
+These should not go into the imenu index.
+
+=cut
+
+our $VERSION = 3.1415;
+say "Line @{[__LINE__]}: package '@{[__PACKAGE__]}', version $VERSION";
+
+sub in_package {
+ # Special test for POD: A line which looks like POD, but actually
+ # is part of a multiline string. In the case shown here, the
+ # semicolon is not part of the string, but POD headings go to the
+ # end of the line. The code needs to distinguish between a POD
+ # heading "This Is Not A Pod/;" and a multiline string.
+ my $not_a_pod = q/Another false positive:
+
+=head1 This Is Not A Pod/;
+
+}
+
+sub Shoved::elsewhere {
+ say "Line @{[__LINE__]}: package '@{[__PACKAGE__]}', sub Shoved::elsewhere";
+}
+
+sub prototyped ($$) {
+ ...;
+}
+
+package Versioned::Package 0.07;
+say "Line @{[__LINE__]}: package '@{[__PACKAGE__]}', version $VERSION";
+
+sub versioned {
+ # This sub is in package Versioned::Package
+ say "sub 'versioned' in package '", __PACKAGE__, "'";
+}
+
+versioned();
+
+my $false_positives = <<'EOH';
+The following declarations are not supposed to be recorded for imenu.
+They are in a HERE-doc, which is a generic comment in CPerl mode.
+
+package Don::T::Report::This;
+sub this_is_no_sub {
+ my $self = shuffle;
+}
+
+And this is not a POD heading:
+
+=head1 Not a POD heading, just a string.
+
+EOH
+
+package Block {
+ our $VERSION = 2.7182;
+ say "Line @{[__LINE__]}: package '@{[__PACKAGE__]}', version $VERSION";
+
+ sub attr:lvalue {
+ say "sub 'attr' in package '", __PACKAGE__, "'";
+ }
+
+ attr();
+
+ package Block::Inner {
+ # This hopefully doesn't happen too often.
+ say "Line @{[__LINE__]}: package '@{[__PACKAGE__]}', version $VERSION";
+ }
+
+ # Now check that we're back to package "Block"
+ say "Line @{[__LINE__]}: package '@{[__PACKAGE__]}', version $VERSION";
+}
+
+sub outer {
+ # This is in package Versioned::Package
+ say "Line @{[__LINE__]}: package '@{[__PACKAGE__]}', version $VERSION";
+}
+
+outer();
+
+package Versioned::Block 42 {
+ say "Line @{[__LINE__]}: package '@{[__PACKAGE__]}', version $VERSION";
+
+ my sub lexical {
+ say "sub 'lexical' in package '", __PACKAGE__, "'";
+ }
+
+ lexical();
+
+ use experimental 'signatures';
+ sub signatured :prototype($@) ($self,@rest)
+ {
+ ...;
+ }
+}
+
+# After all is said and done, we're back in package Versioned::Package.
+say "We're in package '", __PACKAGE__, "' now.";
+say "Now try to call a subroutine which went out of scope:";
+eval { lexical() };
+say $@ if $@;
+
+# Now back to Package. This must not appear separately in the
+# hierarchy list.
+package Package;
+
+our sub in_package_again {
+ say "Line @{[__LINE__]}: package '@{[__PACKAGE__]}', version $VERSION";
+}
+
+
+package :: {
+ # This is just a weird, but legal, package name.
+ say "Line @{[__LINE__]}: package '@{[__PACKAGE__]}', version $VERSION";
+
+ in_package_again(); # weird, but calls the sub from above
+}
+
+Shoved::elsewhere();
+
+# Finally, try unicode identifiers.
+package Erdős::Number;
+
+sub erdős_number {
+ my $name = shift;
+ if ($name eq "Erdős Pál") {
+ return 0;
+ }
+ else {
+ die "No access to the database. Sorry.";
+ }
+}
+
+1;
diff --git a/test/lisp/progmodes/cperl-mode-resources/here-docs.pl b/test/lisp/progmodes/cperl-mode-resources/here-docs.pl
new file mode 100644
index 00000000000..bb3d4871a91
--- /dev/null
+++ b/test/lisp/progmodes/cperl-mode-resources/here-docs.pl
@@ -0,0 +1,143 @@
+use 5.020;
+
+=head1 NAME
+
+here-docs.pl - resource file for cperl-test-here-docs
+
+=head1 DESCRIPTION
+
+This file holds a couple of HERE documents, with a variety of normal
+and edge cases. For a formatted view of this description, run:
+
+ (cperl-perldoc "here-docs.pl")
+
+For each of the HERE documents, the following checks will done:
+
+=over 4
+
+=item *
+
+All occurrences of the string "look-here" are fontified correctly.
+Note that we deliberately test the face, not the syntax property:
+Users won't care for the syntax property, but they see the face.
+Different implementations with different syntax properties have been
+seen in the past.
+
+=item *
+
+Indentation of the line(s) containing "look-here" is 0, i.e. there are no
+leading spaces.
+
+=item *
+
+Indentation of the following perl statement containing "indent" should
+be 0 if the statement contains "noindent", and according to the mode's
+continued-statement-offset otherwise.
+
+=back
+
+=cut
+
+# Prologue to make the test file valid without warnings
+
+my $text;
+my $any;
+my $indentation;
+my $anywhere = 'back again';
+my $noindent;
+
+=head1 The Tests
+
+=head2 Test Case 1
+
+We have two HERE documents in one line with different quoting styles.
+
+=cut
+
+## test case
+
+$text = <<"HERE" . <<'THERE' . $any;
+#look-here and
+HERE
+$tlook-here and
+THERE
+
+$noindent = "This should be left-justified";
+
+=head2 Test case 2
+
+A HERE document followed by a continuation line
+
+=cut
+
+## test case
+
+$text = <<HERE
+look-here
+HERE
+
+. 'indent-level'; # Continuation, should be indented
+
+=head2 Test case 3
+
+A here document with a line-end comment in the starter line,
+after a complete statement
+
+=cut
+
+## test case
+
+$text = <<HERE; # start here
+look-here
+HERE
+
+$noindent = "New statement in this line";
+
+=head2 Test case 4
+
+A HERE document with a to-be-continued statement and a comment in the
+starter line.
+
+=cut
+
+## test case
+
+$text = <<HERE # start here
+look-here
+HERE
+
+. 'indent-level'; # Continuation, should be indented
+
+=head2 Test case 5
+
+A HERE document with a comment sign, but no comment to follow.
+
+
+=cut
+
+## test case
+
+$text = <<HERE; #
+look-here
+HERE
+
+$noindent = "New statement in this line";
+
+=head2 Test case 6
+
+A HERE document with a comment sign, but no comment to follow, with a
+statement to be continued. Also, the character before the comment
+sign has a relevant syntax property (end of string in our case) which
+must be preserved.
+
+=cut
+
+## test case
+
+$text = <<"HERE"#
+look-here
+HERE
+
+. 'indent-level'; # Continuation, should be indented
+
+__END__
diff --git a/test/lisp/progmodes/cperl-mode-resources/proto-and-attrs.pl b/test/lisp/progmodes/cperl-mode-resources/proto-and-attrs.pl
new file mode 100644
index 00000000000..7138bf631df
--- /dev/null
+++ b/test/lisp/progmodes/cperl-mode-resources/proto-and-attrs.pl
@@ -0,0 +1,50 @@
+# The next two lines are required as of 2022, but obsolescent
+# as soon as signatures leave their "experimental" state
+use feature 'signatures';
+no warnings 'experimental::signatures';
+
+# Tests for subroutine prototypes, signatures and the like
+
+# Prototypes have syntactical properties different from "normal" Perl:
+# Perl has a variable $), so ($)) is not an unbalanced parenthesis.
+# On the other hand, in a prototype ($) is _not_ an open paren
+# followed by the variable $), so the parens are balanced. Prototypes
+# are somewhat frowned upon most of the times, but they are required
+# for some Perl magic
+
+# FIXME: 2022-02-02 CPerl mode does not handle subroutine signatures.
+# In simple cases it mistakes them as prototypes, when attributes are
+# present, it doesn't handle them at all. Variables in signatures
+# SHOULD be fontified like variable declarations.
+
+# Part 1: Named subroutines
+# A prototype and a trivial subroutine attribute
+{
+ no feature 'signatures'; # that's a prototype, not a signature
+ sub sub_1 ($) :lvalue { local $); }
+}
+
+# A prototype as an attribute (how it should be written these days)
+sub sub_2 :prototype($) { ...; }
+
+# A signature (these will soon-ish leave the experimental state)
+sub sub_3 ($foo,$bar) { ...; }
+
+# Attribute plus signature FIXME: Not yet supported
+sub bad_sub_4 :prototype($$$) ($foo,$bar,$baz) { ...; }
+
+# Part 2: Same constructs for anonymous subs
+# A prototype and a trivial subroutine attribute
+{
+ no feature 'signatures'; # that's a prototype, not a signature
+ my $subref_1 = sub ($) :lvalue { local $); };
+}
+
+# A prototype as an attribute (how it should be written these days)
+my $subref_2 = sub :prototype($) { ...; };
+
+# A signature (these will soon-ish leave the experimental state)
+my $subref_3 = sub ($foo,$bar) { ...; };
+
+# Attribute plus signature
+my $subref_4 = sub :prototype($$$) ($foo,$bar,$baz) { ...; };
diff --git a/test/lisp/progmodes/cperl-mode-tests.el b/test/lisp/progmodes/cperl-mode-tests.el
new file mode 100644
index 00000000000..1bb206e7040
--- /dev/null
+++ b/test/lisp/progmodes/cperl-mode-tests.el
@@ -0,0 +1,1151 @@
+;;; cperl-mode-tests.el --- Test for cperl-mode -*- lexical-binding: t -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+;; Author: Harald Jörg <haj@posteo.de>
+;; Maintainer: Harald Jörg
+;; Keywords: internal
+;; URL: https://github.com/HaraldJoerg/cperl-mode
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This is a collection of tests for CPerl-mode.
+
+;;; Code:
+
+(defvar cperl-test-mode #'cperl-mode)
+
+(require 'cperl-mode)
+(require 'ert)
+(require 'ert-x)
+
+;;; Utilities
+
+(defun cperl-test-ppss (text regexp)
+ "Return the `syntax-ppss' after the last character matched by REGEXP in TEXT."
+ (interactive)
+ (with-temp-buffer
+ (insert text)
+ (funcall cperl-test-mode)
+ (goto-char (point-min))
+ (re-search-forward regexp)
+ (syntax-ppss)))
+
+(defmacro cperl--run-test-cases (file &rest body)
+ "Run all test cases in FILE with BODY.
+This macro helps with tests which reformat Perl code, e.g. when
+indenting or rearranging flow control. It extracts source code
+snippets and corresponding expected results from a resource file,
+runs BODY on the snippets, and compares the resulting buffer with
+the expected results.
+
+Test cases in FILE are formatted like this:
+
+# -------- NAME: input --------
+Your input to the test case comes here.
+Both input and expected output may span several lines.
+# -------- NAME: expected output --------
+The expected output from running BODY on the input goes here.
+# -------- NAME: end --------
+
+You can have many of these blocks in one test file. You can
+chose a NAME for each block, which is passed to the `should'
+clause for easy identification of the first test case that
+failed (if any). Text outside these the blocks is ignored by the
+tests, so you can use it to document the test cases if you wish."
+ `(with-temp-buffer
+ (insert-file-contents ,file)
+ (goto-char (point-min))
+ (while (re-search-forward
+ (concat "^# ?-+ \\_<\\(?1:.+?\\)\\_>: input ?-+\n"
+ "\\(?2:\\(?:.*\n\\)+?\\)"
+ "# ?-+ \\1: expected output ?-+\n"
+ "\\(?3:\\(?:.*\n\\)+?\\)"
+ "# ?-+ \\1: end ?-+")
+ nil t)
+ (let ((name (match-string 1))
+ (code (match-string 2))
+ (expected (match-string 3))
+ got)
+ (with-temp-buffer
+ (insert code)
+ (goto-char (point-min))
+ (funcall cperl-test-mode)
+ ,@body
+ (setq expected (concat "test case " name ":\n" expected))
+ (setq got (concat "test case " name ":\n" (buffer-string)))
+ (should (equal got expected)))))))
+
+;;; Indentation tests
+
+(ert-deftest cperl-test-indent-exp ()
+ "Run various tests for `cperl-indent-exp' edge cases.
+These exercise some standard blocks and also the special
+treatment for Perl expressions where a closing paren isn't the
+end of the statement."
+ (skip-unless (eq cperl-test-mode #'cperl-mode))
+ (cperl--run-test-cases
+ (ert-resource-file "cperl-indent-exp.pl")
+ (cperl-indent-exp))) ; here we go!
+
+(ert-deftest cperl-test-indent-styles ()
+ (skip-unless (eq cperl-test-mode #'cperl-mode))
+ (cperl--run-test-cases
+ (ert-resource-file "cperl-indent-styles.pl")
+ (cperl-set-style "PBP")
+ (indent-region (point-min) (point-max)) ; here we go!
+ (cperl-set-style-back)))
+
+;;; Fontification tests
+
+(ert-deftest cperl-test-fontify-punct-vars ()
+ "Test fontification of Perl's punctiation variables.
+Perl has variable names containing unbalanced quotes for the list
+separator $\" and pre- and postmatch $` and $'. A reference to
+these variables, for example \\$\", should not cause the dollar
+to be escaped, which would then start a string beginning with the
+quote character. This used to be broken in cperl-mode at some
+point in the distant past, and is still broken in perl-mode. "
+ (skip-unless (eq cperl-test-mode #'cperl-mode))
+ (let ((file (ert-resource-file "fontify-punctuation-vars.pl")))
+ (with-temp-buffer
+ (insert-file-contents file)
+ (goto-char (point-min))
+ (funcall cperl-test-mode)
+ (while (search-forward "##" nil t)
+ ;; The third element of syntax-ppss is true if in a string,
+ ;; which would indicate bad interpretation of the quote. The
+ ;; fourth element is true if in a comment, which should be the
+ ;; case.
+ (should (equal (nth 3 (syntax-ppss)) nil))
+ (should (equal (nth 4 (syntax-ppss)) t))))))
+
+(ert-deftest cperl-test-fontify-declarations ()
+ "Test that declarations and package usage use consistent fontification."
+ (with-temp-buffer
+ (funcall cperl-test-mode)
+ (insert "package Foo::Bar;\n")
+ (insert "use Fee::Fie::Foe::Foo\n;")
+ (insert "my $xyzzy = 'PLUGH';\n")
+ (goto-char (point-min))
+ (font-lock-ensure)
+ (search-forward "Bar")
+ (should (equal (get-text-property (match-beginning 0) 'face)
+ 'font-lock-function-name-face))
+ (search-forward "use") ; This was buggy in perl-mode
+ (should (equal (get-text-property (match-beginning 0) 'face)
+ 'font-lock-keyword-face))
+ (search-forward "my")
+ (should (equal (get-text-property (match-beginning 0) 'face)
+ 'font-lock-keyword-face))))
+
+(ert-deftest cperl-test-fontify-attrs-and-signatures ()
+ "Test fontification of the various combinations of subroutine
+attributes, prototypes and signatures."
+ (skip-unless (eq cperl-test-mode #'cperl-mode))
+ (let ((file (ert-resource-file "proto-and-attrs.pl")))
+ (with-temp-buffer
+ (insert-file-contents file)
+ (goto-char (point-min))
+ (funcall cperl-test-mode)
+ (font-lock-ensure)
+
+ ;; Named subroutines
+ (while (search-forward-regexp "\\_<sub_[[:digit:]]+" nil t)
+ (should (equal (get-text-property (match-beginning 0) 'face)
+ 'font-lock-function-name-face))
+ (let ((start-of-sub (match-beginning 0))
+ (end-of-sub (save-excursion (search-forward "}") (point))))
+
+ ;; Prototypes are shown as strings
+ (when (search-forward-regexp " ([$%@*]*) " end-of-sub t)
+ (should (equal (get-text-property (1+ (match-beginning 0)) 'face)
+ 'font-lock-string-face)))
+ (goto-char start-of-sub)
+ (when (search-forward-regexp "\\(:[a-z]+\\)\\((.*?)\\)?" end-of-sub t)
+ (should (equal (get-text-property (match-beginning 1) 'face)
+ 'font-lock-constant-face))
+ (when (match-beginning 2)
+ (should (equal (get-text-property (match-beginning 2) 'face)
+ 'font-lock-string-face))))
+ (goto-char end-of-sub)))
+
+ ;; Anonymous subroutines
+ (while (search-forward-regexp "= sub" nil t)
+ (let ((start-of-sub (match-beginning 0))
+ (end-of-sub (save-excursion (search-forward "}") (point))))
+
+ ;; Prototypes are shown as strings
+ (when (search-forward-regexp " ([$%@*]*) " end-of-sub t)
+ (should (equal (get-text-property (1+ (match-beginning 0)) 'face)
+ 'font-lock-string-face)))
+ (goto-char start-of-sub)
+ (when (search-forward-regexp "\\(:[a-z]+\\)\\((.*?)\\)?" end-of-sub t)
+ (should (equal (get-text-property (match-beginning 1) 'face)
+ 'font-lock-constant-face))
+ (when (match-beginning 2)
+ (should (equal (get-text-property (match-beginning 2) 'face)
+ 'font-lock-string-face))))
+ (goto-char end-of-sub))))))
+
+(ert-deftest cperl-test-fontify-special-variables ()
+ "Test fontification of variables like $^T or ${^ENCODING}.
+These can occur as \"local\" aliases."
+ (skip-unless (eq cperl-test-mode #'cperl-mode))
+ (with-temp-buffer
+ (insert "local ($^I, ${^UNICODE});\n")
+ (goto-char (point-min))
+ (funcall cperl-test-mode)
+ (font-lock-ensure)
+ (search-forward "$")
+ (should (equal (get-text-property (point) 'face)
+ 'font-lock-variable-name-face))
+ (search-forward "$")
+ (should (equal (get-text-property (point) 'face)
+ 'font-lock-variable-name-face))))
+
+(ert-deftest cperl-test-identify-heredoc ()
+ "Test whether a construct containing \"<<\" followed by a
+ bareword is properly identified for a here-document if
+ appropriate."
+ (let ((here-docs
+ '("$text .= <<DELIM;" ; mutator concatenating a here-doc
+ "func($arg) . <<DELIM;" ; concatenating a return value
+ "func 1, <<DELIM;" ; a function taking two arguments
+ ))
+ ;; There forms are currently mishandled in `perl-mode' :-(
+ (here-docs-cperl
+ '("print {a} <<DELIM;" ; printing to a file handle
+ "system $prog <<DELIM;" ; lie about the program's name
+ ))
+ (_undecidable
+ '("foo <<bar") ; could be either "foo() <<bar"
+ ; or "foo(<<bar)"
+ ))
+ (dolist (code (append here-docs (if (eq cperl-test-mode #'cperl-mode)
+ here-docs-cperl)))
+ (with-temp-buffer
+ (insert code "\n\nDELIM\n")
+ (funcall cperl-test-mode)
+ (goto-char (point-min))
+ (forward-line 1)
+ ;; We should now be within a here-doc.
+ (let ((ppss (syntax-ppss)))
+ (should (and (nth 8 ppss) (nth 4 ppss))))
+ ))))
+
+(ert-deftest cperl-test-identify-no-heredoc ()
+ "Test whether a construct containing \"<<\" which is not a
+ here-document is properly rejected."
+ (let (
+ (not-here-docs
+ '("while (<<>>) {" ; double angle bracket operator
+ "expr <<func();" ; left shift by a return value
+ "$var <<func;" ; left shift by a return value
+ "($var+1) <<func;" ; same for an expression
+ "$hash{key} <<func;" ; same for a hash element
+ "or $var <<func;" ; same for an expression
+ "sorted $by <<func" ; _not_ a call to sort
+ ))
+ (_undecidable
+ '("foo <<bar" ; could be either "foo() <<bar"
+ ; or "foo(<<bar)"
+ "$foo = <<;") ; empty delim forbidden since 5.28
+ ))
+ (dolist (code not-here-docs)
+ (with-temp-buffer
+ (insert code "\n\n")
+ (funcall cperl-test-mode)
+ (goto-char (point-min))
+ (forward-line 1)
+ ;; Point is not within a here-doc (nor string nor comment).
+ (let ((ppss (syntax-ppss)))
+ (should-not (nth 8 ppss)))
+ ))))
+
+(ert-deftest cperl-test-here-doc-missing-end ()
+ "Verify that a missing here-document terminator gives a message.
+This message prints the terminator which wasn't found and is only
+issued by CPerl mode."
+ (skip-unless (eq cperl-test-mode #'cperl-mode))
+ (ert-with-message-capture collected-messages
+ (with-temp-buffer
+ (insert "my $foo = <<HERE\n")
+ (insert "some text here\n")
+ (goto-char (point-min))
+ (funcall cperl-test-mode)
+ (cperl-find-pods-heres)
+ (should (string-match "End of here-document [‘'`]HERE[’']"
+ collected-messages))))
+ (ert-with-message-capture collected-messages
+ (with-temp-buffer
+ (insert "my $foo = <<HERE . <<'THERE'\n")
+ (insert "some text here\n")
+ (insert "HERE\n")
+ (insert "more text here\n")
+ (goto-char (point-min))
+ (funcall cperl-test-mode)
+ (cperl-find-pods-heres)
+ (should (string-match "End of here-document [‘'`]THERE[’']"
+ collected-messages)))))
+
+(defvar perl-continued-statement-offset)
+(defvar perl-indent-level)
+
+(defconst cperl--tests-heredoc-face
+ (if (equal cperl-test-mode 'perl-mode) 'perl-heredoc
+ 'font-lock-string-face))
+(defconst cperl--tests-heredoc-delim-face
+ (if (equal cperl-test-mode 'perl-mode) 'perl-heredoc
+ 'font-lock-constant-face))
+
+(ert-deftest cperl-test-heredocs ()
+ "Test that HERE-docs are fontified with the appropriate face."
+ (require 'perl-mode)
+ (let ((file (ert-resource-file "here-docs.pl"))
+ (cperl-continued-statement-offset perl-continued-statement-offset)
+ (case-fold-search nil))
+ (with-temp-buffer
+ (insert-file-contents file)
+ (goto-char (point-min))
+ (funcall cperl-test-mode)
+ (indent-region (point-min) (point-max))
+ (font-lock-ensure (point-min) (point-max))
+ (while (search-forward "## test case" nil t)
+ (save-excursion
+ (while (search-forward "look-here" nil t)
+ (should (equal
+ (get-text-property (match-beginning 0) 'face)
+ cperl--tests-heredoc-face))
+ (beginning-of-line)
+ (should (null (looking-at "[ \t]")))
+ (forward-line 1)))
+ (should (re-search-forward
+ (concat "^\\([ \t]*\\)" ; the actual indentation amount
+ "\\([^ \t\n].*?\\)\\(no\\)?indent")
+ nil t))
+ (should (equal (- (match-end 1) (match-beginning 1))
+ (if (match-beginning 3) 0
+ perl-indent-level)))))))
+
+;;; Grammar based tests: unit tests
+
+(defun cperl-test--validate-regexp (regexp valid &optional invalid)
+ "Runs tests for elements of VALID and INVALID lists against REGEXP.
+Tests with elements from VALID must match, tests with elements
+from INVALID must not match. The match string must be equal to
+the whole string."
+ (funcall cperl-test-mode)
+ (dolist (string valid)
+ (should (string-match regexp string))
+ (should (string= (match-string 0 string) string)))
+ (when invalid
+ (dolist (string invalid)
+ (should-not
+ (and (string-match regexp string)
+ (string= (match-string 0 string) string))))))
+
+(ert-deftest cperl-test-ws-rx ()
+ "Tests capture of very simple regular expressions (yawn)."
+ (skip-unless (eq cperl-test-mode #'cperl-mode))
+ (let ((valid
+ '(" " "\t" "\n"))
+ (invalid
+ '("a" " " "")))
+ (cperl-test--validate-regexp (rx (eval cperl--ws-rx))
+ valid invalid)))
+
+(ert-deftest cperl-test-ws+-rx ()
+ "Tests sequences of whitespace and comment lines."
+ (skip-unless (eq cperl-test-mode #'cperl-mode))
+ (let ((valid
+ `(" " "\t#\n" "\n# \n"
+ ,(concat "# comment\n" "# comment\n" "\n" "#comment\n")))
+ (invalid
+ '("=head1 NAME\n" )))
+ (cperl-test--validate-regexp (rx (eval cperl--ws+-rx))
+ valid invalid)))
+
+(ert-deftest cperl-test-version-regexp ()
+ "Tests the regexp for recommended syntax of versions in Perl."
+ (skip-unless (eq cperl-test-mode #'cperl-mode))
+ (let ((valid
+ '("1" "1.1" "1.1_1" "5.032001"
+ "v120.100.103"))
+ (invalid
+ '("alpha" "0." ".123" "1E2"
+ "v1.1" ; a "v" version string needs at least 3 components
+ ;; bad examples from "Version numbers should be boring"
+ ;; by xdg AKA David A. Golden
+ "1.20alpha" "2.34beta2" "2.00R3")))
+ (cperl-test--validate-regexp cperl--version-regexp
+ valid invalid)))
+
+(ert-deftest cperl-test-package-regexp ()
+ "Tests the regular expression of Perl package names with versions.
+Also includes valid cases with whitespace in strange places."
+ (skip-unless (eq cperl-test-mode #'cperl-mode))
+ (let ((valid
+ '("package Foo"
+ "package Foo::Bar"
+ "package Foo::Bar v1.2.3"
+ "package Foo::Bar::Baz 1.1"
+ "package \nFoo::Bar\n 1.00"))
+ (invalid
+ '("package Foo;" ; semicolon must not be included
+ "package Foo 1.1 {" ; nor the opening brace
+ "packageFoo" ; not a package declaration
+ "package Foo1.1" ; invalid package name
+ "class O3D::Sphere"))) ; class not yet supported
+ (cperl-test--validate-regexp (rx (eval cperl--package-rx))
+ valid invalid)))
+
+(ert-deftest cperl-test-identifier-rx ()
+ "Test valid and invalid identifiers (no sigils)."
+ (skip-unless (eq cperl-test-mode #'cperl-mode))
+ (let ((valid
+ '("foo" "FOO" "f_oo" "a123"
+ "manĝis")) ; Unicode is allowed!
+ (invalid
+ '("$foo" ; no sigils allowed (yet)
+ "Foo::bar" ; no package qualifiers allowed
+ "lots_of_€"))) ; € is not alphabetic
+ (cperl-test--validate-regexp (rx (eval cperl--basic-identifier-rx))
+ valid invalid)))
+
+;;; Test unicode identifier in various places
+
+(defun cperl--test-unicode-setup (code string)
+ "Insert CODE, prepare it for tests, and find STRING.
+Invoke the appropriate major mode, ensure fontification, and set
+point after the first occurrence of STRING (no regexp!)."
+ (insert code)
+ (funcall cperl-test-mode)
+ (font-lock-ensure)
+ (goto-char (point-min))
+ (search-forward string))
+
+(ert-deftest cperl-test-unicode-labels ()
+ "Verify that non-ASCII labels are processed correctly."
+ (with-temp-buffer
+ (cperl--test-unicode-setup "LABEł: for ($manĝi) { say; }" "LAB")
+ (should (equal (get-text-property (point) 'face)
+ 'font-lock-constant-face))))
+
+(ert-deftest cperl-test-unicode-sub ()
+ (with-temp-buffer
+ (cperl--test-unicode-setup
+ (concat "use strict;\n" ; distinguish bob from b-o-f
+ "sub ℏ {\n"
+ " 6.62607015e-34\n"
+ "};")
+ "sub ") ; point is before "ℏ"
+
+ ;; Testing fontification
+ ;; FIXME 2021-09-10: This tests succeeds because cperl-mode
+ ;; accepts almost anything as a sub name for fontification. For
+ ;; example, it fontifies "sub @ {...;}" which is a syntax error in
+ ;; Perl. I let this pass for the moment.
+ (should (equal (get-text-property (point) 'face)
+ 'font-lock-function-name-face))
+
+ ;; Testing `beginning-of-defun'. Not available in perl-mode,
+ ;; where it jumps to the beginning of the buffer.
+ (when (eq cperl-test-mode #'cperl-mode)
+ (goto-char (point-min))
+ (search-forward "-34")
+ (beginning-of-defun)
+ (should (looking-at "sub")))))
+
+(ert-deftest cperl-test-unicode-varname ()
+ (with-temp-buffer
+ (cperl--test-unicode-setup
+ (concat "use strict;\n"
+ "my $π = 3.1415926535897932384626433832795028841971;\n"
+ "\n"
+ "my $manĝi = $π;\n"
+ "__END__\n")
+ "my $") ; perl-mode doesn't fontify the sigil, so include it here
+
+ ;; Testing fontification
+ ;; FIXME 2021-09-10: This test succeeds in cperl-mode because the
+ ;; π character is "not ASCII alphabetic", so it treats $π as a
+ ;; punctuation variable. The following two `should' forms with a
+ ;; longer variable name were added for stronger verification.
+ (should (equal (get-text-property (point) 'face)
+ 'font-lock-variable-name-face))
+ ;; Test both ends of a longer variable name
+ (search-forward "my $") ; again skip the sigil
+ (should (equal (get-text-property (point) 'face)
+ 'font-lock-variable-name-face))
+ (search-forward "manĝi")
+ (should (equal (get-text-property (1- (match-end 0)) 'face)
+ 'font-lock-variable-name-face))))
+
+(ert-deftest cperl-test-unicode-varname-list ()
+ "Verify that all elements of a variable list are fontified."
+
+ (let ((hash-face (if (eq cperl-test-mode #'perl-mode)
+ 'perl-non-scalar-variable
+ 'cperl-hash-face))
+ (array-face (if (eq cperl-test-mode #'perl-mode)
+ 'perl-non-scalar-variable
+ 'cperl-array-face)))
+ (with-temp-buffer
+ (cperl--test-unicode-setup
+ "my (%äsh,@ärräy,$scâlâr);" "%")
+ (should (equal (get-text-property (point) 'face)
+ hash-face))
+ (search-forward "@")
+ (should (equal (get-text-property (point) 'face)
+ array-face))
+ (search-forward "scâlâr")
+ (should (equal (get-text-property (match-beginning 0) 'face)
+ 'font-lock-variable-name-face))
+ (should (equal (get-text-property (1- (match-end 0)) 'face)
+ 'font-lock-variable-name-face)))
+
+ ;; Now with package-qualified variables
+ (with-temp-buffer
+ (cperl--test-unicode-setup
+ "local (%Søme::äsh,@Søme::ärräy,$Søme::scâlâr);" "%")
+ (should (equal (get-text-property (point) 'face)
+ hash-face))
+ (search-forward "Søme::") ; test basic identifier
+ (should (equal (get-text-property (point) 'face)
+ hash-face))
+ (search-forward "@") ; test package name
+ (should (equal (get-text-property (point) 'face)
+ array-face))
+ (search-forward "Søme::") ; test basic identifier
+ (should (equal (get-text-property (point) 'face)
+ array-face))
+ (search-forward "Søme") ; test package name
+ (should (equal (get-text-property (match-beginning 0) 'face)
+ 'font-lock-variable-name-face))
+ (should (equal (get-text-property (1- (match-end 0)) 'face)
+ 'font-lock-variable-name-face))
+ (search-forward "scâlâr") ; test basic identifier
+ (should (equal (get-text-property (match-beginning 0) 'face)
+ 'font-lock-variable-name-face))
+ (should (equal (get-text-property (1- (match-end 0)) 'face)
+ 'font-lock-variable-name-face)))))
+
+(ert-deftest cperl-test-unicode-arrays ()
+ "Test fontification of array access."
+ ;; Perl mode just looks at the sigil, for element access
+ (skip-unless (eq cperl-test-mode #'cperl-mode))
+ ;; simple array element
+ (with-temp-buffer
+ (cperl--test-unicode-setup
+ "$ärräy[1] = 7;" "$")
+ (should (equal (get-text-property (point) 'face)
+ 'cperl-array-face)))
+ ;; array slice
+ (with-temp-buffer
+ (cperl--test-unicode-setup
+ "@ärräy[(1..3)] = (4..6);" "@")
+ (should (equal (get-text-property (point) 'face)
+ 'cperl-array-face)))
+ ;; array max index
+ (with-temp-buffer
+ (cperl--test-unicode-setup
+ "$#ärräy = 1;" "$")
+ (should (equal (get-text-property (point) 'face)
+ 'cperl-array-face)))
+ ;; array dereference
+ (with-temp-buffer
+ (cperl--test-unicode-setup
+ "@$ärräy = (1,2,3)" "@")
+ (should (equal (get-text-property (1- (point)) 'face)
+ 'cperl-array-face))
+ (should (equal (get-text-property (1+ (point)) 'face)
+ 'font-lock-variable-name-face))))
+
+(ert-deftest cperl-test-unicode-hashes ()
+ "Test fontification of hash access."
+ ;; Perl mode just looks at the sigil, for element access
+ (skip-unless (eq cperl-test-mode #'cperl-mode))
+ ;; simple hash element
+ (with-temp-buffer
+ (cperl--test-unicode-setup
+ "$häsh{'a'} = 7;" "$")
+ (should (equal (get-text-property (point) 'face)
+ 'cperl-hash-face)))
+ ;; hash array slice
+ (with-temp-buffer
+ (cperl--test-unicode-setup
+ "@häsh{(1..3)} = (4..6);" "@")
+ (should (equal (get-text-property (point) 'face)
+ 'cperl-hash-face)))
+ ;; hash subset
+ (with-temp-buffer
+ (cperl--test-unicode-setup
+ "my %hash = %häsh{'a',2,3};" "= %")
+ (should (equal (get-text-property (point) 'face)
+ 'cperl-hash-face)))
+ ;; hash dereference
+ (with-temp-buffer
+ (cperl--test-unicode-setup
+ "%$äsh = (key => 'value');" "%")
+ (should (equal (get-text-property (1- (point)) 'face)
+ 'cperl-hash-face))
+ (should (equal (get-text-property (1+ (point)) 'face)
+ 'font-lock-variable-name-face))))
+
+(ert-deftest cperl-test-unicode-hashref ()
+ "Verify that a hashref access disambiguates {s}.
+CPerl mode takes the token \"s\" as a substitution unless
+detected otherwise. Not for perl-mode: it doesn't stringify
+bareword hash keys and doesn't recognize a substitution
+\"s}foo}bar}\""
+ (skip-unless (eq cperl-test-mode #'cperl-mode))
+ (with-temp-buffer
+ (cperl--test-unicode-setup "$häshref->{s} # }}" "{")
+ (should (equal (get-text-property (point) 'face)
+ 'font-lock-string-face))
+ (should (equal (get-text-property (1+ (point)) 'face)
+ nil))))
+
+(ert-deftest cperl-test-unicode-proto ()
+ ;; perl-mode doesn't fontify prototypes at all
+ (skip-unless (eq cperl-test-mode #'cperl-mode))
+ (with-temp-buffer
+ (cperl--test-unicode-setup
+ (concat "sub prötötyped ($) {\n"
+ " ...;"
+ "}\n")
+ "prötötyped (")
+
+ (should (equal (get-text-property (point) 'face)
+ 'font-lock-string-face))))
+
+(ert-deftest cperl-test-unicode-fhs ()
+ (with-temp-buffer
+ (cperl--test-unicode-setup
+ (concat "while (<BAREWÖRD>) {\n"
+ " ...;)\n"
+ "}\n")
+ "while (<") ; point is before the first char of the handle
+ ;; Testing fontification
+ ;; FIXME 2021-09-10: perl-mode.el and cperl-mode.el handle these
+ ;; completely differently. perl-mode interprets barewords as
+ ;; constants, cperl-mode does not fontify them. Both treat
+ ;; non-barewords as globs, which are not fontified by perl-mode,
+ ;; but fontified as strings in cperl-mode. We keep (and test)
+ ;; that behavior "as is" because both bareword filehandles and
+ ;; <glob> syntax are no longer recommended.
+ (let ((bareword-face
+ (if (equal cperl-test-mode 'perl-mode) 'font-lock-constant-face
+ nil)))
+ (should (equal (get-text-property (point) 'face)
+ bareword-face)))))
+
+(ert-deftest cperl-test-unicode-hashkeys ()
+ "Test stringification of bareword hash keys. Not in perl-mode.
+perl-mode generally does not stringify bareword hash keys."
+ (skip-unless (eq cperl-test-mode #'cperl-mode))
+ ;; Plain hash key
+ (with-temp-buffer
+ (cperl--test-unicode-setup
+ "$häsh { kéy }" "{ ")
+ (should (equal (get-text-property (point) 'face)
+ 'font-lock-string-face)))
+ ;; Nested hash key
+ (with-temp-buffer
+ (cperl--test-unicode-setup
+ "$häsh { kéy } { kèy }" "} { ")
+ (should (equal (get-text-property (point) 'face)
+ 'font-lock-string-face)))
+ ;; Key => value
+ (with-temp-buffer
+ (cperl--test-unicode-setup
+ "( kéy => 'value'," "( ")
+ (should (equal (get-text-property (point) 'face)
+ 'font-lock-string-face))))
+
+(ert-deftest cperl-test-word-at-point ()
+ "Test whether the function captures non-ASCII words."
+ (skip-unless (eq cperl-test-mode #'cperl-mode))
+ (let ((words '("rôle" "café" "ångström"
+ "Data::Dump::dump"
+ "_underscore")))
+ (dolist (word words)
+ (with-temp-buffer
+ (insert " + ") ; this will be the suffix
+ (beginning-of-line)
+ (insert ")") ; A non-word char
+ (insert word)
+ (should (string= word (cperl-word-at-point-hard)))))))
+
+;;; Function test: Building an index for imenu
+
+(ert-deftest cperl-test-imenu-index ()
+ "Test index creation for imenu.
+This test relies on the specific layout of the index alist as
+created by CPerl mode, so skip it for Perl mode."
+ (skip-unless (eq cperl-test-mode #'cperl-mode))
+ (with-temp-buffer
+ (insert-file-contents (ert-resource-file "grammar.pl"))
+ (cperl-mode)
+ (let ((index (cperl-imenu--create-perl-index))
+ current-list)
+ (setq current-list (assoc-string "+Unsorted List+..." index))
+ (should current-list)
+ (let ((expected '("(main)::outside"
+ "Package::in_package"
+ "Shoved::elsewhere"
+ "Package::prototyped"
+ "Versioned::Package::versioned"
+ "Block::attr"
+ "Versioned::Package::outer"
+ "lexical"
+ "Versioned::Block::signatured"
+ "Package::in_package_again"
+ "Erdős::Number::erdős_number")))
+ (dolist (sub expected)
+ (should (assoc-string sub index)))))))
+
+;;; Tests for issues reported in the Bug Tracker
+
+(ert-deftest cperl-test-bug-997 ()
+ "Test that we distinguish a regexp match when there's nothing before it."
+ (let ((code "# some comment\n\n/fontify me/;\n"))
+ (with-temp-buffer
+ (funcall cperl-test-mode)
+ (insert code)
+ (font-lock-ensure)
+ (goto-char (point-min))
+ (search-forward "/f")
+ (should (equal (get-text-property (point) 'face)
+ 'font-lock-string-face)))))
+
+(defun cperl-test--run-bug-10483 ()
+ "Runs a short program, intended to be under timer scrutiny.
+This function is intended to be used by an Emacs subprocess in
+batch mode. The message buffer is used to report the result of
+running `cperl-indent-exp' for a very simple input. The result
+is expected to be different from the input, to verify that
+indentation actually takes place.."
+ (let ((code "poop ('foo', \n'bar')")) ; see the bug report
+ (message "Test Bug#10483 started")
+ (with-temp-buffer
+ (insert code)
+ (funcall cperl-test-mode)
+ (goto-char (point-min))
+ (search-forward "poop")
+ (cperl-indent-exp)
+ (message "%s" (buffer-string)))))
+
+(ert-deftest cperl-test-bug-10483 ()
+ "Check that indenting certain perl code does not loop forever.
+This verifies that indenting a piece of code that ends in a paren
+without a statement terminator on the same line does not loop
+forever. The test starts an asynchronous Emacs batch process
+under timeout control."
+ :tags '(:expensive-test)
+ (skip-unless (not (getenv "EMACS_HYDRA_CI"))) ; FIXME times out
+ (skip-unless (not (< emacs-major-version 28))) ; times out in older Emacsen
+ (skip-unless (eq cperl-test-mode #'cperl-mode))
+ (let* ((emacs (concat invocation-directory invocation-name))
+ (test-function 'cperl-test--run-bug-10483)
+ (test-function-name (symbol-name test-function))
+ (test-file (symbol-file test-function 'defun))
+ (ran-out-of-time nil)
+ (process-connection-type nil)
+ runner)
+ (with-temp-buffer
+ (with-timeout (2
+ (delete-process runner)
+ (setq ran-out-of-time t))
+ (setq runner (start-process "speedy"
+ (current-buffer)
+ emacs
+ "-batch"
+ "--quick"
+ "--load" test-file
+ "--funcall" test-function-name))
+ (while (accept-process-output runner)))
+ (should (equal ran-out-of-time nil))
+ (goto-char (point-min))
+ ;; just a very simple test for indentation: This should
+ ;; be rather robust with regard to indentation defaults
+ (should (string-match
+ "poop ('foo', \n 'bar')" (buffer-string))))))
+
+(ert-deftest cperl-test-bug-11996 ()
+ "Verify that we give the right syntax property to a backslash operator."
+ (with-temp-buffer
+ (insert-file-contents (ert-resource-file "cperl-bug-11996.pl"))
+ (funcall cperl-test-mode)
+ (font-lock-ensure)
+ (goto-char (point-min))
+ (re-search-forward "\\(\\\\(\\)")
+ (save-excursion
+ (goto-char (match-beginning 1))
+ (should (equal (syntax-after (point)) (string-to-syntax ".")))
+ ;; `forward-sexp' shouldn't complain.
+ (forward-sexp)
+ (should (char-equal (char-after) ?\;)))
+ (re-search-forward "\\(\\\\\"\\)")
+ (save-excursion
+ (goto-char (match-beginning 1))
+ (should (equal (syntax-after (point)) (string-to-syntax "\\")))
+ (should (equal (get-text-property (point) 'face) 'font-lock-string-face)))
+ (re-search-forward "\\(\\\\\"\\)")
+ (save-excursion
+ (goto-char (match-beginning 1))
+ (should (equal (syntax-after (point)) (string-to-syntax "\\"))))
+ (re-search-forward "\\(\\\\\"\\)")
+ (save-excursion
+ (goto-char (match-beginning 1))
+ (should (equal (syntax-after (point)) (string-to-syntax ".")))
+ (should (equal (get-text-property (1+ (point)) 'face)
+ 'font-lock-string-face)))))
+
+(ert-deftest cperl-test-bug-14343 ()
+ "Verify that inserting text into a HERE-doc string with Elisp
+does not break fontification."
+ (with-temp-buffer
+ (insert "my $string = <<HERE;\n"
+ "One line of text.\n"
+ "Last line of this string.\n"
+ "HERE\n")
+ (funcall cperl-test-mode)
+ (font-lock-ensure)
+ (goto-char (point-min))
+ (search-forward "One line")
+ (should (equal (get-text-property (point) 'face)
+ cperl--tests-heredoc-face))
+ (beginning-of-line)
+ (insert "Another line if text.\n")
+ (font-lock-ensure)
+ (forward-line -1)
+ (should (equal (get-text-property (point) 'face)
+ cperl--tests-heredoc-face))
+ (search-forward "HERE")
+ (beginning-of-line)
+ (should (equal (get-text-property (point) 'face)
+ cperl--tests-heredoc-delim-face)))
+ ;; insert into an empty here-document
+ (with-temp-buffer
+ (insert "print <<HERE;\n"
+ "HERE\n")
+ (funcall cperl-test-mode)
+ (font-lock-ensure)
+ (goto-char (point-min))
+ (forward-line)
+ (should (equal (get-text-property (point) 'face)
+ cperl--tests-heredoc-delim-face))
+ ;; Insert a newline into the empty here-document
+ (goto-char (point-min))
+ (forward-line)
+ (insert "\n")
+ (search-forward "HERE")
+ (beginning-of-line)
+ (should (equal (get-text-property (point) 'face)
+ cperl--tests-heredoc-delim-face))
+ ;; Insert text at the beginning of the here-doc
+ (goto-char (point-min))
+ (forward-line)
+ (insert "text")
+ (font-lock-ensure)
+ (search-backward "text")
+ (should (equal (get-text-property (point) 'face)
+ cperl--tests-heredoc-face))
+ (search-forward "HERE")
+ (beginning-of-line)
+ (should (equal (get-text-property (point) 'face)
+ cperl--tests-heredoc-delim-face))
+ ;; Insert a new line immediately before the delimiter
+ ;; (That's where the point is anyway)
+ (insert "A new line\n")
+ (font-lock-ensure)
+ ;; The delimiter is still the delimiter
+ (should (equal (get-text-property (point) 'face)
+ cperl--tests-heredoc-delim-face))
+ (forward-line -1)
+ ;; The new line has been "added" to the here-document
+ (should (equal (get-text-property (point) 'face)
+ cperl--tests-heredoc-face))))
+
+(ert-deftest cperl-test-bug-16368 ()
+ "Verify that `cperl-forward-group-in-re' doesn't hide errors."
+ (skip-unless (eq cperl-test-mode #'cperl-mode))
+ (let ((code "/(\\d{4})(?{2}/;") ; the regex from the bug report
+ (result))
+ (with-temp-buffer
+ (insert code)
+ (goto-char 9)
+ (setq result (cperl-forward-group-in-re))
+ (should (equal (car result) 'scan-error))
+ (should (equal (nth 1 result) "Unbalanced parentheses"))
+ (should (= (point) 9)))) ; point remains unchanged on error
+ (let ((code "/(\\d{4})(?{2})/;") ; here all parens are balanced
+ (result))
+ (with-temp-buffer
+ (insert code)
+ (goto-char 9)
+ (setq result (cperl-forward-group-in-re))
+ (should (equal result nil))
+ (should (= (point) 15))))) ; point has skipped the group
+
+(ert-deftest cperl-test-bug-19709 ()
+ "Verify that indentation of closing paren works as intended.
+Note that Perl mode has no setting for close paren offset, per
+documentation it does the right thing anyway."
+ (cperl--run-test-cases
+ (ert-resource-file "cperl-bug-19709.pl")
+ ;; settings from the bug report
+ (setq-local cperl-indent-level 4)
+ (setq-local cperl-indent-parens-as-block t)
+ (setq-local cperl-close-paren-offset -4)
+ ;; same, adapted for per-mode
+ (setq-local perl-indent-level 4)
+ (setq-local perl-indent-parens-as-block t)
+ (while (null (eobp))
+ (cperl-indent-command)
+ (forward-line 1))))
+
+(ert-deftest cperl-test-bug-22355 ()
+ "Verify that substitutions are fontified directly after \"|&\".
+Regular expressions are strings in both perl-mode and cperl-mode."
+ (with-temp-buffer
+ (insert-file-contents (ert-resource-file "cperl-bug-22355.pl"))
+ (funcall cperl-test-mode)
+ (goto-char (point-min))
+ ;; Just check for the start of the string
+ (search-forward "{")
+ (should (nth 3 (syntax-ppss)))))
+
+(ert-deftest cperl-test-bug-23992 ()
+ "Verify that substitutions are fontified directly after \"|&\".
+Regular expressions are strings in both perl-mode and cperl-mode."
+ (with-temp-buffer
+ (insert-file-contents (ert-resource-file "cperl-bug-23992.pl"))
+ (funcall cperl-test-mode)
+ (goto-char (point-min))
+ ;; "or" operator, with spaces
+ (search-forward "RIGHT")
+ (should (nth 3 (syntax-ppss)))
+ ;; "or" operator, without spaces
+ (search-forward "RIGHT")
+ (should (nth 3 (syntax-ppss)))
+ ;; "and" operator, with spaces
+ (search-forward "RIGHT")
+ (should (nth 3 (syntax-ppss)))
+ ;; "and" operator, without spaces
+ (search-forward "RIGHT")
+ (should (nth 3 (syntax-ppss)))))
+
+(ert-deftest cperl-test-bug-25098 ()
+ "Verify that a quotelike operator is recognized after a fat comma \"=>\".
+Related, check that calling a method named q is not mistaken as a
+quotelike operator."
+ (with-temp-buffer
+ (insert-file-contents (ert-resource-file "cperl-bug-25098.pl"))
+ (funcall cperl-test-mode)
+ (goto-char (point-min))
+ ;; good example from the bug report, with a space
+ (search-forward "q{")
+ (should (nth 3 (syntax-ppss)))
+ ;; bad (but now fixed) example from the bug report, without space
+ (search-forward "q{")
+ (should (nth 3 (syntax-ppss)))
+ ;; calling a method "q" (parens instead of braces to make it valid)
+ (search-forward "q(")
+ (should-not (nth 3 (syntax-ppss)))))
+
+(ert-deftest cperl-test-bug-28650 ()
+ "Verify that regular expressions are recognized after 'return'.
+The test uses the syntax property \"inside a string\" for the
+text in regular expressions, which is non-nil for both cperl-mode
+and perl-mode."
+ (with-temp-buffer
+ (insert-file-contents (ert-resource-file "cperl-bug-26850.pl"))
+ (goto-char (point-min))
+ (re-search-forward "sub interesting {[^}]*}")
+ (should-not (equal (nth 3 (cperl-test-ppss (match-string 0) "Today"))
+ nil))
+ (re-search-forward "sub boring {[^}]*}")
+ (should-not (equal (nth 3 (cperl-test-ppss (match-string 0) "likes\\?"))
+ nil))))
+
+(ert-deftest cperl-test-bug-30393 ()
+ "Verify that indentation is not disturbed by an open paren in col 0.
+Perl is not Lisp: An open paren in column 0 does not start a function."
+ (cperl--run-test-cases
+ (ert-resource-file "cperl-bug-30393.pl")
+ (while (null (eobp))
+ (cperl-indent-command)
+ (forward-line 1))))
+
+(ert-deftest cperl-test-bug-37127 ()
+ "Verify that closing a paren in a regex goes without a message.
+Also check that the message is issued if the regex terminator is
+missing."
+ ;; The actual fix for this bug is in simple.el, which is not
+ ;; backported to older versions of Emacs. Therefore we skip this
+ ;; test if we're running Emacs 27 or older.
+ (skip-unless (< 27 emacs-major-version))
+ ;; Part one: Regex is ok, no messages
+ (ert-with-message-capture collected-messages
+ (with-temp-buffer
+ (insert "$_ =~ /(./;")
+ (funcall cperl-test-mode)
+ (goto-char (point-min))
+ (search-forward ".")
+ (let ((last-command-event ?\))
+ ;; Don't emit "Matches ..." even if not visible (e.g. in batch).
+ (blink-matching-paren 'jump-offscreen))
+ (self-insert-command 1)
+ ;; `self-insert-command' doesn't call `blink-matching-open' in
+ ;; batch mode, so we need to call it explicitly.
+ (blink-matching-open))
+ (syntax-propertize (point-max)))
+ (should (string-equal collected-messages "")))
+ ;; part two: Regex terminator missing -> message
+ (when (eq cperl-test-mode #'cperl-mode)
+ ;; This test is only run in `cperl-mode' because only cperl-mode
+ ;; emits a message to warn about such unclosed REs.
+ (ert-with-message-capture collected-messages
+ (with-temp-buffer
+ (insert "$_ =~ /(..;")
+ (goto-char (point-min))
+ (funcall cperl-test-mode)
+ (search-forward ".")
+ (let ((last-command-event ?\)))
+ (self-insert-command 1))
+ (syntax-propertize (point-max)))
+ (should (string-match "^End of .* string/RE"
+ collected-messages)))))
+
+(ert-deftest cperl-test-bug-42168 ()
+ "Verify that '/' is a division after ++ or --, not a regexp.
+Reported in https://github.com/jrockway/cperl-mode/issues/45.
+If seen as regular expression, then the slash is displayed using
+font-lock-constant-face. If seen as a division, then it doesn't
+have a face property."
+ :tags '(:fontification)
+ ;; The next two Perl expressions have divisions. The slash does not
+ ;; start a string.
+ (let ((code "{ $a++ / $b }"))
+ (should (equal (nth 8 (cperl-test-ppss code "/")) nil)))
+ (let ((code "{ $a-- / $b }"))
+ (should (equal (nth 8 (cperl-test-ppss code "/")) nil)))
+ ;; The next two Perl expressions have regular expressions. The slash
+ ;; starts a string.
+ (let ((code "{ $a+ / $b } # /"))
+ (should (equal (nth 8 (cperl-test-ppss code "/")) 7)))
+ (let ((code "{ $a- / $b } # /"))
+ (should (equal (nth 8 (cperl-test-ppss code "/")) 7))))
+
+(ert-deftest cperl-test-bug-45255 ()
+ "Verify that \"<<>>\" is recognized as not starting a HERE-doc."
+ (let ((code (concat "while (<<>>) {\n"
+ " ...;\n"
+ "}\n")))
+ ;; The yadda-yadda operator should not be in a string.
+ (should (equal (nth 8 (cperl-test-ppss code "\\.")) nil))))
+
+(ert-deftest cperl-test-bug-47112 ()
+ "Check that in a bareword starting with a quote-like operator
+followed by an underscore is not interpreted as that quote-like
+operator. Also check that a quote-like operator followed by a
+colon (which is, like ?_, a symbol in CPerl mode) _is_ identified
+as that quote like operator."
+ (with-temp-buffer
+ (funcall cperl-test-mode)
+ (insert "sub y_max { q:bar:; y _bar_foo_; }")
+ (goto-char (point-min))
+ (syntax-propertize (point-max))
+ (font-lock-ensure)
+ (search-forward "max")
+ (should (equal (get-text-property (match-beginning 0) 'face)
+ 'font-lock-function-name-face))
+ (search-forward "bar")
+ (should (equal (get-text-property (match-beginning 0) 'face)
+ 'font-lock-string-face))
+ ; perl-mode doesn't highlight
+ (when (eq cperl-test-mode #'cperl-mode)
+ (search-forward "_")
+ (should (equal (get-text-property (match-beginning 0) 'face)
+ (if (eq cperl-test-mode #'cperl-mode)
+ 'font-lock-constant-face
+ font-lock-string-face))))))
+
+(ert-deftest cperl-test-hyperactive-electric-else ()
+ "Demonstrate cperl-electric-else behavior.
+If `cperl-electric-keywords' is true, keywords like \"else\" and
+\"continue\" are expanded by a following empty block, with the
+cursor in the appropriate position to write that block. This,
+however, must not happen when the keyword occurs in a variable
+\"$else\" or \"$continue\"."
+ (skip-unless (eq cperl-test-mode #'cperl-mode))
+ ;; `self-insert-command' takes a second argument only since Emacs 27
+ (skip-unless (not (< emacs-major-version 27)))
+ (with-temp-buffer
+ (setq cperl-electric-keywords t)
+ (cperl-mode)
+ (insert "continue")
+ (self-insert-command 1 ?\ )
+ (indent-region (point-min) (point-max))
+ (goto-char (point-min))
+ ;; cperl-mode creates a block here
+ (should (search-forward-regexp "continue {\n[[:blank:]]+\n}")))
+ (with-temp-buffer
+ (setq cperl-electric-keywords t)
+ (cperl-mode)
+ (insert "$continue")
+ (self-insert-command 1 ?\ )
+ (indent-region (point-min) (point-max))
+ (goto-char (point-min))
+ ;; No block should have been created here
+ (should-not (search-forward-regexp "{" nil t))))
+
+(ert-deftest cperl-test-bug-47598 ()
+ "Check that a file test followed by ? is no longer interpreted
+as a regex."
+ ;; Testing the text from the bug report
+ (with-temp-buffer
+ (insert "my $f = -f ? 'file'\n")
+ (insert " : -l ? [readlink]\n")
+ (insert " : -d ? 'dir'\n")
+ (insert " : 'unknown';\n")
+ (funcall cperl-test-mode)
+ ;; Perl mode doesn't highlight file tests as functions, so we
+ ;; can't test for the function's face. But we can verify that the
+ ;; function is not a string.
+ (goto-char (point-min))
+ (search-forward "?")
+ (should-not (nth 3 (syntax-ppss (point)))))
+ ;; Testing the actual targets for the regexp: m?foo? (still valid)
+ ;; and ?foo? (invalid since Perl 5.22)
+ (with-temp-buffer
+ (insert "m?foo?;")
+ (funcall cperl-test-mode)
+ (should (nth 3 (syntax-ppss 3))))
+ (with-temp-buffer
+ (insert " ?foo?;")
+ (funcall cperl-test-mode)
+ (should-not (nth 3 (syntax-ppss 3)))))
+
+(ert-deftest test-indentation ()
+ (ert-test-erts-file (ert-resource-file "cperl-indents.erts")))
+
+;;; cperl-mode-tests.el ends here
diff --git a/test/lisp/progmodes/elisp-mode-resources/elisp-indents.erts b/test/lisp/progmodes/elisp-mode-resources/elisp-indents.erts
new file mode 100644
index 00000000000..2c0d51edae8
--- /dev/null
+++ b/test/lisp/progmodes/elisp-mode-resources/elisp-indents.erts
@@ -0,0 +1,88 @@
+Code:
+ (lambda ()
+ (emacs-lisp-mode)
+ (indent-region (point-min) (point-max)))
+
+Name: defun
+
+=-=
+(defun foo ()
+"doc"
+(+ 1 2))
+=-=
+(defun foo ()
+ "doc"
+ (+ 1 2))
+=-=-=
+
+Name: function call
+
+=-=
+(foo zot
+bar
+(zot bar))
+=-=
+(foo zot
+ bar
+ (zot bar))
+=-=-=
+
+Name: lisp data
+
+=-=
+( foo zot
+bar
+(zot bar))
+=-=
+( foo zot
+ bar
+ (zot bar))
+=-=-=
+
+Name: defun-space
+
+=-=
+(defun x ()
+ (print (quote ( thingy great
+ stuff)))
+ (print (quote (thingy great
+ stuff))))
+=-=-=
+
+Name: defvar-keymap
+
+=-=
+(defvar-keymap eww-link-keymap
+ :copy shr-map
+ :foo bar
+ "\r" #'eww-follow-link)
+=-=-=
+
+Name: def-indent1
+
+=-=
+(defzot-does-not-exist 1
+ 2 3)
+=-=-=
+
+Name: def-indent2
+
+=-=
+(define-keymap 1
+ 2 3)
+=-=-=
+
+Name: elisp-indents1
+
+=-=
+(defvar foo
+ ()
+ "bar")
+=-=-=
+
+Name: elisp-indents2
+
+=-=
+(defvar foo ()
+ "bar")
+=-=-=
diff --git a/test/lisp/progmodes/elisp-mode-resources/flet.erts b/test/lisp/progmodes/elisp-mode-resources/flet.erts
new file mode 100644
index 00000000000..da3dcb6ec3e
--- /dev/null
+++ b/test/lisp/progmodes/elisp-mode-resources/flet.erts
@@ -0,0 +1,353 @@
+Name: flet1
+
+=-=
+(cl-flet ()
+ (a (dangerous-position
+ b)))
+=-=-=
+
+Name: flet2
+
+=-=
+(cl-flet wrong-syntax-but-should-not-obstruct-indentation
+ (a (dangerous-position
+ b)))
+=-=-=
+
+Name: flet3
+
+=-=
+(cl-flet ((a (arg-of-flet-a)
+ b
+ c)))
+=-=-=
+
+Name: flet4
+
+=-=
+(cl-flet ((a (arg-of-flet-a)
+ b
+ c
+ (if d
+ e
+ f))
+ (irregular-local-def (form
+ returning
+ lambda))
+ (g (arg-of--flet-g)
+ h
+ i))
+ (let ((j k))
+ (if dangerous-position
+ l
+ m)))
+=-=-=
+
+Name: flet5
+
+=-=
+(cl-flet ((a (arg-of-flet-a)
+ b
+ c
+ (if d
+ e
+ f))
+ (irregular-local-def (form
+ returning
+ lambda))
+ (g (arg-of--flet-g)
+ h
+ i))
+ (let ((j k))
+ (if dangerous-position
+ l
+ m)))
+=-=-=
+
+Name: flet6
+
+=-=
+(cl-flet ((a (arg-of-flet-a)
+ b
+ c
+ (if d
+ e
+ f))
+ (irregular-local-def (form
+ returning
+ lambda))
+ (irregular-local-def (form returning
+ lambda))
+ wrong-syntax-but-should-not-osbtruct-indentation
+ (g (arg-of--flet-g)
+ h
+ i))
+ (let ((j k))
+ (if dangerous-position
+ l
+ m)))
+=-=-=
+
+Name: flet7
+
+=-=
+(cl-flet ((a (arg-of-flet-a)
+ b
+ c
+ (if d
+ e
+ f))
+ (irregular-local-def (form
+ returning
+ lambda))
+ wrong-syntax-but-should-not-osbtruct-indentation
+ (g (arg-of--flet-g)
+ h
+ i))
+ (let ((j k))
+ (if dangerous-position
+ l
+ m)))
+=-=-=
+
+Name: flet8
+
+=-=
+(cl-flet (wrong-syntax-but-should-not-obstruct-indentation
+ (g (arg-of--flet-g)
+ h
+ i))
+ (let ((j k))
+ (if dangerous-position
+ l
+ m)))
+=-=-=
+
+;; (setf _) not yet supported but looks like it will be
+Name: flet9
+
+=-=
+(cl-flet (((setf a) (new value)
+ stuff)
+ wrong-syntax-but-should-not-obstruct-indentation
+ (g (arg-of--flet-g)
+ h
+ i))
+ (let ((j k))
+ (if dangerous-position
+ l
+ m)))
+=-=-=
+
+Name: flet10
+
+=-=
+(cl-flet ( (a (arg-of-flet-a)
+ b
+ c
+ (if d
+ e
+ f))
+ (irregular-local-def (form
+ returning
+ lambda))
+ (g (arg-of--flet-g)
+ h
+ i))
+ (let ((j k))
+ (if dangerous-position
+ l
+ m)))
+=-=-=
+
+Name: flet11
+
+=-=
+(cl-flet ( wrong-syntax-but-should-not-obstruct-indentation
+ (g (arg-of--flet-g)
+ h
+ i))
+ (let ((j k))
+ (if dangerous-position
+ l
+ m)))
+=-=-=
+
+Name: flet12
+
+=-=
+(cl-flet ( wrong-syntax-but-should-not-obstruct-indentation
+ (g (arg-of--flet-g)
+ h
+ i))
+ (let ((j k))
+ (if dangerous-position
+ l
+ m)))
+=-=-=
+
+Name: flet13
+
+=-=
+(cl-flet (wrong-syntax-but-should-not-obstruct-indentation
+ (g (arg-of--flet-g)
+ h
+ i)
+ wrong-syntax-but-should-not-obstruct-indentation
+ (g (arg-of--flet-g)
+ h
+ i)))
+=-=-=
+
+Name: flet14
+
+=-=
+(cl-flet (wrong-syntax-but-should-not-obstruct-indentation
+ wrong-syntax-but-should-not-obstruct-indentation
+ (g (arg-of--flet-g)
+ h
+ i)
+ wrong-syntax-but-should-not-obstruct-indentation))
+=-=-=
+
+Name: flet15
+
+=-=
+(cl-flet (wrong-syntax-but-should-not-obstruct-indentation
+ wrong-syntax-but-should-not-obstruct-indentation
+ wrong-syntax-but-should-not-obstruct-indentation
+ (g (arg-of--flet-g)
+ h
+ i)))
+=-=-=
+
+Name: flet16
+
+=-=
+(cl-flet ((f (x)
+ (g x)))
+ (pcase e
+ ((dangerous-expression)
+ (form))))
+=-=-=
+
+Name: flet-indentation-incomplete-sexp-no-side-effects-1
+Code: (lambda () (emacs-lisp-mode) (setq indent-tabs-mode nil) (newline nil t))
+Point-Char: |
+
+=-=
+(let ((x (and y|
+=-=
+(let ((x (and y
+ |
+=-=-=
+
+Name: flet-indentation-incomplete-sexp-no-side-effects-2
+
+=-=
+(let ((x|
+=-=
+(let ((x
+ |
+=-=-=
+
+Name: flet-indentation-incomplete-sexp-missing-whitespace-1
+Point-Char: |
+
+=-=
+(cl-flet((f (x)|
+=-=
+(cl-flet((f (x)
+ |
+=-=-=
+
+Name: flet-indentation-incomplete-sexp-missing-whitespace-2
+Point-Char: |
+
+=-=
+(cl-flet((f(x)|
+=-=
+(cl-flet((f(x)
+ |
+=-=-=
+
+Name: flet-indentation-incomplete-sexp-missing-whitespace-3
+
+=-=
+(cl-flet ((f(x)|
+=-=
+(cl-flet ((f(x)
+ |
+=-=-=
+
+Name: flet-indentation-incomplete-sexp-missing-whitespace-4
+
+=-=
+(cl-flet( (f (x)|
+=-=
+(cl-flet( (f (x)
+ |
+=-=-=
+
+Name: flet-indentation-incomplete-sexp-missing-whitespace-5
+
+=-=
+(cl-flet( (f(x)|
+=-=
+(cl-flet( (f(x)
+ |
+=-=-=
+
+Name: flet-indentation-incomplete-sexp-missing-and-excessive-whitespace-1
+
+=-=
+(cl-flet((f (x)|
+=-=
+(cl-flet((f (x)
+ |
+=-=-=
+
+Name: flet-indentation-incomplete-sexp-missing-and-excessive-whitespace-2
+
+=-=
+(cl-flet ((f(x)|
+=-=
+(cl-flet ((f(x)
+ |
+=-=-=
+
+Name: flet-indentation-incomplete-sexp-missing-and-excessive-whitespace-3
+
+=-=
+(cl-flet( (f (x)|
+=-=
+(cl-flet( (f (x)
+ |
+=-=-=
+
+Name: flet-indentation-incomplete-sexp-missing-and-excessive-whitespace-4
+
+=-=
+(cl-flet( (f (x)|
+=-=
+(cl-flet( (f (x)
+ |
+=-=-=
+
+Name: flet-indentation-incomplete-sexp-missing-and-excessive-whitespace-5
+
+=-=
+(cl-flet( (f (x)|
+=-=
+(cl-flet( (f (x)
+ |
+=-=-=
+
+Name: flet-indentation-incomplete-sexp-missing-and-excessive-whitespace-6
+
+=-=
+(cl-flet( (f(x)|
+=-=
+(cl-flet( (f(x)
+ |
+=-=-=
diff --git a/test/lisp/progmodes/elisp-mode-resources/simple-shorthand-test.el b/test/lisp/progmodes/elisp-mode-resources/simple-shorthand-test.el
new file mode 100644
index 00000000000..9b41fb5426c
--- /dev/null
+++ b/test/lisp/progmodes/elisp-mode-resources/simple-shorthand-test.el
@@ -0,0 +1,40 @@
+;;; simple-shorthand-test.el --- -*- lexical-binding: t; -*-
+
+(defun f-test ()
+ (let ((read-symbol-shorthands '(("foo-" . "bar-"))))
+ (with-temp-buffer
+ (insert "(foo-bar)")
+ (goto-char (point-min))
+ (read (current-buffer)))))
+
+(defun f-test2 ()
+ (let ((read-symbol-shorthands '(("foo-" . "bar-"))))
+ (read-from-string "(foo-bar)")))
+
+
+(defun f-test3 ()
+ (let ((read-symbol-shorthands '(("foo-" . "bar-"))))
+ (intern "foo-bar")))
+
+(defvar f-test-complete-me 42)
+
+(elisp--foo-test3)
+
+(defun #_f-test4--- () 84)
+
+(defmacro f-define-test-5 ())
+
+;; should be font locked with both shorthand
+;; highlighting _and_ macro highlighting.
+(f-define-test-5)
+
+(when nil
+ (f-test3)
+ (f-test2)
+ (f-test)
+ (#_f-test4---))
+
+
+;; Local Variables:
+;; read-symbol-shorthands: (("f-" . "elisp--foo-"))
+;; End:
diff --git a/test/lisp/progmodes/elisp-mode-tests.el b/test/lisp/progmodes/elisp-mode-tests.el
index a6c64edeb7f..e73be0db504 100644
--- a/test/lisp/progmodes/elisp-mode-tests.el
+++ b/test/lisp/progmodes/elisp-mode-tests.el
@@ -1,6 +1,6 @@
;;; elisp-mode-tests.el --- Tests for emacs-lisp-mode -*- lexical-binding: t; -*-
-;; Copyright (C) 2015-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2022 Free Software Foundation, Inc.
;; Author: Dmitry Gutov <dgutov@yandex.ru>
;; Author: Stephen Leake <stephen_leake@member.fsf.org>
@@ -23,8 +23,10 @@
;;; Code:
(require 'ert)
+(require 'ert-x)
(require 'xref)
(eval-when-compile (require 'cl-lib))
+(require 'ert-x)
;;; Completion
@@ -107,7 +109,7 @@
(should (member "backup-inhibited" comps))
(should-not (member "backup-buffer" comps))))))
-(ert-deftest elisp-completes-functions-after-let-bindings ()
+(ert-deftest elisp-completes-functions-after-let-bindings-2 ()
(with-temp-buffer
(emacs-lisp-mode)
(insert "(let ((bar 1) (baz 2)) (ba")
@@ -181,6 +183,16 @@
(call-interactively #'eval-last-sexp)
(should (equal (current-message) "66 (#o102, #x42, ?B)"))))))
+;;; eval-defun
+
+(ert-deftest eval-defun-prints-edebug-when-instrumented ()
+ (skip-unless (not noninteractive))
+ (with-temp-buffer
+ (let ((current-prefix-arg '(4)))
+ (erase-buffer) (insert "(defun foo ())") (message nil)
+ (call-interactively #'eval-defun)
+ (should (equal (current-message) "Edebug: foo")))))
+
;;; eldoc
(defun elisp-mode-tests--face-propertized-string (string)
@@ -194,7 +206,7 @@
(dotimes (i 3)
(should
(equal (elisp-mode-tests--face-propertized-string
- (elisp--highlight-function-argument 'foo "(A B C)" (1+ i) "foo: "))
+ (elisp--highlight-function-argument 'foo "(A B C)" (1+ i)))
(propertize (nth i '("A" "B" "C"))
'face 'eldoc-highlight-function-argument)))))
@@ -206,7 +218,7 @@
(cl-flet ((bold-arg (i)
(elisp-mode-tests--face-propertized-string
(elisp--highlight-function-argument
- 'foo "(PROMPT LST &key A B C)" i "foo: "))))
+ 'foo "(PROMPT LST &key A B C)" i))))
(should-not (bold-arg 0))
(progn (forward-sexp) (forward-char))
(should (equal (bold-arg 1) "PROMPT"))
@@ -226,7 +238,7 @@
(cl-flet ((bold-arg (i)
(elisp-mode-tests--face-propertized-string
(elisp--highlight-function-argument
- 'foo "(X &key A B C)" i "foo: "))))
+ 'foo "(X &key A B C)" i))))
(should-not (bold-arg 0))
;; The `:b' specifies positional arg `X'.
(progn (forward-sexp) (forward-char))
@@ -298,20 +310,41 @@
)))
+;; tmp may be on a different filesystem to the tests, but, ehh.
+(defvar xref--case-insensitive
+ (ert-with-temp-directory dir
+ (with-temp-file (expand-file-name "hElLo" dir) "hello")
+ (file-exists-p (expand-file-name "HELLO" dir)))
+ "Non-nil if file system seems to be case-insensitive.")
+
(defun xref-elisp-test-run (xrefs expected-xrefs)
(should (= (length xrefs) (length expected-xrefs)))
(while xrefs
(let* ((xref (pop xrefs))
(expected (pop expected-xrefs))
(expected-xref (or (when (consp expected) (car expected)) expected))
- (expected-source (when (consp expected) (cdr expected))))
+ (expected-source (when (consp expected) (cdr expected)))
+ (xref-file (xref-elisp-location-file (xref-item-location xref)))
+ (expected-file (xref-elisp-location-file
+ (xref-item-location expected-xref))))
+
+ ;; Make sure file names compare as strings.
+ (when (file-name-absolute-p xref-file)
+ (setf (xref-elisp-location-file (xref-item-location xref))
+ (file-truename (xref-elisp-location-file (xref-item-location xref)))))
+ (when (file-name-absolute-p expected-file)
+ (setf (xref-elisp-location-file (xref-item-location expected-xref))
+ (file-truename (xref-elisp-location-file
+ (xref-item-location expected-xref)))))
;; Downcase the filenames for case-insensitive file systems.
- (setf (xref-elisp-location-file (oref xref location))
- (downcase (xref-elisp-location-file (oref xref location))))
+ (when xref--case-insensitive
+ (setf (xref-elisp-location-file (xref-item-location xref))
+ (downcase (xref-elisp-location-file (xref-item-location xref))))
- (setf (xref-elisp-location-file (oref expected-xref location))
- (downcase (xref-elisp-location-file (oref expected-xref location))))
+ (setf (xref-elisp-location-file (xref-item-location expected-xref))
+ (downcase (xref-elisp-location-file
+ (xref-item-location expected-xref)))))
(should (equal xref expected-xref))
@@ -346,10 +379,10 @@ to (xref-elisp-test-descr-to-target xref)."
;; `load-path' has the correct case, so this causes the expected test
;; values to have the wrong case). This is handled in
;; `xref-elisp-test-run'.
-(defconst emacs-test-dir
- (downcase
- (file-truename (file-name-directory
- (or load-file-name (buffer-file-name))))))
+(defvar emacs-test-dir
+ (funcall (if xref--case-insensitive 'downcase 'identity)
+ (file-truename (file-name-directory
+ (or load-file-name (buffer-file-name))))))
;; alphabetical by test name
@@ -374,23 +407,24 @@ to (xref-elisp-test-descr-to-target xref)."
"(cl-defstruct (xref-elisp-location")
))
+(require 'em-xtra)
+(require 'find-dired)
(xref-elisp-deftest find-defs-defalias-defun-el
- (elisp--xref-find-definitions 'Buffer-menu-sort)
+ (elisp--xref-find-definitions 'eshell/ff)
(list
- (xref-make "(defalias Buffer-menu-sort)"
+ (xref-make "(defalias eshell/ff)"
(xref-make-elisp-location
- 'Buffer-menu-sort 'defalias
- (expand-file-name "../../../lisp/buff-menu.elc" emacs-test-dir)))
- (xref-make "(defun tabulated-list-sort)"
+ 'eshell/ff 'defalias
+ (expand-file-name "../../../lisp/eshell/em-xtra.elc"
+ emacs-test-dir)))
+ (xref-make "(defun find-name-dired)"
(xref-make-elisp-location
- 'tabulated-list-sort nil
- (expand-file-name "../../../lisp/emacs-lisp/tabulated-list.el" emacs-test-dir)))
- ))
+ 'find-name-dired nil
+ (expand-file-name "../../../lisp/find-dired.el"
+ emacs-test-dir)))))
;; FIXME: defconst
-;; FIXME: eieio defclass
-
;; Possible ways of defining the default method implementation for a
;; generic function. We declare these here, so we know we cover all
;; cases, and we don't rely on other code not changing.
@@ -402,7 +436,7 @@ to (xref-elisp-test-descr-to-target xref)."
slot-1)
(cl-defgeneric xref-elisp-generic-no-methods (arg1 arg2)
- "doc string generic no-methods"
+ "Doc string generic no-methods."
;; No default implementation, no methods, but fboundp is true for
;; this symbol; it calls cl-no-applicable-method
)
@@ -413,45 +447,52 @@ to (xref-elisp-test-descr-to-target xref)."
;; ‘this’. It passes in interactive tests, so I haven't been able to
;; track down the problem.
(cl-defmethod xref-elisp-generic-no-default ((this xref-elisp-root-type) arg2)
- "doc string generic no-default xref-elisp-root-type"
- "non-default for no-default")
+ "Doc string generic no-default xref-elisp-root-type."
+ "non-default for no-default"
+ (list this arg2)) ; silence byte-compiler
;; defgeneric after defmethod in file to ensure the fallback search
;; method of just looking for the function name will fail.
(cl-defgeneric xref-elisp-generic-no-default (arg1 arg2)
- "doc string generic no-default generic"
+ "Doc string generic no-default generic."
;; No default implementation; this function calls the cl-generic
;; dispatching code.
)
-(cl-defgeneric xref-elisp-generic-co-located-default (arg1 arg2)
- "doc string generic co-located-default"
- "co-located default")
+(with-no-warnings ; FIXME: Make more specific.
+ (cl-defgeneric xref-elisp-generic-co-located-default (arg1 arg2)
+ "Doc string generic co-located-default."
+ "co-located default"))
-(cl-defmethod xref-elisp-generic-co-located-default ((this xref-elisp-root-type) arg2)
- "doc string generic co-located-default xref-elisp-root-type"
- "non-default for co-located-default")
+(with-no-warnings ; FIXME: Make more specific.
+ (cl-defmethod xref-elisp-generic-co-located-default ((this xref-elisp-root-type) arg2)
+ "Doc string generic co-located-default xref-elisp-root-type."
+ "non-default for co-located-default"))
(cl-defgeneric xref-elisp-generic-separate-default (arg1 arg2)
- "doc string generic separate-default"
+ "Doc string generic separate-default."
;; default implementation provided separately
)
(cl-defmethod xref-elisp-generic-separate-default (arg1 arg2)
- "doc string generic separate-default default"
- "separate default")
+ "Doc string generic separate-default default."
+ "separate default"
+ (list arg1 arg2)) ; silence byte-compiler
(cl-defmethod xref-elisp-generic-separate-default ((this xref-elisp-root-type) arg2)
- "doc string generic separate-default xref-elisp-root-type"
- "non-default for separate-default")
+ "Doc string generic separate-default xref-elisp-root-type."
+ "non-default for separate-default"
+ (list this arg2)) ; silence byte-compiler
(cl-defmethod xref-elisp-generic-implicit-generic (arg1 arg2)
- "doc string generic implicit-generic default"
- "default for implicit generic")
+ "Doc string generic implicit-generic default."
+ "default for implicit generic"
+ (list arg1 arg2)) ; silence byte-compiler
(cl-defmethod xref-elisp-generic-implicit-generic ((this xref-elisp-root-type) arg2)
- "doc string generic implicit-generic xref-elisp-root-type"
- "non-default for implicit generic")
+ "Doc string generic implicit-generic xref-elisp-root-type."
+ "non-default for implicit generic"
+ (list this arg2)) ; silence byte-compiler
(xref-elisp-deftest find-defs-defgeneric-no-methods
@@ -577,47 +618,54 @@ to (xref-elisp-test-descr-to-target xref)."
'xref-location-marker nil '(xref-etags-location))
'cl-defmethod
(expand-file-name "../../../lisp/progmodes/etags.el" emacs-test-dir)))
+ (xref-make "(cl-defmethod xref-location-marker ((l xref-etags-apropos-location)))"
+ (xref-make-elisp-location
+ (cl--generic-load-hist-format
+ 'xref-location-marker nil '(xref-etags-apropos-location))
+ 'cl-defmethod
+ (expand-file-name "../../../lisp/progmodes/etags.el" emacs-test-dir)))
))
(xref-elisp-deftest find-defs-defgeneric-eval
- (elisp--xref-find-definitions (eval '(cl-defgeneric stephe-leake-cl-defgeneric ())))
+ (elisp--xref-find-definitions (eval '(cl-defgeneric stephe-leake-cl-defgeneric ()) t))
nil)
;; Define some mode-local overloadable/overridden functions for xref to find
(require 'mode-local)
+(declare-function xref-elisp-overloadable-no-methods-default "elisp-mode-tests")
+(declare-function xref-elisp-overloadable-no-default-default "elisp-mode-tests")
+
(define-overloadable-function xref-elisp-overloadable-no-methods ()
- "doc string overloadable no-methods")
+ "Doc string overloadable no-methods.")
(define-overloadable-function xref-elisp-overloadable-no-default ()
- "doc string overloadable no-default")
+ "Doc string overloadable no-default.")
-;; FIXME: byte compiler complains about unused lexical arguments
-;; generated by this macro.
(define-mode-local-override xref-elisp-overloadable-no-default c-mode
- (start end &optional nonterminal depth returnonerror)
- "doc string overloadable no-default c-mode."
+ (_start _end &optional _nonterminal _depth _returnonerror)
+ "Doc string overloadable no-default c-mode."
"result overloadable no-default c-mode.")
(define-overloadable-function xref-elisp-overloadable-co-located-default ()
- "doc string overloadable co-located-default"
+ "Doc string overloadable co-located-default."
"result overloadable co-located-default.")
(define-mode-local-override xref-elisp-overloadable-co-located-default c-mode
- (start end &optional nonterminal depth returnonerror)
- "doc string overloadable co-located-default c-mode."
+ (_start _end &optional _nonterminal _depth _returnonerror)
+ "Doc string overloadable co-located-default c-mode."
"result overloadable co-located-default c-mode.")
(define-overloadable-function xref-elisp-overloadable-separate-default ()
- "doc string overloadable separate-default.")
+ "Doc string overloadable separate-default.")
(defun xref-elisp-overloadable-separate-default-default ()
- "doc string overloadable separate-default default"
+ "Doc string overloadable separate-default default."
"result overloadable separate-default.")
(define-mode-local-override xref-elisp-overloadable-separate-default c-mode
- (start end &optional nonterminal depth returnonerror)
- "doc string overloadable separate-default c-mode."
+ (_start _end &optional _nonterminal _depth _returnonerror)
+ "Doc string overloadable separate-default c-mode."
"result overloadable separate-default c-mode.")
(xref-elisp-deftest find-defs-define-overload-no-methods
@@ -681,7 +729,7 @@ to (xref-elisp-test-descr-to-target xref)."
(expand-file-name "../../../lisp/progmodes/xref.el" emacs-test-dir)))))
(xref-elisp-deftest find-defs-defun-eval
- (elisp--xref-find-definitions (eval '(defun stephe-leake-defun ())))
+ (elisp--xref-find-definitions (eval '(defun stephe-leake-defun ()) t))
nil)
(xref-elisp-deftest find-defs-defun-c
@@ -718,15 +766,11 @@ to (xref-elisp-test-descr-to-target xref)."
;; Source for both variable and defun is "(define-minor-mode
;; compilation-minor-mode". There is no way to tell that directly from
;; the symbol, but we can use (memq sym minor-mode-list) to detect
-;; that the symbol is a minor mode. See `elisp--xref-find-definitions'
-;; for more comments.
-;;
-;; IMPROVEME: return defvar instead of defun if source near starting
-;; point indicates the user is searching for a variable, not a
-;; function.
+;; that the symbol is a minor mode. In non-filtering mode we only
+;; return the function.
(require 'compile) ;; not loaded by default at test time
(xref-elisp-deftest find-defs-defun-defvar-el
- (elisp--xref-find-definitions 'compilation-minor-mode)
+ (xref-backend-definitions 'elisp "compilation-minor-mode")
(list
(cons
(xref-make "(defun compilation-minor-mode)"
@@ -736,12 +780,27 @@ to (xref-elisp-test-descr-to-target xref)."
"(define-minor-mode compilation-minor-mode")
))
+;; Returning only defvar because source near point indicates the user
+;; is searching for a variable, not a function.
+(xref-elisp-deftest find-defs-minor-defvar-c
+ (with-temp-buffer
+ (emacs-lisp-mode)
+ (insert "(foo overwrite-mode")
+ (xref-backend-definitions 'elisp
+ (xref-backend-identifier-at-point 'elisp)))
+ (list
+ (cons
+ (xref-make "(defvar overwrite-mode)"
+ (xref-make-elisp-location 'overwrite-mode 'defvar "src/buffer.c"))
+ "DEFVAR_PER_BUFFER (\"overwrite-mode\"")
+ ))
+
(xref-elisp-deftest find-defs-defvar-el
- (elisp--xref-find-definitions 'xref--marker-ring)
+ (elisp--xref-find-definitions 'xref--history)
(list
- (xref-make "(defvar xref--marker-ring)"
+ (xref-make "(defvar xref--history)"
(xref-make-elisp-location
- 'xref--marker-ring 'defvar
+ 'xref--history 'defvar
(expand-file-name "../../../lisp/progmodes/xref.el" emacs-test-dir)))
))
@@ -755,7 +814,7 @@ to (xref-elisp-test-descr-to-target xref)."
"DEFVAR_PER_BUFFER (\"default-directory\"")))
(xref-elisp-deftest find-defs-defvar-eval
- (elisp--xref-find-definitions (eval '(defvar stephe-leake-defvar nil)))
+ (elisp--xref-find-definitions (eval '(defvar stephe-leake-defvar nil) t))
nil)
(xref-elisp-deftest find-defs-face-el
@@ -773,7 +832,7 @@ to (xref-elisp-test-descr-to-target xref)."
))
(xref-elisp-deftest find-defs-face-eval
- (elisp--xref-find-definitions (eval '(defface stephe-leake-defface nil "")))
+ (elisp--xref-find-definitions (eval '(defface stephe-leake-defface nil "") t))
nil)
(xref-elisp-deftest find-defs-feature-el
@@ -788,7 +847,7 @@ to (xref-elisp-test-descr-to-target xref)."
))
(xref-elisp-deftest find-defs-feature-eval
- (elisp--xref-find-definitions (eval '(provide 'stephe-leake-feature)))
+ (elisp--xref-find-definitions (eval '(provide 'stephe-leake-feature) t))
nil)
(ert-deftest elisp--preceding-sexp--char-name ()
@@ -797,5 +856,275 @@ to (xref-elisp-test-descr-to-target xref)."
(insert "?\\N{HEAVY CHECK MARK}")
(should (equal (elisp--preceding-sexp) ?\N{HEAVY CHECK MARK}))))
+(defun test--font (form search)
+ (with-temp-buffer
+ (emacs-lisp-mode)
+ (if (stringp form)
+ (insert form)
+ (pp form (current-buffer)))
+ (with-suppressed-warnings ((interactive-only font-lock-debug-fontify))
+ (font-lock-debug-fontify))
+ (goto-char (point-min))
+ (and (re-search-forward search nil t)
+ (get-text-property (match-beginning 1) 'face))))
+
+(ert-deftest test-elisp-font-keywords-1 ()
+ ;; Special form.
+ (should (eq (test--font '(if foo bar) "(\\(if\\)")
+ 'font-lock-keyword-face))
+ ;; Macro.
+ (should (eq (test--font '(when foo bar) "(\\(when\\)")
+ 'font-lock-keyword-face))
+ (should (eq (test--font '(condition-case nil
+ (foo)
+ (error (if a b)))
+ "(\\(if\\)")
+ 'font-lock-keyword-face))
+ (should (eq (test--font '(condition-case nil
+ (foo)
+ (when (if a b)))
+ "(\\(when\\)")
+ 'nil)))
+
+(ert-deftest test-elisp-font-keywords-2 ()
+ (should (eq (test--font '(condition-case nil
+ (foo)
+ (error (when a b)))
+ "(\\(when\\)")
+ 'font-lock-keyword-face)))
+
+(ert-deftest test-elisp-font-keywords-3 ()
+ (should (eq (test--font '(setq a '(if when zot))
+ "(\\(if\\)")
+ nil)))
+
+(ert-deftest test-elisp-font-keywords-4 ()
+ :expected-result :failed ; FIXME bug#43265
+ (should (eq (test--font '(condition-case nil
+ (foo)
+ ((if foo) (when a b)))
+ "(\\(if\\)")
+ nil)))
+
+(ert-deftest test-elisp-font-keywords-5 ()
+ (should (eq (test--font '(condition-case (when a)
+ (foo)
+ (error t))
+ "(\\(when\\)")
+ nil)))
+
+(defmacro elisp-mode-test--with-buffer (text-with-pos &rest body)
+ "Eval BODY with buffer and variables from TEXT-WITH-POS.
+All occurrences of {NAME} are removed from TEXT-WITH-POS and
+the remaining text put in a buffer in `elisp-mode'.
+Each NAME is then bound to its position in the text during the
+evaluation of BODY."
+ (declare (indent 1))
+ (let* ((annot-text (eval text-with-pos t))
+ (pieces nil)
+ (positions nil)
+ (tlen (length annot-text))
+ (ofs 0)
+ (text-ofs 0))
+ (while
+ (and (< ofs tlen)
+ (let ((m (string-match (rx "{" (group (+ (not "}"))) "}")
+ annot-text ofs)))
+ (and m
+ (let ((var (intern (match-string 1 annot-text))))
+ (push (substring annot-text ofs m) pieces)
+ (setq text-ofs (+ text-ofs (- m ofs)))
+ (push (list var (1+ text-ofs)) positions)
+ (setq ofs (match-end 0))
+ t)))))
+ (push (substring annot-text ofs tlen) pieces)
+ (let ((text (apply #'concat (nreverse pieces)))
+ (bindings (nreverse positions)))
+ `(with-temp-buffer
+ (ert-info (,text :prefix "text: ")
+ (emacs-lisp-mode)
+ (insert ,text)
+ (let ,bindings . ,body))))))
+
+(ert-deftest elisp-mode-with-buffer ()
+ ;; Sanity test of macro, also demonstrating how it works.
+ (elisp-mode-test--with-buffer
+ "{a}123{b}45{c}6"
+ (should (equal a 1))
+ (should (equal b 4))
+ (should (equal c 6))
+ (should (equal (buffer-string) "123456"))))
+
+(ert-deftest elisp-mode-infer-namespace ()
+ (elisp-mode-test--with-buffer
+ (concat " ({p1}alphaX {p2}beta {p3}gamma '{p4}delta\n"
+ " #'{p5}epsilon `{p6}zeta `(,{p7}eta ,@{p8}theta))\n")
+ (should (equal (elisp--xref-infer-namespace p1) 'function))
+ (should (equal (elisp--xref-infer-namespace p2) 'maybe-variable))
+ (should (equal (elisp--xref-infer-namespace p3) 'maybe-variable))
+ (should (equal (elisp--xref-infer-namespace p4) 'any))
+ (should (equal (elisp--xref-infer-namespace p5) 'function))
+ (should (equal (elisp--xref-infer-namespace p6) 'any))
+ (should (equal (elisp--xref-infer-namespace p7) 'variable))
+ (should (equal (elisp--xref-infer-namespace p8) 'variable)))
+
+ (elisp-mode-test--with-buffer
+ (concat "(let ({p1}alpha {p2}beta ({p3}gamma {p4}delta))\n"
+ " ({p5}epsilon {p6}zeta)\n"
+ " {p7}eta)\n")
+ (should (equal (elisp--xref-infer-namespace p1) 'variable))
+ (should (equal (elisp--xref-infer-namespace p2) 'variable))
+ (should (equal (elisp--xref-infer-namespace p3) 'variable))
+ (should (equal (elisp--xref-infer-namespace p4) 'variable))
+ (should (equal (elisp--xref-infer-namespace p5) 'function))
+ (should (equal (elisp--xref-infer-namespace p6) 'maybe-variable))
+ (should (equal (elisp--xref-infer-namespace p7) 'variable)))
+
+ (elisp-mode-test--with-buffer
+ (concat "(let (({p1}alpha {p2}beta)\n"
+ " ({p3}gamma ({p4}delta {p5}epsilon)))\n"
+ " ({p6}zeta))\n")
+ (should (equal (elisp--xref-infer-namespace p1) 'variable))
+ (should (equal (elisp--xref-infer-namespace p2) 'variable))
+ (should (equal (elisp--xref-infer-namespace p3) 'variable))
+ (should (equal (elisp--xref-infer-namespace p4) 'function))
+ (should (equal (elisp--xref-infer-namespace p5) 'maybe-variable))
+ (should (equal (elisp--xref-infer-namespace p6) 'function)))
+
+ (elisp-mode-test--with-buffer
+ (concat "(defun {p1}alpha () {p2}beta)\n"
+ "(defface {p3}gamma ...)\n"
+ "(defvar {p4}delta {p5}epsilon)\n"
+ "(function {p6}zeta)\n")
+ (should (equal (elisp--xref-infer-namespace p1) 'function))
+ (should (equal (elisp--xref-infer-namespace p2) 'variable))
+ (should (equal (elisp--xref-infer-namespace p3) 'face))
+ (should (equal (elisp--xref-infer-namespace p4) 'variable))
+ (should (equal (elisp--xref-infer-namespace p5) 'variable))
+ (should (equal (elisp--xref-infer-namespace p6) 'function)))
+
+ (elisp-mode-test--with-buffer
+ (concat "(require '{p1}alpha)\n"
+ "(fboundp '{p2}beta)\n"
+ "(boundp '{p3}gamma)\n"
+ "(facep '{p4}delta)\n"
+ "(define-key map [f1] '{p5}epsilon)\n")
+ (should (equal (elisp--xref-infer-namespace p1) 'feature))
+ (should (equal (elisp--xref-infer-namespace p2) 'function))
+ (should (equal (elisp--xref-infer-namespace p3) 'variable))
+ (should (equal (elisp--xref-infer-namespace p4) 'face))
+ (should (equal (elisp--xref-infer-namespace p5) 'function)))
+
+ (elisp-mode-test--with-buffer
+ (concat "(list {p1}alpha {p2}beta)\n"
+ "(progn {p3}gamma {p4}delta)\n"
+ "(lambda ({p5}epsilon {p6}zeta) {p7}eta)\n")
+ (should (equal (elisp--xref-infer-namespace p1) 'variable))
+ (should (equal (elisp--xref-infer-namespace p2) 'variable))
+ (should (equal (elisp--xref-infer-namespace p3) 'variable))
+ (should (equal (elisp--xref-infer-namespace p4) 'variable))
+ (should (equal (elisp--xref-infer-namespace p5) 'variable))
+ (should (equal (elisp--xref-infer-namespace p6) 'variable))
+ (should (equal (elisp--xref-infer-namespace p7) 'variable)))
+
+ (elisp-mode-test--with-buffer
+ (concat "'({p1}alpha {p2}beta\n"
+ " ({p3}gamma ({p4}delta)))\n")
+ (should (equal (elisp--xref-infer-namespace p1) 'any))
+ (should (equal (elisp--xref-infer-namespace p2) 'any))
+ (should (equal (elisp--xref-infer-namespace p3) 'any))
+ (should (equal (elisp--xref-infer-namespace p4) 'any))))
+
+
+(ert-deftest elisp-shorthand-read-buffer ()
+ (let* ((gsym (downcase (symbol-name (cl-gensym "sh-"))))
+ (shorthand-sname (format "s-%s" gsym))
+ (expected (intern (format "shorthand-longhand-%s" gsym))))
+ (cl-assert (not (intern-soft shorthand-sname)))
+ (should (equal (let ((read-symbol-shorthands
+ '(("s-" . "shorthand-longhand-"))))
+ (with-temp-buffer
+ (insert shorthand-sname)
+ (goto-char (point-min))
+ (read (current-buffer))))
+ expected))
+ (should (not (intern-soft shorthand-sname)))))
+
+(ert-deftest elisp-shorthand-read-from-string ()
+ (let* ((gsym (downcase (symbol-name (cl-gensym "sh-"))))
+ (shorthand-sname (format "s-%s" gsym))
+ (expected (intern (format "shorthand-longhand-%s" gsym))))
+ (cl-assert (not (intern-soft shorthand-sname)))
+ (should (equal (let ((read-symbol-shorthands
+ '(("s-" . "shorthand-longhand-"))))
+ (car (read-from-string shorthand-sname)))
+ expected))
+ (should (not (intern-soft shorthand-sname)))))
+
+(ert-deftest elisp-shorthand-load-a-file ()
+ (let ((test-file (ert-resource-file "simple-shorthand-test.el")))
+ (mapatoms (lambda (s)
+ (when (string-match "^elisp--foo-" (symbol-name s))
+ (unintern s obarray))))
+ (load test-file)
+ (should (intern-soft "elisp--foo-test"))
+ (should-not (intern-soft "f-test"))))
+
+(ert-deftest elisp-shorthand-byte-compile-a-file ()
+
+ (let ((test-file (ert-resource-file "simple-shorthand-test.el"))
+ (byte-compiled (ert-resource-file "simple-shorthand-test.elc")))
+ (mapatoms (lambda (s)
+ (when (string-match "^elisp--foo-" (symbol-name s))
+ (unintern s obarray))))
+ (byte-compile-file test-file)
+ (should-not (intern-soft "f-test"))
+ (should (intern-soft "elisp--foo-test"))
+ (should-not (fboundp (intern-soft "elisp--foo-test")))
+ (load byte-compiled)
+ (should (intern-soft "elisp--foo-test"))
+ (should-not (intern-soft "f-test"))))
+
+(ert-deftest elisp-shorthand-completion-at-point ()
+ (let ((test-file (ert-resource-file "simple-shorthand-test.el")))
+ (load test-file)
+ (with-current-buffer (find-file-noselect test-file)
+ (revert-buffer t t)
+ (goto-char (point-min))
+ (insert "f-test-compl")
+ (completion-at-point)
+ (goto-char (point-min))
+ (should (search-forward "f-test-complete-me" (pos-eol) t))
+ (goto-char (point-min))
+ (should (string= (symbol-name (read (current-buffer)))
+ "elisp--foo-test-complete-me"))
+ (revert-buffer t t))))
+
+(ert-deftest elisp-shorthand-escape ()
+ (let ((test-file (ert-resource-file "simple-shorthand-test.el")))
+ (load test-file)
+ (should (intern-soft "f-test4---"))
+ (should-not (intern-soft "elisp--foo-test4---"))
+ (should (= 84 (funcall (intern-soft "f-test4---"))))
+ (should (unintern "f-test4---"))))
+
+(ert-deftest elisp-dont-shadow-punctuation-only-symbols ()
+ (let* ((shorthanded-form '(/= 42 (-foo 42)))
+ (expected-longhand-form '(/= 42 (fooey-foo 42)))
+ (observed (let ((read-symbol-shorthands
+ '(("-" . "fooey-"))))
+ (car (read-from-string
+ (with-temp-buffer
+ (print shorthanded-form (current-buffer))
+ (buffer-string)))))))
+ (should (equal observed expected-longhand-form))))
+
+(ert-deftest test-indentation ()
+ (ert-test-erts-file (ert-resource-file "elisp-indents.erts"))
+ (ert-test-erts-file (ert-resource-file "flet.erts")
+ (lambda ()
+ (emacs-lisp-mode)
+ (indent-region (point-min) (point-max)))))
+
(provide 'elisp-mode-tests)
;;; elisp-mode-tests.el ends here
diff --git a/test/lisp/progmodes/etags-tests.el b/test/lisp/progmodes/etags-tests.el
index f8393317611..673c582cc7a 100644
--- a/test/lisp/progmodes/etags-tests.el
+++ b/test/lisp/progmodes/etags-tests.el
@@ -1,6 +1,6 @@
-;;; etags-tests.el --- Test suite for etags.el.
+;;; etags-tests.el --- Test suite for etags.el. -*- lexical-binding:t -*-
-;; Copyright (C) 2016-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2022 Free Software Foundation, Inc.
;; Author: Eli Zaretskii <eliz@gnu.org>
@@ -22,6 +22,7 @@
;;; Code:
(require 'ert)
+(require 'ert-x)
(require 'etags)
(eval-when-compile (require 'cl-lib))
@@ -95,19 +96,19 @@
(ert-deftest etags-buffer-local-tags-table-list ()
"Test that a buffer-local value of `tags-table-list' is used."
- (let ((file (make-temp-file "etag-test-tmpfile")))
- (unwind-protect
- (progn
- (set-buffer (find-file-noselect file))
- (fundamental-mode)
- (setq-local tags-table-list
- (list (expand-file-name "manual/etags/ETAGS.good_3"
- etags-tests--test-dir)))
- (cl-letf ((tag-tables tags-table-list)
- (tags-file-name nil)
- ((symbol-function 'read-file-name)
- (lambda (&rest _)
- (error "We should not prompt the user"))))
- (should (visit-tags-table-buffer))
- (should (equal tags-file-name (car tag-tables)))))
- (delete-file file))))
+ (ert-with-temp-file file
+ :suffix "etag-test-tmpfile"
+ (set-buffer (find-file-noselect file))
+ (fundamental-mode)
+ (setq-local tags-table-list
+ (list (expand-file-name "manual/etags/ETAGS.good_3"
+ etags-tests--test-dir)))
+ (cl-letf ((tag-tables tags-table-list)
+ (tags-file-name nil)
+ ((symbol-function 'read-file-name)
+ (lambda (&rest _)
+ (error "We should not prompt the user"))))
+ (should (visit-tags-table-buffer))
+ (should (equal tags-file-name (car tag-tables))))))
+
+;;; etags-tests.el ends here
diff --git a/test/lisp/progmodes/executable-tests.el b/test/lisp/progmodes/executable-tests.el
new file mode 100644
index 00000000000..6988fef87de
--- /dev/null
+++ b/test/lisp/progmodes/executable-tests.el
@@ -0,0 +1,51 @@
+;;; executable-tests.el --- Tests for executable.el -*- lexical-binding:t -*-
+
+;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'executable)
+
+(ert-deftest executable-tests-set-magic ()
+ (with-temp-buffer
+ (insert "#!/foo/bar")
+ (executable-set-magic "/bin/bash" nil t t)
+ (should (equal (buffer-string) "#!/bin/bash"))))
+
+(ert-deftest executable-tests-set-magic/with-argument ()
+ (with-temp-buffer
+ (insert "#!/foo/bar")
+ (executable-set-magic "/bin/bash" "--norc" t t)
+ (should (equal (buffer-string) "#!/bin/bash --norc"))))
+
+(ert-deftest executable-tests-set-magic/executable-insert-nil ()
+ (let ((executable-insert nil))
+ (with-temp-buffer
+ (insert "#!/foo/bar")
+ (executable-set-magic "/bin/bash" nil t nil)
+ (should (equal (buffer-string) "#!/foo/bar"))))
+ (let ((executable-insert nil))
+ (with-temp-buffer
+ (insert "#!/foo/bar")
+ (executable-set-magic "/bin/bash" nil t t)
+ (should (equal (buffer-string) "#!/bin/bash")))))
+
+;;; executable-tests.el ends here
diff --git a/test/lisp/progmodes/f90-tests.el b/test/lisp/progmodes/f90-tests.el
index 0c03a190ca2..b857a25bf2a 100644
--- a/test/lisp/progmodes/f90-tests.el
+++ b/test/lisp/progmodes/f90-tests.el
@@ -1,8 +1,9 @@
-;;; f90-tests.el --- tests for progmodes/f90.el
+;;; f90-tests.el --- tests for progmodes/f90.el -*- lexical-binding:t -*-
-;; Copyright (C) 2011-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2022 Free Software Foundation, Inc.
;; Author: Glenn Morris <rgm@gnu.org>
+;; Maintainer: emacs-devel@gnu.org
;; This file is part of GNU Emacs.
@@ -21,9 +22,6 @@
;;; Commentary:
-;; This file does not have "test" in the name, because it lives under
-;; a test/ directory, so that would be superfluous.
-
;;; Code:
(require 'ert)
@@ -98,7 +96,7 @@ end subroutine test")
(insert "(/ x /)")
(f90-do-auto-fill)
(beginning-of-line)
- (skip-chars-forward "[ \t]")
+ (skip-chars-forward " \t")
(should (equal "&(/" (buffer-substring (point) (+ 3 (point)))))))
;; TODO bug#5593
@@ -256,21 +254,45 @@ end program prog")
(should (= 5 (current-indentation)))))
(ert-deftest f90-test-bug25039 ()
- "Test for https://debbugs.gnu.org/25039 ."
+ "Test for https://debbugs.gnu.org/25039 and 28786."
(with-temp-buffer
(f90-mode)
(insert "program prog
select type (a)
-class is (c1)
-x = 1
type is (t1)
x = 2
+class is (c1)
+x = 1
+class default
+x=3
end select
end program prog")
(f90-indent-subprogram)
(forward-line -3)
- (should (= 2 (current-indentation))) ; type is
+ (should (= 2 (current-indentation))) ; class default
+ (forward-line -2)
+ (should (= 2 (current-indentation))) ; class is
(forward-line -2)
- (should (= 2 (current-indentation))))) ; class is
+ (should (= 2 (current-indentation))))) ; type is
+
+(ert-deftest f90-test-bug38415 ()
+ "Test for https://debbugs.gnu.org/38415 ."
+ (with-temp-buffer
+ (f90-mode)
+ (setq-local f90-smart-end 'no-blink)
+ (insert "module function foo(x)
+real :: x
+end")
+ (f90-indent-line)
+ (should (equal " function foo"
+ (buffer-substring (point) (pos-eol))))
+ (goto-char (point-max))
+ (insert "\nmodule subroutine bar(x)
+real :: x
+end")
+ (f90-indent-line)
+ (should (equal " subroutine bar"
+ (buffer-substring (point) (pos-eol))))))
+
;;; f90-tests.el ends here
diff --git a/test/lisp/progmodes/flymake-resources/Makefile b/test/lisp/progmodes/flymake-resources/Makefile
index 0f3f39791c8..05399ba388b 100644
--- a/test/lisp/progmodes/flymake-resources/Makefile
+++ b/test/lisp/progmodes/flymake-resources/Makefile
@@ -1,6 +1,6 @@
# Makefile for flymake tests
-CC_OPTS = -Wall
+CC_OPTS = -Wall -Wextra
## Recent gcc (e.g. 4.8.2 on RHEL7) can automatically colorize their output,
## which can confuse flymake. Set GCC_COLORS to disable that.
@@ -8,6 +8,6 @@ CC_OPTS = -Wall
## normally use flymake, so it seems like just avoiding the issue
## in this test is fine. Set flymake-log-level to 3 to investigate.
check-syntax:
- GCC_COLORS= $(CC) $(CC_OPTS) ${CHK_SOURCES}
+ GCC_COLORS= gcc $(CC_OPTS) ${CHK_SOURCES} || true
# eof
diff --git a/test/lisp/progmodes/flymake-resources/another-problematic-file.c b/test/lisp/progmodes/flymake-resources/another-problematic-file.c
new file mode 100644
index 00000000000..03eacdd8011
--- /dev/null
+++ b/test/lisp/progmodes/flymake-resources/another-problematic-file.c
@@ -0,0 +1,5 @@
+#include "some-problems.h"
+
+int frob(char* freb) {
+ return 42;
+}
diff --git a/test/lisp/progmodes/flymake-resources/errors-and-warnings.c b/test/lisp/progmodes/flymake-resources/errors-and-warnings.c
new file mode 100644
index 00000000000..1d38bd6bd27
--- /dev/null
+++ b/test/lisp/progmodes/flymake-resources/errors-and-warnings.c
@@ -0,0 +1,13 @@
+/* Flymake should notice an error on the next line, since
+ that file has at least one warning.*/
+#include "some-problems.h"
+/* But not this one */
+#include "no-problems.h"
+
+int main()
+{
+ char c = 1000; /* a note and a warning */
+ int bla;
+ char c; if (bla == (void*)3); /* an error, and two warnings */
+ return c;
+}
diff --git a/test/lisp/progmodes/flymake-resources/no-problems.h b/test/lisp/progmodes/flymake-resources/no-problems.h
new file mode 100644
index 00000000000..19ddc615b32
--- /dev/null
+++ b/test/lisp/progmodes/flymake-resources/no-problems.h
@@ -0,0 +1 @@
+typedef int no_problems;
diff --git a/test/lisp/progmodes/flymake-resources/some-problems.h b/test/lisp/progmodes/flymake-resources/some-problems.h
new file mode 100644
index 00000000000..86ea2de3b0d
--- /dev/null
+++ b/test/lisp/progmodes/flymake-resources/some-problems.h
@@ -0,0 +1,7 @@
+#include <stdio.h>
+
+strange;
+
+int frob(char);
+
+sint main();
diff --git a/test/lisp/progmodes/flymake-resources/test.pl b/test/lisp/progmodes/flymake-resources/test.pl
index d5abcb47e7f..6f4f1ccef50 100644
--- a/test/lisp/progmodes/flymake-resources/test.pl
+++ b/test/lisp/progmodes/flymake-resources/test.pl
@@ -1,2 +1,4 @@
@arr = [1,2,3,4];
+unknown;
my $b = @arr[1];
+[
diff --git a/test/lisp/progmodes/flymake-resources/test.rb b/test/lisp/progmodes/flymake-resources/test.rb
new file mode 100644
index 00000000000..1419eaf3ad2
--- /dev/null
+++ b/test/lisp/progmodes/flymake-resources/test.rb
@@ -0,0 +1,5 @@
+def bla
+ return 2
+ print "not reached"
+ something
+ oops
diff --git a/test/lisp/progmodes/flymake-tests.el b/test/lisp/progmodes/flymake-tests.el
index b04346fd97c..71b03b21e5c 100644
--- a/test/lisp/progmodes/flymake-tests.el
+++ b/test/lisp/progmodes/flymake-tests.el
@@ -1,6 +1,6 @@
-;;; flymake-tests.el --- Test suite for flymake
+;;; flymake-tests.el --- Test suite for flymake -*- lexical-binding: t -*-
-;; Copyright (C) 2011-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2022 Free Software Foundation, Inc.
;; Author: Eduard Wiebe <usenet@pusto.de>
@@ -23,58 +23,358 @@
;;; Code:
(require 'ert)
+(require 'ert-x)
(require 'flymake)
+(eval-when-compile (require 'subr-x)) ; string-trim
(defvar flymake-tests-data-directory
- (expand-file-name "lisp/progmodes/flymake-resources" (getenv "EMACS_TEST_DIRECTORY"))
+ (expand-file-name "lisp/progmodes/flymake-resources"
+ (or (getenv "EMACS_TEST_DIRECTORY")
+ (expand-file-name "../../.."
+ (or load-file-name
+ buffer-file-name))))
"Directory containing flymake test data.")
-;; Warning predicate
-(defun flymake-tests--current-face (file predicate)
- (let ((buffer (find-file-noselect
- (expand-file-name file flymake-tests-data-directory)))
- (process-environment (cons "LC_ALL=C" process-environment))
- (i 0))
+;;
+;;
+(defun flymake-tests--wait-for-backends ()
+ ;; Weirdness here... https://debbugs.gnu.org/17647#25
+ ;; ... meaning `sleep-for', and even
+ ;; `accept-process-output', won't suffice as ways to get
+ ;; process filters and sentinels to run, though they do work
+ ;; fine in a non-interactive batch session. The only thing
+ ;; that will indeed unblock pending process output is
+ ;; reading an input event, so, as a workaround, use a dummy
+ ;; `read-event' with a very short timeout.
+ (unless noninteractive (read-event "" nil 0.1))
+ (cl-loop repeat 5
+ for notdone = (cl-set-difference (flymake-running-backends)
+ (flymake-reporting-backends))
+ while notdone
+ unless noninteractive do (read-event "" nil 0.1)
+ do (sleep-for (+ 0.5 (or flymake-no-changes-timeout 0)))
+ finally (when notdone (ert-skip
+ (format "Some backends not reporting yet %s"
+ notdone)))))
+
+(cl-defun flymake-tests--call-with-fixture (fn file
+ &key (severity-predicate
+ nil sev-pred-supplied-p))
+ "Call FN after flymake setup in FILE, using `flymake-proc'.
+SEVERITY-PREDICATE is used to setup
+`flymake-proc-diagnostic-type-pred'"
+ (let* ((file (expand-file-name file flymake-tests-data-directory))
+ (visiting (find-buffer-visiting file))
+ (buffer (or visiting (find-file-noselect file)))
+ (process-environment (cons "LC_ALL=C" process-environment))
+ (warning-minimum-log-level :error))
(unwind-protect
(with-current-buffer buffer
- (setq-local flymake-warning-predicate predicate)
- (goto-char (point-min))
- (flymake-mode 1)
- ;; Weirdness here... https://debbugs.gnu.org/17647#25
- (while (and flymake-is-running (< (setq i (1+ i)) 10))
- (sleep-for (+ 0.5 flymake-no-changes-timeout)))
- (flymake-goto-next-error)
- (face-at-point))
- (and buffer (let (kill-buffer-query-functions) (kill-buffer buffer))))))
+ (save-excursion
+ (when sev-pred-supplied-p
+ (setq-local flymake-proc-diagnostic-type-pred severity-predicate))
+ (goto-char (point-min))
+ (let ((flymake-start-on-flymake-mode nil))
+ (unless flymake-mode (flymake-mode 1)))
+ (flymake-start)
+ (flymake-tests--wait-for-backends)
+ (funcall fn)))
+ (and buffer
+ (not visiting)
+ (let (kill-buffer-query-functions) (kill-buffer buffer))))))
+
+(cl-defmacro flymake-tests--with-flymake ((file &rest args)
+ &body body)
+ (declare (indent 1)
+ (debug (sexp &rest form)))
+ `(flymake-tests--call-with-fixture (lambda () ,@body) ,file ,@args))
(ert-deftest warning-predicate-rx-gcc ()
"Test GCC warning via regexp predicate."
(skip-unless (and (executable-find "gcc") (executable-find "make")))
- (should (eq 'flymake-warnline
- (flymake-tests--current-face "test.c" "^[Ww]arning"))))
+ (flymake-tests--with-flymake
+ ("test.c" :severity-predicate "^[Ww]arning")
+ (flymake-goto-next-error)
+ (should (eq 'flymake-warning
+ (face-at-point)))))
(ert-deftest warning-predicate-function-gcc ()
"Test GCC warning via function predicate."
(skip-unless (and (executable-find "gcc") (executable-find "make")))
- (should (eq 'flymake-warnline
- (flymake-tests--current-face "test.c"
- (lambda (msg) (string-match "^[Ww]arning" msg))))))
+ (flymake-tests--with-flymake
+ ("test.c" :severity-predicate
+ (lambda (msg) (string-match "^[Ww]arning" msg)))
+ (flymake-goto-next-error)
+ (should (eq 'flymake-warning
+ (face-at-point)))))
-(ert-deftest warning-predicate-rx-perl ()
- "Test perl warning via regular expression predicate."
+(ert-deftest perl-backend ()
+ "Test the perl backend."
(skip-unless (executable-find "perl"))
- (should (eq 'flymake-warnline
- (flymake-tests--current-face "test.pl" "^Scalar value"))))
+ (flymake-tests--with-flymake ("test.pl")
+ (flymake-goto-next-error)
+ (should (eq 'flymake-warning (face-at-point)))
+ (goto-char (point-max))
+ (flymake-goto-prev-error)
+ (should (eq 'flymake-error (face-at-point)))))
+
+(defvar ruby-mode-hook)
+(ert-deftest ruby-backend ()
+ "Test the ruby backend."
+ (skip-unless (executable-find "ruby"))
+ ;; Some versions of ruby fail if HOME doesn't exist (bug#29187).
+ (ert-with-temp-directory tempdir
+ :suffix "flymake-tests-ruby"
+ (let* ((process-environment (cons (format "HOME=%s" tempdir)
+ process-environment))
+ ;; And see https://debbugs.gnu.org/cgi/bugreport.cgi?bug=19657#20
+ ;; for this particular yuckiness
+ (abbreviated-home-dir nil)
+ (ruby-mode-hook
+ (lambda ()
+ (setq flymake-diagnostic-functions '(ruby-flymake-simple)))))
+ (flymake-tests--with-flymake ("test.rb")
+ (flymake-goto-next-error)
+ (should (eq 'flymake-warning (face-at-point)))
+ (flymake-goto-next-error)
+ (should (eq 'flymake-error (face-at-point)))))))
+
+(ert-deftest different-diagnostic-types ()
+ "Test GCC warning via function predicate."
+ (skip-unless (and (executable-find "gcc")
+ (not (ert-gcc-is-clang-p))
+ (version<=
+ "5" (string-trim
+ (shell-command-to-string "gcc -dumpversion")))
+ (executable-find "make")))
+ (let ((flymake-wrap-around nil))
+ (flymake-tests--with-flymake
+ ("errors-and-warnings.c")
+ (flymake-goto-next-error)
+ (should (eq 'flymake-error (face-at-point)))
+ (flymake-goto-next-error)
+ (should (eq 'flymake-note (face-at-point)))
+ (flymake-goto-next-error)
+ (should (eq 'flymake-warning (face-at-point)))
+ (flymake-goto-next-error)
+ (should (eq 'flymake-error (face-at-point)))
+ (flymake-goto-next-error)
+ (should (eq 'flymake-warning (face-at-point)))
+ (flymake-goto-next-error)
+ (should (eq 'flymake-warning (face-at-point)))
+ (should-error (flymake-goto-next-error nil nil t)))))
+
+(ert-deftest included-c-header-files ()
+ "Test inclusion of .h header files."
+ (skip-unless (and (executable-find "gcc")
+ (not (ert-gcc-is-clang-p))
+ (executable-find "make")))
+ (let ((flymake-wrap-around nil))
+ (flymake-tests--with-flymake
+ ("some-problems.h")
+ (flymake-goto-next-error)
+ (should (eq 'flymake-warning (face-at-point)))
+ (flymake-goto-next-error)
+ (should (eq 'flymake-error (face-at-point)))
+ (should-error (flymake-goto-next-error nil nil t)))
+ (flymake-tests--with-flymake
+ ("no-problems.h")
+ (should-error (flymake-goto-next-error nil nil t)))))
+
+(defmacro flymake-tests--assert-set (set
+ should
+ should-not)
+ (declare (indent 1))
+ `(progn
+ ,@(cl-loop
+ for s in should
+ collect `(should (memq (quote ,s) ,set)))
+ ,@(cl-loop
+ for s in should-not
+ collect `(should-not (memq (quote ,s) ,set)))))
+
+(defun flymake-tests--diagnose-words
+ (report-fn type words)
+ "Helper. Call REPORT-FN with diagnostics for WORDS in buffer."
+ (funcall report-fn
+ (cl-loop
+ for word in words
+ append
+ (save-excursion
+ (goto-char (point-min))
+ (cl-loop while (word-search-forward word nil t)
+ collect (flymake-make-diagnostic
+ (current-buffer)
+ (match-beginning 0)
+ (match-end 0)
+ type
+ (concat word " is wrong")))))))
+
+(ert-deftest dummy-backends ()
+ "Test many different kinds of backends."
+ (with-temp-buffer
+ (cl-letf
+ (((symbol-function 'error-backend)
+ (lambda (report-fn)
+ (run-with-timer
+ 0.5 nil
+ #'flymake-tests--diagnose-words report-fn :error '("manha" "prognata"))))
+ ((symbol-function 'warning-backend)
+ (lambda (report-fn)
+ (run-with-timer
+ 0.5 nil
+ #'flymake-tests--diagnose-words report-fn :warning '("ut" "dolor"))))
+ ((symbol-function 'sync-backend)
+ (lambda (report-fn)
+ (flymake-tests--diagnose-words report-fn :note '("quis" "commodo"))))
+ ((symbol-function 'panicking-backend)
+ (lambda (report-fn)
+ (run-with-timer
+ 0.5 nil
+ report-fn :panic :explanation "The spanish inquisition!")))
+ ((symbol-function 'crashing-backend)
+ (lambda (_report-fn)
+ ;; HACK: Shoosh log during tests
+ (setq-local warning-minimum-log-level :emergency)
+ (error "Crashed"))))
+ (insert "Lorem ipsum dolor sit amet, consectetur adipiscing
+ elit, sed do eiusmod tempor incididunt ut labore et dolore
+ manha aliqua. Ut enim ad minim veniam, quis nostrud
+ exercitation ullamco laboris nisi ut aliquip ex ea commodo
+ consequat. Duis aute irure dolor in reprehenderit in
+ voluptate velit esse cillum dolore eu fugiat nulla
+ pariatur. Excepteur sint occaecat cupidatat non prognata
+ sunt in culpa qui officia deserunt mollit anim id est
+ laborum.")
+ (let ((flymake-diagnostic-functions
+ (list 'error-backend 'warning-backend 'sync-backend
+ 'panicking-backend
+ 'crashing-backend
+ ))
+ (flymake-wrap-around nil))
+ (let ((flymake-start-on-flymake-mode nil))
+ (flymake-mode))
+ (flymake-start)
+
+ (flymake-tests--assert-set (flymake-running-backends)
+ (error-backend warning-backend panicking-backend)
+ (crashing-backend))
+
+ (flymake-tests--assert-set (flymake-disabled-backends)
+ (crashing-backend)
+ (error-backend warning-backend sync-backend
+ panicking-backend))
+
+ (flymake-tests--wait-for-backends)
+
+ (flymake-tests--assert-set (flymake-disabled-backends)
+ (crashing-backend panicking-backend)
+ (error-backend warning-backend sync-backend))
+
+ (goto-char (point-min))
+ (flymake-goto-next-error)
+ (should (eq 'flymake-warning (face-at-point))) ; dolor
+ (flymake-goto-next-error)
+ (should (eq 'flymake-warning (face-at-point))) ; ut
+ (flymake-goto-next-error)
+ (should (eq 'flymake-error (face-at-point))) ; manha
+ (flymake-goto-next-error)
+ (should (eq 'flymake-warning (face-at-point))) ; Ut
+ (flymake-goto-next-error)
+ (should (eq 'flymake-note (face-at-point))) ; quis
+ (flymake-goto-next-error)
+ (should (eq 'flymake-warning (face-at-point))) ; ut
+ (flymake-goto-next-error)
+ (should (eq 'flymake-note (face-at-point))) ; commodo
+ (flymake-goto-next-error)
+ (should (eq 'flymake-warning (face-at-point))) ; dolor
+ (flymake-goto-next-error)
+ (should (eq 'flymake-error (face-at-point))) ; prognata
+ (should-error (flymake-goto-next-error nil nil t))))))
+
+(ert-deftest recurrent-backend ()
+ "Test a backend that calls REPORT-FN multiple times."
+ (with-temp-buffer
+ (let (tick)
+ (cl-letf
+ (((symbol-function 'eager-backend)
+ (lambda (report-fn)
+ (funcall report-fn nil :explanation "very eager but no diagnostics")
+ (display-buffer (current-buffer))
+ (run-with-timer
+ 0.5 nil
+ (lambda ()
+ (flymake-tests--diagnose-words report-fn :warning '("consectetur"))
+ (setq tick t)
+ (run-with-timer
+ 0.5 nil
+ (lambda ()
+ (flymake-tests--diagnose-words report-fn :error '("fugiat"))
+ (setq tick t))))))))
+ (insert "Lorem ipsum dolor sit amet, consectetur adipiscing
+ elit, sed do eiusmod tempor incididunt ut labore et dolore
+ manha aliqua. Ut enim ad minim veniam, quis nostrud
+ exercitation ullamco laboris nisi ut aliquip ex ea commodo
+ consequat. Duis aute irure dolor in reprehenderit in
+ voluptate velit esse cillum dolore eu fugiat nulla
+ pariatur. Excepteur sint occaecat cupidatat non prognata
+ sunt in culpa qui officia deserunt mollit anim id est
+ laborum.")
+ (let ((flymake-diagnostic-functions
+ (list 'eager-backend))
+ (flymake-wrap-around nil))
+ (let ((flymake-start-on-flymake-mode nil))
+ (flymake-mode))
+ (flymake-start)
+ (flymake-tests--assert-set (flymake-running-backends)
+ (eager-backend) ())
+ (cl-loop until tick repeat 4 do (sleep-for 0.2))
+ (setq tick nil)
+ (goto-char (point-max))
+ (flymake-goto-prev-error)
+ (should (eq 'flymake-warning (face-at-point))) ; consectetur
+ (should-error (flymake-goto-prev-error nil nil t))
+ (cl-loop until tick repeat 4 do (sleep-for 0.2))
+ (flymake-goto-next-error)
+ (should (eq 'flymake-error (face-at-point))) ; fugiat
+ (flymake-goto-prev-error)
+ (should (eq 'flymake-warning (face-at-point))) ; back at consectetur
+ (should-error (flymake-goto-prev-error nil nil t))
+ )))))
+
+(ert-deftest eob-region-and-trailing-newline ()
+ "`flymake-diag-region' at eob with varying trailing newlines."
+ (cl-flet ((diag-region-substring
+ (line col)
+ (pcase-let
+ ((`(,a . ,b) (flymake-diag-region (current-buffer) line col)))
+ (buffer-substring a b))))
+ (with-temp-buffer
+ (insert "beg\nmmm\nend")
+ (should (equal
+ (diag-region-substring 3 3)
+ "d"))
+ (should (equal
+ (diag-region-substring 3 nil)
+ "end"))
+ (insert "\n")
+ (should (equal
+ (diag-region-substring 4 1)
+ "end"))
+ (should (equal
+ (diag-region-substring 4 nil)
+ "end"))
+ (insert "\n")
+ (should (equal
+ (diag-region-substring 5 1)
+ "\n"))
+ (should (equal
+ (diag-region-substring 5 nil)
+ "\n")))))
+
-(ert-deftest warning-predicate-function-perl ()
- "Test perl warning via function predicate."
- (skip-unless (executable-find "perl"))
- (should (eq 'flymake-warnline
- (flymake-tests--current-face
- "test.pl"
- (lambda (msg) (string-match "^Scalar value" msg))))))
(provide 'flymake-tests)
-;;; flymake.el ends here
+;;; flymake-tests.el ends here
diff --git a/test/lisp/progmodes/gdb-mi-tests.el b/test/lisp/progmodes/gdb-mi-tests.el
new file mode 100644
index 00000000000..b91eab77057
--- /dev/null
+++ b/test/lisp/progmodes/gdb-mi-tests.el
@@ -0,0 +1,50 @@
+;;; gdb-mi-tests.el --- tests for gdb-mi.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'gdb-mi)
+
+(ert-deftest gdb-mi-parse-value ()
+ ;; Test the GDB/MI result/value parser.
+ (should (equal
+ (gdb-mi--from-string
+ "alpha=\"ab\\ncd\",beta=[\"x\",{gamma=\"y\",delta=[]}]")
+ '((alpha . "ab\ncd")
+ (beta . ("x" ((gamma . "y") (delta . ())))))))
+ (should (equal
+ (gdb-mi--from-string
+ "alpha=\"ab\\ncd\",beta=[\"x\",{gamma=\"y\",delta=[]}]"
+ 'gamma)
+ '((alpha . "ab\ncd")
+ (beta . ("x" ("y" (delta . ())))))))
+
+ (let ((gdb-mi-decode-strings nil))
+ (let ((ref `((alpha . ,(string-to-multibyte "a\303\245b")))))
+ (should (equal (gdb-mi--from-string "alpha=\"a\\303\\245b\"")
+ ref))))
+ (let ((gdb-mi-decode-strings 'utf-8))
+ (should (equal (gdb-mi--from-string "alpha=\"a\\303\\245b\"")
+ '((alpha . "aåb")))))
+ )
+
+(provide 'gdb-mi-tests)
+
+;;; gdb-mi-tests.el ends here
diff --git a/test/lisp/progmodes/glasses-tests.el b/test/lisp/progmodes/glasses-tests.el
new file mode 100644
index 00000000000..915fb60d3c8
--- /dev/null
+++ b/test/lisp/progmodes/glasses-tests.el
@@ -0,0 +1,101 @@
+;;; glasses-tests.el --- Tests for glasses.el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+;; Author: Simen Heggestøyl <simenheg@gmail.com>
+;; Keywords:
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;
+
+;;; Code:
+
+(require 'ert)
+(require 'glasses)
+(require 'seq)
+
+(ert-deftest glasses-tests-parenthesis-exception-p ()
+ (with-temp-buffer
+ (insert "public OnClickListener menuListener() {}")
+ (let ((glasses-separate-parentheses-exceptions '("^Listen")))
+ (should-not (glasses-parenthesis-exception-p 1 (point-max)))
+ (should (glasses-parenthesis-exception-p 15 (point-max)))
+ (should-not (glasses-parenthesis-exception-p 24 (point-max)))
+ (should (glasses-parenthesis-exception-p 28 (point-max))))))
+
+(ert-deftest glasses-tests-overlay-p ()
+ (should
+ (glasses-overlay-p (glasses-make-overlay (point-min) (point-max))))
+ (should-not
+ (glasses-overlay-p (make-overlay (point-min) (point-max)))))
+
+(ert-deftest glasses-tests-make-overlay-p ()
+ (let ((o (glasses-make-overlay (point-min) (point-max))))
+ (should (eq (overlay-get o 'category) 'glasses)))
+ (let ((o (glasses-make-overlay (point-min) (point-max) 'foo)))
+ (should (eq (overlay-get o 'category) 'foo))))
+
+(ert-deftest glasses-tests-make-readable ()
+ (with-temp-buffer
+ (insert "pp.setBackgroundResource(R.drawable.button_right);")
+ (glasses-make-readable (point-min) (point-max))
+ (pcase-let ((`(,o1 ,o2 ,o3)
+ (sort (overlays-in (point-min) (point-max))
+ (lambda (o1 o2)
+ (< (overlay-start o1) (overlay-start o2))))))
+ (should (= (overlay-start o1) 7))
+ (should (equal (overlay-get o1 'before-string)
+ glasses-separator))
+ (should (= (overlay-start o2) 17))
+ (should (equal (overlay-get o2 'before-string)
+ glasses-separator))
+ (should (= (overlay-start o3) 25))
+ (should (equal (overlay-get o3 'before-string) " ")))))
+
+(ert-deftest glasses-tests-make-readable-dont-separate-parentheses ()
+ (with-temp-buffer
+ (insert "pp.setBackgroundResource(R.drawable.button_right);")
+ (let ((glasses-separate-parentheses-p nil))
+ (glasses-make-readable (point-min) (point-max))
+ (should-not (overlays-at 25)))))
+
+(ert-deftest glasses-tests-make-unreadable ()
+ (with-temp-buffer
+ (insert "pp.setBackgroundResource(R.drawable.button_right);")
+ (glasses-make-readable (point-min) (point-max))
+ (should (seq-some #'glasses-overlay-p
+ (overlays-in (point-min) (point-max))))
+ (glasses-make-unreadable (point-min) (point-max))
+ (should-not (seq-some #'glasses-overlay-p
+ (overlays-in (point-min) (point-max))))))
+
+(ert-deftest glasses-tests-convert-to-unreadable ()
+ (with-temp-buffer
+ (insert "set_Background_Resource(R.button_right);")
+ (let ((glasses-convert-on-write-p nil))
+ (should-not (glasses-convert-to-unreadable))
+ (should (equal (buffer-string)
+ "set_Background_Resource(R.button_right);")))
+ (let ((glasses-convert-on-write-p t))
+ (should-not (glasses-convert-to-unreadable))
+ (should (equal (buffer-string)
+ "setBackgroundResource(R.button_right);")))))
+
+(provide 'glasses-tests)
+;;; glasses-tests.el ends here
diff --git a/test/lisp/progmodes/grep-tests.el b/test/lisp/progmodes/grep-tests.el
new file mode 100644
index 00000000000..101052c5adc
--- /dev/null
+++ b/test/lisp/progmodes/grep-tests.el
@@ -0,0 +1,69 @@
+;;; grep-tests.el --- Test suite for grep.el -*- lexical-binding:t -*-
+
+;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'grep)
+
+(defconst grep-tests--ellipsis (if (char-displayable-p ?…) "[…]" "[...]")
+ "The form that the ellipsis takes in `grep-find-abbreviate-properties'.")
+
+(defun grep-tests--get-rgrep-abbreviation ()
+ "Get the `display' property of the excessive part of the rgrep command."
+ (with-temp-buffer
+ (grep-compute-defaults)
+ (insert (rgrep-default-command "search" "*" nil))
+ (grep-mode)
+ (font-lock-mode)
+ (font-lock-ensure)
+ (goto-char (point-min))
+ (re-search-forward "find ")
+ (get-text-property (point) 'display)))
+
+(defun grep-tests--check-rgrep-abbreviation ()
+ "Check that the excessive part of the rgrep command is abbreviated iff
+`grep-find-abbreviate' is non-nil."
+ (let ((grep-find-abbreviate t))
+ (should (equal (grep-tests--get-rgrep-abbreviation)
+ grep-tests--ellipsis)))
+ (let ((grep-find-abbreviate nil))
+ (should-not (grep-tests--get-rgrep-abbreviation))))
+
+(ert-deftest grep-tests--rgrep-abbreviate-properties-gnu-linux ()
+ (let ((system-type 'gnu/linux))
+ (grep-tests--check-rgrep-abbreviation)))
+
+(ert-deftest grep-tests--rgrep-abbreviate-properties-darwin ()
+ (let ((system-type 'darwin))
+ (grep-tests--check-rgrep-abbreviation)))
+
+(ert-deftest grep-tests--rgrep-abbreviate-properties-windows-nt-dos-semantics ()
+ (let ((system-type 'windows-nt))
+ (cl-letf (((symbol-function 'w32-shell-dos-semantics) #'always))
+ (grep-tests--check-rgrep-abbreviation))))
+
+(ert-deftest grep-tests--rgrep-abbreviate-properties-windows-nt-sh-semantics ()
+ (let ((system-type 'windows-nt))
+ (cl-letf (((symbol-function 'w32-shell-dos-semantics) #'ignore))
+ (grep-tests--check-rgrep-abbreviation))))
+
+;;; grep-tests.el ends here
diff --git a/test/lisp/progmodes/hideshow-tests.el b/test/lisp/progmodes/hideshow-tests.el
new file mode 100644
index 00000000000..22d73fb3c46
--- /dev/null
+++ b/test/lisp/progmodes/hideshow-tests.el
@@ -0,0 +1,374 @@
+;;; hideshow-tests.el --- Test suite for hideshow.el -*- lexical-binding:t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'ert-x)
+(require 'hideshow)
+
+;; Dependencies for testing:
+(require 'cc-mode)
+
+
+(defmacro hideshow-tests-with-temp-buffer (mode contents &rest body)
+ "Create a `hs-minor-mode' enabled MODE temp buffer with CONTENTS.
+BODY is code to be executed within the temp buffer. Point is
+always located at the beginning of buffer."
+ (declare (indent 1) (debug t))
+ `(with-temp-buffer
+ (,mode)
+ (hs-minor-mode 1)
+ (insert ,contents)
+ (goto-char (point-min))
+ ,@body))
+
+(defmacro hideshow-tests-with-temp-buffer-selected (mode contents &rest body)
+ "Create and switch to a `hs-minor-mode' enabled MODE temp buffer with CONTENTS.
+BODY is code to be executed within the temp buffer. Point is
+always located at the beginning of buffer."
+ (declare (indent 1) (debug t))
+ `(ert-with-test-buffer-selected ()
+ (,mode)
+ (hs-minor-mode 1)
+ (insert ,contents)
+ (goto-char (point-min))
+ ,@body))
+
+(defun hideshow-tests-look-at (string &optional num restore-point)
+ "Move point at beginning of STRING in the current buffer.
+Optional argument NUM defaults to 1 and is an integer indicating
+how many occurrences must be found, when positive the search is
+done forwards, otherwise backwards. When RESTORE-POINT is
+non-nil the point is not moved but the position found is still
+returned. When searching forward and point is already looking at
+STRING, it is skipped so the next STRING occurrence is selected."
+ (let* ((num (or num 1))
+ (starting-point (point))
+ (string (regexp-quote string))
+ (search-fn (if (> num 0) #'re-search-forward #'re-search-backward))
+ (deinc-fn (if (> num 0) #'1- #'1+))
+ (found-point))
+ (prog2
+ (catch 'exit
+ (while (not (= num 0))
+ (when (and (> num 0)
+ (looking-at string))
+ ;; Moving forward and already looking at STRING, skip it.
+ (forward-char (length (match-string-no-properties 0))))
+ (and (not (funcall search-fn string nil t))
+ (throw 'exit t))
+ (when (> num 0)
+ ;; `re-search-forward' leaves point at the end of the
+ ;; occurrence, move back so point is at the beginning
+ ;; instead.
+ (forward-char (- (length (match-string-no-properties 0)))))
+ (setq
+ num (funcall deinc-fn num)
+ found-point (point))))
+ found-point
+ (and restore-point (goto-char starting-point)))))
+
+(defun hideshow-tests-visible-string (&optional min max)
+ "Return the buffer string excluding invisible overlays.
+Argument MIN and MAX delimit the region to be returned and
+default to `point-min' and `point-max' respectively."
+ (let* ((min (or min (point-min)))
+ (max (or max (point-max)))
+ (buffer-contents (buffer-substring-no-properties min max))
+ (overlays
+ (sort (overlays-in min max)
+ (lambda (a b)
+ (let ((overlay-end-a (overlay-end a))
+ (overlay-end-b (overlay-end b)))
+ (> overlay-end-a overlay-end-b))))))
+ (with-temp-buffer
+ (insert buffer-contents)
+ (dolist (overlay overlays)
+ (if (overlay-get overlay 'invisible)
+ (delete-region (overlay-start overlay)
+ (overlay-end overlay))))
+ (buffer-substring-no-properties (point-min) (point-max)))))
+
+(defun hideshow-tests-make-event-at (string)
+ "Make dummy mouse event at beginning of STRING."
+ (save-excursion
+ (let ((pos (hideshow-tests-look-at string)))
+ (vector
+ `(S-mouse-2
+ (,(get-buffer-window) ,pos (1 . 1) 0 nil ,pos (1 . 1)
+ nil (1 . 1) (1 . 1)))))))
+
+(ert-deftest hideshow-already-hidden-p-1 ()
+ (let ((contents "
+int
+main()
+{
+ printf(\"Hello\\n\");
+}
+"))
+ (hideshow-tests-with-temp-buffer
+ c-mode
+ contents
+ (hideshow-tests-look-at "printf")
+ (should (not (hs-already-hidden-p)))
+ (hs-hide-block)
+ (goto-char (point-min))
+ (hideshow-tests-look-at "{")
+ (should (hs-already-hidden-p))
+ (forward-line -1)
+ (should (not (hs-already-hidden-p)))
+ (hideshow-tests-look-at "}")
+ (should (hs-already-hidden-p))
+ (forward-line)
+ (should (not (hs-already-hidden-p))))))
+
+(ert-deftest hideshow-hide-block-1 ()
+ "Should hide current block."
+ (let ((contents "
+int
+main()
+{
+ printf(\"Hello\\n\");
+}
+"))
+ (hideshow-tests-with-temp-buffer
+ c-mode
+ contents
+ (hideshow-tests-look-at "printf")
+ (hs-hide-block)
+ (should (string=
+ (hideshow-tests-visible-string)
+ "
+int
+main()
+{}
+"))
+ (hs-show-block)
+ (should (string= (hideshow-tests-visible-string) contents)))))
+
+(ert-deftest hideshow-hide-all-1 ()
+ "Should hide all blocks and comments."
+ (let ((contents "
+/*
+ Comments
+*/
+
+int
+main()
+{
+ sub();
+}
+
+void
+sub()
+{
+ printf(\"Hello\\n\");
+}
+"))
+ (hideshow-tests-with-temp-buffer
+ c-mode
+ contents
+ (hs-hide-all)
+ (should (string=
+ (hideshow-tests-visible-string)
+ "
+/*
+
+int
+main()
+{}
+
+void
+sub()
+{}
+"))
+ (hs-show-all)
+ (should (string= (hideshow-tests-visible-string) contents)))))
+
+(ert-deftest hideshow-hide-all-2 ()
+ "Should not hide comments when `hs-hide-comments-when-hiding-all' is nil."
+ (let ((contents "
+/*
+ Comments
+*/
+
+int
+main()
+{
+ sub();
+}
+
+void
+sub()
+{
+ printf(\"Hello\\n\");
+}
+"))
+ (hideshow-tests-with-temp-buffer
+ c-mode
+ contents
+ (let ((hs-hide-comments-when-hiding-all nil))
+ (hs-hide-all))
+ (should (string=
+ (hideshow-tests-visible-string)
+ "
+/*
+ Comments
+*/
+
+int
+main()
+{}
+
+void
+sub()
+{}
+"))
+ (hs-show-all)
+ (should (string= (hideshow-tests-visible-string) contents)))))
+
+(ert-deftest hideshow-hide-level-1 ()
+ "Should hide 1st level blocks."
+ (hideshow-tests-with-temp-buffer
+ c-mode
+ "
+/*
+ Comments
+*/
+
+int
+main(int argc, char **argv)
+{
+ if (argc > 1) {
+ printf(\"Hello\\n\");
+ }
+}
+"
+ (hs-hide-level 1)
+ (should (string=
+ (hideshow-tests-visible-string)
+ "
+/*
+ Comments
+*/
+
+int
+main(int argc, char **argv)
+{}
+"))))
+
+(ert-deftest hideshow-hide-level-2 ()
+ "Should hide 2nd level blocks."
+ (hideshow-tests-with-temp-buffer
+ c-mode
+ "
+/*
+ Comments
+*/
+
+int
+main(int argc, char **argv)
+{
+ if (argc > 1) {
+ printf(\"Hello\\n\");
+ }
+}
+"
+ (hs-hide-level 2)
+ (should (string=
+ (hideshow-tests-visible-string)
+ "
+/*
+ Comments
+*/
+
+int
+main(int argc, char **argv)
+{
+ if (argc > 1) {}
+}
+"))))
+
+(ert-deftest hideshow-toggle-hiding-1 ()
+ "Should toggle hiding/showing of a block."
+ (let ((contents "
+int
+main()
+{
+ printf(\"Hello\\n\");
+}
+"))
+ (hideshow-tests-with-temp-buffer
+ c-mode
+ contents
+ (hideshow-tests-look-at "printf")
+ (hs-toggle-hiding)
+ (should (string=
+ (hideshow-tests-visible-string)
+ "
+int
+main()
+{}
+"))
+ (hs-toggle-hiding)
+ (should (string= (hideshow-tests-visible-string) contents)))))
+
+(ert-deftest hideshow-mouse-toggle-hiding-1 ()
+ "Should toggle hiding/showing of a block by mouse events."
+ (let ((contents "
+int
+main()
+{
+ printf(\"Hello\\n\");
+}
+")
+ (hidden "
+int
+main()
+{}
+")
+ (call-at (lambda (str)
+ (let* ((events (hideshow-tests-make-event-at str))
+ (last-nonmenu-event (aref events 0)))
+ (call-interactively #'hs-toggle-hiding nil events)))))
+ (hideshow-tests-with-temp-buffer-selected
+ c-mode
+ contents
+ ;; Should not hide the block when clicked outside of the block.
+ (funcall call-at "int")
+ (should (string= (hideshow-tests-visible-string) contents))
+ ;; Should hide the block when clicked inside of the block.
+ (goto-char (point-min))
+ (funcall call-at "printf")
+ (should (string= (hideshow-tests-visible-string) hidden))
+ ;; Should not show the block when clicked outside of the block.
+ (goto-char (point-min))
+ (funcall call-at "int")
+ (should (string= (hideshow-tests-visible-string) hidden))
+ ;; Should show the block when clicked inside of the block.
+ (goto-char (point-min))
+ (funcall call-at "}")
+ (should (string= (hideshow-tests-visible-string) contents)))))
+
+(provide 'hideshow-tests)
+
+;;; hideshow-tests.el ends here
diff --git a/test/manual/indent/js-chain.js b/test/lisp/progmodes/js-resources/js-chain.js
index 2a290294026..2a290294026 100644
--- a/test/manual/indent/js-chain.js
+++ b/test/lisp/progmodes/js-resources/js-chain.js
diff --git a/test/manual/indent/js-indent-align-list-continuation-nil.js b/test/lisp/progmodes/js-resources/js-indent-align-list-continuation-nil.js
index 383b2539a26..383b2539a26 100644
--- a/test/manual/indent/js-indent-align-list-continuation-nil.js
+++ b/test/lisp/progmodes/js-resources/js-indent-align-list-continuation-nil.js
diff --git a/test/manual/indent/js-indent-init-dynamic.js b/test/lisp/progmodes/js-resources/js-indent-init-dynamic.js
index 536a976e86e..536a976e86e 100644
--- a/test/manual/indent/js-indent-init-dynamic.js
+++ b/test/lisp/progmodes/js-resources/js-indent-init-dynamic.js
diff --git a/test/manual/indent/js-indent-init-t.js b/test/lisp/progmodes/js-resources/js-indent-init-t.js
index bb755420ba7..bb755420ba7 100644
--- a/test/manual/indent/js-indent-init-t.js
+++ b/test/lisp/progmodes/js-resources/js-indent-init-t.js
diff --git a/test/manual/indent/js.js b/test/lisp/progmodes/js-resources/js.js
index 1ad76a83e18..9658c95701c 100644
--- a/test/manual/indent/js.js
+++ b/test/lisp/progmodes/js-resources/js.js
@@ -7,6 +7,9 @@ let c = 1,
var e = 100500,
+ 1;
+// Don't misinterpret "const"
+/const/
+
function test ()
{
return /[/]/.test ('/') // (bug#19397)
@@ -135,6 +138,33 @@ if (1) {
: 4
}
+// Regexp is not a continuation
+bar(
+ "string arg1",
+ /abc/
+)
+
+// No infloop inside js--re-search-backward-inner
+let b = {
+ a : `
+ //1
+ `
+}
+
+// bug#25904
+foo.bar.baz(very => // A comment
+ very
+).biz(([baz={a: [123]}, boz]) =>
+ baz
+).snarf((snorf) => /* Another comment */
+ snorf
+);
+
+// Continuation of bug#25904; support broken arrow as N+1th arg
+map(arr, (val) =>
+ val
+)
+
// Local Variables:
// indent-tabs-mode: nil
// js-indent-level: 2
diff --git a/test/lisp/progmodes/js-resources/jsx-align-gt-with-lt.jsx b/test/lisp/progmodes/js-resources/jsx-align-gt-with-lt.jsx
new file mode 100644
index 00000000000..8eb1d6d718c
--- /dev/null
+++ b/test/lisp/progmodes/js-resources/jsx-align-gt-with-lt.jsx
@@ -0,0 +1,12 @@
+<element
+ attr=""
+ >
+</element>
+<input
+ />
+
+// Local Variables:
+// indent-tabs-mode: nil
+// js-indent-level: 2
+// js-jsx-align->-with-<: nil
+// End:
diff --git a/test/lisp/progmodes/js-resources/jsx-comment-string.jsx b/test/lisp/progmodes/js-resources/jsx-comment-string.jsx
new file mode 100644
index 00000000000..cae023e7288
--- /dev/null
+++ b/test/lisp/progmodes/js-resources/jsx-comment-string.jsx
@@ -0,0 +1,23 @@
+// Local Variables:
+// indent-tabs-mode: nil
+// js-indent-level: 2
+// End:
+
+// The following tests go below any comments to avoid including
+// misindented comments among the erroring lines.
+
+// The JSX-like text in comments/strings should be treated like the enclosing
+// syntax, not like JSX.
+
+// <Foo>
+void 0
+
+"<Bar>"
+void 0
+
+<Chicken>
+ {/* <Pork> */}
+ <Beef attr="<Turkey>">
+ Yum!
+ </Beef>
+</Chicken>
diff --git a/test/lisp/progmodes/js-resources/jsx-indent-level.jsx b/test/lisp/progmodes/js-resources/jsx-indent-level.jsx
new file mode 100644
index 00000000000..0a84b9eb77a
--- /dev/null
+++ b/test/lisp/progmodes/js-resources/jsx-indent-level.jsx
@@ -0,0 +1,13 @@
+return (
+ <element>
+ <element>
+ Hello World!
+ </element>
+ </element>
+)
+
+// Local Variables:
+// indent-tabs-mode: nil
+// js-indent-level: 4
+// js-jsx-indent-level: 2
+// End:
diff --git a/test/lisp/progmodes/js-resources/jsx-quote.jsx b/test/lisp/progmodes/js-resources/jsx-quote.jsx
new file mode 100644
index 00000000000..1b2c6528734
--- /dev/null
+++ b/test/lisp/progmodes/js-resources/jsx-quote.jsx
@@ -0,0 +1,16 @@
+// JSX text node values should be strings, but only JS string syntax
+// is considered, so quote marks delimit strings like normal, with
+// disastrous results (https://github.com/mooz/js2-mode/issues/409).
+function Bug() {
+ return <div>C'est Montréal</div>;
+}
+function Test(foo = /'/,
+ bar = 123) {}
+
+// This test is in a separate file because it can break other tests
+// when indenting the whole buffer (not sure why).
+
+// Local Variables:
+// indent-tabs-mode: nil
+// js-indent-level: 2
+// End:
diff --git a/test/lisp/progmodes/js-resources/jsx-self-closing.jsx b/test/lisp/progmodes/js-resources/jsx-self-closing.jsx
new file mode 100644
index 00000000000..f8ea7a138ad
--- /dev/null
+++ b/test/lisp/progmodes/js-resources/jsx-self-closing.jsx
@@ -0,0 +1,13 @@
+// Local Variables:
+// indent-tabs-mode: nil
+// js-indent-level: 2
+// End:
+
+// The following test goes below any comments to avoid including
+// misindented comments among the erroring lines.
+
+// Properly parse/indent code with a self-closing tag inside the
+// attribute of another self-closing tag.
+<div>
+ <div attr={() => <div attr="" />} />
+</div>
diff --git a/test/lisp/progmodes/js-resources/jsx-unclosed-1.jsx b/test/lisp/progmodes/js-resources/jsx-unclosed-1.jsx
new file mode 100644
index 00000000000..1f5c3fba8da
--- /dev/null
+++ b/test/lisp/progmodes/js-resources/jsx-unclosed-1.jsx
@@ -0,0 +1,13 @@
+// Local Variables:
+// indent-tabs-mode: nil
+// js-indent-level: 2
+// End:
+
+// The following test goes below any comments to avoid including
+// misindented comments among the erroring lines.
+
+return (
+ <div>
+ {array.map(function () {
+ return {
+ a: 1
diff --git a/test/lisp/progmodes/js-resources/jsx-unclosed-2.jsx b/test/lisp/progmodes/js-resources/jsx-unclosed-2.jsx
new file mode 100644
index 00000000000..fb665b96a43
--- /dev/null
+++ b/test/lisp/progmodes/js-resources/jsx-unclosed-2.jsx
@@ -0,0 +1,65 @@
+// Local Variables:
+// indent-tabs-mode: nil
+// js-indent-level: 2
+// End:
+
+// The following tests go below any comments to avoid including
+// misindented comments among the erroring lines.
+
+// Don’t misinterpret inequality operators as JSX.
+for (; i < length;) void 0
+if (foo > bar) void 0
+
+// Don’t misintrepet inequalities within JSX, either.
+<div>
+ {foo < bar}
+</div>
+
+// Don’t even misinterpret unary operators as JSX.
+if (foo < await bar) void 0
+while (await foo > bar) void 0
+
+<div>
+ {foo < await bar}
+</div>
+
+// Allow unary keyword names as null-valued JSX attributes.
+// (As if this will EVER happen…)
+<Foo yield>
+ <Bar void>
+ <Baz
+ zorp
+ typeof>
+ <Please do_n0t delete this_stupidTest >
+ How would we ever live without unary support
+ </Please>
+ </Baz>
+ </Bar>
+</Foo>
+
+// “-” is not allowed in a JSXBoundaryElement’s name.
+<ABC />
+ <A-B-C /> // Weirdly-indented “continued expression.”
+
+// “-” may be used in a JSXAttribute’s name.
+<Foo a-b-c=""
+ x-y-z="" />
+
+// Weird spaces should be tolerated.
+< div >
+ < div >
+ < div
+ attr=""
+ / >
+ < div
+ attr=""
+ / >
+ < / div>
+< / div >
+
+// Non-ASCII identifiers are acceptable.
+<Über>
+ <Québec διακριτικός sueño="">
+ Guten Tag!
+ </Québec>
+</Über>
diff --git a/test/lisp/progmodes/js-resources/jsx.jsx b/test/lisp/progmodes/js-resources/jsx.jsx
new file mode 100644
index 00000000000..c200979df8c
--- /dev/null
+++ b/test/lisp/progmodes/js-resources/jsx.jsx
@@ -0,0 +1,314 @@
+var foo = <div></div>;
+
+return (
+ <div>
+ </div>
+ <div>
+ <div></div>
+ <div>
+ <div></div>
+ </div>
+ </div>
+);
+
+React.render(
+ <div>
+ <div></div>
+ </div>,
+ {
+ a: 1
+ },
+ <div>
+ <div></div>
+ </div>
+);
+
+return (
+ // Sneaky!
+ <div></div>
+);
+
+return (
+ <div></div>
+ // Sneaky!
+);
+
+React.render(
+ <input
+ />,
+ {
+ a: 1
+ }
+);
+
+return (
+ <div>
+ {array.map(function () {
+ return {
+ a: 1
+ };
+ })}
+ </div>
+);
+
+return (
+ <div attribute={array.map(function () {
+ return {
+ a: 1
+ };
+
+ return {
+ a: 1
+ };
+
+ return {
+ a: 1
+ };
+ })}>
+ </div>
+);
+
+return (
+ <div attribute={{
+ a: 1, // Indent relative to “attribute” column.
+ b: 2
+ } && { // Dedent to “attribute” column.
+ a: 1,
+ b: 2
+ }} /> // Also dedent.
+);
+
+return (
+ <div attribute=
+ { // Indent properly on another line, too.
+ {
+ a: 1,
+ b: 2,
+ } && (
+ // Indent other forms, too.
+ a ? b :
+ c ? d :
+ e
+ )
+ } />
+)
+
+// JSXMemberExpression names are parsed/indented:
+<Foo.Bar>
+ <div>
+ <Foo.Bar>
+ Hello World!
+ </Foo.Bar>
+ <Foo.Bar>
+ <div>
+ </div>
+ </Foo.Bar>
+ </div>
+</Foo.Bar>
+
+// JSXOpeningFragment and JSXClosingFragment are parsed/indented:
+<>
+ <div>
+ <>
+ Hello World!
+ </>
+ <>
+ <div>
+ </div>
+ </>
+ </div>
+</>
+
+// Indent void expressions (no need for contextual parens / commas)
+// (https://github.com/mooz/js2-mode/issues/140#issuecomment-166250016).
+<div className="class-name">
+ <h2>Title</h2>
+ {array.map(() => {
+ return <Element />;
+ })}
+ {message}
+</div>
+// Another example of above issue
+// (https://github.com/mooz/js2-mode/issues/490).
+<App>
+ <div>
+ {variable1}
+ <Component/>
+ </div>
+</App>
+
+// Comments and arrows can break indentation (Bug#24896 /
+// https://github.com/mooz/js2-mode/issues/389).
+const Component = props => (
+ <FatArrow a={e => c}
+ b={123}>
+ </FatArrow>
+);
+const Component = props => (
+ <NoFatArrow a={123}
+ b={123}>
+ </NoFatArrow>
+);
+const Component = props => ( // Parse this comment, please.
+ <FatArrow a={e => c}
+ b={123}>
+ </FatArrow>
+);
+const Component = props => ( // Parse this comment, please.
+ <NoFatArrow a={123}
+ b={123}>
+ </NoFatArrow>
+);
+// Another example of above issue (Bug#30225).
+class {
+ render() {
+ return (
+ <select style={{paddingRight: "10px"}}
+ onChange={e => this.setState({value: e.target.value})}
+ value={this.state.value}>
+ <option>Hi</option>
+ </select>
+ );
+ }
+}
+
+// JSX attributes of an arrow function’s expression body’s JSX
+// expression should be indented with respect to the JSX opening
+// element (Bug#26001 /
+// https://github.com/mooz/js2-mode/issues/389#issuecomment-271869380).
+class {
+ render() {
+ const messages = this.state.messages.map(
+ message => <Message key={message.id}
+ text={message.text}
+ mine={message.mine} />
+ ); return messages;
+ }
+ render() {
+ const messages = this.state.messages.map(message =>
+ <Message key={message.timestamp}
+ text={message.text}
+ mine={message.mine} />
+ ); return messages;
+ }
+}
+
+// Users expect tag closers to align with the tag’s start; this is the
+// style used in the React docs, so it should be the default.
+// - https://github.com/mooz/js2-mode/issues/389#issuecomment-390766873
+// - https://github.com/mooz/js2-mode/issues/482
+// - Bug#32158
+const foo = (props) => (
+ <div>
+ <input
+ cat={i => i}
+ />
+ <button
+ className="square"
+ >
+ {this.state.value}
+ </button>
+ </div>
+);
+
+// Embedded JSX in parens breaks indentation
+// (https://github.com/mooz/js2-mode/issues/411).
+let a = (
+ <div>
+ {condition && <Component/>}
+ {condition && <Component/>}
+ <div/>
+ </div>
+)
+let b = (
+ <div>
+ {condition && (<Component/>)}
+ <div/>
+ </div>
+)
+let c = (
+ <div>
+ {condition && (<Component/>)}
+ {condition && "something"}
+ </div>
+)
+let d = (
+ <div>
+ {(<Component/>)}
+ {condition && "something"}
+ </div>
+)
+// Another example of the above issue (Bug#27000).
+function testA() {
+ return (
+ <div>
+ <div> { ( <div/> ) } </div>
+ </div>
+ );
+}
+function testB() {
+ return (
+ <div>
+ <div> { <div/> } </div>
+ </div>
+ );
+}
+// Another example of the above issue
+// (https://github.com/mooz/js2-mode/issues/451).
+class Classy extends React.Component {
+ render () {
+ return (
+ <div>
+ <ul className="tocListRoot">
+ { this.state.list.map((item) => {
+ return (<div />)
+ })}
+ </ul>
+ </div>
+ )
+ }
+}
+
+// Self-closing tags should be indented properly
+// (https://github.com/mooz/js2-mode/issues/459).
+export default ({ stars }) => (
+ <div className='overlay__container'>
+ <div className='overlay__header overlay--text'>
+ Congratulations!
+ </div>
+ <div className='overlay__reward'>
+ <Icon {...createIconProps(stars > 0)} size='large' />
+ <div className='overlay__reward__bottom'>
+ <Icon {...createIconProps(stars > 1)} size='small' />
+ <Icon {...createIconProps(stars > 2)} size='small' />
+ </div>
+ </div>
+ <div className='overlay__description overlay--text'>
+ You have created <large>1</large> reminder
+ </div>
+ </div>
+)
+
+// JS expressions should not break indentation
+// (https://github.com/mooz/js2-mode/issues/462).
+//
+// In the referenced issue, the user actually wanted indentation which
+// was simply different than Emacs’ SGML attribute indentation.
+// Nevertheless, his issue highlighted our inability to properly
+// indent code with JSX inside JSXExpressionContainers inside JSX.
+return (
+ <Router>
+ <Bar>
+ <Route exact path="/foo"
+ render={() => (
+ <div>nothing</div>
+ )} />
+ <Route exact path="/bar" />
+ </Bar>
+ </Router>
+)
+
+// Local Variables:
+// indent-tabs-mode: nil
+// js-indent-level: 2
+// End:
diff --git a/test/lisp/progmodes/js-tests.el b/test/lisp/progmodes/js-tests.el
index 35143b1ec79..2ce9db65d47 100644
--- a/test/lisp/progmodes/js-tests.el
+++ b/test/lisp/progmodes/js-tests.el
@@ -1,6 +1,6 @@
-;;; js-tests.el --- Test suite for js-mode
+;;; js-tests.el --- Test suite for js-mode -*- lexical-binding:t -*-
-;; Copyright (C) 2017 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2022 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -22,6 +22,7 @@
;;; Code:
(require 'ert)
+(require 'ert-x)
(require 'js)
(require 'syntax)
@@ -196,6 +197,46 @@ if (!/[ (:,='\"]/.test(value)) {
;; The bug was a hang.
(should t)))
+;;;; Indentation tests.
+
+(defun js-tests--remove-indentation ()
+ "Remove all indentation in the current buffer."
+ (goto-char (point-min))
+ (while (re-search-forward (rx bol (+ (in " \t"))) nil t)
+ (let ((syntax (save-match-data (syntax-ppss))))
+ (unless (nth 3 syntax) ; Avoid multiline string literals.
+ (replace-match "")))))
+
+(defmacro js-deftest-indent (file)
+ `(ert-deftest ,(intern (format "js-indent-test/%s" file)) ()
+ :tags '(:expensive-test)
+ (let ((buf (find-file-noselect (ert-resource-file ,file))))
+ (unwind-protect
+ (with-current-buffer buf
+ (let ((orig (buffer-string)))
+ (js-tests--remove-indentation)
+ ;; Indent and check that we get the original text.
+ (indent-region (point-min) (point-max))
+ (should (equal (buffer-string) orig))
+ ;; Verify idempotency.
+ (indent-region (point-min) (point-max))
+ (should (equal (buffer-string) orig))))
+ (kill-buffer buf)))))
+
+(js-deftest-indent "js-chain.js")
+(js-deftest-indent "js-indent-align-list-continuation-nil.js")
+(js-deftest-indent "js-indent-init-dynamic.js")
+(js-deftest-indent "js-indent-init-t.js")
+(js-deftest-indent "js.js")
+(js-deftest-indent "jsx-align-gt-with-lt.jsx")
+(js-deftest-indent "jsx-comment-string.jsx")
+(js-deftest-indent "jsx-indent-level.jsx")
+(js-deftest-indent "jsx-quote.jsx")
+(js-deftest-indent "jsx-self-closing.jsx")
+(js-deftest-indent "jsx-unclosed-1.jsx")
+(js-deftest-indent "jsx-unclosed-2.jsx")
+(js-deftest-indent "jsx.jsx")
+
(provide 'js-tests)
;;; js-tests.el ends here
diff --git a/test/lisp/progmodes/octave-tests.el b/test/lisp/progmodes/octave-tests.el
new file mode 100644
index 00000000000..76dd5c9e5f7
--- /dev/null
+++ b/test/lisp/progmodes/octave-tests.el
@@ -0,0 +1,49 @@
+;;; octave-tests.el --- Test suite for octave.el -*- lexical-binding:t -*-
+
+;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'octave)
+
+(defun octave-test--indent (string)
+ (with-temp-buffer
+ (octave-mode)
+ (insert string)
+ (indent-region (point-min) (point-max))
+ (buffer-string)))
+
+(ert-deftest octave-tests--continuation-indentation ()
+ (should
+ (equal (octave-test--indent "a = b + a * \\
+c;
+")
+ "a = b + a * \\
+ c;
+"))
+ (should (equal (octave-test--indent "a = \\
+b;
+")
+ "a = \\
+ b;
+")))
+
+;;; octave-tests.el ends here
diff --git a/test/lisp/progmodes/opascal-tests.el b/test/lisp/progmodes/opascal-tests.el
new file mode 100644
index 00000000000..cf6bd376142
--- /dev/null
+++ b/test/lisp/progmodes/opascal-tests.el
@@ -0,0 +1,47 @@
+;;; opascal-tests.el --- tests for opascal.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'opascal)
+
+(ert-deftest opascal-indent-bug-36348 ()
+ (with-temp-buffer
+ (opascal-mode)
+ (let ((orig "{ -*- opascal -*- }
+
+procedure Toto ();
+begin
+ for i := 0 to 1 do
+ Write (str.Chars[i]);
+
+ // bug#36348
+ for var i := 0 to 1 do
+ Write (str.Chars[i]);
+
+end;
+"))
+ (insert orig)
+ (indent-region (point-min) (point-max))
+ (should (equal (buffer-string) orig)))))
+
+(provide 'opascal-tests)
+
+;;; opascal-tests.el ends here
diff --git a/test/lisp/progmodes/pascal-tests.el b/test/lisp/progmodes/pascal-tests.el
new file mode 100644
index 00000000000..fb9b52fb864
--- /dev/null
+++ b/test/lisp/progmodes/pascal-tests.el
@@ -0,0 +1,67 @@
+;;; pascal-tests.el --- tests for pascal.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'pascal)
+
+(ert-deftest pascal-completion ()
+ ;; Bug#41740: completion functions must preserve point.
+ (let ((pascal-completion-cache nil))
+ (with-temp-buffer
+ (pascal-mode)
+ (insert "program test; var")
+ (let* ((point-before (point))
+ (completions (pascal-completion "var" nil 'metadata))
+ (point-after (point)))
+ (should (equal completions nil))
+ (should (equal point-before point-after)))))
+
+ (let ((pascal-completion-cache nil))
+ (with-temp-buffer
+ (pascal-mode)
+ (insert "program test; function f(x : i")
+ (let* ((point-before (point))
+ (completions (pascal-completion "i" nil 'metadata))
+ (point-after (point)))
+ (should (equal completions nil))
+ (should (equal point-before point-after)))))
+
+ (let ((pascal-completion-cache nil))
+ (with-temp-buffer
+ (pascal-mode)
+ (insert "program test; function f(x : integer) : real")
+ (let* ((point-before (point))
+ (completions (pascal-completion "real" nil 'metadata))
+ (point-after (point)))
+ (should (equal completions nil))
+ (should (equal point-before point-after))))))
+
+(ert-deftest pascal-beg-of-defun ()
+ (with-temp-buffer
+ (pascal-mode)
+ (insert "program test; procedure p(")
+ (forward-char -1)
+ (pascal-beg-of-defun)
+ (should (equal (point) 15))))
+
+(provide 'pascal-tests)
+
+;;; pascal-tests.el ends here
diff --git a/test/lisp/progmodes/perl-mode-tests.el b/test/lisp/progmodes/perl-mode-tests.el
new file mode 100644
index 00000000000..91f1db23d62
--- /dev/null
+++ b/test/lisp/progmodes/perl-mode-tests.el
@@ -0,0 +1,42 @@
+;;; perl-mode-tests.el --- Test for perl-mode -*- lexical-binding: t -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'perl-mode)
+
+(ert-deftest perl-test-lock ()
+ (with-temp-buffer
+ (perl-mode)
+ (insert "$package = foo;")
+ (font-lock-ensure (point-min) (point-max))
+ (should (equal (get-text-property 4 'face) 'font-lock-variable-name-face))))
+
+;;;; Re-use cperl-mode tests
+
+(defvar cperl-test-mode)
+(setq cperl-test-mode #'perl-mode)
+(load-file (expand-file-name "cperl-mode-tests.el"
+ (file-truename
+ (file-name-directory (or load-file-name
+ buffer-file-name)))))
+
+(setq ert-load-file-name load-file-name)
+
+;;; perl-mode-tests.el ends here
diff --git a/test/lisp/progmodes/project-tests.el b/test/lisp/progmodes/project-tests.el
new file mode 100644
index 00000000000..d4b6bca7e8f
--- /dev/null
+++ b/test/lisp/progmodes/project-tests.el
@@ -0,0 +1,113 @@
+;;; project-tests.el --- tests for project.el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+;; Keywords:
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Unit tests for progmodes/project.el.
+
+;;; Code:
+
+(require 'project)
+
+(require 'cl-lib)
+(require 'ert)
+(require 'ert-x) ; ert-with-temp-directory
+(require 'grep)
+(require 'xref)
+
+(ert-deftest project/quoted-directory ()
+ "Check that `project-files' and `project-find-regexp' deal with
+quoted directory names (Bug#47799)."
+ (skip-unless (executable-find find-program))
+ (skip-unless (executable-find "xargs"))
+ (skip-unless (executable-find "grep"))
+ (ert-with-temp-directory directory
+ (let ((default-directory directory)
+ (project-current-inhibit-prompt t)
+ (project-find-functions nil)
+ (project-list-file
+ (expand-file-name "projects" directory))
+ (project (cons 'transient (file-name-quote directory)))
+ (file (expand-file-name "file" directory)))
+ (add-hook 'project-find-functions (lambda (_dir) project))
+ (should (eq (project-current) project))
+ (write-region "contents" nil file nil nil nil 'excl)
+ (should (equal (project-files project)
+ (list (file-name-quote file))))
+ (let* ((references nil)
+ (xref-search-program 'grep)
+ (xref-show-xrefs-function
+ (lambda (fetcher _display)
+ (push (funcall fetcher) references))))
+ (project-find-regexp "tent")
+ (pcase references
+ (`((,item))
+ ;; FIXME: Shouldn't `xref-match-item' be a subclass of
+ ;; `xref-item'?
+ (should (cl-typep item '(or xref-item xref-match-item)))
+ (should (file-equal-p
+ (xref-location-group (xref-item-location item))
+ file)))
+ (otherwise
+ (ert-fail (format-message "Unexpected references: %S"
+ otherwise))))))))
+
+(cl-defstruct project-tests--trivial root ignores)
+
+(cl-defmethod project-root ((project project-tests--trivial))
+ (project-tests--trivial-root project))
+
+(cl-defmethod project-ignores ((project project-tests--trivial) _dir)
+ (project-tests--trivial-ignores project))
+
+(ert-deftest project-ignores ()
+ "Check that `project-files' correctly ignores the files
+returned by `project-ignores' if the root directory is a
+directory name (Bug#48471)."
+ (skip-unless (executable-find find-program))
+ (ert-with-temp-directory dir
+ (make-empty-file (expand-file-name "some-file" dir))
+ (make-empty-file (expand-file-name "ignored-file" dir))
+ (let* ((project (make-project-tests--trivial
+ :root (file-name-as-directory dir)
+ :ignores '("./ignored-file")))
+ (files (project-files project))
+ (relative-files
+ (cl-loop for file in files
+ collect (file-relative-name file dir))))
+ (should (equal relative-files '("some-file"))))))
+
+(ert-deftest project-ignores-bug-50240 ()
+ "Check that `project-files' does not ignore all files.
+When `project-ignores' includes a name matching project dir."
+ (skip-unless (executable-find find-program))
+ (ert-with-temp-directory dir
+ (make-empty-file (expand-file-name "some-file" dir))
+ (let* ((project (make-project-tests--trivial
+ :root (file-name-as-directory dir)
+ :ignores (list (file-name-nondirectory
+ (directory-file-name dir)))))
+ (files (project-files project)))
+ (should (equal files
+ (list
+ (expand-file-name "some-file" dir)))))))
+
+;;; project-tests.el ends here
diff --git a/test/lisp/progmodes/ps-mode-tests.el b/test/lisp/progmodes/ps-mode-tests.el
new file mode 100644
index 00000000000..7fa40eb0cb4
--- /dev/null
+++ b/test/lisp/progmodes/ps-mode-tests.el
@@ -0,0 +1,72 @@
+;;; ps-mode-tests.el --- Test suite for ps-mode -*- lexical-binding:t -*-
+
+;; Copyright (C) 2019-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'ps-mode)
+
+(ert-deftest ps-mode-test-octal-region-unibyte ()
+ (with-temp-buffer
+ (set-buffer-multibyte nil)
+ (insert "foo" #x90 #x91 #x92 "bar")
+ (ps-mode-octal-region (point-min) (point-max))
+ (should (equal (buffer-string)
+ "foo\\220\\221\\222bar"))))
+
+(ert-deftest ps-mode-test-octal-region-multibyte ()
+ (with-temp-buffer
+ (insert "foo"
+ (unibyte-char-to-multibyte #x90)
+ (unibyte-char-to-multibyte #x91)
+ (unibyte-char-to-multibyte #x92)
+ "bar")
+ (ps-mode-octal-region (point-min) (point-max))
+ (should (equal (buffer-string)
+ "foo\\220\\221\\222bar"))))
+
+(ert-deftest ps-mode-test-indent ()
+ ;; Converted from manual test.
+ (with-temp-buffer
+ (ps-mode)
+ ;; TODO: Should some of these be fontification tests as well?
+ (let ((orig "%!PS-2.0
+
+<< 23 45 >> %dictionary
+< 23 > %hex string
+<~a>a%a~> %base85 string
+(%)s
+(sf\\(g>a)sdg)
+
+/foo {
+ <<
+ hello 2
+ 3
+ >>
+} def
+"))
+ (insert orig)
+ (indent-region (point-min) (point-max))
+ (should (equal (buffer-string) orig)))))
+
+(provide 'ps-mode-tests)
+
+;;; ps-mode-tests.el ends here
diff --git a/test/lisp/progmodes/python-tests.el b/test/lisp/progmodes/python-tests.el
index a59885637e9..fdaedb5fd7a 100644
--- a/test/lisp/progmodes/python-tests.el
+++ b/test/lisp/progmodes/python-tests.el
@@ -1,6 +1,6 @@
-;;; python-tests.el --- Test suite for python.el
+;;; python-tests.el --- Test suite for python.el -*- lexical-binding:t -*-
-;; Copyright (C) 2013-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2022 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -22,6 +22,7 @@
;;; Code:
(require 'ert)
+(require 'ert-x)
(require 'python)
;; Dependencies for testing:
@@ -48,17 +49,17 @@ BODY is code to be executed within the temp buffer. Point is
always located at the beginning of buffer."
(declare (indent 1) (debug t))
;; temp-file never actually used for anything?
- `(let* ((temp-file (make-temp-file "python-tests" nil ".py"))
- (buffer (find-file-noselect temp-file))
- (python-indent-guess-indent-offset nil))
- (unwind-protect
- (with-current-buffer buffer
- (python-mode)
- (insert ,contents)
- (goto-char (point-min))
- ,@body)
- (and buffer (kill-buffer buffer))
- (delete-file temp-file))))
+ `(ert-with-temp-file temp-file
+ :suffix "-python.py"
+ (let ((buffer (find-file-noselect temp-file))
+ (python-indent-guess-indent-offset nil))
+ (unwind-protect
+ (with-current-buffer buffer
+ (python-mode)
+ (insert ,contents)
+ (goto-char (point-min))
+ ,@body)
+ (and buffer (kill-buffer buffer))))))
(defun python-tests-look-at (string &optional num restore-point)
"Move point at beginning of STRING in the current buffer.
@@ -94,6 +95,33 @@ STRING, it is skipped so the next STRING occurrence is selected."
found-point
(and restore-point (goto-char starting-point)))))
+(defun python-tests-assert-faces (content faces)
+ "Assert that font faces for CONTENT are equal to FACES."
+ (python-tests-with-temp-buffer content
+ (font-lock-ensure nil nil)
+ (should (equal faces (python-tests-get-buffer-faces)))))
+
+(defun python-tests-get-buffer-faces ()
+ "Return a list of (position . face) for each face change positions."
+ (cl-loop for pos = (point-min)
+ then (next-single-property-change pos 'face)
+ while pos
+ collect (cons pos (get-text-property pos 'face))))
+
+(defun python-tests-assert-faces-after-change (content faces search replace)
+ "Assert that font faces for CONTENT are equal to FACES after change.
+All occurrences of SEARCH are changed to REPLACE."
+ (python-tests-with-temp-buffer
+ content
+ ;; Force enable font-lock mode without jit-lock.
+ (rename-buffer "*python-font-lock-test*" t)
+ (let (noninteractive font-lock-support-mode)
+ (font-lock-mode))
+ (while
+ (re-search-forward search nil t)
+ (replace-match replace))
+ (should (equal faces (python-tests-get-buffer-faces)))))
+
(defun python-tests-self-insert (char-or-str)
"Call `self-insert-command' for chars in CHAR-OR-STR."
(let ((chars
@@ -118,7 +146,6 @@ Argument MIN and MAX delimit the region to be returned and
default to `point-min' and `point-max' respectively."
(let* ((min (or min (point-min)))
(max (or max (point-max)))
- (buffer (current-buffer))
(buffer-contents (buffer-substring-no-properties min max))
(overlays
(sort (overlays-in min max)
@@ -134,6 +161,16 @@ default to `point-min' and `point-max' respectively."
(overlay-end overlay))))
(buffer-substring-no-properties (point-min) (point-max)))))
+(defun python-virt-bin (&optional virt-root)
+ "Return the virtualenv bin dir, starting from VIRT-ROOT.
+If nil, VIRT-ROOT defaults to `python-shell-virtualenv-root'.
+The name of this directory depends on `system-type'."
+ (expand-file-name
+ (concat
+ (file-name-as-directory (or virt-root
+ python-shell-virtualenv-root))
+ (if (eq system-type 'windows-nt) "Scripts" "bin"))))
+
;;; Tests for your tests, so you can test while you test.
@@ -144,7 +181,7 @@ default to `point-min' and `point-max' respectively."
sed do eiusmod tempor incididunt ut labore et dolore magna
aliqua."
(let ((expected (save-excursion
- (dotimes (i 3)
+ (dotimes (_ 3)
(re-search-forward "et" nil t))
(forward-char -2)
(point))))
@@ -153,7 +190,7 @@ aliqua."
;; one should be returned.
(should (= (python-tests-look-at "et" 6 t) expected))
;; If already looking at STRING, it should skip it.
- (dotimes (i 2) (re-search-forward "et"))
+ (dotimes (_ 2) (re-search-forward "et"))
(forward-char -2)
(should (= (python-tests-look-at "et") expected)))))
@@ -168,7 +205,7 @@ aliqua."
(re-search-forward "et" nil t)
(forward-char -2)
(point))))
- (dotimes (i 3)
+ (dotimes (_ 3)
(re-search-forward "et" nil t))
(should (= (python-tests-look-at "et" -3 t) expected))
(should (= (python-tests-look-at "et" -6 t) expected)))))
@@ -184,7 +221,6 @@ aliqua."
(ert-deftest python-syntax-after-python-backspace ()
;; `python-indent-dedent-line-backspace' garbles syntax
- :expected-result :failed
(python-tests-with-temp-buffer
"\"\"\""
(goto-char (point-max))
@@ -192,10 +228,435 @@ aliqua."
(should (string= (buffer-string) "\"\""))
(should (null (nth 3 (syntax-ppss))))))
+(ert-deftest python-font-lock-keywords-level-1-1 ()
+ (python-tests-assert-faces
+ "def func():"
+ '((1 . font-lock-keyword-face) (4)
+ (5 . font-lock-function-name-face) (9))))
+
+(ert-deftest python-font-lock-keywords-level-1-2 ()
+ "Invalid function name should not be font-locked."
+ (python-tests-assert-faces
+ "def 1func():"
+ '((1 . font-lock-keyword-face) (4))))
+
+(ert-deftest python-font-lock-keywords-level-1-3 ()
+ (python-tests-assert-faces
+ "def \\
+ func():"
+ '((1 . font-lock-keyword-face) (4)
+ (15 . font-lock-function-name-face) (19))))
+
+(ert-deftest python-font-lock-assignment-statement-1 ()
+ (python-tests-assert-faces
+ "a, b, c = 1, 2, 3"
+ '((1 . font-lock-variable-name-face) (2)
+ (4 . font-lock-variable-name-face) (5)
+ (7 . font-lock-variable-name-face) (8))))
+
+(ert-deftest python-font-lock-assignment-statement-2 ()
+ (python-tests-assert-faces
+ "a, *b, c = 1, 2, 3, 4, 5"
+ '((1 . font-lock-variable-name-face) (2)
+ (5 . font-lock-variable-name-face) (6)
+ (8 . font-lock-variable-name-face) (9))))
+
+(ert-deftest python-font-lock-assignment-statement-3 ()
+ (python-tests-assert-faces
+ "[a, b] = (1, 2)"
+ '((1)
+ (2 . font-lock-variable-name-face) (3)
+ (5 . font-lock-variable-name-face) (6))))
+
+(ert-deftest python-font-lock-assignment-statement-4 ()
+ (python-tests-assert-faces
+ "(l[1], l[2]) = (10, 11)"
+ '((1)
+ (2 . font-lock-variable-name-face) (3)
+ (8 . font-lock-variable-name-face) (9))))
+
+(ert-deftest python-font-lock-assignment-statement-5 ()
+ (python-tests-assert-faces
+ "(a, b, c, *d) = *x, y = 5, 6, 7, 8, 9"
+ '((1)
+ (2 . font-lock-variable-name-face) (3)
+ (5 . font-lock-variable-name-face) (6)
+ (8 . font-lock-variable-name-face) (9)
+ (12 . font-lock-variable-name-face) (13)
+ (18 . font-lock-variable-name-face) (19)
+ (21 . font-lock-variable-name-face) (22))))
+
+(ert-deftest python-font-lock-assignment-statement-6 ()
+ (python-tests-assert-faces
+ "(a,) = 'foo',"
+ '((1)
+ (2 . font-lock-variable-name-face) (3)
+ (8 . font-lock-string-face) (13))))
+
+(ert-deftest python-font-lock-assignment-statement-7 ()
+ (python-tests-assert-faces
+ "(*a,) = ['foo', 'bar', 'baz']"
+ '((1)
+ (3 . font-lock-variable-name-face) (4)
+ (10 . font-lock-string-face) (15)
+ (17 . font-lock-string-face) (22)
+ (24 . font-lock-string-face) (29))))
+
+(ert-deftest python-font-lock-assignment-statement-8 ()
+ (python-tests-assert-faces
+ "d = D('a', ['b'], 'c')"
+ '((1 . font-lock-variable-name-face) (2)
+ (7 . font-lock-string-face) (10)
+ (13 . font-lock-string-face) (16)
+ (19 . font-lock-string-face) (22))))
+
+(ert-deftest python-font-lock-assignment-statement-9 ()
+ (python-tests-assert-faces
+ "d.x, d.y[0], *d.z = 'a', 'b', 'c', 'd', 'e'"
+ '((1)
+ (3 . font-lock-variable-name-face) (4)
+ (8 . font-lock-variable-name-face) (9)
+ (17 . font-lock-variable-name-face) (18)
+ (21 . font-lock-string-face) (24)
+ (26 . font-lock-string-face) (29)
+ (31 . font-lock-string-face) (34)
+ (36 . font-lock-string-face) (39)
+ (41 . font-lock-string-face))))
+
+(ert-deftest python-font-lock-assignment-statement-10 ()
+ (python-tests-assert-faces
+ "a: int = 5"
+ '((1 . font-lock-variable-name-face) (2)
+ (4 . font-lock-builtin-face) (7))))
+
+(ert-deftest python-font-lock-assignment-statement-11 ()
+ (python-tests-assert-faces
+ "b: Tuple[Optional[int], Union[Sequence[str], str]] = (None, 'foo')"
+ '((1 . font-lock-variable-name-face) (2)
+ (19 . font-lock-builtin-face) (22)
+ (40 . font-lock-builtin-face) (43)
+ (46 . font-lock-builtin-face) (49)
+ (55 . font-lock-constant-face) (59)
+ (61 . font-lock-string-face) (66))))
+
+(ert-deftest python-font-lock-assignment-statement-12 ()
+ (python-tests-assert-faces
+ "c: Collection = {1, 2, 3}"
+ '((1 . font-lock-variable-name-face) (2))))
+
+(ert-deftest python-font-lock-assignment-statement-13 ()
+ (python-tests-assert-faces
+ "d: Mapping[int, str] = {1: 'bar', 2: 'baz'}"
+ '((1 . font-lock-variable-name-face) (2)
+ (12 . font-lock-builtin-face) (15)
+ (17 . font-lock-builtin-face) (20)
+ (28 . font-lock-string-face) (33)
+ (38 . font-lock-string-face) (43))))
+
+(ert-deftest python-font-lock-assignment-statement-14 ()
+ (python-tests-assert-faces
+ "(a) = 5; (b) = 6"
+ '((1)
+ (2 . font-lock-variable-name-face) (3)
+ (11 . font-lock-variable-name-face) (12))))
+
+(ert-deftest python-font-lock-assignment-statement-15 ()
+ (python-tests-assert-faces
+ "[a] = 5,; [b] = 6,"
+ '((1)
+ (2 . font-lock-variable-name-face) (3)
+ (12 . font-lock-variable-name-face) (13))))
+
+(ert-deftest python-font-lock-assignment-statement-16 ()
+ (python-tests-assert-faces
+ "[*a] = 5, 6; [*b] = 7, 8"
+ '((1)
+ (3 . font-lock-variable-name-face) (4)
+ (16 . font-lock-variable-name-face) (17))))
+
+(ert-deftest python-font-lock-assignment-statement-17 ()
+ (python-tests-assert-faces
+ "(a) = (b) = 1"
+ `((1)
+ (2 . font-lock-variable-name-face) (3)
+ (8 . font-lock-variable-name-face) (9))))
+
+(ert-deftest python-font-lock-assignment-statement-18 ()
+ (python-tests-assert-faces
+ "CustomInt = int
+
+def f(x: CustomInt) -> CustomInt:
+ y = x + 1
+ ys: Sequence[CustomInt] = [y, y + 1]
+ res: CustomInt = sum(ys) + 1
+ return res
+"
+ '((1 . font-lock-variable-name-face) (10)
+ (13 . font-lock-builtin-face) (16)
+ (18 . font-lock-keyword-face) (21)
+ (22 . font-lock-function-name-face) (23)
+ (56 . font-lock-variable-name-face) (57)
+ (70 . font-lock-variable-name-face) (72)
+ (111 . font-lock-variable-name-face) (114)
+ (128 . font-lock-builtin-face) (131)
+ (144 . font-lock-keyword-face) (150))))
+
+(ert-deftest python-font-lock-assignment-statement-multiline-1 ()
+ (python-tests-assert-faces-after-change
+ "
+[
+ a,
+ b
+] # (
+ 1,
+ 2
+)
+"
+ '((1)
+ (8 . font-lock-variable-name-face) (9)
+ (15 . font-lock-variable-name-face) (16))
+ "#" "="))
+
+(ert-deftest python-font-lock-assignment-statement-multiline-2 ()
+ (python-tests-assert-faces-after-change
+ "
+[
+ *a
+] # 5, 6
+"
+ '((1)
+ (9 . font-lock-variable-name-face) (10))
+ "#" "="))
+
+(ert-deftest python-font-lock-assignment-statement-multiline-3 ()
+ (python-tests-assert-faces-after-change
+ "a\\
+ ,\\
+ b\\
+ ,\\
+ c\\
+ #\\
+ 1\\
+ ,\\
+ 2\\
+ ,\\
+ 3"
+ '((1 . font-lock-variable-name-face) (2)
+ (15 . font-lock-variable-name-face) (16)
+ (29 . font-lock-variable-name-face) (30))
+ "#" "="))
+
+(ert-deftest python-font-lock-assignment-statement-multiline-4 ()
+ (python-tests-assert-faces-after-change
+ "a\\
+ :\\
+ int\\
+ #\\
+ 5"
+ '((1 . font-lock-variable-name-face) (2)
+ (15 . font-lock-builtin-face) (18))
+ "#" "="))
+
+(ert-deftest python-font-lock-assignment-statement-multiline-5 ()
+ (python-tests-assert-faces-after-change
+ "(\\
+ a\\
+)\\
+ #\\
+ 5\\
+ ;\\
+ (\\
+ b\\
+ )\\
+ #\\
+ 6"
+ '((1)
+ (8 . font-lock-variable-name-face) (9)
+ (46 . font-lock-variable-name-face) (47))
+ "#" "="))
+
+(ert-deftest python-font-lock-assignment-statement-multiline-6 ()
+ (python-tests-assert-faces-after-change
+ "(
+ a
+)\\
+ #\\
+ 5\\
+ ;\\
+ (
+ b
+ )\\
+ #\\
+ 6"
+ '((1)
+ (7 . font-lock-variable-name-face) (8)
+ (43 . font-lock-variable-name-face) (44))
+ "#" "="))
+
+(ert-deftest python-font-lock-escape-sequence-string-newline ()
+ (python-tests-assert-faces
+ "'\\n'
+\"\\n\"
+f'\\n'
+f\"\\n\"
+u'\\n'
+u\"\\n\""
+ '((1 . font-lock-doc-face)
+ (2 . font-lock-constant-face)
+ (4 . font-lock-doc-face) (5)
+ (6 . font-lock-doc-face)
+ (7 . font-lock-constant-face)
+ (9 . font-lock-doc-face) (10)
+ (12 . font-lock-string-face)
+ (13 . font-lock-constant-face)
+ (15 . font-lock-string-face) (16)
+ (18 . font-lock-string-face)
+ (19 . font-lock-constant-face)
+ (21 . font-lock-string-face) (22)
+ (24 . font-lock-string-face)
+ (25 . font-lock-constant-face)
+ (27 . font-lock-string-face) (28)
+ (30 . font-lock-string-face)
+ (31 . font-lock-constant-face)
+ (33 . font-lock-string-face))))
+
+(ert-deftest python-font-lock-escape-sequence-multiline-string ()
+ (python-tests-assert-faces
+ (let ((escape-sequences "\\x12 \123 \\n \\u1234 \\U00010348 \\N{Plus-Minus Sign}"))
+ (cl-loop for string-prefix in '("" "f" "rf" "fr" "r" "rb" "br" "b")
+ concat (cl-loop for quote-string in '("\"\"\"" "'''")
+ concat (concat string-prefix
+ quote-string
+ escape-sequences
+ quote-string
+ "\n"))))
+ '((1 . font-lock-doc-face)
+ (4 . font-lock-constant-face)
+ (8 . font-lock-doc-face)
+ (11 . font-lock-constant-face)
+ (13 . font-lock-doc-face)
+ (14 . font-lock-constant-face)
+ (20 . font-lock-doc-face)
+ (21 . font-lock-constant-face)
+ (31 . font-lock-doc-face)
+ (32 . font-lock-constant-face)
+ (51 . font-lock-doc-face) (54)
+ (55 . font-lock-doc-face)
+ (58 . font-lock-constant-face)
+ (62 . font-lock-doc-face)
+ (65 . font-lock-constant-face)
+ (67 . font-lock-doc-face)
+ (68 . font-lock-constant-face)
+ (74 . font-lock-doc-face)
+ (75 . font-lock-constant-face)
+ (85 . font-lock-doc-face)
+ (86 . font-lock-constant-face)
+ (105 . font-lock-doc-face) (108)
+ (110 . font-lock-string-face)
+ (113 . font-lock-constant-face)
+ (117 . font-lock-string-face)
+ (120 . font-lock-constant-face)
+ (122 . font-lock-string-face)
+ (123 . font-lock-constant-face)
+ (129 . font-lock-string-face)
+ (130 . font-lock-constant-face)
+ (140 . font-lock-string-face)
+ (141 . font-lock-constant-face)
+ (160 . font-lock-string-face) (163)
+ (165 . font-lock-string-face)
+ (168 . font-lock-constant-face)
+ (172 . font-lock-string-face)
+ (175 . font-lock-constant-face)
+ (177 . font-lock-string-face)
+ (178 . font-lock-constant-face)
+ (184 . font-lock-string-face)
+ (185 . font-lock-constant-face)
+ (195 . font-lock-string-face)
+ (196 . font-lock-constant-face)
+ (215 . font-lock-string-face) (218)
+ (221 . font-lock-string-face) (254)
+ (271 . font-lock-string-face) (274)
+ (277 . font-lock-string-face) (310)
+ (327 . font-lock-string-face) (330)
+ (333 . font-lock-string-face) (366)
+ (383 . font-lock-string-face) (386)
+ (389 . font-lock-string-face) (422)
+ (439 . font-lock-string-face) (442)
+ (444 . font-lock-string-face) (497)
+ (499 . font-lock-string-face) (552)
+ (555 . font-lock-string-face) (608)
+ (611 . font-lock-string-face) (664)
+ (667 . font-lock-string-face) (720)
+ (723 . font-lock-string-face) (776)
+ (778 . font-lock-string-face)
+ (781 . font-lock-constant-face)
+ (785 . font-lock-string-face)
+ (788 . font-lock-constant-face)
+ (790 . font-lock-string-face) (831)
+ (833 . font-lock-string-face)
+ (836 . font-lock-constant-face)
+ (840 . font-lock-string-face)
+ (843 . font-lock-constant-face)
+ (845 . font-lock-string-face) (886))))
+
+(ert-deftest python-font-lock-escape-sequence-bytes-newline ()
+ (python-tests-assert-faces
+ "b'\\n'
+b\"\\n\""
+ '((1)
+ (2 . font-lock-doc-face)
+ (3 . font-lock-constant-face)
+ (5 . font-lock-doc-face) (6)
+ (8 . font-lock-doc-face)
+ (9 . font-lock-constant-face)
+ (11 . font-lock-doc-face))))
+
+(ert-deftest python-font-lock-escape-sequence-hex-octal ()
+ (python-tests-assert-faces
+ "b'\\x12 \\777 \\1\\23'
+'\\x12 \\777 \\1\\23'"
+ '((1)
+ (2 . font-lock-doc-face)
+ (3 . font-lock-constant-face)
+ (7 . font-lock-doc-face)
+ (8 . font-lock-constant-face)
+ (12 . font-lock-doc-face)
+ (13 . font-lock-constant-face)
+ (18 . font-lock-doc-face) (19)
+ (20 . font-lock-doc-face)
+ (21 . font-lock-constant-face)
+ (25 . font-lock-doc-face)
+ (26 . font-lock-constant-face)
+ (30 . font-lock-doc-face)
+ (31 . font-lock-constant-face)
+ (36 . font-lock-doc-face))))
+
+(ert-deftest python-font-lock-escape-sequence-unicode ()
+ (python-tests-assert-faces
+ "b'\\u1234 \\U00010348 \\N{Plus-Minus Sign}'
+'\\u1234 \\U00010348 \\N{Plus-Minus Sign}'"
+ '((1)
+ (2 . font-lock-doc-face) (41)
+ (42 . font-lock-doc-face)
+ (43 . font-lock-constant-face)
+ (49 . font-lock-doc-face)
+ (50 . font-lock-constant-face)
+ (60 . font-lock-doc-face)
+ (61 . font-lock-constant-face)
+ (80 . font-lock-doc-face))))
+
+(ert-deftest python-font-lock-raw-escape-sequence ()
+ (python-tests-assert-faces
+ "rb'\\x12 \123 \\n'
+r'\\x12 \123 \\n \\u1234 \\U00010348 \\N{Plus-Minus Sign}'"
+ '((1)
+ (3 . font-lock-doc-face) (14)
+ (16 . font-lock-doc-face))))
+
;;; Indentation
-;; See: http://www.python.org/dev/peps/pep-0008/#indentation
+;; See: https://www.python.org/dev/peps/pep-0008/#indentation
(ert-deftest python-indent-pep8-1 ()
"First pep8 case."
@@ -260,6 +721,19 @@ foo = long_function_name(
(should (eq (car (python-indent-context)) :inside-paren-newline-start))
(should (= (python-indent-calculate-indentation) 4))))
+(ert-deftest python-indent-hanging-close-paren ()
+ "Like first pep8 case, but with hanging close paren." ;; See Bug#20742.
+ (python-tests-with-temp-buffer
+ "\
+foo = long_function_name(var_one, var_two,
+ var_three, var_four
+ )
+"
+ (should (= (python-indent-calculate-indentation) 0))
+ (python-tests-look-at ")")
+ (should (eq (car (python-indent-context)) :inside-paren-at-closing-paren))
+ (should (= (python-indent-calculate-indentation) 25))))
+
(ert-deftest python-indent-base-case ()
"Check base case does not trigger errors."
(python-tests-with-temp-buffer
@@ -317,7 +791,7 @@ def func(arg):
# I don't do much
return arg
# This comment is badly indented because the user forced so.
- # At this line python.el wont dedent, user is always right.
+ # At this line python.el won't dedent, user is always right.
comment_wins_over_ender = True
@@ -336,7 +810,7 @@ comment_wins_over_ender = True
;; The return keyword do make indentation lose a level...
(should (= (python-indent-calculate-indentation) 0))
;; ...but the current indentation was forced by the user.
- (python-tests-look-at "# At this line python.el wont dedent")
+ (python-tests-look-at "# At this line python.el won't dedent")
(should (eq (car (python-indent-context)) :after-comment))
(should (= (python-indent-calculate-indentation) 4))
;; Should behave the same for blank lines: potentially a comment.
@@ -780,6 +1254,25 @@ def delete_all_things():
:after-backslash-dotted-continuation))
(should (= (python-indent-calculate-indentation) 16))))
+(ert-deftest python-indent-after-backslash-6 ()
+ "Backslash continuation from for block."
+ (python-tests-with-temp-buffer
+ "
+for long_variable_name \\
+ in (1, 2):
+ print(long_variable_name)
+"
+ (python-tests-look-at "for long_variable_name \\")
+ (should (eq (car (python-indent-context)) :no-indent))
+ (should (= (python-indent-calculate-indentation) 0))
+ (python-tests-look-at "in (1, 2):")
+ (should (eq (car (python-indent-context))
+ :after-backslash-block-continuation))
+ (should (= (python-indent-calculate-indentation) 8))
+ (python-tests-look-at "print(long_variable_name)")
+ (should (eq (car (python-indent-context)) :after-block-start))
+ (should (= (python-indent-calculate-indentation) 4))))
+
(ert-deftest python-indent-block-enders-1 ()
"Test de-indentation for pass keyword."
(python-tests-with-temp-buffer
@@ -921,6 +1414,35 @@ if save:
(python-indent-line t)
(should (= (python-indent-calculate-indentation t) 8))))
+(ert-deftest python-indent-dedenters-comment-else ()
+ "Test de-indentation for the else keyword with comments before it."
+ (python-tests-with-temp-buffer
+ "
+if save:
+ try:
+ write_to_disk(data)
+ except IOError:
+ msg = 'Error saving to disk'
+ message(msg)
+ logger.exception(msg)
+ except Exception:
+ if hide_details:
+ logger.exception('Unhandled exception')
+ # comment
+ else
+ finally:
+ data.free()
+"
+ (python-tests-look-at "else\n")
+ (should (eq (car (python-indent-context)) :at-dedenter-block-start))
+ (should (= (python-indent-calculate-indentation) 8))
+ (python-indent-line t)
+ (should (= (python-indent-calculate-indentation t) 4))
+ (python-indent-line t)
+ (should (= (python-indent-calculate-indentation t) 0))
+ (python-indent-line t)
+ (should (= (python-indent-calculate-indentation t) 8))))
+
(ert-deftest python-indent-dedenters-3 ()
"Test de-indentation for the except keyword."
(python-tests-with-temp-buffer
@@ -1109,6 +1631,37 @@ def fn(a, b, c=True):
(should (eq (car (python-indent-context)) :inside-string))
(should (= (python-indent-calculate-indentation) 4))))
+(ert-deftest python-indent-electric-comma-inside-multiline-string ()
+ "Test indentation ...."
+ (python-tests-with-temp-buffer
+ "
+a = (
+ '''\
+- foo,
+- bar
+'''
+"
+ (python-tests-look-at "- bar")
+ (should (eq (car (python-indent-context)) :inside-string))
+ (goto-char (pos-eol))
+ (python-tests-self-insert ",")
+ (should (= (current-indentation) 0))))
+
+(ert-deftest python-indent-electric-comma-after-multiline-string ()
+ "Test indentation ...."
+ (python-tests-with-temp-buffer
+ "
+a = (
+ '''\
+- foo,
+- bar'''
+"
+ (python-tests-look-at "- bar'''")
+ (should (eq (car (python-indent-context)) :inside-string))
+ (goto-char (pos-eol))
+ (python-tests-self-insert ",")
+ (should (= (current-indentation) 0))))
+
(ert-deftest python-indent-electric-colon-1 ()
"Test indentation case from Bug#18228."
(python-tests-with-temp-buffer
@@ -1119,7 +1672,7 @@ def a():
def b()
"
(python-tests-look-at "def b()")
- (goto-char (line-end-position))
+ (goto-char (pos-eol))
(python-tests-self-insert ":")
(should (= (current-indentation) 0))))
@@ -1130,10 +1683,13 @@ def b()
if do:
something()
else
+outside
"
(python-tests-look-at "else")
- (goto-char (line-end-position))
+ (goto-char (pos-eol))
(python-tests-self-insert ":")
+ (should (= (current-indentation) 0))
+ (python-tests-look-at "outside")
(should (= (current-indentation) 0))))
(ert-deftest python-indent-electric-colon-3 ()
@@ -1147,7 +1703,7 @@ if do:
that)
"
(python-tests-look-at "that)")
- (goto-char (line-end-position))
+ (goto-char (pos-eol))
(python-tests-self-insert ":")
(python-tests-look-at "elif" -1)
(should (= (current-indentation) 0))
@@ -1172,7 +1728,7 @@ def f():
else
"
(python-tests-look-at "else")
- (goto-char (line-end-position))
+ (goto-char (pos-eol))
(python-tests-self-insert ":")
(python-tests-look-at "else" -1)
(should (= (current-indentation) 4))))
@@ -1293,6 +1849,60 @@ this is an arbitrarily
(should (string= (buffer-substring-no-properties (point-min) (point-max))
expected)))))
+(ert-deftest python-indent-after-match-block ()
+ "Test PEP634 match."
+ (python-tests-with-temp-buffer
+ "
+match foo:
+"
+ (should (eq (car (python-indent-context)) :no-indent))
+ (should (= (python-indent-calculate-indentation) 0))
+ (goto-char (point-max))
+ (should (eq (car (python-indent-context)) :after-block-start))
+ (should (= (python-indent-calculate-indentation) 4))))
+
+(ert-deftest python-indent-after-case-block ()
+ "Test PEP634 case."
+ (python-tests-with-temp-buffer
+ "
+match foo:
+ case 1:
+"
+ (should (eq (car (python-indent-context)) :no-indent))
+ (should (= (python-indent-calculate-indentation) 0))
+ (goto-char (point-max))
+ (should (eq (car (python-indent-context)) :after-block-start))
+ (should (= (python-indent-calculate-indentation) 8))))
+
+
+;;; Filling
+
+(ert-deftest python-auto-fill-docstring ()
+ (python-tests-with-temp-buffer
+ "\
+def some_function(arg1,
+ arg2):
+ \"\"\"
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
+ (auto-fill-mode +1)
+ (goto-char (point-max))
+ (newline)
+ (search-backward "Lorem")
+ (let ((docindent (current-indentation)))
+ (forward-line 1)
+ (should (= docindent (current-indentation))))))
+
+(ert-deftest python-fill-docstring ()
+ (python-tests-with-temp-buffer
+ "\
+r'''aaa
+
+this is a test this is a test this is a test this is a test this is a test this is a test.
+'''"
+ (search-forward "test.")
+ (fill-paragraph)
+ (should (= (current-indentation) 0))))
+
;;; Mark
@@ -1378,7 +1988,7 @@ class C:
(expected-mark-beginning-position
(progn
(python-tests-look-at "def __init__(self):")
- (1- (line-beginning-position))))
+ (1- (pos-bol))))
(expected-mark-end-position-1
(save-excursion
(python-tests-look-at "self.b = 'b'")
@@ -1435,7 +2045,7 @@ class C:
(progn
(python-tests-look-at "def fun(self):")
(python-tests-look-at "(self):")
- (1- (line-beginning-position))))
+ (1- (pos-bol))))
(expected-mark-end-position
(save-excursion
(python-tests-look-at "return self.b")
@@ -1447,6 +2057,57 @@ class C:
(should (= (marker-position (mark-marker))
expected-mark-end-position)))))
+(ert-deftest python-mark-defun-4 ()
+ "Test `python-mark-defun' with nested functions."
+ (python-tests-with-temp-buffer
+ "
+def foo(x):
+ def bar():
+ return x
+ if True:
+ return bar
+"
+ (let ((expected-mark-beginning-position
+ (progn
+ (python-tests-look-at "def foo(x):")
+ (1- (pos-bol))))
+ (expected-mark-end-position (point-max)))
+ (python-tests-look-at "return bar")
+ (python-mark-defun 1)
+ (should (= (point) expected-mark-beginning-position))
+ (should (= (marker-position (mark-marker))
+ expected-mark-end-position)))))
+
+(ert-deftest python-mark-defun-5 ()
+ "Test `python-mark-defun' with point inside backslash escaped defun."
+ (python-tests-with-temp-buffer
+ "
+def \\
+ foo(x):
+ return x
+"
+ (let ((transient-mark-mode t)
+ (expected-mark-beginning-position
+ (progn
+ (python-tests-look-at "def ")
+ (1- (pos-bol))))
+ (expected-mark-end-position
+ (save-excursion
+ (python-tests-look-at "return x")
+ (forward-line)
+ (point))))
+ (python-tests-look-at "def ")
+ (python-mark-defun 1)
+ (should (= (point) expected-mark-beginning-position))
+ (should (= (marker-position (mark-marker))
+ expected-mark-end-position))
+ (deactivate-mark)
+ (python-tests-look-at "foo(x)")
+ (python-mark-defun 1)
+ (should (= (point) expected-mark-beginning-position))
+ (should (= (marker-position (mark-marker))
+ expected-mark-end-position)))))
+
;;; Navigation
@@ -1473,12 +2134,20 @@ def decoratorFunctionWithArguments(arg1, arg2, arg3):
return wrapped_f
return wwrap
"
- (python-tests-look-at "return wrap")
+ (python-tests-look-at "return wwrap")
+ (should (= (save-excursion
+ (python-nav-beginning-of-defun)
+ (point))
+ (save-excursion
+ (python-tests-look-at "def decoratorFunctionWithArguments" -1)
+ (beginning-of-line)
+ (point))))
+ (python-tests-look-at "return wrap" -1)
(should (= (save-excursion
(python-nav-beginning-of-defun)
(point))
(save-excursion
- (python-tests-look-at "def wrapped_f(*args):" -1)
+ (python-tests-look-at "def wwrap(f):" -1)
(beginning-of-line)
(point))))
(python-tests-look-at "def wrapped_f(*args):" -1)
@@ -1512,6 +2181,9 @@ class C(object):
def a():
pass
+ if True:
+ return a
+
def c(self):
pass
"
@@ -1524,7 +2196,25 @@ class C(object):
(python-tests-look-at "def m(self):" -1)
(beginning-of-line)
(point))))
+ ;; Nested defuns should be skipped.
+ (forward-line -1)
+ (should (= (save-excursion
+ (python-nav-beginning-of-defun)
+ (point))
+ (save-excursion
+ (python-tests-look-at "def m(self):" -1)
+ (beginning-of-line)
+ (point))))
;; Defuns on same levels should be respected.
+ (python-tests-look-at "if True:" -1)
+ (forward-line -1)
+ (should (= (save-excursion
+ (python-nav-beginning-of-defun)
+ (point))
+ (save-excursion
+ (python-tests-look-at "def a():" -1)
+ (beginning-of-line)
+ (point))))
(python-tests-look-at "def a():" -1)
(should (= (save-excursion
(python-nav-beginning-of-defun)
@@ -1533,7 +2223,7 @@ class C(object):
(python-tests-look-at "def b():" -1)
(beginning-of-line)
(point))))
- ;; Jump to a top level defun.
+ ;; Jump to an upper level defun.
(python-tests-look-at "def b():" -1)
(should (= (save-excursion
(python-nav-beginning-of-defun)
@@ -1542,6 +2232,14 @@ class C(object):
(python-tests-look-at "def m(self):" -1)
(beginning-of-line)
(point))))
+ (forward-line -1)
+ (should (= (save-excursion
+ (python-nav-beginning-of-defun)
+ (point))
+ (save-excursion
+ (python-tests-look-at "def m(self):" -1)
+ (beginning-of-line)
+ (point))))
;; Jump to a top level defun again.
(python-tests-look-at "def m(self):" -1)
(should (= (save-excursion
@@ -1572,6 +2270,93 @@ class C(object):
(beginning-of-line)
(point))))))
+(ert-deftest python-nav-beginning-of-defun-4 ()
+ (python-tests-with-temp-buffer
+ "
+def a():
+ pass
+
+def \\
+ b():
+ return 0
+
+def c():
+ pass
+"
+ (python-tests-look-at "def c():")
+ (should (= (save-excursion
+ (python-nav-beginning-of-defun)
+ (point))
+ (save-excursion
+ (python-tests-look-at "def \\" -1)
+ (beginning-of-line)
+ (point))))
+ (python-tests-look-at "return 0" -1)
+ (should (= (save-excursion
+ (python-nav-beginning-of-defun)
+ (point))
+ (save-excursion
+ (python-tests-look-at "def \\" -1)
+ (beginning-of-line)
+ (point))))
+ (python-tests-look-at "b():" -1)
+ (should (= (save-excursion
+ (python-nav-beginning-of-defun)
+ (point))
+ (save-excursion
+ (python-tests-look-at "def \\" -1)
+ (beginning-of-line)
+ (point))))
+ (python-tests-look-at "def a():" -1)
+ (should (= (save-excursion
+ (python-nav-beginning-of-defun -1)
+ (point))
+ (save-excursion
+ (python-tests-look-at "def \\")
+ (beginning-of-line)
+ (point))))))
+
+(ert-deftest python-nav-beginning-of-defun-5 ()
+ (python-tests-with-temp-buffer
+ "
+class C:
+
+ def \\
+ m(self):
+ pass
+"
+ (python-tests-look-at "m(self):")
+ (should (= (save-excursion
+ (python-nav-beginning-of-defun)
+ (point))
+ (save-excursion
+ (python-tests-look-at "def \\" -1)
+ (beginning-of-line)
+ (point))))
+ (python-tests-look-at "class C:" -1)
+ (should (= (save-excursion
+ (python-nav-beginning-of-defun -1)
+ (point))
+ (save-excursion
+ (python-tests-look-at "def \\")
+ (beginning-of-line)
+ (point))))))
+
+(ert-deftest python-nav-beginning-of-defun-6 ()
+ (python-tests-with-temp-buffer
+ "
+class C:
+ def foo(self):
+ pass
+"
+ (python-tests-look-at "self")
+ (should (= (save-excursion
+ (python-nav-beginning-of-defun)
+ (point))
+ (save-excursion
+ (beginning-of-line)
+ (point))))))
+
(ert-deftest python-nav-end-of-defun-1 ()
(python-tests-with-temp-buffer
"
@@ -1605,12 +2390,25 @@ class C(object):
(point))))
(should (= (save-excursion
(python-tests-look-at "def b():")
+ (forward-line -1)
+ (python-nav-end-of-defun)
+ (point))
+ (save-excursion
+ (python-tests-look-at "def c(self):")
+ (forward-line -1)
+ (point))))
+ (should (= (save-excursion
+ (python-tests-look-at "def b():")
(python-nav-end-of-defun)
(point))
(save-excursion
(python-tests-look-at "def b():")
(forward-line 2)
(point))))
+ (should (not (save-excursion
+ (python-tests-look-at "def a():")
+ (forward-line -1)
+ (python-nav-end-of-defun))))
(should (= (save-excursion
(python-tests-look-at "def c(self):")
(python-nav-end-of-defun)
@@ -1659,21 +2457,55 @@ def decoratorFunctionWithArguments(arg1, arg2, arg3):
(point))
(save-excursion
(python-tests-look-at "return wwrap")
- (line-beginning-position))))
+ (pos-bol))))
(should (= (save-excursion
(python-tests-look-at "def wrapped_f(*args):")
(python-nav-end-of-defun)
(point))
(save-excursion
(python-tests-look-at "return wrapped_f")
- (line-beginning-position))))
+ (pos-bol))))
(should (= (save-excursion
(python-tests-look-at "f(*args)")
(python-nav-end-of-defun)
(point))
(save-excursion
(python-tests-look-at "return wrapped_f")
- (line-beginning-position))))))
+ (pos-bol))))))
+
+(ert-deftest python-nav-end-of-defun-3 ()
+ (python-tests-with-temp-buffer
+ "
+def \\
+ a():
+ return 0
+"
+ (should (= (save-excursion
+ (python-tests-look-at "def \\")
+ (python-nav-end-of-defun)
+ (point))
+ (save-excursion
+ (point-max))))))
+
+(ert-deftest python-end-of-defun-1 ()
+ (python-tests-with-temp-buffer
+ "
+class C:
+ def a(self
+ ):
+ pass
+
+ def b(self):
+ pass
+"
+ (should (= (save-excursion
+ (python-tests-look-at "def a")
+ (end-of-defun)
+ (point))
+ (save-excursion
+ (python-tests-look-at "def b")
+ (forward-line -1)
+ (point))))))
(ert-deftest python-nav-backward-defun-1 ()
(python-tests-with-temp-buffer
@@ -1773,6 +2605,18 @@ class A(object):
(should (not (python-nav-backward-defun)))
(should (= point (point))))))
+(ert-deftest python-nav-backward-defun-4 ()
+ (python-tests-with-temp-buffer
+ "
+def \\
+ a():
+ return 0
+"
+ (goto-char (point-max))
+ (should (= (save-excursion (python-nav-backward-defun))
+ (python-tests-look-at "def \\" -1)))
+ (should (not (python-nav-backward-defun)))))
+
(ert-deftest python-nav-forward-defun-1 ()
(python-tests-with-temp-buffer
"
@@ -1871,6 +2715,18 @@ class A(object):
(should (not (python-nav-forward-defun)))
(should (= point (point))))))
+(ert-deftest python-nav-forward-defun-4 ()
+ (python-tests-with-temp-buffer
+ "
+def \\
+ a():
+ return 0
+"
+ (goto-char (point-min))
+ (should (= (save-excursion (python-nav-forward-defun))
+ (python-tests-look-at "():")))
+ (should (not (python-nav-forward-defun)))))
+
(ert-deftest python-nav-beginning-of-statement-1 ()
(python-tests-with-temp-buffer
"
@@ -1948,14 +2804,14 @@ string
(point))
(save-excursion
(python-tests-look-at "789")
- (line-end-position))))
+ (pos-eol))))
(python-tests-look-at "v2 =")
(should (= (save-excursion
(python-nav-end-of-statement)
(point))
(save-excursion
(python-tests-look-at "value4)")
- (line-end-position))))
+ (pos-eol))))
(python-tests-look-at "v3 =")
(should (= (save-excursion
(python-nav-end-of-statement)
@@ -1963,7 +2819,7 @@ string
(save-excursion
(python-tests-look-at
"'continue previous line')")
- (line-end-position))))
+ (pos-eol))))
(python-tests-look-at "v4 =")
(should (= (save-excursion
(python-nav-end-of-statement)
@@ -1973,6 +2829,12 @@ string
(python-util-forward-comment -1)
(point))))))
+(ert-deftest python-nav-end-of-statement-2 ()
+ "Test the string overlap assertion (Bug#30964)."
+ (python-tests-with-temp-buffer
+ "'\n''\n"
+ (python-nav-end-of-statement)))
+
(ert-deftest python-nav-forward-statement-1 ()
(python-tests-with-temp-buffer
"
@@ -2122,6 +2984,28 @@ def decoratorFunctionWithArguments(arg1, arg2, arg3):
(point))
(python-tests-look-at "def wwrap(f):" -1)))))
+(ert-deftest python-nav-beginning-of-block-2 ()
+ (python-tests-with-temp-buffer
+ "
+if True:
+
+ pass
+if False:
+ # comment
+ pass
+"
+ (python-tests-look-at "if True:")
+ (forward-line)
+ (should (= (save-excursion
+ (python-nav-beginning-of-block)
+ (point))
+ (python-tests-look-at "if True:" -1)))
+ (python-tests-look-at "# comment")
+ (should (= (save-excursion
+ (python-nav-beginning-of-block)
+ (point))
+ (python-tests-look-at "if False:" -1)))))
+
(ert-deftest python-nav-end-of-block-1 ()
(python-tests-with-temp-buffer
"
@@ -2159,21 +3043,33 @@ def decoratorFunctionWithArguments(arg1, arg2, arg3):
(point))
(save-excursion
(python-tests-look-at "return wrapped_f")
- (line-end-position))))
+ (pos-eol))))
(end-of-line)
(should (= (save-excursion
(python-nav-end-of-block)
(point))
(save-excursion
(python-tests-look-at "return wrapped_f")
- (line-end-position))))
+ (pos-eol))))
(python-tests-look-at "f(*args)")
(should (= (save-excursion
(python-nav-end-of-block)
(point))
(save-excursion
(python-tests-look-at "print 'After f(*args)'")
- (line-end-position))))))
+ (pos-eol))))))
+
+(ert-deftest python-nav-end-of-block-2 ()
+ "Ensure that `python-nav-end-of-block' does not enter an infinite loop."
+ (python-tests-with-temp-buffer
+ "def
+ =''
+ '
+\"\"\"\"\"\"
+ #
+''
+"
+ (python-nav-end-of-block)))
(ert-deftest python-nav-forward-block-1 ()
"This also accounts as a test for `python-nav-backward-block'."
@@ -2217,6 +3113,22 @@ if request.user.is_authenticated():
(python-tests-look-at
"if request.user.is_authenticated():" -1)))))
+(ert-deftest python-nav-forward-block-2 ()
+ (python-tests-with-temp-buffer
+ "
+if True:
+ pass
+"
+ (python-tests-look-at "if True:")
+ (should (not (save-excursion (python-nav-forward-block))))
+ (should (not (save-excursion (python-nav-forward-block -1))))
+ (forward-char)
+ (should (not (save-excursion (python-nav-forward-block))))
+ (should (= (save-excursion (python-nav-forward-block -1))
+ (progn
+ (end-of-line)
+ (python-tests-look-at "if True:" -1))))))
+
(ert-deftest python-nav-forward-sexp-1 ()
(python-tests-with-temp-buffer
"
@@ -2435,11 +3347,11 @@ if x:
\tabcdefg
"
(python-tests-look-at "abcdefg")
- (goto-char (line-end-position))
+ (goto-char (pos-eol))
(call-interactively #'python-indent-dedent-line-backspace)
(should
(string= (buffer-substring-no-properties
- (line-beginning-position) (line-end-position))
+ (pos-bol) (pos-eol))
"\tabcdef")))))
(ert-deftest python-indent-dedent-line-backspace-3 ()
@@ -2452,27 +3364,27 @@ if x:
\t abcdefg
"
(python-tests-look-at "abcdefg")
- (goto-char (line-end-position))
+ (goto-char (pos-eol))
(call-interactively #'python-indent-dedent-line-backspace)
(should
(string= (buffer-substring-no-properties
- (line-beginning-position) (line-end-position))
+ (pos-bol) (pos-eol))
"\t abcdef"))
(back-to-indentation)
(call-interactively #'python-indent-dedent-line-backspace)
(should
(string= (buffer-substring-no-properties
- (line-beginning-position) (line-end-position))
+ (pos-bol) (pos-eol))
"\tabcdef"))
(call-interactively #'python-indent-dedent-line-backspace)
(should
(string= (buffer-substring-no-properties
- (line-beginning-position) (line-end-position))
+ (pos-bol) (pos-eol))
" abcdef"))
(call-interactively #'python-indent-dedent-line-backspace)
(should
(string= (buffer-substring-no-properties
- (line-beginning-position) (line-end-position))
+ (pos-bol) (pos-eol))
"abcdef")))))
(ert-deftest python-bob-infloop-avoid ()
@@ -2543,58 +3455,59 @@ if x:
"Test `python-shell-process-environment' modification."
(let* ((python-shell-process-environment
'("TESTVAR1=value1" "TESTVAR2=value2"))
- (process-environment (python-shell-calculate-process-environment)))
- (should (equal (getenv "TESTVAR1") "value1"))
- (should (equal (getenv "TESTVAR2") "value2"))))
+ (env (python-shell--calculate-process-environment)))
+ (should (equal (getenv-internal "TESTVAR1" env) "value1"))
+ (should (equal (getenv-internal "TESTVAR2" env) "value2"))))
(ert-deftest python-shell-calculate-process-environment-2 ()
"Test `python-shell-extra-pythonpaths' modification."
(let* ((process-environment process-environment)
- (original-pythonpath (setenv "PYTHONPATH" "/path0"))
+ (_original-pythonpath (setenv "PYTHONPATH" "/path0"))
(python-shell-extra-pythonpaths '("/path1" "/path2"))
- (process-environment (python-shell-calculate-process-environment)))
- (should (equal (getenv "PYTHONPATH")
+ (env (python-shell--calculate-process-environment)))
+ (should (equal (getenv-internal "PYTHONPATH" env)
(concat "/path1" path-separator
"/path2" path-separator "/path0")))))
(ert-deftest python-shell-calculate-process-environment-3 ()
"Test `python-shell-virtualenv-root' modification."
(let* ((python-shell-virtualenv-root "/env")
- (process-environment
+ (env
(let ((process-environment process-environment))
(setenv "PYTHONHOME" "/home")
(setenv "VIRTUAL_ENV")
- (python-shell-calculate-process-environment))))
- (should (not (getenv "PYTHONHOME")))
- (should (string= (getenv "VIRTUAL_ENV") "/env"))))
+ (python-shell--calculate-process-environment))))
+ (should (member "PYTHONHOME" env))
+ (should (string= (getenv-internal "VIRTUAL_ENV" env) "/env"))))
(ert-deftest python-shell-calculate-process-environment-4 ()
"Test PYTHONUNBUFFERED when `python-shell-unbuffered' is non-nil."
(let* ((python-shell-unbuffered t)
- (process-environment
+ (env
(let ((process-environment process-environment))
(setenv "PYTHONUNBUFFERED")
- (python-shell-calculate-process-environment))))
- (should (string= (getenv "PYTHONUNBUFFERED") "1"))))
+ (python-shell--calculate-process-environment))))
+ (should (string= (getenv-internal "PYTHONUNBUFFERED" env) "1"))))
(ert-deftest python-shell-calculate-process-environment-5 ()
"Test PYTHONUNBUFFERED when `python-shell-unbuffered' is nil."
(let* ((python-shell-unbuffered nil)
- (process-environment
+ (env
(let ((process-environment process-environment))
(setenv "PYTHONUNBUFFERED")
- (python-shell-calculate-process-environment))))
- (should (not (getenv "PYTHONUNBUFFERED")))))
+ (python-shell--calculate-process-environment))))
+ (should (not (getenv-internal "PYTHONUNBUFFERED" env)))))
(ert-deftest python-shell-calculate-process-environment-6 ()
"Test PYTHONUNBUFFERED=1 when `python-shell-unbuffered' is nil."
(let* ((python-shell-unbuffered nil)
- (process-environment
+ (env
(let ((process-environment process-environment))
(setenv "PYTHONUNBUFFERED" "1")
- (python-shell-calculate-process-environment))))
+ (append (python-shell--calculate-process-environment)
+ process-environment))))
;; User default settings must remain untouched:
- (should (string= (getenv "PYTHONUNBUFFERED") "1"))))
+ (should (string= (getenv-internal "PYTHONUNBUFFERED" env) "1"))))
(ert-deftest python-shell-calculate-process-environment-7 ()
"Test no side-effects on `process-environment'."
@@ -2604,7 +3517,7 @@ if x:
(python-shell-unbuffered t)
(python-shell-extra-pythonpaths'("/path1" "/path2"))
(original-process-environment (copy-sequence process-environment)))
- (python-shell-calculate-process-environment)
+ (python-shell--calculate-process-environment)
(should (equal process-environment original-process-environment))))
(ert-deftest python-shell-calculate-process-environment-8 ()
@@ -2617,7 +3530,7 @@ if x:
(python-shell-extra-pythonpaths'("/path1" "/path2"))
(original-process-environment
(copy-sequence tramp-remote-process-environment)))
- (python-shell-calculate-process-environment)
+ (python-shell--calculate-process-environment)
(should (equal tramp-remote-process-environment original-process-environment))))
(ert-deftest python-shell-calculate-exec-path-1 ()
@@ -2633,7 +3546,7 @@ if x:
(python-shell-virtualenv-root "/env")
(new-exec-path (python-shell-calculate-exec-path)))
(should (equal new-exec-path
- (list (expand-file-name "/env/bin") "/path0")))))
+ (list (python-virt-bin) "/path0")))))
(ert-deftest python-shell-calculate-exec-path-3 ()
"Test complete `python-shell-virtualenv-root' modification."
@@ -2642,7 +3555,7 @@ if x:
(python-shell-virtualenv-root "/env")
(new-exec-path (python-shell-calculate-exec-path)))
(should (equal new-exec-path
- (list (expand-file-name "/env/bin")
+ (list (python-virt-bin)
"/path1" "/path2" "/path0")))))
(ert-deftest python-shell-calculate-exec-path-4 ()
@@ -2653,7 +3566,7 @@ if x:
(python-shell-virtualenv-root "/env")
(new-exec-path (python-shell-calculate-exec-path)))
(should (equal new-exec-path
- (list (expand-file-name "/env/bin")
+ (list (python-virt-bin)
"/path1" "/path2" "/path0")))))
(ert-deftest python-shell-calculate-exec-path-5 ()
@@ -2683,29 +3596,49 @@ if x:
(python-shell-virtualenv-root "/env"))
(python-shell-with-environment
(should (equal exec-path
- (list (expand-file-name "/env/bin")
+ (list (python-virt-bin)
"/path1" "/path2" "/path0")))
(should (not (getenv "PYTHONHOME")))
(should (string= (getenv "VIRTUAL_ENV") "/env")))
(should (equal exec-path original-exec-path))))
+(defun python--tests-process-env-canonical (pe)
+ ;; `process-environment' can contain various entries for the same
+ ;; var, and the first in the list hides the others.
+ (let ((process-environment '()))
+ (dolist (x (reverse pe))
+ (if (string-match "=" x)
+ (setenv (substring x 0 (match-beginning 0))
+ (substring x (match-end 0)))
+ (setenv x nil)))
+ process-environment))
+
+(defun python--tests-process-env-eql (pe1 pe2)
+ (equal (python--tests-process-env-canonical pe1)
+ (python--tests-process-env-canonical pe2)))
+
(ert-deftest python-shell-with-environment-2 ()
"Test environment with remote `default-directory'."
(let* ((default-directory "/ssh::/example/dir/")
(python-shell-remote-exec-path '("/remote1" "/remote2"))
(python-shell-exec-path '("/path1" "/path2"))
(tramp-remote-process-environment '("EMACS=t"))
- (original-process-environment (copy-sequence tramp-remote-process-environment))
+ (original-process-environment
+ (copy-sequence tramp-remote-process-environment))
(python-shell-virtualenv-root "/env"))
(python-shell-with-environment
(should (equal (python-shell-calculate-exec-path)
- (list (expand-file-name "/env/bin")
+ (list (python-virt-bin)
"/path1" "/path2" "/remote1" "/remote2")))
- (let ((process-environment (python-shell-calculate-process-environment)))
+ (let ((process-environment
+ (append (python-shell--calculate-process-environment)
+ tramp-remote-process-environment)))
(should (not (getenv "PYTHONHOME")))
(should (string= (getenv "VIRTUAL_ENV") "/env"))
- (should (equal tramp-remote-process-environment process-environment))))
- (should (equal tramp-remote-process-environment original-process-environment))))
+ (should (python--tests-process-env-eql
+ tramp-remote-process-environment process-environment))))
+ (should (equal tramp-remote-process-environment
+ original-process-environment))))
(ert-deftest python-shell-with-environment-3 ()
"Test `python-shell-with-environment' is idempotent."
@@ -2714,11 +3647,14 @@ if x:
(python-shell-virtualenv-root "/home/user/env")
(single-call
(python-shell-with-environment
- (list exec-path process-environment)))
+ (list exec-path
+ (python--tests-process-env-canonical process-environment))))
(nested-call
(python-shell-with-environment
(python-shell-with-environment
- (list exec-path process-environment)))))
+ (list exec-path
+ (python--tests-process-env-canonical
+ process-environment))))))
(should (equal single-call nested-call))))
(ert-deftest python-shell-make-comint-1 ()
@@ -3388,10 +4324,7 @@ def foo():
(should (string= (python-shell-buffer-substring
(python-tests-look-at "print ('a')")
(point-max))
- "if True:
-
- print ('a')
-"))))
+ "# -*- coding: utf-8 -*-\nif True:\n print ('a')\n\n"))))
(ert-deftest python-shell-buffer-substring-11 ()
"Check substring from partial block and point within indentation."
@@ -3406,10 +4339,7 @@ def foo():
(backward-char 1)
(point))
(point-max))
- "if True:
-
- print ('a')
-"))))
+ "# -*- coding: utf-8 -*-\nif True:\n print ('a')\n\n"))))
(ert-deftest python-shell-buffer-substring-12 ()
"Check substring from partial block and point in whitespace."
@@ -3424,13 +4354,7 @@ def foo():
(should (string= (python-shell-buffer-substring
(python-tests-look-at "# Whitespace")
(point-max))
- "if True:
-
-
- # Whitespace
-
- print ('a')
-"))))
+ "# -*- coding: utf-8 -*-\n\nif True:\n # Whitespace\n\n print ('a')\n\n"))))
@@ -3462,7 +4386,7 @@ def foo():
;;; Code check
-;;; Eldoc
+;;; ElDoc
(ert-deftest python-eldoc--get-symbol-at-point-1 ()
"Test paren handling."
@@ -3473,11 +4397,11 @@ map(codecs.open('somefile'
"
(python-tests-look-at "ap(xx")
(should (string= (python-eldoc--get-symbol-at-point) "map"))
- (goto-char (line-end-position))
+ (goto-char (pos-eol))
(should (string= (python-eldoc--get-symbol-at-point) "map"))
(python-tests-look-at "('somefile'")
(should (string= (python-eldoc--get-symbol-at-point) "map"))
- (goto-char (line-end-position))
+ (goto-char (pos-eol))
(should (string= (python-eldoc--get-symbol-at-point) "codecs.open"))))
(ert-deftest python-eldoc--get-symbol-at-point-2 ()
@@ -3990,7 +4914,7 @@ def long_function_name(
(should (not (python-info-beginning-of-statement-p)))
(python-tests-look-at "print (var_one)")
(should (python-info-beginning-of-statement-p))
- (goto-char (line-beginning-position))
+ (goto-char (pos-bol))
(should (not (python-info-beginning-of-statement-p)))))
(ert-deftest python-info-beginning-of-statement-p-2 ()
@@ -4010,7 +4934,7 @@ if width == 0 and height == 0 and \\
(should (not (python-info-beginning-of-statement-p)))
(python-tests-look-at "raise ValueError(")
(should (python-info-beginning-of-statement-p))
- (goto-char (line-beginning-position))
+ (goto-char (pos-bol))
(should (not (python-info-beginning-of-statement-p)))))
(ert-deftest python-info-end-of-statement-p-1 ()
@@ -4828,6 +5752,69 @@ def decorat0r(deff):
(python-tests-look-at "deff()")
(should (not (python-info-looking-at-beginning-of-defun)))))
+(ert-deftest python-info-looking-at-beginning-of-defun-2 ()
+ (python-tests-with-temp-buffer
+ "
+def \\
+ foo(arg):
+ pass
+"
+ (python-tests-look-at "def \\")
+ (should (python-info-looking-at-beginning-of-defun))
+ (should (python-info-looking-at-beginning-of-defun nil t))
+ (python-tests-look-at "foo(arg):")
+ (should (not (python-info-looking-at-beginning-of-defun)))
+ (should (python-info-looking-at-beginning-of-defun nil t))
+ (python-tests-look-at "pass")
+ (should (not (python-info-looking-at-beginning-of-defun)))
+ (should (not (python-info-looking-at-beginning-of-defun nil t)))))
+
+(ert-deftest python-info-looking-at-beginning-of-defun-3 ()
+ (python-tests-with-temp-buffer
+ "
+def foo(arg=\"default\"): # Comment
+ pass
+"
+ (python-tests-look-at "arg")
+ (should (python-info-looking-at-beginning-of-defun))
+ (python-tests-look-at "default")
+ (should (python-info-looking-at-beginning-of-defun))
+ (python-tests-look-at "Comment")
+ (should (python-info-looking-at-beginning-of-defun))))
+
+(ert-deftest python-info-looking-at-beginning-of-block-1 ()
+ (python-tests-with-temp-buffer
+ "
+def f():
+ if True:
+ pass
+ l = [x * 2
+ for x in range(5)
+ if x < 3]
+# if False:
+\"\"\"
+if 0:
+\"\"\"
+"
+ (python-tests-look-at "def f():")
+ (should (python-info-looking-at-beginning-of-block))
+ (forward-char)
+ (should (not (python-info-looking-at-beginning-of-block)))
+ (python-tests-look-at "if True:")
+ (should (python-info-looking-at-beginning-of-block))
+ (forward-char)
+ (should (not (python-info-looking-at-beginning-of-block)))
+ (beginning-of-line)
+ (should (python-info-looking-at-beginning-of-block))
+ (python-tests-look-at "for x")
+ (should (not (python-info-looking-at-beginning-of-block)))
+ (python-tests-look-at "if x < 3")
+ (should (not (python-info-looking-at-beginning-of-block)))
+ (python-tests-look-at "if False:")
+ (should (not (python-info-looking-at-beginning-of-block)))
+ (python-tests-look-at "if 0:")
+ (should (not (python-info-looking-at-beginning-of-block)))))
+
(ert-deftest python-info-current-line-comment-p-1 ()
(python-tests-with-temp-buffer
"
@@ -5192,7 +6179,7 @@ urlpatterns = patterns('',
(should (= (current-indentation) 23))))
(or eim (electric-indent-mode -1)))))
-(ert-deftest python-triple-quote-pairing ()
+(ert-deftest python-triple-double-quote-pairing ()
(let ((epm electric-pair-mode))
(unwind-protect
(progn
@@ -5219,6 +6206,33 @@ urlpatterns = patterns('',
"\"\n\"\"\"\n"))))
(or epm (electric-pair-mode -1)))))
+(ert-deftest python-triple-single-quote-pairing ()
+ (let ((epm electric-pair-mode))
+ (unwind-protect
+ (progn
+ (python-tests-with-temp-buffer
+ "''\n"
+ (or epm (electric-pair-mode 1))
+ (goto-char (1- (point-max)))
+ (python-tests-self-insert ?')
+ (should (string= (buffer-string)
+ "''''''\n"))
+ (should (= (point) 4)))
+ (python-tests-with-temp-buffer
+ "\n"
+ (python-tests-self-insert (list ?' ?' ?'))
+ (should (string= (buffer-string)
+ "''''''\n"))
+ (should (= (point) 4)))
+ (python-tests-with-temp-buffer
+ "'\n''\n"
+ (goto-char (1- (point-max)))
+ (python-tests-self-insert ?')
+ (should (= (point) (1- (point-max))))
+ (should (string= (buffer-string)
+ "'\n'''\n"))))
+ (or epm (electric-pair-mode -1)))))
+
;;; Hideshow support
@@ -5254,8 +6268,11 @@ class SomeClass:
class SomeClass:
def __init__(self, arg, kwarg=1):
+
def filter(self, nums):
- def __str__(self):"))))
+
+ def __str__(self):
+"))))
(or enabled (hs-minor-mode -1)))))
(ert-deftest python-hideshow-hide-levels-2 ()
@@ -5301,17 +6318,186 @@ class SomeClass:
"))))
(or enabled (hs-minor-mode -1)))))
+(ert-deftest python-hideshow-hide-levels-3 ()
+ "Should hide all blocks."
+ (python-tests-with-temp-buffer
+ "
+def f():
+ if 0:
+ l = [i for i in range(5)
+ if i < 3]
+ abc = o.match(1, 2, 3)
+
+def g():
+ pass
+"
+ (hs-minor-mode 1)
+ (hs-hide-level 1)
+ (should
+ (string=
+ (python-tests-visible-string)
+ "
+def f():
+
+def g():
+"))))
+
+(ert-deftest python-hideshow-hide-levels-4 ()
+ "Should hide 2nd level block."
+ (python-tests-with-temp-buffer
+ "
+def f():
+ if 0:
+ l = [i for i in range(5)
+ if i < 3]
+ abc = o.match(1, 2, 3)
+
+def g():
+ pass
+"
+ (hs-minor-mode 1)
+ (hs-hide-level 2)
+ (should
+ (string=
+ (python-tests-visible-string)
+ "
+def f():
+ if 0:
+
+def g():
+ pass
+"))))
+
+(ert-deftest python-hideshow-hide-all-1 ()
+ "Should hide all blocks."
+ (python-tests-with-temp-buffer
+ "if 0:
+
+ aaa
+ l = [i for i in range(5)
+ if i < 3]
+ ccc
+ abc = o.match(1, 2, 3)
+ ddd
+
+def f():
+ pass
+"
+ (hs-minor-mode 1)
+ (hs-hide-all)
+ (should
+ (string=
+ (python-tests-visible-string)
+ "if 0:
+
+def f():
+"))))
+
+(ert-deftest python-hideshow-hide-all-2 ()
+ "Should hide comments."
+ (python-tests-with-temp-buffer
+ "
+# Multi line
+# comment
+
+\"\"\"
+# Multi line
+# string
+\"\"\"
+"
+ (hs-minor-mode 1)
+ (hs-hide-all)
+ (should
+ (string=
+ (python-tests-visible-string)
+ "
+# Multi line
+
+\"\"\"
+# Multi line
+# string
+\"\"\"
+"))))
+
+(ert-deftest python-hideshow-hide-all-3 ()
+ "Should not hide comments when `hs-hide-comments-when-hiding-all' is nil."
+ (python-tests-with-temp-buffer
+ "
+# Multi line
+# comment
+
+\"\"\"
+# Multi line
+# string
+\"\"\"
+"
+ (hs-minor-mode 1)
+ (let ((hs-hide-comments-when-hiding-all nil))
+ (hs-hide-all))
+ (should
+ (string=
+ (python-tests-visible-string)
+ "
+# Multi line
+# comment
+
+\"\"\"
+# Multi line
+# string
+\"\"\"
+"))))
+
+(ert-deftest python-hideshow-hide-block-1 ()
+ "Should hide current block."
+ (python-tests-with-temp-buffer
+ "
+if 0:
+
+ aaa
+ l = [i for i in range(5)
+ if i < 3]
+ ccc
+ abc = o.match(1, 2, 3)
+ ddd
+
+def f():
+ pass
+"
+ (hs-minor-mode 1)
+ (python-tests-look-at "ddd")
+ (forward-line)
+ (hs-hide-block)
+ (should
+ (string=
+ (python-tests-visible-string)
+ "
+if 0:
+
+def f():
+ pass
+"))))
+
(ert-deftest python-tests--python-nav-end-of-statement--infloop ()
"Checks that `python-nav-end-of-statement' doesn't infloop in a
buffer with overlapping strings."
+ ;; FIXME: The treatment of strings has changed in the mean time, and the
+ ;; test below now neither signals an error nor inf-loops.
+ ;; The description of the problem it's trying to catch is not clear enough
+ ;; to be able to see if the underlying problem is really fixed, sadly.
+ ;; E.g. I don't know what is meant by "overlap", really.
+ :tags '(:unstable)
(python-tests-with-temp-buffer "''' '\n''' ' '\n"
(syntax-propertize (point-max))
;; Create a situation where strings nominally overlap. This
;; shouldn't happen in practice, but apparently it can happen when
;; a package calls `syntax-ppss' in a narrowed buffer during JIT
;; lock.
+ ;; FIXME: 4-5 is the SPC right after the opening triple quotes: why
+ ;; put a string-fence syntax on it?
(put-text-property 4 5 'syntax-table (string-to-syntax "|"))
+ ;; FIXME: 8-9 is the middle quote in the closing triple quotes:
+ ;; it shouldn't have any syntax-table property to remove anyway!
(remove-text-properties 8 9 '(syntax-table nil))
(goto-char 4)
(setq-local syntax-propertize-function nil)
@@ -5321,11 +6507,80 @@ buffer with overlapping strings."
(python-nav-end-of-statement)))
(should (eolp))))
+;; Interactively, `run-python' focuses the buffer running the
+;; interpreter.
+(ert-deftest python-tests--run-python-selects-window ()
+ "Test for bug#31398. See also bug#44421 and bug#52380."
+ (skip-unless (executable-find python-tests-shell-interpreter))
+ (let* ((buffer (process-buffer (run-python nil nil 'show)))
+ (window (get-buffer-window buffer)))
+ ;; We look at `selected-window' rather than `current-buffer'
+ ;; because as `(elisp)Current buffer' says, the latter will only
+ ;; be synchronized with the former when returning to the "command
+ ;; loop"; until then, `current-buffer' can change arbitrarily.
+ (should (eq window (selected-window)))
+ (pop-to-buffer (other-buffer))
+ (run-python nil nil 'show)
+ (should (eq window (selected-window)))))
+
+(ert-deftest python-tests--fill-long-first-line ()
+ (should
+ (equal
+ (with-temp-buffer
+ (insert "def asdf():
+ \"\"\"123 123 123 123 123 123 123 123 123 123 123 123 123 SHOULDBEWRAPPED 123 123 123 123
-(provide 'python-tests)
+ \"\"\"
+ a = 1
+")
+ (python-mode)
+ (goto-char (point-min))
+ (forward-line 1)
+ (end-of-line)
+ (fill-paragraph)
+ (buffer-substring-no-properties (point-min) (point-max)))
+ "def asdf():
+ \"\"\"123 123 123 123 123 123 123 123 123 123 123 123 123
+ SHOULDBEWRAPPED 123 123 123 123
+
+ \"\"\"
+ a = 1
+")))
-;; Local Variables:
-;; indent-tabs-mode: nil
-;; End:
+
+;;; Flymake
+
+(ert-deftest python-tests--flymake-command-output-pattern ()
+ (pcase-let ((`(,patt ,line ,col ,type ,msg)
+ python-flymake-command-output-pattern))
+ ;; Pyflakes output as of version 2.4.0
+ (let ((output "<stdin>:12:34 'a.b.c as d' imported but unused"))
+ (string-match patt output)
+ (should (equal (match-string line output) "12"))
+ (when col (should (equal (match-string col output) "34")))
+ (should (equal (match-string msg output)
+ "'a.b.c as d' imported but unused")))
+ ;; Flake8 output as of version 4.0.1
+ (let ((output "stdin:12:34: F401 'a.b.c as d' imported but unused"))
+ (string-match patt output)
+ (should (equal (match-string line output) "12"))
+ (when col (should (equal (match-string col output) "34")))
+ (when type (should (equal (match-string type output) "F401")))
+ (should (equal (match-string msg output)
+ (if type
+ "'a.b.c as d' imported but unused"
+ "F401 'a.b.c as d' imported but unused"))))
+ ;; Pylint output as of version 2.14.5
+ (let ((output "stdin:12:34: W0611: Unused import a.b.c (unused-import)"))
+ (string-match patt output)
+ (should (equal (match-string line output) "12"))
+ (when col (should (equal (match-string col output) "34")))
+ (when type (should (equal (match-string type output) "W0611")))
+ (should (equal (match-string msg output)
+ (if type
+ "Unused import a.b.c (unused-import)"
+ "W0611: Unused import a.b.c (unused-import)"))))))
+
+(provide 'python-tests)
;;; python-tests.el ends here
diff --git a/test/manual/indent/ruby.rb b/test/lisp/progmodes/ruby-mode-resources/ruby.rb
index b038512b114..0c206b1e0c2 100644
--- a/test/manual/indent/ruby.rb
+++ b/test/lisp/progmodes/ruby-mode-resources/ruby.rb
@@ -34,7 +34,7 @@ x = # "tot %q/to"; =
# Regexp after whitelisted method.
"abc".sub /b/, 'd'
-# Don't mis-match "sub" at the end of words.
+# Don't mismatch "sub" at the end of words.
a = asub / aslb + bsub / bslb;
# Highlight the regexp after "if".
@@ -108,7 +108,7 @@ foo( # ruby-deep-indent-disabled
# Multiline regexp.
/bars
tees # toots
- nfoos/
+ nfoos::/
def test1(arg)
puts "hello"
@@ -343,7 +343,7 @@ abc(foo
tee
.qux)
-# http://stackoverflow.com/questions/17786563/emacs-ruby-mode-if-expressions-indentation
+# https://stackoverflow.com/questions/17786563/emacs-ruby-mode-if-expressions-indentation
tee = if foo
bar
else
@@ -475,3 +475,28 @@ top test(
foo bar, {
tee: qux
}
+
+# Bug#42846, bug#18644
+
+:foo=
+# indent here
+2 = 3
+:foo= if true
+{:abc=>4} # not indented, and '=' is not highlighted
+
+# Pattern matching
+case translation
+in ['th', orig_text, 'en', trans_text]
+ puts "English translation: #{orig_text} => #{trans_text}"
+in {'th' => orig_text, 'ja' => trans_text}
+ puts "Japanese translation: #{orig_text} => #{trans_text}"
+end
+
+# Tokenizing "**" and "|" separately.
+def resolve(**args)
+ members = proc do |**args|
+ p(**args)
+ end
+
+ member.call(**args)
+end
diff --git a/test/lisp/progmodes/ruby-mode-tests.el b/test/lisp/progmodes/ruby-mode-tests.el
index aa177e31b46..33fded5a59b 100644
--- a/test/lisp/progmodes/ruby-mode-tests.el
+++ b/test/lisp/progmodes/ruby-mode-tests.el
@@ -1,6 +1,6 @@
-;;; ruby-mode-tests.el --- Test suite for ruby-mode
+;;; ruby-mode-tests.el --- Test suite for ruby-mode -*- lexical-binding:t -*-
-;; Copyright (C) 2012-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2022 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -22,6 +22,7 @@
;;; Code:
(require 'ert)
+(require 'ert-x)
(require 'ruby-mode)
(defmacro ruby-with-temp-buffer (contents &rest body)
@@ -31,6 +32,13 @@
(ruby-mode)
,@body))
+(defmacro ruby-with-temp-file (contents &rest body)
+ `(ruby-with-temp-buffer ,contents
+ (set-visited-file-name "ruby-mode-tests")
+ ,@body
+ (set-buffer-modified-p nil)
+ (delete-file buffer-file-name)))
+
(defun ruby-should-indent (content column)
"Assert indentation COLUMN on the last line of CONTENT."
(ruby-with-temp-buffer content
@@ -349,7 +357,7 @@ VALUES-PLIST is a list with alternating index and value elements."
(let ((ruby-align-chained-calls t))
(ruby-should-indent-buffer
"one.two.three
- | .four
+ | .four
|
|my_array.select { |str| str.size > 5 }
| .map { |str| str.downcase }"
@@ -369,7 +377,11 @@ VALUES-PLIST is a list with alternating index and value elements."
(ruby-with-temp-buffer "foo {|b|\n}"
(beginning-of-line)
(ruby-toggle-block)
- (should (string= "foo do |b|\nend" (buffer-string)))))
+ (should (string= "foo do |b|\nend" (buffer-string))))
+ (ruby-with-temp-buffer "foo {|b| b }"
+ (beginning-of-line)
+ (ruby-toggle-block)
+ (should (string= "foo do |b|\n b\nend" (buffer-string)))))
(ert-deftest ruby-toggle-block-to-brace ()
(let ((pairs '((17 . "foo { |b| b + 2 }")
@@ -395,6 +407,13 @@ VALUES-PLIST is a list with alternating index and value elements."
(ruby-toggle-block)
(should (string= "foo { \"#{bar}\" }" (buffer-string)))))
+(ert-deftest ruby-toggle-block-to-brace-no-space ()
+ (ruby-with-temp-buffer "foo do |b|\n b + 2\nend"
+ (beginning-of-line)
+ (let (ruby-toggle-block-space-before-parameters)
+ (ruby-toggle-block))
+ (should (string= "foo {|b| b + 2 }" (buffer-string)))))
+
(ert-deftest ruby-recognize-symbols-starting-with-at-character ()
(ruby-assert-face ":@abc" 3 font-lock-constant-face))
@@ -492,7 +511,8 @@ VALUES-PLIST is a list with alternating index and value elements."
(ert-deftest ruby-add-log-current-method-examples ()
(let ((pairs '(("foo" . "#foo")
("C.foo" . ".foo")
- ("self.foo" . ".foo"))))
+ ("self.foo" . ".foo")
+ ("<<" . "#<<"))))
(dolist (pair pairs)
(let ((name (car pair))
(value (cdr pair)))
@@ -705,17 +725,109 @@ VALUES-PLIST is a list with alternating index and value elements."
(ert-deftest ruby-forward-sexp-skips-method-calls-with-keyword-names ()
(ruby-with-temp-buffer ruby-sexp-test-example
- (goto-line 2)
- (ruby-forward-sexp)
+ (goto-char (point-min))
+ (forward-line 1)
+ (forward-sexp)
(should (= 8 (line-number-at-pos)))))
(ert-deftest ruby-backward-sexp-skips-method-calls-with-keyword-names ()
(ruby-with-temp-buffer ruby-sexp-test-example
- (goto-line 8)
+ (goto-char (point-min))
+ (forward-line 7)
(end-of-line)
- (ruby-backward-sexp)
+ (backward-sexp)
(should (= 2 (line-number-at-pos)))))
+(ert-deftest ruby-forward-sexp-jumps-do-end-block-with-no-args ()
+ (ruby-with-temp-buffer
+ (ruby-test-string
+ "proc do
+ |end")
+ (search-backward "do\n")
+ (forward-sexp)
+ (should (eobp))))
+
+(ert-deftest ruby-backward-sexp-jumps-do-end-block-with-no-args ()
+ (ruby-with-temp-buffer
+ (ruby-test-string
+ "proc do
+ |end")
+ (goto-char (point-max))
+ (backward-sexp)
+ (should (looking-at "do$"))))
+
+(ert-deftest ruby-forward-sexp-jumps-do-end-block-with-empty-args ()
+ (ruby-with-temp-buffer
+ (ruby-test-string
+ "proc do ||
+ |end")
+ (search-backward "do ")
+ (forward-sexp)
+ (should (eobp))))
+
+(ert-deftest ruby-backward-sexp-jumps-do-end-block-with-empty-args ()
+ (ruby-with-temp-buffer
+ (ruby-test-string
+ "proc do ||
+ |end")
+ (goto-char (point-max))
+ (backward-sexp)
+ (should (looking-at "do "))))
+
+(ert-deftest ruby-forward-sexp-jumps-do-end-block-with-args ()
+ (ruby-with-temp-buffer
+ (ruby-test-string
+ "proc do |a,b|
+ |end")
+ (search-backward "do ")
+ (forward-sexp)
+ (should (eobp))))
+
+(ert-deftest ruby-backward-sexp-jumps-do-end-block-with-args ()
+ (ruby-with-temp-buffer
+ (ruby-test-string
+ "proc do |a,b|
+ |end")
+ (goto-char (point-max))
+ (backward-sexp)
+ (should (looking-at "do "))))
+
+(ert-deftest ruby-forward-sexp-jumps-do-end-block-with-any-args ()
+ (ruby-with-temp-buffer
+ (ruby-test-string
+ "proc do |*|
+ |end")
+ (search-backward "do ")
+ (forward-sexp)
+ (should (eobp))))
+
+(ert-deftest ruby-forward-sexp-jumps-do-end-block-with-expanded-one-arg ()
+ (ruby-with-temp-buffer
+ (ruby-test-string
+ "proc do |a,|
+ |end")
+ (search-backward "do ")
+ (forward-sexp)
+ (should (eobp))))
+
+(ert-deftest ruby-forward-sexp-jumps-do-end-block-with-one-and-any-args ()
+ (ruby-with-temp-buffer
+ (ruby-test-string
+ "proc do |a,*|
+ |end")
+ (search-backward "do ")
+ (forward-sexp)
+ (should (eobp))))
+
+(ert-deftest ruby-backward-sexp-jumps-do-end-block-with-one-and-any-args ()
+ (ruby-with-temp-buffer
+ (ruby-test-string
+ "proc do |a,*|
+ |end")
+ (goto-char (point-max))
+ (backward-sexp)
+ (should (looking-at "do "))))
+
(ert-deftest ruby-toggle-string-quotes-quotes-correctly ()
(let ((pairs
'(("puts '\"foo\"\\''" . "puts \"\\\"foo\\\"'\"")
@@ -746,6 +858,89 @@ VALUES-PLIST is a list with alternating index and value elements."
(ruby--insert-coding-comment "utf-8")
(should (string= "# encoding: utf-8\n\n" (buffer-string))))))
+(ert-deftest ruby--set-encoding-when-ascii ()
+ (ruby-with-temp-file "ascii"
+ (let ((ruby-encoding-magic-comment-style 'ruby)
+ (ruby-insert-encoding-magic-comment t))
+ (setq save-buffer-coding-system 'us-ascii)
+ (ruby-mode-set-encoding)
+ (should (string= "ascii" (buffer-string))))))
+
+(ert-deftest ruby--set-encoding-when-utf8 ()
+ (ruby-with-temp-file "💎"
+ (let ((ruby-encoding-magic-comment-style 'ruby)
+ (ruby-insert-encoding-magic-comment t))
+ (setq save-buffer-coding-system 'utf-8)
+ (ruby-mode-set-encoding)
+ (should (string= "💎" (buffer-string))))))
+
+(ert-deftest ruby--set-encoding-when-latin-15 ()
+ (ruby-with-temp-file "Ⓡ"
+ (let ((ruby-encoding-magic-comment-style 'ruby)
+ (ruby-insert-encoding-magic-comment t))
+ (setq save-buffer-coding-system 'iso-8859-15)
+ (ruby-mode-set-encoding)
+ (should (string= "# coding: iso-8859-15\nⓇ" (buffer-string))))))
+
+(ert-deftest ruby-imenu-with-private-modifier ()
+ (ruby-with-temp-buffer
+ (ruby-test-string
+ "class Blub
+ | def hi
+ | 'Hi!'
+ | end
+ |
+ | def bye
+ | 'Bye!'
+ | end
+ |
+ | private def hiding
+ | 'You can't see me'
+ | end
+ |end")
+ (should (equal (mapcar #'car (ruby-imenu-create-index))
+ '("Blub"
+ "Blub#hi"
+ "Blub#bye"
+ "Blub#hiding")))))
+
+(ert-deftest ruby--indent/converted-from-manual-test ()
+ :tags '(:expensive-test)
+ ;; Converted from manual test.
+ (let ((buf (find-file-noselect (ert-resource-file "ruby.rb"))))
+ (unwind-protect
+ (with-current-buffer buf
+ (let ((orig (buffer-string)))
+ (indent-region (point-min) (point-max))
+ (should (equal (buffer-string) orig))))
+ (kill-buffer buf))))
+
+(ert-deftest ruby--test-chained-indentation ()
+ (with-temp-buffer
+ (ruby-mode)
+ (setq-local ruby-align-chained-calls t)
+ (insert "some_variable.where
+.not(x: nil)
+.where(y: 2)
+")
+ (indent-region (point-min) (point-max))
+ (should (equal (buffer-string)
+ "some_variable.where
+ .not(x: nil)
+ .where(y: 2)
+")))
+
+ (with-temp-buffer
+ (ruby-mode)
+ (setq-local ruby-align-chained-calls t)
+ (insert "some_variable.where.not(x: nil)
+.where(y: 2)
+")
+ (indent-region (point-min) (point-max))
+ (should (equal (buffer-string)
+ "some_variable.where.not(x: nil)
+ .where(y: 2)
+"))))
(provide 'ruby-mode-tests)
diff --git a/test/lisp/progmodes/scheme-tests.el b/test/lisp/progmodes/scheme-tests.el
new file mode 100644
index 00000000000..b36e85c770d
--- /dev/null
+++ b/test/lisp/progmodes/scheme-tests.el
@@ -0,0 +1,50 @@
+;;; scheme-tests.el --- Test suite for scheme.el -*- lexical-binding:t -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'scheme)
+
+(ert-deftest scheme-test-indent ()
+ ;; FIXME: Look into what is the expected indent here and fix it.
+ :expected-result :failed
+ ;; Converted from manual test.
+ (with-temp-buffer
+ (scheme-mode)
+ ;; TODO: Should some of these be fontification tests as well?
+ (let ((orig "#!/usr/bin/scheme is this a comment?
+
+;; This one is a comment
+(a)
+#| and this one as #|well|# as this! |#
+(b)
+(cons #;(this is a
+ comment)
+ head tail)
+"))
+ (insert orig)
+ (indent-region (point-min) (point-max))
+ (should (equal (buffer-string) orig)))))
+
+(provide 'scheme-tests)
+
+;;; scheme-tests.el ends here
diff --git a/test/lisp/progmodes/sh-script-resources/sh-indents.erts b/test/lisp/progmodes/sh-script-resources/sh-indents.erts
new file mode 100644
index 00000000000..1f92610b3aa
--- /dev/null
+++ b/test/lisp/progmodes/sh-script-resources/sh-indents.erts
@@ -0,0 +1,40 @@
+Code:
+ (lambda ()
+ (shell-script-mode)
+ (indent-region (point-min) (point-max)))
+
+Name: sh-indents1
+
+=-=
+if test;then
+ something
+fi
+other
+=-=-=
+
+Name: sh-indents2
+
+=-=
+if test; then
+ something
+fi
+other
+=-=-=
+
+Name: sh-indents3
+
+=-=
+if test ; then
+ something
+fi
+other
+=-=-=
+
+Name: sh-indents4
+
+=-=
+if test ;then
+ something
+fi
+other
+=-=-=
diff --git a/test/lisp/progmodes/sh-script-tests.el b/test/lisp/progmodes/sh-script-tests.el
new file mode 100644
index 00000000000..5d01cc1c226
--- /dev/null
+++ b/test/lisp/progmodes/sh-script-tests.el
@@ -0,0 +1,72 @@
+;;; sh-script-tests.el --- Tests for sh-script.el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'sh-script)
+(require 'ert)
+(require 'ert-x)
+
+(ert-deftest test-sh-script-indentation ()
+ (with-temp-buffer
+ (insert "relative-path/to/configure --prefix=$prefix\\
+ --with-x")
+ (shell-script-mode)
+ (goto-char (point-min))
+ (forward-line 1)
+ (indent-for-tab-command)
+ (should (equal
+ (buffer-substring-no-properties (point-min) (point-max))
+ "relative-path/to/configure --prefix=$prefix\\
+ --with-x"))))
+
+(ert-deftest test-basic-sh-indentation ()
+ (with-temp-buffer
+ (insert "myecho () {\necho foo\n}\n")
+ (shell-script-mode)
+ (indent-region (point-min) (point-max))
+ (should (equal (buffer-string)
+ "myecho () {
+ echo foo
+}
+"))))
+
+(ert-deftest test-indentation ()
+ (ert-test-erts-file (ert-resource-file "sh-indents.erts")))
+
+(defun test-sh-back (string &optional pos)
+ (with-temp-buffer
+ (shell-script-mode)
+ (insert string)
+ (sh-smie--default-backward-token)
+ (= (point) (or pos 1))))
+
+(ert-deftest test-backward-token ()
+ (should (test-sh-back "foo"))
+ (should (test-sh-back "foo.bar"))
+ (should (test-sh-back "foo\\1bar"))
+ (should (test-sh-back "foo\\\nbar"))
+ (should (test-sh-back "foo\\\n\\\n\\\nbar"))
+ (should (test-sh-back "foo"))
+ (should-not (test-sh-back "foo;bar"))
+ (should (test-sh-back "foo#zot")))
+
+;;; sh-script-tests.el ends here
diff --git a/test/lisp/progmodes/sql-tests.el b/test/lisp/progmodes/sql-tests.el
index ad22906ecf1..c644d115df6 100644
--- a/test/lisp/progmodes/sql-tests.el
+++ b/test/lisp/progmodes/sql-tests.el
@@ -1,6 +1,6 @@
;;; sql-tests.el --- Tests for sql.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2016-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2022 Free Software Foundation, Inc.
;; Author: Simen Heggestøyl <simenheg@gmail.com>
;; Keywords:
@@ -28,6 +28,7 @@
(require 'cl-lib)
(require 'ert)
+(require 'ert-x)
(require 'sql)
(ert-deftest sql-tests-postgres-list-databases ()
@@ -50,8 +51,459 @@
(lambda (_command) t))
((symbol-function 'process-lines)
(lambda (_program &rest _args)
- (error))))
+ (error "Some error"))))
(should-not (sql-postgres-list-databases))))
+;;; Check Connection Password Handling/Wallet
+
+(defvar sql-test-login-params nil)
+(defmacro with-sql-test-connect-harness (id login-params connection expected)
+ "Set-up and tear-down SQL connect related test.
+
+Identify tests by ID. Set :sql-login dialect attribute to
+LOGIN-PARAMS. Provide the CONNECTION parameters and the EXPECTED
+string of values passed to the comint function for validation."
+ (declare (indent 2))
+ `(ert-with-temp-file tempfile
+ :suffix "sql-test-netrc"
+ :text (concat
+ "machine aMachine user aUserName password \"netrc-A aPassword\""
+ "machine aServer user aUserName password \"netrc-B aPassword\""
+ "machine aMachine server aServer user aUserName password \"netrc-C aPassword\""
+ "machine aMachine database aDatabase user aUserName password \"netrc-D aPassword\""
+ "machine aDatabase user aUserName password \"netrc-E aPassword\""
+ "machine aMachine server aServer database aDatabase user aUserName password \"netrc-F aPassword\""
+ "machine \"aServer/aDatabase\" user aUserName password \"netrc-G aPassword\""
+ "\n")
+ (cl-letf
+ ((sql-test-login-params ' ,login-params)
+ ((symbol-function 'sql-comint-test)
+ (lambda (product options &optional buf-name)
+ (with-current-buffer (get-buffer-create buf-name)
+ (insert (pp-to-string (list product options sql-user sql-password sql-server sql-database))))))
+ ((symbol-function 'sql-run-test)
+ (lambda (&optional buffer)
+ (interactive "P")
+ (sql-product-interactive 'sqltest buffer)))
+ (sql-user nil)
+ (sql-server nil)
+ (sql-database nil)
+ (sql-product-alist
+ '((ansi)
+ (sqltest
+ :name "SqlTest"
+ :sqli-login sql-test-login-params
+ :sqli-comint-func sql-comint-test)))
+ (sql-connection-alist
+ '((,(format "test-%s" id)
+ ,@connection)))
+ (sql-password-wallet (list tempfile)))
+ (let* ((connection ,(format "test-%s" id))
+ (buffername (format "*SQL: ERT TEST <%s>*" connection)))
+ (when (get-buffer buffername)
+ (kill-buffer buffername))
+ (sql-connect connection buffername)
+ (should (get-buffer buffername))
+ (should (string-equal (with-current-buffer buffername (buffer-string)) ,expected))
+ (when (get-buffer buffername)
+ (kill-buffer buffername))))))
+
+(ert-deftest sql-test-connect ()
+ "Test of basic `sql-connect'."
+ (with-sql-test-connect-harness 1 (user password server database)
+ ((sql-product 'sqltest)
+ (sql-user "aUserName")
+ (sql-password "test-1 aPassword")
+ (sql-server "aServer")
+ (sql-database "aDatabase"))
+ "(sqltest nil \"aUserName\" \"test-1 aPassword\" \"aServer\" \"aDatabase\")\n"))
+
+(ert-deftest sql-test-connect-password-func ()
+ "Test of password function."
+ (with-sql-test-connect-harness 2 (user password server database)
+ ((sql-product 'sqltest)
+ (sql-user "aUserName")
+ (sql-password (lambda () (concat [?t ?e ?s ?t ?- ?2 ?\s
+ ?a ?P ?a ?s ?s ?w ?o ?r ?d])))
+ (sql-server "aServer")
+ (sql-database "aDatabase"))
+ "(sqltest nil \"aUserName\" \"test-2 aPassword\" \"aServer\" \"aDatabase\")\n"))
+
+(ert-deftest sql-test-connect-wallet-server-database ()
+ "Test of password function."
+ (with-sql-test-connect-harness 3 (user password server database)
+ ((sql-product 'sqltest)
+ (sql-user "aUserName")
+ (sql-server "aServer")
+ (sql-database "aDatabase"))
+ "(sqltest nil \"aUserName\" \"netrc-G aPassword\" \"aServer\" \"aDatabase\")\n"))
+
+(ert-deftest sql-test-connect-wallet-database ()
+ "Test of password function."
+ (with-sql-test-connect-harness 4 (user password database)
+ ((sql-product 'sqltest)
+ (sql-user "aUserName")
+ (sql-database "aDatabase"))
+ "(sqltest nil \"aUserName\" \"netrc-E aPassword\" nil \"aDatabase\")\n"))
+
+(ert-deftest sql-test-connect-wallet-server ()
+ "Test of password function."
+ (with-sql-test-connect-harness 5 (user password server)
+ ((sql-product 'sqltest)
+ (sql-user "aUserName")
+ (sql-server "aServer"))
+ "(sqltest nil \"aUserName\" \"netrc-B aPassword\" \"aServer\" nil)\n"))
+
+;;; Set/Get Product Features
+
+(defvar sql-test-feature-value-a nil "Indirect value A.")
+(defvar sql-test-feature-value-b nil "Indirect value B.")
+(defvar sql-test-feature-value-c nil "Indirect value C.")
+(defvar sql-test-feature-value-d nil "Indirect value D.")
+(defmacro sql-test-product-feature-harness (&rest action)
+ "Set-up and tear-down of testing product/feature API.
+
+Perform ACTION and validate results"
+ (declare (indent 2))
+ `(cl-letf
+ ((sql-product-alist
+ (list (list 'a :X 1 :Y 2 :Z 'sql-test-feature-value-a)
+ (list 'b :X 3 :Z 'sql-test-feature-value-b)
+ (list 'c :Y 6 :Z 'sql-test-feature-value-c)
+ (list 'd :X 7 :Y 8 )))
+ (sql-indirect-features '(:Z :W))
+ (sql-test-feature-value-a "original A")
+ (sql-test-feature-value-b "original B")
+ (sql-test-feature-value-c "original C")
+ (sql-test-feature-value-d "original D"))
+ ,@action))
+
+(ert-deftest sql-test-add-product ()
+ "Add a product"
+
+ (sql-test-product-feature-harness
+ (sql-add-product 'xyz "XyzDb")
+
+ (should (equal (pp-to-string (assoc 'xyz sql-product-alist))
+ "(xyz :name \"XyzDb\")\n")))
+
+ (sql-test-product-feature-harness
+ (sql-add-product 'stu "StuDb" :X 1 :Y "2")
+
+ (should (equal (pp-to-string (assoc 'stu sql-product-alist))
+ "(stu :name \"StuDb\" :X 1 :Y \"2\")\n"))))
+
+(ert-deftest sql-test-add-existing-product ()
+ "Add a product that already exists."
+
+ (sql-test-product-feature-harness
+ (should-error (sql-add-product 'a "Aaa"))
+ (should (equal (pp-to-string (assoc 'a sql-product-alist))
+ "(a :X 1 :Y 2 :Z sql-test-feature-value-a)\n"))))
+
+(ert-deftest sql-test-set-feature ()
+ "Add a feature"
+
+ (sql-test-product-feature-harness
+ (sql-set-product-feature 'b :Y 4)
+ (should (equal (pp-to-string (assoc 'b sql-product-alist))
+ "(b :Y 4 :X 3 :Z sql-test-feature-value-b)\n"))))
+
+(ert-deftest sql-test-set-indirect-feature ()
+ "Set a new indirect feature"
+
+ (sql-test-product-feature-harness
+ (sql-set-product-feature 'd :Z 'sql-test-feature-value-d)
+ (should (equal (pp-to-string (assoc 'd sql-product-alist))
+ "(d :Z sql-test-feature-value-d :X 7 :Y 8)\n"))))
+
+(ert-deftest sql-test-set-existing-feature ()
+ "Set an existing feature."
+
+ (sql-test-product-feature-harness
+ (sql-set-product-feature 'b :X 33)
+ (should (equal (pp-to-string (assoc 'b sql-product-alist))
+ "(b :X 33 :Z sql-test-feature-value-b)\n"))))
+
+(ert-deftest sql-test-set-existing-indirect-feature ()
+ "Set an existing indirect feature."
+
+ (sql-test-product-feature-harness
+ (should (equal sql-test-feature-value-b "original B"))
+ (sql-set-product-feature 'b :Z "Hurray!")
+ (should (equal (pp-to-string (assoc 'b sql-product-alist))
+ "(b :X 3 :Z sql-test-feature-value-b)\n")) ;; unchanged
+ (should (equal sql-test-feature-value-b "Hurray!"))))
+
+(ert-deftest sql-test-set-missing-product ()
+ "Add a feature to a missing product."
+
+ (sql-test-product-feature-harness
+ (should-error (sql-set-product-feature 'x :Y 4))
+ (should-not (assoc 'x sql-product-alist))))
+
+(ert-deftest sql-test-get-feature ()
+ "Get a feature value."
+
+ (sql-test-product-feature-harness
+ (should (equal (sql-get-product-feature 'c :Y) 6))))
+
+(ert-deftest sql-test-get-indirect-feature ()
+ "Get a feature indirect value."
+
+ (sql-test-product-feature-harness
+ (should (equal (sql-get-product-feature 'c :Z nil t) 'sql-test-feature-value-c))
+ (should (equal sql-test-feature-value-c "original C"))
+ (should (equal (sql-get-product-feature 'c :Z) "original C"))))
+
+(ert-deftest sql-test-get-missing-product ()
+ "Get a feature value from a missing product."
+
+ (sql-test-product-feature-harness
+ (should-error (sql-get-product-feature 'x :Y))))
+
+(ert-deftest sql-test-get-missing-feature ()
+ "Get a missing feature value."
+
+ (sql-test-product-feature-harness
+ (should-not (sql-get-product-feature 'c :X))))
+
+(ert-deftest sql-test-get-missing-indirect-feature ()
+ "Get a missing indirect feature value."
+
+ (sql-test-product-feature-harness
+ (should-not (sql-get-product-feature 'd :Z))))
+
+;;; SQL Oracle SCAN/DEFINE
+(defmacro sql-tests-placeholder-filter-harness (orig repl outp)
+ "Set-up and tear-down of testing of placeholder filter.
+
+The placeholder in ORIG will be replaced by REPL which should
+yield OUTP."
+
+ (declare (indent 0))
+ `(let ((syntab (syntax-table))
+ (sql-oracle-scan-on t))
+ (set-syntax-table sql-mode-syntax-table)
+
+ (cl-letf
+ (((symbol-function 'read-from-minibuffer)
+ (lambda (&rest _) ,repl)))
+
+ (should (equal (sql-placeholders-filter ,orig) ,outp)))
+
+ (set-syntax-table syntab)))
+
+(ert-deftest sql-tests-placeholder-filter-simple ()
+ "Test that placeholder relacement of simple replacement text."
+ (sql-tests-placeholder-filter-harness
+ "select '&x' from dual;" "XX"
+ "select 'XX' from dual;"))
+
+(ert-deftest sql-tests-placeholder-filter-ampersand ()
+ "Test that placeholder relacement of replacement text with ampersand."
+ (sql-tests-placeholder-filter-harness
+ "select '&x' from dual;" "&Y"
+ "select '&Y' from dual;")
+
+ (sql-tests-placeholder-filter-harness
+ "select '&x' from dual;" "Y&"
+ "select 'Y&' from dual;")
+
+ (sql-tests-placeholder-filter-harness
+ "select '&x' from dual;" "Y&Y"
+ "select 'Y&Y' from dual;"))
+
+(ert-deftest sql-tests-placeholder-filter-period ()
+ "Test that placeholder relacement of token terminated by a period."
+ (sql-tests-placeholder-filter-harness
+ "select '&x.' from dual;" "&Y"
+ "select '&Y' from dual;")
+
+ (sql-tests-placeholder-filter-harness
+ "select '&x.y' from dual;" "&Y"
+ "select '&Yy' from dual;")
+
+ (sql-tests-placeholder-filter-harness
+ "select '&x..y' from dual;" "&Y"
+ "select '&Y.y' from dual;"))
+
+;; Buffer naming
+(defmacro sql-tests-buffer-naming-harness (product &rest action)
+ "Set-up and tear-down of test of buffer naming.
+
+The ACTION will be tested after set-up of PRODUCT."
+
+ (declare (indent 1))
+ `(progn
+ (ert--skip-unless (executable-find sql-sqlite-program))
+ (let (new-bufs)
+ (cl-letf
+ (((symbol-function 'make-comint-in-buffer)
+ (lambda (_name buffer _program &optional _startfile &rest _switches)
+ (let ((b (get-buffer-create buffer)))
+ (message ">>make-comint-in-buffer %S" b)
+ (cl-pushnew b new-bufs) ;; Keep track of what we create
+ b))))
+
+ (let (,(intern (format "sql-%s-login-params" product)))
+ ,@action)
+
+ (let (kill-buffer-query-functions) ;; Kill what we create
+ (mapc #'kill-buffer new-bufs))))))
+
+(ert-deftest sql-tests-buffer-naming-default ()
+ "Test buffer naming."
+ (sql-tests-buffer-naming-harness sqlite
+ (sql-sqlite)
+ (message ">> %S" (current-buffer))
+ (should (equal (buffer-name) "*SQL: SQLite*"))))
+
+(ert-deftest sql-tests-buffer-naming-multiple ()
+ "Test buffer naming of multiple buffers."
+ (sql-tests-buffer-naming-harness sqlite
+ (sql-sqlite)
+ (should (equal (buffer-name) "*SQL: SQLite*"))
+
+ (switch-to-buffer "*scratch*")
+
+ (sql-sqlite)
+ (should (equal (buffer-name) "*SQL: SQLite*"))))
+
+(ert-deftest sql-tests-buffer-naming-explicit ()
+ "Test buffer naming with explicit name."
+ (sql-tests-buffer-naming-harness sqlite
+ (sql-sqlite "A")
+ (should (equal (buffer-name) "*SQL: A*"))
+
+ (switch-to-buffer "*scratch*")
+
+ (sql-sqlite "A")
+ (should (equal (buffer-name) "*SQL: A*"))))
+
+(ert-deftest sql-tests-buffer-naming-universal-argument ()
+ "Test buffer naming with explicit name."
+ (sql-tests-buffer-naming-harness sqlite
+ (cl-letf
+ (((symbol-function 'read-string)
+ (lambda (_prompt &optional _initial-input _history _default-value _inherit-input-method)
+ "1")))
+ (sql-sqlite '(4))
+ (should (equal (buffer-name) "*SQL: 1*")))
+
+ (switch-to-buffer "*scratch*")
+
+ (cl-letf
+ (((symbol-function 'read-string)
+ (lambda (_prompt &optional _initial-input _history _default-value _inherit-input-method)
+ "2")))
+ (sql-sqlite '(16))
+ (should (equal (buffer-name) "*SQL: 2*")))))
+
+(ert-deftest sql-tests-buffer-naming-existing ()
+ "Test buffer naming with an existing non-SQLi buffer."
+ (sql-tests-buffer-naming-harness sqlite
+ (get-buffer-create "*SQL: exist*")
+
+ (cl-letf
+ (((symbol-function 'read-string)
+ (lambda (_prompt &optional _initial-input _history _default-value _inherit-input-method)
+ "exist")))
+ (sql-sqlite '(4))
+ (should (equal (buffer-name) "*SQL: exist-1*")))
+
+ (kill-buffer "*SQL: exist*")))
+
+(ert-deftest sql-tests-comint-automatic-password ()
+ (let ((sql-password nil))
+ (should-not (sql-comint-automatic-password "Password: ")))
+ (let ((sql-password ""))
+ (should-not (sql-comint-automatic-password "Password: ")))
+ (let ((sql-password "password"))
+ (should (equal "password" (sql-comint-automatic-password "Password: "))))
+ ;; Also, we shouldn't care what the password is - we rely on comint for that.
+ (let ((sql-password "password"))
+ (should (equal "password" (sql-comint-automatic-password "")))))
+
+
+
+;; Tests for sql-interactive-remove-continuation-prompt
+
+(defmacro sql-tests-remove-cont-prompts-harness (&rest body)
+ "Set-up and tear-down for tests of
+`sql-interactive-remove-continuation-prompt'."
+ (declare (indent 0))
+ `(let ((comint-prompt-regexp "^ +\\.\\{3\\} ")
+ (sql-output-newline-count nil)
+ (sql-preoutput-hold nil))
+ ,@body
+ (should (null sql-output-newline-count))
+ (should (null sql-preoutput-hold))))
+
+(ert-deftest sql-tests-remove-cont-prompts-pass-through ()
+ "Test that `sql-interactive-remove-continuation-prompt' just
+passes the output line through when it doesn't expect prompts."
+ (sql-tests-remove-cont-prompts-harness
+ (should
+ (equal " ... "
+ (sql-interactive-remove-continuation-prompt
+ " ... ")))))
+
+(ert-deftest sql-tests-remove-cont-prompts-anchored-successive ()
+ "Test that `sql-interactive-remove-continuation-prompt' is able
+to delete multiple prompts (anchored to bol) even if they appear
+in a single line, but not more than `sql-output-newline-count'."
+ (sql-tests-remove-cont-prompts-harness
+ (setq sql-output-newline-count 2)
+ (should
+ (equal
+ ;; 2 of 3 prompts are deleted
+ "some output ... more output...\n\
+ ... \n\
+output after prompt"
+ (sql-interactive-remove-continuation-prompt
+ "some output ... more output...\n\
+ ... ... ... \n\
+output after prompt")))))
+
+(ert-deftest sql-tests-remove-cont-prompts-collect-chunked-output ()
+ "Test that `sql-interactive-remove-continuation-prompt' properly
+collects output when output arrives in chunks, with prompts
+intermixed."
+ (sql-tests-remove-cont-prompts-harness
+ (setq sql-output-newline-count 2)
+
+ ;; Part of first prompt gets held. Complete line is passed
+ ;; through.
+ (should (equal "line1\n"
+ (sql-interactive-remove-continuation-prompt
+ "line1\n ..")))
+ (should (equal " .." sql-preoutput-hold))
+ (should (equal 2 sql-output-newline-count))
+
+ ;; First prompt is complete - remove it. Hold part of line2.
+ (should (equal ""
+ (sql-interactive-remove-continuation-prompt ". li")))
+ (should (equal "li" sql-preoutput-hold))
+ (should (equal 1 sql-output-newline-count))
+
+ ;; Remove second prompt. Flush output & don't hold / process any
+ ;; output further on.
+ (should (equal "line2\nli"
+ (sql-interactive-remove-continuation-prompt "ne2\n ... li")))
+ (should (null sql-preoutput-hold))
+ (should (null sql-output-newline-count))
+ (should (equal "line3\n ... "
+ (sql-interactive-remove-continuation-prompt "line3\n ... ")))))
+
+(ert-deftest sql-tests-remove-cont-prompts-flush-held ()
+ "Test that when we don't wait for prompts,
+ `sql-interactive-remove-continuation-prompt' just 'flushes' held
+ output, with no prompt processing."
+ (sql-tests-remove-cont-prompts-harness
+ (setq sql-preoutput-hold "line1\n ..")
+ (should (equal "line1\n ... line2 .."
+ (sql-interactive-remove-continuation-prompt ". line2 ..")))))
+
(provide 'sql-tests)
;;; sql-tests.el ends here
diff --git a/test/lisp/progmodes/subword-tests.el b/test/lisp/progmodes/subword-tests.el
index 66fe1472e4c..7ce27e4df4f 100644
--- a/test/lisp/progmodes/subword-tests.el
+++ b/test/lisp/progmodes/subword-tests.el
@@ -1,22 +1,24 @@
-;;; subword-tests.el --- Testing the subword rules
+;;; subword-tests.el --- Testing the subword rules -*- lexical-binding:t -*-
-;; Copyright (C) 2011-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2022 Free Software Foundation, Inc.
;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
;; Keywords:
-;; This program is free software; you can redistribute it and/or modify
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
-;; This program is distributed in the hope that it will be useful,
+;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
-;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
diff --git a/test/lisp/progmodes/tcl-tests.el b/test/lisp/progmodes/tcl-tests.el
new file mode 100644
index 00000000000..d2346606c27
--- /dev/null
+++ b/test/lisp/progmodes/tcl-tests.el
@@ -0,0 +1,86 @@
+;;; tcl-tests.el --- Test suite for tcl-mode -*- lexical-binding:t -*-
+
+;; Copyright (C) 2018-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'tcl)
+
+;; From bug#23565
+(ert-deftest tcl-mode-beginning-of-defun-1 ()
+ (with-temp-buffer
+ (tcl-mode)
+ (insert "proc bad {{value \"\"}} {\n # do something\n}")
+ (should (beginning-of-defun))
+ (should (= (point) (point-min)))
+ (end-of-defun)
+ (should (= (point) (point-max)))))
+
+;; From bug#23565
+(ert-deftest tcl-mode-beginning-of-defun-2 ()
+ (with-temp-buffer
+ (tcl-mode)
+ (insert "proc good {{value}} {\n # do something\n}")
+ (should (beginning-of-defun))
+ (should (= (point) (point-min)))
+ (end-of-defun)
+ (should (= (point) (point-max)))))
+
+(ert-deftest tcl-mode-function-name ()
+ (with-temp-buffer
+ (tcl-mode)
+ (insert "proc notinthis {} {\n # nothing\n}\n\n")
+ (should-not (add-log-current-defun))))
+
+(ert-deftest tcl-mode-function-name-2 ()
+ (with-temp-buffer
+ (tcl-mode)
+ (insert "proc simple {} {\n # nothing\n}")
+ (backward-char 3)
+ (should (equal "simple" (add-log-current-defun)))))
+
+(ert-deftest tcl-mode-function-name-3 ()
+ (with-temp-buffer
+ (tcl-mode)
+ (insert "proc inthis {} {\n # nothing\n")
+ (should (equal "inthis" (add-log-current-defun)))))
+
+;; From bug#32035
+(ert-deftest tcl-mode-namespace-indent ()
+ (with-temp-buffer
+ (tcl-mode)
+ (let ((text "namespace eval Foo {\n variable foo\n}\n"))
+ (insert text)
+ (indent-region (point-min) (point-max))
+ (should (equal (buffer-string) text)))))
+
+;; From bug#44834
+(ert-deftest tcl-mode-namespace-indent-2 ()
+ (with-temp-buffer
+ (tcl-mode)
+ (let ((text "namespace eval Foo {\n proc foo {} {}\n\n proc bar {}{}}\n"))
+ (insert text)
+ (indent-region (point-min) (point-max))
+ (should (equal (buffer-string) text)))))
+
+(provide 'tcl-tests)
+
+;;; tcl-tests.el ends here
diff --git a/test/lisp/progmodes/xref-resources/file1.txt b/test/lisp/progmodes/xref-resources/file1.txt
new file mode 100644
index 00000000000..85b92f11566
--- /dev/null
+++ b/test/lisp/progmodes/xref-resources/file1.txt
@@ -0,0 +1,2 @@
+ foo foo
+bar
diff --git a/test/data/xref/file2.txt b/test/lisp/progmodes/xref-resources/file2.txt
index 9f075f26004..9f075f26004 100644
--- a/test/data/xref/file2.txt
+++ b/test/lisp/progmodes/xref-resources/file2.txt
diff --git a/test/lisp/progmodes/xref-resources/file3.txt b/test/lisp/progmodes/xref-resources/file3.txt
new file mode 100644
index 00000000000..6283185910d
--- /dev/null
+++ b/test/lisp/progmodes/xref-resources/file3.txt
@@ -0,0 +1 @@
+ match some words match more match ends here
diff --git a/test/lisp/progmodes/xref-tests.el b/test/lisp/progmodes/xref-tests.el
index 465aab51128..f7af5055c78 100644
--- a/test/lisp/progmodes/xref-tests.el
+++ b/test/lisp/progmodes/xref-tests.el
@@ -1,6 +1,6 @@
-;;; xref-tests.el --- tests for xref
+;;; xref-tests.el --- tests for xref -*- lexical-binding:t -*-
-;; Copyright (C) 2016-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2022 Free Software Foundation, Inc.
;; Author: Dmitry Gutov <dgutov@yandex.ru>
@@ -23,46 +23,80 @@
;;; Code:
+(require 'ert)
(require 'xref)
(require 'cl-lib)
-(defvar xref-tests-data-dir
- (expand-file-name "data/xref/"
- (getenv "EMACS_TEST_DIRECTORY")))
+(defvar xref-tests--data-dir
+ (expand-file-name "xref-resources/"
+ (file-name-directory
+ (or load-file-name buffer-file-name))))
-(ert-deftest xref-collect-matches-finds-none-for-some-regexp ()
- (should (null (xref-collect-matches "zzz" "*" xref-tests-data-dir nil))))
+(defun xref-tests--matches-in-data-dir (regexp &optional files)
+ (xref-matches-in-directory regexp (or files "*") xref-tests--data-dir nil))
-(ert-deftest xref-collect-matches-finds-some-for-bar ()
- (let* ((matches (xref-collect-matches "bar" "*" xref-tests-data-dir nil))
- (locs (cl-sort (mapcar #'xref-item-location matches)
- #'string<
- :key #'xref-location-group)))
- (should (= 2 (length matches)))
+(defun xref-tests--locations-in-data-dir (regexp &optional files)
+ (let ((matches (xref-tests--matches-in-data-dir regexp files)))
+ ;; Sort in order to guarantee an order independent from the
+ ;; filesystem traversal.
+ (cl-sort (mapcar #'xref-item-location matches)
+ #'string<
+ :key #'xref-location-group)))
+
+(ert-deftest xref-matches-in-directory-finds-none-for-some-regexp ()
+ (should (null (xref-tests--matches-in-data-dir "zzz"))))
+
+(ert-deftest xref-matches-in-directory-finds-some-for-bar ()
+ (let ((locs (xref-tests--locations-in-data-dir "bar")))
+ (should (= 2 (length locs)))
(should (string-match-p "file1\\.txt\\'" (xref-location-group (nth 0 locs))))
(should (string-match-p "file2\\.txt\\'" (xref-location-group (nth 1 locs))))))
-(ert-deftest xref-collect-matches-finds-two-matches-on-the-same-line ()
- (let* ((matches (xref-collect-matches "foo" "*" xref-tests-data-dir nil))
- (locs (mapcar #'xref-item-location matches)))
- (should (= 2 (length matches)))
+(ert-deftest xref-matches-in-directory-filters-with-ignores ()
+ (let ((locs (xref-matches-in-directory "bar" "*" xref-tests--data-dir
+ '("./file1.*"))))
+ (should (= 1 (length locs)))
+ (should (string-match-p "file2\\.txt\\'" (xref-location-group
+ (xref-item-location
+ (nth 0 locs)))))))
+
+(ert-deftest xref-matches-in-directory-finds-two-matches-on-the-same-line ()
+ (let ((locs (xref-tests--locations-in-data-dir "foo")))
+ (should (= 2 (length locs)))
(should (string-match-p "file1\\.txt\\'" (xref-location-group (nth 0 locs))))
(should (string-match-p "file1\\.txt\\'" (xref-location-group (nth 1 locs))))
(should (equal 1 (xref-location-line (nth 0 locs))))
(should (equal 1 (xref-location-line (nth 1 locs))))
- (should (equal 0 (xref-file-location-column (nth 0 locs))))
- (should (equal 4 (xref-file-location-column (nth 1 locs))))))
+ (should (equal 1 (xref-file-location-column (nth 0 locs))))
+ (should (equal 5 (xref-file-location-column (nth 1 locs))))))
-(ert-deftest xref-collect-matches-finds-an-empty-line-regexp-match ()
- (let* ((matches (xref-collect-matches "^$" "*" xref-tests-data-dir nil))
- (locs (mapcar #'xref-item-location matches)))
- (should (= 1 (length matches)))
+(ert-deftest xref-matches-in-directory-finds-an-empty-line-regexp-match ()
+ (let ((locs (xref-tests--locations-in-data-dir "^$")))
+ (should (= 1 (length locs)))
(should (string-match-p "file2\\.txt\\'" (xref-location-group (nth 0 locs))))
(should (equal 1 (xref-location-line (nth 0 locs))))
(should (equal 0 (xref-file-location-column (nth 0 locs))))))
+(ert-deftest xref-matches-in-files-includes-matches-from-all-the-files ()
+ (let ((matches (xref-matches-in-files "bar"
+ (directory-files xref-tests--data-dir t
+ "\\`[^.]"))))
+ (should (= 2 (length matches)))
+ (should (cl-every
+ (lambda (match) (equal (xref-item-summary match) "bar"))
+ matches))))
+
+(ert-deftest xref-matches-in-files-trims-summary-for-matches-on-same-line ()
+ (let ((matches (xref-matches-in-files "match"
+ (directory-files xref-tests--data-dir t
+ "\\`[^.]"))))
+ (should (= 3 (length matches)))
+ (should
+ (equal (mapcar #'xref-item-summary matches)
+ '(" match some words " "match more " "match ends here")))))
+
(ert-deftest xref--buf-pairs-iterator-groups-markers-by-buffers-1 ()
- (let* ((xrefs (xref-collect-matches "foo" "*" xref-tests-data-dir nil))
+ (let* ((xrefs (xref-tests--matches-in-data-dir "foo"))
(iter (xref--buf-pairs-iterator xrefs))
(cons (funcall iter :next)))
(should (null (funcall iter :next)))
@@ -70,7 +104,7 @@
(should (= 2 (length (cdr cons))))))
(ert-deftest xref--buf-pairs-iterator-groups-markers-by-buffers-2 ()
- (let* ((xrefs (xref-collect-matches "bar" "*" xref-tests-data-dir nil))
+ (let* ((xrefs (xref-tests--matches-in-data-dir "bar"))
(iter (xref--buf-pairs-iterator xrefs))
(cons1 (funcall iter :next))
(cons2 (funcall iter :next)))
@@ -80,7 +114,7 @@
(should (= 1 (length (cdr cons2))))))
(ert-deftest xref--buf-pairs-iterator-cleans-up-markers ()
- (let* ((xrefs (xref-collect-matches "bar" "*" xref-tests-data-dir nil))
+ (let* ((xrefs (xref-tests--matches-in-data-dir "bar"))
(iter (xref--buf-pairs-iterator xrefs))
(cons1 (funcall iter :next))
(cons2 (funcall iter :next)))
@@ -89,3 +123,48 @@
(should (null (marker-position (cdr (nth 0 (cdr cons1))))))
(should (null (marker-position (car (nth 0 (cdr cons2))))))
(should (null (marker-position (cdr (nth 0 (cdr cons2))))))))
+
+(ert-deftest xref--xref-file-name-display-is-abs ()
+ (let ((xref-file-name-display 'abs))
+ (should (equal
+ (delete-dups
+ (mapcar
+ (lambda (loc)
+ (xref--group-name-for-display
+ (xref-location-group loc)
+ nil))
+ (xref-tests--locations-in-data-dir "\\(bar\\|foo\\)")))
+ (list
+ (concat xref-tests--data-dir "file1.txt")
+ (concat xref-tests--data-dir "file2.txt"))))))
+
+(ert-deftest xref--xref-file-name-display-is-nondirectory ()
+ (let ((xref-file-name-display 'nondirectory))
+ (should (equal (delete-dups
+ (mapcar
+ (lambda (loc)
+ (xref--group-name-for-display
+ (xref-location-group loc)
+ nil))
+ (xref-tests--locations-in-data-dir "\\(bar\\|foo\\)")))
+ (list
+ "file1.txt"
+ "file2.txt")))))
+
+(ert-deftest xref--xref-file-name-display-is-relative-to-project-root ()
+ (let* ((data-parent-dir
+ (file-name-directory (directory-file-name xref-tests--data-dir)))
+ (xref-file-name-display 'project-relative))
+ (should (equal
+ (delete-dups
+ (mapcar
+ (lambda (loc)
+ (xref--group-name-for-display
+ (xref-location-group loc)
+ data-parent-dir))
+ (xref-tests--locations-in-data-dir "\\(bar\\|foo\\)")))
+ (list
+ "xref-resources/file1.txt"
+ "xref-resources/file2.txt")))))
+
+;;; xref-tests.el ends here
diff --git a/test/lisp/ps-print-tests.el b/test/lisp/ps-print-tests.el
index 0eb65aab61c..35aa1a9bd19 100644
--- a/test/lisp/ps-print-tests.el
+++ b/test/lisp/ps-print-tests.el
@@ -1,6 +1,6 @@
;;; ps-print-tests.el --- Test suite for ps-print.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2015-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2022 Free Software Foundation, Inc.
;; Author: Phillip Lord <phillip.lord@russet.org.uk>
@@ -34,3 +34,5 @@
(autoloadp
(symbol-function
'ps-mule-initialize))))
+
+;;; ps-print-tests.el ends here
diff --git a/test/lisp/register-tests.el b/test/lisp/register-tests.el
index fd6d1edea25..881a2f90e1e 100644
--- a/test/lisp/register-tests.el
+++ b/test/lisp/register-tests.el
@@ -1,6 +1,6 @@
;;; register-tests.el --- tests for register.el -*- lexical-binding: t-*-
-;; Copyright (C) 2017 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2022 Free Software Foundation, Inc.
;; Author: Tino Calancha <tino.calancha@gmail.com>
;; Keywords:
diff --git a/test/lisp/repeat-tests.el b/test/lisp/repeat-tests.el
new file mode 100644
index 00000000000..1382d003599
--- /dev/null
+++ b/test/lisp/repeat-tests.el
@@ -0,0 +1,141 @@
+;;; repeat-tests.el --- Tests for repeat.el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+;; Author: Juri Linkov <juri@linkov.net>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'repeat)
+
+(defvar repeat-tests-calls nil)
+
+(defun repeat-tests-call-a (&optional arg)
+ (interactive "p")
+ (push `(,arg a) repeat-tests-calls))
+
+(defun repeat-tests-call-b (&optional arg)
+ (interactive "p")
+ (push `(,arg b) repeat-tests-calls))
+
+(defvar-keymap repeat-tests-map
+ :doc "Keymap for keys that initiate repeating sequences."
+ "C-x w a" 'repeat-tests-call-a
+ "C-M-a" 'repeat-tests-call-a
+ "C-M-z" 'repeat-tests-call-a)
+
+(defvar-keymap repeat-tests-repeat-map
+ :doc "Keymap for repeating sequences."
+ "a" 'repeat-tests-call-a
+ "b" 'repeat-tests-call-b)
+(put 'repeat-tests-call-a 'repeat-map 'repeat-tests-repeat-map)
+(put 'repeat-tests-call-b 'repeat-map repeat-tests-repeat-map)
+
+(defmacro with-repeat-mode (&rest body)
+ "Create environment for testing `repeat-mode'."
+ `(unwind-protect
+ (progn
+ (repeat-mode +1)
+ (with-temp-buffer
+ (save-window-excursion
+ ;; `execute-kbd-macro' applied to window only
+ (set-window-buffer nil (current-buffer))
+ (use-local-map repeat-tests-map)
+ ,@body)))
+ (repeat-mode -1)))
+
+(defun repeat-tests--check (keys calls inserted)
+ (setq repeat-tests-calls nil)
+ (delete-region (point-min) (point-max))
+ (execute-kbd-macro (kbd keys))
+ (should (equal (nreverse repeat-tests-calls) calls))
+ ;; Check for self-inserting keys
+ (should (equal (buffer-string) inserted)))
+
+(ert-deftest repeat-tests-check-key ()
+ (with-repeat-mode
+ (let ((repeat-echo-function 'ignore))
+ (let ((repeat-check-key t))
+ (repeat-tests--check
+ "C-x w a b a c"
+ '((1 a) (1 b) (1 a)) "c")
+ (repeat-tests--check
+ "M-C-a b a c"
+ '((1 a) (1 b) (1 a)) "c")
+ (repeat-tests--check
+ "M-C-z b a c"
+ '((1 a)) "bac")
+ (unwind-protect
+ (progn
+ (put 'repeat-tests-call-a 'repeat-check-key 'no)
+ (repeat-tests--check
+ "M-C-z b a c"
+ '((1 a) (1 b) (1 a)) "c"))
+ (put 'repeat-tests-call-a 'repeat-check-key nil)))
+ (let ((repeat-check-key nil))
+ (repeat-tests--check
+ "M-C-z b a c"
+ '((1 a) (1 b) (1 a)) "c")
+ (unwind-protect
+ (progn
+ (put 'repeat-tests-call-a 'repeat-check-key t)
+ (repeat-tests--check
+ "M-C-z b a c"
+ '((1 a)) "bac"))
+ (put 'repeat-tests-call-a 'repeat-check-key nil))))))
+
+(ert-deftest repeat-tests-exit-key ()
+ (with-repeat-mode
+ (let ((repeat-echo-function 'ignore))
+ (let ((repeat-exit-key nil))
+ (repeat-tests--check
+ "C-x w a b a b RET c"
+ '((1 a) (1 b) (1 a) (1 b)) "\nc"))
+ (let ((repeat-exit-key [return]))
+ (repeat-tests--check
+ "C-x w a b a b <return> c"
+ '((1 a) (1 b) (1 a) (1 b)) "c")))))
+
+(ert-deftest repeat-tests-keep-prefix ()
+ (with-repeat-mode
+ (let ((repeat-echo-function 'ignore))
+ (repeat-tests--check
+ "C-x w a b a b c"
+ '((1 a) (1 b) (1 a) (1 b)) "c")
+ (let ((repeat-keep-prefix nil))
+ (repeat-tests--check
+ "C-2 C-x w a b a b c"
+ '((2 a) (1 b) (1 a) (1 b)) "c")
+ (repeat-tests--check
+ "C-2 C-x w a C-3 c"
+ '((2 a)) "ccc"))
+ ;; TODO: fix and uncomment
+ ;; (let ((repeat-keep-prefix t))
+ ;; (repeat-tests--check
+ ;; "C-2 C-x w a b a b c"
+ ;; '((2 a) (2 b) (2 a) (2 b)) "c")
+ ;; (repeat-tests--check
+ ;; "C-2 C-x w a C-1 C-2 b a C-3 C-4 b c"
+ ;; '((2 a) (12 b) (12 a) (34 b)) "c"))
+ )))
+
+;; TODO: :tags '(:expensive-test) for repeat-exit-timeout
+
+(provide 'repeat-tests)
+;;; repeat-tests.el ends here
diff --git a/test/lisp/replace-tests.el b/test/lisp/replace-tests.el
index 06b6dd8a0a9..23ec24840fb 100644
--- a/test/lisp/replace-tests.el
+++ b/test/lisp/replace-tests.el
@@ -1,6 +1,6 @@
-;;; replace-tests.el --- tests for replace.el.
+;;; replace-tests.el --- tests for replace.el. -*- lexical-binding:t -*-
-;; Copyright (C) 2010-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2022 Free Software Foundation, Inc.
;; Author: Nicolas Richard <youngfrog@members.fsf.org>
;; Author: Juri Linkov <juri@jurta.org>
@@ -23,6 +23,7 @@
;;; Code:
(require 'ert)
+(eval-when-compile (require 'subr-x))
(ert-deftest query-replace--split-string-tests ()
(let ((sep (propertize "\0" 'separator t)))
@@ -54,7 +55,7 @@ fx
6:fx
")
;; * Test multi-line matches, this is the first test from
- ;; https://lists.gnu.org/archive/html/emacs-devel/2005-06/msg01008.html
+ ;; https://lists.gnu.org/r/emacs-devel/2005-06/msg01008.html
;; where numbers are replaced with letters.
("a\na" 0 "\
a
@@ -70,7 +71,7 @@ a
:a
")
;; * Test multi-line matches, this is the second test from
- ;; https://lists.gnu.org/archive/html/emacs-devel/2005-06/msg01008.html
+ ;; https://lists.gnu.org/r/emacs-devel/2005-06/msg01008.html
;; where numbers are replaced with letters.
("a\nb" 0 "\
a
@@ -358,26 +359,359 @@ Each element has the format:
(dotimes (i (length replace-occur-tests))
(replace-occur-test-create i))
-(defun replace-tests--query-replace-undo (&optional comma)
+(ert-deftest replace-occur-revert-bug32543 ()
+ "Test `occur-revert' with non-nil `list-matching-lines-jump-to-current-line'."
+ (let ((temp-buffer (get-buffer-create " *test-occur*")))
+ (unwind-protect
+ (save-window-excursion
+ (with-current-buffer temp-buffer
+ (erase-buffer)
+ (setq list-matching-lines-jump-to-current-line t)
+ (insert
+";; This buffer is for text that is not saved, and for Lisp evaluation.
+;; To create a file, visit it with C-x C-f and enter text in its buffer.
+
+")
+ (occur "and")
+ (with-current-buffer "*Occur*"
+ (revert-buffer)
+ (goto-char (point-min))
+ (should (string-match "\\`2 matches for \"and\" in buffer: "
+ (buffer-substring-no-properties
+ (point) (pos-eol)))))))
+ (and (buffer-name temp-buffer)
+ (kill-buffer temp-buffer)))))
+
+(ert-deftest replace-occur-revert-bug32987 ()
+ "Test `occur-revert' with non-nil `list-matching-lines-jump-to-current-line'."
+ (let ((temp-buffer (get-buffer-create " *test-occur*")))
+ (unwind-protect
+ (save-window-excursion
+ (with-current-buffer temp-buffer
+ (erase-buffer)
+ (setq list-matching-lines-jump-to-current-line nil)
+ (insert
+";; This buffer is for text that is not saved, and for Lisp evaluation.
+;; To create a file, visit it with C-x C-f and enter text in its buffer.
+
+")
+ (occur "and")
+ (with-current-buffer "*Occur*"
+ (revert-buffer)
+ (goto-char (point-min))
+ (should (string-match "\\`2 matches for \"and\" in buffer: "
+ (buffer-substring-no-properties
+ (point) (pos-eol)))))))
+ (and (buffer-name temp-buffer)
+ (kill-buffer temp-buffer)))))
+
+
+;;; General tests for `query-replace' and `query-replace-regexp'.
+
+(defconst query-replace-tests
+ '(
+ ;; query-replace
+ ("aaa" "M-% a RET 1 RET !" "111")
+ ("aaa" "M-% a RET 1 RET y n y" "1a1")
+ ;; Empty inputs
+ ("aaa" "M-% a RET RET !" "")
+ ("aaa" "M-% RET 1 RET !" "1a1a1a")
+ ("aaa" "M-% RET RET !" "aaa")
+ ;; Reuse the previous default
+ ("aaa" "M-% a RET 1 RET . M-% RET !" "111")
+
+ ;; query-replace-regexp
+ ("aaa" "C-M-% a* RET 1 RET !" "1")
+ ;; Empty inputs
+ ("aaa" "C-M-% a* RET RET !" "")
+ ("aaa" "C-M-% RET 1 RET !" "1a1a1a")
+ ("aaa" "C-M-% RET RET !" "aaa")
+ ;; Empty matches
+ ("aaa" "C-M-% b* RET 1 RET !" "1a1a1a")
+ ;; Complete matches
+ ("aaa" "C-M-% .* RET 1 RET !" "1")
+ ;; Adjacent non-empty matches
+ ("abaab" "C-M-% ab* RET 12 RET !" "121212")
+ ;; Adjacent non-empty and empty matches
+ ("abab" "C-M-% a* RET 1 RET !" "1b1b")
+ ("abab" "C-M-% b* RET 1 RET !" "1a1a1")
+ ;; Test case from commit 5632eb272c7
+ ("a a a " "C-M-% \\ba SPC RET c RET !" "ccc") ; not "ca c"
+ ))
+
+(defun query-replace--run-tests (tests)
+ (with-temp-buffer
+ (save-window-excursion
+ ;; `execute-kbd-macro' is applied to window only
+ (set-window-buffer nil (current-buffer))
+ (dolist (case tests)
+ ;; Ensure empty input means empty string to replace:
+ (setq query-replace-defaults nil)
+ (delete-region (point-min) (point-max))
+ (insert (nth 0 case))
+ (goto-char (point-min))
+ (execute-kbd-macro (kbd (nth 1 case)))
+ (should (equal (buffer-string) (nth 2 case)))))))
+
+(ert-deftest query-replace-tests ()
+ (query-replace--run-tests query-replace-tests))
+
+(ert-deftest query-replace-search-function-tests ()
+ (let* ((replace-re-search-function #'re-search-forward))
+ (query-replace--run-tests query-replace-tests))
+
+ (let* ((pairs '((1 . 2) (3 . 4)))
+ (replace-re-search-function
+ (lambda (string &optional _bound noerror count)
+ (let (found)
+ (while (and (not found) pairs)
+ (goto-char (caar pairs))
+ (when (re-search-forward string (cdar pairs) noerror count)
+ (setq found t))
+ (pop pairs))
+ found)))
+ (tests
+ '(
+ ;; FIXME: this test should pass after fixing bug#54733:
+ ;; ("aaaa" "C-M-% .* RET 1 RET !" "1a1a")
+ )))
+ (query-replace--run-tests tests)))
+
+
+;;; General tests for `perform-replace'.
+
+(defconst perform-replace-tests
+ '(
+ ;; Test case from commit 5632eb272c7
+ ("a a a " "\\ba " "c" nil t nil nil nil nil nil nil nil "ccc") ; not "ca c"
+ ;; The same with region inside the second match
+ ;; FIXME: this test should pass after fixing bug#54733:
+ ;; ("a a a " "\\ba " "c" nil t nil nil nil 1 4 nil nil "ca a ")
+ ))
+
+(defun perform-replace--run-tests (tests)
(with-temp-buffer
- (insert "111")
- (goto-char 1)
- (let ((count 0))
- ;; Don't wait for user input.
- (cl-letf (((symbol-function 'read-event)
- (lambda (&rest args)
- (cl-incf count)
- (let ((val (pcase count
- ('2 (if comma ?, ?\s)) ; replace and: ',' no move; '\s' go next
- ('3 ?u) ; undo
- ('4 ?q) ; exit
- (_ ?\s)))) ; replace current and go next
- val))))
- (perform-replace "1" "2" t nil nil)))
- (buffer-string)))
+ (dolist (case tests)
+ (delete-region (point-min) (point-max))
+ (insert (pop case))
+ (goto-char (point-min))
+ (apply 'perform-replace (butlast case))
+ (should (equal (buffer-string) (car (last case)))))))
+
+(ert-deftest perform-replace-tests ()
+ (perform-replace--run-tests perform-replace-tests))
+
+
+;;; Tests for `query-replace' undo feature.
+
+(defvar replace-tests-bind-read-string nil
+ "A string to bind `read-string' and avoid the prompt.")
+
+(defvar replace-tests-perform-replace-regexp-flag t
+ "Value for regexp-flag argument passed to `perform-replace' in undo tests.")
+
+(defmacro replace-tests-with-undo (input from to char-nums def-chr &rest body)
+ "Helper to test `query-replace' undo feature.
+INPUT is a string to insert in a temporary buffer.
+FROM is the string to match and replace.
+TO is the replacement string.
+CHAR-NUMS is a list of elements (CHAR . NUMS), where CHAR is
+one of the characters `,', `?\\s', `u', `U', `E' or `q'
+and NUMS a list of integers.
+DEF-CHAR is the character `?\\s' or `q'.
+BODY is a list of forms to evaluate.
+
+Use CHAR-NUMS and DEF-CHAR to temporary bind the function value of
+`read-event', thus avoiding the prompt.
+For instance, if CHAR-NUMS is the lists ((?\\s . (1 2 3)) (?u . (4))),
+then replace 3 matches of FROM with TO, and undo the last replacement.
+
+Return the last evalled form in BODY."
+ (declare (indent 5) (debug (stringp stringp stringp form characterp body)))
+ (let ((text (gensym "text"))
+ (count (gensym "count")))
+ `(let* ((,text ,input)
+ (,count 0)
+ (inhibit-message t))
+ (with-temp-buffer
+ (insert ,text)
+ (goto-char 1)
+ ;; Bind `read-event' to simulate user input.
+ ;; If `replace-tests-bind-read-string' is non-nil, then
+ ;; bind `read-string' as well.
+ (cl-letf (((symbol-function 'read-event)
+ (lambda (&rest _args)
+ (cl-incf ,count)
+ (pcase ,count ; Build the clauses from CHAR-NUMS
+ ,@(append
+ (delq nil
+ (mapcar
+ (lambda (chr)
+ (when-let (it (alist-get chr char-nums))
+ (if (cdr it)
+ `(,(cons 'or it) ,chr)
+ `(,(car it) ,chr))))
+ '(?, ?\s ?u ?U ?E ?q)))
+ `((_ ,def-chr))))))
+ ((symbol-function 'read-string)
+ (if replace-tests-bind-read-string
+ (lambda (&rest _args) replace-tests-bind-read-string)
+ (symbol-function 'read-string)))
+ ;; Emulate replace-highlight clobbering match-data via
+ ;; isearch-lazy-highlight-new-loop and sit-for (bug#36328)
+ ((symbol-function 'replace-highlight)
+ (lambda (&rest _args)
+ (string-match "[A-Z ]" "ForestGreen")))
+ ;; Override `sit-for' and `ding' so that we don't have
+ ;; to wait and listen to bells when running the test.
+ ((symbol-function 'sit-for)
+ (lambda (&rest _args) (redisplay)))
+ ((symbol-function 'ding) 'ignore))
+ (perform-replace ,from ,to t replace-tests-perform-replace-regexp-flag nil))
+ ,@body))))
+
+(defun replace-tests--query-replace-undo (&optional comma)
+ (let ((input "111"))
+ (if comma
+ (should
+ (replace-tests-with-undo
+ input "1" "2" ((?, . (2)) (?u . (3)) (?q . (4))) ?\s (buffer-string)))
+ (should
+ (replace-tests-with-undo
+ input "1" "2" ((?\s . (2)) (?u . (3)) (?q . (4))) ?\s (buffer-string))))))
(ert-deftest query-replace--undo ()
(should (string= "211" (replace-tests--query-replace-undo)))
(should (string= "211" (replace-tests--query-replace-undo 'comma))))
+(ert-deftest query-replace-undo-bug31073 ()
+ "Test for https://debbugs.gnu.org/31073 ."
+ (let ((input "aaa aaa"))
+ (should
+ (replace-tests-with-undo
+ input "a" "B" ((?\s . (1 2 3)) (?U . (4))) ?q
+ (string= input (buffer-string))))))
+
+(ert-deftest query-replace-undo-bug31492 ()
+ "Test for https://debbugs.gnu.org/31492 ."
+ (let ((input "a\nb\nc\n"))
+ (should
+ (replace-tests-with-undo
+ input "^\\|\b\\|$" "foo" ((?\s . (1 2)) (?U . (3))) ?q
+ (string= input (buffer-string))))))
+
+(ert-deftest query-replace-undo-bug31538 ()
+ "Test for https://debbugs.gnu.org/31538 ."
+ (let ((input "aaa aaa")
+ (replace-tests-bind-read-string "Bfoo"))
+ (should
+ (replace-tests-with-undo
+ input "a" "B" ((?\s . (1 2 3)) (?E . (4)) (?U . (5))) ?q
+ (string= input (buffer-string))))))
+
+(ert-deftest query-replace-undo-bug37073 ()
+ "Test for https://debbugs.gnu.org/37073 ."
+ (let ((input "theorem 1\ntheorem 2\ntheorem 3"))
+ (should
+ (replace-tests-with-undo
+ input "theorem \\([0-9]+\\)"
+ '(replace-eval-replacement
+ replace-quote
+ (format "theorem \\\\ref{theo_%d}" (1+ (string-to-number (match-string 1)))))
+ ((?\s . (1 2)) (?U . (3)))
+ ?q
+ (string= input (buffer-string)))))
+ ;; Now run a test with regexp-flag arg in `perform-replace' set to nil
+ (let ((input " ^theorem$ 1\n ^theorem$ 2\n ^theorem$ 3")
+ (replace-tests-perform-replace-regexp-flag nil)
+ (expected " theo 1\n ^theorem$ 2\n ^theorem$ 3"))
+ (should
+ (replace-tests-with-undo
+ input "^theorem$"
+ "theo"
+ ((?\s . (1 2 4)) (?U . (3)))
+ ?q
+ (string= expected (buffer-string))))))
+
+(ert-deftest query-replace-undo-bug37287 ()
+ "Test for https://debbugs.gnu.org/37287 ."
+ (let ((input "foo-1\nfoo-2\nfoo-3")
+ (expected "foo-2\nfoo-2\nfoo-3"))
+ (should
+ (replace-tests-with-undo
+ input "\\([0-9]\\)"
+ '(replace-eval-replacement
+ replace-quote
+ (format "%d" (1+ (string-to-number (match-string 1)))))
+ ((?\s . (1 2 4)) (?U . (3)))
+ ?q
+ (string= expected (buffer-string))))))
+
+(defmacro replace-tests-with-highlighted-occurrence (highlight-locus &rest body)
+ "Helper macro to test the highlight of matches when navigating occur buffer.
+
+Eval BODY with `next-error-highlight' and `next-error-highlight-no-select'
+bound to HIGHLIGHT-LOCUS."
+ (declare (indent 1) (debug (form body)))
+ `(let ((regexp "foo")
+ (next-error-highlight ,highlight-locus)
+ (next-error-highlight-no-select ,highlight-locus)
+ (buffer (generate-new-buffer "test"))
+ (inhibit-message t))
+ (unwind-protect
+ ;; Local bind to disable the deletion of `occur-highlight-overlay'
+ (cl-letf (((symbol-function 'occur-goto-locus-delete-o) (lambda ())))
+ (with-current-buffer buffer (dotimes (_ 3) (insert regexp ?\n)))
+ (pop-to-buffer buffer)
+ (occur regexp)
+ (pop-to-buffer "*Occur*")
+ (occur-next)
+ ,@body)
+ (kill-buffer buffer)
+ (kill-buffer "*Occur*"))))
+
+(ert-deftest occur-highlight-occurrence ()
+ "Test for https://debbugs.gnu.org/39121 ."
+ (let ((alist '((nil . nil) (0.5 . t) (t . t) (fringe-arrow . nil)))
+ (check-overlays
+ (lambda (has-ov)
+ (eq has-ov (not (null (overlays-in (point-min) (point-max))))))))
+ (pcase-dolist (`(,highlight-locus . ,has-overlay) alist)
+ ;; Visiting occurrences
+ (replace-tests-with-highlighted-occurrence highlight-locus
+ (occur-mode-goto-occurrence)
+ (should (funcall check-overlays has-overlay)))
+ ;; Displaying occurrences
+ (replace-tests-with-highlighted-occurrence highlight-locus
+ (occur-mode-display-occurrence)
+ (with-current-buffer (marker-buffer
+ (caar (get-text-property (point) 'occur-target)))
+ (should (funcall check-overlays has-overlay)))))))
+
+(ert-deftest replace-regexp-bug45973 ()
+ "Test for https://debbugs.gnu.org/45973 ."
+ (let ((before "1RB 1LC 1RC 1RB 1RD 0LE 1LA 1LD 1RH 0LA")
+ (after "1LB 1RC 1LC 1LB 1LD 0RE 1RA 1RD 1LH 0RA"))
+ (with-temp-buffer
+ (insert before)
+ (goto-char (point-min))
+ (with-suppressed-warnings ((interactive-only replace-regexp))
+ (replace-regexp
+ "\\(\\(L\\)\\|\\(R\\)\\)"
+ '(replace-eval-replacement
+ replace-quote
+ (if (match-string 2) "R" "L"))))
+ (should (equal (buffer-string) after)))))
+
+(ert-deftest test-count-matches ()
+ (with-temp-buffer
+ (insert "oooooooooo")
+ (goto-char (point-min))
+ (should (= (count-matches "oo") 5))
+ (should (= (count-matches "o+") 1)))
+ (with-temp-buffer
+ (insert "o\n\n\n\no\n\n")
+ (goto-char (point-min))
+ (should (= (count-matches "^$") 4))))
+
;;; replace-tests.el ends here
diff --git a/test/lisp/rot13-tests.el b/test/lisp/rot13-tests.el
index 1eae3976ef5..bbe95316660 100644
--- a/test/lisp/rot13-tests.el
+++ b/test/lisp/rot13-tests.el
@@ -1,6 +1,6 @@
;;; rot13-tests.el --- Tests for rot13.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2016-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2022 Free Software Foundation, Inc.
;; Author: Simen Heggestøyl <simenheg@gmail.com>
;; Keywords:
diff --git a/test/lisp/saveplace-resources/saveplace b/test/lisp/saveplace-resources/saveplace
new file mode 100644
index 00000000000..3f3f6d501d6
--- /dev/null
+++ b/test/lisp/saveplace-resources/saveplace
@@ -0,0 +1,4 @@
+;;; -*- coding: utf-8 -*-
+(("/home/skangas/.emacs.d/cache/recentf" . 1306)
+ ("/home/skangas/wip/emacs/"
+ (dired-filename . "/home/skangas/wip/emacs/COPYING")))
diff --git a/test/lisp/saveplace-tests.el b/test/lisp/saveplace-tests.el
new file mode 100644
index 00000000000..99318d295dd
--- /dev/null
+++ b/test/lisp/saveplace-tests.el
@@ -0,0 +1,94 @@
+;;; saveplace-tests.el --- Tests for saveplace.el -*- lexical-binding:t -*-
+
+;; Copyright (C) 2019-2022 Free Software Foundation, Inc.
+
+;; Author: Stefan Kangas <stefankangas@gmail.com>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'ert-x)
+(require 'saveplace)
+
+(ert-deftest saveplace-test-save-place-to-alist/dir ()
+ (save-place-mode)
+ (let* ((save-place-alist nil)
+ (save-place-loaded t)
+ (loc (ert-resource-directory)))
+ (save-window-excursion
+ (dired loc)
+ (save-place-to-alist)
+ (should (equal save-place-alist
+ `((,loc
+ (dired-filename . ,(concat loc "saveplace")))))))))
+
+(ert-deftest saveplace-test-save-place-to-alist/file ()
+ (save-place-mode)
+ (ert-with-temp-file tmpfile
+ (let* ((tmpfile (file-truename tmpfile))
+ (save-place-alist nil)
+ (save-place-loaded t)
+ (loc tmpfile)
+ (pos 4))
+ (save-window-excursion
+ (find-file loc)
+ (insert "abc") ; must insert something
+ (save-place-to-alist)
+ (should (equal save-place-alist (list (cons tmpfile pos))))))))
+
+(ert-deftest saveplace-test-forget-unreadable-files ()
+ (save-place-mode)
+ (ert-with-temp-file tmpfile
+ :suffix "-saveplace"
+ (let* ((save-place-loaded t)
+ (alist-orig (list (cons "/this/file/does/not/exist" 10)
+ (cons tmpfile 1917)))
+ (save-place-alist alist-orig))
+ (save-place-forget-unreadable-files)
+ (should (equal save-place-alist (cdr alist-orig))))))
+
+(ert-deftest saveplace-test-place-alist-to-file ()
+ (save-place-mode)
+ (ert-with-temp-file tmpfile
+ (ert-with-temp-file tmpfile2
+ (let* ((save-place-file tmpfile)
+ (save-place-alist (list (cons tmpfile2 99))))
+ (save-place-alist-to-file)
+ (setq save-place-alist nil)
+ (save-window-excursion
+ (find-file save-place-file)
+ (unwind-protect
+ (should (string-match tmpfile2 (buffer-string)))
+ (kill-buffer)))))))
+
+(ert-deftest saveplace-test-load-alist-from-file ()
+ (save-place-mode)
+ (let ((save-place-loaded nil)
+ (save-place-file
+ (ert-resource-file "saveplace"))
+ (save-place-alist nil))
+ (save-place-load-alist-from-file)
+ (should (equal save-place-alist
+ '(("/home/skangas/.emacs.d/cache/recentf" . 1306)
+ ("/home/skangas/wip/emacs/"
+ (dired-filename . "/home/skangas/wip/emacs/COPYING")))))))
+
+(provide 'saveplace-tests)
+;;; saveplace-tests.el ends here
diff --git a/test/lisp/scroll-lock-tests.el b/test/lisp/scroll-lock-tests.el
new file mode 100644
index 00000000000..2bad8e7d48f
--- /dev/null
+++ b/test/lisp/scroll-lock-tests.el
@@ -0,0 +1,68 @@
+;;; scroll-lock-tests.el --- Test suite for scroll-lock -*- lexical-binding: t -*-
+
+;; Copyright (C) 2019-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'scroll-lock)
+
+
+(defun point-in-window-line-p (n)
+ "Return if point is in window line N.
+Meaning of N as in `move-to-window-line'.
+Precondition: the line N must be available in the window."
+ (save-excursion
+ (let ((point (progn (beginning-of-line) (point))))
+ (let ((moved-to-line (move-to-window-line n)))
+ (cl-assert (= n moved-to-line) t "precondition violation"))
+ (= point (progn (beginning-of-line) (point))))))
+
+
+(ert-deftest scroll-lock-next-line-always-scroll-1 ()
+ "Point stays in top line."
+ (with-temp-buffer
+ (insert "\n\n\n")
+ (goto-char (point-min))
+ (switch-to-buffer (current-buffer))
+ (scroll-lock-next-line-always-scroll)
+ (should (point-in-window-line-p 0))))
+
+(ert-deftest scroll-lock-next-line-always-scroll-2 ()
+ "Point stays in second line."
+ (with-temp-buffer
+ (scroll-lock-mode)
+ (insert "\n\n\n")
+ (goto-char (1+ (point-min)))
+ (switch-to-buffer (current-buffer))
+ (scroll-lock-next-line-always-scroll)
+ (should (point-in-window-line-p 1))))
+
+(ert-deftest scroll-lock-next-line-always-scroll-3 ()
+ "Point stays in second line when scrolling beyond the number of buffer lines."
+ (with-temp-buffer
+ (scroll-lock-mode)
+ (insert (make-string 1000 ?\n))
+ (goto-char (1+ (point-min)))
+ (switch-to-buffer (current-buffer))
+ (scroll-lock-next-line-always-scroll 1234)
+ (should (point-in-window-line-p 1))))
+
+(provide 'scroll-lock-tests)
+
+;;; scroll-lock-tests.el ends here
diff --git a/test/lisp/ses-tests.el b/test/lisp/ses-tests.el
index 3194b261565..ea3f9d05d70 100644
--- a/test/lisp/ses-tests.el
+++ b/test/lisp/ses-tests.el
@@ -1,6 +1,6 @@
;;; ses-tests.el --- Tests for ses.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2015-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2022 Free Software Foundation, Inc.
;; Author: Vincent Belaïche <vincentb1@users.sourceforge.net>
@@ -22,8 +22,24 @@
;;; Code:
(require 'ert)
+(eval-when-compile (require 'ert-x))
(require 'ses)
+;; Silence byte-compiler.
+(with-suppressed-warnings ((lexical ses--cells)
+ (lexical A2)
+ (lexical A3)
+ (lexical ses--foo)
+ (lexical ses--bar)
+ (lexical B2)
+ (lexical ses--toto))
+ (defvar ses--cells)
+ (defvar A2)
+ (defvar A3)
+ (defvar ses--foo)
+ (defvar ses--bar)
+ (defvar B2)
+ (defvar ses--toto))
;; PLAIN FORMULA TESTS
;; ======================================================================
@@ -38,7 +54,7 @@ interactively."
(dolist (c '((0 0 1) (1 0 (1+ A1))))
(apply 'ses-cell-set-formula c)
(apply 'ses-calculate-cell (list (car c) (cadr c) nil)))
- (should (eq A2 2)))))
+ (should (eq (bound-and-true-p A2) 2)))))
(ert-deftest ses-tests-plain-formula ()
"Check that setting A1 to 1 and A2 to (1+ A1), makes A2 value
@@ -49,13 +65,13 @@ equal to 2. This is done using interactive calls."
(dolist (c '((0 0 1) (1 0 (1+ A1))))
(apply 'funcall-interactively 'ses-edit-cell c))
(ses-command-hook)
- (should (eq A2 2)))))
+ (should (eq (bound-and-true-p A2) 2)))))
;; PLAIN CELL RENAMING TESTS
;; ======================================================================
(ert-deftest ses-tests-lowlevel-renamed-cell ()
- "Check that renaming A1 to `foo' and setting `foo' to 1 and A2 to (1+ foo), makes A2 value equal to 2.
+ "Check that renaming A1 to `ses--foo' and setting `ses--foo' to 1 and A2 to (1+ ses--foo), makes A2 value equal to 2.
This is done using low level functions, `ses-rename-cell' is not
called but instead we use text replacement in the buffer
previously passed in text mode."
@@ -69,63 +85,63 @@ previously passed in text mode."
(text-mode)
(goto-char (point-min))
(while (re-search-forward "\\<A1\\>" nil t)
- (replace-match "foo" t t))
+ (replace-match "ses--foo" t t))
(ses-mode)
(should-not (local-variable-p 'A1))
- (should (eq foo 1))
- (should (equal (ses-cell-formula 1 0) '(ses-safe-formula (1+ foo))))
- (should (eq A2 2)))))
+ (should (eq ses--foo 1))
+ (should (equal (ses-cell-formula 1 0) '(ses-safe-formula (1+ ses--foo))))
+ (should (eq (bound-and-true-p A2) 2)))))
(ert-deftest ses-tests-renamed-cell ()
- "Check that renaming A1 to `foo' and setting `foo' to 1 and A2
-to (1+ foo), makes A2 value equal to 2."
+ "Check that renaming A1 to `ses--foo' and setting `ses--foo' to 1 and A2
+to (1+ ses--foo), makes A2 value equal to 2."
(let ((ses-initial-size '(2 . 1)))
(with-temp-buffer
(ses-mode)
- (ses-rename-cell 'foo (ses-get-cell 0 0))
- (dolist (c '((0 0 1) (1 0 (1+ foo))))
+ (ses-rename-cell 'ses--foo (ses-get-cell 0 0))
+ (dolist (c '((0 0 1) (1 0 (1+ ses--foo))))
(apply 'funcall-interactively 'ses-edit-cell c))
(ses-command-hook)
(should-not (local-variable-p 'A1))
- (should (eq foo 1))
- (should (equal (ses-cell-formula 1 0) '(1+ foo)))
- (should (eq A2 2)))))
+ (should (eq ses--foo 1))
+ (should (equal (ses-cell-formula 1 0) '(1+ ses--foo)))
+ (should (eq (bound-and-true-p A2) 2)))))
(ert-deftest ses-tests-renamed-cell-after-setting ()
"Check that setting A1 to 1 and A2 to (1+ A1), and then
-renaming A1 to `foo' makes `foo' value equal to 2."
+renaming A1 to `ses--foo' makes `ses--foo' value equal to 2."
(let ((ses-initial-size '(2 . 1)))
(with-temp-buffer
(ses-mode)
(dolist (c '((0 0 1) (1 0 (1+ A1))))
(apply 'funcall-interactively 'ses-edit-cell c))
(ses-command-hook); deferred recalc
- (ses-rename-cell 'foo (ses-get-cell 0 0))
+ (ses-rename-cell 'ses--foo (ses-get-cell 0 0))
(should-not (local-variable-p 'A1))
- (should (eq foo 1))
- (should (equal (ses-cell-formula 1 0) '(1+ foo)))
- (should (eq A2 2)))))
+ (should (eq ses--foo 1))
+ (should (equal (ses-cell-formula 1 0) '(1+ ses--foo)))
+ (should (eq (bound-and-true-p A2) 2)))))
(ert-deftest ses-tests-renaming-cell-with-one-symbol-formula ()
"Check that setting A1 to 1 and A2 to A1, and then renaming A1
-to `foo' makes `foo' value equal to 1. Then set A1 to 2 and check
-that `foo' becomes 2."
+to `ses--foo' makes `ses--foo' value equal to 1. Then set A1 to 2 and check
+that `ses--foo' becomes 2."
(let ((ses-initial-size '(3 . 1)))
(with-temp-buffer
(ses-mode)
(dolist (c '((0 0 1) (1 0 A1)))
(apply 'funcall-interactively 'ses-edit-cell c))
(ses-command-hook); deferred recalc
- (ses-rename-cell 'foo (ses-get-cell 0 0))
+ (ses-rename-cell 'ses--foo (ses-get-cell 0 0))
(ses-command-hook); deferred recalc
(should-not (local-variable-p 'A1))
- (should (eq foo 1))
- (should (equal (ses-cell-formula 1 0) 'foo))
- (should (eq A2 1))
+ (should (eq ses--foo 1))
+ (should (equal (ses-cell-formula 1 0) 'ses--foo))
+ (should (eq (bound-and-true-p A2) 1))
(funcall-interactively 'ses-edit-cell 0 0 2)
(ses-command-hook); deferred recalc
- (should (eq A2 2))
- (should (eq foo 2)))))
+ (should (eq (bound-and-true-p A2) 2))
+ (should (eq ses--foo 2)))))
;; ROW INSERTION TESTS
@@ -144,32 +160,87 @@ to A2 and inserting a row, makes A2 value empty, and A3 equal to
(ses-jump 'A2)
(ses-insert-row 1)
(ses-command-hook)
- (should-not A2)
- (should (eq A3 2)))))
+ (should-not (bound-and-true-p A2))
+ (should (eq (bound-and-true-p A3) 2)))))
-; (defvar ses-tests-trigger nil)
(ert-deftest ses-tests-renamed-cells-row-insertion ()
- "Check that setting A1 to 1 and A2 to (1+ A1), and then renaming A1 to `foo' and A2 to `bar' jumping
-to `bar' and inserting a row, makes A2 value empty, and `bar' equal to
+ "Check that setting A1 to 1 and A2 to (1+ A1), and then renaming A1 to `ses--foo' and A2 to `ses--bar' jumping
+to `ses--bar' and inserting a row, makes A2 value empty, and `ses--bar' equal to
2."
- (setq ses-tests-trigger nil)
(let ((ses-initial-size '(2 . 1)))
(with-temp-buffer
(ses-mode)
(dolist (c '((0 0 1) (1 0 (1+ A1))))
(apply 'funcall-interactively 'ses-edit-cell c))
(ses-command-hook)
- (ses-rename-cell 'foo (ses-get-cell 0 0))
+ (ses-rename-cell 'ses--foo (ses-get-cell 0 0))
(ses-command-hook)
- (ses-rename-cell 'bar (ses-get-cell 1 0))
+ (ses-rename-cell 'ses--bar (ses-get-cell 1 0))
(ses-command-hook)
- (should (eq bar 2))
- (ses-jump 'bar)
+ (should (eq ses--bar 2))
+ (ses-jump 'ses--bar)
(ses-insert-row 1)
(ses-command-hook)
- (should-not A2)
- (should (eq bar 2)))))
+ (should-not (bound-and-true-p A2))
+ (should (eq ses--bar 2)))))
+;; JUMP tests
+;; ======================================================================
+(ert-deftest ses-jump-B2-prefix-arg ()
+ "Test jumping to cell B2 by use of prefix argument"
+ (let ((ses-initial-size '(3 . 3))
+ ses-after-entry-functions)
+ (with-temp-buffer
+ (ses-mode)
+ ;; C-u 4 M-x ses-jump
+ (let ((current-prefix-arg 4))
+ (call-interactively 'ses-jump))
+ (should (eq (ses--cell-at-pos (point)) 'B2)))))
+
+
+(ert-deftest ses-jump-B2-lowcase ()
+ "Test jumping to cell B2 by use of lowcase cell name string"
+ (let ((ses-initial-size '(3 . 3))
+ ses-after-entry-functions)
+ (with-temp-buffer
+ (ses-mode)
+ (funcall-interactively 'ses-jump "b2")
+ (ses-command-hook)
+ (should (eq (ses--cell-at-pos (point)) 'B2)))))
+
+(ert-deftest ses-jump-B2-lowcase-keys ()
+ "Test jumping to cell B2 by use of lowcase cell name string with simulating keys"
+ (let ((ses-initial-size '(3 . 3))
+ ses-after-entry-functions)
+ (with-temp-buffer
+ (ses-mode)
+ (ert-simulate-keys [ ?b ?2 return] (ses-jump))
+ (ses-command-hook)
+ (should (eq (ses--cell-at-pos (point)) 'B2)))))
+
+(ert-deftest ses-jump-B2-symbol ()
+ "Test jumping to cell B2 by use of cell name symbol"
+ (let ((ses-initial-size '(3 . 3))
+ ses-after-entry-functions)
+ (with-temp-buffer
+ (ses-mode)
+ (funcall-interactively 'ses-jump 'B2)
+ (ses-command-hook)
+ (should (eq (ses--cell-at-pos (point)) 'B2)))))
+
+(ert-deftest ses-jump-B2-renamed ()
+ "Test jumping to cell B2 after renaming it `ses--toto'."
+ (let ((ses-initial-size '(3 . 3))
+ ses-after-entry-functions)
+ (with-temp-buffer
+ (ses-mode)
+ (ses-rename-cell 'ses--toto (ses-get-cell 1 1))
+ (ses-jump 'ses--toto)
+ (ses-command-hook)
+ (should (eq (ses--cell-at-pos (point)) 'ses--toto)))))
+
(provide 'ses-tests)
+
+;;; ses-tests.el ends here
diff --git a/test/lisp/shadowfile-tests.el b/test/lisp/shadowfile-tests.el
new file mode 100644
index 00000000000..0916f7ce688
--- /dev/null
+++ b/test/lisp/shadowfile-tests.el
@@ -0,0 +1,947 @@
+;;; shadowfile-tests.el --- Tests of shadowfile -*- lexical-binding:t -*-
+
+;; Copyright (C) 2018-2022 Free Software Foundation, Inc.
+
+;; Author: Michael Albinus <michael.albinus@gmx.de>
+
+;; This file is part of GNU Emacs.
+;;
+;; GNU Emacs is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; GNU Emacs is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Some of the tests require access to a remote host files. Since
+;; this could be problematic, a mock-up connection method "mock" is
+;; used. Emulating a remote connection, it simply calls "sh -i".
+;; Tramp's file name handlers still run, so this test is sufficient
+;; except for connection establishing.
+
+;; If you want to test a real Tramp connection, set
+;; $REMOTE_TEMPORARY_FILE_DIRECTORY to a suitable value in order to
+;; overwrite the default value. If you want to skip tests accessing a
+;; remote host, set this environment variable to "/dev/null" or
+;; whatever is appropriate on your system.
+
+;; A whole test run can be performed calling the command `shadowfile-test-all'.
+
+;;; Code:
+
+(require 'tramp)
+(require 'ert-x)
+(require 'shadowfile)
+
+(setq auth-source-save-behavior nil
+ password-cache-expiry nil
+ shadow-debug (or (getenv "EMACS_HYDRA_CI") (getenv "EMACS_EMBA_CI"))
+ ;; When the remote user id is 0, Tramp refuses unsafe temporary files.
+ tramp-allow-unsafe-temporary-files
+ (or tramp-allow-unsafe-temporary-files noninteractive)
+ tramp-cache-read-persistent-data t ;; For auth-sources.
+ tramp-persistency-file-name nil
+ tramp-verbose 0
+ ;; On macOS, `temporary-file-directory' is a symlinked directory.
+ temporary-file-directory (file-truename temporary-file-directory)
+ ert-remote-temporary-file-directory
+ (ignore-errors (file-truename ert-remote-temporary-file-directory)))
+
+(defconst shadow-test-info-file
+ (expand-file-name "shadows_test" temporary-file-directory)
+ "File to keep shadow information in during tests.")
+
+(defconst shadow-test-todo-file
+ (expand-file-name "shadow_todo_test" temporary-file-directory)
+ "File to store the list of uncopied shadows in during tests.")
+
+(defun shadow--tests-cleanup ()
+ "Reset all `shadowfile' internals."
+ ;; Cleanup Tramp.
+ (tramp-cleanup-connection
+ (tramp-dissect-file-name ert-remote-temporary-file-directory) t t)
+ ;; Delete auto-saved files.
+ (with-current-buffer (find-file-noselect shadow-info-file 'nowarn)
+ (ignore-errors (delete-file (make-auto-save-file-name)))
+ (set-buffer-modified-p nil)
+ (kill-buffer))
+ (with-current-buffer (find-file-noselect shadow-todo-file 'nowarn)
+ (ignore-errors (delete-file (make-auto-save-file-name)))
+ (set-buffer-modified-p nil)
+ (kill-buffer))
+ ;; Delete buffers.
+ (ignore-errors
+ (with-current-buffer shadow-info-buffer
+ (set-buffer-modified-p nil)
+ (kill-buffer)))
+ (ignore-errors
+ (with-current-buffer shadow-todo-buffer
+ (set-buffer-modified-p nil)
+ (kill-buffer)))
+ ;; Delete files.
+ (ignore-errors (delete-file shadow-info-file))
+ (ignore-errors (delete-file shadow-todo-file))
+ ;; Reset variables.
+ (shadow-invalidate-hashtable)
+ (setq shadow-info-buffer nil
+ shadow-todo-buffer nil
+ shadow-files-to-copy nil))
+
+(ert-deftest shadow-test00-clusters ()
+ "Check cluster definitions.
+Per definition, all files are identical on the different hosts of
+a cluster (or site). This is not tested here; it must be
+guaranteed by the originator of a cluster definition."
+ :tags '(:expensive-test)
+ (skip-unless (not (memq system-type '(windows-nt ms-dos))))
+ (skip-unless (file-remote-p ert-remote-temporary-file-directory))
+
+ (let ((text-quoting-style 'grave) ;; We inspect the *Messages* buffer!
+ (inhibit-message t)
+ (shadow-info-file shadow-test-info-file)
+ (shadow-todo-file shadow-test-todo-file)
+ shadow-clusters
+ cluster primary regexp mocked-input)
+ (unwind-protect
+ ;; We must mock `read-from-minibuffer' and `read-string', in
+ ;; order to avoid interactive arguments.
+ (cl-letf* (((symbol-function #'read-from-minibuffer)
+ (lambda (&rest _args) (pop mocked-input)))
+ ((symbol-function #'read-string)
+ (lambda (&rest _args) (pop mocked-input))))
+
+ ;; Cleanup & initialize.
+ (shadow--tests-cleanup)
+ (shadow-initialize)
+
+ ;; Define a cluster.
+ (setq cluster "cluster"
+ primary shadow-system-name
+ regexp (shadow-regexp-superquote primary)
+ mocked-input `(,cluster ,primary ,regexp))
+ (call-interactively #'shadow-define-cluster)
+ (should
+ (string-equal
+ (shadow-cluster-name (shadow-get-cluster cluster)) cluster))
+ (should
+ (string-equal
+ (shadow-cluster-primary (shadow-get-cluster cluster)) primary))
+ (should
+ (string-equal
+ (shadow-cluster-regexp (shadow-get-cluster cluster)) regexp))
+ (should-not (shadow-get-cluster "non-existent-cluster-name"))
+
+ ;; Test `shadow-set-cluster' and `make-shadow-cluster'.
+ (shadow-set-cluster cluster primary regexp)
+ (should
+ (equal (shadow-get-cluster cluster)
+ (make-shadow-cluster
+ :name cluster :primary primary :regexp regexp)))
+
+ ;; The primary must be either `shadow-system-name', or a remote file.
+ (setq ;; The second "cluster" is wrong.
+ mocked-input `(,cluster ,cluster ,primary ,regexp))
+ (with-current-buffer (messages-buffer)
+ (narrow-to-region (point-max) (point-max)))
+ (call-interactively #'shadow-define-cluster)
+ (should
+ (string-match
+ (regexp-quote "Not a valid primary!")
+ (with-current-buffer (messages-buffer) (buffer-string))))
+ ;; The first cluster definition is still valid.
+ (should
+ (string-equal
+ (shadow-cluster-name (shadow-get-cluster cluster)) cluster))
+ (should
+ (string-equal
+ (shadow-cluster-primary (shadow-get-cluster cluster)) primary))
+ (should
+ (string-equal
+ (shadow-cluster-regexp (shadow-get-cluster cluster)) regexp))
+
+ ;; The regexp must match the primary name.
+ (setq ;; The second "cluster" is wrong.
+ mocked-input `(,cluster ,primary ,cluster ,regexp))
+ (with-current-buffer (messages-buffer)
+ (narrow-to-region (point-max) (point-max)))
+ (call-interactively #'shadow-define-cluster)
+ (should
+ (string-match
+ (regexp-quote "Regexp doesn't include the primary host!")
+ (with-current-buffer (messages-buffer) (buffer-string))))
+ ;; The first cluster definition is still valid.
+ (should
+ (string-equal
+ (shadow-cluster-name (shadow-get-cluster cluster)) cluster))
+ (should
+ (string-equal
+ (shadow-cluster-primary (shadow-get-cluster cluster)) primary))
+ (should
+ (string-equal
+ (shadow-cluster-regexp (shadow-get-cluster cluster)) regexp))
+
+ ;; Redefine the cluster.
+ (setq primary (file-remote-p ert-remote-temporary-file-directory)
+ regexp (shadow-regexp-superquote primary)
+ mocked-input `(,cluster ,primary ,regexp))
+ (call-interactively #'shadow-define-cluster)
+ (should
+ (string-equal
+ (shadow-cluster-name (shadow-get-cluster cluster)) cluster))
+ (should
+ (string-equal
+ (shadow-cluster-primary (shadow-get-cluster cluster)) primary))
+ (should
+ (string-equal
+ (shadow-cluster-regexp (shadow-get-cluster cluster)) regexp))
+
+ ;; Test `shadow-set-cluster' and `make-shadow-cluster'.
+ (shadow-set-cluster cluster primary regexp)
+ (should
+ (equal (shadow-get-cluster cluster)
+ (make-shadow-cluster
+ :name cluster :primary primary :regexp regexp))))
+
+ ;; Cleanup.
+ (with-current-buffer (messages-buffer) (widen))
+ (shadow--tests-cleanup))))
+
+(ert-deftest shadow-test01-sites ()
+ "Check site definitions.
+Per definition, all files are identical on the different hosts of
+a cluster (or site). This is not tested here; it must be
+guaranteed by the originator of a cluster definition."
+ (skip-unless (not (memq system-type '(windows-nt ms-dos))))
+ (skip-unless (file-remote-p ert-remote-temporary-file-directory))
+
+ (let ((shadow-info-file shadow-test-info-file)
+ (shadow-todo-file shadow-test-todo-file)
+ shadow-clusters
+ cluster1 cluster2 primary1 primary2 regexp1 regexp2 mocked-input)
+ (unwind-protect
+ ;; We must mock `read-from-minibuffer' and `read-string', in
+ ;; order to avoid interactive arguments.
+ (cl-letf* (((symbol-function #'read-from-minibuffer)
+ (lambda (&rest _args) (pop mocked-input)))
+ ((symbol-function #'read-string)
+ (lambda (&rest _args) (pop mocked-input))))
+
+ ;; Cleanup & initialize.
+ (shadow--tests-cleanup)
+ (shadow-initialize)
+
+ ;; Define a cluster.
+ (setq cluster1 "cluster1"
+ primary1 shadow-system-name
+ regexp1 (shadow-regexp-superquote primary1))
+ (shadow-set-cluster cluster1 primary1 regexp1)
+
+ ;; A site is either a cluster identification, or a primary host.
+ (should (string-equal cluster1 (shadow-site-name cluster1)))
+ (should (string-equal primary1 (shadow-name-site primary1)))
+ (should
+ (string-equal (format "/%s:" cluster1) (shadow-name-site cluster1)))
+ (should (string-equal (system-name) (shadow-site-name primary1)))
+ (should
+ (string-equal
+ (file-remote-p ert-remote-temporary-file-directory)
+ (shadow-name-site
+ (file-remote-p ert-remote-temporary-file-directory))))
+ (should
+ (string-equal
+ (file-remote-p ert-remote-temporary-file-directory)
+ (shadow-site-name
+ (file-remote-p ert-remote-temporary-file-directory))))
+
+ (should (equal (shadow-site-cluster cluster1)
+ (shadow-get-cluster cluster1)))
+ (should (equal (shadow-site-cluster (shadow-name-site cluster1))
+ (shadow-get-cluster cluster1)))
+ (should (equal (shadow-site-cluster primary1)
+ (shadow-get-cluster cluster1)))
+ (should (equal (shadow-site-cluster (shadow-site-name primary1))
+ (shadow-get-cluster cluster1)))
+ (should (string-equal (shadow-site-primary cluster1) primary1))
+ (should (string-equal (shadow-site-primary primary1) primary1))
+
+ ;; `shadow-read-site' accepts "cluster", "/cluster:",
+ ;; "system", "/system:". It shall reject bad site names.
+ (setq mocked-input
+ `(,cluster1 ,(shadow-name-site cluster1)
+ ,primary1 ,(shadow-site-name primary1)
+ ,shadow-system-name "" "bad" "/bad:"))
+ (should (string-equal (shadow-read-site) cluster1))
+ (should (string-equal (shadow-read-site) (shadow-name-site cluster1)))
+ (should (string-equal (shadow-read-site) primary1))
+ (should (string-equal (shadow-read-site) (shadow-site-name primary1)))
+ (should (string-equal (shadow-read-site) shadow-system-name))
+ (should-not (shadow-read-site)) ; ""
+ (should-not (shadow-read-site)) ; "bad"
+ (should-not (shadow-read-site)) ; "/bad:"
+ (should-error (shadow-read-site)) ; no input at all
+
+ ;; Define a second cluster.
+ (setq cluster2 "cluster2"
+ primary2 (file-remote-p ert-remote-temporary-file-directory)
+ regexp2 (format "^\\(%s\\|%s\\)$" shadow-system-name primary2))
+ (shadow-set-cluster cluster2 primary2 regexp2)
+
+ ;; `shadow-site-match' shall know all different kind of site names.
+ (should (shadow-site-match cluster1 cluster1))
+ (should (shadow-site-match primary1 primary1))
+ (should (shadow-site-match cluster1 primary1))
+ (should (shadow-site-match primary1 cluster1))
+ (should (shadow-site-match cluster2 cluster2))
+ (should (shadow-site-match primary2 primary2))
+ (should (shadow-site-match cluster2 primary2))
+ (should (shadow-site-match primary2 cluster2))
+
+ ;; The regexp of `cluster2' matches the primary of
+ ;; `cluster1'. Not vice versa.
+ (should (shadow-site-match cluster2 cluster1))
+ (should-not (shadow-site-match cluster1 cluster2))
+
+ ;; If we use the primaries of a cluster, it doesn't match.
+ (should-not
+ (shadow-site-match (shadow-site-primary cluster2) cluster1))
+ (should-not
+ (shadow-site-match (shadow-site-primary cluster1) cluster2)))
+
+ ;; Cleanup.
+ (shadow--tests-cleanup))))
+
+(ert-deftest shadow-test02-files ()
+ "Check file manipulation functions."
+ (skip-unless (not (memq system-type '(windows-nt ms-dos))))
+ (skip-unless (file-remote-p ert-remote-temporary-file-directory))
+
+ (let ((shadow-info-file shadow-test-info-file)
+ (shadow-todo-file shadow-test-todo-file)
+ shadow-clusters
+ cluster primary regexp file hup)
+ (unwind-protect
+ (progn
+
+ ;; Cleanup & initialize.
+ (shadow--tests-cleanup)
+ (shadow-initialize)
+
+ ;; Define a cluster.
+ (setq cluster "cluster"
+ primary shadow-system-name
+ regexp (shadow-regexp-superquote primary)
+ file (make-temp-name
+ (expand-file-name
+ "shadowfile-tests" temporary-file-directory)))
+ (shadow-set-cluster cluster primary regexp)
+
+ ;; The constant structure to compare with.
+ (setq hup (make-tramp-file-name :host (system-name) :localname file))
+
+ ;; The structure a local file is transformed in.
+ (should (equal (shadow-parse-name file) hup))
+ (should (equal (shadow-parse-name (concat "/" cluster ":" file)) hup))
+ (should (equal (shadow-parse-name (concat primary file)) hup))
+
+ ;; A local file name is kept.
+ (should
+ (string-equal (shadow-local-file file) file))
+ ;; A file on this cluster is also local.
+ (should
+ (string-equal
+ (shadow-local-file (concat "/" cluster ":" file)) file))
+ ;; A file on the primary host is also local.
+ (should
+ (string-equal (shadow-local-file (concat primary file)) file))
+
+ ;; Redefine the cluster.
+ (setq primary (file-remote-p ert-remote-temporary-file-directory)
+ regexp (shadow-regexp-superquote primary))
+ (shadow-set-cluster cluster primary regexp)
+
+ ;; The structure of the local file is still the same.
+ (should (equal (shadow-parse-name file) hup))
+ ;; The cluster name must be used.
+ (setf (tramp-file-name-host hup) cluster)
+ (should (equal (shadow-parse-name (concat "/" cluster ":" file)) hup))
+ ;; The structure of a remote file is different.
+ (should
+ (equal (shadow-parse-name (concat primary file))
+ (tramp-dissect-file-name (concat primary file))))
+
+ ;; A local file is still local.
+ (should (shadow-local-file file))
+ ;; A file on this cluster is not local.
+ (should-not (shadow-local-file (concat "/" cluster ":" file)))
+ ;; A file on the primary host is not local.
+ (should-not (shadow-local-file (concat primary file)))
+ ;; There's no error on wrong FILE.
+ (should-not (shadow-local-file nil)))
+
+ ;; Cleanup.
+ (shadow--tests-cleanup))))
+
+(ert-deftest shadow-test03-expand-cluster-in-file-name ()
+ "Check canonical file name of a cluster or site."
+ (skip-unless (not (memq system-type '(windows-nt ms-dos))))
+ (skip-unless (file-remote-p ert-remote-temporary-file-directory))
+
+ (let ((shadow-info-file shadow-test-info-file)
+ (shadow-todo-file shadow-test-todo-file)
+ shadow-clusters
+ cluster primary regexp file1 file2)
+ (unwind-protect
+ (progn
+
+ ;; Cleanup & initialize.
+ (shadow--tests-cleanup)
+ (shadow-initialize)
+
+ ;; Define a cluster.
+ (setq cluster "cluster"
+ primary shadow-system-name
+ regexp (shadow-regexp-superquote primary))
+ (shadow-set-cluster cluster primary regexp)
+
+ (setq file1
+ (make-temp-name
+ (expand-file-name "shadowfile-tests" temporary-file-directory))
+ file2
+ (make-temp-name
+ (expand-file-name
+ "shadowfile-tests" ert-remote-temporary-file-directory)))
+
+ ;; A local file name is kept.
+ (should
+ (string-equal (shadow-expand-cluster-in-file-name file1) file1))
+ ;; A remote file is kept.
+ (should
+ (string-equal (shadow-expand-cluster-in-file-name file2) file2))
+ ;; A cluster name is expanded to the primary name.
+ (should
+ (string-equal
+ (shadow-expand-cluster-in-file-name (format "/%s:%s" cluster file1))
+ (shadow-expand-cluster-in-file-name (concat primary file1))))
+ ;; A primary name is expanded if it is a local file name.
+ (should
+ (string-equal
+ (shadow-expand-cluster-in-file-name (concat primary file1)) file1))
+
+ ;; Redefine the cluster.
+ (setq primary (file-remote-p ert-remote-temporary-file-directory)
+ regexp (shadow-regexp-superquote primary))
+ (shadow-set-cluster cluster primary regexp)
+
+ ;; A cluster name is expanded to the primary name.
+ (should
+ (string-equal
+ (shadow-expand-cluster-in-file-name (format "/%s:%s" cluster file1))
+ (shadow-expand-cluster-in-file-name (concat primary file1))))
+ ;; A primary name is not expanded if it isn't is a local file name.
+ (should
+ (string-equal
+ (shadow-expand-cluster-in-file-name (concat primary file1))
+ (concat primary file1))))
+
+ ;; Cleanup.
+ (shadow--tests-cleanup))))
+
+(ert-deftest shadow-test04-contract-file-name ()
+ "Check canonical file name of a cluster or site."
+ (skip-unless (not (memq system-type '(windows-nt ms-dos))))
+ (skip-unless (file-remote-p ert-remote-temporary-file-directory))
+
+ (let ((shadow-info-file shadow-test-info-file)
+ (shadow-todo-file shadow-test-todo-file)
+ shadow-clusters
+ cluster primary regexp file)
+ (unwind-protect
+ (progn
+
+ ;; Cleanup & initialize.
+ (shadow--tests-cleanup)
+ (shadow-initialize)
+
+ ;; Define a cluster.
+ (setq cluster "cluster"
+ primary shadow-system-name
+ regexp (shadow-regexp-superquote primary)
+ file (make-temp-name
+ (expand-file-name
+ "shadowfile-tests" temporary-file-directory)))
+ (shadow-set-cluster cluster primary regexp)
+
+ ;; The cluster name is prepended for local files.
+ (should
+ (string-equal
+ (shadow-contract-file-name file) (concat "/cluster:" file)))
+ ;; A cluster file name is preserved.
+ (should
+ (string-equal
+ (shadow-contract-file-name (concat "/cluster:" file))
+ (concat "/cluster:" file)))
+ ;; `shadow-system-name' is mapped to the cluster.
+ (should
+ (string-equal
+ (shadow-contract-file-name (concat shadow-system-name file))
+ (concat "/cluster:" file)))
+
+ ;; Redefine the cluster.
+ (setq primary (file-remote-p ert-remote-temporary-file-directory)
+ regexp (shadow-regexp-superquote primary))
+ (shadow-set-cluster cluster primary regexp)
+
+ ;; A remote file name is mapped to the cluster.
+ (should
+ (string-equal
+ (shadow-contract-file-name
+ (concat (file-remote-p ert-remote-temporary-file-directory) file))
+ (concat "/cluster:" file))))
+
+ ;; Cleanup.
+ (shadow--tests-cleanup))))
+
+(ert-deftest shadow-test05-file-match ()
+ "Check `shadow-same-site' and `shadow-file-match'."
+ (skip-unless (not (memq system-type '(windows-nt ms-dos))))
+ (skip-unless (file-remote-p ert-remote-temporary-file-directory))
+
+ (let ((shadow-info-file shadow-test-info-file)
+ (shadow-todo-file shadow-test-todo-file)
+ shadow-clusters
+ cluster primary regexp file)
+ (unwind-protect
+ (progn
+
+ ;; Cleanup & initialize.
+ (shadow--tests-cleanup)
+ (shadow-initialize)
+
+ ;; Define a cluster.
+ (setq cluster "cluster"
+ primary shadow-system-name
+ regexp (shadow-regexp-superquote primary)
+ file (make-temp-name
+ (expand-file-name
+ "shadowfile-tests" temporary-file-directory)))
+ (shadow-set-cluster cluster primary regexp)
+
+ (should (shadow-same-site (shadow-parse-name "/cluster:") file))
+ (should
+ (shadow-same-site (shadow-parse-name shadow-system-name) file))
+ (should (shadow-same-site (shadow-parse-name file) file))
+
+ (should
+ (shadow-file-match
+ (shadow-parse-name (concat "/cluster:" file)) file))
+ (should
+ (shadow-file-match
+ (shadow-parse-name (concat shadow-system-name file)) file))
+ (should (shadow-file-match (shadow-parse-name file) file))
+
+ ;; Redefine the cluster.
+ (setq primary (file-remote-p ert-remote-temporary-file-directory)
+ regexp (shadow-regexp-superquote primary))
+ (shadow-set-cluster cluster primary regexp)
+
+ (should
+ (shadow-file-match
+ (shadow-parse-name
+ (concat (file-remote-p ert-remote-temporary-file-directory) file))
+ file)))
+
+ ;; Cleanup.
+ (shadow--tests-cleanup))))
+
+(ert-deftest shadow-test06-literal-groups ()
+ "Check literal group definitions."
+ (skip-unless (not (memq system-type '(windows-nt ms-dos))))
+ (skip-unless (file-remote-p ert-remote-temporary-file-directory))
+
+ (let ((shadow-info-file shadow-test-info-file)
+ (shadow-todo-file shadow-test-todo-file)
+ shadow-clusters shadow-literal-groups
+ cluster1 cluster2 primary regexp file1 file2 mocked-input)
+ (unwind-protect
+ ;; We must mock `read-from-minibuffer' and `read-string', in
+ ;; order to avoid interactive arguments.
+ (cl-letf* (((symbol-function #'read-from-minibuffer)
+ (lambda (&rest _args) (pop mocked-input)))
+ ((symbol-function #'read-string)
+ (lambda (&rest _args) (pop mocked-input))))
+
+ ;; Cleanup & initialize.
+ (shadow--tests-cleanup)
+ (shadow-initialize)
+
+ ;; Define clusters.
+ (setq cluster1 "cluster1"
+ primary shadow-system-name
+ regexp (shadow-regexp-superquote primary))
+ (shadow-set-cluster cluster1 primary regexp)
+
+ (setq cluster2 "cluster2"
+ primary (file-remote-p ert-remote-temporary-file-directory)
+ regexp (format "^\\(%s\\|%s\\)$" shadow-system-name primary))
+ (shadow-set-cluster cluster2 primary regexp)
+
+ ;; Define a literal group.
+ (setq file1
+ (make-temp-name
+ (expand-file-name "shadowfile-tests" temporary-file-directory))
+ file2
+ (make-temp-name
+ (expand-file-name
+ "shadowfile-tests" ert-remote-temporary-file-directory))
+ mocked-input
+ `(,cluster1 ,file1 ,cluster2 ,file2
+ ,primary ,file1 ,(kbd "RET")))
+ (with-temp-buffer
+ (set-visited-file-name file1)
+ (call-interactively #'shadow-define-literal-group)
+ (set-buffer-modified-p nil))
+
+ ;; `shadow-literal-groups' is a list of lists.
+ (should (consp shadow-literal-groups))
+ (should (consp (car shadow-literal-groups)))
+ (should-not (cdr shadow-literal-groups))
+
+ (should (member (format "/%s:%s" cluster1 (file-local-name file1))
+ (car shadow-literal-groups)))
+ (should (member (format "/%s:%s" cluster2 (file-local-name file2))
+ (car shadow-literal-groups)))
+ ;; Bug#49596.
+ (should (member (concat primary file1) (car shadow-literal-groups)))
+
+ ;; Error handling.
+ (setq shadow-literal-groups nil)
+ ;; There's no `buffer-file-name'.
+ (with-temp-buffer
+ (call-interactively #'shadow-define-literal-group)
+ (set-buffer-modified-p nil))
+ (should-not shadow-literal-groups)
+ ;; Define an empty literal group.
+ (setq mocked-input `(,(kbd "RET")))
+ (with-temp-buffer
+ (set-visited-file-name file1)
+ (call-interactively #'shadow-define-literal-group)
+ (set-buffer-modified-p nil))
+ (should-not shadow-literal-groups)
+ ;; Use a non-existing site name.
+ (setq mocked-input `("foo" ,(kbd "RET")))
+ (with-temp-buffer
+ (set-visited-file-name file1)
+ (call-interactively #'shadow-define-literal-group)
+ (set-buffer-modified-p nil))
+ (should-not shadow-literal-groups))
+
+ ;; Cleanup.
+ (shadow--tests-cleanup))))
+
+(ert-deftest shadow-test07-regexp-groups ()
+ "Check regexp group definitions."
+ (skip-unless (not (memq system-type '(windows-nt ms-dos))))
+ (skip-unless (file-remote-p ert-remote-temporary-file-directory))
+
+ (let ((shadow-info-file shadow-test-info-file)
+ (shadow-todo-file shadow-test-todo-file)
+ shadow-clusters shadow-regexp-groups
+ cluster1 cluster2 primary regexp file mocked-input)
+ (unwind-protect
+ ;; We must mock `read-from-minibuffer' and `read-string', in
+ ;; order to avoid interactive arguments.
+ (cl-letf* (((symbol-function #'read-from-minibuffer)
+ (lambda (&rest _args) (pop mocked-input)))
+ ((symbol-function #'read-string)
+ (lambda (&rest _args) (pop mocked-input))))
+
+ ;; Cleanup & initialize.
+ (shadow--tests-cleanup)
+ (shadow-initialize)
+
+ ;; Define clusters.
+ (setq cluster1 "cluster1"
+ primary shadow-system-name
+ regexp (shadow-regexp-superquote primary))
+ (shadow-set-cluster cluster1 primary regexp)
+
+ (setq cluster2 "cluster2"
+ primary (file-remote-p ert-remote-temporary-file-directory)
+ regexp (format "^\\(%s\\|%s\\)$" shadow-system-name primary))
+ (shadow-set-cluster cluster2 primary regexp)
+
+ ;; Define a regexp group.
+ (setq file
+ (make-temp-name
+ (expand-file-name "shadowfile-tests" temporary-file-directory))
+ mocked-input `(,(shadow-regexp-superquote file)
+ ,cluster1 ,cluster2 ,(kbd "RET")))
+ (with-temp-buffer
+ (set-visited-file-name nil)
+ (call-interactively #'shadow-define-regexp-group)
+ (set-buffer-modified-p nil))
+
+ ;; `shadow-regexp-groups' is a list of lists.
+ (should (consp shadow-regexp-groups))
+ (should (consp (car shadow-regexp-groups)))
+ (should-not (cdr shadow-regexp-groups))
+
+ (should
+ (member
+ (concat
+ (shadow-site-primary cluster1) (shadow-regexp-superquote file))
+ (car shadow-regexp-groups)))
+ (should
+ (member
+ (concat
+ (shadow-site-primary cluster2) (shadow-regexp-superquote file))
+ (car shadow-regexp-groups))))
+
+ ;; Cleanup.
+ (shadow--tests-cleanup))))
+
+(ert-deftest shadow-test08-shadow-todo ()
+ "Check that needed shadows are added to todo."
+ (skip-unless (not (memq system-type '(windows-nt ms-dos))))
+ (skip-unless (file-remote-p ert-remote-temporary-file-directory))
+ (skip-unless (file-writable-p ert-remote-temporary-file-directory))
+
+ (let ((backup-inhibited t)
+ create-lockfiles
+ (shadow-info-file shadow-test-info-file)
+ (shadow-todo-file shadow-test-todo-file)
+ (shadow-inhibit-message t)
+ shadow-clusters shadow-literal-groups shadow-regexp-groups
+ shadow-files-to-copy
+ cluster1 cluster2 primary regexp file)
+ (unwind-protect
+ (progn
+
+ ;; Cleanup & initialize.
+ (shadow--tests-cleanup)
+ (shadow-initialize)
+ (when shadow-debug
+ (message
+ "%s %s %s %s %s"
+ temporary-file-directory
+ ert-remote-temporary-file-directory
+ shadow-homedir shadow-info-file shadow-todo-file))
+
+ ;; Define clusters.
+ (setq cluster1 "cluster1"
+ primary shadow-system-name
+ regexp (shadow-regexp-superquote primary))
+ (shadow-set-cluster cluster1 primary regexp)
+ (when shadow-debug
+ (message
+ "shadow-test08-shadow-todo: %s %s %s %s"
+ cluster1 primary regexp shadow-clusters))
+
+ (setq cluster2 "cluster2"
+ primary (file-remote-p ert-remote-temporary-file-directory)
+ regexp (shadow-regexp-superquote primary))
+ (shadow-set-cluster cluster2 primary regexp)
+ (when shadow-debug
+ (message
+ "shadow-test08-shadow-todo: %s %s %s %s"
+ cluster2 primary regexp shadow-clusters))
+
+ ;; Define a literal group.
+ (setq file
+ (make-temp-name
+ (expand-file-name "shadowfile-tests" temporary-file-directory))
+ shadow-literal-groups
+ `((,(concat "/cluster1:" file) ,(concat "/cluster2:" file))))
+ (when shadow-debug
+ (message
+ "shadow-test08-shadow-todo: %s %s" file shadow-literal-groups))
+
+ ;; Save file from "cluster1" definition.
+ (with-temp-buffer
+ (set-visited-file-name file)
+ (insert "foo")
+ (save-buffer))
+ (when shadow-debug
+ (message
+ "shadow-test08-shadow-todo: %s %s"
+ (cons file (shadow-contract-file-name (concat "/cluster2:" file)))
+ shadow-files-to-copy))
+ (should
+ (member
+ (cons file (shadow-contract-file-name (concat "/cluster2:" file)))
+ shadow-files-to-copy))
+
+ ;; Save file from "cluster2" definition.
+ (with-temp-buffer
+ (set-visited-file-name (concat (shadow-site-primary cluster2) file))
+ (insert "foo")
+ (save-buffer))
+ (when shadow-debug
+ (message
+ "shadow-test08-shadow-todo: %s %s"
+ (cons
+ (concat (shadow-site-primary cluster2) file)
+ (shadow-contract-file-name (concat "/cluster1:" file)))
+ shadow-files-to-copy))
+ (should
+ (member
+ (cons
+ (concat (shadow-site-primary cluster2) file)
+ (shadow-contract-file-name (concat "/cluster1:" file)))
+ shadow-files-to-copy))
+
+ ;; Define a regexp group.
+ (setq shadow-files-to-copy nil
+ shadow-regexp-groups
+ `((,(concat (shadow-site-primary cluster1)
+ (shadow-regexp-superquote file))
+ ,(concat (shadow-site-primary cluster2)
+ (shadow-regexp-superquote file)))))
+ (when shadow-debug
+ (message
+ "shadow-test08-shadow-todo: %s %s" file shadow-regexp-groups))
+
+ ;; Save file from "cluster1" definition.
+ (with-temp-buffer
+ (set-visited-file-name file)
+ (insert "foo")
+ (save-buffer))
+ (when shadow-debug
+ (message
+ "shadow-test08-shadow-todo: %s %s"
+ (cons file (shadow-contract-file-name (concat "/cluster2:" file)))
+ shadow-files-to-copy))
+ (should
+ (member
+ (cons file (shadow-contract-file-name (concat "/cluster2:" file)))
+ shadow-files-to-copy))
+
+ ;; Save file from "cluster2" definition.
+ (with-temp-buffer
+ (set-visited-file-name (concat (shadow-site-primary cluster2) file))
+ (insert "foo")
+ (save-buffer))
+ (when shadow-debug
+ (message
+ "shadow-test08-shadow-todo: %s %s"
+ (cons
+ (concat (shadow-site-primary cluster2) file)
+ (shadow-contract-file-name (concat "/cluster1:" file)))
+ shadow-files-to-copy))
+ (should
+ (member
+ (cons
+ (concat (shadow-site-primary cluster2) file)
+ (shadow-contract-file-name (concat "/cluster1:" file)))
+ shadow-files-to-copy)))
+
+ ;; Cleanup.
+ (dolist (elt `(,file ,(concat (shadow-site-primary cluster2) file)))
+ (ignore-errors
+ (with-current-buffer (get-file-buffer elt)
+ (set-buffer-modified-p nil)
+ (kill-buffer)))
+ (ignore-errors (delete-file elt)))
+ (shadow--tests-cleanup))))
+
+(ert-deftest shadow-test09-shadow-copy-files ()
+ "Check that needed shadow files are copied."
+ :tags '(:expensive-test)
+ (skip-unless (not (memq system-type '(windows-nt ms-dos))))
+ (skip-unless (file-remote-p ert-remote-temporary-file-directory))
+ (skip-unless (file-writable-p ert-remote-temporary-file-directory))
+
+ (let ((backup-inhibited t)
+ create-lockfiles
+ (shadow-info-file shadow-test-info-file)
+ (shadow-todo-file shadow-test-todo-file)
+ (shadow-inhibit-message t)
+ (shadow-noquery t)
+ shadow-clusters shadow-files-to-copy
+ cluster1 cluster2 primary regexp file mocked-input)
+ (unwind-protect
+ (progn
+
+ ;; Cleanup & initialize.
+ (shadow--tests-cleanup)
+ (shadow-initialize)
+
+ ;; Define clusters.
+ (setq cluster1 "cluster1"
+ primary shadow-system-name
+ regexp (shadow-regexp-superquote primary))
+ (shadow-set-cluster cluster1 primary regexp)
+
+ (setq cluster2 "cluster2"
+ primary (file-remote-p ert-remote-temporary-file-directory)
+ regexp (shadow-regexp-superquote primary))
+ (shadow-set-cluster cluster2 primary regexp)
+
+ ;; Define files to copy.
+ (setq file
+ (make-temp-name
+ (expand-file-name "shadowfile-tests" temporary-file-directory))
+ shadow-literal-groups
+ `((,(concat "/cluster1:" file) ,(concat "/cluster2:" file)))
+ shadow-regexp-groups
+ `((,(concat (shadow-site-primary cluster1)
+ (shadow-regexp-superquote file))
+ ,(concat (shadow-site-primary cluster2)
+ (shadow-regexp-superquote file))))
+ mocked-input `(,(concat (shadow-site-primary cluster2) file)
+ ,file))
+
+ ;; Save files.
+ (with-temp-buffer
+ (set-visited-file-name file)
+ (insert "foo")
+ (save-buffer))
+ (with-temp-buffer
+ (set-visited-file-name (concat (shadow-site-primary cluster2) file))
+ (insert "foo")
+ (save-buffer))
+
+ ;; We must mock `write-region', in order to check proper
+ ;; action.
+ (add-function
+ :before (symbol-function #'write-region)
+ (lambda (&rest _args)
+ (when (and (buffer-file-name) mocked-input)
+ (should (equal (buffer-file-name) (pop mocked-input)))))
+ '((name . "write-region-mock")))
+
+ ;; Copy the files.
+ (shadow-copy-files 'noquery)
+ (should-not shadow-files-to-copy)
+ (with-current-buffer shadow-todo-buffer
+ (goto-char (point-min))
+ (should
+ (looking-at (regexp-quote "(setq shadow-files-to-copy nil)")))))
+
+ ;; Cleanup.
+ (remove-function (symbol-function #'write-region) "write-region-mock")
+ (dolist (elt `(,file ,(concat (shadow-site-primary cluster2) file)))
+ (ignore-errors
+ (with-current-buffer (get-file-buffer elt)
+ (set-buffer-modified-p nil)
+ (kill-buffer)))
+ (ignore-errors (delete-file elt)))
+ (shadow--tests-cleanup))))
+
+(defun shadowfile-test-all (&optional interactive)
+ "Run all tests for \\[shadowfile]."
+ (interactive "p")
+ (if interactive
+ (ert-run-tests-interactively "^shadowfile-")
+ (ert-run-tests-batch "^shadowfile-")))
+
+(provide 'shadowfile-tests)
+;;; shadowfile-tests.el ends here
diff --git a/test/lisp/shell-tests.el b/test/lisp/shell-tests.el
index c51150069a6..f2cd2f6aead 100644
--- a/test/lisp/shell-tests.el
+++ b/test/lisp/shell-tests.el
@@ -1,6 +1,6 @@
-;;; shell-tests.el -*- lexical-binding:t -*-
+;;; shell-tests.el --- Tests for shell.el -*- lexical-binding:t -*-
-;; Copyright (C) 2010-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2022 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -30,4 +30,38 @@
"Test problem found by Filipp Gunbin in emacs-devel."
(should (equal (car (shell--unquote&requote-argument "te'st" 2)) "test")))
+(ert-deftest shell-tests-completion-before-semi ()
+ (with-temp-buffer
+ (shell-mode)
+ (insert "cd ba;")
+ (forward-char -1)
+ (should (equal (shell--parse-pcomplete-arguments)
+ '(("cd" "ba") 1 4)))))
+
+(ert-deftest shell-tests-completion-after-semi ()
+ (with-temp-buffer
+ (shell-mode)
+ (insert "cd ba;")
+ (should (equal (shell--parse-pcomplete-arguments)
+ '(("cd" "ba" "") 1 4 7)))))
+
+(ert-deftest shell-tests-split-string ()
+ (should (equal (split-string-shell-command "ls /tmp")
+ '("ls" "/tmp")))
+ (should (equal (split-string-shell-command "ls '/tmp/foo bar'")
+ '("ls" "/tmp/foo bar")))
+ (should (equal (split-string-shell-command "ls \"/tmp/foo bar\"")
+ '("ls" "/tmp/foo bar")))
+ (should (equal (split-string-shell-command "ls /tmp/'foo bar'")
+ '("ls" "/tmp/foo bar")))
+ (should (equal (split-string-shell-command "ls /tmp/'foo\"bar'")
+ '("ls" "/tmp/foo\"bar")))
+ (should (equal (split-string-shell-command "ls /tmp/\"foo''bar\"")
+ '("ls" "/tmp/foo''bar")))
+ (should (equal (split-string-shell-command "ls /tmp/'foo\\ bar'")
+ '("ls" "/tmp/foo\\ bar")))
+ (unless (memq system-type '(windows-nt ms-dos))
+ (should (equal (split-string-shell-command "ls /tmp/foo\\ bar")
+ '("ls" "/tmp/foo bar")))))
+
;;; shell-tests.el ends here
diff --git a/test/lisp/simple-tests.el b/test/lisp/simple-tests.el
index 90a627f261e..97f425f6f48 100644
--- a/test/lisp/simple-tests.el
+++ b/test/lisp/simple-tests.el
@@ -1,27 +1,34 @@
-;;; simple-test.el --- Tests for simple.el -*- lexical-binding: t; -*-
+;;; simple-tests.el --- Tests for simple.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2015-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2022 Free Software Foundation, Inc.
;; Author: Artur Malabarba <bruce.connor.am@gmail.com>
-;; This program is free software; you can redistribute it and/or modify
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
-;; This program is distributed in the hope that it will be useful,
+;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
-;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Code:
(require 'ert)
(eval-when-compile (require 'cl-lib))
+(defun simple-test--buffer-substrings ()
+ "Return cons of buffer substrings before and after point."
+ (cons (buffer-substring (point-min) (point))
+ (buffer-substring (point) (point-max))))
+
(defmacro simple-test--dummy-buffer (&rest body)
(declare (indent 0)
(debug t))
@@ -31,10 +38,39 @@
(insert "(a b")
(save-excursion (insert " c d)"))
,@body
- (with-no-warnings
- (cons (buffer-substring (point-min) (point))
- (buffer-substring (point) (point-max))))))
+ (with-no-warnings (simple-test--buffer-substrings))))
+
+;;; `count-words'
+(ert-deftest simple-test-count-words-bug-41761 ()
+ (with-temp-buffer
+ (dotimes (_i 10) (insert (propertize "test " 'field (cons nil nil))))
+ (should (= (count-words (point-min) (point-max)) 10))))
+
+
+;;; `count-lines'
+
+(ert-deftest simple-test-count-lines ()
+ (with-temp-buffer
+ (should (= (count-lines (point-min) (point-max)) 0))
+ (insert "foo")
+ (should (= (count-lines (point-min) (point-max)) 1))
+ (insert "\nbar\nbaz\n")
+ (should (= (count-lines (point-min) (point-max)) 3))
+ (insert "r\n")
+ (should (= (count-lines (point-min) (point-max)) 4))))
+
+(ert-deftest simple-test-count-lines/ignore-invisible-lines ()
+ (with-temp-buffer
+ (insert "foo\nbar")
+ (should (= (count-lines (point-min) (point-max) t) 2))
+ (insert (propertize "\nbar\nbaz\nzut" 'invisible t))
+ (should (= (count-lines (point-min) (point-max) t) 2))))
+
+(ert-deftest simple-text-count-lines-non-ascii ()
+ (with-temp-buffer
+ (insert "あ\nい\nう\nえ\nお\n")
+ (should (= (count-lines (point) (point)) 0))))
;;; `transpose-sexps'
@@ -46,8 +82,7 @@
(insert "(s1) (s2) (s3) (s4) (s5)")
(backward-sexp 1)
,@body
- (cons (buffer-substring (point-min) (point))
- (buffer-substring (point) (point-max)))))
+ (simple-test--buffer-substrings)))
;;; Transposition with negative args (bug#20698, bug#21885)
(ert-deftest simple-transpose-subr ()
@@ -188,7 +223,7 @@
;; From 24 Oct - 21 Nov 2015, `open-line' took a second argument
;; INTERACTIVE and ran `post-self-insert-hook' if the argument was
;; true. This test tested that. Currently, however, `open-line'
-;; does not run run `post-self-insert-hook' at all, so for now
+;; does not run `post-self-insert-hook' at all, so for now
;; this test just makes sure that it doesn't.
(ert-deftest open-line-hook ()
(let* ((x 0)
@@ -214,6 +249,143 @@
(remove-hook 'post-self-insert-hook inc))))
+;;; `delete-indentation'
+
+(ert-deftest simple-delete-indentation-no-region ()
+ "Test `delete-indentation' when no mark is set; see bug#35021."
+ (with-temp-buffer
+ (insert " first \n second \n third \n fourth ")
+ (should-not (mark t))
+ ;; Without prefix argument.
+ (should-not (call-interactively #'delete-indentation))
+ (should (equal (simple-test--buffer-substrings)
+ '(" first \n second \n third" . " fourth ")))
+ (should-not (call-interactively #'delete-indentation))
+ (should (equal (simple-test--buffer-substrings)
+ '(" first \n second" . " third fourth ")))
+ ;; With prefix argument.
+ (goto-char (point-min))
+ (let ((current-prefix-arg '(4)))
+ (should-not (call-interactively #'delete-indentation)))
+ (should (equal (simple-test--buffer-substrings)
+ '(" first" . " second third fourth ")))))
+
+(ert-deftest simple-delete-indentation-inactive-region ()
+ "Test `delete-indentation' with an inactive region."
+ (with-temp-buffer
+ (insert " first \n second \n third ")
+ (set-marker (mark-marker) (point-min))
+ (should (mark t))
+ (should-not (call-interactively #'delete-indentation))
+ (should (equal (simple-test--buffer-substrings)
+ '(" first \n second" . " third ")))))
+
+(ert-deftest simple-delete-indentation-blank-line ()
+ "Test `delete-indentation' does not skip blank lines.
+See bug#35036."
+ (with-temp-buffer
+ (insert "\n\n third \n \n \n sixth \n\n")
+ ;; Without prefix argument.
+ (should-not (delete-indentation))
+ (should (equal (simple-test--buffer-substrings)
+ '("\n\n third \n \n \n sixth \n" . "")))
+ (should-not (delete-indentation))
+ (should (equal (simple-test--buffer-substrings)
+ '("\n\n third \n \n \n sixth" . "")))
+ (should-not (delete-indentation))
+ (should (equal (simple-test--buffer-substrings)
+ '("\n\n third \n \n" . "sixth")))
+ ;; With prefix argument.
+ (goto-char (point-min))
+ (should-not (delete-indentation t))
+ (should (equal (simple-test--buffer-substrings)
+ '("" . "\n third \n \nsixth")))
+ (should-not (delete-indentation t))
+ (should (equal (simple-test--buffer-substrings)
+ '("" . "third \n \nsixth")))
+ (should-not (delete-indentation t))
+ (should (equal (simple-test--buffer-substrings)
+ '("third" . "\nsixth")))
+ (should-not (delete-indentation t))
+ (should (equal (simple-test--buffer-substrings)
+ '("third" . " sixth")))))
+
+(ert-deftest simple-delete-indentation-boundaries ()
+ "Test `delete-indentation' motion at buffer boundaries."
+ (with-temp-buffer
+ (insert " first \n second \n third ")
+ ;; Stay at EOB.
+ (should-not (delete-indentation t))
+ (should (equal (simple-test--buffer-substrings)
+ '(" first \n second \n third " . "")))
+ ;; Stay at BOB.
+ (forward-line -1)
+ (save-restriction
+ (narrow-to-region (point) (pos-eol))
+ (should-not (delete-indentation))
+ (should (equal (simple-test--buffer-substrings)
+ '("" . " second ")))
+ ;; Go to EOB.
+ (should-not (delete-indentation t))
+ (should (equal (simple-test--buffer-substrings)
+ '(" second " . ""))))
+ ;; Go to BOB.
+ (end-of-line 0)
+ (should-not (delete-indentation))
+ (should (equal (simple-test--buffer-substrings)
+ '("" . " first \n second \n third ")))))
+
+(ert-deftest simple-delete-indentation-region ()
+ "Test `delete-indentation' with an active region."
+ (with-temp-buffer
+ ;; Empty region.
+ (insert " first ")
+ (should-not (delete-indentation nil (point) (point)))
+ (should (equal (simple-test--buffer-substrings)
+ '(" first " . "")))
+ ;; Single line.
+ (should-not (delete-indentation nil (pos-bol) (1- (point))))
+ (should (equal (simple-test--buffer-substrings)
+ '("" . " first ")))
+ (should-not (delete-indentation nil (1+ (point)) (pos-eol)))
+ (should (equal (simple-test--buffer-substrings)
+ '(" " . "first ")))
+ (should-not (delete-indentation nil (pos-bol) (pos-eol)))
+ (should (equal (simple-test--buffer-substrings)
+ '("" . " first ")))
+ ;; Multiple lines.
+ (goto-char (point-max))
+ (insert "\n second \n third \n fourth ")
+ (goto-char (point-min))
+ (should-not (delete-indentation nil (pos-eol) (pos-bol 2)))
+ (should (equal (simple-test--buffer-substrings)
+ '(" first" . " second \n third \n fourth ")))
+ (should-not (delete-indentation nil (point) (1+ (pos-bol 2))))
+ (should (equal (simple-test--buffer-substrings)
+ '(" first second" . " third \n fourth ")))
+ ;; Prefix argument overrides region.
+ (should-not (delete-indentation t (point-min) (point)))
+ (should (equal (simple-test--buffer-substrings)
+ '(" first second third" . " fourth ")))))
+
+(ert-deftest simple-delete-indentation-prefix ()
+ "Test `delete-indentation' with a fill prefix."
+ (with-temp-buffer
+ (insert "> first \n> second \n> third \n> fourth ")
+ (let ((fill-prefix ""))
+ (delete-indentation))
+ (should (equal (simple-test--buffer-substrings)
+ '("> first \n> second \n> third" . " > fourth ")))
+ (let ((fill-prefix "<"))
+ (delete-indentation))
+ (should (equal (simple-test--buffer-substrings)
+ '("> first \n> second" . " > third > fourth ")))
+ (let ((fill-prefix ">"))
+ (delete-indentation))
+ (should (equal (simple-test--buffer-substrings)
+ '("> first" . " second > third > fourth ")))))
+
+
;;; `delete-trailing-whitespace'
(ert-deftest simple-delete-trailing-whitespace--bug-21766 ()
"Test bug#21766: delete-whitespace sometimes deletes non-whitespace."
@@ -250,6 +422,164 @@
(should (equal ?\s (char-syntax ?\n))))))
+;;; undo tests
+
+(defun simple-tests--exec (cmds)
+ (dolist (cmd cmds)
+ (setq last-command this-command)
+ (setq this-command cmd)
+ (run-hooks 'pre-command-hook)
+ (command-execute cmd)
+ (run-hooks 'post-command-hook)
+ (undo-boundary)))
+
+(ert-deftest simple-tests--undo ()
+ (with-temp-buffer
+ (buffer-enable-undo)
+ (dolist (x '("a" "b" "c" "d" "e"))
+ (insert x)
+ (undo-boundary))
+ (should (equal (buffer-string) "abcde"))
+ (simple-tests--exec '(undo undo))
+ (should (equal (buffer-string) "abc"))
+ (simple-tests--exec '(backward-char undo))
+ (should (equal (buffer-string) "abcd"))
+ (simple-tests--exec '(undo))
+ (should (equal (buffer-string) "abcde"))
+ (simple-tests--exec '(backward-char undo undo))
+ (should (equal (buffer-string) "abc"))
+ (simple-tests--exec '(backward-char undo-redo))
+ (should (equal (buffer-string) "abcd"))
+ (simple-tests--exec '(undo))
+ (should (equal (buffer-string) "abc"))
+ (simple-tests--exec '(backward-char undo-redo undo-redo))
+ (should (equal (buffer-string) "abcde"))
+ (simple-tests--exec '(undo undo))
+ (should (equal (buffer-string) "abc"))
+ (simple-tests--exec '(backward-char undo-only undo-only))
+ (should (equal (buffer-string) "a"))
+ (simple-tests--exec '(backward-char undo-redo undo-redo))
+ (should (equal (buffer-string) "abc"))
+ (simple-tests--exec '(backward-char undo-redo undo-redo))
+ (should (equal (buffer-string) "abcde"))))
+
+(ert-deftest simple-tests--undo-in-region ()
+ ;; Test undo/redo in region.
+ (with-temp-buffer
+ ;; Enable `transient-mark-mode' so `region-active-p' works as
+ ;; expected. `region-active-p' is used to determine whether to
+ ;; perform regional undo in `undo'.
+ (transient-mark-mode)
+ (buffer-enable-undo)
+ (dolist (x '("a" "b" "c" "d" "e"))
+ (insert x)
+ (undo-boundary))
+ (should (equal (buffer-string) "abcde"))
+ ;; The test does this: activate region, `undo', break the undo
+ ;; chain (by deactivating and reactivating the region), then
+ ;; `undo-only'. There used to be a bug in
+ ;; `undo-make-selective-list' that makes `undo-only' error out in
+ ;; that case, which is fixed by in the same commit as this change.
+ (simple-tests--exec '(move-beginning-of-line
+ push-mark-command
+ forward-char
+ forward-char
+ undo))
+ (should (equal (buffer-string) "acde"))
+ (simple-tests--exec '(move-beginning-of-line
+ push-mark-command
+ forward-char
+ forward-char
+ undo-only))
+ (should (equal (buffer-string) "abcde"))
+ ;; Rest are simple redo in region tests.
+ (simple-tests--exec '(undo-redo))
+ (should (equal (buffer-string) "acde"))
+ (simple-tests--exec '(undo-redo))
+ (should (equal (buffer-string) "abcde"))))
+
+(defun simple-tests--sans-leading-nil (lst)
+ "Return LST sans the leading nils."
+ (while (and (consp lst) (null (car lst)))
+ (setq lst (cdr lst)))
+ lst)
+
+(ert-deftest simple-tests--undo-equiv-table ()
+ (with-temp-buffer
+ (buffer-enable-undo)
+ (transient-mark-mode)
+ (let ((ul-hash-table (make-hash-table :test #'equal)))
+ (dolist (x '("a" "b" "c"))
+ (insert x)
+ (puthash x (simple-tests--sans-leading-nil buffer-undo-list)
+ ul-hash-table)
+ (undo-boundary))
+ (should (equal (buffer-string) "abc"))
+ ;; Tests mappings in `undo-equiv-table'.
+ (simple-tests--exec '(undo))
+ (should (equal (buffer-string) "ab"))
+ (should (eq (gethash (simple-tests--sans-leading-nil
+ buffer-undo-list)
+ undo-equiv-table)
+ (gethash "b" ul-hash-table)))
+ (simple-tests--exec '(backward-char undo))
+ (should (equal (buffer-string) "abc"))
+ (should (eq (gethash (simple-tests--sans-leading-nil
+ buffer-undo-list)
+ undo-equiv-table)
+ (gethash "c" ul-hash-table)))
+ ;; Undo in region should map to 'undo-in-region.
+ (simple-tests--exec '(backward-char
+ push-mark-command
+ move-end-of-line
+ undo))
+ (should (equal (buffer-string) "ab"))
+ (should (eq (gethash (simple-tests--sans-leading-nil
+ buffer-undo-list)
+ undo-equiv-table)
+ 'undo-in-region))
+ ;; The undo that undoes to the beginning should map to t.
+ (deactivate-mark 'force)
+ (simple-tests--exec '(backward-char
+ undo undo undo
+ undo undo undo))
+ (should (equal (buffer-string) ""))
+ (should (eq (gethash (simple-tests--sans-leading-nil
+ buffer-undo-list)
+ undo-equiv-table)
+ t))
+ ;; Erroneous nil undo should map to 'empty.
+ (insert "a")
+ (undo-boundary)
+ (push nil buffer-undo-list)
+ (simple-tests--exec '(backward-char undo))
+ (should (equal (buffer-string) "a"))
+ (should (eq (gethash (simple-tests--sans-leading-nil
+ buffer-undo-list)
+ undo-equiv-table)
+ 'empty))
+ ;; But if the previous record is a redo record, its mapping
+ ;; shouldn't change.
+ (insert "e")
+ (undo-boundary)
+ (should (equal (buffer-string) "ea"))
+ (puthash "e" (simple-tests--sans-leading-nil buffer-undo-list)
+ ul-hash-table)
+ (insert "a")
+ (undo-boundary)
+ (simple-tests--exec '(backward-char undo))
+ (should (equal (buffer-string) "ea"))
+ (push nil buffer-undo-list)
+ (simple-tests--exec '(forward-char undo))
+ ;; Buffer content should change since we just undid a nil
+ ;; record.
+ (should (equal (buffer-string) "ea"))
+ ;; The previous redo record shouldn't map to empty.
+ (should (equal (gethash (simple-tests--sans-leading-nil
+ buffer-undo-list)
+ undo-equiv-table)
+ (gethash "e" ul-hash-table))))))
+
;;; undo auto-boundary tests
(ert-deftest undo-auto-boundary-timer ()
(should
@@ -280,12 +610,12 @@
(undo-auto--boundaries 'test))))
;; Test for a regression introduced by undo-auto--boundaries changes.
-;; https://lists.gnu.org/archive/html/emacs-devel/2015-11/msg01652.html
+;; https://lists.gnu.org/r/emacs-devel/2015-11/msg01652.html
(defun undo-test-kill-c-a-then-undo ()
(with-temp-buffer
(switch-to-buffer (current-buffer))
(setq buffer-undo-list nil)
- (insert "a\nb\n\c\n")
+ (insert "a\nb\nc\n")
(goto-char (point-max))
;; We use a keyboard macro because it adds undo events in the same
;; way as if a user were involved.
@@ -448,6 +778,17 @@ See Bug#21722."
(call-interactively #'eval-expression)
(should (equal (current-message) "66 (#o102, #x42, ?B)"))))))
+(ert-deftest command-execute-prune-command-history ()
+ "Check that Bug#31211 is fixed."
+ (let ((history-length 1)
+ (command-history ()))
+ (dotimes (_ (1+ history-length))
+ (command-execute "" t))
+ (should (= (length command-history) history-length))))
+
+
+;;; `line-number-at-pos'
+
(ert-deftest line-number-at-pos-in-widen-buffer ()
(let ((target-line 3))
(with-temp-buffer
@@ -463,7 +804,7 @@ See Bug#21722."
(insert "a\nb\nc\nd\n")
(goto-char (point-min))
(forward-line (1- target-line))
- (narrow-to-region (line-beginning-position) (line-end-position))
+ (narrow-to-region (pos-bol) (pos-eol))
(should (equal (line-number-at-pos) 1))
(should (equal (line-number-at-pos nil t) target-line)))))
@@ -472,7 +813,7 @@ See Bug#21722."
(insert "a\nb\nc\nd\n")
(goto-char (point-min))
(forward-line 2)
- (narrow-to-region (line-beginning-position) (line-end-position))
+ (narrow-to-region (pos-bol) (pos-eol))
(should (equal (line-number-at-pos) 1))
(line-number-at-pos nil t)
(should (equal (line-number-at-pos) 1))))
@@ -489,13 +830,12 @@ See Bug#21722."
(should (equal pos (point))))))
(ert-deftest line-number-at-pos-when-passing-point ()
- (let (pos)
- (with-temp-buffer
- (insert "a\nb\nc\nd\n")
- (should (equal (line-number-at-pos 1) 1))
- (should (equal (line-number-at-pos 3) 2))
- (should (equal (line-number-at-pos 5) 3))
- (should (equal (line-number-at-pos 7) 4)))))
+ (with-temp-buffer
+ (insert "a\nb\nc\nd\n")
+ (should (equal (line-number-at-pos 1) 1))
+ (should (equal (line-number-at-pos 3) 2))
+ (should (equal (line-number-at-pos 5) 3))
+ (should (equal (line-number-at-pos 7) 4))))
;;; Auto fill.
@@ -511,5 +851,176 @@ See Bug#21722."
(do-auto-fill)
(should (string-equal (buffer-string) "foo bar"))))
+
+;;; Shell command.
+
+(ert-deftest simple-tests-async-shell-command-30280 ()
+ "Test for https://debbugs.gnu.org/30280 ."
+ (let* ((async-shell-command-buffer 'new-buffer)
+ (async-shell-command-display-buffer nil)
+ (base "name")
+ (first (buffer-name (generate-new-buffer base)))
+ (second (generate-new-buffer-name base))
+ ;; `save-window-excursion' doesn't restore frame configurations.
+ (pop-up-frames nil)
+ (inhibit-message t)
+ (emacs (expand-file-name invocation-name invocation-directory)))
+ (skip-unless (file-executable-p emacs))
+ ;; Let `shell-command' create the buffer as needed.
+ (kill-buffer first)
+ (unwind-protect
+ (save-window-excursion
+ ;; One command has no output, the other does.
+ ;; Removing the -eval argument also yields no output, but
+ ;; then both commands exit simultaneously when
+ ;; `accept-process-output' is called on the second command.
+ (dolist (form '("(sleep-for 8)" "(message \"\")"))
+ (async-shell-command (format "%s -Q -batch -eval '%s'"
+ emacs form)
+ first))
+ ;; First command should neither have nor display output.
+ (let* ((buffer (get-buffer first))
+ (process (get-buffer-process buffer)))
+ (should (buffer-live-p buffer))
+ (should process)
+ (should (zerop (buffer-size buffer)))
+ (should (not (get-buffer-window buffer))))
+ ;; Second command should both have and display output.
+ (let* ((buffer (get-buffer second))
+ (process (get-buffer-process buffer)))
+ (should (buffer-live-p buffer))
+ (should process)
+ (should (accept-process-output process 4 nil t))
+ (should (> (buffer-size buffer) 0))
+ (should (get-buffer-window buffer))))
+ (dolist (name (list first second))
+ (let* ((buffer (get-buffer name))
+ (process (and buffer (get-buffer-process buffer))))
+ (when process (delete-process process))
+ (when buffer (kill-buffer buffer)))))))
+
+
+;;; Tests for shell-command-dont-erase-buffer
+
+(defmacro with-shell-command-dont-erase-buffer (str output-buffer-is-current &rest body)
+ (declare (debug (sexp form body)) (indent 2))
+ (let ((command (make-symbol "command"))
+ (caller-buf (make-symbol "caller-buf"))
+ (output-buf (make-symbol "output-buf")))
+ `(let* ((,caller-buf (generate-new-buffer "caller-buf"))
+ (,output-buf (if ,output-buffer-is-current ,caller-buf
+ (generate-new-buffer "output-buf")))
+ (emacs (expand-file-name invocation-name invocation-directory))
+ (,command
+ (format "%s -Q --batch --eval %s"
+ emacs (shell-quote-argument (format "(princ %S)" ,str))))
+ (inhibit-message t))
+ (unwind-protect
+ ;; Feature must work the same regardless how we specify the 2nd arg of `shell-command', ie,
+ ;; as a buffer, buffer name (or t, if the output must go to the current buffer).
+ (dolist (output (append (list ,output-buf (buffer-name ,output-buf))
+ (if ,output-buffer-is-current '(t) nil)))
+ (dolist (save-pos '(erase nil beg-last-out end-last-out save-point))
+ (let ((shell-command-dont-erase-buffer save-pos))
+ (with-current-buffer ,output-buf (erase-buffer))
+ (with-current-buffer ,caller-buf
+ (dotimes (_ 2) (shell-command ,command output)))
+ (with-current-buffer ,output-buf
+ ,@body))))
+ (kill-buffer ,caller-buf)
+ (when (buffer-live-p ,output-buf)
+ (kill-buffer ,output-buf))))))
+
+(ert-deftest simple-tests-shell-command-39067 ()
+ "The output buffer is erased or not according to `shell-command-dont-erase-buffer'."
+ (let ((str "foo\\n"))
+ (dolist (output-current '(t nil))
+ (with-shell-command-dont-erase-buffer str output-current
+ (let ((expected (cond ((eq shell-command-dont-erase-buffer 'erase) str)
+ ((null shell-command-dont-erase-buffer)
+ (if output-current (concat str str)
+ str))
+ (t (concat str str)))))
+ (should (string= expected (buffer-string))))))))
+
+(ert-deftest simple-tests-shell-command-dont-erase-buffer ()
+ "The point is set at the expected position after execution of the command."
+ (let* ((str "foo\\n")
+ (expected-point `((beg-last-out . ,(1+ (length str)))
+ (end-last-out . ,(1+ (* 2 (length str))))
+ (save-point . 1)
+ (erase . ,(1+ (length str)))
+ (nil . ,(1+ (length str))))))
+ (dolist (output-buffer-is-current '(nil))
+ (with-shell-command-dont-erase-buffer str output-buffer-is-current
+ (should (= (point) (alist-get shell-command-dont-erase-buffer expected-point)))))))
+
+(ert-deftest test-undo-region ()
+ (with-temp-buffer
+ (insert "This is a test\n")
+ (goto-char (point-min))
+ (setq buffer-undo-list nil)
+ (downcase-word 1)
+ (should (= (length (delq nil (undo-make-selective-list 1 9))) 2))
+ ;; FIXME: These should give 0, but currently give 1.
+ ;;(should (= (length (delq nil (undo-make-selective-list 4 9))) 0))
+ ;;(should (= (length (delq nil (undo-make-selective-list 5 9))) 0))
+ (should (= (length (delq nil (undo-make-selective-list 6 9))) 0))))
+
+(ert-deftest test-yank-in-context ()
+ (should
+ (equal
+ (with-temp-buffer
+ (sh-mode)
+ (insert "echo \"foo\"")
+ (kill-new "\"bar\"")
+ (goto-char 8)
+ (yank-in-context)
+ (buffer-string))
+ "echo \"f\\\"bar\\\"oo\""))
+
+ (should
+ (equal
+ (with-temp-buffer
+ (sh-mode)
+ (insert "echo \"foo\"")
+ (kill-new "'bar'")
+ (goto-char 8)
+ (yank-in-context)
+ (buffer-string))
+ "echo \"f'bar'oo\""))
+
+ (should
+ (equal
+ (with-temp-buffer
+ (sh-mode)
+ (insert "echo 'foo'")
+ (kill-new "'bar'")
+ (goto-char 8)
+ (yank-in-context)
+ (buffer-string))
+ "echo 'f'\\''bar'\\''oo'")))
+
+;;; Tests for `zap-to-char'
+
+(defmacro with-zap-to-char-test (original result &rest body)
+ (declare (indent 2) (debug (stringp stringp body)))
+ `(with-temp-buffer
+ (insert ,original)
+ (goto-char (point-min))
+ ,@body
+ (should (equal (buffer-string) ,result))))
+
+(ert-deftest simple-tests-zap-to-char ()
+ (with-zap-to-char-test "abcde" "de"
+ (zap-to-char 1 ?c))
+ (with-zap-to-char-test "abcde abc123" "123"
+ (zap-to-char 2 ?c))
+ (let ((case-fold-search t))
+ (with-zap-to-char-test "abcdeCXYZ" "deCXYZ"
+ (zap-to-char 1 ?C))
+ (with-zap-to-char-test "abcdeCXYZ" "XYZ"
+ (zap-to-char 1 ?C 'interactive))))
+
(provide 'simple-test)
-;;; simple-test.el ends here
+;;; simple-tests.el ends here
diff --git a/test/lisp/so-long-tests/autoload-longlines-mode-tests.el b/test/lisp/so-long-tests/autoload-longlines-mode-tests.el
new file mode 100644
index 00000000000..11c018b36c4
--- /dev/null
+++ b/test/lisp/so-long-tests/autoload-longlines-mode-tests.el
@@ -0,0 +1,52 @@
+;;; autoload-longlines-mode-tests.el --- Test suite for so-long.el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2019-2022 Free Software Foundation, Inc.
+
+;; Author: Phil Sainty <psainty@orcon.net.nz>
+;; Keywords: convenience
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(load (expand-file-name "so-long-tests-helpers"
+ (file-name-directory (or load-file-name
+ default-directory))))
+
+(declare-function so-long-tests-remember "so-long-tests-helpers")
+(declare-function so-long-tests-assert-and-revert "so-long-tests-helpers")
+(defvar so-long-action)
+
+;; We're testing the initial state. We could alternatively use
+;; `unload-feature' to revert to that, but this option is simple.
+
+(autoload 'so-long "so-long")
+(autoload 'longlines-mode "longlines")
+
+(ert-deftest so-long-tests-autoload-longlines-mode ()
+ "File-local -*- so-long-action: longlines-mode; eval: (so-long) -*-"
+ (with-temp-buffer
+ (display-buffer (current-buffer))
+ (so-long-tests-remember)
+ (insert "-*- so-long-action: longlines-mode; eval: (so-long) -*-\n")
+ (put 'so-long-action 'safe-local-variable #'symbolp)
+ (push '(eval . (so-long)) safe-local-variable-values)
+ (hack-local-variables)
+ (should (eq so-long-action 'longlines-mode))
+ (so-long-tests-assert-and-revert 'longlines-mode)))
+
+;;; autoload-longlines-mode-tests.el ends here
diff --git a/test/lisp/so-long-tests/autoload-major-mode-tests.el b/test/lisp/so-long-tests/autoload-major-mode-tests.el
new file mode 100644
index 00000000000..2cde241d0b8
--- /dev/null
+++ b/test/lisp/so-long-tests/autoload-major-mode-tests.el
@@ -0,0 +1,47 @@
+;;; autoload-major-mode-tests.el --- Test suite for so-long.el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2019-2022 Free Software Foundation, Inc.
+
+;; Author: Phil Sainty <psainty@orcon.net.nz>
+;; Keywords: convenience
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(load (expand-file-name "so-long-tests-helpers"
+ (file-name-directory (or load-file-name
+ default-directory))))
+
+(declare-function so-long-tests-remember "so-long-tests-helpers")
+(declare-function so-long-tests-assert-and-revert "so-long-tests-helpers")
+
+;; We're testing the initial state. We could alternatively use
+;; `unload-feature' to revert to that, but this option is simple.
+
+(autoload 'so-long-mode "so-long")
+
+(ert-deftest so-long-tests-autoload-major-mode ()
+ "File-local -*- so-long -*-"
+ (with-temp-buffer
+ (display-buffer (current-buffer))
+ (so-long-tests-remember)
+ (insert "-*- so-long -*-\n")
+ (normal-mode)
+ (so-long-tests-assert-and-revert 'so-long-mode)))
+
+;;; autoload-major-mode-tests.el ends here
diff --git a/test/lisp/so-long-tests/autoload-minor-mode-tests.el b/test/lisp/so-long-tests/autoload-minor-mode-tests.el
new file mode 100644
index 00000000000..cf89cff558a
--- /dev/null
+++ b/test/lisp/so-long-tests/autoload-minor-mode-tests.el
@@ -0,0 +1,51 @@
+;;; autoload-minor-mode-tests.el --- Test suite for so-long.el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2019-2022 Free Software Foundation, Inc.
+
+;; Author: Phil Sainty <psainty@orcon.net.nz>
+;; Keywords: convenience
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(load (expand-file-name "so-long-tests-helpers"
+ (file-name-directory (or load-file-name
+ default-directory))))
+
+(declare-function so-long-tests-remember "so-long-tests-helpers")
+(declare-function so-long-tests-assert-and-revert "so-long-tests-helpers")
+(defvar so-long-action)
+
+;; We're testing the initial state. We could alternatively use
+;; `unload-feature' to revert to that, but this option is simple.
+
+(autoload 'so-long "so-long")
+
+(ert-deftest so-long-tests-autoload-minor-mode ()
+ "File-local -*- so-long-action: so-long-minor-mode; eval: (so-long) -*-"
+ (with-temp-buffer
+ (display-buffer (current-buffer))
+ (so-long-tests-remember)
+ (insert "-*- so-long-action: so-long-minor-mode; eval: (so-long) -*-\n")
+ (put 'so-long-action 'safe-local-variable #'symbolp)
+ (push '(eval . (so-long)) safe-local-variable-values)
+ (hack-local-variables)
+ (should (eq so-long-action 'so-long-minor-mode))
+ (so-long-tests-assert-and-revert 'so-long-minor-mode)))
+
+;;; autoload-minor-mode-tests.el ends here
diff --git a/test/lisp/so-long-tests/so-long-tests-helpers.el b/test/lisp/so-long-tests/so-long-tests-helpers.el
new file mode 100644
index 00000000000..79df532f899
--- /dev/null
+++ b/test/lisp/so-long-tests/so-long-tests-helpers.el
@@ -0,0 +1,141 @@
+;;; so-long-tests-helpers.el --- Test suite for so-long.el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2019-2022 Free Software Foundation, Inc.
+
+;; Author: Phil Sainty <psainty@orcon.net.nz>
+;; Keywords: convenience
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'so-long)
+
+(defvar longlines-mode)
+(declare-function longlines-mode "longlines")
+
+(defvar so-long-tests-memory nil
+ "Original values of minor modes and variables.")
+
+(defun so-long-tests-assert-active (action)
+ "Assert that ACTION is active."
+ (cl-destructuring-bind (_key _label actionfunc revertfunc)
+ (assq action so-long-action-alist)
+ (should (eq so-long-function actionfunc))
+ (should (eq so-long-revert-function revertfunc))
+ (should (eq so-long-enabled t))
+ (should (eq so-long--active t))
+ ;; pcase fails here in Emacs 24.
+ (cl-case action
+ (so-long-mode
+ (should (eq major-mode 'so-long-mode))
+ (so-long-tests-assert-overrides)
+ (so-long-tests-assert-preserved))
+ (so-long-minor-mode
+ (should (eq so-long-minor-mode t))
+ (so-long-tests-assert-overrides))
+ (longlines-mode
+ (should (eq longlines-mode t))))))
+
+(defun so-long-tests-assert-reverted (action)
+ "Assert that ACTION has been reverted."
+ (cl-destructuring-bind (_key _label actionfunc revertfunc)
+ (assq action so-long-action-alist)
+ (should (eq so-long-function actionfunc))
+ (should (eq so-long-revert-function revertfunc))
+ (should (eq so-long-enabled t))
+ (should (eq so-long--active nil))
+ ;; pcase fails here in Emacs 24.
+ (cl-case action
+ (so-long-mode
+ (should-not (eq major-mode 'so-long-mode))
+ (so-long-tests-assert-overrides-reverted)
+ (so-long-tests-assert-preserved))
+ (so-long-minor-mode
+ (should-not (eq so-long-minor-mode t))
+ (so-long-tests-assert-overrides-reverted))
+ (longlines-mode
+ (should-not (eq longlines-mode t))))))
+
+(defun so-long-tests-assert-and-revert (action)
+ "Assert ACTION, revert it, and then assert the revert."
+ (so-long-tests-assert-active action)
+ (so-long-revert)
+ (so-long-tests-assert-reverted action))
+
+(defun so-long-tests-assert-overrides ()
+ "Assert that overridden modes and variables have their expected values."
+ (dolist (ovar so-long-variable-overrides)
+ (when (boundp (car ovar))
+ (should (equal (symbol-value (car ovar)) (cdr ovar)))))
+ (dolist (mode so-long-minor-modes)
+ (when (boundp mode)
+ (should (eq (symbol-value mode) nil)))))
+
+(defun so-long-tests-assert-overrides-reverted ()
+ "Assert that each remembered variable has its original value."
+ (dolist (ovar so-long-tests-memory)
+ (when (boundp (car ovar))
+ (should (equal (symbol-value (car ovar)) (cdr ovar))))))
+
+(defun so-long-tests-assert-preserved ()
+ "Assert that preserved modes and variables have their expected values."
+ (dolist (var so-long-mode-preserved-variables)
+ (when (boundp var)
+ (should (equal (symbol-value var)
+ (alist-get var so-long-tests-memory)))))
+ (dolist (mode so-long-mode-preserved-minor-modes)
+ (when (boundp mode)
+ (should (equal (symbol-value mode)
+ (alist-get mode so-long-tests-memory))))))
+
+(defun so-long-tests-remember ()
+ "Remember the original states of modes and variables.
+
+Call this after setting up a buffer in the normal (not `so-long')
+state for its major mode, so that after triggering a `so-long'
+action we can call `so-long-revert' and compare the reverted
+state against this remembered state."
+ (setq so-long-tests-memory nil)
+ (push (cons 'major-mode major-mode)
+ so-long-tests-memory)
+ (dolist (ovar so-long-variable-overrides)
+ (when (boundp (car ovar))
+ (push (cons (car ovar) (symbol-value (car ovar)))
+ so-long-tests-memory)))
+ (dolist (mode so-long-minor-modes)
+ (when (boundp mode)
+ (push (cons mode (symbol-value mode))
+ so-long-tests-memory)))
+ (dolist (var so-long-mode-preserved-variables)
+ (when (boundp var)
+ (push (cons var (symbol-value var))
+ so-long-tests-memory)))
+ (dolist (mode so-long-mode-preserved-minor-modes)
+ (when (boundp mode)
+ (push (cons mode (symbol-value mode))
+ so-long-tests-memory))))
+
+(defun so-long-tests-predicates ()
+ "Return the list of testable predicate functions."
+ (if (fboundp 'buffer-line-statistics)
+ '(so-long-statistics-excessive-p
+ so-long-detected-long-line-p)
+ '(so-long-detected-long-line-p)))
+
+(provide 'so-long-tests-helpers)
+;;; so-long-tests-helpers.el ends here
diff --git a/test/lisp/so-long-tests/so-long-tests.el b/test/lisp/so-long-tests/so-long-tests.el
new file mode 100644
index 00000000000..bf619f453d2
--- /dev/null
+++ b/test/lisp/so-long-tests/so-long-tests.el
@@ -0,0 +1,645 @@
+;;; so-long-tests.el --- Test suite for so-long.el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2019-2022 Free Software Foundation, Inc.
+
+;; Author: Phil Sainty <psainty@orcon.net.nz>
+;; Keywords: convenience
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Most of these tests use the shebang #!emacs to get `normal-mode' to
+;; select `emacs-lisp-mode', as using a file-local mode variable would
+;; usually trigger `so-long-file-local-mode-function'. In cases where
+;; we need to `hack-local-variables', we instead set `buffer-file-name'.
+;; (We could consistently use the latter, but the mixture of approaches
+;; means that we're testing more things.)
+
+;; Running manually:
+;;
+;; for test in lisp/so-long-tests/*-tests.el; do make ${test%.el}; done \
+;; 2>&1 | grep -E -v '^(Loading|Source file|make|Changed to so-long-mode)'
+;;
+;; Which is equivalent to:
+;;
+;; for test in lisp/so-long-tests/*-tests.el; do \
+;; HOME=/nonexistent EMACSLOADPATH= LC_ALL=C EMACS_TEST_DIRECTORY=. \
+;; "../src/emacs" --no-init-file --no-site-file --no-site-lisp \
+;; -L ":." -l ert -l "$test" --batch --eval \
+;; '(ert-run-tests-batch-and-exit (quote (not (tag :unstable))))'; \
+;; done 2>&1 | grep -E -v '^(Loading|Source file|Changed to so-long-mode)'
+;;
+;; See also `ert-run-tests-batch-and-exit'.
+
+;;; Code:
+
+(require 'ert)
+(require 'so-long)
+(load (expand-file-name "so-long-tests-helpers"
+ (file-name-directory (or load-file-name
+ default-directory))))
+
+(declare-function so-long-tests-remember "so-long-tests-helpers")
+(declare-function so-long-tests-assert-active "so-long-tests-helpers")
+(declare-function so-long-tests-assert-reverted "so-long-tests-helpers")
+(declare-function so-long-tests-assert-and-revert "so-long-tests-helpers")
+(declare-function so-long-tests-predicates "so-long-tests-helpers")
+
+;; Enable the automated behavior for all tests.
+(global-so-long-mode 1)
+
+(ert-deftest so-long-tests-threshold-under ()
+ "Under line length threshold."
+ (dolist (so-long-predicate (so-long-tests-predicates))
+ (with-temp-buffer
+ (display-buffer (current-buffer))
+ (insert "#!emacs\n")
+ (insert (make-string (1- so-long-threshold) ?x))
+ (normal-mode)
+ (should (eq major-mode 'emacs-lisp-mode)))))
+
+(ert-deftest so-long-tests-threshold-at ()
+ "At line length threshold."
+ (dolist (so-long-predicate (so-long-tests-predicates))
+ (with-temp-buffer
+ (display-buffer (current-buffer))
+ (insert "#!emacs\n")
+ (insert (make-string (1- so-long-threshold) ?x))
+ (normal-mode)
+ (should (eq major-mode 'emacs-lisp-mode)))))
+
+(ert-deftest so-long-tests-threshold-over ()
+ "Over line length threshold."
+ (dolist (so-long-predicate (so-long-tests-predicates))
+ (with-temp-buffer
+ (display-buffer (current-buffer))
+ (insert "#!emacs\n")
+ (normal-mode)
+ (so-long-tests-remember)
+ (insert (make-string (1+ so-long-threshold) ?x))
+ (normal-mode)
+ (so-long-tests-assert-and-revert 'so-long-mode))))
+
+(ert-deftest so-long-tests-skip-comments ()
+ "Skip leading shebang, whitespace, and comments."
+ ;; Only for `so-long-detected-long-line-p' -- comments are not
+ ;; treated differently when using `so-long-statistics-excessive-p'.
+ (dolist (so-long-predicate (so-long-tests-predicates))
+ ;; Long comment, no newline.
+ (with-temp-buffer
+ (display-buffer (current-buffer))
+ (insert "#!emacs\n")
+ (insert (make-string (1+ so-long-threshold) ?\;))
+ (normal-mode)
+ (should (eq major-mode
+ (cond ((eq so-long-predicate #'so-long-detected-long-line-p)
+ 'emacs-lisp-mode)
+ ((eq so-long-predicate #'so-long-statistics-excessive-p)
+ 'so-long-mode)))))
+ ;; Long comment, with newline.
+ (with-temp-buffer
+ (display-buffer (current-buffer))
+ (insert "#!emacs\n")
+ (insert (make-string (1+ so-long-threshold) ?\;))
+ (insert "\n")
+ (normal-mode)
+ (should (eq major-mode
+ (cond ((eq so-long-predicate #'so-long-detected-long-line-p)
+ 'emacs-lisp-mode)
+ ((eq so-long-predicate #'so-long-statistics-excessive-p)
+ 'so-long-mode)))))
+ ;; Long comment, with short text following.
+ (with-temp-buffer
+ (display-buffer (current-buffer))
+ (insert "#!emacs\n")
+ (insert (make-string (1+ so-long-threshold) ?\;))
+ (insert "\n")
+ (insert (make-string so-long-threshold ?x))
+ (normal-mode)
+ (should (eq major-mode
+ (cond ((eq so-long-predicate #'so-long-detected-long-line-p)
+ 'emacs-lisp-mode)
+ ((eq so-long-predicate #'so-long-statistics-excessive-p)
+ 'so-long-mode)))))
+ ;; Long comment, with long text following.
+ (with-temp-buffer
+ (display-buffer (current-buffer))
+ (insert "#!emacs\n")
+ (insert (make-string (1+ so-long-threshold) ?\;))
+ (insert "\n")
+ (insert (make-string (1+ so-long-threshold) ?x))
+ (normal-mode)
+ (should (eq major-mode 'so-long-mode)))))
+
+(ert-deftest so-long-tests-max-lines ()
+ "Give up after `so-long-max-lines'."
+ ;; Only for `so-long-detected-long-line-p' -- the whole buffer is
+ ;; 'seen' when using `so-long-statistics-excessive-p'.
+ (dolist (so-long-predicate (so-long-tests-predicates))
+ (with-temp-buffer
+ (display-buffer (current-buffer))
+ (insert "#!emacs\n")
+ ;; Insert exactly `so-long-max-lines' non-comment lines, followed
+ ;; by a long line.
+ (dotimes (_ so-long-max-lines)
+ (insert "x\n"))
+ (insert (make-string (1+ so-long-threshold) ?x))
+ (normal-mode)
+ (should (eq major-mode
+ (cond ((eq so-long-predicate #'so-long-detected-long-line-p)
+ 'emacs-lisp-mode)
+ ((eq so-long-predicate #'so-long-statistics-excessive-p)
+ 'so-long-mode))))
+ ;; If `so-long-max-lines' is nil, don't give up the search.
+ (let ((so-long-max-lines nil))
+ (normal-mode)
+ (should (eq major-mode 'so-long-mode)))
+ ;; If `so-long-skip-leading-comments' is nil, all lines are
+ ;; counted, and so the shebang line counts, which makes the
+ ;; long line one line further away.
+ (let ((so-long-skip-leading-comments nil)
+ (so-long-max-lines (1+ so-long-max-lines)))
+ (normal-mode)
+ (should (eq major-mode
+ (cond ((eq so-long-predicate #'so-long-detected-long-line-p)
+ 'emacs-lisp-mode)
+ ((eq so-long-predicate #'so-long-statistics-excessive-p)
+ 'so-long-mode))))
+ (let ((so-long-max-lines (1+ so-long-max-lines)))
+ (normal-mode)
+ (should (eq major-mode 'so-long-mode)))))))
+
+(ert-deftest so-long-tests-invisible-buffer-function ()
+ "Call `so-long-invisible-buffer-function' in invisible buffers."
+ ;; Visible buffer.
+ (with-temp-buffer
+ (display-buffer (current-buffer))
+ (insert "#!emacs\n")
+ (normal-mode)
+ (so-long-tests-remember)
+ (insert (make-string (1+ so-long-threshold) ?x))
+ (normal-mode)
+ (so-long-tests-assert-and-revert 'so-long-mode))
+ ;; Invisible buffer.
+ (with-temp-buffer
+ (insert "#!emacs\n")
+ (normal-mode)
+ (so-long-tests-remember)
+ (insert (make-string (1+ so-long-threshold) ?x))
+ (normal-mode)
+ (should (eq major-mode 'emacs-lisp-mode))
+ (should (eq nil (get-buffer-window)))
+ ;; Displaying the buffer should invoke `so-long'.
+ (display-buffer (current-buffer))
+ (should (window-live-p (get-buffer-window)))
+ (unless (version< emacs-version "27")
+ ;; From Emacs 27 the `display-buffer' call is insufficient.
+ ;; The various 'window change functions' are now invoked by the
+ ;; redisplay, and redisplay does nothing at all in batch mode,
+ ;; so we cannot test under this revised behavior. Refer to:
+ ;; https://lists.gnu.org/r/emacs-devel/2019-10/msg00971.html
+ ;; For interactive (non-batch) test runs, calling `redisplay'
+ ;; does do the trick; so do that first.
+ (redisplay)
+ (when noninteractive
+ ;; In batch mode we need to cheat, and just pretend that
+ ;; `redisplay' triggered `window-configuration-change-hook'.
+ ;; This means the test is not as useful, but it still covers
+ ;; part of the process, and so it's better than nothing.
+ ;;
+ ;; Also test `so-long--active', in case a future version of
+ ;; Emacs adds the framework necessary to make `redisplay' work
+ ;; in batch mode.
+ (unless (eq so-long--active t)
+ (with-suppressed-warnings
+ ((obsolete run-window-configuration-change-hook))
+ (run-window-configuration-change-hook)))))
+ (so-long-tests-assert-and-revert 'so-long-mode))
+ ;; `so-long-invisible-buffer-function' is nil.
+ (with-temp-buffer
+ (insert "#!emacs\n")
+ (normal-mode)
+ (so-long-tests-remember)
+ (insert (make-string (1+ so-long-threshold) ?x))
+ (let ((so-long-invisible-buffer-function nil))
+ (normal-mode))
+ (so-long-tests-assert-and-revert 'so-long-mode))
+ ;; `so-long-invisible-buffer-function' is `so-long'.
+ (with-temp-buffer
+ (insert "#!emacs\n")
+ (normal-mode)
+ (so-long-tests-remember)
+ (insert (make-string (1+ so-long-threshold) ?x))
+ (let ((so-long-invisible-buffer-function #'so-long))
+ (normal-mode))
+ (so-long-tests-assert-and-revert 'so-long-mode))
+ ;; `so-long-invisible-buffer-function' is `ignore'.
+ (with-temp-buffer
+ (insert "#!emacs\n")
+ (normal-mode)
+ (so-long-tests-remember)
+ (insert (make-string (1+ so-long-threshold) ?x))
+ (let ((so-long-invisible-buffer-function #'ignore))
+ (normal-mode))
+ (should (eq major-mode 'emacs-lisp-mode))
+ (display-buffer (current-buffer))
+ (unless (version< emacs-version "27")
+ ;; See the "Invisible buffer" case earlier in this function.
+ (redisplay)
+ (when noninteractive
+ (unless (eq so-long--active t)
+ (with-suppressed-warnings
+ ((obsolete run-window-configuration-change-hook))
+ (run-window-configuration-change-hook)))))
+ (should (eq major-mode 'emacs-lisp-mode))))
+
+(ert-deftest so-long-tests-actions ()
+ "Test each of the standard actions."
+ (dolist (action (mapcar #'car so-long-action-alist))
+ (with-temp-buffer
+ (display-buffer (current-buffer))
+ (insert "#!emacs\n")
+ (normal-mode)
+ (so-long-tests-remember)
+ (insert (make-string (1+ so-long-threshold) ?x))
+ (let ((so-long-action action))
+ (normal-mode)
+ (so-long-tests-assert-and-revert action)))))
+
+(ert-deftest so-long-tests-command-so-long ()
+ "Test the `so-long' command."
+ ;; Includes argument of nil, meaning the default `so-long-mode' action.
+ (dolist (action (cons nil (mapcar #'car so-long-action-alist)))
+ (with-temp-buffer
+ (insert "#!emacs\n")
+ (normal-mode)
+ (so-long-tests-remember)
+ (insert (make-string (1+ so-long-threshold) ?x))
+ (so-long action)
+ (so-long-tests-assert-and-revert (or action 'so-long-mode)))))
+
+(ert-deftest so-long-tests-so-long-menu-item-replace-action ()
+ "Test using the `so-long-menu' action commands."
+ (with-temp-buffer
+ (insert "#!emacs\n")
+ (normal-mode)
+ (so-long-tests-remember)
+ (insert (make-string (1+ so-long-threshold) ?x))
+ (let ((menu (so-long-menu))
+ action
+ command)
+ (dolist (item so-long-action-alist)
+ (setq action (car item)
+ command (lookup-key menu (vector action)))
+ (funcall command)
+ (so-long-tests-assert-active action))
+ ;; After all actions have been used, revert to normal and assert
+ ;; that the most recent action to have been applied is the one
+ ;; we have just reverted.
+ (funcall (lookup-key menu [so-long-revert]))
+ (so-long-tests-assert-reverted action))))
+
+(ert-deftest so-long-tests-major-mode ()
+ "Test calling `so-long-mode' directly."
+ (with-temp-buffer
+ (insert "#!emacs\n")
+ (normal-mode)
+ (so-long-tests-remember)
+ (so-long-mode)
+ (so-long-tests-assert-and-revert 'so-long-mode)))
+
+(ert-deftest so-long-tests-minor-mode ()
+ "Test calling `so-long-minor-mode' directly."
+ (with-temp-buffer
+ (insert "#!emacs\n")
+ (normal-mode)
+ (so-long-tests-remember)
+ (so-long-minor-mode 1)
+ (so-long-tests-assert-active 'so-long-minor-mode)
+ (so-long-minor-mode 0)
+ (so-long-tests-assert-reverted 'so-long-minor-mode)))
+
+(ert-deftest so-long-tests-target-modes ()
+ "Targeted major modes."
+ ;; Test the `so-long-target-modes' user option.
+ (with-temp-buffer
+ (display-buffer (current-buffer))
+ (insert "#!emacs\n")
+ (insert (make-string (1+ so-long-threshold) ?x))
+ ;; Nil target modes.
+ (let ((so-long-target-modes nil))
+ (normal-mode)
+ (should (eq major-mode 'emacs-lisp-mode)))
+ ;; Non-matching target modes.
+ (let ((so-long-target-modes '(text-mode)))
+ (normal-mode)
+ (should (eq major-mode 'emacs-lisp-mode)))
+ ;; Matching mode (direct).
+ (let ((so-long-target-modes '(emacs-lisp-mode)))
+ (normal-mode)
+ (should (eq major-mode 'so-long-mode)))
+ ;; Matching mode (indirect).
+ (let ((so-long-target-modes '(prog-mode)))
+ (normal-mode)
+ (should (eq major-mode 'so-long-mode)))))
+
+(ert-deftest so-long-tests-preserved-variables-and-modes ()
+ "Preserved variables and minor modes when using `so-long-mode'."
+ ;; Test the user options `so-long-mode-preserved-variables' and
+ ;; `so-long-mode-preserved-minor-modes'. The minor mode `view-mode'
+ ;; is 'preserved' by default (using both options).
+ (with-temp-buffer
+ (display-buffer (current-buffer))
+ (insert "#!emacs\n")
+ (normal-mode)
+ ;; We enable `view-mode' before triggering `so-long'.
+ (insert (make-string (1+ so-long-threshold) ?x))
+ (view-mode 1)
+ (should (eq view-mode t))
+ (should (eq buffer-read-only t))
+ (so-long-tests-remember)
+ (let ((so-long-action 'so-long-mode)
+ (menu (so-long-menu)))
+ (so-long)
+ (so-long-tests-assert-active 'so-long-mode)
+ (should (eq view-mode t))
+ (should (eq buffer-read-only t))
+ ;; Revert.
+ (funcall (lookup-key menu [so-long-revert]))
+ (so-long-tests-assert-reverted 'so-long-mode)
+ (should (eq view-mode t))
+ (should (eq buffer-read-only t))
+ ;; Disable `view-mode'. Note that without the preserved
+ ;; variables, the conflict between how `view-mode' and `so-long'
+ ;; each deal with the buffer's original `buffer-read-only' value
+ ;; would lead to a situation whereby the buffer would still be
+ ;; read-only after `view-mode' had been disabled.
+ (view-mode 0)
+ (should (eq view-mode nil))
+ (should (eq buffer-read-only nil))))
+ ;; Without `view-mode'.
+ (with-temp-buffer
+ (display-buffer (current-buffer))
+ (insert "#!emacs\n")
+ (normal-mode)
+ (insert (make-string (1+ so-long-threshold) ?x))
+ (should (eq view-mode nil))
+ (so-long-tests-remember)
+ (let ((so-long-action 'so-long-mode)
+ (menu (so-long-menu)))
+ (so-long)
+ (so-long-tests-assert-active 'so-long-mode)
+ (should (eq view-mode nil))
+ ;; Revert.
+ (funcall (lookup-key menu [so-long-revert]))
+ (so-long-tests-assert-reverted 'so-long-mode)
+ (should (eq view-mode nil)))))
+
+(ert-deftest so-long-tests-predicate ()
+ "Custom predicate function."
+ ;; Test the `so-long-predicate' user option.
+ ;; Always true. Trigger when we normally wouldn't.
+ (with-temp-buffer
+ (display-buffer (current-buffer))
+ (insert "#!emacs\n")
+ (let ((so-long-predicate (lambda () t)))
+ (normal-mode)
+ (should (eq major-mode 'so-long-mode))))
+ ;; Always false. Don't trigger when we normally would.
+ (with-temp-buffer
+ (display-buffer (current-buffer))
+ (insert "#!emacs\n")
+ (insert (make-string (1+ so-long-threshold) ?x))
+ (let ((so-long-predicate #'ignore))
+ (normal-mode)
+ (should (eq major-mode 'emacs-lisp-mode)))))
+
+(ert-deftest so-long-tests-file-local-action ()
+ "File-local action."
+ ;; Test `so-long-action' as a file-local variable.
+ ;; Only valid in Emacs26+. Refer to "Caveats" in the so-long.el Commentary.
+ (unless (version< emacs-version "26")
+ (with-temp-buffer
+ (insert "#!emacs\n")
+ (normal-mode)
+ (so-long-tests-remember))
+ ;; n.b. `run-mode-hooks' *only* runs `hack-local-variables' when there's a
+ ;; (buffer-file-name), so the #!emacs approach is insufficient here. It's
+ ;; valid for the file-locals to be on the second line after the shebang,
+ ;; but with the *.el filename we no longer need the shebang.
+ (with-temp-buffer
+ (display-buffer (current-buffer))
+ (setq buffer-file-name (expand-file-name "so-long-tests-data.el"))
+ (insert ";; -*- so-long-action:so-long-minor-mode; -*-\n")
+ (put 'so-long-action 'safe-local-variable #'symbolp)
+ (insert (make-string (1+ so-long-threshold) ?x))
+ (normal-mode)
+ (so-long-tests-assert-and-revert 'so-long-minor-mode))))
+
+(ert-deftest so-long-tests-file-local-action-eval-so-long ()
+ "File-local action and eval:(so-long)."
+ ;; As per previous test, but using file-local `eval' to call `so-long'.
+ ;; Only valid in Emacs26+. Refer to "Caveats" in the so-long.el Commentary.
+ ;; See also `so-long-tests-file-local-action' above.
+ (unless (version< emacs-version "26")
+ (with-temp-buffer
+ (insert "#!emacs\n")
+ (normal-mode)
+ (so-long-tests-remember))
+ (with-temp-buffer
+ (display-buffer (current-buffer))
+ (setq buffer-file-name (concat (make-temp-name "so-long-tests-") ".el"))
+ (insert ";; -*- so-long-action:so-long-minor-mode; eval:(so-long) -*-\n")
+ (put 'so-long-action 'safe-local-variable #'symbolp)
+ (push '(eval . (so-long)) safe-local-variable-values)
+ (normal-mode)
+ (so-long-tests-assert-and-revert 'so-long-minor-mode))))
+
+(defvar so-long-tests-local-mode 'unset
+ "Set by `so-long-tests-file-local-mode-function'.")
+
+(defun so-long-tests-file-local-mode-function (mode)
+ "A custom value for `so-long-file-local-mode-function'."
+ (setq so-long-tests-local-mode mode))
+
+;; Test `so-long-file-local-mode-function' when the file-local major
+;; mode is `emacs-lisp-mode'.
+
+(defmacro so-long-tests-deftest-file-local-emacs-lisp-mode
+ (sym docstring prop-line &optional local-vars)
+ "Generate tests for using `emacs-lisp-mode' as a file-local mode."
+ (setq prop-line (or prop-line "")
+ local-vars (or local-vars ""))
+ `(ert-deftest ,sym ()
+ ,docstring
+ (let ((orig so-long-file-local-mode-function))
+ ;; Do nothing at all when a file-local mode is used.
+ (setq-default so-long-file-local-mode-function 'so-long-inhibit)
+ (with-temp-buffer
+ (insert ,prop-line)
+ (insert (make-string (1+ so-long-threshold) ?x))
+ (insert ,local-vars)
+ (normal-mode)
+ ;; Remember the `emacs-lisp-mode' state. The other cases
+ ;; will validate the 'reverted' state against this. (Note
+ ;; that we haven't displayed the buffer, and therefore only
+ ;; `so-long-invisible-buffer-function' has acted, so we are
+ ;; still remembering the 'before' state.)
+ (so-long-tests-remember)
+ (should (eq major-mode 'emacs-lisp-mode)))
+ ;; Downgrade the action from major mode to minor mode.
+ (setq-default so-long-file-local-mode-function 'so-long-mode-downgrade)
+ (with-temp-buffer
+ (display-buffer (current-buffer))
+ (insert ,prop-line)
+ (insert (make-string (1+ so-long-threshold) ?x))
+ (insert ,local-vars)
+ (normal-mode)
+ (so-long-tests-assert-and-revert 'so-long-minor-mode))
+ ;; Do not treat the file-local mode specially.
+ (setq-default so-long-file-local-mode-function nil)
+ (with-temp-buffer
+ (display-buffer (current-buffer))
+ (insert ,prop-line)
+ (insert (make-string (1+ so-long-threshold) ?x))
+ (insert ,local-vars)
+ (normal-mode)
+ (so-long-tests-assert-and-revert 'so-long-mode))
+ ;; Custom function
+ (setq-default so-long-file-local-mode-function
+ #'so-long-tests-file-local-mode-function)
+ (with-temp-buffer
+ (display-buffer (current-buffer))
+ (insert ,prop-line)
+ (insert (make-string (1+ so-long-threshold) ?x))
+ (insert ,local-vars)
+ (let (so-long-tests-local-mode)
+ (normal-mode)
+ (should (eq so-long-tests-local-mode 'emacs-lisp-mode))
+ (so-long-tests-assert-active 'so-long-mode)))
+ ;; end
+ (setq-default so-long-file-local-mode-function orig))))
+
+(so-long-tests-deftest-file-local-emacs-lisp-mode
+ so-long-tests-file-local-emacs-lisp-mode-short-form
+ "File-local mode (short form). -*- emacs-lisp -*-"
+ ";; -*- emacs-lisp -*-\n")
+
+(so-long-tests-deftest-file-local-emacs-lisp-mode
+ so-long-tests-file-local-emacs-lisp-mode-long-form
+ "File-local mode (long form). -*- emacs-lisp -*-"
+ ";; -*- mode: emacs-lisp -*-\n")
+
+(so-long-tests-deftest-file-local-emacs-lisp-mode
+ so-long-tests-file-local-emacs-lisp-mode-long-form2
+ "File-local mode (long form). -*- emacs-lisp -*-"
+ nil "\n;; Local Variables:\n;; mode: emacs-lisp\n;; End:\n")
+
+;; Test `so-long-file-local-mode-function' when the file-local major
+;; mode is `so-long-mode'. In this case we should always end up with
+;; the major mode being `so-long-mode'.
+
+(defmacro so-long-tests-deftest-file-local-so-long-mode
+ (sym docstring prop-line &optional local-vars)
+ "Generate tests for using `so-long-mode' as a file-local mode."
+ (setq prop-line (or prop-line "")
+ local-vars (or local-vars ""))
+ `(ert-deftest ,sym ()
+ ,docstring
+ (let ((orig so-long-file-local-mode-function))
+ ;; Do nothing at all when a file-local mode is used.
+ (setq-default so-long-file-local-mode-function 'so-long-inhibit)
+ (with-temp-buffer
+ (display-buffer (current-buffer))
+ ;; Remember the new-buffer state. The other cases will
+ ;; validate the 'reverted' state against this.
+ (so-long-tests-remember)
+ (insert ,prop-line)
+ (insert (make-string (1+ so-long-threshold) ?x))
+ (insert ,local-vars)
+ (normal-mode)
+ (so-long-tests-assert-and-revert 'so-long-mode))
+ ;; Downgrade from major mode to minor mode.
+ (setq-default so-long-file-local-mode-function 'so-long-mode-downgrade)
+ (with-temp-buffer
+ (display-buffer (current-buffer))
+ (insert ,prop-line)
+ (insert (make-string (1+ so-long-threshold) ?x))
+ (insert ,local-vars)
+ (normal-mode)
+ (so-long-tests-assert-and-revert 'so-long-mode))
+ ;; Do not treat the file-local mode specially.
+ (setq-default so-long-file-local-mode-function nil)
+ (with-temp-buffer
+ (display-buffer (current-buffer))
+ (insert ,prop-line)
+ (insert (make-string (1+ so-long-threshold) ?x))
+ (insert ,local-vars)
+ (normal-mode)
+ (so-long-tests-assert-and-revert 'so-long-mode))
+ ;; Custom function.
+ (setq-default so-long-file-local-mode-function
+ #'so-long-tests-file-local-mode-function)
+ (with-temp-buffer
+ (display-buffer (current-buffer))
+ (insert ,prop-line)
+ (insert (make-string (1+ so-long-threshold) ?x))
+ (insert ,local-vars)
+ (let (so-long-tests-local-mode)
+ (normal-mode)
+ (should (eq so-long--inhibited t))
+ (should (eq so-long-tests-local-mode 'so-long-mode))
+ (so-long-tests-assert-active 'so-long-mode)))
+ ;; end
+ (setq-default so-long-file-local-mode-function orig))))
+
+(so-long-tests-deftest-file-local-so-long-mode
+ so-long-tests-file-local-so-long-mode-short-form
+ "File-local mode (short form). -*- so-long -*-"
+ ";; -*- so-long -*-\n")
+
+(so-long-tests-deftest-file-local-so-long-mode
+ so-long-tests-file-local-so-long-mode-long-form
+ "File-local mode (long form). -*- mode: so-long -*-"
+ ";; -*- mode: so-long -*-\n")
+
+(so-long-tests-deftest-file-local-so-long-mode
+ so-long-tests-file-local-so-long-mode-long-form2
+ "File-local mode (long form). -*- mode: so-long -*-"
+ nil "\n;; Local Variables:\n;; mode: so-long\n;; End:\n")
+
+(ert-deftest so-long-tests-commentary ()
+ "Test the `so-long-commentary' command."
+ (so-long-commentary)
+ (should (string= (buffer-name) "*So Long: Commentary*"))
+ (should (eq major-mode 'outline-mode))
+ (should (eq view-mode t))
+ (should (looking-at "^\\* Introduction$"))
+ (goto-char (point-min))
+ (should (looking-at "^so-long\\.el$"))
+ (should (re-search-forward "^\\* Change Log:$")))
+
+(ert-deftest so-long-tests-customize ()
+ "Test the `so-long-customize' command."
+ (so-long-customize)
+ (should (string= (buffer-name) "*Customize Group: So Long*"))
+ (should (eq major-mode 'Custom-mode)))
+
+;; Page break to prevent the local vars strings above from
+;; being misinterpreted as actual local vars declarations.
+
+;;; so-long-tests.el ends here
diff --git a/test/lisp/so-long-tests/spelling-tests.el b/test/lisp/so-long-tests/spelling-tests.el
new file mode 100644
index 00000000000..7bd06395535
--- /dev/null
+++ b/test/lisp/so-long-tests/spelling-tests.el
@@ -0,0 +1,69 @@
+;;; spelling-tests.el --- Test suite for so-long.el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2019-2022 Free Software Foundation, Inc.
+
+;; Author: Phil Sainty <psainty@orcon.net.nz>
+;; Keywords: convenience
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'ert-x)
+(require 'ispell)
+(require 'cl-lib)
+
+;; This test is tagged as :unstable on the basis that there may be
+;; inconsistencies between spell-checking facilities on different
+;; systems, which may cause the test to be unreliable in practice.
+;; As such the Emacs test Makefile will skip it by default, but you
+;; can run it manually with:
+;;
+;; make lisp/so-long-tests/spelling-tests SELECTOR=t
+
+;; Only define the test if spell-checking is possible.
+(when (ignore-errors
+ (and ispell-program-name
+ (executable-find ispell-program-name)
+ (progn (ispell-check-version) t)
+ (member "british" (ispell-valid-dictionary-list))))
+ (ert-deftest so-long-spelling ()
+ "Check the spelling in the source code."
+ :tags '(:unstable) ;; It works for me, but I'm not sure about others.
+ ;; There could be different "british" dictionaries yielding different
+ ;; results, for instance.
+ ;;
+ ;; The Emacs test Makefile's use of HOME=/nonexistent triggers an error
+ ;; when starting the inferior ispell process, so we set HOME to a valid
+ ;; (but empty) temporary directory for this test.
+ (ert-with-temp-directory tmpdir
+ :prefix "so-long."
+ :suffix ".ispell"
+ (let* ((process-environment (cons (format "HOME=%s" tmpdir)
+ process-environment))
+ (find-spelling-mistake
+ (cl-letf (((symbol-function 'ispell-command-loop)
+ (lambda (_miss _guess word _start _end)
+ (message "Unrecognized word: %s." word)
+ (throw 'mistake t))))
+ (catch 'mistake
+ (find-library "so-long")
+ (ispell-buffer)
+ nil))))
+ (should (not find-spelling-mistake))))))
+
+;;; spelling-tests.el ends here
diff --git a/test/lisp/sort-tests.el b/test/lisp/sort-tests.el
index a53b8e5380b..d8d42452ec8 100644
--- a/test/lisp/sort-tests.el
+++ b/test/lisp/sort-tests.el
@@ -1,21 +1,23 @@
;;; sort-tests.el --- Tests for sort.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2015-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2022 Free Software Foundation, Inc.
;; Author: Artur Malabarba <bruce.connor.am@gmail.com>
-;; This program is free software; you can redistribute it and/or modify
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
-;; This program is distributed in the hope that it will be useful,
+;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
-;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Code:
@@ -26,7 +28,7 @@
(mapconcat (lambda (_) (string (let ((c (random 52)))
(+ (if (> c 25) 71 65)
c))))
- (make-list n nil) ""))
+ (make-list n nil)))
(defun sort-tests--insert-words-sort-and-compare (words separator function reverse less-predicate)
(with-temp-buffer
diff --git a/test/lisp/soundex-tests.el b/test/lisp/soundex-tests.el
index 59bdfa4e01e..0ac0ddd666b 100644
--- a/test/lisp/soundex-tests.el
+++ b/test/lisp/soundex-tests.el
@@ -1,6 +1,6 @@
;;; soundex-tests.el --- tests for soundex.el -*- lexical-binding: t -*-
-;; Copyright (C) 2017 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2022 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
diff --git a/test/lisp/startup-tests.el b/test/lisp/startup-tests.el
new file mode 100644
index 00000000000..01ed3a69fd8
--- /dev/null
+++ b/test/lisp/startup-tests.el
@@ -0,0 +1,47 @@
+;;; startup-tests.el --- unit tests for startup.el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+;; Author: Philipp Stephani <phst@google.com>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Unit tests for startup.el.
+
+;;; Code:
+
+(ert-deftest startup-tests/command-switch-alist ()
+ (let* ((foo-args ()) (bar-args ())
+ (command-switch-alist
+ (list (cons "--foo"
+ (lambda (arg)
+ (ert-info ("Processing argument --foo")
+ (push arg foo-args)
+ (should (equal command-line-args-left
+ '("value" "--bar=value")))
+ (pop command-line-args-left))))
+ (cons "--bar=value"
+ (lambda (arg)
+ (ert-info ("Processing argument --bar")
+ (push arg bar-args)
+ (should-not command-line-args-left)))))))
+ (command-line-1 '("--foo" "value" "--bar=value"))
+ (should (equal foo-args '("--foo")))
+ (should (equal bar-args '("--bar=value")))))
+
+;;; startup-tests.el ends here
diff --git a/test/lisp/subr-tests.el b/test/lisp/subr-tests.el
index a68688eba7a..347981e8185 100644
--- a/test/lisp/subr-tests.el
+++ b/test/lisp/subr-tests.el
@@ -1,6 +1,6 @@
-;;; subr-tests.el --- Tests for subr.el
+;;; subr-tests.el --- Tests for subr.el -*- lexical-binding:t -*-
-;; Copyright (C) 2015-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2022 Free Software Foundation, Inc.
;; Author: Oleh Krehel <ohwoeowho@gmail.com>,
;; Nicolas Petton <nicolas@petton.fr>
@@ -26,7 +26,6 @@
;;
;;; Code:
-
(require 'ert)
(eval-when-compile (require 'cl-lib))
@@ -62,6 +61,303 @@
(quote
(0 font-lock-keyword-face))))))))
+
+;;;; List functions.
+
+(ert-deftest subr-test-caaar ()
+ (should (null (caaar '())))
+ (should (null (caaar '(() (2)))))
+ (should (null (caaar '((() (2)) (a b)))))
+ (should-error (caaar '(1 2)) :type 'wrong-type-argument)
+ (should-error (caaar '((1 2))) :type 'wrong-type-argument)
+ (should (= 1 (caaar '(((1 2) (3 4))))))
+ (should (null (caaar '((() (3 4)))))))
+
+(ert-deftest subr-test-caadr ()
+ (should (null (caadr '())))
+ (should (null (caadr '(1))))
+ (should-error (caadr '(1 2)) :type 'wrong-type-argument)
+ (should (= 2 (caadr '(1 (2 3)))))
+ (should (equal '((2) (3)) (caadr '((1) (((2) (3))) (4))))))
+
+
+;;;; Keymap support.
+
+(ert-deftest subr-test-kbd ()
+ (should (equal (kbd "") ""))
+ (should (equal (kbd "f") "f"))
+ (should (equal (kbd "X") "X"))
+ (should (equal (kbd "foobar") "foobar")) ; 6 characters
+ (should (equal (kbd "return") "return")) ; 6 characters
+
+ (should (equal (kbd "<F2>") [F2]))
+ (should (equal (kbd "<f1> <f2> TAB") [f1 f2 ?\t]))
+ (should (equal (kbd "<f1> RET") [f1 ?\r]))
+ (should (equal (kbd "<f1> SPC") [f1 ? ]))
+ (should (equal (kbd "<f1>") [f1]))
+ (should (equal (kbd "<f1>") [f1]))
+ (should (equal (kbd "[f1]") "[f1]"))
+ (should (equal (kbd "<return>") [return]))
+ (should (equal (kbd "< right >") "<right>")) ; 7 characters
+
+ ;; Modifiers:
+ (should (equal (kbd "C-x") "\C-x"))
+ (should (equal (kbd "C-x a") "\C-xa"))
+ (should (equal (kbd "C-;") [?\C-\;]))
+ (should (equal (kbd "C-a") "\C-a"))
+ (should (equal (kbd "C-c SPC") "\C-c "))
+ (should (equal (kbd "C-c TAB") "\C-c\t"))
+ (should (equal (kbd "C-c c") "\C-cc"))
+ (should (equal (kbd "C-x 4 C-f") "\C-x4\C-f"))
+ (should (equal (kbd "C-x C-f") "\C-x\C-f"))
+ (should (equal (kbd "C-M-<down>") [C-M-down]))
+ (should (equal (kbd "<C-M-down>") [C-M-down]))
+ (should (equal (kbd "C-RET") [?\C-\r]))
+ (should (equal (kbd "C-SPC") [?\C- ]))
+ (should (equal (kbd "C-TAB") [?\C-\t]))
+ (should (equal (kbd "C-<down>") [C-down]))
+ (should (equal (kbd "C-c C-c C-c") "\C-c\C-c\C-c"))
+
+ (should (equal (kbd "M-a") [?\M-a]))
+ (should (equal (kbd "M-<DEL>") [?\M-\d]))
+ (should (equal (kbd "M-C-a") [?\M-\C-a]))
+ (should (equal (kbd "M-ESC") [?\M-\e]))
+ (should (equal (kbd "M-RET") [?\M-\r]))
+ (should (equal (kbd "M-SPC") [?\M- ]))
+ (should (equal (kbd "M-TAB") [?\M-\t]))
+ (should (equal (kbd "M-x a") [?\M-x ?a]))
+ (should (equal (kbd "M-<up>") [M-up]))
+ (should (equal (kbd "M-c M-c M-c") [?\M-c ?\M-c ?\M-c]))
+
+ (should (equal (kbd "s-SPC") [?\s- ]))
+ (should (equal (kbd "s-a") [?\s-a]))
+ (should (equal (kbd "s-x a") [?\s-x ?a]))
+ (should (equal (kbd "s-c s-c s-c") [?\s-c ?\s-c ?\s-c]))
+
+ (should (equal (kbd "S-H-a") [?\S-\H-a]))
+ (should (equal (kbd "S-a") [?\S-a]))
+ (should (equal (kbd "S-x a") [?\S-x ?a]))
+ (should (equal (kbd "S-c S-c S-c") [?\S-c ?\S-c ?\S-c]))
+
+ (should (equal (kbd "H-<RET>") [?\H-\r]))
+ (should (equal (kbd "H-DEL") [?\H-\d]))
+ (should (equal (kbd "H-a") [?\H-a]))
+ (should (equal (kbd "H-x a") [?\H-x ?a]))
+ (should (equal (kbd "H-c H-c H-c") [?\H-c ?\H-c ?\H-c]))
+
+ (should (equal (kbd "A-H-a") [?\A-\H-a]))
+ (should (equal (kbd "A-SPC") [?\A- ]))
+ (should (equal (kbd "A-TAB") [?\A-\t]))
+ (should (equal (kbd "A-a") [?\A-a]))
+ (should (equal (kbd "A-c A-c A-c") [?\A-c ?\A-c ?\A-c]))
+
+ (should (equal (kbd "C-M-a") [?\C-\M-a]))
+ (should (equal (kbd "C-M-<up>") [C-M-up]))
+
+ ;; Special characters.
+ (should (equal (kbd "DEL") "\d"))
+ (should (equal (kbd "ESC C-a") "\e\C-a"))
+ (should (equal (kbd "ESC") "\e"))
+ (should (equal (kbd "LFD") "\n"))
+ (should (equal (kbd "NUL") "\0"))
+ (should (equal (kbd "RET") "\C-m"))
+ (should (equal (kbd "SPC") "\s"))
+ (should (equal (kbd "TAB") "\t"))
+ (should (equal (kbd "\^i") ""))
+ (should (equal (kbd "^M") "\^M"))
+
+ ;; With numbers.
+ (should (equal (kbd "\177") "\^?"))
+ (should (equal (kbd "\000") "\0"))
+ (should (equal (kbd "\\177") "\^?"))
+ (should (equal (kbd "\\000") "\0"))
+ (should (equal (kbd "C-x \\150") "\C-xh"))
+
+ ;; Multibyte
+ (should (equal (kbd "ñ") [?ñ]))
+ (should (equal (kbd "ü") [?ü]))
+ (should (equal (kbd "ö") [?ö]))
+ (should (equal (kbd "ğ") [?ğ]))
+ (should (equal (kbd "ա") [?ա]))
+ (should (equal (kbd "üüöö") [?ü ?ü ?ö ?ö]))
+ (should (equal (kbd "C-ü") [?\C-ü]))
+ (should (equal (kbd "M-ü") [?\M-ü]))
+ (should (equal (kbd "H-ü") [?\H-ü]))
+
+ ;; Handle both new and old style key descriptions (bug#45536).
+ (should (equal (kbd "s-<return>") [s-return]))
+ (should (equal (kbd "<s-return>") [s-return]))
+ (should (equal (kbd "C-M-<return>") [C-M-return]))
+ (should (equal (kbd "<C-M-return>") [C-M-return]))
+
+ ;; Error.
+ (should-error (kbd "C-xx"))
+ (should-error (kbd "M-xx"))
+ (should-error (kbd "M-x<TAB>"))
+
+ ;; These should be equivalent:
+ (should (equal (kbd "\C-xf") (kbd "C-x f"))))
+
+(ert-deftest subr-test-key-valid-p ()
+ (should (not (key-valid-p "")))
+ (should (key-valid-p "f"))
+ (should (key-valid-p "X"))
+ (should (not (key-valid-p " X")))
+ (should (key-valid-p "X f"))
+ (should (not (key-valid-p "a b")))
+ (should (not (key-valid-p "foobar")))
+ (should (not (key-valid-p "return")))
+
+ (should (key-valid-p "<F2>"))
+ (should (key-valid-p "<f1> <f2> TAB"))
+ (should (key-valid-p "<f1> RET"))
+ (should (key-valid-p "<f1> SPC"))
+ (should (key-valid-p "<f1>"))
+ (should (not (key-valid-p "[f1]")))
+ (should (key-valid-p "<return>"))
+ (should (not (key-valid-p "< right >")))
+
+ ;; Modifiers:
+ (should (key-valid-p "C-x"))
+ (should (key-valid-p "C-x a"))
+ (should (key-valid-p "C-;"))
+ (should (key-valid-p "C-a"))
+ (should (key-valid-p "C-c SPC"))
+ (should (key-valid-p "C-c TAB"))
+ (should (key-valid-p "C-c c"))
+ (should (key-valid-p "C-x 4 C-f"))
+ (should (key-valid-p "C-x C-f"))
+ (should (key-valid-p "C-M-<down>"))
+ (should (not (key-valid-p "<C-M-down>")))
+ (should (key-valid-p "C-RET"))
+ (should (key-valid-p "C-SPC"))
+ (should (key-valid-p "C-TAB"))
+ (should (key-valid-p "C-<down>"))
+ (should (key-valid-p "C-c C-c C-c"))
+
+ (should (key-valid-p "M-a"))
+ (should (key-valid-p "M-<DEL>"))
+ (should (not (key-valid-p "M-C-a")))
+ (should (key-valid-p "C-M-a"))
+ (should (key-valid-p "M-ESC"))
+ (should (key-valid-p "M-RET"))
+ (should (key-valid-p "M-SPC"))
+ (should (key-valid-p "M-TAB"))
+ (should (key-valid-p "M-x a"))
+ (should (key-valid-p "M-<up>"))
+ (should (key-valid-p "M-c M-c M-c"))
+
+ (should (key-valid-p "s-SPC"))
+ (should (key-valid-p "s-a"))
+ (should (key-valid-p "s-x a"))
+ (should (key-valid-p "s-c s-c s-c"))
+
+ (should (not (key-valid-p "S-H-a")))
+ (should (key-valid-p "S-a"))
+ (should (key-valid-p "S-x a"))
+ (should (key-valid-p "S-c S-c S-c"))
+
+ (should (key-valid-p "H-<RET>"))
+ (should (key-valid-p "H-DEL"))
+ (should (key-valid-p "H-a"))
+ (should (key-valid-p "H-x a"))
+ (should (key-valid-p "H-c H-c H-c"))
+
+ (should (key-valid-p "A-H-a"))
+ (should (key-valid-p "A-SPC"))
+ (should (key-valid-p "A-TAB"))
+ (should (key-valid-p "A-a"))
+ (should (key-valid-p "A-c A-c A-c"))
+
+ (should (key-valid-p "C-M-a"))
+ (should (key-valid-p "C-M-<up>"))
+
+ ;; Special characters.
+ (should (key-valid-p "DEL"))
+ (should (key-valid-p "ESC C-a"))
+ (should (key-valid-p "ESC"))
+ (should (key-valid-p "LFD"))
+ (should (key-valid-p "NUL"))
+ (should (key-valid-p "RET"))
+ (should (key-valid-p "SPC"))
+ (should (key-valid-p "TAB"))
+ (should (not (key-valid-p "\^i")))
+ (should (not (key-valid-p "^M")))
+
+ ;; With numbers.
+ (should (not (key-valid-p "\177")))
+ (should (not (key-valid-p "\000")))
+ (should (not (key-valid-p "\\177")))
+ (should (not (key-valid-p "\\000")))
+ (should (not (key-valid-p "C-x \\150")))
+
+ ;; Multibyte
+ (should (key-valid-p "ñ"))
+ (should (key-valid-p "ü"))
+ (should (key-valid-p "ö"))
+ (should (key-valid-p "ğ"))
+ (should (key-valid-p "ա"))
+ (should (not (key-valid-p "üüöö")))
+ (should (key-valid-p "C-ü"))
+ (should (key-valid-p "M-ü"))
+ (should (key-valid-p "H-ü"))
+
+ ;; Handle both new and old style key descriptions (bug#45536).
+ (should (key-valid-p "s-<return>"))
+ (should (not (key-valid-p "<s-return>")))
+ (should (key-valid-p "C-M-<return>"))
+ (should (not (key-valid-p "<C-M-return>")))
+
+ (should (key-valid-p "<mouse-1>"))
+ (should (key-valid-p "<Scroll_Lock>"))
+
+ (should (not (key-valid-p "c-x")))
+ (should (not (key-valid-p "C-xx")))
+ (should (not (key-valid-p "M-xx")))
+ (should (not (key-valid-p "M-x<TAB>"))))
+
+(ert-deftest subr-test-define-prefix-command ()
+ (define-prefix-command 'foo-prefix-map)
+ (defvar foo-prefix-map)
+ (declare-function foo-prefix-map "subr-tests")
+ (should (keymapp foo-prefix-map))
+ (should (fboundp #'foo-prefix-map))
+ ;; With optional argument.
+ (define-prefix-command 'bar-prefix 'bar-prefix-map)
+ (defvar bar-prefix-map)
+ (declare-function bar-prefix "subr-tests")
+ (should (keymapp bar-prefix-map))
+ (should (fboundp #'bar-prefix))
+ ;; Returns the symbol.
+ (should (eq (define-prefix-command 'foo-bar) 'foo-bar)))
+
+(ert-deftest subr-test-local-key-binding ()
+ (with-temp-buffer
+ (emacs-lisp-mode)
+ (should (keymapp (local-key-binding [menu-bar])))
+ (should-not (local-key-binding [f12]))))
+
+(ert-deftest subr-test-global-key-binding ()
+ (should (eq (global-key-binding [f1]) 'help-command))
+ (should (eq (global-key-binding "x") 'self-insert-command))
+ (should-not (global-key-binding [f12])))
+
+
+;;;; Mode hooks.
+
+(defalias 'subr-tests--parent-mode
+ (if (fboundp 'prog-mode) 'prog-mode 'fundamental-mode))
+
+(ert-deftest provided-mode-derived-p ()
+ ;; base case: `derived-mode' directly derives `prog-mode'
+ (should (progn
+ (define-derived-mode derived-mode prog-mode "test")
+ (provided-mode-derived-p 'derived-mode 'prog-mode)))
+ ;; edge case: `derived-mode' derives an alias of `prog-mode'
+ (should (progn
+ (define-derived-mode derived-mode subr-tests--parent-mode "test")
+ (provided-mode-derived-p 'derived-mode 'prog-mode))))
+
(ert-deftest number-sequence-test ()
(should (= (length
(number-sequence (1- most-positive-fixnum) most-positive-fixnum))
@@ -72,6 +368,17 @@
2)))
(ert-deftest string-comparison-test ()
+ (should (string-equal-ignore-case "abc" "abc"))
+ (should (string-equal-ignore-case "abc" "ABC"))
+ (should (string-equal-ignore-case "abc" "abC"))
+ (should-not (string-equal-ignore-case "abc" "abCD"))
+ (should (string-equal-ignore-case "S" "s"))
+ (should (string-equal-ignore-case "ẞ" "ß"))
+ (should (string-equal-ignore-case "Dz" "DZ"))
+ (should (string-equal-ignore-case "Όσος" "ΌΣΟΣ"))
+ ;; not yet: (should (string-equal-ignore-case "SS" "ß"))
+ ;; not yet: (should (string-equal-ignore-case "SS" "ẞ"))
+
(should (string-lessp "abc" "acb"))
(should (string-lessp "aBc" "abc"))
(should (string-lessp "abc" "abcd"))
@@ -113,6 +420,13 @@
(should (equal (macroexpand-all '(when a b c d))
'(if a (progn b c d)))))
+(ert-deftest subr-test-xor ()
+ "Test `xor'."
+ (should-not (xor nil nil))
+ (should (eq (xor nil 'true) 'true))
+ (should (eq (xor 'true nil) 'true))
+ (should-not (xor t t)))
+
(ert-deftest subr-test-version-parsing ()
(should (equal (version-to-list ".5") '(0 5)))
(should (equal (version-to-list "0.9 alpha1") '(0 9 -3 1)))
@@ -153,27 +467,28 @@
(should (equal (version-to-list "6.9.30Beta") '(6 9 30 -2)))
(should (equal (version-to-list "6.9.30_Beta") '(6 9 30 -2)))
- (should (equal
- (error-message-string (should-error (version-to-list "OTP-18.1.5")))
- "Invalid version syntax: `OTP-18.1.5' (must start with a number)"))
- (should (equal
- (error-message-string (should-error (version-to-list "")))
- "Invalid version syntax: `' (must start with a number)"))
- (should (equal
- (error-message-string (should-error (version-to-list "1.0..7.5")))
- "Invalid version syntax: `1.0..7.5'"))
- (should (equal
- (error-message-string (should-error (version-to-list "1.0prepre2")))
- "Invalid version syntax: `1.0prepre2'"))
- (should (equal
- (error-message-string (should-error (version-to-list "22.8X3")))
- "Invalid version syntax: `22.8X3'"))
- (should (equal
- (error-message-string (should-error (version-to-list "beta22.8alpha3")))
- "Invalid version syntax: `beta22.8alpha3' (must start with a number)"))
- (should (equal
- (error-message-string (should-error (version-to-list "honk")))
- "Invalid version syntax: `honk' (must start with a number)"))
+ (let ((text-quoting-style 'grave))
+ (should (equal
+ (error-message-string (should-error (version-to-list "OTP-18.1.5")))
+ "Invalid version syntax: `OTP-18.1.5' (must start with a number)"))
+ (should (equal
+ (error-message-string (should-error (version-to-list "")))
+ "Invalid version syntax: `' (must start with a number)"))
+ (should (equal
+ (error-message-string (should-error (version-to-list "1.0..7.5")))
+ "Invalid version syntax: `1.0..7.5'"))
+ (should (equal
+ (error-message-string (should-error (version-to-list "1.0prepre2")))
+ "Invalid version syntax: `1.0prepre2'"))
+ (should (equal
+ (error-message-string (should-error (version-to-list "22.8X3")))
+ "Invalid version syntax: `22.8X3'"))
+ (should (equal
+ (error-message-string (should-error (version-to-list "beta22.8alpha3")))
+ "Invalid version syntax: `beta22.8alpha3' (must start with a number)"))
+ (should (equal
+ (error-message-string (should-error (version-to-list "honk")))
+ "Invalid version syntax: `honk' (must start with a number)")))
(should (equal
(error-message-string (should-error (version-to-list 9)))
"Version must be a string"))
@@ -212,18 +527,40 @@
(should (equal (version-to-list "6_9_30.Beta") '(6 9 30 -2)))
(should (equal (version-to-list "6_9_30Beta") '(6 9 30 -2)))
- (should (equal
- (error-message-string (should-error (version-to-list "1_0__7_5")))
- "Invalid version syntax: `1_0__7_5'"))
- (should (equal
- (error-message-string (should-error (version-to-list "1_0prepre2")))
- "Invalid version syntax: `1_0prepre2'"))
- (should (equal
- (error-message-string (should-error (version-to-list "22.8X3")))
- "Invalid version syntax: `22.8X3'"))
- (should (equal
- (error-message-string (should-error (version-to-list "beta22_8alpha3")))
- "Invalid version syntax: `beta22_8alpha3' (must start with a number)"))))
+ (let ((text-quoting-style 'grave))
+ (should (equal
+ (error-message-string (should-error (version-to-list "1_0__7_5")))
+ "Invalid version syntax: `1_0__7_5'"))
+ (should (equal
+ (error-message-string (should-error (version-to-list "1_0prepre2")))
+ "Invalid version syntax: `1_0prepre2'"))
+ (should (equal
+ (error-message-string (should-error (version-to-list "22.8X3")))
+ "Invalid version syntax: `22.8X3'"))
+ (should (equal
+ (error-message-string (should-error (version-to-list "beta22_8alpha3")))
+ "Invalid version syntax: `beta22_8alpha3' (must start with a number)")))))
+
+(ert-deftest subr-test-version-list-< ()
+ (should (version-list-< '(0) '(1)))
+ (should (version-list-< '(0 9) '(1 0)))
+ (should (version-list-< '(1 -1) '(1 0)))
+ (should (version-list-< '(1 -2) '(1 -1)))
+ (should (not (version-list-< '(1) '(0))))
+ (should (not (version-list-< '(1 1) '(1 0))))
+ (should (not (version-list-< '(1) '(1 0))))
+ (should (not (version-list-< '(1 0) '(1 0 0)))))
+
+(ert-deftest subr-test-version-list-= ()
+ (should (version-list-= '(1) '(1)))
+ (should (version-list-= '(1 0) '(1)))
+ (should (not (version-list-= '(0) '(1)))))
+
+(ert-deftest subr-test-version-list-<= ()
+ (should (version-list-<= '(0) '(1)))
+ (should (version-list-<= '(1) '(1)))
+ (should (version-list-<= '(1 0) '(1)))
+ (should (not (version-list-<= '(1) '(0)))))
(defun subr-test--backtrace-frames-with-backtrace-frame (base)
"Reference implementation of `backtrace-frames'."
@@ -285,19 +622,20 @@ indirectly `mapbacktrace'."
(ert-deftest subr-tests--dolist--wrong-number-of-args ()
"Test that `dolist' doesn't accept wrong types or length of SPEC,
cf. Bug#25477."
- (should-error (eval '(dolist (a)))
- :type 'wrong-number-of-arguments)
- (should-error (eval '(dolist (a () 'result 'invalid)) t)
- :type 'wrong-number-of-arguments)
- (should-error (eval '(dolist "foo") t)
- :type 'wrong-type-argument))
+ (dolist (lb '(nil t))
+ (should-error (eval '(dolist (a)) lb)
+ :type 'wrong-number-of-arguments)
+ (should-error (eval '(dolist (a () 'result 'invalid)) lb)
+ :type 'wrong-number-of-arguments)
+ (should-error (eval '(dolist "foo") lb)
+ :type 'wrong-type-argument)))
(ert-deftest subr-tests-bug22027 ()
"Test for https://debbugs.gnu.org/22027 ."
(let ((default "foo") res)
(cl-letf (((symbol-function 'read-string)
- (lambda (_prompt _init _hist def) def)))
- (setq res (read-passwd "pass: " 'confirm (mapconcat #'string default "")))
+ (lambda (_prompt &optional _init _hist def _inher-input) def)))
+ (setq res (read-passwd "pass: " 'confirm (mapconcat #'string default)))
(should (string= default res)))))
(ert-deftest subr-tests--gensym ()
@@ -307,5 +645,526 @@ cf. Bug#25477."
(should (eq (string-to-char (symbol-name (gensym))) ?g))
(should (eq (string-to-char (symbol-name (gensym "X"))) ?X)))
+(ert-deftest subr-tests--assq-delete-all ()
+ "Test `assq-delete-all' behavior."
+ (cl-flet ((new-list-fn
+ ()
+ (list (cons 'a 1) (cons 'b 2) (cons 'c 3) 'd (cons "foo" "bar"))))
+ (should (equal (cdr (new-list-fn)) (assq-delete-all 'a (new-list-fn))))
+ (should (equal (new-list-fn) (assq-delete-all 'd (new-list-fn))))
+ (should (equal (new-list-fn) (assq-delete-all "foo" (new-list-fn))))))
+
+(ert-deftest subr-tests--assoc-delete-all ()
+ "Test `assoc-delete-all' behavior."
+ (cl-flet ((new-list-fn
+ ()
+ (list (cons 'a 1) (cons 'b 2) (cons 'c 3) 'd (cons "foo" "bar"))))
+ (should (equal (cdr (new-list-fn)) (assoc-delete-all 'a (new-list-fn))))
+ (should (equal (new-list-fn) (assoc-delete-all 'd (new-list-fn))))
+ (should (equal (butlast (new-list-fn))
+ (assoc-delete-all "foo" (new-list-fn))))))
+
+(ert-deftest shell-quote-argument-%-on-w32 ()
+ "Quoting of `%' in w32 shells isn't perfect.
+See https://debbugs.gnu.org/cgi/bugreport.cgi?bug=19350."
+ :expected-result :failed
+ (skip-unless (and (fboundp 'w32-shell-dos-semantics)
+ (w32-shell-dos-semantics)))
+ (let ((process-environment (append '("ca^=with-caret"
+ "ca=without-caret")
+ process-environment)))
+ ;; It actually results in
+ ;; without-caret with-caret
+ (should (equal (shell-command-to-string
+ (format "echo %s %s"
+ "%ca%"
+ (shell-quote-argument "%ca%")))
+ "without-caret %ca%"))))
+
+(ert-deftest subr-tests-flatten-tree ()
+ "Test `flatten-tree' behavior."
+ (should (equal (flatten-tree '(1 (2 . 3) nil (4 5 (6)) 7))
+ '(1 2 3 4 5 6 7)))
+ (should (equal (flatten-tree '((1 . 2)))
+ '(1 2)))
+ (should (equal (flatten-tree '(1 nil 2))
+ '(1 2)))
+ (should (equal (flatten-tree 42)
+ '(42)))
+ (should (equal (flatten-tree t)
+ '(t)))
+ (should (equal (flatten-tree nil)
+ nil))
+ (should (equal (flatten-tree '((nil) ((((nil)))) nil))
+ nil))
+ (should (equal (flatten-tree '(1 ("foo" "bar") 2))
+ '(1 "foo" "bar" 2))))
+
+(ert-deftest subr--tests-letrec ()
+ ;; Test that simple cases of `letrec' get optimized back to `let*'.
+ (should (equal (macroexpand '(letrec ((subr-tests-var1 1)
+ (subr-tests-var2 subr-tests-var1))
+ (+ subr-tests-var1 subr-tests-var2)))
+ '(let* ((subr-tests-var1 1)
+ (subr-tests-var2 subr-tests-var1))
+ (+ subr-tests-var1 subr-tests-var2)))))
+
+(defvar subr-tests--hook nil)
+
+(ert-deftest subr-tests-add-hook-depth ()
+ "Test the `depth' arg of `add-hook'."
+ (setq-default subr-tests--hook nil)
+ (add-hook 'subr-tests--hook 'f1)
+ (add-hook 'subr-tests--hook 'f2)
+ (should (equal subr-tests--hook '(f2 f1)))
+ (add-hook 'subr-tests--hook 'f3 t)
+ (should (equal subr-tests--hook '(f2 f1 f3)))
+ (add-hook 'subr-tests--hook 'f4 50)
+ (should (equal subr-tests--hook '(f2 f1 f4 f3)))
+ (add-hook 'subr-tests--hook 'f5 -50)
+ (should (equal subr-tests--hook '(f5 f2 f1 f4 f3)))
+ (add-hook 'subr-tests--hook 'f6)
+ (should (equal subr-tests--hook '(f5 f6 f2 f1 f4 f3)))
+ ;; Make sure t is equivalent to 90.
+ (add-hook 'subr-tests--hook 'f7 90)
+ (add-hook 'subr-tests--hook 'f8 t)
+ (should (equal subr-tests--hook '(f5 f6 f2 f1 f4 f3 f7 f8)))
+ ;; Make sure nil is equivalent to 0.
+ (add-hook 'subr-tests--hook 'f9 0)
+ (add-hook 'subr-tests--hook 'f10)
+ (should (equal subr-tests--hook '(f5 f10 f9 f6 f2 f1 f4 f3 f7 f8)))
+ )
+
+(ert-deftest ignore-error-tests ()
+ (should (equal (ignore-error (end-of-file)
+ (read ""))
+ nil))
+ (should (equal (ignore-error end-of-file
+ (read ""))
+ nil))
+ (should-error (ignore-error foo
+ (read ""))))
+
+(ert-deftest string-replace ()
+ (should (equal (string-replace "foo" "bar" "zot")
+ "zot"))
+ (should (equal (string-replace "foo" "bar" "foozot")
+ "barzot"))
+ (should (equal (string-replace "foo" "bar" "barfoozot")
+ "barbarzot"))
+ (should (equal (string-replace "zot" "bar" "barfoozot")
+ "barfoobar"))
+ (should (equal (string-replace "z" "bar" "barfoozot")
+ "barfoobarot"))
+ (should (equal (string-replace "zot" "bar" "zat")
+ "zat"))
+ (should (equal (string-replace "azot" "bar" "zat")
+ "zat"))
+ (should (equal (string-replace "azot" "bar" "azot")
+ "bar"))
+
+ (should (equal (string-replace "azot" "bar" "foozotbar")
+ "foozotbar"))
+
+ (should (equal (string-replace "fo" "bar" "lafofofozot")
+ "labarbarbarzot"))
+
+ (should (equal (string-replace "\377" "x" "a\377b")
+ "axb"))
+ (should (equal (string-replace "\377" "x" "a\377ø")
+ "axø"))
+ (should (equal (string-replace (string-to-multibyte "\377") "x" "a\377b")
+ "axb"))
+ (should (equal (string-replace (string-to-multibyte "\377") "x" "a\377ø")
+ "axø"))
+
+ (should (equal (string-replace "ana" "ANA" "ananas") "ANAnas"))
+
+ (should (equal (string-replace "a" "" "") ""))
+ (should (equal (string-replace "a" "" "aaaaa") ""))
+ (should (equal (string-replace "ab" "" "ababab") ""))
+ (should (equal (string-replace "ab" "" "abcabcabc") "ccc"))
+ (should (equal (string-replace "a" "aa" "aaa") "aaaaaa"))
+ (should (equal (string-replace "abc" "defg" "abc") "defg"))
+
+ (should (equal (should-error (string-replace "" "x" "abc"))
+ '(wrong-length-argument 0))))
+
+(ert-deftest subr-replace-regexp-in-string ()
+ (should (equal (replace-regexp-in-string "a+" "xy" "abaabbabaaba")
+ "xybxybbxybxybxy"))
+ ;; FIXEDCASE
+ (let ((case-fold-search t))
+ (should (equal (replace-regexp-in-string "a+" "xy" "ABAABBABAABA")
+ "XYBXYBBXYBXYBXY"))
+ (should (equal (replace-regexp-in-string "a+" "xy" "ABAABBABAABA" t)
+ "xyBxyBBxyBxyBxy"))
+ (should (equal (replace-regexp-in-string
+ "a[bc]*" "xyz"
+ "a A ab AB Ab aB abc ABC Abc AbC aBc")
+ "xyz XYZ xyz XYZ Xyz xyz xyz XYZ Xyz Xyz xyz"))
+ (should (equal (replace-regexp-in-string
+ "a[bc]*" "xyz"
+ "a A ab AB Ab aB abc ABC Abc AbC aBc" t)
+ "xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz")))
+ (let ((case-fold-search nil))
+ (should (equal (replace-regexp-in-string "a+" "xy" "ABAABBABAABA")
+ "ABAABBABAABA")))
+ ;; group substitution
+ (should (equal (replace-regexp-in-string
+ "a\\(b*\\)" "<\\1,\\&>" "babbcaabacbab")
+ "b<bb,abb>c<,a><b,ab><,a>cb<b,ab>"))
+ (should (equal (replace-regexp-in-string
+ "x\\(?2:..\\)\\(?1:..\\)\\(..\\)\\(..\\)\\(..\\)"
+ "<\\3,\\5,\\4,\\1,\\2>" "yxabcdefghijkl")
+ "y<ef,ij,gh,cd,ab>kl"))
+ ;; LITERAL
+ (should (equal (replace-regexp-in-string
+ "a\\(b*\\)" "<\\1,\\&>" "babbcaabacbab" nil t)
+ "b<\\1,\\&>c<\\1,\\&><\\1,\\&><\\1,\\&>cb<\\1,\\&>"))
+ (should (equal (replace-regexp-in-string
+ "a" "\\\\,\\?" "aba")
+ "\\,\\?b\\,\\?"))
+ (should (equal (replace-regexp-in-string
+ "a" "\\\\,\\?" "aba" nil t)
+ "\\\\,\\?b\\\\,\\?"))
+ ;; SUBEXP
+ (should (equal (replace-regexp-in-string
+ "\\(a\\)\\(b*\\)c" "xy" "babbcdacd" nil nil 2)
+ "baxycdaxycd"))
+ ;; START
+ (should (equal (replace-regexp-in-string
+ "ab" "x" "abcabdabeabf" nil nil nil 4)
+ "bdxexf"))
+ ;; An empty pattern matches once before every character.
+ (should (equal (replace-regexp-in-string "" "x" "abc")
+ "xaxbxc"))
+ (should (equal (replace-regexp-in-string "y*" "x" "abc")
+ "xaxbxc"))
+ ;; replacement function
+ (should (equal (replace-regexp-in-string
+ "a\\(b*\\)c"
+ (lambda (s)
+ (format "<%s,%s,%s,%s,%s>"
+ s
+ (match-beginning 0) (match-end 0)
+ (match-beginning 1) (match-end 1)))
+ "babbcaacabc")
+ "b<abbc,0,4,1,3>a<ac,0,2,1,1><abc,0,3,1,2>"))
+ ;; anchors (bug#15107, bug#44861)
+ (should (equal (replace-regexp-in-string "a\\B" "b" "a aaaa")
+ "a bbba"))
+ (should (equal (replace-regexp-in-string "\\`\\|x" "z" "--xx--")
+ "z--zz--")))
+
+(ert-deftest subr-match-substitute-replacement ()
+ (with-temp-buffer
+ (insert "Alpha Beta Gamma Delta Epsilon")
+ (goto-char (point-min))
+ (re-search-forward "B\\(..\\)a")
+ (should (equal (match-substitute-replacement "carrot")
+ "Carrot"))
+ (should (equal (match-substitute-replacement "<\\&>")
+ "<Beta>"))
+ (should (equal (match-substitute-replacement "m\\1a")
+ "Meta"))
+ (should (equal (match-substitute-replacement "ernin" nil nil nil 1)
+ "Bernina")))
+ (let ((s "Tau Beta Gamma Delta Epsilon"))
+ (string-match "B\\(..\\)a" s)
+ (should (equal (match-substitute-replacement "carrot" nil nil s)
+ "Carrot"))
+ (should (equal (match-substitute-replacement "<\\&>" nil nil s)
+ "<Beta>"))
+ (should (equal (match-substitute-replacement "m\\1a" nil nil s)
+ "Meta"))
+ (should (equal (match-substitute-replacement "ernin" nil nil s 1)
+ "Bernina"))))
+
+(ert-deftest subr-tests--change-group-33341 ()
+ (with-temp-buffer
+ (buffer-enable-undo)
+ (insert "0\n")
+ (let ((g (prepare-change-group)))
+ (activate-change-group g)
+ (insert "b\n")
+ (insert "c\n")
+ (cancel-change-group g))
+ (should (equal (buffer-string) "0\n"))
+ (erase-buffer)
+ (setq buffer-undo-list nil)
+ (insert "0\n")
+ (let ((g (prepare-change-group)))
+ (activate-change-group g)
+ (insert "b\n")
+ (insert "c\n")
+ (accept-change-group g))
+ (should (equal (buffer-string) "0\nb\nc\n"))
+ (undo-boundary)
+ (undo)
+ (should (equal (buffer-string) ""))))
+
+(defvar subr--ordered nil)
+
+(ert-deftest subr--add-to-ordered-list-eq ()
+ (setq subr--ordered nil)
+ (add-to-ordered-list 'subr--ordered 'b 2)
+ (should (equal subr--ordered '(b)))
+ (add-to-ordered-list 'subr--ordered 'c 3)
+ (should (equal subr--ordered '(b c)))
+ (add-to-ordered-list 'subr--ordered 'a 1)
+ (should (equal subr--ordered '(a b c)))
+ (add-to-ordered-list 'subr--ordered 'e)
+ (should (equal subr--ordered '(a b c e)))
+ (add-to-ordered-list 'subr--ordered 'd 4)
+ (should (equal subr--ordered '(a b c d e)))
+ (add-to-ordered-list 'subr--ordered 'e)
+ (should (equal subr--ordered '(a b c d e)))
+ (add-to-ordered-list 'subr--ordered 'b 5)
+ (should (equal subr--ordered '(a c d b e))))
+
+
+;;; Apropos.
+
+(ert-deftest apropos-apropos-internal ()
+ (should (equal (apropos-internal "^next-line$") '(next-line)))
+ (should (>= (length (apropos-internal "^help")) 100))
+ (should-not (apropos-internal "^test-a-missing-symbol-foo-bar-zot$")))
+
+(ert-deftest apropos-apropos-internal/predicate ()
+ (should (equal (apropos-internal "^next-line$" #'commandp) '(next-line)))
+ (should (>= (length (apropos-internal "^help" #'commandp)) 15))
+ (should-not (apropos-internal "^next-line$" #'keymapp)))
+
+
+(defvar test-global-boundp)
+(ert-deftest test-buffer-local-boundp ()
+ (let ((buf (generate-new-buffer "boundp")))
+ (with-current-buffer buf
+ (setq-local test-boundp t))
+ (setq test-global-boundp t)
+ (should (buffer-local-boundp 'test-boundp buf))
+ (should-not (buffer-local-boundp 'test-not-boundp buf))
+ (should (buffer-local-boundp 'test-global-boundp buf))))
+
+(ert-deftest test-replace-string-in-region ()
+ (with-temp-buffer
+ (insert "foo bar zot foobar")
+ (should (= (replace-string-in-region "foo" "new" (point-min) (point-max))
+ 2))
+ (should (equal (buffer-string) "new bar zot newbar")))
+
+ (with-temp-buffer
+ (insert "foo bar zot foobar")
+ (should (= (replace-string-in-region "foo" "new" (point-min) 14)
+ 1))
+ (should (equal (buffer-string) "new bar zot foobar")))
+
+ (with-temp-buffer
+ (insert "foo bar zot foobar")
+ (should-error (replace-string-in-region "foo" "new" (point-min) 30)))
+
+ (with-temp-buffer
+ (insert "Foo bar zot foobar")
+ (should (= (replace-string-in-region "Foo" "new" (point-min))
+ 1))
+ (should (equal (buffer-string) "new bar zot foobar")))
+
+ (with-temp-buffer
+ (insert "foo bar baz")
+ (should (= (replace-string-in-region "ba" "quux corge grault" (point-min))
+ 2))
+ (should (equal (buffer-string)
+ "foo quux corge graultr quux corge graultz")))
+
+ (with-temp-buffer
+ (insert "foo bar bar")
+ (should (= (replace-string-in-region " bar" "" (point-min) 8)
+ 1))
+ (should (equal (buffer-string)
+ "foo bar"))))
+
+(ert-deftest test-replace-regexp-in-region ()
+ (with-temp-buffer
+ (insert "foo bar zot foobar")
+ (should (= (replace-regexp-in-region "fo+" "new" (point-min) (point-max))
+ 2))
+ (should (equal (buffer-string) "new bar zot newbar")))
+
+ (with-temp-buffer
+ (insert "foo bar zot foobar")
+ (should (= (replace-regexp-in-region "fo+" "new" (point-min) 14)
+ 1))
+ (should (equal (buffer-string) "new bar zot foobar")))
+
+ (with-temp-buffer
+ (insert "foo bar zot foobar")
+ (should-error (replace-regexp-in-region "fo+" "new" (point-min) 30)))
+
+ (with-temp-buffer
+ (insert "Foo bar zot foobar")
+ (should (= (replace-regexp-in-region "Fo+" "new" (point-min))
+ 1))
+ (should (equal (buffer-string) "new bar zot foobar")))
+
+ (with-temp-buffer
+ (insert "foo bar baz")
+ (should (= (replace-regexp-in-region "ba." "quux corge grault" (point-min))
+ 2))
+ (should (equal (buffer-string)
+ "foo quux corge grault quux corge grault")))
+
+ (with-temp-buffer
+ (insert "foo bar bar")
+ (should (= (replace-regexp-in-region " bar" "" (point-min) 8)
+ 1))
+ (should (equal (buffer-string)
+ "foo bar"))))
+
+(ert-deftest test-with-existing-directory ()
+ (let ((dir (make-temp-name "/tmp/not-exist-")))
+ (let ((default-directory dir))
+ (should-not (file-exists-p default-directory)))
+ (with-existing-directory
+ (should-not (equal dir default-directory))
+ (should (file-exists-p default-directory)))))
+
+(ert-deftest subr-test-internal--format-docstring-line ()
+ (should
+ (string= (let ((fill-column 70))
+ (internal--format-docstring-line
+ "In addition to any hooks its parent mode might have run, this \
+mode runs the hook ‘foo-bar-baz-very-long-name-indeed-mode-hook’, as the final \
+or penultimate step during initialization."))
+ "In addition to any hooks its parent mode might have run, this mode
+runs the hook ‘foo-bar-baz-very-long-name-indeed-mode-hook’, as the
+final or penultimate step during initialization."))
+ (should-error (internal--format-docstring-line "foo\nbar")))
+
+(ert-deftest test-ensure-list ()
+ (should (equal (ensure-list nil) nil))
+ (should (equal (ensure-list :foo) '(:foo)))
+ (should (equal (ensure-list '(1 2 3)) '(1 2 3))))
+
+(ert-deftest test-alias-p ()
+ (should-not (function-alias-p 1))
+
+ (defun subr-tests--fun ())
+ (should-not (function-alias-p 'subr-tests--fun))
+
+ (defalias 'subr-tests--a 'subr-tests--b)
+ (defalias 'subr-tests--b 'subr-tests--c)
+ (should (equal (function-alias-p 'subr-tests--a)
+ '(subr-tests--b subr-tests--c)))
+
+ (defalias 'subr-tests--d 'subr-tests--e)
+ (defalias 'subr-tests--e 'subr-tests--d)
+ (should-error (function-alias-p 'subr-tests--d))
+ (should (equal (function-alias-p 'subr-tests--d t)
+ '(subr-tests--e))))
+
+(ert-deftest test-readablep ()
+ (should (readablep "foo"))
+ (should-not (readablep (list (make-marker))))
+ (should-not (readablep (make-marker))))
+
+(ert-deftest test-print-unreadable-function ()
+ ;; Check that problem with unwinding properly is fixed (bug#56773).
+ (let* ((before nil)
+ (after nil)
+ (r (with-temp-buffer
+ (setq before (current-buffer))
+ (prog1 (readablep (make-marker))
+ (setq after (current-buffer))))))
+ (should (equal after before))
+ (should (equal r nil))))
+
+(ert-deftest test-string-lines ()
+ (should (equal (string-lines "") '("")))
+ (should (equal (string-lines "" t) '()))
+
+ (should (equal (string-lines "foo") '("foo")))
+ (should (equal (string-lines "foo\n") '("foo")))
+ (should (equal (string-lines "foo\nbar") '("foo" "bar")))
+
+ (should (equal (string-lines "foo" t) '("foo")))
+ (should (equal (string-lines "foo\n" t) '("foo")))
+ (should (equal (string-lines "foo\nbar" t) '("foo" "bar")))
+ (should (equal (string-lines "foo\n\n\nbar" t) '("foo" "bar")))
+
+ (should (equal (string-lines "foo" nil t) '("foo")))
+ (should (equal (string-lines "foo\n" nil t) '("foo\n")))
+ (should (equal (string-lines "foo\nbar" nil t) '("foo\n" "bar")))
+ (should (equal (string-lines "foo\n\n\nbar" nil t)
+ '("foo\n" "\n" "\n" "bar")))
+
+ (should (equal (string-lines "foo" t t) '("foo")))
+ (should (equal (string-lines "foo\n" t t) '("foo\n")))
+ (should (equal (string-lines "foo\nbar" t t) '("foo\n" "bar")))
+ (should (equal (string-lines "foo\n\n\nbar" t t)
+ '("foo\n" "bar"))))
+
+(ert-deftest test-keymap-parse-macros ()
+ (should (equal (key-parse "C-x ( C-d C-x )") [24 40 4 24 41]))
+ (should (equal (kbd "C-x ( C-d C-x )") ""))
+ (should (equal (kbd "C-x ( C-x )") "")))
+
+(defvar subr-test--global)
+(ert-deftest test-local-set-state ()
+ (setq subr-test--global 1)
+ (with-temp-buffer
+ (setq-local subr-test--local 2)
+ (let ((state (buffer-local-set-state subr-test--global 10
+ subr-test--local 20
+ subr-test--unexist 30)))
+ (should (= subr-test--global 10))
+ (should (= subr-test--local 20))
+ (should (= subr-test--unexist 30))
+ (buffer-local-restore-state state)
+ (should (= subr-test--global 1))
+ (should (= subr-test--local 2))
+ (should-not (boundp 'subr-test--unexist)))))
+
+(ert-deftest test-char-uppercase-p ()
+ "Tests for `char-uppercase-p'."
+ (dolist (c (list ?R ?S ?Ω ?Ψ))
+ (should (char-uppercase-p c)))
+ (dolist (c (list ?a ?b ?α ?β))
+ (should-not (char-uppercase-p c))))
+
+(ert-deftest test-plistp ()
+ (should (plistp nil))
+ (should-not (plistp 1))
+ (should (plistp '(1 2)))
+ (should-not (plistp '(1 . 2)))
+ (should (plistp '(1 2 3 4)))
+ (should-not (plistp '(1 2 3)))
+ (should-not (plistp '(1 2 3 . 4))))
+
+(defun subr-tests--butlast-ref (list &optional n)
+ "Reference implementation of `butlast'."
+ (let ((m (or n 1))
+ (len (length list)))
+ (let ((r nil))
+ (while (and list (> len m))
+ (push (car list) r)
+ (setq list (cdr list))
+ (setq len (1- len)))
+ (nreverse r))))
+
+(ert-deftest subr-butlast ()
+ (dolist (l '(nil '(a) '(a b) '(a b c) '(a b c d)))
+ (dolist (n (cons nil (number-sequence -2 6)))
+ (should (equal (butlast l n)
+ (subr-tests--butlast-ref l n))))))
+
+(ert-deftest test-list-of-strings-p ()
+ (should-not (list-of-strings-p 1))
+ (should (list-of-strings-p nil))
+ (should (list-of-strings-p '("a" "b")))
+ (should-not (list-of-strings-p ["a" "b"]))
+ (should-not (list-of-strings-p '("a" nil "b")))
+ (should-not (list-of-strings-p '("a" "b" . "c"))))
+
(provide 'subr-tests)
;;; subr-tests.el ends here
diff --git a/test/lisp/tab-bar-tests.el b/test/lisp/tab-bar-tests.el
new file mode 100644
index 00000000000..6d57146cd02
--- /dev/null
+++ b/test/lisp/tab-bar-tests.el
@@ -0,0 +1,51 @@
+;;; tab-bar-tests.el --- Tests for tab-bar.el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+;; Author: Juri Linkov <juri@linkov.net>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+
+(defun tab-bar-tests-close-other-tabs (arg)
+ (tab-bar-tabs-set nil)
+ (tab-rename "1")
+ (tab-new) (tab-rename "2") ;; (tab-switch "2")
+ (tab-new) (tab-rename "3") ;; (tab-switch "3")
+ (should (eq (length (tab-bar-tabs)) 3))
+ (should (equal (alist-get 'name (tab-bar--current-tab-find)) "3"))
+ (tab-bar-close-other-tabs arg)
+ (should (equal (alist-get 'name (tab-bar--current-tab-find))
+ (if arg (number-to-string (max 1 (min arg 3))) "3")))
+ (should (eq (length (tab-bar-tabs)) 1))
+ (should (eq (length tab-bar-closed-tabs) 2))
+ (tab-undo)
+ (tab-undo)
+ (should (equal (tab-undo) "No more closed tabs to undo"))
+ (should (eq (length (tab-bar-tabs)) 3))
+ (should (eq (length tab-bar-closed-tabs) 0)))
+
+(ert-deftest tab-bar-tests-close-other-tabs-default ()
+ (tab-bar-tests-close-other-tabs nil))
+
+(ert-deftest tab-bar-tests-close-other-tabs-with-arg ()
+ (dotimes (i 5) (tab-bar-tests-close-other-tabs i)))
+
+(provide 'tab-bar-tests)
+;;; tab-bar-tests.el ends here
diff --git a/test/lisp/tabify-tests.el b/test/lisp/tabify-tests.el
new file mode 100644
index 00000000000..1c8940c30fe
--- /dev/null
+++ b/test/lisp/tabify-tests.el
@@ -0,0 +1,79 @@
+;;; tabify-tests.el --- tests for tabify.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2019-2022 Free Software Foundation, Inc.
+
+;; Author: Stefan Kangas <stefankangas@gmail.com>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'tabify)
+
+(defun tabify-tests--test-changes (fun changes width)
+ (with-temp-buffer
+ (let ((tab-width width))
+ (insert (mapconcat #'car changes))
+ (funcall fun (point-min) (point-max))
+ (should (equal (buffer-string) (mapconcat #'cadr changes))))))
+
+(ert-deftest tabify-tests-untabify ()
+ (let ((changes '(("***\n" "***\n")
+ (" ***\n" " ***\n")
+ ("\t***\n" " ***\n")
+ ("\t ***\n" " ***\n")
+ ("\t\t***\n" " ***\n")
+ ("\t\t ***\n" " ***\n")
+ ("\t\t\t***\n" " ***\n")
+ ("\t\t\t ***\n" " ***\n")
+ (" ***\n" " ***\n")
+ (" \t ***\n" " ***\n")
+ (" \t***\n" " ***\n")
+ (" \t***\n" " ***\n"))))
+ (tabify-tests--test-changes #'untabify changes 2)))
+
+(ert-deftest tabify-tests-tabify ()
+ (let ((changes '(("***\n" "***\n")
+ (" ***\n" " ***\n")
+ (" ***\n" "\t***\n")
+ (" ***\n" "\t ***\n")
+ (" ***\n" "\t\t***\n")
+ (" ***\n" "\t\t ***\n")
+ (" ***\n" "\t\t\t***\n")
+ (" ***\n" "\t\t\t ***\n")
+ ("\t***\n" "\t***\n")
+ ("\t ***\n" "\t ***\n")
+ ("\t\t***\n" "\t\t***\n"))))
+ (tabify-tests--test-changes #'tabify changes 2)))
+
+(ert-deftest tabify-tests-tabify/all-spaces-on-line ()
+ (with-temp-buffer
+ (let ((tab-width 2))
+ (insert " ** ** ")
+ (tabify (point-min) (point-max))
+ (should (equal (buffer-string) "\t**\t**\t")))))
+
+(ert-deftest tabify-tests-tabify/only-initial ()
+ (with-temp-buffer
+ (let ((tab-width 2)
+ (tabify-regexp "^\\t* [ \\t]+")) ; from tabify-regexp docstring
+ (insert " ** ")
+ (tabify (point-min) (point-max))
+ (should (equal (buffer-string) "\t** ")))))
+
+(provide 'tabify-tests)
+;;; tabify-tests.el ends here
diff --git a/test/lisp/tar-mode-tests.el b/test/lisp/tar-mode-tests.el
index e005c2d8cc0..47c658eb9ad 100644
--- a/test/lisp/tar-mode-tests.el
+++ b/test/lisp/tar-mode-tests.el
@@ -1,6 +1,6 @@
;;; tar-mode-tests.el --- Test suite for tar-mode. -*- lexical-binding: t -*-
-;; Copyright (C) 2017 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2022 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -21,16 +21,31 @@
(require 'ert)
(require 'tar-mode)
+(defvar tar-mode-tests-data-directory
+ (expand-file-name "test/data/decompress" source-directory))
(ert-deftest tar-mode-test-tar-grind-file-mode ()
(let ((alist (list (cons 448 "rwx------")
(cons 420 "rw-r--r--")
(cons 292 "r--r--r--")
(cons 512 "--------T")
- (cons 1024 "-----S---"))))
+ (cons 1024 "-----S---")
+ (cons 2048 "--S------"))))
(dolist (x alist)
- (should (equal (cdr x) (tar-grind-file-mode (car x)))))))
+ (with-suppressed-warnings ((obsolete tar-grind-file-mode))
+ (should (equal (cdr x) (tar-grind-file-mode (car x))))))))
+
+(ert-deftest tar-mode-test-tar-extract-gz ()
+ (skip-unless (executable-find "gzip"))
+ (let* ((tar-file (expand-file-name "tg.tar.gz" tar-mode-tests-data-directory))
+ tar-buffer gz-buffer)
+ (unwind-protect
+ (with-current-buffer (setq tar-buffer (find-file-noselect tar-file))
+ (setq gz-buffer (tar-extract))
+ (should (equal (char-after) ?\N{SNOWFLAKE})))
+ (when (buffer-live-p tar-buffer) (kill-buffer tar-buffer))
+ (when (buffer-live-p gz-buffer) (kill-buffer gz-buffer)))))
(provide 'tar-mode-tests)
-;; tar-mode-tests.el ends here
+;;; tar-mode-tests.el ends here
diff --git a/test/lisp/tempo-tests.el b/test/lisp/tempo-tests.el
new file mode 100644
index 00000000000..52553d791f2
--- /dev/null
+++ b/test/lisp/tempo-tests.el
@@ -0,0 +1,267 @@
+;;; tempo-tests.el --- Test suite for tempo.el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2019-2022 Free Software Foundation, Inc.
+
+;; Author: Federico Tedin <federicotedin@gmail.com>
+;; Keywords: abbrev
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'tempo)
+(eval-when-compile (require 'cl-lib))
+
+(ert-deftest tempo-string-element-test ()
+ "Test a template containing a string element."
+ (with-temp-buffer
+ (tempo-define-template "test" '("GNU Emacs Tempo test"))
+ (tempo-insert-template 'tempo-template-test nil)
+ (should (equal (buffer-string) "GNU Emacs Tempo test"))))
+
+(ert-deftest tempo-p-bare-element-test ()
+ "Test a template containing a bare `p' element."
+ (with-temp-buffer
+ (tempo-define-template "test" '("abcde" p))
+ (tempo-insert-template 'tempo-template-test nil)
+ (tempo-forward-mark)
+ (should (equal (point) 6))))
+
+(ert-deftest tempo-r-bare-element-test ()
+ "Test a template containing a bare `r' element."
+ (with-temp-buffer
+ (tempo-define-template "test" '("abcde" r "ghijk"))
+ (insert "F")
+ (set-mark (point))
+ (goto-char (point-min))
+ (tempo-insert-template 'tempo-template-test t)
+ (should (equal (buffer-string) "abcdeFghijk"))))
+
+(ert-deftest tempo-p-element-test ()
+ "Testing template containing a `p' (prompt) element."
+ (with-temp-buffer
+ (tempo-define-template "test" '("hello " (p ">")))
+ (let ((tempo-interactive t))
+ (cl-letf (((symbol-function 'read-string) (lambda (&rest _) "world")))
+ (tempo-insert-template 'tempo-template-test nil))
+ (should (equal (buffer-string) "hello world")))))
+
+(ert-deftest tempo-P-element-test ()
+ "Testing template containing a `P' (prompt) element."
+ (with-temp-buffer
+ (tempo-define-template "test" '("hello " (P ">")))
+ ;; By default, `tempo-interactive' is nil, `P' should ignore this.
+ (cl-letf (((symbol-function 'read-string) (lambda (&rest _) "world")))
+ (tempo-insert-template 'tempo-template-test nil))
+ (should (equal (buffer-string) "hello world"))))
+
+(ert-deftest tempo-r-element-test ()
+ "Testing template containing an `r' (with prompt) element."
+ (with-temp-buffer
+ (tempo-define-template "test" '("abcde" (r ">") "ghijk"))
+ (let ((tempo-interactive t))
+ (cl-letf (((symbol-function 'read-string) (lambda (&rest _) "F")))
+ (tempo-insert-template 'tempo-template-test nil))
+ (should (equal (buffer-string) "abcdeFghijk")))))
+
+(ert-deftest tempo-s-element-test ()
+ "Testing template containing an `s' element."
+ (with-temp-buffer
+ (tempo-define-template "test" '("hello " (p ">" P1) " " (s P1)))
+ (let ((tempo-interactive t))
+ (cl-letf (((symbol-function 'read-string) (lambda (&rest _) "world!")))
+ (tempo-insert-template 'tempo-template-test nil))
+ (should (equal (buffer-string) "hello world! world!")))))
+
+(ert-deftest tempo-&-element-test ()
+ "Testing template containing an `&' element."
+ (tempo-define-template "test" '(& "test"))
+ (with-temp-buffer
+ (insert " ")
+ (tempo-insert-template 'tempo-template-test nil)
+ (should (equal (buffer-string) " test")))
+ (with-temp-buffer
+ (insert "hello")
+ (tempo-insert-template 'tempo-template-test nil)
+ (should (equal (buffer-string) "hello\ntest"))))
+
+(ert-deftest tempo-%-element-test ()
+ "Testing template containing an `%' element."
+ (tempo-define-template "test" '("test" %))
+ (with-temp-buffer
+ (tempo-insert-template 'tempo-template-test nil)
+ (should (equal (buffer-string) "test")))
+ (with-temp-buffer
+ (insert "hello")
+ (goto-char (point-min))
+ (tempo-insert-template 'tempo-template-test nil)
+ (should (equal (buffer-string) "test\nhello"))))
+
+(ert-deftest tempo-n-element-test ()
+ "Testing template containing an `n' element."
+ (tempo-define-template "test" '("test" n "test"))
+ (with-temp-buffer
+ (tempo-insert-template 'tempo-template-test nil)
+ (should (equal (buffer-string) "test\ntest"))))
+
+(ert-deftest tempo-n>-element-test ()
+ "Testing template containing an `n>' element."
+ (tempo-define-template "test" '("(progn" n> "(list 1 2 3))"))
+ (with-temp-buffer
+ (emacs-lisp-mode)
+ (tempo-insert-template 'tempo-template-test nil)
+ ;; Tempo should have inserted two spaces before (list 1 2 3)
+ (should (equal (buffer-string) "(progn\n (list 1 2 3))"))))
+
+(ert-deftest tempo->-element-test ()
+ "Testing template containing a `>' element."
+ (with-temp-buffer
+ (emacs-lisp-mode)
+ (insert "(progn\n)")
+ (backward-char)
+ (tempo-define-template "test" '("(list 1 2 3)" >))
+ (tempo-insert-template 'tempo-template-test nil)
+ ;; Tempo should have inserted two spaces before (list 1 2 3)
+ (should (equal (buffer-string) "(progn\n (list 1 2 3))"))))
+
+(ert-deftest tempo-r>-bare-element-test ()
+ "Testing template containing a bare `r>' element."
+ (with-temp-buffer
+ (tempo-define-template "test" '("(progn" n r> ")"))
+ (emacs-lisp-mode)
+ (insert "(list 1 2 3)")
+ (set-mark (point))
+ (goto-char (point-min))
+ (tempo-insert-template 'tempo-template-test t)
+ ;; Tempo should have inserted two spaces before (list 1 2 3)
+ (should (equal (buffer-string) "(progn\n (list 1 2 3))"))))
+
+(ert-deftest tempo-r>-element-test ()
+ "Testing template containing an `r>' (with prompt) element."
+ (tempo-define-template "test" '("(progn" n (r> ":") ")"))
+ (with-temp-buffer
+ ;; Test on-region use
+ (emacs-lisp-mode)
+ (insert "(list 1 2 3)")
+ (set-mark (point))
+ (goto-char (point-min))
+ (tempo-insert-template 'tempo-template-test t)
+ (should (equal (buffer-string) "(progn\n (list 1 2 3))")))
+ (with-temp-buffer
+ ;; Test interactive use
+ (emacs-lisp-mode)
+ (let ((tempo-interactive t))
+ (cl-letf (((symbol-function 'read-string) (lambda (&rest _) " (list 1 2 3)")))
+ (tempo-insert-template 'tempo-template-test nil))
+ (should (equal (buffer-string) "(progn\n (list 1 2 3))")))))
+
+(ert-deftest tempo-o-element-test ()
+ "Testing template containing an `o' element."
+ (with-temp-buffer
+ (tempo-define-template "test" '("test" o))
+ (insert "hello")
+ (goto-char (point-min))
+ (tempo-insert-template 'tempo-template-test nil)
+ (should (equal (buffer-string) "test\nhello"))
+ (should (equal (point) 5))))
+
+(ert-deftest tempo-nil-element-test ()
+ "Testing template with nil elements."
+ (with-temp-buffer
+ (tempo-define-template "test" '("Hello," nil " World!"))
+ (tempo-insert-template 'tempo-template-test nil)
+ (should (equal (buffer-string) "Hello, World!"))))
+
+(ert-deftest tempo-eval-element-test ()
+ "Testing template with Emacs Lisp expressions."
+ (with-temp-buffer
+ (tempo-define-template "test" '((int-to-string (+ 1 1)) "=" (concat "1" "+1")))
+ (tempo-insert-template 'tempo-template-test nil)
+ (should (equal (buffer-string) "2=1+1"))))
+
+(ert-deftest tempo-l-element-test ()
+ "Testing template containing an `l' element."
+ (with-temp-buffer
+ (tempo-define-template "test" '("list: " (l "1, " "2, " (int-to-string (+ 1 2)))))
+ (tempo-insert-template 'tempo-template-test nil)
+ (should (equal (buffer-string) "list: 1, 2, 3"))))
+
+(ert-deftest tempo-tempo-user-elements-test ()
+ "Testing a template with elements for `tempo-user-elements'."
+ (with-temp-buffer
+ (make-local-variable 'tempo-user-elements)
+ (add-to-list 'tempo-user-elements (lambda (x) (int-to-string (* x x))))
+ (tempo-define-template "test" '(1 " " 2 " " 3 " " 4))
+ (tempo-insert-template 'tempo-template-test nil)
+ (should (equal (buffer-string) "1 4 9 16"))))
+
+(ert-deftest tempo-expand-tag-test ()
+ "Testing expansion of a template with a tag."
+ (with-temp-buffer
+ (tempo-define-template "test" '("Hello, World!") "hello")
+ (insert "hello")
+ (tempo-complete-tag)
+ (should (equal (buffer-string) "Hello, World!"))))
+
+(ert-deftest tempo-define-tag-globally-test ()
+ "Testing usage of a template tag defined from another buffer."
+ (tempo-define-template "test" '("Hello, World!") "hello")
+
+ (with-temp-buffer
+ ;; Use a tag in buffer 1
+ (insert "hello")
+ (tempo-complete-tag)
+ (should (equal (buffer-string) "Hello, World!"))
+ (erase-buffer)
+
+ ;; Collection should not be dirty
+ (should-not tempo-dirty-collection)
+
+ ;; Define a tag on buffer 2
+ (with-temp-buffer
+ (tempo-define-template "test2" '("Now expanded.") "mytag"))
+
+ ;; I should be able to use this template back in buffer 1
+ (insert "mytag")
+ (tempo-complete-tag)
+ (should (equal (buffer-string) "Now expanded."))))
+
+(ert-deftest tempo-overwrite-tag-test ()
+ "Testing ability to reassign templates to tags."
+ (with-temp-buffer
+ ;; Define a tag and use it
+ (tempo-define-template "test-tag-1" '("abc") "footag")
+ (insert "footag")
+ (tempo-complete-tag)
+ (should (equal (buffer-string) "abc"))
+ (erase-buffer)
+
+ ;; Define a new template with the same tag
+ (tempo-define-template "test-tag-2" '("xyz") "footag")
+ (insert "footag")
+ (tempo-complete-tag)
+ (should (equal (buffer-string) "xyz"))))
+
+(ert-deftest tempo-expand-partial-tag-test ()
+ "Testing expansion of a template with a tag, with a partial match."
+ (with-temp-buffer
+ (tempo-define-template "test" '("Hello, World!") "hello")
+ (insert "hel")
+ (tempo-complete-tag)
+ (should (equal (buffer-string) "Hello, World!"))))
+
+(provide 'tempo-tests)
+;;; tempo-tests.el ends here
diff --git a/test/lisp/term-tests.el b/test/lisp/term-tests.el
new file mode 100644
index 00000000000..f60d2ff5747
--- /dev/null
+++ b/test/lisp/term-tests.el
@@ -0,0 +1,406 @@
+;;; term-tests.el --- tests for term.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2017, 2019-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+
+;;; Code:
+(require 'ert)
+(require 'term)
+(eval-when-compile (require 'cl-lib))
+
+(defvar term-height) ; Number of lines in window.
+(defvar term-width) ; Number of columns in window.
+
+(defvar yellow-fg-props
+ `( :foreground ,(face-foreground 'term-color-yellow nil 'default)
+ :background "unspecified-bg" :inverse-video nil))
+(defvar yellow-bg-props
+ `( :foreground "unspecified-fg"
+ :background ,(face-background 'term-color-yellow nil 'default)
+ :inverse-video nil))
+(defvar bright-yellow-fg-props
+ `( :foreground ,(face-foreground 'term-color-bright-yellow nil 'default)
+ :background "unspecified-bg" :inverse-video nil))
+(defvar bright-yellow-bg-props
+ `( :foreground "unspecified-fg"
+ :background ,(face-background 'term-color-bright-yellow nil 'default)
+ :inverse-video nil))
+(defvar custom-color-fg-props
+ `( :foreground "#87FFFF"
+ :background "unspecified-bg" :inverse-video nil))
+
+(defvar ansi-test-strings
+ `(("\e[33mHello World\e[0m"
+ ,(propertize "Hello World" 'font-lock-face `(,yellow-fg-props)))
+ ("\e[43mHello World\e[0m"
+ ,(propertize "Hello World" 'font-lock-face `(,yellow-bg-props)))
+ ("\e[93mHello World\e[0m"
+ ,(propertize "Hello World" 'font-lock-face `(,bright-yellow-fg-props)))
+ ("\e[103mHello World\e[0m"
+ ,(propertize "Hello World" 'font-lock-face `(,bright-yellow-bg-props)))
+ ("\e[1;33mHello World\e[0m"
+ ,(propertize "Hello World" 'font-lock-face
+ `(,yellow-fg-props term-bold))
+ ,(propertize "Hello World" 'font-lock-face
+ `(,bright-yellow-fg-props term-bold)))
+ ("\e[33;1mHello World\e[0m"
+ ,(propertize "Hello World" 'font-lock-face
+ `(,yellow-fg-props term-bold))
+ ,(propertize "Hello World" 'font-lock-face
+ `(,bright-yellow-fg-props term-bold)))
+ ("\e[1m\e[33mHello World\e[0m"
+ ,(propertize "Hello World" 'font-lock-face
+ `(,yellow-fg-props term-bold))
+ ,(propertize "Hello World" 'font-lock-face
+ `(,bright-yellow-fg-props term-bold)))
+ ("\e[33m\e[1mHello World\e[0m"
+ ,(propertize "Hello World" 'font-lock-face
+ `(,yellow-fg-props term-bold))
+ ,(propertize "Hello World" 'font-lock-face
+ `(,bright-yellow-fg-props term-bold)))
+ ("\e[38;5;3;1mHello World\e[0m"
+ ,(propertize "Hello World" 'font-lock-face
+ `(,yellow-fg-props term-bold))
+ ,(propertize "Hello World" 'font-lock-face
+ `(,bright-yellow-fg-props term-bold)))
+ ("\e[38;5;123;1mHello World\e[0m"
+ ,(propertize "Hello World" 'font-lock-face
+ `(,custom-color-fg-props term-bold)))
+ ("\e[38;2;135;255;255;1mHello World\e[0m"
+ ,(propertize "Hello World" 'font-lock-face
+ `(,custom-color-fg-props term-bold)))))
+
+(defun term-test-screen-from-input (width height input &optional return-var)
+ (with-temp-buffer
+ (term-mode)
+ ;; Keep dimensions independent from window size.
+ (remove-function (local 'window-adjust-process-window-size-function)
+ 'term-maybe-reset-size)
+ (term-exec (current-buffer) "test" "cat" nil nil)
+ (term-char-mode)
+ (setq term-width width)
+ (setq term-height height)
+ ;; Pass input directly to `term-emulate-terminal', it's easier to
+ ;; control chunking, and we don't have to worry about wrestling
+ ;; with stty settings.
+ (let ((proc (get-buffer-process (current-buffer))))
+ ;; Don't get stuck when we close the buffer.
+ (set-process-query-on-exit-flag proc nil)
+ (if (consp input)
+ (mapc (lambda (input) (term-emulate-terminal proc input)) input)
+ (term-emulate-terminal proc input))
+ (if return-var (buffer-local-value return-var (current-buffer))
+ (buffer-substring (point-min) (point-max))))))
+
+(ert-deftest term-simple-lines ()
+ (skip-unless (not (memq system-type '(windows-nt ms-dos))))
+ (let ((str "\
+first line\r
+next line\r\n"))
+ (should (equal (term-test-screen-from-input 40 12 str)
+ (string-replace "\r" "" str)))))
+
+(ert-deftest term-carriage-return ()
+ (skip-unless (not (memq system-type '(windows-nt ms-dos))))
+ (let ((str "\
+first line\r_next line\r\n"))
+ (should (equal (term-test-screen-from-input 40 12 str)
+ "_next line\n"))))
+
+(ert-deftest term-line-wrap ()
+ (skip-unless (not (memq system-type '(windows-nt ms-dos))))
+ (should (string-match-p
+ ;; Don't be strict about trailing whitespace.
+ "\\`a\\{40\\}\na\\{20\\} *\\'"
+ (term-test-screen-from-input 40 12 (make-string 60 ?a))))
+ ;; Again, but split input into chunks.
+ (should (string-match-p
+ "\\`a\\{40\\}\na\\{20\\} *\\'"
+ (term-test-screen-from-input 40 12 (let ((str (make-string 30 ?a)))
+ (list str str))))))
+
+(ert-deftest term-colors ()
+ (skip-unless (not (memq system-type '(windows-nt ms-dos))))
+ (pcase-dolist (`(,str ,expected) ansi-test-strings)
+ (let ((result (term-test-screen-from-input 40 12 str)))
+ (should (equal result expected))
+ (should (equal (text-properties-at 0 result)
+ (text-properties-at 0 expected))))))
+
+(ert-deftest term-colors-bold-is-bright ()
+ (skip-unless (not (memq system-type '(windows-nt ms-dos))))
+ (let ((ansi-color-bold-is-bright t))
+ (pcase-dolist (`(,str ,expected ,bright-expected) ansi-test-strings)
+ (let ((expected (or bright-expected expected))
+ (result (term-test-screen-from-input 40 12 str)))
+ (should (equal result expected))
+ (should (equal (text-properties-at 0 result)
+ (text-properties-at 0 expected)))))))
+
+(ert-deftest term-cursor-movement ()
+ (skip-unless (not (memq system-type '(windows-nt ms-dos))))
+ ;; Absolute positioning.
+ (should (equal "ab\ncd"
+ (term-test-screen-from-input
+ 40 12 (concat "\e[2;2Hd"
+ "\e[2;1Hc"
+ "\e[1;2Hb"
+ "\e[1;1Ha"))))
+ ;; Send one byte at a time.
+ (should (equal "ab\ncd"
+ (term-test-screen-from-input
+ 40 12 (split-string (concat "\e[2;2Hd"
+ "\e[2;1Hc"
+ "\e[1;2Hb"
+ "\e[1;1Ha") "" t))))
+ (should (equal "abcde j"
+ (term-test-screen-from-input
+ 10 12 '("abcdefghij"
+ "\e[H" ;move back to point-min
+ "abcde"
+ " j"))))
+
+ ;; Relative positioning.
+ (should (equal "ab\ncd"
+ (term-test-screen-from-input
+ 40 12 (concat "\e[B\e[Cd"
+ "\e[D\e[Dc"
+ "\e[Ab"
+ "\e[D\e[Da")))))
+
+(ert-deftest term-scrolling-region ()
+ (skip-unless (not (memq system-type '(windows-nt ms-dos))))
+ (should (equal "\
+line3
+line4
+line5
+line6
+"
+ (term-test-screen-from-input
+ 40 12 "\e[1;5r\
+line1\r
+line2\r
+line3\r
+line4\r
+line5\r
+line6\r
+")))
+
+ ;; test reverse scrolling
+ (should (equal "line1
+line7
+line6
+line2
+line5"
+ (term-test-screen-from-input 40 5
+ '("\e[0;0H"
+ "\e[J"
+ "line1\r
+line2\r
+line3\r
+line4\r
+line5"
+ "\e[2;4r"
+ "\e[2;0H"
+ "\e[2;0H"
+ "\eMline6"
+ "\e[2;0H"
+ "\eMline7"))))
+
+ ;; test scrolling down
+ (should (equal "line1
+line3
+line4
+line7
+line5"
+ (term-test-screen-from-input 40 5
+ '("\e[0;0H"
+ "\e[J"
+ "line1\r
+line2\r
+line3\r
+line4\r
+line5"
+ "\e[2;4r"
+ "\e[2;0H"
+ "\e[4;5H"
+ "\n\rline7"))))
+
+ ;; setting the scroll region end beyond the max height should not
+ ;; turn on term-scroll-with-delete
+ (should (equal "line1
+line2
+line3
+line4
+line5
+line6
+line7"
+ (term-test-screen-from-input 40 5
+ '("\e[1;10r"
+ "line1\r
+line2\r
+line3\r
+line4\r
+line5\r
+line6\r
+line7"))))
+
+
+ ;; resetting the terminal should set the scroll region end to (1- term-height).
+ (should (equal "
+line1
+line2
+line3
+line4
+"
+ (term-test-screen-from-input 40 5
+ '("\e[1;10r"
+ "\ec" ;reset
+ "line1\r
+line2\r
+line3\r
+line4\r
+line5"
+ "\e[1;1H"
+ "\e[L"))))
+
+ ;; scroll region should be limited to the (1- term-height). Note,
+ ;; this fixes an off by one error when comparing the scroll region
+ ;; end with term-height.
+ (should (equal "
+line1
+line2
+line3
+line4
+"
+ (term-test-screen-from-input 40 5
+ '("\e[1;6r"
+ "line1\r
+line2\r
+line3\r
+line4\r
+line5"
+ "\e[1;1H" ;go back to home
+ "\e[L" ;insert a new line at the top
+ ))))
+
+ ;; setting the scroll region to the entire height should not turn on
+ ;; term-scroll-with-delete
+ (should (equal "line1
+line2
+line3
+line4
+line5
+line6"
+ (term-test-screen-from-input 40 5
+ '("\e[1;5r"
+ "line1\r
+line2\r
+line3\r
+line4\r
+line5\r
+line6"))))
+
+ ;; reset should reset term-scroll-with-delete
+ (should (equal "line1
+line2
+line3
+line4
+line5
+line6
+line7"
+ (term-test-screen-from-input 40 5
+ '("\e[2;5r" ;set the region
+ "\ec" ;reset
+ "line1\r
+line2\r
+line3\r
+line4\r
+line5\r
+line6\r
+line7")))))
+
+(ert-deftest term-set-directory ()
+ (skip-unless (not (memq system-type '(windows-nt ms-dos))))
+ (let ((term-ansi-at-user (user-real-login-name)))
+ (should (equal (term-test-screen-from-input
+ 40 12 "\eAnSiTc /foo/\n" 'default-directory)
+ "/foo/"))
+ ;; Split input (Bug#17231).
+ (should (equal (term-test-screen-from-input
+ 40 12 (list "\eAnSiTc /f" "oo/\n") 'default-directory)
+ "/foo/"))))
+
+(ert-deftest term-line-wrapping-then-motion ()
+ "Make sure we reset the line-wrapping state after moving cursor.
+A real-life example is the default zsh prompt which writes spaces
+to the end of line (triggering line-wrapping state), and then
+sends a carriage return followed by another space to overwrite
+the first character of the line."
+ (skip-unless (not (memq system-type '(windows-nt ms-dos))))
+ (let* ((width 10)
+ (strs (list "x" (make-string (1- width) ?_)
+ "\r_")))
+ (should (equal (term-test-screen-from-input width 12 strs)
+ (make-string width ?_)))))
+
+(ert-deftest term-to-margin ()
+ "Test cursor movement at the scroll margin.
+This is a reduced example from GNU nano's initial screen."
+ (skip-unless (not (memq system-type '(windows-nt ms-dos))))
+ (let* ((width 10)
+ (x (make-string width ?x))
+ (y (make-string width ?y)))
+ (should (equal (term-test-screen-from-input
+ width 3
+ `("\e[1;3r" ; Setup 3 line scrolling region.
+ "\e[2;1H" ; Move to 2nd last line.
+ ,x ; Fill with 'x'.
+ "\r\e[1B" ; Next line.
+ ,y)) ; Fill with 'y'.
+ (concat "\n" x "\n" y)))
+ ;; Same idea, but moving upwards.
+ (should (equal (term-test-screen-from-input
+ width 3
+ `("\e[1;3r" "\e[2;1H" ,x "\r\e[1A" ,y))
+ (concat y "\n" x)))))
+
+(ert-deftest term-decode-partial () ;; Bug#25288.
+ "Test multibyte characters sent into multiple chunks."
+ ;; Set `locale-coding-system' so test will be deterministic.
+ (let* ((locale-coding-system 'utf-8-unix)
+ (string (make-string 7 ?ш))
+ (bytes (encode-coding-string string locale-coding-system)))
+ (should (equal string
+ (term-test-screen-from-input
+ 40 1 `(,(substring bytes 0 (/ (length bytes) 2))
+ ,(substring bytes (/ (length bytes) 2))))))))
+(ert-deftest term-undecodable-input () ;; Bug#29918.
+ "Undecodable bytes should be passed through without error."
+ (let* ((locale-coding-system 'utf-8-unix) ; As above.
+ (bytes "\376\340\360\370")
+ (string (decode-coding-string bytes locale-coding-system)))
+ (should (equal string
+ (term-test-screen-from-input
+ 40 1 bytes)))))
+
+(provide 'term-tests)
+
+;;; term-tests.el ends here
diff --git a/test/lisp/term/tty-colors-tests.el b/test/lisp/term/tty-colors-tests.el
new file mode 100644
index 00000000000..e55b10511ee
--- /dev/null
+++ b/test/lisp/term/tty-colors-tests.el
@@ -0,0 +1,38 @@
+;;; tty-colors-tests.el --- tests for tty-colors.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2019-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+
+;;; Code:
+(require 'ert)
+(require 'term/tty-colors)
+
+(ert-deftest tty-colors-test-standard-colors ()
+ (should (equal (tty-color-standard-values "white") '(65535 65535 65535)))
+ (should (equal (tty-color-standard-values "#F00") '(65535 0 0)))
+ (should (equal (tty-color-standard-values "#00FF00") '(0 65535 0)))
+ (should (equal (tty-color-standard-values "#00000000FFFF") '(0 0 65535)))
+ (should (equal (tty-color-standard-values "rgb:0/0/7") '(0 0 30583)))
+ (should (equal (tty-color-standard-values "rgb:0/ff/0") '(0 65535 0)))
+ (should (equal (tty-color-standard-values "rgb:ffFF/0000/0000") '(65535 0 0))))
+
+(provide 'term-tests)
+
+;;; tty-colors-tests.el ends here
diff --git a/test/lisp/textmodes/bibtex-tests.el b/test/lisp/textmodes/bibtex-tests.el
new file mode 100644
index 00000000000..1bf15d17294
--- /dev/null
+++ b/test/lisp/textmodes/bibtex-tests.el
@@ -0,0 +1,57 @@
+;;; bibtex-tests.el --- Test suite for bibtex. -*- lexical-binding:t -*-
+
+;; Copyright (C) 2013-2022 Free Software Foundation, Inc.
+
+;; Keywords: bibtex
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'bibtex)
+
+(ert-deftest bibtex-test-set-dialect ()
+ "Tests if `bibtex-set-dialect' is executed."
+ (with-temp-buffer
+ (insert "@article{someID,
+ author = {some author},
+ title = {some title},
+}")
+ (bibtex-mode)
+ (should-not (null bibtex-dialect))
+ (should-not (null bibtex-entry-type))
+ (should-not (null bibtex-entry-head))
+ (should-not (null bibtex-reference-key))
+ (should-not (null bibtex-entry-head))
+ (should-not (null bibtex-entry-maybe-empty-head))
+ (should-not (null bibtex-any-valid-entry-type))))
+
+(ert-deftest bibtex-test-parse-buffers-stealthily ()
+ "Tests if `bibtex-parse-buffers-stealthily' can be executed."
+ (with-temp-buffer
+ (insert "@article{someID,
+ author = {some author},
+ title = {some title},
+}")
+ (bibtex-mode)
+ (should (progn (bibtex-parse-buffers-stealthily) t))))
+
+(provide 'bibtex-tests)
+
+;;; bibtex-tests.el ends here
diff --git a/test/lisp/textmodes/conf-mode-tests.el b/test/lisp/textmodes/conf-mode-tests.el
new file mode 100644
index 00000000000..097b25f1144
--- /dev/null
+++ b/test/lisp/textmodes/conf-mode-tests.el
@@ -0,0 +1,201 @@
+;;; conf-mode-tests.el --- Test suite for conf mode -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2016-2022 Free Software Foundation, Inc.
+
+;; Author: J. Alexander Branham <alex.branham@gmail.com>
+;; Keywords: internal
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+(require 'conf-mode)
+(require 'ert)
+
+(ert-deftest conf-test-align-assignments ()
+ "Test for `conf-align-assignments'."
+ (with-temp-buffer
+ (insert "foo: bar\nbar: baz")
+ (conf-colon-mode)
+ (conf-align-assignments)
+ (should (equal (buffer-string)
+ "foo: bar\nbar: baz"))))
+
+(ert-deftest conf-test-font-lock ()
+ (with-temp-buffer
+ (insert "foo: bar\nbar: baz")
+ (conf-colon-mode)
+ (font-lock-mode)
+ (font-lock-ensure)
+ (goto-char (point-min))
+ (should (equal (face-at-point) 'font-lock-variable-name-face))
+ (search-forward "bar")
+ (should-not (face-at-point))))
+
+(ert-deftest conf-test-windows-mode ()
+ (with-temp-buffer
+ ;; from `conf-windows-mode' docstring:
+ (insert "[ExtShellFolderViews]
+Default={5984FFE0-28D4-11CF-AE66-08002B2E1262}
+{5984FFE0-28D4-11CF-AE66-08002B2E1262}={5984FFE0-28D4-11CF-AE66-08002B2E1262}
+
+[{5984FFE0-28D4-11CF-AE66-08002B2E1262}]
+PersistMoniker=file://Folder.htt")
+ (goto-char (point-min))
+ (conf-windows-mode)
+ (font-lock-mode)
+ (font-lock-ensure)
+ (search-forward "ExtShell")
+ (should (equal (face-at-point) 'font-lock-type-face))
+ (search-forward "Defau")
+ (should (equal (face-at-point) 'font-lock-variable-name-face))
+ (forward-line)
+ (beginning-of-line)
+ (should (equal (face-at-point) 'font-lock-variable-name-face))
+ (forward-line 2)
+ (should-not (face-at-point))
+ (forward-char)
+ (should (equal (face-at-point) 'font-lock-type-face))))
+
+(ert-deftest conf-test-javaprop-mode ()
+ (with-temp-buffer
+ ;; From `conf-javaprop-mode' docstring
+ (insert "# comment
+
+name:value
+name=value
+name value
+x.1 =
+x.2.y.1.z.1 =
+x.2.y.1.z.2.zz =")
+ (goto-char (point-min))
+ (conf-javaprop-mode)
+ (font-lock-mode)
+ (font-lock-ensure)
+ (should (equal (face-at-point) 'font-lock-comment-delimiter-face))
+ (forward-char 3)
+ (should (equal (face-at-point) 'font-lock-comment-face))
+ (while (search-forward "nam" nil t)
+ (should (equal (face-at-point) 'font-lock-variable-name-face))
+ (search-forward "val")
+ (should-not (face-at-point)))
+ (while (re-search-forward "a-z" nil t)
+ (backward-char)
+ (should (equal (face-at-point) 'font-lock-variable-name-face))
+ (re-search-forward "[0-0]" nil t)
+ (backward-char)
+ (should (equal (face-at-point) 'font-lock-constant-face)))))
+
+(ert-deftest conf-test-space-mode ()
+ ;; From `conf-space-mode' docstring.
+ (with-temp-buffer
+ (insert "image/jpeg jpeg jpg jpe
+image/png png
+image/tiff tiff tif
+")
+ (goto-char (point-min))
+ (conf-space-mode)
+ (font-lock-mode)
+ (font-lock-ensure)
+ (should (equal (face-at-point) 'font-lock-variable-name-face))
+ (forward-char 15)
+ (should-not (face-at-point))))
+
+(ert-deftest conf-test-colon-mode ()
+ ;; From `conf-colon-mode' docstring.
+ (with-temp-buffer
+ (insert "<Multi_key> <exclam> <exclam> : \"\\241\" exclamdown
+<Multi_key> <c> <slash> : \"\\242\" cent")
+ (goto-char (point-min))
+ (conf-colon-mode)
+ (font-lock-mode)
+ (font-lock-ensure)
+ (should (equal (face-at-point) 'font-lock-variable-name-face))
+ (search-forward "24")
+ (should (equal (face-at-point) 'font-lock-string-face))
+ (forward-line)
+ (should (equal (face-at-point) 'font-lock-variable-name-face))))
+
+(ert-deftest conf-test-ppd-mode ()
+ ;; From `conf-ppd-mode' docstring.
+ (with-temp-buffer
+ (insert "*DefaultTransfer: Null
+*Transfer Null.Inverse: \"{ 1 exch sub }\"")
+ (goto-char (point-min))
+ (conf-ppd-mode)
+ (font-lock-mode)
+ (font-lock-ensure)
+ (should (equal (face-at-point) 'font-lock-variable-name-face))
+ (search-forward "Nul")
+ (should-not (face-at-point))))
+
+(ert-deftest conf-test-xdefaults-mode ()
+ ;; From `conf-xdefaults-mode' docstring.
+ (with-temp-buffer
+ (insert "*background: gray99
+*foreground: black")
+ (goto-char (point-min))
+ (conf-xdefaults-mode)
+ (font-lock-mode)
+ (font-lock-ensure)
+ (should (equal (face-at-point) 'font-lock-variable-name-face))
+ (search-forward "gray")
+ (should-not (face-at-point))))
+
+(ert-deftest conf-test-toml-mode ()
+ ;; From `conf-toml-mode' docstring.
+ (with-temp-buffer
+ (insert "[entry]
+value = \"some string\"")
+ (goto-char (point-min))
+ (conf-toml-mode)
+ (font-lock-mode)
+ (font-lock-ensure)
+ (should-not (face-at-point))
+ (forward-char)
+ (should (equal (face-at-point) 'font-lock-type-face))
+ (forward-line)
+ (should (equal (face-at-point) 'font-lock-variable-name-face))
+ (search-forward "som")
+ (should (equal (face-at-point) 'font-lock-string-face))))
+
+(ert-deftest conf-test-desktop-mode ()
+ ;; From `conf-desktop-mode' dostring.
+ (with-temp-buffer
+ (insert " [Desktop Entry]
+ Name=GNU Image Manipulation Program
+ Name[oc]=Editor d'imatge GIMP
+ Exec=gimp-2.8 %U
+ Terminal=false")
+ (goto-char (point-min))
+ (conf-desktop-mode)
+ (font-lock-mode)
+ (font-lock-ensure)
+ (search-forward "Desk")
+ (should (equal (face-at-point) 'font-lock-type-face))
+ (search-forward "Nam")
+ (should (equal (face-at-point) 'font-lock-variable-name-face))
+ (forward-char 2)
+ (should-not (face-at-point))
+ (search-forward "[")
+ (should (equal (face-at-point) 'font-lock-constant-face))))
+
+
+
+(provide 'conf-mode-tests)
+
+;;; conf-mode-tests.el ends here
diff --git a/test/lisp/textmodes/css-mode-resources/css-selectors.txt b/test/lisp/textmodes/css-mode-resources/css-selectors.txt
new file mode 100644
index 00000000000..5b3d990f279
--- /dev/null
+++ b/test/lisp/textmodes/css-mode-resources/css-selectors.txt
@@ -0,0 +1,56 @@
+#firstname
+*
+p
+p.intro
+div, p
+div p
+div > p
+div + p
+p ~ ul
+[target]
+[target=_blank]
+[title~=flower]
+[lang|=en]
+a[href^="https"]
+a[href$=".pdf"]
+a[href*="w3schools"]
+a:active
+p::after
+p::before
+input:checked
+input:default
+input:disabled
+p:empty
+input:enabled
+p:first-child
+p::first-letter
+p::first-line
+p:first-of-type
+input:focus
+:fullscreen
+a:hover
+input:in-range
+input:indeterminate
+input:invalid
+p:lang(it)
+p:last-child
+p:last-of-type
+a:link
+::marker
+:not(p)
+p:nth-child(2)
+p:nth-last-child(2)
+p:nth-last-of-type(2)
+p:nth-of-type(2)
+p:only-of-type
+p:only-child
+input:optional
+input:out-of-range
+input:read-only
+input:read-write
+input:required
+:root
+::selection
+#news:target
+input:valid
+a:visited
diff --git a/test/lisp/textmodes/css-mode-resources/scss-selectors.txt b/test/lisp/textmodes/css-mode-resources/scss-selectors.txt
new file mode 100644
index 00000000000..3e05191a910
--- /dev/null
+++ b/test/lisp/textmodes/css-mode-resources/scss-selectors.txt
@@ -0,0 +1,10 @@
+p.#{$name} var
+p.#{$name}:active var
+p.#{$name}::after var
+f.#{$bar}::after p::after
+p.#{$name} f.#{$bar} k.var #{$bar} #{$bar}
+p.#{$name}
+&:hover
+> li
++ li
+~ li
diff --git a/test/manual/indent/css-mode.css b/test/lisp/textmodes/css-mode-resources/test-indent.css
index bf612b53a14..041aeec1b15 100644
--- a/test/manual/indent/css-mode.css
+++ b/test/lisp/textmodes/css-mode-resources/test-indent.css
@@ -56,6 +56,8 @@ div::before {
sans-serif;
font: 15px "Helvetica Neue", Helvetica, Arial,
"Nimbus Sans L", sans-serif;
+ background: no-repeat right
+ 5px center;
transform: matrix(1.0, 2.0,
3.0, 4.0,
5.0, 6.0);
@@ -66,6 +68,16 @@ div::before {
);
}
+/* Multi-line selector including both a pseudo-class and
+ parenthesis. */
+.form-group:not(.required) label,
+.birth-date .row > * {
+ &::after {
+ display: inline;
+ font-weight: normal;
+ }
+}
+
@font-face {
src: url("Sans-Regular.eot") format("eot"),
url("Sans-Regular.woff") format("woff"),
@@ -80,5 +92,9 @@ div::before {
.foo-bar--baz {
--foo-variable: 5px;
+ --_variable_with_underscores: #fff;
+ --_variable-starting-with-underscore: none;
margin: var(--foo-variable);
+ color: var(--_variable_with_underscores);
+ display: var(--_variable-starting-with-underscore);
}
diff --git a/test/lisp/textmodes/css-mode-tests.el b/test/lisp/textmodes/css-mode-tests.el
index 47cf5f9244b..1d2d556992b 100644
--- a/test/lisp/textmodes/css-mode-tests.el
+++ b/test/lisp/textmodes/css-mode-tests.el
@@ -1,24 +1,26 @@
;;; css-mode-tests.el --- Test suite for CSS mode -*- lexical-binding: t; -*-
-;; Copyright (C) 2016-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2022 Free Software Foundation, Inc.
;; Author: Simen Heggestøyl <simenheg@gmail.com>
;; Keywords: internal
;; This file is part of GNU Emacs.
-;; This program is free software; you can redistribute it and/or modify
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
-;; This program is distributed in the hope that it will be useful,
+;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
-;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
@@ -26,6 +28,7 @@
(require 'css-mode)
(require 'ert)
+(require 'ert-x)
(require 'seq)
(ert-deftest css-test-property-values ()
@@ -58,7 +61,7 @@
;; Check that the `color' property doesn't cause infinite recursion
;; because it refers to the value class of the same name.
- (should (= (length (css--property-values "color")) 152)))
+ (should (= (length (css--property-values "color")) 154)))
(ert-deftest css-test-property-value-cache ()
"Test that `css--property-value-cache' is in use."
@@ -85,7 +88,7 @@
(insert "body { top: 0; }")
(goto-char 7)
(should (equal (css-current-defun-name) "body"))
- (goto-char 18)
+ (goto-char 15)
(should (equal (css-current-defun-name) "body"))))
(ert-deftest css-test-current-defun-name-nested ()
@@ -140,20 +143,20 @@
(css-mode)
(insert "body:a")
(let ((completions (css-mode-tests--completions)))
- (should (member "active" completions))
- (should-not (member "disabled" completions))
+ (should (member ":active" completions))
+ (should-not (member ":disabled" completions))
;; Don't include pseudo-elements
- (should-not (member "after" completions)))))
+ (should-not (member "::after" completions)))))
(ert-deftest css-test-complete-pseudo-element ()
(with-temp-buffer
(css-mode)
(insert "body::a")
(let ((completions (css-mode-tests--completions)))
- (should (member "after" completions))
- (should-not (member "disabled" completions))
+ (should (member "::after" completions))
+ (should-not (member "::disabled" completions))
;; Don't include pseudo-classes
- (should-not (member "active" completions)))))
+ (should-not (member ":active" completions)))))
(ert-deftest css-test-complete-at-rule ()
(with-temp-buffer
@@ -244,6 +247,99 @@
(should (member "body" completions))
(should-not (member "article" completions)))))
+(ert-deftest css-test-color-to-4-dpc ()
+ (should (equal (css--color-to-4-dpc "#ffffff")
+ (css--color-to-4-dpc "#fff")))
+ (should (equal (css--color-to-4-dpc "#aabbcc")
+ (css--color-to-4-dpc "#abc")))
+ (should (equal (css--color-to-4-dpc "#fab")
+ "#ffffaaaabbbb"))
+ (should (equal (css--color-to-4-dpc "#fafbfc")
+ "#fafafbfbfcfc")))
+
+(ert-deftest css-test-format-hex ()
+ (should (equal (css--format-hex "#fff") "#fff"))
+ (should (equal (css--format-hex "#ffffff") "#fff"))
+ (should (equal (css--format-hex "#aabbcc") "#abc"))
+ (should (equal (css--format-hex "#12ff34") "#12ff34"))
+ (should (equal (css--format-hex "#aabbccdd") "#abcd"))
+ (should (equal (css--format-hex "#aabbccde") "#aabbccde"))
+ (should (equal (css--format-hex "#abcdef") "#abcdef")))
+
+(ert-deftest css-test-named-color-to-hex ()
+ (dolist (item '(("black" "#000")
+ ("white" "#fff")
+ ("salmon" "#fa8072")))
+ (with-temp-buffer
+ (css-mode)
+ (insert (nth 0 item))
+ (css--named-color-to-hex)
+ (should (equal (buffer-string) (nth 1 item))))))
+
+(ert-deftest css-test-format-rgba-alpha ()
+ (should (equal (css--format-rgba-alpha 0) "0"))
+ (should (equal (css--format-rgba-alpha 0.0) "0"))
+ (should (equal (css--format-rgba-alpha 0.00001) "0"))
+ (should (equal (css--format-rgba-alpha 1) "1"))
+ (should (equal (css--format-rgba-alpha 1.0) "1"))
+ (should (equal (css--format-rgba-alpha 1.00001) "1"))
+ (should (equal (css--format-rgba-alpha 0.10000) "0.1"))
+ (should (equal (css--format-rgba-alpha 0.100001) "0.1"))
+ (should (equal (css--format-rgba-alpha 0.2524334) "0.25")))
+
+(ert-deftest css-test-hex-to-rgb ()
+ (dolist (item '(("#000" "rgb(0, 0, 0)")
+ ("#000000" "rgb(0, 0, 0)")
+ ("#fff" "rgb(255, 255, 255)")
+ ("#ffffff" "rgb(255, 255, 255)")
+ ("#ffffff80" "rgba(255, 255, 255, 0.5)")
+ ("#fff0" "rgba(255, 255, 255, 0)")
+ ("#fff8" "rgba(255, 255, 255, 0.53)")
+ ("#ffff" "rgba(255, 255, 255, 1)")))
+ (with-temp-buffer
+ (css-mode)
+ (insert (nth 0 item))
+ (css--hex-to-rgb)
+ (should (equal (buffer-string) (nth 1 item))))))
+
+(ert-deftest css-test-rgb-to-named-color-or-hex ()
+ (dolist (item '(("rgb(0, 0, 0)" "black")
+ ("rgb(255, 255, 255)" "white")
+ ("rgb(255, 255, 240)" "ivory")
+ ("rgb(18, 52, 86)" "#123456")
+ ("rgba(18, 52, 86, 0.5)" "#12345680")
+ ("rgba(18, 52, 86, 50%)" "#12345680")
+ ("rgba(50%, 50%, 50%, 50%)" "#80808080")))
+ (with-temp-buffer
+ (css-mode)
+ (insert (nth 0 item))
+ (css--rgb-to-named-color-or-hex)
+ (should (equal (buffer-string) (nth 1 item))))))
+
+(ert-deftest css-test-cycle-color-format ()
+ (with-temp-buffer
+ (css-mode)
+ (insert "black")
+ (css-cycle-color-format)
+ (should (equal (buffer-string) "#000"))
+ (css-cycle-color-format)
+ (should (equal (buffer-string) "rgb(0, 0, 0)"))
+ (css-cycle-color-format)
+ (should (equal (buffer-string) "black"))))
+
+(ert-deftest css-test-join-nested-selectors ()
+ (should (equal (css--join-nested-selectors '("div" "&:hover"))
+ "div:hover"))
+ (should
+ (equal (css--join-nested-selectors '("a" "&::before, &::after"))
+ "a::before, a::after"))
+ (should
+ (equal (css--join-nested-selectors
+ '("article" "& > .front-page" "& h1, & h2"))
+ "article > .front-page h1, article > .front-page h2"))
+ (should (equal (css--join-nested-selectors '(".link" "& + &"))
+ ".link + .link")))
+
(ert-deftest css-mdn-symbol-guessing ()
(dolist (item '(("@med" "ia" "@media")
("@keyframes " "{" "@keyframes")
@@ -263,11 +359,11 @@
(ert-deftest css-test-rgb-parser ()
(with-temp-buffer
(css-mode)
- (dolist (input '("255, 0, 127"
- "255, /* comment */ 0, 127"
- "255 0 127"
- "255, 0, 127, 0.75"
- "255 0 127 / 0.75"
+ (dolist (input '("255, 0, 128"
+ "255, /* comment */ 0, 128"
+ "255 0 128"
+ "255, 0, 128, 0.75"
+ "255 0 128 / 0.75"
"100%, 0%, 50%"
"100%, 0%, 50%, 0.115"
"100% 0% 50%"
@@ -275,7 +371,7 @@
(erase-buffer)
(save-excursion
(insert input ")"))
- (should (equal (css--rgb-color) "#ff007f")))))
+ (should (equal (css--rgb-color) "#ff0080")))))
(ert-deftest css-test-hsl-parser ()
(with-temp-buffer
@@ -295,6 +391,18 @@
(insert input ")"))
(should (equal (css--hsl-color) "#ff0000")))))
+(ert-deftest css-test-hex-color ()
+ (should (equal (css--hex-color "#abc") "#abc"))
+ (should (equal (css--hex-color "#abcd") "#abc"))
+ (should (equal (css--hex-color "#aabbcc") "#aabbcc"))
+ (should (equal (css--hex-color "#aabbccdd") "#aabbcc")))
+
+(ert-deftest css-test-hex-alpha ()
+ (should (equal (css--hex-alpha "#abcd") "d"))
+ (should-not (css--hex-alpha "#abc"))
+ (should (equal (css--hex-alpha "#aabbccdd") "dd"))
+ (should-not (css--hex-alpha "#aabbcc")))
+
(ert-deftest css-test-named-color ()
(dolist (text '("@mixin black" "@include black"))
(with-temp-buffer
@@ -304,5 +412,81 @@
(point))
"black")))))
+(ert-deftest css-mode-test-indent ()
+ (with-current-buffer
+ (find-file-noselect (ert-resource-file "test-indent.css"))
+ (let ((orig (buffer-string)))
+ (indent-region (point-min) (point-max))
+ (should (equal (buffer-string) orig)))))
+
+(ert-deftest css-mode-test-selectors ()
+ (let ((selectors
+ (with-temp-buffer
+ (insert-file-contents (ert-resource-file "css-selectors.txt"))
+ (string-lines (buffer-string)))))
+ (with-suppressed-warnings ((interactive-only font-lock-debug-fontify))
+ (dolist (selector selectors)
+ (with-temp-buffer
+ (css-mode)
+ (insert selector " {\n}\n")
+ (font-lock-debug-fontify)
+ (goto-char (point-min))
+ (unless (eq (get-text-property (point) 'face)
+ 'css-selector)
+ (should-not (format "Didn't recognize %s as a selector"
+ (buffer-substring-no-properties
+ (point) (pos-eol)))))))
+ ;; Test many selectors.
+ (dolist (selector selectors)
+ (with-temp-buffer
+ (css-mode)
+ (insert selector " ")
+ (dotimes (_ (random 5))
+ (insert (seq-random-elt '(" , " " > " " + "))
+ (seq-random-elt selectors)))
+ (insert "{\n}\n")
+ (font-lock-debug-fontify)
+ (goto-char (point-min))
+ (unless (eq (get-text-property (point) 'face)
+ 'css-selector)
+ (should-not (format "Didn't recognize %s as a selector"
+ (buffer-substring-no-properties
+ (point) (pos-eol)))))))
+ ;; Test wrong separators.
+ (dolist (selector selectors)
+ (with-temp-buffer
+ (css-mode)
+ (insert selector " ")
+ (dotimes (_ (1+ (random 5)))
+ (insert (seq-random-elt '("=" " @ "))
+ (seq-random-elt selectors)))
+ (insert "{\n}\n")
+ (font-lock-debug-fontify)
+ (goto-char (point-min))
+ (when (eq (get-text-property (point) 'face)
+ 'css-selector)
+ (should-not (format "Recognized %s as a selector"
+ (buffer-substring-no-properties
+ (point) (pos-eol))))))))))
+
+(ert-deftest scss-mode-test-selectors ()
+ (let ((selectors
+ (with-temp-buffer
+ (insert-file-contents (ert-resource-file "scss-selectors.txt"))
+ (string-lines (buffer-string)))))
+ (with-suppressed-warnings ((interactive-only font-lock-debug-fontify))
+ (dolist (selector selectors)
+ (with-temp-buffer
+ (scss-mode)
+ (insert selector " {\n}\n")
+ (font-lock-debug-fontify)
+ (goto-char (point-min))
+ (unless (eq (get-text-property (point) 'face)
+ 'css-selector)
+ (should-not (format "Didn't recognize %s as a selector"
+ (buffer-substring-no-properties
+ (point) (pos-eol))))))))))
+
+
(provide 'css-mode-tests)
;;; css-mode-tests.el ends here
diff --git a/test/lisp/textmodes/dns-mode-tests.el b/test/lisp/textmodes/dns-mode-tests.el
index f71f9040df7..40896cf2f38 100644
--- a/test/lisp/textmodes/dns-mode-tests.el
+++ b/test/lisp/textmodes/dns-mode-tests.el
@@ -1,6 +1,6 @@
;;; dns-mode-tests.el --- Test suite for dns-mode -*- lexical-binding: t; -*-
-;; Copyright (C) 2017 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2022 Free Software Foundation, Inc.
;; Author: Peder O. Klingenberg <peder@klingenberg.no>
;; Keywords: dns zone
@@ -25,6 +25,27 @@
(require 'ert)
(require 'dns-mode)
+(ert-deftest dns-mode-tests-dns-mode-soa-increment-serial ()
+ (with-temp-buffer
+ (insert "$TTL 86400
+@ IN SOA ns.icann.org. noc.dns.icann.org. (
+ 2015080302 ;Serial
+ 7200 ;Refresh
+ 3600 ;Retry
+ 1209600 ;Expire
+ 3600 ;Negative response caching TTL\n)")
+ (dns-mode-soa-increment-serial)
+ ;; Number is updated from 2015080302 to the current date
+ ;; (actually, just ensure the year part is later than 2020).
+ (should (string-match "\\$TTL 86400
+@ IN SOA ns.icann.org. noc.dns.icann.org. (
+ 20[2-9][0-9]+ ;Serial
+ 7200 ;Refresh
+ 3600 ;Retry
+ 1209600 ;Expire
+ 3600 ;Negative response caching TTL\n)"
+ (buffer-string)))))
+
;;; IPv6 reverse zones
(ert-deftest dns-mode-ipv6-conversion ()
(let ((address "2001:db8::42"))
@@ -56,3 +77,5 @@
(insert " ")
(dns-mode-ipv6-to-nibbles nil)
(should (equal (buffer-string) "8.b.d.0.1.0.0.2.ip6.arpa. ")))))
+
+;;; dns-mode-tests.el ends here
diff --git a/test/lisp/textmodes/emacs-news-mode-resources/toggle-tag.erts b/test/lisp/textmodes/emacs-news-mode-resources/toggle-tag.erts
new file mode 100644
index 00000000000..63c3b1b7d8a
--- /dev/null
+++ b/test/lisp/textmodes/emacs-news-mode-resources/toggle-tag.erts
@@ -0,0 +1,131 @@
+Name: tag1
+Point-Char: |
+
+=-=
++++
+*** 'dired-do-relsymlink-regexp' moved from dired-x to dired.
+The corresponding key "% Y" is now bound by default in Dired.
+
+*** 'M-G' is now bound to 'dired-goto-subdir'.
+|Before, that binding was only available with 'dired-x'.
+=-=
++++
+*** 'dired-do-relsymlink-regexp' moved from dired-x to dired.
+The corresponding key "% Y" is now bound by default in Dired.
+
+---
+*** 'M-G' is now bound to 'dired-goto-subdir'.
+|Before, that binding was only available with 'dired-x'.
+=-=-=
+
+Name: tag2
+Point-Char: |
+
+=-=
++++
+*** 'dired-do-relsymlink-regexp' moved from dired-x to dired.
+The corresponding key "% Y" is now bound by default in Dired.
+
+---
+*** 'M-G' is now bound to 'dired-goto-subdir'.
+|Before, that binding was only available if the 'dired-x' package was
+loaded.
+=-=
++++
+*** 'dired-do-relsymlink-regexp' moved from dired-x to dired.
+The corresponding key "% Y" is now bound by default in Dired.
+
++++
+*** 'M-G' is now bound to 'dired-goto-subdir'.
+|Before, that binding was only available if the 'dired-x' package was
+loaded.
+=-=-=
+
+Name: tag3
+Point-Char: |
+
+=-=
++++
+*** 'dired-do-relsymlink-regexp' moved from dired-x to dired.
+The corresponding key "% Y" is now bound by default in Dired.
+
++++
+*** 'M-G' is now bound to 'dired-goto-subdir'.
+|Before, that binding was only available if the 'dired-x' package was
+loaded.
+=-=
++++
+*** 'dired-do-relsymlink-regexp' moved from dired-x to dired.
+The corresponding key "% Y" is now bound by default in Dired.
+
+*** 'M-G' is now bound to 'dired-goto-subdir'.
+|Before, that binding was only available if the 'dired-x' package was
+loaded.
+=-=-=
+
+Name: tag4-point-at-headline
+Point-Char: |
+
+=-=
++++
+*** 'dired-do-relsymlink-regexp' moved from dired-x to dired.
+The corresponding key "% Y" is now bound by default in Dired.
+
+|*** 'M-G' is now bound to 'dired-goto-subdir'.
+Before, that binding was only available if the 'dired-x' package was
+loaded.
+=-=
++++
+*** 'dired-do-relsymlink-regexp' moved from dired-x to dired.
+The corresponding key "% Y" is now bound by default in Dired.
+
+---
+|*** 'M-G' is now bound to 'dired-goto-subdir'.
+Before, that binding was only available if the 'dired-x' package was
+loaded.
+=-=-=
+
+Name: tag5-point-at-tag
+Point-Char: |
+
+=-=
++++
+*** 'dired-do-relsymlink-regexp' moved from dired-x to dired.
+The corresponding key "% Y" is now bound by default in Dired.
+
+|---
+*** 'M-G' is now bound to 'dired-goto-subdir'.
+Before, that binding was only available if the 'dired-x' package was
+loaded.
+=-=
++++
+*** 'dired-do-relsymlink-regexp' moved from dired-x to dired.
+The corresponding key "% Y" is now bound by default in Dired.
+
+|+++
+*** 'M-G' is now bound to 'dired-goto-subdir'.
+Before, that binding was only available if the 'dired-x' package was
+loaded.
+=-=-=
+
+Name: tag6-point-at-tag
+Point-Char: |
+
+=-=
++++
+*** 'dired-do-relsymlink-regexp' moved from dired-x to dired.
+The corresponding key "% Y" is now bound by default in Dired.
+
+|+++
+*** 'M-G' is now bound to 'dired-goto-subdir'.
+Before, that binding was only available if the 'dired-x' package was
+loaded.
+=-=
++++
+*** 'dired-do-relsymlink-regexp' moved from dired-x to dired.
+The corresponding key "% Y" is now bound by default in Dired.
+
+|*** 'M-G' is now bound to 'dired-goto-subdir'.
+Before, that binding was only available if the 'dired-x' package was
+loaded.
+=-=-=
diff --git a/test/lisp/textmodes/emacs-news-mode-tests.el b/test/lisp/textmodes/emacs-news-mode-tests.el
new file mode 100644
index 00000000000..d2da5eda906
--- /dev/null
+++ b/test/lisp/textmodes/emacs-news-mode-tests.el
@@ -0,0 +1,32 @@
+;;; emacs-news-mode-tests.el --- Tests for emacs-news-mode.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'ert-x)
+(require 'emacs-news-mode)
+
+(ert-deftest emacs-news-toggle-tag ()
+ (ert-test-erts-file (ert-resource-file "toggle-tag.erts")
+ (lambda ()
+ (emacs-news-mode)
+ (emacs-news-toggle-tag))))
+
+;;; emacs-news-mode-tests.el ends here
diff --git a/test/lisp/textmodes/fill-tests.el b/test/lisp/textmodes/fill-tests.el
new file mode 100644
index 00000000000..f2a0daf8122
--- /dev/null
+++ b/test/lisp/textmodes/fill-tests.el
@@ -0,0 +1,126 @@
+;;; fill-tests.el --- ERT tests for fill.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2017-2022 Free Software Foundation, Inc.
+
+;; Author: Marcin Borkowski <mbork@mbork.pl>
+;; Keywords: text, wp
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This package defines tests for the filling feature, specifically
+;; the `fill-polish-nobreak-p' function.
+
+;;; Code:
+
+(require 'ert)
+
+(ert-deftest fill-test-no-fill-polish-nobreak-p nil
+ "Tests of the `fill-polish-nobreak-p' function."
+ (with-temp-buffer
+ (insert "Abc d efg (h ijk).")
+ (setq fill-column 8)
+ (setq-local fill-nobreak-predicate '())
+ (fill-paragraph)
+ (should (string= (buffer-string) "Abc d\nefg (h\nijk).")))
+ (with-temp-buffer
+ (insert "Abc d efg (h ijk).")
+ (setq fill-column 8)
+ (setq-local fill-nobreak-predicate '(fill-polish-nobreak-p))
+ (fill-paragraph)
+ (should (string= (buffer-string) "Abc\nd efg\n(h ijk)."))))
+
+(ert-deftest fill-test-unbreakable-paragraph ()
+ ;; See bug#45720 and bug#53537.
+ :expected-result :failed
+ (with-temp-buffer
+ (let ((string "aaa = baaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"))
+ (insert string)
+ (goto-char (point-min))
+ (search-forward "b")
+ (let* ((pos (point))
+ (beg (pos-bol))
+ (end (pos-eol))
+ (fill-prefix (make-string (- pos beg) ?\s))
+ ;; `fill-column' is too small to accommodate the current line
+ (fill-column (- end beg 10)))
+ (fill-region-as-paragraph beg end nil nil pos))
+ (should (equal (buffer-string) string)))))
+
+(ert-deftest fill-test-breakable-paragraph ()
+ (with-temp-buffer
+ (let ((string "aaa = baaaaaaaa aaaaaaaaaa aaaaaaaaaa\n"))
+ (insert string)
+ (goto-char (point-min))
+ (search-forward "b")
+ (let* ((pos (point))
+ (beg (pos-bol))
+ (end (pos-eol))
+ (fill-prefix (make-string (- pos beg) ?\s))
+ ;; `fill-column' is too small to accommodate the current line
+ (fill-column (- end beg 10)))
+ (fill-region-as-paragraph beg end nil nil pos))
+ (should (equal
+ (buffer-string)
+ "aaa = baaaaaaaa aaaaaaaaaa\n aaaaaaaaaa\n")))))
+
+(ert-deftest test-fill-end-period ()
+ (should
+ (equal
+ (with-temp-buffer
+ (text-mode)
+ (auto-fill-mode)
+ (insert "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eius.")
+ (self-insert-command 1 ?\s)
+ (buffer-string))
+ "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eius. "))
+ (should
+ (equal
+ (with-temp-buffer
+ (text-mode)
+ (auto-fill-mode)
+ (insert "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eius.Foo")
+ (forward-char -3)
+ (self-insert-command 1 ?\s)
+ (buffer-string))
+ "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do
+eius. Foo")))
+
+(ert-deftest test-fill-haskell ()
+ (should
+ (equal
+ (with-temp-buffer
+ (asm-mode)
+ (dolist (line '(" ;; a b c"
+ " ;; d e f"
+ " ;; x y z"
+ " ;; w"))
+ (insert line "\n"))
+ (goto-char (point-min))
+ (end-of-line)
+ (setf fill-column 10)
+ (fill-paragraph nil)
+ (buffer-string))
+ " ;; a b c
+ ;; d e f
+ ;; x y z
+ ;; w
+")))
+
+(provide 'fill-tests)
+
+;;; fill-tests.el ends here
diff --git a/test/lisp/textmodes/mhtml-mode-tests.el b/test/lisp/textmodes/mhtml-mode-tests.el
index df49f6780fa..f09a768f985 100644
--- a/test/lisp/textmodes/mhtml-mode-tests.el
+++ b/test/lisp/textmodes/mhtml-mode-tests.el
@@ -1,6 +1,6 @@
-;;; mhtml-mode-tests.el --- Tests for mhtml-mode
+;;; mhtml-mode-tests.el --- Tests for mhtml-mode -*- lexical-binding:t -*-
-;; Copyright (C) 2017 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2022 Free Software Foundation, Inc.
;; Keywords: tests
diff --git a/test/lisp/textmodes/page-tests.el b/test/lisp/textmodes/page-tests.el
new file mode 100644
index 00000000000..b7217e69f0c
--- /dev/null
+++ b/test/lisp/textmodes/page-tests.el
@@ -0,0 +1,115 @@
+;;; page-tests.el --- Tests for page.el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2019-2022 Free Software Foundation, Inc.
+
+;; Author: Simen Heggestøyl <simenheg@gmail.com>
+;; Keywords:
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;
+
+;;; Code:
+
+(require 'ert)
+(require 'page)
+
+(ert-deftest page-tests-forward-page ()
+ (with-temp-buffer
+ (insert "foo\n \nbar\n \nbaz")
+ (forward-page -1)
+ (should (looking-at-p "\nbaz"))
+ (forward-page -2)
+ (should (= (point) (point-min)))
+ (forward-page 1)
+ (should (looking-at-p "\nbar"))
+ (forward-page)
+ (should (looking-at-p "\nbaz"))
+ (forward-page 1)
+ (should (= (point) (point-max)))))
+
+(ert-deftest page-tests-backward-page ()
+ (with-temp-buffer
+ (insert "foo\n \nbar\n \nbaz")
+ (backward-page 1)
+ (should (looking-at-p "\nbaz"))
+ (backward-page)
+ (should (looking-at-p "\nbar"))
+ (backward-page 1)
+ (should (= (point) (point-min)))
+ (backward-page -1)
+ (should (looking-at-p "\nbar"))
+ (backward-page -2)
+ (should (= (point) (point-max)))))
+
+(defun page-tests--region-string ()
+ "Return the contents of the region as a string."
+ (buffer-substring (region-beginning) (region-end)))
+
+(ert-deftest page-tests-mark-page ()
+ (with-temp-buffer
+ (insert "foo\n \nbar\n \nbaz")
+ (mark-page)
+ (should (equal (page-tests--region-string) "\nbaz"))
+ (mark-page -2)
+ (should (equal (page-tests--region-string) "foo\n "))
+ (mark-page 1)
+ (should (equal (page-tests--region-string) "\nbar\n "))))
+
+(ert-deftest page-tests-narrow-to-page ()
+ (with-temp-buffer
+ (insert "foo\n \nbar\n \nbaz")
+ (goto-char (point-min))
+ (narrow-to-page)
+ (should (equal (buffer-string) "foo\n"))
+ (narrow-to-page 2)
+ (should (equal (buffer-string) "baz"))
+ (narrow-to-page -1)
+ (should (equal (buffer-string) "bar\n"))
+
+ (widen)
+ (goto-char (point-min))
+ (narrow-to-page)
+ (should (equal (buffer-string) "foo\n"))
+ (goto-char (point-max))
+ (narrow-to-page 2)
+ (should (equal (buffer-string) "baz"))
+ (goto-char (point-max))
+ (narrow-to-page -1)
+ (should (equal (buffer-string) "bar\n"))))
+
+(ert-deftest page-tests-count-lines-page ()
+ (with-temp-buffer
+ (insert "foo\n \nbar\n \nbaz")
+ (goto-char (point-min))
+ (should (equal (page--count-lines-page) '(1 0 1)))
+ (goto-char (point-max))
+ (should (equal (page--count-lines-page) '(2 2 0)))))
+
+(ert-deftest page-tests-what-page ()
+ (with-temp-buffer
+ (insert "foo\n \nbar\n \nbaz")
+ (goto-char (point-min))
+ (should (equal (page--what-page) '(1 1)))
+ (forward-page)
+ (should (equal (page--what-page) '(2 2)))
+ (forward-page)
+ (should (equal (page--what-page) '(3 4)))))
+
+
+;;; page-tests.el ends here
diff --git a/test/lisp/textmodes/paragraphs-resources/mark-paragraph.bin b/test/lisp/textmodes/paragraphs-resources/mark-paragraph.bin
new file mode 100644
index 00000000000..1905477af8c
--- /dev/null
+++ b/test/lisp/textmodes/paragraphs-resources/mark-paragraph.bin
@@ -0,0 +1,9 @@
+First
+paragraph
+
+Second
+
+Third
+paragraph
+
+No line end \ No newline at end of file
diff --git a/test/lisp/textmodes/paragraphs-tests.el b/test/lisp/textmodes/paragraphs-tests.el
new file mode 100644
index 00000000000..e54b459b20e
--- /dev/null
+++ b/test/lisp/textmodes/paragraphs-tests.el
@@ -0,0 +1,188 @@
+;;; paragraphs-tests.el --- Tests for paragraphs.el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2019-2022 Free Software Foundation, Inc.
+
+;; Author: Stefan Kangas <stefankangas@gmail.com>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'ert-x)
+;; (require 'paragraphs) ; loaded by default
+
+(ert-deftest paragraphs-tests-sentence-end ()
+ (should (> (length (sentence-end)) 0))
+ (let ((sentence-end "override works"))
+ (should (equal (sentence-end) sentence-end))))
+
+(ert-deftest paragraphs-tests-forward-backward-paragraph ()
+ (with-temp-buffer
+ (insert "AA\nAA\n\nBB\nBB\n")
+ (goto-char (point-min))
+ (forward-paragraph)
+ (should (equal (point) 7))
+ (forward-paragraph)
+ (should (equal (point) 14))
+ (backward-paragraph)
+ (should (equal (point) 7))
+ (backward-paragraph)
+ (should (equal (point) (point-min)))))
+
+(ert-deftest paragraphs-tests-mark-paragraph ()
+ (with-temp-buffer
+ (insert "AA\nAA\n\nBB\nBB\n")
+ (goto-char (point-min))
+ (mark-paragraph)
+ (should mark-active)
+ (should (equal (mark) 7))))
+;;; (should-error (mark-paragraph 0)))
+
+(ert-deftest paragraphs-tests-kill-paragraph ()
+ (with-temp-buffer
+ (insert "AA\nAA\n\nBB\nBB\n")
+ (goto-char (point-min))
+ (kill-paragraph nil)
+ (should (equal (buffer-string) "\nBB\nBB\n"))))
+
+(ert-deftest paragraphs-tests-backward-kill-paragraph ()
+ (with-temp-buffer
+ (insert "AA\nAA\n\nBB\nBB\n")
+ (goto-char 7)
+ (backward-kill-paragraph nil)
+ (should (equal (buffer-string) "\nBB\nBB\n"))))
+
+(ert-deftest paragraphs-tests-transpose-paragraphs ()
+ (with-temp-buffer
+ (insert "AA\nAA\n\nBB\nBB\n")
+ (goto-char (point-min))
+ (transpose-paragraphs 1)
+ (should (equal (buffer-string) "\nBB\nBB\nAA\nAA\n"))))
+
+(ert-deftest paragraphs-tests-start-of-paragraph-text ()
+ (with-temp-buffer
+ (insert "AA\nAA\n\nBB\nBB\n")
+ (goto-char (point-max))
+ (start-of-paragraph-text)
+ (should (equal (point) 8))))
+
+(ert-deftest paragraphs-tests-end-of-paragraph-text ()
+ (with-temp-buffer
+ (insert "AA\nAA\n\nBB\nBB\n")
+ (goto-char (point-min))
+ (end-of-paragraph-text)
+ (should (equal (point) 6))))
+
+(ert-deftest paragraphs-tests-forward-sentence ()
+ (with-temp-buffer
+ (insert "First sentence. Second sentence.")
+ (goto-char (point-min))
+ (forward-sentence)
+ (should (equal (point) 16))
+ (goto-char (point-min))
+ (forward-sentence 2)
+ (should (equal (point) 34))))
+
+(ert-deftest paragraphs-tests-repunctuate-sentences ()
+ (with-temp-buffer
+ (insert "Just. Some. Sentences.")
+ (goto-char (point-min))
+ (repunctuate-sentences t)
+ (should (equal (buffer-string) "Just. Some. Sentences."))))
+
+(ert-deftest paragraphs-tests-backward-sentence ()
+ (with-temp-buffer
+ (insert "First sentence. Second sentence.")
+ (goto-char (point-max))
+ (backward-sentence)
+ (should (equal (point) 18))))
+
+(ert-deftest paragraphs-tests-kill-sentence ()
+ (with-temp-buffer
+ (insert "First sentence. Second sentence.")
+ (goto-char (point-min))
+ (kill-sentence)
+ (should (equal (buffer-string) " Second sentence."))))
+
+(ert-deftest paragraphs-tests-backward-kill-sentence ()
+ (with-temp-buffer
+ (insert "Should not be killed. Should be killed.")
+ (goto-char (point-max))
+ (backward-kill-sentence)
+ (should (equal (buffer-string) "Should not be killed. "))))
+
+(ert-deftest paragraphs-tests-mark-end-of-sentence ()
+ (with-temp-buffer
+ (insert "Example sentence. Followed by another one.")
+ (goto-char (point-min))
+ (mark-end-of-sentence 1)
+ (should mark-active)
+ (should (equal (mark) 18)))
+ (with-temp-buffer
+ (insert "Example sentence. Followed by another one.")
+ (goto-char (point-min))
+ (mark-end-of-sentence 2)
+ (should mark-active)
+ (should (equal (mark) 44)))
+ ;; FIXME: This does not work -- how do I do it?
+ (with-temp-buffer ; test repeating the command
+ (insert "Example sentence. Followed by another one.")
+ (goto-char (point-min))
+ (mark-end-of-sentence 1)
+ (setq last-command 'mark-end-of-sentence) ; hack
+ (mark-end-of-sentence 1)
+ (should mark-active)
+ (should (equal (mark) 18))))
+
+(ert-deftest paragraphs-tests-transpose-sentences ()
+ (with-temp-buffer
+ (insert "First sentence. Second sentence. Third sentence.")
+ (goto-char (point-min))
+ (transpose-sentences 1)
+ (should (equal (buffer-string)
+ "Second sentence. First sentence. Third sentence."))
+ (goto-char (point-min))
+ (transpose-sentences 2)
+ (should (equal (buffer-string)
+ "First sentence. Third sentence. Second sentence."))))
+
+(ert-deftest test-mark-paragraphs ()
+ (with-current-buffer
+ (find-file-noselect (ert-resource-file "mark-paragraph.bin"))
+ (goto-char (point-max))
+ ;; Just a sanity check that the file hasn't changed.
+ (should (= (point) 54))
+ (mark-paragraph)
+ (should (= (point) 42))
+ (should (= (mark) 54))
+ ;; Doesn't move.
+ (mark-paragraph)
+ (should (= (point) 42))
+ (should (= (mark) 54))
+ (forward-line -1)
+ (mark-paragraph)
+ (should (= (point) 25))
+ (should (= (mark) 42))
+ (goto-char (point-min))
+ (mark-paragraph)
+ (should (= (point) 1))
+ (should (= (mark) 17))))
+
+(provide 'paragraphs-tests)
+;;; paragraphs-tests.el ends here
diff --git a/test/lisp/textmodes/po-tests.el b/test/lisp/textmodes/po-tests.el
new file mode 100644
index 00000000000..982d3404ff8
--- /dev/null
+++ b/test/lisp/textmodes/po-tests.el
@@ -0,0 +1,68 @@
+;;; po-tests.el --- Tests for po.el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+;; Author: Simen Heggestøyl <simenheg@gmail.com>
+;; Keywords:
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;
+
+;;; Code:
+
+(require 'po)
+(require 'ert)
+
+(defconst po-tests--buffer-string
+ "# Norwegian bokmål translation of the GIMP.
+# Copyright (C) 1999-2001 Free Software Foundation, Inc.
+#
+msgid \"\"
+msgstr \"\"
+\"Project-Id-Version: gimp 2.8.5\\n\"
+\"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gimp/issues\\n\"
+\"POT-Creation-Date: 2013-05-27 14:57+0200\\n\"
+\"PO-Revision-Date: 2013-05-27 15:21+0200\\n\"
+\"Language: nb\\n\"
+\"MIME-Version: 1.0\\n\"
+\"Content-Type: text/plain; charset=UTF-8\\n\"
+\"Content-Transfer-Encoding: 8bit\\n\"
+\"Plural-Forms: nplurals=2; plural=(n != 1);\\n\"
+
+#: ../desktop/gimp.desktop.in.in.h:1 ../app/about.h:26
+msgid \"GNU Image Manipulation Program\"
+msgstr \"GNU bildebehandlingsprogram\"
+")
+
+(ert-deftest po-tests-find-charset ()
+ (with-temp-buffer
+ (insert po-tests--buffer-string)
+ (should (equal (po-find-charset (cons nil (current-buffer)))
+ "UTF-8"))))
+
+(ert-deftest po-tests-find-file-coding-system-guts ()
+ (with-temp-buffer
+ (insert po-tests--buffer-string)
+ (should (equal (po-find-file-coding-system-guts
+ 'insert-file-contents
+ (cons "*tmp*" (current-buffer)))
+ '(utf-8 . nil)))))
+
+(provide 'po-tests)
+;;; po-tests.el ends here
diff --git a/test/lisp/textmodes/reftex-tests.el b/test/lisp/textmodes/reftex-tests.el
index 0b67b2eb5b9..67e01004755 100644
--- a/test/lisp/textmodes/reftex-tests.el
+++ b/test/lisp/textmodes/reftex-tests.el
@@ -1,6 +1,6 @@
;;; reftex-tests.el --- Test suite for reftex. -*- lexical-binding: t -*-
-;; Copyright (C) 2013-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2022 Free Software Foundation, Inc.
;; Author: Rüdiger Sonderfeld <ruediger@c-plusplus.de>
;; Keywords: internal
@@ -24,6 +24,7 @@
;;; Code:
(require 'ert)
+(require 'ert-x)
;;; reftex
(require 'reftex)
@@ -33,32 +34,31 @@
(ert-deftest reftex-locate-bibliography-files ()
"Test `reftex-locate-bibliography-files'."
- (let ((temp-dir (make-temp-file "reftex-bib" 'dir))
- (files '("ref1.bib" "ref2.bib"))
- (test '(("\\addbibresource{ref1.bib}\n" . ("ref1.bib"))
- ("\\\\addbibresource[label=x]{ref2.bib}\\n" . ("ref2.bib"))
- ("\\begin{document}\n\\bibliographystyle{plain}\n
+ (ert-with-temp-directory temp-dir
+ (let ((files '("ref1.bib" "ref2.bib"))
+ (test '(("\\addbibresource{ref1.bib}\n" . ("ref1.bib"))
+ ("\\\\addbibresource[label=x]{ref2.bib}\\n" . ("ref2.bib"))
+ ("\\begin{document}\n\\bibliographystyle{plain}\n
\\bibliography{ref1,ref2}\n\\end{document}" . ("ref1.bib" "ref2.bib"))))
- (reftex-bibliography-commands
- ;; Default value: See reftex-vars.el `reftex-bibliography-commands'
- '("bibliography" "nobibliography" "setupbibtex\\[.*?database="
- "addbibresource")))
- (with-temp-buffer
- (insert "test\n")
+ (reftex-bibliography-commands
+ ;; Default value: See reftex-vars.el `reftex-bibliography-commands'
+ '("bibliography" "nobibliography" "setupbibtex\\[.*?database="
+ "addbibresource")))
+ (with-temp-buffer
+ (insert "test\n")
+ (mapc
+ (lambda (file)
+ (write-region (point-min) (point-max) (expand-file-name file
+ temp-dir)))
+ files))
(mapc
- (lambda (file)
- (write-region (point-min) (point-max) (expand-file-name file
- temp-dir)))
- files))
- (mapc
- (lambda (data)
- (with-temp-buffer
- (insert (car data))
- (let ((res (mapcar #'file-name-nondirectory
- (reftex-locate-bibliography-files temp-dir))))
- (should (equal res (cdr data))))))
- test)
- (delete-directory temp-dir 'recursive)))
+ (lambda (data)
+ (with-temp-buffer
+ (insert (car data))
+ (let ((res (mapcar #'file-name-nondirectory
+ (reftex-locate-bibliography-files temp-dir))))
+ (should (equal res (cdr data))))))
+ test))))
(ert-deftest reftex-what-environment-test ()
"Test `reftex-what-environment'."
@@ -102,12 +102,12 @@
;; reason. (An alternative solution would be to use file-equal-p,
;; but I'm too lazy to do that, as one of the tests compares a
;; list.)
- (let* ((temp-dir (file-truename (make-temp-file "reftex-parse" 'dir)))
- (tex-file (expand-file-name "test.tex" temp-dir))
- (bib-file (expand-file-name "ref.bib" temp-dir)))
- (with-temp-buffer
- (insert
-"\\begin{document}
+ (ert-with-temp-directory temp-dir
+ (let* ((tex-file (expand-file-name "test.tex" temp-dir))
+ (bib-file (expand-file-name "ref.bib" temp-dir)))
+ (with-temp-buffer
+ (insert
+ "\\begin{document}
\\section{test}\\label{sec:test}
\\subsection{subtest}
@@ -118,27 +118,26 @@
\\bibliographystyle{plain}
\\bibliography{ref}
\\end{document}")
- (write-region (point-min) (point-max) tex-file))
- (with-temp-buffer
- (insert "test\n")
- (write-region (point-min) (point-max) bib-file))
- (reftex-ensure-compiled-variables)
- (let ((parsed (reftex-parse-from-file tex-file nil temp-dir)))
- (should (equal (car parsed) `(eof ,tex-file)))
- (pop parsed)
- (while parsed
- (let ((entry (pop parsed)))
- (cond
- ((eq (car entry) 'bib)
- (should (string= (cadr entry) bib-file)))
- ((eq (car entry) 'toc)) ;; ...
- ((string= (car entry) "eq:foo"))
- ((string= (car entry) "sec:test"))
- ((eq (car entry) 'bof)
- (should (string= (cadr entry) tex-file))
- (should (null parsed)))
- (t (should-not t)))))
- (delete-directory temp-dir 'recursive))))
+ (write-region (point-min) (point-max) tex-file))
+ (with-temp-buffer
+ (insert "test\n")
+ (write-region (point-min) (point-max) bib-file))
+ (reftex-ensure-compiled-variables)
+ (let ((parsed (reftex-parse-from-file tex-file nil temp-dir)))
+ (should (equal (car parsed) `(eof ,tex-file)))
+ (pop parsed)
+ (while parsed
+ (let ((entry (pop parsed)))
+ (cond
+ ((eq (car entry) 'bib)
+ (should (string= (cadr entry) bib-file)))
+ ((eq (car entry) 'toc)) ;; ...
+ ((string= (car entry) "eq:foo"))
+ ((string= (car entry) "sec:test"))
+ ((eq (car entry) 'bof)
+ (should (string= (cadr entry) tex-file))
+ (should (null parsed)))
+ (t (should-not t)))))))))
;;; reftex-cite
(require 'reftex-cite)
@@ -153,24 +152,23 @@
edition = {17th},
note = {Updated for Emacs Version 24.2}
}")
- (check (function
- (lambda (parsed)
- (should (string= (reftex-get-bib-field "&key" parsed)
- "Stallman12"))
- (should (string= (reftex-get-bib-field "&type" parsed)
- "book"))
- (should (string= (reftex-get-bib-field "author" parsed)
- "Richard Stallman et al."))
- (should (string= (reftex-get-bib-field "title" parsed)
- "The Emacs Editor"))
- (should (string= (reftex-get-bib-field "publisher" parsed)
- "GNU Press"))
- (should (string= (reftex-get-bib-field "year" parsed)
- "2012"))
- (should (string= (reftex-get-bib-field "edition" parsed)
- "17th"))
- (should (string= (reftex-get-bib-field "note" parsed)
- "Updated for Emacs Version 24.2"))))))
+ (check (lambda (parsed)
+ (should (string= (reftex-get-bib-field "&key" parsed)
+ "Stallman12"))
+ (should (string= (reftex-get-bib-field "&type" parsed)
+ "book"))
+ (should (string= (reftex-get-bib-field "author" parsed)
+ "Richard Stallman et al."))
+ (should (string= (reftex-get-bib-field "title" parsed)
+ "The Emacs Editor"))
+ (should (string= (reftex-get-bib-field "publisher" parsed)
+ "GNU Press"))
+ (should (string= (reftex-get-bib-field "year" parsed)
+ "2012"))
+ (should (string= (reftex-get-bib-field "edition" parsed)
+ "17th"))
+ (should (string= (reftex-get-bib-field "note" parsed)
+ "Updated for Emacs Version 24.2")))))
(funcall check (reftex-parse-bibtex-entry entry))
(with-temp-buffer
(insert entry)
@@ -192,8 +190,8 @@
(ert-deftest reftex-format-citation-test ()
"Test `reftex-format-citation'."
- (let ((entry (reftex-parse-bibtex-entry
-"@article{Foo13,
+ (let ((entry (reftex-parse-bibtex-entry "\
+@article{Foo13,
author = {Jane Roe and John Doe and Jane Q. Taxpayer},
title = {Some Article},
journal = {Some Journal},
@@ -204,6 +202,310 @@
(should (string= (reftex-format-citation entry "%l:%A:%y:%t %j %P %a")
"Foo13:Jane Roe:2013:Some Article Some Journal 1 Jane Roe, John Doe \\& Jane Taxpayer"))))
+(ert-deftest reftex-all-used-citation-keys ()
+ "Test `reftex-all-used-citation-keys'.
+Take the cite macros provided by biblatex package as reference."
+ (ert-with-temp-directory temp-dir
+ (let ((tex-file (expand-file-name "keys.tex" temp-dir))
+ keys)
+ (with-temp-buffer
+ (insert "\
+\\documentclass{article}
+\\usepackage{biblatex}
+\\begin{document}
+
+Standard commands:
+\\cite[pre][pos]{cite:2022}
+\\Cite[pos]{Cite:2022}
+\\parencite{parencite:2022}
+\\Parencite[pre][]{Parencite:2022}
+\\footcite[][]{footcite:2022}
+\\footcitetext[pre][pos]{footcitetext:2022}
+
+Style specific commands:
+\\textcite{textcite:2022}
+\\Textcite[pos]{Textcite:2022}
+\\smartcite[pre][pos]{smartcite:2022}
+\\Smartcite[pre][]{Smartcite:2022}
+\\cite*[pre][pos]{cite*:2022}
+\\parencite*[][]{parencite*:2022}
+
+Style independent commands:
+\\autocite[pre][pos]{autocite:2022}
+\\autocite*[pos]{autocite*:2022}
+\\Autocite[pre][]{Autocite:2022}
+\\Autocite*{Autocite*:2022}
+
+Text commands:
+\\citeauthor[pre][pos]{citeauthor:2022}
+\\citeauthor*[pre][]{citeauthor*:2022}
+\\Citeauthor[pos]{Citeauthor:2022}
+\\Citeauthor*{Citeauthor*:2022}
+\\citetitle[][]{citetitle:2022}
+\\citetitle*[pre][pos]{citetitle*:2022}
+\\citeyear[pre][pos]{citeyear:2022}
+\\citeyear*[pre][pos]{citeyear*:2022}
+\\citedate[pre][pos]{citedate:2022}
+\\citedate*[pre][pos]{citedate*:2022}
+\\citeurl[pre][pos]{citeurl:2022}
+
+Special commands:
+\\nocite{nocite:2022}
+\\fullcite[pos]{fullcite:2022}
+\\footfullcite[][]{fullfootcite:2022}
+``volcite'' macros have different number of args.
+\\volcite{2}{volcite:2022}
+\\Volcite[pre]{1}{Volcite:2022}
+\\pvolcite{1}[pg]{pvolcite:2022}
+\\Pvolcite[pre]{2}[pg]{Pvolcite:2022}
+\\fvolcite[pre]{3}[pg]{fvolcite:2022}
+\\ftvolcite[pre]{3}[pg]{ftvolcite:2022}
+\\svolcite[pre]{2}[pg]{svolcite:2022}
+\\Svolcite[pre]{4}[pg]{Svolcite:2022}
+\\tvolcite[pre]{5}[pg]{tvolcite:2022}
+\\Tvolcite[pre]{2}[pg]{Tvolcite:2022}
+\\avolcite[pre]{3}[pg]{avolcite:2022}
+\\Avolcite[pre]{1}[pg]{Avolcite:2022}
+\\Notecite[pre]{Notecite:2022}
+\\pnotecite[pre]{pnotecite:2022}
+\\Pnotecite[pre]{Pnotecite:2022}
+\\fnotecite[pre]{fnotecite:2022}
+
+Natbib compatibility commands:
+\\citet{citet:2022}
+\\citet*[pre][pos]{citet*:2022}
+\\citep[pre][pos]{citep:2022}
+\\citep*[pos]{citep*:2022}
+\\citealt[pre][]{citealt:2022}
+\\citealt*[][]{citealt*:2022}
+\\citealp[pre][pos]{citealp:2022}
+\\citealp*{citealp*:2022}
+\\Citet[pre][pos]{Citet:2022}
+\\Citet*[pre][pos]{Citet*:2022}
+\\Citep[pre][pos]{Citep:2022}
+\\Citep*[pre][pos]{Citep*:2022}
+
+Test for bug#56655:
+There was a few \\% of increase in budget \\Citep*{bug:56655}.
+
+And this should be % \\cite{ignored}.
+\\end{document}")
+ (write-region (point-min) (point-max) tex-file))
+ (find-file tex-file)
+ (setq keys (reftex-all-used-citation-keys))
+ (should (equal (sort keys #'string<)
+ (sort '(;; Standard commands:
+ "cite:2022" "Cite:2022"
+ "parencite:2022" "Parencite:2022"
+ "footcite:2022" "footcitetext:2022"
+ ;; Style specific commands:
+ "textcite:2022" "Textcite:2022"
+ "smartcite:2022" "Smartcite:2022"
+ "cite*:2022" "parencite*:2022"
+ ;; Style independent commands:
+ "autocite:2022" "autocite*:2022"
+ "Autocite:2022" "Autocite*:2022"
+ ;; Text commands
+ "citeauthor:2022" "citeauthor*:2022"
+ "Citeauthor:2022" "Citeauthor*:2022"
+ "citetitle:2022" "citetitle*:2022"
+ "citeyear:2022" "citeyear*:2022"
+ "citedate:2022" "citedate*:2022"
+ "citeurl:2022"
+ ;; Special commands:
+ "nocite:2022" "fullcite:2022"
+ "fullfootcite:2022"
+ "volcite:2022" "Volcite:2022"
+ "pvolcite:2022" "Pvolcite:2022"
+ "fvolcite:2022" "ftvolcite:2022"
+ "svolcite:2022" "Svolcite:2022"
+ "tvolcite:2022" "Tvolcite:2022"
+ "avolcite:2022" "Avolcite:2022"
+ "Notecite:2022" "pnotecite:2022"
+ "Pnotecite:2022" "fnotecite:2022"
+ ;; Natbib compatibility commands:
+ "citet:2022" "citet*:2022"
+ "citep:2022" "citep*:2022"
+ "citealt:2022" "citealt*:2022"
+ "citealp:2022" "citealp*:2022"
+ "Citet:2022" "Citet*:2022"
+ "Citep:2022" "Citep*:2022"
+ "bug:56655")
+ #'string<)))
+ (kill-buffer (file-name-nondirectory tex-file)))))
+
+(ert-deftest reftex-renumber-simple-labels ()
+ "Test `reftex-renumber-simple-labels'.
+The function must recognize labels defined with macros like
+\\label and the ones as key=value option in optional or mandatory
+argument of other macros or environments."
+ (ert-with-temp-directory temp-dir
+ (let ((tex-file (expand-file-name "renumber.tex" temp-dir)))
+ (with-temp-buffer
+ (insert "\
+\\documentclass{article}
+\\usepackage{tcolorbox}
+\\tcbuselibrary{theorems}
+\\usepackage{fancyvrb}
+\\usepackage{listings}
+
+\\begin{document}
+
+This is with tcolorbox package:
+\\begin{problem}[%
+ colback = white ,
+ colframe = red!50!black ,
+ fonttitle = \\bfseries ,
+ description delimiters = {\\flqq}{\\frqq} ,
+ label = {problem:2}]{Prove RH2}{}
+ Problem
+\\end{problem}
+
+This is with vanilla \\LaTeX:
+\\begin{equation}
+ \\label{eq:2}
+ 2
+\\end{equation}
+By \\eqref{eq:2} and \\ref{problem:2}
+
+This is with tcolorbox package:
+\\begin{problem}[%
+ colback=white,
+ colframe=red!50!black,
+ fonttitle=\\bfseries,
+ theorem label supplement={hypertarget={XYZ-##1}},
+ theorem full label supplement={code={\\marginnote{##1}}},
+ label={problem:1}]{Prove RH1}{}
+ Problem
+\\end{problem}
+
+This is with vanilla \\LaTeX:
+\\begin{equation}
+ \\label{eq:1}
+ 1
+\\end{equation}
+
+\\Cref{problem:1} and \\pageref{eq:1}.
+
+\\begin{problem}[label={problem:6}]{Some Problem}{}
+ Problem
+\\end{problem}
+
+\\Ref{problem:6}.
+
+This is with fancyvrb package:
+\\begin{Verbatim}[reflabel={lst:6}]
+Some Verb Content
+\\end{Verbatim}
+
+\\pageref{lst:6}
+
+This is with listings package:
+\\begin{lstlisting}[language=elisp,caption=Some Caption,label={lst:3}]
+(car (cons 1 '(2)))
+\\end{lstlisting}
+
+\\ref{lst:3}
+
+\\end{document}")
+ (write-region (point-min) (point-max) tex-file))
+ ;; The label prefix must be known to RefTeX:
+ (add-to-list 'reftex-label-alist
+ '("problem" ?p "problem:" "~\\ref{%s}"
+ nil nil nil)
+ t)
+ (add-to-list 'reftex-label-alist
+ '("Verbatim" ?l "lst:" "~\\ref{%s}"
+ nil nil nil)
+ t)
+ ;; The environments must be known to RefTeX otherwise the labels
+ ;; aren't parsed correctly:
+ (add-to-list 'reftex-label-regexps
+ (concat "\\\\begin{\\(?:problem\\|Verbatim\\)}"
+ "\\[[^][]*"
+ "\\(?:{[^}{]*"
+ "\\(?:{[^}{]*"
+ "\\(?:{[^}{]*}[^}{]*\\)*"
+ "}[^}{]*\\)*"
+ "}[^][]*\\)*"
+ "\\<\\(?:ref\\)?label[[:space:]]*=[[:space:]]*"
+ "{?\\(?1:[^] ,}\r\n\t%]+\\)"
+ "[^]]*\\]")
+ t)
+ ;; Always run this after changing `reftex-label-regexps':
+ (reftex-compile-variables)
+ (find-file tex-file)
+ ;; Silence the user query:
+ (cl-letf (((symbol-function 'yes-or-no-p) #'always))
+ (reftex-renumber-simple-labels))
+ (should (string= (buffer-string)
+ "\
+\\documentclass{article}
+\\usepackage{tcolorbox}
+\\tcbuselibrary{theorems}
+\\usepackage{fancyvrb}
+\\usepackage{listings}
+
+\\begin{document}
+
+This is with tcolorbox package:
+\\begin{problem}[%
+ colback = white ,
+ colframe = red!50!black ,
+ fonttitle = \\bfseries ,
+ description delimiters = {\\flqq}{\\frqq} ,
+ label = {problem:1}]{Prove RH2}{}
+ Problem
+\\end{problem}
+
+This is with vanilla \\LaTeX:
+\\begin{equation}
+ \\label{eq:1}
+ 2
+\\end{equation}
+By \\eqref{eq:1} and \\ref{problem:1}
+
+This is with tcolorbox package:
+\\begin{problem}[%
+ colback=white,
+ colframe=red!50!black,
+ fonttitle=\\bfseries,
+ theorem label supplement={hypertarget={XYZ-##1}},
+ theorem full label supplement={code={\\marginnote{##1}}},
+ label={problem:2}]{Prove RH1}{}
+ Problem
+\\end{problem}
+
+This is with vanilla \\LaTeX:
+\\begin{equation}
+ \\label{eq:2}
+ 1
+\\end{equation}
+
+\\Cref{problem:2} and \\pageref{eq:2}.
+
+\\begin{problem}[label={problem:3}]{Some Problem}{}
+ Problem
+\\end{problem}
+
+\\Ref{problem:3}.
+
+This is with fancyvrb package:
+\\begin{Verbatim}[reflabel={lst:1}]
+Some Verb Content
+\\end{Verbatim}
+
+\\pageref{lst:1}
+
+This is with listings package:
+\\begin{lstlisting}[language=elisp,caption=Some Caption,label={lst:2}]
+(car (cons 1 '(2)))
+\\end{lstlisting}
+
+\\ref{lst:2}
+
+\\end{document}"))
+ (kill-buffer (file-name-nondirectory tex-file)))))
;;; Autoload tests
diff --git a/test/lisp/textmodes/sgml-mode-tests.el b/test/lisp/textmodes/sgml-mode-tests.el
index 4281ab8558f..d08851eb41c 100644
--- a/test/lisp/textmodes/sgml-mode-tests.el
+++ b/test/lisp/textmodes/sgml-mode-tests.el
@@ -1,6 +1,6 @@
-;;; sgml-mode-tests.el --- Tests for sgml-mode
+;;; sgml-mode-tests.el --- Tests for sgml-mode -*- lexical-binding:t -*-
-;; Copyright (C) 2015-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2022 Free Software Foundation, Inc.
;; Author: Przemysław Wojnowski <esperanto@cumego.com>
;; Keywords: tests
@@ -125,11 +125,111 @@ The point is set to the beginning of the buffer."
(should (string= content (buffer-string))))))
(ert-deftest sgml-delete-tag-bug-8203-should-not-delete-apostrophe ()
- :expected-result :failed
(sgml-with-content
"<title>Winter is comin'</title>"
(sgml-delete-tag 1)
(should (string= "Winter is comin'" (buffer-string)))))
+(ert-deftest sgml-quote-works ()
+ (let ((text "Foo<Bar> \"Baz\" 'Qux'\n"))
+ (with-temp-buffer
+ ;; Back and forth transformation.
+ (insert text)
+ (sgml-quote (point-min) (point-max))
+ (should (string= "Foo&lt;Bar&gt; &#34;Baz&#34; &#39;Qux&#39;\n"
+ (buffer-string)))
+ (sgml-quote (point-min) (point-max) t)
+ (should (string= text (buffer-string)))
+
+ ;; The same text escaped differently.
+ (erase-buffer)
+ (insert "Foo&lt;Bar&gt; &#34;Baz&quot; &#x27;Qux&#X27;\n")
+ (sgml-quote (point-min) (point-max) t)
+ (should (string= text (buffer-string)))
+
+ ;; Lack of semicolon.
+ (erase-buffer)
+ (insert "&amp&amp")
+ (sgml-quote (point-min) (point-max) t)
+ (should (string= "&&" (buffer-string)))
+
+ ;; Double quoting
+ (sgml-quote (point-min) (point-max))
+ (sgml-quote (point-min) (point-max))
+ (sgml-quote (point-min) (point-max) t)
+ (sgml-quote (point-min) (point-max) t)
+ (should (string= "&&" (buffer-string))))))
+
+(ert-deftest sgml-tests--quotes-syntax ()
+ (dolist (str '("a\"b <t>c'd</t>"
+ "a'b <t>c\"d</t>"
+ "<t>\"a'</t>"
+ "<t>'a\"</t>"
+ "<t>\"a'\"</t>"
+ "<t>'a\"'</t>"
+ "a\"b <tag>c'd</tag>"
+ "<tag>c>'d</tag>"
+ "<t><!-- \" --></t>"
+ "<t><!-- ' --></t>"
+ "<t>(')</t>"
+ "<t>(\")</t>"
+ ))
+ (with-temp-buffer
+ (sgml-mode)
+ (insert str)
+ (ert-info ((format "%S" str) :prefix "Test case: ")
+ ;; Check that last tag is parsed as a tag.
+ (should (= 1 (car (syntax-ppss (1- (point-max))))))
+ (should (= 0 (car (syntax-ppss (point-max)))))))))
+
+(ert-deftest sgml-mode-quote-in-long-text ()
+ (with-temp-buffer
+ (sgml-mode)
+ (insert "<t>"
+ ;; `syntax-propertize-wholelines' extends chunk size based
+ ;; on line length, so newlines are significant!
+ (make-string syntax-propertize-chunk-size ?a) "\n"
+ "'"
+ (make-string syntax-propertize-chunk-size ?a) "\n"
+ "</t>")
+ ;; If we just check (syntax-ppss (point-max)) immediately, then
+ ;; we'll end up propertizing the whole buffer in one chunk (so the
+ ;; test is useless). Simulate something more like what happens
+ ;; when the buffer is viewed normally.
+ (cl-loop for pos from (point-min) to (point-max)
+ by syntax-propertize-chunk-size
+ do (syntax-ppss pos))
+ (syntax-ppss (point-max))
+ ;; Check that last tag is parsed as a tag.
+ (should (= 1 (- (car (syntax-ppss (1- (point-max))))
+ (car (syntax-ppss (point-max))))))))
+
+(ert-deftest sgml-test-brackets ()
+ "Test fontification of apostrophe preceded by paired-bracket character."
+ (let (brackets)
+ (map-char-table
+ (lambda (key value)
+ (setq brackets (cons (list
+ (if (consp key)
+ (list (car key) (cdr key))
+ key)
+ value)
+ brackets)))
+ (unicode-property-table-internal 'paired-bracket))
+ (setq brackets (delete-dups (flatten-tree brackets)))
+ (setq brackets (append brackets (list ?$ ?% ?& ?* ?+ ?/)))
+ (with-temp-buffer
+ (while brackets
+ (let ((char (string (pop brackets))))
+ (insert (concat "<p>" char "'s</p>\n"))))
+ (html-mode)
+ (font-lock-ensure (point-min) (point-max))
+ (goto-char (point-min))
+ (while (not (eobp))
+ (goto-char (next-single-char-property-change (point) 'face))
+ (let ((val (get-text-property (point) 'face)))
+ (when val
+ (should-not (eq val 'font-lock-string-face))))))))
+
(provide 'sgml-mode-tests)
;;; sgml-mode-tests.el ends here
diff --git a/test/lisp/textmodes/texinfo-resources/fill.erts b/test/lisp/textmodes/texinfo-resources/fill.erts
new file mode 100644
index 00000000000..95f3b09eba8
--- /dev/null
+++ b/test/lisp/textmodes/texinfo-resources/fill.erts
@@ -0,0 +1,70 @@
+Code:
+ (lambda ()
+ (texinfo-mode)
+ (fill-paragraph))
+
+Name: fill1
+Point-Char: |
+
+=-=
+@noindent Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
+=-=
+@noindent Everyone is permitted to copy and distribute verbatim copies
+of this license document, but changing it is not allowed.
+=-=-=
+
+Name: fill2
+Point-Char: |
+
+=-=
+@cindex relative| remapping, faces
+@cindex base remapping, faces
+ The following functions implement a higher-level interface to @code{face-remapping-alist}.
+=-=-=
+
+
+Name: fill3
+Point-Char: |
+
+=-=
+@cindex relative remapping, faces
+@cindex base remapping, faces|
+ The following functions implement a higher-level interface to @code{face-remapping-alist}.
+=-=-=
+
+Name: fill4
+Point-Char: |
+
+=-=
+@cindex relative remapping, faces
+@cindex base remapping, faces
+ The following functions| implement a higher-level interface to @code{face-remapping-alist}.
+=-=
+@cindex relative remapping, faces
+@cindex base remapping, faces
+ The following functions| implement a higher-level interface to
+@code{face-remapping-alist}.
+=-=-=
+
+Name: fill5
+Point-Char: |
+
+=-=
+@defun face-remap-add-relative face &rest specs
+|This function adds the face spec in @var{specs} as relative
+remappings for face @var{face} in the current buffer. The remaining
+arguments, @var{specs}, should form either a list of face names, or a
+property list of attribute/value pairs.
+=-=
+@defun face-remap-add-relative face &rest specs
+This function adds the face spec in @var{specs} as relative remappings
+for face @var{face} in the current buffer. The remaining arguments,
+@var{specs}, should form either a list of face names, or a property
+list of attribute/value pairs.
+=-=-=
+
+Name: fill6
+
+=-=
+@subsection This is a very very very very very very very very very very long subsection name
+=-=-=
diff --git a/test/lisp/textmodes/texinfo-tests.el b/test/lisp/textmodes/texinfo-tests.el
new file mode 100644
index 00000000000..48cc5fece2c
--- /dev/null
+++ b/test/lisp/textmodes/texinfo-tests.el
@@ -0,0 +1,33 @@
+;;; texinfo-tests.el --- Tests for texinfo.el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;
+
+;;; Code:
+
+(require 'texinfo)
+(require 'ert)
+(require 'ert-x)
+
+(ert-deftest test-filling ()
+ (ert-test-erts-file (ert-resource-file "fill.erts")))
+
+;;; texinfo-tests.el ends here
diff --git a/test/lisp/textmodes/tildify-tests.el b/test/lisp/textmodes/tildify-tests.el
index 30038296a21..a663bc29962 100644
--- a/test/lisp/textmodes/tildify-tests.el
+++ b/test/lisp/textmodes/tildify-tests.el
@@ -1,6 +1,6 @@
-;;; tildify-test.el --- ERT tests for tildify.el -*- lexical-binding: t -*-
+;;; tildify-tests.el --- ERT tests for tildify.el -*- lexical-binding: t -*-
-;; Copyright (C) 2014-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2022 Free Software Foundation, Inc.
;; Author: Michal Nazarewicz <mina86@mina86.com>
;; Version: 4.5
diff --git a/test/lisp/textmodes/underline-tests.el b/test/lisp/textmodes/underline-tests.el
new file mode 100644
index 00000000000..acc72a78a0f
--- /dev/null
+++ b/test/lisp/textmodes/underline-tests.el
@@ -0,0 +1,42 @@
+;;; underline-tests.el --- Tests for underline.el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2019-2022 Free Software Foundation, Inc.
+
+;; Author: Stefan Kangas <stefankangas@gmail.com>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'underline)
+
+(ert-deftest underline-tests-underline-region ()
+ (with-temp-buffer
+ (insert "foo bar baz")
+ (underline-region 5 8)
+ (should (equal (buffer-string) "foo _\C-hb_\C-ha_\C-hr baz"))))
+
+(ert-deftest underline-tests-ununderline-region ()
+ (with-temp-buffer
+ (insert "foo _\C-hb_\C-ha_\C-hr baz")
+ (ununderline-region 5 13)
+ (should (equal (buffer-string) "foo bar baz"))))
+
+(provide 'underline-tests)
+;;; underline-tests.el ends here
diff --git a/test/lisp/thingatpt-tests.el b/test/lisp/thingatpt-tests.el
index aeee3b52de9..b6d0b1446a3 100644
--- a/test/lisp/thingatpt-tests.el
+++ b/test/lisp/thingatpt-tests.el
@@ -1,6 +1,6 @@
-;;; thingatpt.el --- tests for thing-at-point.
+;;; thingatpt-tests.el --- tests for thing-at-point. -*- lexical-binding:t -*-
-;; Copyright (C) 2013-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2022 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -20,6 +20,7 @@
;;; Code:
(require 'ert)
+(require 'thingatpt)
(defvar thing-at-point-test-data
'(("https://1.gnu.org" 1 url "https://1.gnu.org")
@@ -65,8 +66,11 @@
("http://example.com/ab)c" 4 url "http://example.com/ab)c")
;; URL markup, lacking schema
("<url:foo@example.com>" 1 url "mailto:foo@example.com")
- ("<url:ftp.example.net/abc/>" 1 url "ftp://ftp.example.net/abc/"))
- "List of thing-at-point tests.
+ ("<url:ftp.example.net/abc/>" 1 url "ftp://ftp.example.net/abc/")
+ ;; UUID, only hex is allowed
+ ("01234567-89ab-cdef-ABCD-EF0123456789" 1 uuid "01234567-89ab-cdef-ABCD-EF0123456789")
+ ("01234567-89ab-cdef-ABCD-EF012345678G" 1 uuid nil))
+ "List of `thing-at-point' tests.
Each list element should have the form
(STRING POS THING RESULT)
@@ -84,41 +88,43 @@ position to retrieve THING.")
(goto-char (nth 1 test))
(should (equal (thing-at-point (nth 2 test)) (nth 3 test))))))
-;; These tests reflect the actual behavior of
-;; `thing-at-point-bounds-of-list-at-point'.
-(ert-deftest thing-at-point-bug24627 ()
- "Test for https://debbugs.gnu.org/24627 ."
- (let ((string-result '(("(a \"b\" c)" . (a "b" c))
- (";(a \"b\" c)")
- ("(a \"b\" c\n)" . (a "b" c))
- ("\"(a b c)\"")
- ("(a ;(b c d)\ne)" . (a e))
- ("(foo\n(a ;(b c d)\ne) bar)" . (a e))
- ("(foo\na ;(b c d)\ne bar)" . (foo a e bar))
- ("(foo\n(a \"(b c d)\"\ne) bar)" . (a "(b c d)" e))
- ("(b\n(a ;(foo c d)\ne) bar)" . (a e))
- ("(princ \"(a b c)\")" . (princ "(a b c)"))
- ("(defun foo ()\n \"Test function.\"\n ;;(a b)\n nil)" . (defun foo nil "Test function." nil))))
- (file
- (expand-file-name "lisp/thingatpt.el" source-directory))
- buf)
- ;; Test for `thing-at-point'.
- (when (file-exists-p file)
- (unwind-protect
- (progn
- (setq buf (find-file file))
- (goto-char (point-max))
- (forward-line -1)
- (should-not (thing-at-point 'list)))
- (kill-buffer buf)))
- ;; Tests for `list-at-point'.
- (dolist (str-res string-result)
- (with-temp-buffer
- (emacs-lisp-mode)
- (insert (car str-res))
- (re-search-backward "\\((a\\|^a\\)")
- (should (equal (list-at-point)
- (cdr str-res)))))))
+;; See bug#24627 and bug#31772.
+(ert-deftest thing-at-point-bounds-of-list-at-point ()
+ (cl-macrolet ((with-test-buffer (str &rest body)
+ `(with-temp-buffer
+ (emacs-lisp-mode)
+ (insert ,str)
+ (search-backward "|")
+ (delete-char 1)
+ ,@body)))
+ (let ((tests1
+ '(("|(a \"b\" c)" (a "b" c))
+ (";|(a \"b\" c)" (a "b" c) nil)
+ ("|(a \"b\" c\n)" (a "b" c))
+ ("\"|(a b c)\"" (a b c) nil)
+ ("|(a ;(b c d)\ne)" (a e))
+ ("(foo\n|(a ;(b c d)\ne) bar)" (foo (a e) bar))
+ ("(foo\n|a ;(b c d)\ne bar)" (foo a e bar))
+ ("(foo\n|(a \"(b c d)\"\ne) bar)" (foo (a "(b c d)" e) bar))
+ ("(b\n|(a ;(foo c d)\ne) bar)" (b (a e) bar))
+ ("(princ \"|(a b c)\")" (a b c) (princ "(a b c)"))
+ ("(defun foo ()\n \"Test function.\"\n ;;|(a b)\n nil)"
+ (defun foo nil "Test function." nil)
+ (defun foo nil "Test function." nil))))
+ (tests2
+ '(("|list-at-point" . "list-at-point")
+ ("list-|at-point" . "list-at-point")
+ ("list-at-point|" . nil)
+ ("|(a b c)" . "(a b c)")
+ ("(a b c)|" . nil))))
+ (dolist (test tests1)
+ (with-test-buffer (car test)
+ (should (equal (list-at-point) (cl-second test)))
+ (when (cddr test)
+ (should (equal (list-at-point t) (cl-third test))))))
+ (dolist (test tests2)
+ (with-test-buffer (car test)
+ (should (equal (thing-at-point 'list) (cdr test))))))))
(ert-deftest thing-at-point-url-in-comment ()
(with-temp-buffer
@@ -129,4 +135,84 @@ position to retrieve THING.")
(goto-char 23)
(should (equal (thing-at-point 'url) "http://foo/bar(baz)"))))
-;;; thingatpt.el ends here
+(ert-deftest thing-at-point-looking-at ()
+ (with-temp-buffer
+ (insert "1abcd 2abcd 3abcd")
+ (goto-char (point-min))
+ (let ((m2 (progn (search-forward "2abcd")
+ (match-data))))
+ (goto-char (point-min))
+ (search-forward "2ab")
+ (should (thing-at-point-looking-at "2abcd"))
+ (should (equal (match-data) m2)))))
+
+(ert-deftest test-symbol-thing-1 ()
+ (with-temp-buffer
+ (insert "foo bar zot")
+ (goto-char 4)
+ (should (eq (symbol-at-point) 'foo))
+ (forward-char 1)
+ (should (eq (symbol-at-point) 'bar))
+ (forward-char 1)
+ (should (eq (symbol-at-point) 'bar))
+ (forward-char 1)
+ (should (eq (symbol-at-point) 'bar))
+ (forward-char 1)
+ (should (eq (symbol-at-point) 'bar))
+ (forward-char 1)
+ (should (eq (symbol-at-point) 'zot))))
+
+(ert-deftest test-symbol-thing-2 ()
+ (with-temp-buffer
+ (insert " bar ")
+ (goto-char (point-max))
+ (should (eq (symbol-at-point) nil))
+ (forward-char -1)
+ (should (eq (symbol-at-point) 'bar))))
+
+(ert-deftest test-symbol-thing-3 ()
+ (with-temp-buffer
+ (insert "bar")
+ (goto-char 2)
+ (should (eq (symbol-at-point) 'bar))))
+
+(ert-deftest test-symbol-thing-4 ()
+ (with-temp-buffer
+ (insert "`[[`(")
+ (goto-char 2)
+ (should (eq (symbol-at-point) nil))))
+
+(defun test--number (number pos)
+ (with-temp-buffer
+ (insert (format "%s\n" number))
+ (goto-char (point-min))
+ (forward-char pos)
+ (number-at-point)))
+
+(ert-deftest test-numbers-none ()
+ (should (equal (test--number "foo" 0) nil)))
+
+(ert-deftest test-numbers-decimal ()
+ (should (equal (test--number "42" 0) 42))
+ (should (equal (test--number "42" 1) 42))
+ (should (equal (test--number "42" 2) 42)))
+
+(ert-deftest test-numbers-hex-lisp ()
+ (should (equal (test--number "#x42" 0) 66))
+ (should (equal (test--number "#x42" 1) 66))
+ (should (equal (test--number "#x42" 2) 66))
+ (should (equal (test--number "#xf00" 0) 3840))
+ (should (equal (test--number "#xf00" 1) 3840))
+ (should (equal (test--number "#xf00" 2) 3840))
+ (should (equal (test--number "#xf00" 3) 3840)))
+
+(ert-deftest test-numbers-hex-c ()
+ (should (equal (test--number "0x42" 0) 66))
+ (should (equal (test--number "0x42" 1) 66))
+ (should (equal (test--number "0x42" 2) 66))
+ (should (equal (test--number "0xf00" 0) 3840))
+ (should (equal (test--number "0xf00" 1) 3840))
+ (should (equal (test--number "0xf00" 2) 3840))
+ (should (equal (test--number "0xf00" 3) 3840)))
+
+;;; thingatpt-tests.el ends here
diff --git a/test/lisp/thread-tests.el b/test/lisp/thread-tests.el
new file mode 100644
index 00000000000..108fa8cb983
--- /dev/null
+++ b/test/lisp/thread-tests.el
@@ -0,0 +1,96 @@
+;;; thread-tests.el --- Test suite for thread.el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2018-2022 Free Software Foundation, Inc.
+
+;; Author: Gemini Lasswell <gazally@runbox.com>
+;; Keywords: threads
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+
+;;; Code:
+
+(require 'ert)
+(require 'thread)
+
+;; Declare the functions used here in case Emacs has been configured
+;; --without-threads.
+(declare-function make-mutex "thread.c" (&optional name))
+(declare-function mutex-lock "thread.c" (mutex))
+(declare-function mutex-unlock "thread.c" (mutex))
+(declare-function make-thread "thread.c" (function &optional name))
+(declare-function thread-join "thread.c" (thread))
+(declare-function thread-yield "thread.c" ())
+
+(defvar thread-tests-flag)
+(defvar thread-tests-mutex (when (featurep 'threads) (make-mutex "mutex1")))
+
+(defun thread-tests--thread-function ()
+ (setq thread-tests-flag t)
+ (with-mutex thread-tests-mutex
+ (sleep-for 0.01)))
+
+(ert-deftest thread-tests-thread-list-send-error ()
+ "A thread can be sent an error signal from the *Thread List* buffer."
+ (skip-unless (featurep 'threads))
+ (cl-letf (((symbol-function 'y-or-n-p) (lambda (_prompt) t)))
+ (with-mutex thread-tests-mutex
+ (setq thread-tests-flag nil)
+ (let ((thread (make-thread #'thread-tests--thread-function
+ "thread-tests-wait")))
+ (while (not thread-tests-flag)
+ (thread-yield))
+ (list-threads)
+ (goto-char (point-min))
+ (re-search-forward
+ "^thread-tests.+[[:blank:]]+Blocked[[:blank:]]+.+mutex1.+?")
+ (thread-list-send-error-signal)
+ (should-error (thread-join thread))
+ (list-threads)
+ (goto-char (point-min))
+ (should-error (re-search-forward "thread-tests"))))))
+
+(ert-deftest thread-tests-thread-list-show-backtrace ()
+ "Show a backtrace for another thread from the *Thread List* buffer."
+ (skip-unless (featurep 'threads))
+ (let (thread)
+ (with-mutex thread-tests-mutex
+ (setq thread-tests-flag nil)
+ (setq thread
+ (make-thread #'thread-tests--thread-function "thread-tests-back"))
+ (while (not thread-tests-flag)
+ (thread-yield))
+ (list-threads)
+ (goto-char (point-min))
+ (re-search-forward
+ "^thread-tests.+[[:blank:]]+Blocked[[:blank:]]+.+mutex1.+?")
+ (thread-list-pop-to-backtrace)
+ (goto-char (point-min))
+ (re-search-forward "thread-tests-back")
+ (re-search-forward "mutex-lock")
+ (re-search-forward "thread-tests--thread-function"))
+ (thread-join thread)))
+
+(ert-deftest thread-tests-list-threads-error-when-not-configured ()
+ "Signal an error running `list-threads' if threads are not configured."
+ (skip-unless (not (featurep 'threads)))
+ (should-error (list-threads)))
+
+(provide 'thread-tests)
+
+;;; thread-tests.el ends here
diff --git a/test/lisp/time-resources/non-empty b/test/lisp/time-resources/non-empty
new file mode 100644
index 00000000000..86f5704d8ee
--- /dev/null
+++ b/test/lisp/time-resources/non-empty
@@ -0,0 +1 @@
+This file should be non-empty.
diff --git a/test/lisp/time-stamp-tests.el b/test/lisp/time-stamp-tests.el
new file mode 100644
index 00000000000..55e37b71d80
--- /dev/null
+++ b/test/lisp/time-stamp-tests.el
@@ -0,0 +1,1118 @@
+;;; time-stamp-tests.el --- tests for time-stamp.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2019-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'generator)
+(eval-when-compile (require 'cl-lib))
+(require 'time-stamp)
+
+(defmacro with-time-stamp-test-env (&rest body)
+ "Evaluate BODY with some standard time-stamp test variables bound."
+ (declare (indent 0) (debug t))
+ `(let ((user-login-name "test-logname")
+ (user-full-name "100%d Tester") ;verify "%" passed unchanged
+ (buffer-file-name "/emacs/test/time-stamped-file")
+ (mail-host-address "test-mail-host-name")
+ (ref-time1 '(17337 16613)) ;Monday, Jan 2, 2006, 3:04:05 PM
+ (ref-time2 '(22574 61591)) ;Friday, Nov 18, 2016, 12:14:15 PM
+ (ref-time3 '(21377 34956)) ;Sunday, May 25, 2014, 06:07:08 AM
+ (time-stamp-time-zone t)) ;use UTC
+ (cl-letf (((symbol-function 'time-stamp-conv-warn)
+ (lambda (old-format _new)
+ (ert-fail
+ (format "Unexpected format warning for '%s'" old-format)))))
+ ;; Not all reference times are used in all tests;
+ ;; suppress the byte compiler's "unused" warning.
+ (list ref-time1 ref-time2 ref-time3)
+ ,@body)))
+
+(defmacro with-time-stamp-test-time (reference-time &rest body)
+ "Force any contained time-stamp call to use time REFERENCE-TIME."
+ (declare (indent 1) (debug t))
+ `(cl-letf*
+ ((orig-time-stamp-string-fn (symbol-function 'time-stamp-string))
+ ((symbol-function 'time-stamp-string)
+ (lambda (ts-format)
+ (apply orig-time-stamp-string-fn ts-format ,reference-time nil))))
+ ,@body))
+
+(defmacro with-time-stamp-system-name (name &rest body)
+ "Force (system-name) to return NAME while evaluating BODY."
+ (declare (indent 1) (debug t))
+ `(cl-letf (((symbol-function 'system-name)
+ (lambda () ,name)))
+ ,@body))
+
+(defmacro time-stamp-should-warn (form)
+ "Similar to `should' but verifies that a format warning is generated."
+ (declare (debug t))
+ `(let ((warning-count 0))
+ (cl-letf (((symbol-function 'time-stamp-conv-warn)
+ (lambda (_old _new)
+ (setq warning-count (1+ warning-count)))))
+ (should ,form)
+ (if (not (= warning-count 1))
+ (ert-fail (format "Should have warned about format: %S" ',form))))))
+
+;;; Tests:
+
+;;; Tests of customization variables
+
+(ert-deftest time-stamp-custom-time-zone ()
+ "Test that setting time-stamp-time-zone affects the format."
+ (with-time-stamp-test-env
+ (let ((time-stamp-time-zone "PST8"))
+ (should (equal (time-stamp-string "%H %Z" ref-time1) "07 PST")))
+ (let ((time-stamp-time-zone "UTC0"))
+ (should (equal (time-stamp-string "%H %Z" ref-time1) "15 UTC")))
+ (let ((time-stamp-time-zone "GMT0"))
+ (should (equal (time-stamp-string "%H %Z" ref-time1) "15 GMT")))))
+
+(iter-defun time-stamp-test-pattern-sequential ()
+ "Iterate through each possibility for a part of `time-stamp-pattern'."
+ (let ((pattern-value-parts
+ '(("4/" "10/" "-4/" "0/" "") ;0: line limit
+ ("stamp<" "") ;1: start
+ ("%-d" "%_H" "%^a" "%#Z" "%:A" "%02H" "%%" "") ;2: format part 1
+ (" " "x" ":" "\n" "") ;3: format part 2
+ ("%-d" "%_H" "%^a" "%#Z" "%:A" "%02H" "%%") ;4: format part 3
+ (">end" "")))) ;5: end
+ (dotimes (cur (length pattern-value-parts))
+ (dotimes (cur-index (length (nth cur pattern-value-parts)))
+ (cl-flet ((extract-part
+ (lambda (desired-part)
+ (let ((part-list (nth desired-part pattern-value-parts)))
+ (if (= desired-part cur)
+ (nth cur-index part-list)
+ (nth 0 part-list))))))
+ ;; Don't repeat the default pattern.
+ (if (or (= cur 0) (> cur-index 0))
+ ;; The whole format must start with %, so not all
+ ;; generated combinations are valid
+ (if (or (not (equal (extract-part 2) ""))
+ (equal (extract-part 3) ""))
+ (iter-yield (list (extract-part 0)
+ (extract-part 1)
+ (apply #'concat
+ (mapcar #'extract-part '(2 3 4)))
+ (extract-part 5))))))))))
+
+(iter-defun time-stamp-test-pattern-multiply ()
+ "Iterate through every combination of parts of `time-stamp-pattern'."
+ (let ((line-limit-values '("" "4/"))
+ (start-values '("" "stamp<"))
+ (format-values '("%%" "%m"))
+ (end-values '("" ">end")))
+ ;; yield all combinations of the above
+ (dolist (line-limit line-limit-values)
+ (dolist (start start-values)
+ (dolist (format format-values)
+ (dolist (end end-values)
+ (iter-yield (list line-limit start format end))))))))
+
+(iter-defun time-stamp-test-pattern-all ()
+ (iter-yield-from (time-stamp-test-pattern-sequential))
+ (iter-yield-from (time-stamp-test-pattern-multiply)))
+
+(ert-deftest time-stamp-custom-pattern ()
+ "Test that time-stamp-pattern is parsed correctly."
+ (iter-do (pattern-parts (time-stamp-test-pattern-all))
+ (cl-destructuring-bind (line-limit1 start1 whole-format end1) pattern-parts
+ (cl-letf
+ (((symbol-function 'time-stamp-once)
+ (lambda (start search-limit ts-start ts-end
+ ts-format _format-lines _end-lines)
+ ;; Verify that time-stamp parsed time-stamp-pattern and
+ ;; called us with the correct pieces.
+ (let ((limit-number (if (equal line-limit1 "")
+ time-stamp-line-limit
+ (string-to-number line-limit1))))
+ (goto-char (point-min))
+ (if (> limit-number 0)
+ (should (= search-limit (pos-bol (1+ limit-number))))
+ (should (= search-limit (point-max))))
+ (goto-char (point-max))
+ (if (< limit-number 0)
+ (should (= start (pos-bol (1+ limit-number))))
+ (should (= start (point-min)))))
+ (if (equal start1 "")
+ (should (equal ts-start time-stamp-start))
+ (should (equal ts-start start1)))
+ (if (equal whole-format "%%")
+ (should (equal ts-format time-stamp-format))
+ (should (equal ts-format whole-format)))
+ (if (equal end1 "")
+ (should (equal ts-end time-stamp-end))
+ (should (equal ts-end end1)))
+ ;; return nil to stop time-stamp from calling us again
+ nil)))
+ (let ((time-stamp-pattern (concat
+ line-limit1 start1 whole-format end1)))
+ (with-temp-buffer
+ ;; prep the buffer with more than the
+ ;; largest line-limit1 number of lines
+ (insert "\n\n\n\n\n\n\n\n\n\n\n\n")
+ ;; Call time-stamp, which will call time-stamp-once,
+ ;; triggering the tests above.
+ (time-stamp)))))))
+
+(ert-deftest time-stamp-custom-format-tabs-expand ()
+ "Test that Tab characters expand in the format but not elsewhere."
+ (with-time-stamp-test-env
+ (let ((time-stamp-start "Updated in: <\t")
+ ;; Tabs in the format should expand
+ (time-stamp-format "\t%Y\t")
+ (time-stamp-end "\t>"))
+ (with-time-stamp-test-time ref-time1
+ (with-temp-buffer
+ (insert "Updated in: <\t\t>")
+ (time-stamp)
+ (should (equal (buffer-string)
+ "Updated in: <\t 2006 \t>")))))))
+
+(ert-deftest time-stamp-custom-inserts-lines ()
+ "Test that time-stamp inserts lines or not, as directed."
+ (with-time-stamp-test-env
+ (let ((time-stamp-start "Updated on:")
+ ;; the newline in the format will insert a line if we let it
+ (time-stamp-format "\n %Y-%m-%d")
+ (time-stamp-end "$")
+ (time-stamp-inserts-lines nil) ;changed later in the test
+ (buffer-expected-1line "Updated on:\n 2006-01-02\n")
+ (buffer-expected-2line "Updated on:\n 2006-01-02\n 2006-01-02\n"))
+ (with-time-stamp-test-time ref-time1
+ (with-temp-buffer
+ (insert "Updated on:\n\n")
+ (time-stamp)
+ (should (equal (buffer-string) buffer-expected-1line))
+ ;; second call should not add a line
+ (time-stamp)
+ (should (equal (buffer-string) buffer-expected-1line))
+
+ (setq time-stamp-inserts-lines t)
+ ;; with time-stamp-inserts-lines set, should add a line
+ (time-stamp)
+ (should (equal (buffer-string) buffer-expected-2line)))))))
+
+(ert-deftest time-stamp-custom-end ()
+ "Test that time-stamp finds the end pattern on the correct line."
+ (with-time-stamp-test-env
+ (let ((time-stamp-start "Updated on: <")
+ (time-stamp-format "%Y-%m-%d")
+ (time-stamp-end ">") ;changed later in the test
+ (buffer-original-contents "Updated on: <\n>\n")
+ (buffer-expected-time-stamped "Updated on: <2006-01-02\n>\n"))
+ (with-time-stamp-test-time ref-time1
+ (with-temp-buffer
+ (insert buffer-original-contents)
+ ;; time-stamp-end is not on same line, should not be seen
+ (time-stamp)
+ (should (equal (buffer-string) buffer-original-contents))
+
+ ;; add a newline to time-stamp-end, so it starts on same line
+ (setq time-stamp-end "\n>")
+ (time-stamp)
+ (should (equal (buffer-string) buffer-expected-time-stamped)))))))
+
+(ert-deftest time-stamp-custom-count ()
+ "Test that time-stamp updates no more than time-stamp-count templates."
+ (with-time-stamp-test-env
+ (let ((time-stamp-start "TS: <")
+ (time-stamp-format "%Y-%m-%d")
+ (time-stamp-count 0) ;changed later in the test
+ (buffer-expected-once "TS: <2006-01-02>\nTS: <>")
+ (buffer-expected-twice "TS: <2006-01-02>\nTS: <2006-01-02>"))
+ (with-time-stamp-test-time ref-time1
+ (with-temp-buffer
+ (insert "TS: <>\nTS: <>")
+ (time-stamp)
+ ;; even with count = 0, expect one time stamp
+ (should (equal (buffer-string) buffer-expected-once)))
+ (with-temp-buffer
+ (setq time-stamp-count 1)
+ (insert "TS: <>\nTS: <>")
+ (time-stamp)
+ (should (equal (buffer-string) buffer-expected-once))
+
+ (setq time-stamp-count 2)
+ (time-stamp)
+ (should (equal (buffer-string) buffer-expected-twice)))))))
+
+;;; Tests of time-stamp-string formatting
+
+(ert-deftest time-stamp-format-day-of-week ()
+ "Test time-stamp formats for named day of week."
+ (with-time-stamp-test-env
+ (let ((Mon (format-time-string "%a" ref-time1 t))
+ (MON (format-time-string "%^a" ref-time1 t))
+ (Monday (format-time-string "%A" ref-time1 t))
+ (MONDAY (format-time-string "%^A" ref-time1 t)))
+ ;; implemented and documented since 1997
+ (should (equal (time-stamp-string "%3a" ref-time1) Mon))
+ (should (equal (time-stamp-string "%#A" ref-time1) MONDAY))
+ ;; documented 1997-2019
+ (should (equal (time-stamp-string "%3A" ref-time1)
+ (substring MONDAY 0 3)))
+ (should (equal (time-stamp-string "%:a" ref-time1) Monday))
+ ;; implemented since 2001, documented since 2019
+ (should (equal (time-stamp-string "%#a" ref-time1) MON))
+ (should (equal (time-stamp-string "%:A" ref-time1) Monday))
+ ;; allowed but undocumented since 2019 (warned 1997-2019)
+ (should (equal (time-stamp-string "%^A" ref-time1) MONDAY))
+ ;; warned 1997-2019, changed in 2019
+ (should (equal (time-stamp-string "%a" ref-time1) Mon))
+ (should (equal (time-stamp-string "%^a" ref-time1) MON))
+ (should (equal (time-stamp-string "%A" ref-time1) Monday)))))
+
+(ert-deftest time-stamp-format-month-name ()
+ "Test time-stamp formats for month name."
+ (with-time-stamp-test-env
+ (let ((Jan (format-time-string "%b" ref-time1 t))
+ (JAN (format-time-string "%^b" ref-time1 t))
+ (January (format-time-string "%B" ref-time1 t))
+ (JANUARY (format-time-string "%^B" ref-time1 t)))
+ ;; implemented and documented since 1997
+ (should (equal (time-stamp-string "%3b" ref-time1)
+ (substring January 0 3)))
+ (should (equal (time-stamp-string "%#B" ref-time1) JANUARY))
+ ;; documented 1997-2019
+ (should (equal (time-stamp-string "%3B" ref-time1)
+ (substring JANUARY 0 3)))
+ (should (equal (time-stamp-string "%:b" ref-time1) January))
+ ;; implemented since 2001, documented since 2019
+ (should (equal (time-stamp-string "%#b" ref-time1) JAN))
+ (should (equal (time-stamp-string "%:B" ref-time1) January))
+ ;; allowed but undocumented since 2019 (warned 1997-2019)
+ (should (equal (time-stamp-string "%^B" ref-time1) JANUARY))
+ ;; warned 1997-2019, changed in 2019
+ (should (equal (time-stamp-string "%b" ref-time1) Jan))
+ (should (equal (time-stamp-string "%^b" ref-time1) JAN))
+ (should (equal (time-stamp-string "%B" ref-time1) January)))))
+
+(ert-deftest time-stamp-format-day-of-month ()
+ "Test time-stamp formats for day of month."
+ (with-time-stamp-test-env
+ ;; implemented and documented since 1995
+ (should (equal (time-stamp-string "%2d" ref-time1) " 2"))
+ (should (equal (time-stamp-string "%2d" ref-time2) "18"))
+ (should (equal (time-stamp-string "%02d" ref-time1) "02"))
+ (should (equal (time-stamp-string "%02d" ref-time2) "18"))
+ ;; documented 1997-2019
+ (should (equal (time-stamp-string "%:d" ref-time1) "2"))
+ (should (equal (time-stamp-string "%:d" ref-time2) "18"))
+ ;; implemented since 1997, documented since 2019
+ (should (equal (time-stamp-string "%1d" ref-time1) "2"))
+ (should (equal (time-stamp-string "%1d" ref-time2) "18"))
+ ;; allowed but undocumented since 2019 (warned 1997-2019)
+ (should (equal (time-stamp-string "%-d" ref-time1) "2"))
+ (should (equal (time-stamp-string "%-d" ref-time2) "18"))
+ ;; warned 1997-2019, changed in 2019
+ (should (equal (time-stamp-string "%_d" ref-time1) " 2"))
+ (should (equal (time-stamp-string "%_d" ref-time2) "18"))
+ (should (equal (time-stamp-string "%d" ref-time1) "02"))
+ (should (equal (time-stamp-string "%d" ref-time2) "18"))))
+
+(ert-deftest time-stamp-format-hours-24 ()
+ "Test time-stamp formats for hour on a 24-hour clock."
+ (with-time-stamp-test-env
+ ;; implemented and documented since 1995
+ (should (equal (time-stamp-string "%2H" ref-time1) "15"))
+ (should (equal (time-stamp-string "%2H" ref-time2) "12"))
+ (should (equal (time-stamp-string "%2H" ref-time3) " 6"))
+ (should (equal (time-stamp-string "%02H" ref-time1) "15"))
+ (should (equal (time-stamp-string "%02H" ref-time2) "12"))
+ (should (equal (time-stamp-string "%02H" ref-time3) "06"))
+ ;; documented 1997-2019
+ (should (equal (time-stamp-string "%:H" ref-time1) "15"))
+ (should (equal (time-stamp-string "%:H" ref-time2) "12"))
+ (should (equal (time-stamp-string "%:H" ref-time3) "6"))
+ ;; implemented since 1997, documented since 2019
+ (should (equal (time-stamp-string "%1H" ref-time1) "15"))
+ (should (equal (time-stamp-string "%1H" ref-time2) "12"))
+ (should (equal (time-stamp-string "%1H" ref-time3) "6"))
+ ;; allowed but undocumented since 2019 (warned 1997-2019)
+ (should (equal (time-stamp-string "%-H" ref-time1) "15"))
+ (should (equal (time-stamp-string "%-H" ref-time2) "12"))
+ (should (equal (time-stamp-string "%-H" ref-time3) "6"))
+ ;; warned 1997-2019, changed in 2019
+ (should (equal (time-stamp-string "%_H" ref-time1) "15"))
+ (should (equal (time-stamp-string "%_H" ref-time2) "12"))
+ (should (equal (time-stamp-string "%_H" ref-time3) " 6"))
+ (should (equal (time-stamp-string "%H" ref-time1) "15"))
+ (should (equal (time-stamp-string "%H" ref-time2) "12"))
+ (should (equal (time-stamp-string "%H" ref-time3) "06"))))
+
+(ert-deftest time-stamp-format-hours-12 ()
+ "Test time-stamp formats for hour on a 12-hour clock."
+ (with-time-stamp-test-env
+ ;; implemented and documented since 1995
+ (should (equal (time-stamp-string "%2I" ref-time1) " 3"))
+ (should (equal (time-stamp-string "%2I" ref-time2) "12"))
+ (should (equal (time-stamp-string "%2I" ref-time3) " 6"))
+ (should (equal (time-stamp-string "%02I" ref-time1) "03"))
+ (should (equal (time-stamp-string "%02I" ref-time2) "12"))
+ (should (equal (time-stamp-string "%02I" ref-time3) "06"))
+ ;; documented 1997-2019
+ (should (equal (time-stamp-string "%:I" ref-time1) "3")) ;PM
+ (should (equal (time-stamp-string "%:I" ref-time2) "12")) ;PM
+ (should (equal (time-stamp-string "%:I" ref-time3) "6")) ;AM
+ ;; implemented since 1997, documented since 2019
+ (should (equal (time-stamp-string "%1I" ref-time1) "3"))
+ (should (equal (time-stamp-string "%1I" ref-time2) "12"))
+ (should (equal (time-stamp-string "%1I" ref-time3) "6"))
+ ;; allowed but undocumented since 2019 (warned 1997-2019)
+ (should (equal (time-stamp-string "%-I" ref-time1) "3"))
+ (should (equal (time-stamp-string "%-I" ref-time2) "12"))
+ (should (equal (time-stamp-string "%-I" ref-time3) "6"))
+ ;; warned 1997-2019, changed in 2019
+ (should (equal (time-stamp-string "%_I" ref-time1) " 3"))
+ (should (equal (time-stamp-string "%_I" ref-time2) "12"))
+ (should (equal (time-stamp-string "%_I" ref-time3) " 6"))
+ (should (equal (time-stamp-string "%I" ref-time1) "03"))
+ (should (equal (time-stamp-string "%I" ref-time2) "12"))
+ (should (equal (time-stamp-string "%I" ref-time3) "06"))))
+
+(ert-deftest time-stamp-format-month-number ()
+ "Test time-stamp formats for month number."
+ (with-time-stamp-test-env
+ ;; implemented and documented since 1995
+ (should (equal (time-stamp-string "%2m" ref-time1) " 1"))
+ (should (equal (time-stamp-string "%2m" ref-time2) "11"))
+ (should (equal (time-stamp-string "%02m" ref-time1) "01"))
+ (should (equal (time-stamp-string "%02m" ref-time2) "11"))
+ ;; documented 1997-2019
+ (should (equal (time-stamp-string "%:m" ref-time1) "1"))
+ (should (equal (time-stamp-string "%:m" ref-time2) "11"))
+ ;; implemented since 1997, documented since 2019
+ (should (equal (time-stamp-string "%1m" ref-time1) "1"))
+ (should (equal (time-stamp-string "%1m" ref-time2) "11"))
+ ;; allowed but undocumented since 2019 (warned 1997-2019)
+ (should (equal (time-stamp-string "%-m" ref-time1) "1"))
+ (should (equal (time-stamp-string "%-m" ref-time2) "11"))
+ ;; warned 1997-2019, changed in 2019
+ (should (equal (time-stamp-string "%_m" ref-time1) " 1"))
+ (should (equal (time-stamp-string "%_m" ref-time2) "11"))
+ (should (equal (time-stamp-string "%m" ref-time1) "01"))
+ (should (equal (time-stamp-string "%m" ref-time2) "11"))))
+
+(ert-deftest time-stamp-format-minute ()
+ "Test time-stamp formats for minute."
+ (with-time-stamp-test-env
+ ;; implemented and documented since 1995
+ (should (equal (time-stamp-string "%2M" ref-time1) " 4"))
+ (should (equal (time-stamp-string "%2M" ref-time2) "14"))
+ (should (equal (time-stamp-string "%02M" ref-time1) "04"))
+ (should (equal (time-stamp-string "%02M" ref-time2) "14"))
+ ;; documented 1997-2019
+ (should (equal (time-stamp-string "%:M" ref-time1) "4"))
+ (should (equal (time-stamp-string "%:M" ref-time2) "14"))
+ ;; implemented since 1997, documented since 2019
+ (should (equal (time-stamp-string "%1M" ref-time1) "4"))
+ (should (equal (time-stamp-string "%1M" ref-time2) "14"))
+ ;; allowed but undocumented since 2019 (warned 1997-2019)
+ (should (equal (time-stamp-string "%-M" ref-time1) "4"))
+ (should (equal (time-stamp-string "%-M" ref-time2) "14"))
+ ;; warned 1997-2019, changed in 2019
+ (should (equal (time-stamp-string "%_M" ref-time1) " 4"))
+ (should (equal (time-stamp-string "%_M" ref-time2) "14"))
+ (should (equal (time-stamp-string "%M" ref-time1) "04"))
+ (should (equal (time-stamp-string "%M" ref-time2) "14"))))
+
+(ert-deftest time-stamp-format-second ()
+ "Test time-stamp formats for second."
+ (with-time-stamp-test-env
+ ;; implemented and documented since 1995
+ (should (equal (time-stamp-string "%2S" ref-time1) " 5"))
+ (should (equal (time-stamp-string "%2S" ref-time2) "15"))
+ (should (equal (time-stamp-string "%02S" ref-time1) "05"))
+ (should (equal (time-stamp-string "%02S" ref-time2) "15"))
+ ;; documented 1997-2019
+ (should (equal (time-stamp-string "%:S" ref-time1) "5"))
+ (should (equal (time-stamp-string "%:S" ref-time2) "15"))
+ ;; implemented since 1997, documented since 2019
+ (should (equal (time-stamp-string "%1S" ref-time1) "5"))
+ (should (equal (time-stamp-string "%1S" ref-time2) "15"))
+ ;; allowed but undocumented since 2019 (warned 1997-2019)
+ (should (equal (time-stamp-string "%-S" ref-time1) "5"))
+ (should (equal (time-stamp-string "%-S" ref-time2) "15"))
+ ;; warned 1997-2019, changed in 2019
+ (should (equal (time-stamp-string "%_S" ref-time1) " 5"))
+ (should (equal (time-stamp-string "%_S" ref-time2) "15"))
+ (should (equal (time-stamp-string "%S" ref-time1) "05"))
+ (should (equal (time-stamp-string "%S" ref-time2) "15"))))
+
+(ert-deftest time-stamp-format-year-2digit ()
+ "Test time-stamp formats for %y."
+ (with-time-stamp-test-env
+ ;; implemented and documented since 1995
+ (should (equal (time-stamp-string "%02y" ref-time1) "06"))
+ (should (equal (time-stamp-string "%02y" ref-time2) "16"))
+ ;; documented 1997-2019
+ (should (equal (time-stamp-string "%:y" ref-time1) "2006"))
+ (should (equal (time-stamp-string "%:y" ref-time2) "2016"))
+ ;; warned 1997-2019, changed in 2019
+ ;; (We don't expect the %-y or %_y form to be useful,
+ ;; but we test both so that we can confidently state that
+ ;; `-' and `_' affect all 2-digit conversions identically.)
+ (should (equal (time-stamp-string "%-y" ref-time1) "6"))
+ (should (equal (time-stamp-string "%-y" ref-time2) "16"))
+ (should (equal (time-stamp-string "%_y" ref-time1) " 6"))
+ (should (equal (time-stamp-string "%_y" ref-time2) "16"))
+ (should (equal (time-stamp-string "%y" ref-time1) "06"))
+ (should (equal (time-stamp-string "%y" ref-time2) "16"))
+ ;; implemented since 1995, warned since 2019, will change
+ (time-stamp-should-warn
+ (equal (time-stamp-string "%04y" ref-time1) "2006"))
+ (time-stamp-should-warn
+ (equal (time-stamp-string "%4y" ref-time1) "2006"))))
+
+(ert-deftest time-stamp-format-year-4digit ()
+ "Test time-stamp format %Y."
+ (with-time-stamp-test-env
+ ;; implemented since 1997, documented since 2019
+ (should (equal (time-stamp-string "%Y" ref-time1) "2006"))
+ ;; numbers do not truncate
+ (should (equal (time-stamp-string "%2Y" ref-time1) "2006"))
+ (should (equal (time-stamp-string "%02Y" ref-time1) "2006"))))
+
+(ert-deftest time-stamp-format-am-pm ()
+ "Test time-stamp formats for AM and PM strings."
+ (with-time-stamp-test-env
+ (let ((pm (format-time-string "%#p" ref-time1 t))
+ (am (format-time-string "%#p" ref-time3 t))
+ (PM (format-time-string "%p" ref-time1 t))
+ (AM (format-time-string "%p" ref-time3 t)))
+ ;; implemented and documented since 1997
+ (should (equal (time-stamp-string "%#p" ref-time1) pm))
+ (should (equal (time-stamp-string "%#p" ref-time3) am))
+ (should (equal (time-stamp-string "%P" ref-time1) PM))
+ (should (equal (time-stamp-string "%P" ref-time3) AM))
+ ;; warned 1997-2019, changed in 2019
+ (should (equal (time-stamp-string "%p" ref-time1) PM))
+ (should (equal (time-stamp-string "%p" ref-time3) AM)))))
+
+(ert-deftest time-stamp-format-day-number-in-week ()
+ "Test time-stamp formats for day number in week."
+ (with-time-stamp-test-env
+ (should (equal (time-stamp-string "%w" ref-time1) "1"))
+ (should (equal (time-stamp-string "%w" ref-time2) "5"))
+ (should (equal (time-stamp-string "%w" ref-time3) "0"))))
+
+(ert-deftest time-stamp-format-time-zone-name ()
+ "Test time-stamp format %Z."
+ (with-time-stamp-test-env
+ (let ((UTC-abbr (format-time-string "%Z" ref-time1 t))
+ (utc-abbr (format-time-string "%#Z" ref-time1 t)))
+ ;; implemented and documented since 1995
+ (should (equal (time-stamp-string "%Z" ref-time1) UTC-abbr))
+ ;; implemented since 1997, documented since 2019
+ (should (equal (time-stamp-string "%#Z" ref-time1) utc-abbr)))))
+
+(ert-deftest time-stamp-format-time-zone-offset ()
+ "Tests time-stamp legacy format %z and spot tests of new offset format %5z."
+ (with-time-stamp-test-env
+ (let ((utc-abbr (format-time-string "%#Z" ref-time1 t)))
+ ;; documented 1995-2019, warned since 2019, will change
+ (time-stamp-should-warn
+ (equal (time-stamp-string "%z" ref-time1) utc-abbr)))
+ ;; implemented and documented (with compat caveat) since 2019
+ (should (equal (time-stamp-string "%5z" ref-time1) "+0000"))
+ (let ((time-stamp-time-zone "PST8"))
+ (should (equal (time-stamp-string "%5z" ref-time1) "-0800")))
+ (let ((time-stamp-time-zone "HST10"))
+ (should (equal (time-stamp-string "%5z" ref-time1) "-1000")))
+ (let ((time-stamp-time-zone "CET-1"))
+ (should (equal (time-stamp-string "%5z" ref-time1) "+0100")))
+ ;; implemented since 2019, verify that these don't warn
+ ;; See also the "formatz" tests below, which since 2021 test more
+ ;; variants with more offsets.
+ (should (equal (time-stamp-string "%-z" ref-time1) "+00"))
+ (should (equal (time-stamp-string "%:z" ref-time1) "+00:00"))
+ (should (equal (time-stamp-string "%::z" ref-time1) "+00:00:00"))
+ (should (equal (time-stamp-string "%9::z" ref-time1) "+00:00:00"))
+ (should (equal (time-stamp-string "%:::z" ref-time1) "+00"))))
+
+(ert-deftest time-stamp-format-non-date-conversions ()
+ "Test time-stamp formats for non-date items."
+ (with-time-stamp-test-env
+ (with-time-stamp-system-name "test-system-name.example.org"
+ ;; implemented and documented since 1995
+ (should (equal (time-stamp-string "%%" ref-time1) "%")) ;% last char
+ (should (equal (time-stamp-string "%%P" ref-time1) "%P")) ;% not last char
+ (should (equal (time-stamp-string "%f" ref-time1) "time-stamped-file"))
+ (should (equal (time-stamp-string "%F" ref-time1)
+ "/emacs/test/time-stamped-file"))
+ (with-temp-buffer
+ (should (equal (time-stamp-string "%f" ref-time1) "(no file)"))
+ (should (equal (time-stamp-string "%F" ref-time1) "(no file)")))
+ (should (equal (time-stamp-string "%h" ref-time1) "test-mail-host-name"))
+ (let ((mail-host-address nil))
+ (should (equal (time-stamp-string "%h" ref-time1)
+ "test-system-name.example.org")))
+ ;; documented 1995-2019
+ (should (equal (time-stamp-string "%s" ref-time1)
+ "test-system-name.example.org"))
+ (should (equal (time-stamp-string "%U" ref-time1) "100%d Tester"))
+ (should (equal (time-stamp-string "%u" ref-time1) "test-logname"))
+ ;; implemented since 2001, documented since 2019
+ (should (equal (time-stamp-string "%L" ref-time1) "100%d Tester"))
+ (should (equal (time-stamp-string "%l" ref-time1) "test-logname"))
+ ;; implemented since 2007, documented since 2019
+ (should (equal (time-stamp-string "%Q" ref-time1)
+ "test-system-name.example.org"))
+ (should (equal (time-stamp-string "%q" ref-time1) "test-system-name")))
+ (with-time-stamp-system-name "sysname-no-dots"
+ (should (equal (time-stamp-string "%Q" ref-time1) "sysname-no-dots"))
+ (should (equal (time-stamp-string "%q" ref-time1) "sysname-no-dots")))))
+
+(ert-deftest time-stamp-format-ignored-modifiers ()
+ "Test additional args allowed (but ignored) to allow for future expansion."
+ (with-time-stamp-test-env
+ (let ((May (format-time-string "%B" ref-time3 t)))
+ ;; allowed modifiers
+ (should (equal (time-stamp-string "%.,@+ (stuff)B" ref-time3) May))
+ ;; parens nest
+ (should (equal (time-stamp-string "%(st(u)ff)B" ref-time3) May))
+ ;; escaped parens do not change the nesting level
+ (should (equal (time-stamp-string "%(st\\)u\\(ff)B" ref-time3) May))
+ ;; incorrectly nested parens do not crash us
+ (should-not (equal (time-stamp-string "%(stuffB" ref-time3) May))
+ (should-not (equal (time-stamp-string "%)B" ref-time3) May))
+ ;; unterminated format does not crash us
+ (should-not (equal (time-stamp-string "%" ref-time3) May))
+ ;; not all punctuation is allowed
+ (should-not (equal (time-stamp-string "%&B" ref-time3) May))
+ (should-not (equal (time-stamp-string "%/B" ref-time3) May))
+ (should-not (equal (time-stamp-string "%;B" ref-time3) May)))))
+
+(ert-deftest time-stamp-format-non-conversions ()
+ "Test that without a %, the text is copied literally."
+ (with-time-stamp-test-env
+ (should (equal (time-stamp-string "No percent" ref-time1) "No percent"))))
+
+(ert-deftest time-stamp-format-multiple-conversions ()
+ "Tests that multiple %-conversions are independent."
+ (with-time-stamp-test-env
+ (let ((Mon (format-time-string "%a" ref-time1 t))
+ (MON (format-time-string "%^a" ref-time1 t))
+ (Monday (format-time-string "%A" ref-time1 t)))
+ ;; change-case flag is independent
+ (should (equal (time-stamp-string "%a.%#a.%a" ref-time1)
+ (concat Mon "." MON "." Mon)))
+ ;; up-case flag is independent
+ (should (equal (time-stamp-string "%a.%^a.%a" ref-time1)
+ (concat Mon "." MON "." Mon)))
+ ;; underscore flag is independent
+ (should (equal (time-stamp-string "%_d.%d.%_d" ref-time1) " 2.02. 2"))
+ (should (equal (time-stamp-string "%_7z.%7z.%_7z" ref-time1)
+ "+000000.+0000 .+000000"))
+ ;; minus flag is independent
+ (should (equal (time-stamp-string "%d.%-d.%d" ref-time1) "02.2.02"))
+ (should (equal (time-stamp-string "%3z.%-3z.%3z" ref-time1)
+ "+0000.+00.+0000"))
+ ;; 0 flag is independent
+ (should (equal (time-stamp-string "%2d.%02d.%2d" ref-time1) " 2.02. 2"))
+ (should (equal (time-stamp-string "%6:::z.%06:::z.%6:::z" ref-time1)
+ "+00 .+00:00.+00 "))
+ ;; field width is independent
+ (should (equal
+ (time-stamp-string "%6Y.%Y.%6Y" ref-time1) " 2006.2006. 2006"))
+ ;; colon modifier is independent
+ (should (equal (time-stamp-string "%a.%:a.%a" ref-time1)
+ (concat Mon "." Monday "." Mon)))
+ (should (equal (time-stamp-string "%5z.%5::z.%5z" ref-time1)
+ "+0000.+00:00:00.+0000"))
+ ;; format character is independent
+ (should (equal (time-stamp-string "%H:%M%%%S" ref-time1) "15:04%05")))))
+
+(ert-deftest time-stamp-format-string-width ()
+ "Test time-stamp string width modifiers."
+ (with-time-stamp-test-env
+ (let ((May (format-time-string "%b" ref-time3 t))
+ (SUN (format-time-string "%^a" ref-time3 t))
+ (NOV (format-time-string "%^b" ref-time2 t)))
+ ;; strings truncate on the right or are blank-padded on the left
+ (should (equal (time-stamp-string "%0b" ref-time3) ""))
+ (should (equal (time-stamp-string "%1b" ref-time3) (substring May 0 1)))
+ (should (equal (time-stamp-string "%2b" ref-time3) (substring May 0 2)))
+ (should (equal (time-stamp-string "%3b" ref-time3) (substring May 0 3)))
+ (should (equal (time-stamp-string "%4b" ref-time3) (concat " " May)))
+ (should (equal (time-stamp-string "%0%" ref-time3) ""))
+ (should (equal (time-stamp-string "%1%" ref-time3) "%"))
+ (should (equal (time-stamp-string "%2%" ref-time3) " %"))
+ (should (equal (time-stamp-string "%9%" ref-time3) " %"))
+ (should (equal (time-stamp-string "%10%" ref-time3) " %"))
+ (should (equal (time-stamp-string "%#3a" ref-time3)
+ (substring SUN 0 3)))
+ (should (equal (time-stamp-string "%#3b" ref-time2)
+ (substring NOV 0 3))))))
+
+;;; Tests of helper functions
+
+(ert-deftest time-stamp-helper-string-defaults ()
+ "Test that time-stamp-string defaults its format to time-stamp-format."
+ (with-time-stamp-test-env
+ (should (equal (time-stamp-string nil ref-time1)
+ (time-stamp-string time-stamp-format ref-time1)))
+ (should (equal (time-stamp-string 'not-a-string ref-time1) nil))))
+
+(ert-deftest time-stamp-helper-zone-type-p ()
+ "Test time-stamp-zone-type-p."
+ (should (time-stamp-zone-type-p t))
+ (should (time-stamp-zone-type-p nil))
+ (should (time-stamp-zone-type-p 'wall))
+ (should-not (time-stamp-zone-type-p 'floor))
+ (should (time-stamp-zone-type-p "arbitrary string"))
+ (should (time-stamp-zone-type-p 0))
+ (should-not (time-stamp-zone-type-p 3.14))
+ (should-not (time-stamp-zone-type-p '(0)))
+ (should-not (time-stamp-zone-type-p '(0 . "A")))
+ (should (time-stamp-zone-type-p '(0 "A")))
+ (should-not (time-stamp-zone-type-p '(0 0)))
+ (should-not (time-stamp-zone-type-p '("A" "A"))))
+
+(ert-deftest time-stamp-helper-safe-locals ()
+ "Test that our variables are known to be safe local variables."
+ (should (safe-local-variable-p 'time-stamp-format "a string"))
+ (should-not (safe-local-variable-p 'time-stamp-format '(a list)))
+ (should (safe-local-variable-p 'time-stamp-time-zone "a string"))
+ (should-not (safe-local-variable-p 'time-stamp-time-zone 0.5))
+ (should (safe-local-variable-p 'time-stamp-line-limit 8))
+ (should-not (safe-local-variable-p 'time-stamp-line-limit "a string"))
+ (should (safe-local-variable-p 'time-stamp-start "a string"))
+ (should-not (safe-local-variable-p 'time-stamp-start 17))
+ (should (safe-local-variable-p 'time-stamp-end "a string"))
+ (should-not (safe-local-variable-p 'time-stamp-end 17))
+ (should (safe-local-variable-p 'time-stamp-inserts-lines t))
+ (should-not (safe-local-variable-p 'time-stamp-inserts-lines 17))
+ (should (safe-local-variable-p 'time-stamp-count 2))
+ (should-not (safe-local-variable-p 'time-stamp-count t))
+ (should (safe-local-variable-p 'time-stamp-pattern "a string"))
+ (should-not (safe-local-variable-p 'time-stamp-pattern 17)))
+
+;;;; Setup for tests of time offset formatting with %z
+
+(defun formatz (format zone)
+ "Uses FORMAT to format the offset of ZONE, returning the result.
+FORMAT must be time format \"%z\" or some variation thereof.
+ZONE is as the ZONE argument of the `format-time-string' function.
+This function is called by 99% of the `time-stamp' \"%z\" unit tests."
+ (with-time-stamp-test-env
+ (let ((time-stamp-time-zone zone))
+ ;; Call your favorite time formatter here.
+ ;; For narrower-scope unit testing,
+ ;; instead of calling time-stamp-string here,
+ ;; we could directly call (format-time-offset format zone)
+ (time-stamp-string format)
+ )))
+
+(defun format-time-offset (format offset-secs)
+ "Uses FORMAT to format the time zone represented by OFFSET-SECS.
+FORMAT must be time format \"%z\" or some variation thereof.
+This function is a wrapper around `time-stamp-formatz-from-parsed-options'
+and is called by some low-level `time-stamp' \"%z\" unit tests."
+ ;; This wrapper adds a simple regexp-based parser that handles only
+ ;; %z and variants. In normal use, time-stamp-formatz-from-parsed-options
+ ;; is called from a parser that handles all time string formats.
+ (string-match
+ "\\`\\([^%]*\\)%\\([-_]?\\)\\(0?\\)\\([1-9][0-9]*\\)?\\([EO]?\\)\\(:*\\)\\([^a-zA-Z]+\\)?z\\(.*\\)"
+ format)
+ (let ((leading-string (match-string 1 format))
+ (flag-minimize (seq-find (lambda (x) (eq x ?-))
+ (match-string 2 format)))
+ (flag-pad-with-spaces (seq-find (lambda (x) (eq x ?_))
+ (match-string 2 format)))
+ (flag-pad-with-zeros (equal (match-string 3 format) "0"))
+ (field-width (string-to-number (or (match-string 4 format) "")))
+ (colon-count (length (match-string 6 format)))
+ (garbage (match-string 7 format))
+ (trailing-string (match-string 8 format)))
+ (concat leading-string
+ (if garbage
+ ""
+ (time-stamp-formatz-from-parsed-options flag-minimize
+ flag-pad-with-spaces
+ flag-pad-with-zeros
+ colon-count
+ field-width
+ offset-secs))
+ trailing-string)))
+
+(defun fz-make+zone (h &optional m s)
+ "Creates a non-negative offset."
+ (let ((m (or m 0))
+ (s (or s 0)))
+ (+ (* 3600 h) (* 60 m) s)))
+
+(defun fz-make-zone (h &optional m s)
+ "Creates a negative offset. The arguments are all non-negative."
+ (- (fz-make+zone h m s)))
+
+(defmacro formatz-should-equal (zone expect)
+ "Formats ZONE and compares it to EXPECT.
+Uses the free variables `form-string' and `pattern-mod'.
+The functions in `pattern-mod' are composed left to right."
+ (declare (debug t))
+ `(let ((result ,expect))
+ (dolist (fn pattern-mod)
+ (setq result (funcall fn result)))
+ (should (equal (formatz form-string ,zone) result))))
+
+;; These test cases have zeros in all places (first, last, none, both)
+;; for hours, minutes, and seconds.
+
+(defun formatz-hours-exact-helper (form-string pattern-mod)
+ "Tests format %z with whole hours."
+ (formatz-should-equal (fz-make+zone 0) "+00") ;0 sign always +, both digits
+ (formatz-should-equal (fz-make+zone 10) "+10")
+ (formatz-should-equal (fz-make-zone 10) "-10")
+ (formatz-should-equal (fz-make+zone 2) "+02")
+ (formatz-should-equal (fz-make-zone 2) "-02")
+ (formatz-should-equal (fz-make+zone 13) "+13")
+ (formatz-should-equal (fz-make-zone 13) "-13")
+ )
+
+(defun formatz-nonzero-minutes-helper (form-string pattern-mod)
+ "Tests format %z with whole minutes."
+ (formatz-should-equal (fz-make+zone 0 30) "+00:30") ;has hours even though 0
+ (formatz-should-equal (fz-make-zone 0 30) "-00:30")
+ (formatz-should-equal (fz-make+zone 0 4) "+00:04")
+ (formatz-should-equal (fz-make-zone 0 4) "-00:04")
+ (formatz-should-equal (fz-make+zone 8 40) "+08:40")
+ (formatz-should-equal (fz-make-zone 8 40) "-08:40")
+ (formatz-should-equal (fz-make+zone 0 15) "+00:15")
+ (formatz-should-equal (fz-make-zone 0 15) "-00:15")
+ (formatz-should-equal (fz-make+zone 11 30) "+11:30")
+ (formatz-should-equal (fz-make-zone 11 30) "-11:30")
+ (formatz-should-equal (fz-make+zone 3 17) "+03:17")
+ (formatz-should-equal (fz-make-zone 3 17) "-03:17")
+ (formatz-should-equal (fz-make+zone 12 45) "+12:45")
+ (formatz-should-equal (fz-make-zone 12 45) "-12:45")
+ )
+
+(defun formatz-nonzero-seconds-helper (form-string pattern-mod)
+ "Tests format %z with non-0 seconds."
+ ;; non-0 seconds are always included
+ (formatz-should-equal (fz-make+zone 0 0 50) "+00:00:50")
+ (formatz-should-equal (fz-make-zone 0 0 50) "-00:00:50")
+ (formatz-should-equal (fz-make+zone 0 0 06) "+00:00:06")
+ (formatz-should-equal (fz-make-zone 0 0 06) "-00:00:06")
+ (formatz-should-equal (fz-make+zone 0 7 50) "+00:07:50")
+ (formatz-should-equal (fz-make-zone 0 7 50) "-00:07:50")
+ (formatz-should-equal (fz-make+zone 0 0 16) "+00:00:16")
+ (formatz-should-equal (fz-make-zone 0 0 16) "-00:00:16")
+ (formatz-should-equal (fz-make+zone 0 12 36) "+00:12:36")
+ (formatz-should-equal (fz-make-zone 0 12 36) "-00:12:36")
+ (formatz-should-equal (fz-make+zone 0 3 45) "+00:03:45")
+ (formatz-should-equal (fz-make-zone 0 3 45) "-00:03:45")
+ (formatz-should-equal (fz-make+zone 8 45 30) "+08:45:30")
+ (formatz-should-equal (fz-make-zone 8 45 30) "-08:45:30")
+ (formatz-should-equal (fz-make+zone 0 11 45) "+00:11:45")
+ (formatz-should-equal (fz-make-zone 0 11 45) "-00:11:45")
+ (formatz-should-equal (fz-make+zone 3 20 15) "+03:20:15")
+ (formatz-should-equal (fz-make-zone 3 20 15) "-03:20:15")
+ (formatz-should-equal (fz-make+zone 11 14 30) "+11:14:30")
+ (formatz-should-equal (fz-make-zone 11 14 30) "-11:14:30")
+ (formatz-should-equal (fz-make+zone 12 30 49) "+12:30:49")
+ (formatz-should-equal (fz-make-zone 12 30 49) "-12:30:49")
+ (formatz-should-equal (fz-make+zone 12 0 34) "+12:00:34")
+ (formatz-should-equal (fz-make-zone 12 0 34) "-12:00:34")
+ )
+
+(defun formatz-hours-big-helper (form-string pattern-mod)
+ "Tests format %z with hours that don't fit in two digits."
+ (formatz-should-equal (fz-make+zone 101) "+101:00")
+ (formatz-should-equal (fz-make+zone 123 10) "+123:10")
+ (formatz-should-equal (fz-make-zone 123 10) "-123:10")
+ (formatz-should-equal (fz-make+zone 123 2) "+123:02")
+ (formatz-should-equal (fz-make-zone 123 2) "-123:02")
+ )
+
+(defun formatz-seconds-big-helper (form-string pattern-mod)
+ "Tests format %z with hours greater than 99 and non-zero seconds."
+ (formatz-should-equal (fz-make+zone 123 0 30) "+123:00:30")
+ (formatz-should-equal (fz-make-zone 123 0 30) "-123:00:30")
+ (formatz-should-equal (fz-make+zone 120 0 4) "+120:00:04")
+ (formatz-should-equal (fz-make-zone 120 0 4) "-120:00:04")
+ )
+
+;; Functions that modify the expected output string, so that we can
+;; use the above test cases for multiple formats.
+
+(defun formatz-mod-del-colons (string)
+ "Returns STRING with any colons removed."
+ (string-replace ":" "" string))
+
+(defun formatz-mod-add-00 (string)
+ "Returns STRING with \"00\" appended."
+ (concat string "00"))
+
+(defun formatz-mod-add-colon00 (string)
+ "Returns STRING with \":00\" appended."
+ (concat string ":00"))
+
+(defun formatz-mod-pad-r10 (string)
+ "Returns STRING padded on the right to 10 characters."
+ (concat string (make-string (- 10 (length string)) ?\s)))
+
+(defun formatz-mod-pad-r12 (string)
+ "Returns STRING padded on the right to 12 characters."
+ (concat string (make-string (- 12 (length string)) ?\s)))
+
+;; Convenience macro for generating groups of test cases.
+
+(defmacro formatz-generate-tests
+ (form-strings hour-mod mins-mod secs-mod big-mod secbig-mod)
+ "Defines tests for time formats FORM-STRINGS.
+FORM-STRINGS is a list of formats, each \"%z\" or some variation thereof.
+
+Each of the remaining arguments is an unquoted list of the form
+(SAMPLE-OUTPUT . MODIFIERS). SAMPLE-OUTPUT is the result of the
+FORM-STRINGS for a particular offset, detailed below for each argument.
+The remaining elements of the list, the MODIFIERS, are the names of
+functions to modify the expected results for sets of tests.
+The MODIFIERS do not modify the SAMPLE-OUTPUT.
+
+The one, literal sample output is given in the call to this macro
+to provide a visual check at the call site that the format
+behaves as expected.
+
+HOUR-MOD is the result for offset 0 and modifiers for the other
+expected results for whole hours.
+MINS-MOD is the result for offset +30 minutes and modifiers for the
+other expected results for whole minutes.
+SECS-MOD is the result for offset +30 seconds and modifiers for the
+other expected results for offsets with non-zero seconds.
+BIG-MOD is the result for offset +100 hours and modifiers for the other
+expected results for hours greater than 99 with a whole number of minutes.
+SECBIG-MOD is the result for offset +100 hours 30 seconds and modifiers for
+the other expected results for hours greater than 99 with non-zero seconds."
+ (declare (indent 1) (debug (&rest sexp)))
+ ;; Generate a form to create a list of tests to define. When this
+ ;; macro is called, the form is evaluated, thus defining the tests.
+ ;; We will modify this list, so start with a list consed at runtime.
+ (let ((ert-test-list (list 'list)))
+ (dolist (form-string form-strings ert-test-list)
+ (nconc
+ ert-test-list
+ (list
+ `(ert-deftest ,(intern (concat "formatz-" form-string "-hhmm")) ()
+ ,(concat "Tests time-stamp format " form-string
+ " with whole hours or minutes.")
+ (should (equal (formatz ,form-string (fz-make+zone 0))
+ ,(car hour-mod)))
+ (formatz-hours-exact-helper ,form-string ',(cdr hour-mod))
+ (should (equal (formatz ,form-string (fz-make+zone 0 30))
+ ,(car mins-mod)))
+ (formatz-nonzero-minutes-helper ,form-string ',(cdr mins-mod)))
+ `(ert-deftest ,(intern (concat "formatz-" form-string "-seconds")) ()
+ ,(concat "Tests time-stamp format " form-string
+ " with offsets that have non-zero seconds.")
+ (should (equal (formatz ,form-string (fz-make+zone 0 0 30))
+ ,(car secs-mod)))
+ (formatz-nonzero-seconds-helper ,form-string ',(cdr secs-mod)))
+ `(ert-deftest ,(intern (concat "formatz-" form-string "-threedigit")) ()
+ ,(concat "Tests time-stamp format " form-string
+ " with offsets that are 100 hours or greater.")
+ (should (equal (formatz ,form-string (fz-make+zone 100))
+ ,(car big-mod)))
+ (formatz-hours-big-helper ,form-string ',(cdr big-mod))
+ (should (equal (formatz ,form-string (fz-make+zone 100 0 30))
+ ,(car secbig-mod)))
+ (formatz-seconds-big-helper ,form-string ',(cdr secbig-mod)))
+ )))))
+
+;;;; The actual test cases for %z
+
+;;; %z formats without colons.
+
+;; Option character "-" (minus) minimizes; it removes "00" minutes.
+(formatz-generate-tests ("%-z" "%-3z")
+ ("+00")
+ ("+0030" formatz-mod-del-colons)
+ ("+000030" formatz-mod-del-colons)
+ ("+100:00")
+ ("+100:00:30"))
+;; Tests that minus with padding pads with spaces.
+(formatz-generate-tests ("%-12z")
+ ("+00 " formatz-mod-pad-r12)
+ ("+0030 " formatz-mod-del-colons formatz-mod-pad-r12)
+ ("+000030 " formatz-mod-del-colons formatz-mod-pad-r12)
+ ("+100:00 " formatz-mod-pad-r12)
+ ("+100:00:30 " formatz-mod-pad-r12))
+;; Tests that 0 after other digits becomes padding of ten, not zero flag.
+(formatz-generate-tests ("%-10z")
+ ("+00 " formatz-mod-pad-r10)
+ ("+0030 " formatz-mod-del-colons formatz-mod-pad-r10)
+ ("+000030 " formatz-mod-del-colons formatz-mod-pad-r10)
+ ("+100:00 " formatz-mod-pad-r10)
+ ("+100:00:30"))
+
+;; Although time-stamp doesn't call us for %z, we do want to spot-check
+;; it here, to verify the implementation we will eventually use.
+;; The legacy exception for %z in time-stamp will need to remain
+;; through at least 2024 and Emacs 28.
+(ert-deftest formatz-%z-spotcheck ()
+ "Spot-checks internal implementation of time-stamp format %z."
+ (should (equal (format-time-offset "%z" (fz-make+zone 0)) "+0000"))
+ (should (equal (format-time-offset "%z" (fz-make+zone 0 30)) "+0030"))
+ (should (equal (format-time-offset "%z" (fz-make+zone 0 0 30)) "+000030"))
+ (should (equal (format-time-offset "%z" (fz-make+zone 100)) "+100:00"))
+ (should (equal (format-time-offset "%z" (fz-make+zone 100 0 30)) "+100:00:30"))
+ )
+
+;; Basic %z outputs 4 digits.
+;; Small padding values do not extend the result.
+(formatz-generate-tests (;; We don't check %z here because time-stamp
+ ;; has a legacy behavior for it.
+ ;;"%z"
+ "%5z" "%0z" "%05z")
+ ("+0000" formatz-mod-add-00)
+ ("+0030" formatz-mod-del-colons)
+ ("+000030" formatz-mod-del-colons)
+ ("+100:00")
+ ("+100:00:30"))
+
+;; Tests that padding adds spaces.
+(formatz-generate-tests ("%12z")
+ ("+0000 " formatz-mod-add-00 formatz-mod-pad-r12)
+ ("+0030 " formatz-mod-del-colons formatz-mod-pad-r12)
+ ("+000030 " formatz-mod-del-colons formatz-mod-pad-r12)
+ ("+100:00 " formatz-mod-pad-r12)
+ ("+100:00:30 " formatz-mod-pad-r12))
+
+;; Requiring 0-padding to 6 adds seconds (only) as needed.
+(formatz-generate-tests ("%06z")
+ ("+000000" formatz-mod-add-00 formatz-mod-add-00)
+ ("+003000" formatz-mod-del-colons formatz-mod-add-00)
+ ("+000030" formatz-mod-del-colons)
+ ("+100:00")
+ ("+100:00:30"))
+
+;; Option character "_" always adds seconds.
+(formatz-generate-tests ("%_z" "%_7z")
+ ("+000000" formatz-mod-add-00 formatz-mod-add-00)
+ ("+003000" formatz-mod-del-colons formatz-mod-add-00)
+ ("+000030" formatz-mod-del-colons)
+ ("+100:00:00" formatz-mod-add-colon00)
+ ("+100:00:30"))
+
+;; Enough 0-padding adds seconds, then adds spaces.
+(formatz-generate-tests ("%012z" "%_12z")
+ ("+000000 " formatz-mod-add-00 formatz-mod-add-00 formatz-mod-pad-r12)
+ ("+003000 " formatz-mod-del-colons formatz-mod-add-00 formatz-mod-pad-r12)
+ ("+000030 " formatz-mod-del-colons formatz-mod-pad-r12)
+ ("+100:00:00 " formatz-mod-add-colon00 formatz-mod-pad-r12)
+ ("+100:00:30 " formatz-mod-pad-r12))
+
+;;; %z formats with colons
+
+;; Three colons can output hours only,
+;; like %-z, but uses colons with non-zero minutes and seconds.
+(formatz-generate-tests ("%:::z" "%0:::z"
+ "%3:::z" "%03:::z")
+ ("+00")
+ ("+00:30")
+ ("+00:00:30")
+ ("+100:00")
+ ("+100:00:30"))
+
+;; Padding with three colons adds spaces
+(formatz-generate-tests ("%12:::z")
+ ("+00 " formatz-mod-pad-r12)
+ ("+00:30 " formatz-mod-pad-r12)
+ ("+00:00:30 " formatz-mod-pad-r12)
+ ("+100:00 " formatz-mod-pad-r12)
+ ("+100:00:30 " formatz-mod-pad-r12))
+;; Tests that 0 after other digits becomes padding of ten, not zero flag.
+(formatz-generate-tests ("%10:::z")
+ ("+00 " formatz-mod-pad-r10)
+ ("+00:30 " formatz-mod-pad-r10)
+ ("+00:00:30 " formatz-mod-pad-r10)
+ ("+100:00 " formatz-mod-pad-r10)
+ ("+100:00:30"))
+
+;; One colon outputs minutes, like %z but with colon.
+(formatz-generate-tests ("%:z" "%6:z" "%0:z" "%06:z" "%06:::z")
+ ("+00:00" formatz-mod-add-colon00)
+ ("+00:30")
+ ("+00:00:30")
+ ("+100:00")
+ ("+100:00:30"))
+
+;; Padding with one colon adds spaces
+(formatz-generate-tests ("%12:z")
+ ("+00:00 " formatz-mod-add-colon00 formatz-mod-pad-r12)
+ ("+00:30 " formatz-mod-pad-r12)
+ ("+00:00:30 " formatz-mod-pad-r12)
+ ("+100:00 " formatz-mod-pad-r12)
+ ("+100:00:30 " formatz-mod-pad-r12))
+
+;; Requiring 0-padding to 7 adds seconds (only) as needed.
+(formatz-generate-tests ("%07:z" "%07:::z")
+ ("+00:00:00" formatz-mod-add-colon00 formatz-mod-add-colon00)
+ ("+00:30:00" formatz-mod-add-colon00)
+ ("+00:00:30")
+ ("+100:00")
+ ("+100:00:30"))
+
+;; Two colons outputs HH:MM:SS, like %_z but with colons.
+(formatz-generate-tests ("%::z" "%9::z" "%0::z" "%09::z")
+ ("+00:00:00" formatz-mod-add-colon00 formatz-mod-add-colon00)
+ ("+00:30:00" formatz-mod-add-colon00)
+ ("+00:00:30")
+ ("+100:00:00" formatz-mod-add-colon00)
+ ("+100:00:30"))
+
+;; Enough padding adds minutes and seconds, then adds spaces.
+(formatz-generate-tests ("%012:z" "%012::z" "%12::z" "%012:::z")
+ ("+00:00:00 " formatz-mod-add-colon00 formatz-mod-add-colon00
+ formatz-mod-pad-r12)
+ ("+00:30:00 " formatz-mod-add-colon00 formatz-mod-pad-r12)
+ ("+00:00:30 " formatz-mod-pad-r12)
+ ("+100:00:00 " formatz-mod-add-colon00 formatz-mod-pad-r12)
+ ("+100:00:30 " formatz-mod-pad-r12))
+
+;;; Illegal %z formats
+
+(ert-deftest formatz-illegal-options ()
+ "Tests that illegal/nonsensical/ambiguous %z formats don't produce output."
+ ;; multiple options
+ (should (equal "" (formatz "%_-z" 0)))
+ (should (equal "" (formatz "%-_z" 0)))
+ (should (equal "" (formatz "%_0z" 0)))
+ (should (equal "" (formatz "%0_z" 0)))
+ (should (equal "" (formatz "%0-z" 0)))
+ (should (equal "" (formatz "%-0z" 0)))
+ ;; inconsistent to both minimize and require mins or secs
+ (should (equal "" (formatz "%-:z" 0)))
+ (should (equal "" (formatz "%-::z" 0)))
+ ;; consistent, but redundant
+ (should (equal "" (formatz "%-:::z" 0)))
+ (should (equal "" (formatz "%_::z" 0)))
+ ;; inconsistent to both pre-expand and default to hours or mins
+ (should (equal "" (formatz "%_:::z" 0)))
+ (should (equal "" (formatz "%_:z" 0)))
+ ;; options that don't make sense with %z
+ (should (equal "" (formatz "%#z" 0)))
+ )
+
+;;; time-stamp-tests.el ends here
diff --git a/test/lisp/time-tests.el b/test/lisp/time-tests.el
new file mode 100644
index 00000000000..a95871eb56b
--- /dev/null
+++ b/test/lisp/time-tests.el
@@ -0,0 +1,82 @@
+;;; time-tests.el --- Tests for time.el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+;; Author: Stefan Kangas <stefankangas@gmail.com>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'ert-x)
+(require 'time)
+
+(ert-deftest time-tests-display-time-mail-check-directory ()
+ (let ((display-time-mail-directory (ert-resource-directory)))
+ (should (display-time-mail-check-directory))))
+
+(ert-deftest time-tests-display-time-update--load ()
+ (let ((display-time-load-average 1)
+ (display-time-load-average-threshold 0))
+ (display-time-next-load-average)
+ (should (string-match (rx string-start " "
+ (+ (| digit "."))
+ string-end)
+ (display-time-update--load))))
+ (let (display-time-load-average)
+ (should (equal (display-time-update--load) ""))))
+
+(ert-deftest time-tests-display-time-update ()
+ (let ((display-time-load-average 1)
+ (display-time-load-average-threshold 0)
+ display-time-string)
+ (display-time-update)
+ (should (string-match (rx string-start
+ (? digit) digit ":" digit digit
+ (? (| "AM" "PM"))
+ " " (+ (| digit "."))
+ (? " Mail")
+ " "
+ string-end)
+ display-time-string))))
+
+(ert-deftest time-tests-display-time-file-nonempty-p ()
+ (should (display-time-file-nonempty-p (ert-resource-file "non-empty")))
+ (should-not (display-time-file-nonempty-p "/non/existent")))
+
+(ert-deftest time-tests-world-clock ()
+ (save-window-excursion
+ (world-clock)
+ (should (equal (buffer-name) world-clock-buffer-name))
+ (should (string-match "New York" (buffer-string)))))
+
+(ert-deftest time-tests-world-clock/revert-buffer-works ()
+ (save-window-excursion
+ (world-clock)
+ (revert-buffer)
+ (should (string-match "New York" (buffer-string)))))
+
+(ert-deftest time-tests-emacs-uptime ()
+ (should (string-match "^[0-9.]+ seconds?$" (emacs-uptime "%S"))))
+
+(ert-deftest time-tests-emacs-init-time ()
+ (should (string-match "^[0-9.]+ seconds?$" (emacs-init-time))))
+
+(provide 'time-tests)
+;;; time-tests.el ends here
diff --git a/test/lisp/timezone-tests.el b/test/lisp/timezone-tests.el
new file mode 100644
index 00000000000..a87f2623767
--- /dev/null
+++ b/test/lisp/timezone-tests.el
@@ -0,0 +1,172 @@
+;;; timezone-tests.el --- Tests for timezone.el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2019-2022 Free Software Foundation, Inc.
+
+;; Author: Stefan Kangas <stefankangas@gmail.com>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'timezone)
+
+(ert-deftest timezone-tests-make-date-arpa-standard ()
+ (should (equal (timezone-make-date-arpa-standard "14 Apr 89 03:20" "PST" "GMT")
+ "14 Apr 1989 11:20:00 GMT"))
+ (should (equal (timezone-make-date-arpa-standard "14 Apr 89 03:20" "GMT" "GMT")
+ "14 Apr 1989 03:20:00 GMT"))
+ (should (equal (timezone-make-date-arpa-standard "14 Apr 89 03:20" nil "GMT") ; assume GMT
+ "14 Apr 1989 03:20:00 GMT")))
+
+(ert-deftest timezone-tests-make-date-sortable ()
+ (should (equal (timezone-make-date-sortable "14 Apr 89 03:20" "GMT" "GMT")
+ "1989041403:20:00"))
+ (should (equal (timezone-make-date-sortable "14 Apr 89 03:20" nil "GMT") ; assume GMT
+ "1989041403:20:00")))
+
+(ert-deftest timezone-tests-make-arpa-date ()
+ (should (equal (timezone-make-arpa-date 2020 1 1 "00:00")
+ "01 Jan 2020 00:00 +0000"))
+ (should (equal (timezone-make-arpa-date 2020 1 1 "00:00" "GMT")
+ "01 Jan 2020 00:00 GMT")))
+
+(ert-deftest timezone-tests-make-sortable-date ()
+ (should (equal (timezone-make-sortable-date 2020 1 1 "00:00")
+ "2020010100:00")))
+
+(ert-deftest timezone-tests-make-time-string ()
+ (should (equal (timezone-make-time-string 1 2 3) "01:02:03")))
+
+(ert-deftest timezone-tests-parse-date ()
+ ;; Accepted style 1 from docstring
+ (should (equal (timezone-parse-date "14 Apr 89 03:20")
+ ["1989" "4" "14" "03:20" nil]))
+ (should (equal (timezone-parse-date "14 Apr 89 03:20 GMT")
+ ["1989" "4" "14" "03:20" "GMT"]))
+ (should (equal (timezone-parse-date "14 Apr 89 03:20:12")
+ ["1989" "4" "14" "03:20:12" nil]))
+ (should (equal (timezone-parse-date "14 Apr 89 03:20:12 GMT")
+ ["1989" "4" "14" "03:20:12" "GMT"]))
+ ;; Accepted style 2 from docstring
+ (should (equal (timezone-parse-date "Fri, 17 Mar 89 4:01")
+ ["1989" "3" "17" "4:01" nil]))
+ (should (equal (timezone-parse-date "Fri, 17 Mar 89 4:01 GMT")
+ ["1989" "3" "17" "4:01" "GMT"]))
+ (should (equal (timezone-parse-date "Fri, 17 Mar 89 4:01:33")
+ ["1989" "3" "17" "4:01:33" nil]))
+ (should (equal (timezone-parse-date "Fri, 17 Mar 89 4:01:33 GMT")
+ ["1989" "3" "17" "4:01:33" "GMT"]))
+ ;; Accepted style 3 from docstring
+ (should (equal (timezone-parse-date "Mon Jan 16 16:12 1989")
+ ["1989" "1" "16" "16:12" nil]))
+ (should (equal (timezone-parse-date "Mon Jan 16 16:12 GMT 1989")
+ ["1989" "1" "16" "16:12" "GMT"]))
+ (should (equal (timezone-parse-date "Mon Jan 16 16:12:37 1989")
+ ["1989" "1" "16" "16:12:37" nil]))
+ (should (equal (timezone-parse-date "Mon Jan 16 16:12:37 GMT 1989")
+ ["1989" "1" "16" "16:12:37" "GMT"]))
+ ;; Accepted style 4 from docstring
+ (should (equal (timezone-parse-date "6 May 1992 1641-JST (Wednesday)")
+ ["1992" "5" "6" "1641" "-JST"]))
+ ;; Accepted style 5 from docstring
+ (should (equal (timezone-parse-date "22-AUG-1993 10:59:12.82")
+ ["1993" "8" "22" "10:59:12" nil]))
+ ;; Accepted style 6 from docstring
+ (should (equal (timezone-parse-date "Thu, 11 Apr 16:17:12 91")
+ ["1991" "4" "11" "16:17:12" nil]))
+ (should (equal (timezone-parse-date "Thu, 11 Apr 16:17:12 91 MET")
+ ["1991" "4" "11" "16:17:12" "MET"]))
+ ;; Accepted style 7 from docstring
+ (should (equal (timezone-parse-date "Mon, 6 Jul 16:47:20 T 1992")
+ ["1992" "7" "6" "16:47:20" nil]))
+ (should (equal (timezone-parse-date "Mon, 6 Jul 16:47:20 T 1992 MET")
+ ["1992" "7" "6" "16:47:20" "MET"]))
+ ;; Accepted style 8 from docstring
+ (should (equal (timezone-parse-date "1996-06-24 21:13")
+ ["1996" "06" "24" "21:13" nil]))
+ (should (equal (timezone-parse-date "1996-06-24 21:13 GMT")
+ ["1996" "06" "24" "21:13" "GMT"]))
+ (should (equal (timezone-parse-date "1996-06-24 21:13:12")
+ ["1996" "06" "24" "21:13:12" nil]))
+ (should (equal (timezone-parse-date "1996-06-24 21:13:12 GMT")
+ ["1996" "06" "24" "21:13:12" "GMT"]))
+ ;; Accepted style 9 from docstring
+ (should (equal (timezone-parse-date "1996-06-24 21:13-ZONE")
+ ["1996" "06" "24" "21:13" "-ZONE"]))
+ ;; Accepted style 10 from docstring
+ (should (equal (timezone-parse-date "19960624T211312")
+ ["1996" "06" "24" "211312" nil]))
+ (should (equal (timezone-parse-date "*invalid*") ["0" "0" "0" "0" nil])))
+
+(ert-deftest timezone-tests-parse-date/windowed-dates ()
+ (should (equal (timezone-parse-date "14 Apr 69 10:00")
+ ["1969" "4" "14" "10:00" nil]))
+ (should (equal (timezone-parse-date "14 Apr 68 10:00")
+ ["2068" "4" "14" "10:00" nil]))
+ (should (equal (timezone-parse-date "14 Apr 199 10:00")
+ ["2099" "4" "14" "10:00" nil])))
+
+(ert-deftest timezone-tests-parse-time ()
+ (should (equal (timezone-parse-time "1234") ["12" "34" "0"]))
+ (should (equal (timezone-parse-time "12:34") ["12" "34" "0"]))
+ (should (equal (timezone-parse-time "123456") ["12" "34" "56"]))
+ (should (equal (timezone-parse-time "12:34:56") ["12" "34" "56"]))
+ (should (equal (timezone-parse-time "*invalid*") ["0" "0" "0"])))
+
+(ert-deftest timezone-tests-zone-to-minute ()
+ (should (equal (timezone-zone-to-minute "GMT") 0))
+ (should (equal (timezone-zone-to-minute "CDT") -300))
+ (should (equal (timezone-zone-to-minute "+100") 60))
+ (should (equal (timezone-zone-to-minute "-100") -60))
+ (should (equal (timezone-zone-to-minute "*invalid*") 0)))
+
+(ert-deftest timezone-tests-time-from-absolute ()
+ (should (time-equal-p
+ (timezone-time-from-absolute (* 2020 365) ; Jan 1 2020
+ (* 12 60 60)) ; 12:00
+ '(23911 48704 0 0))))
+
+;; TODO: Write tests for timezone-tests-time-zone-from-absolute, which is a
+;; bit tricky since the results depend on `current-time-zone'.
+
+(ert-deftest timezone-tests-fix-time ()
+ (should (equal (timezone-fix-time "20200501 20:20" "GMT" "GMT")
+ [2020 5 1 20 20 0 "GMT"]))
+ (should (equal (timezone-fix-time "20200501 20:20" nil "GMT") ; assume GMT
+ [2020 5 1 20 20 0 "GMT"])))
+
+(ert-deftest timezone-tests-last-day-of-month ()
+ (should (equal (timezone-last-day-of-month 2 1999) 28))
+ (should (equal (timezone-last-day-of-month 2 2000) 29))) ; leap year
+
+(ert-deftest timezone-tests-leap-year-p ()
+ (should (equal (timezone-leap-year-p 1999) nil))
+ (should (equal (timezone-leap-year-p 2000) t))
+ (should (equal (timezone-leap-year-p 2024) t))
+ (should (equal (timezone-leap-year-p 2100) nil)))
+
+(ert-deftest timezone-tests-day-number ()
+ (should (equal (timezone-day-number 5 1 1999) 121))
+ (should (equal (timezone-day-number 5 1 2000) 122))) ; leap year
+
+(ert-deftest timezone-tests-absolute-from-gregorian ()
+ (should (equal (timezone-absolute-from-gregorian 1 1 2020) 737425)))
+
+(provide 'timezone-tests)
+;;; timezone-tests.el ends here
diff --git a/test/lisp/url/url-auth-tests.el b/test/lisp/url/url-auth-tests.el
index e7aeb6e6164..fa6ecdce390 100644
--- a/test/lisp/url/url-auth-tests.el
+++ b/test/lisp/url/url-auth-tests.el
@@ -1,6 +1,6 @@
-;;; url-auth-tests.el --- Test suite for url-auth.
+;;; url-auth-tests.el --- Test suite for url-auth. -*- lexical-binding:t -*-
-;; Copyright (C) 2015-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2022 Free Software Foundation, Inc.
;; Author: Jarno Malmari <jarno@malmari.fi>
@@ -154,7 +154,7 @@ Essential is how realms and paths are matched."
auth)
(dolist (row (list
- ;; If :expected-user is `nil' it indicates
+ ;; If :expected-user is nil it indicates
;; authentication information shouldn't be found.
;; non-existent server
diff --git a/test/lisp/url/url-domsuf-tests.el b/test/lisp/url/url-domsuf-tests.el
new file mode 100644
index 00000000000..33962846820
--- /dev/null
+++ b/test/lisp/url/url-domsuf-tests.el
@@ -0,0 +1,51 @@
+;;; url-domsuf-tests.el --- Tests for url-domsuf.el -*- lexical-binding:t -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'url-domsuf)
+(require 'ert)
+
+(defun url-domsuf-tests--run ()
+ (should-not (url-domsuf-cookie-allowed-p "com"))
+ (should (url-domsuf-cookie-allowed-p "foo.bar.bd"))
+ (should-not (url-domsuf-cookie-allowed-p "bar.bd"))
+ (should-not (url-domsuf-cookie-allowed-p "co.uk"))
+ (should (url-domsuf-cookie-allowed-p "foo.bar.hokkaido.jo"))
+ (should-not (url-domsuf-cookie-allowed-p "bar.yokohama.jp"))
+ (should (url-domsuf-cookie-allowed-p "city.yokohama.jp")))
+
+(ert-deftest url-domsuf-test-cookie-allowed-p ()
+ "Run the domsuf tests without need for parsing a file."
+ (let ((url-domsuf-domains '(("com")
+ ("bar.bd")
+ ("co.uk")
+ ("bar.yokohama.jp"))))
+ (url-domsuf-tests--run)))
+
+(ert-deftest url-domsuf-test-cookie-allowed-p/and-parse ()
+ "Run the domsuf tests, but also parse the file."
+ :tags '(:expensive-test)
+ (url-domsuf-tests--run))
+
+(provide 'url-domsuf-tests)
+
+;;; url-domsuf-tests.el ends here
diff --git a/test/lisp/url/url-expand-tests.el b/test/lisp/url/url-expand-tests.el
index d147bddb3d3..a9695c6a192 100644
--- a/test/lisp/url/url-expand-tests.el
+++ b/test/lisp/url/url-expand-tests.el
@@ -1,6 +1,6 @@
-;;; url-expand-tests.el --- Test suite for relative URI/URL resolution.
+;;; url-expand-tests.el --- Test suite for relative URI/URL resolution. -*- lexical-binding:t -*-
-;; Copyright (C) 2012-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2022 Free Software Foundation, Inc.
;; Author: Alain Schneble <a.s@realize.ch>
;; Version: 1.0
@@ -100,6 +100,13 @@
(should (equal (url-expand-file-name "foo#bar" "http://host/foobar") "http://host/foo#bar"))
(should (equal (url-expand-file-name "foo#bar" "http://host/foobar/") "http://host/foobar/foo#bar")))
+(ert-deftest url-expand-file-name/relative-resolution-file-url ()
+ "RFC 3986, Section 5.4 Reference Resolution Examples / Section 5.4.1. Normal Examples"
+ (should (equal (url-expand-file-name "bar.html" "file:///a/b/c/foo.html") "file:///a/b/c/bar.html"))
+ (should (equal (url-expand-file-name "bar.html" "file:///a/b/c/") "file:///a/b/c/bar.html"))
+ (should (equal (url-expand-file-name "../d/bar.html" "file:///a/b/c/") "file:///a/b/d/bar.html"))
+ (should (equal (url-expand-file-name "../d/bar.html" "file:///a/b/c/foo.html") "file:///a/b/d/bar.html")))
+
(provide 'url-expand-tests)
;;; url-expand-tests.el ends here
diff --git a/test/lisp/url/url-file-resources/file.txt b/test/lisp/url/url-file-resources/file.txt
new file mode 100644
index 00000000000..b0b4e38e5fd
--- /dev/null
+++ b/test/lisp/url/url-file-resources/file.txt
@@ -0,0 +1 @@
+Some file data
diff --git a/test/lisp/url/url-file-tests.el b/test/lisp/url/url-file-tests.el
new file mode 100644
index 00000000000..9fe3cb38ebb
--- /dev/null
+++ b/test/lisp/url/url-file-tests.el
@@ -0,0 +1,44 @@
+;;; url-file-tests.el --- Test suite for url-file. -*- lexical-binding: t -*-
+
+;; Copyright (C) 2018-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'url-file)
+(require 'ert)
+(require 'ert-x)
+
+(ert-deftest url-file ()
+ "Test reading file via file:/// URL."
+ (let* ((file (ert-resource-file "file.txt"))
+ (uri-prefix (if (eq (aref file 0) ?/) "file://" "file:///")))
+ (should (equal
+ (with-current-buffer
+ (url-file (url-generic-parse-url (concat uri-prefix file))
+ #'ignore nil)
+ (prog1 (buffer-substring (point) (point-max))
+ (kill-buffer)))
+ (with-temp-buffer
+ (insert-file-contents-literally file)
+ (buffer-string))))))
+
+(provide 'url-file-tests)
+
+;;; url-file-tests.el ends here
diff --git a/test/lisp/url/url-future-tests.el b/test/lisp/url/url-future-tests.el
index e7bcbd696a4..5083fc5abae 100644
--- a/test/lisp/url/url-future-tests.el
+++ b/test/lisp/url/url-future-tests.el
@@ -1,6 +1,6 @@
-;;; url-future-tests.el --- Test suite for url-future.
+;;; url-future-tests.el --- Test suite for url-future. -*- lexical-binding:t -*-
-;; Copyright (C) 2011-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2022 Free Software Foundation, Inc.
;; Author: Teodor Zlatanov <tzz@lifelogs.com>
;; Keywords: data
@@ -25,31 +25,33 @@
(require 'ert)
(require 'url-future)
+(defvar url-future-tests--saver)
+
(ert-deftest url-future-tests ()
- (let* (saver
+ (let* (url-future-tests--saver
(text "running future")
(good (make-url-future :value (lambda () (format text))
- :callback (lambda (f) (set 'saver f))))
+ :callback (lambda (f) (setq url-future-tests--saver f))))
(bad (make-url-future :value (lambda () (/ 1 0))
- :errorback (lambda (&rest d) (set 'saver d))))
+ :errorback (lambda (&rest d) (setq url-future-tests--saver d))))
(tocancel (make-url-future :value (lambda () (/ 1 0))
- :callback (lambda (f) (set 'saver f))
+ :callback (lambda (f) (setq url-future-tests--saver f))
:errorback (lambda (&rest d)
- (set 'saver d)))))
+ (setq url-future-tests--saver d)))))
(should (equal good (url-future-call good)))
- (should (equal good saver))
+ (should (equal good url-future-tests--saver))
(should (equal text (url-future-value good)))
(should (url-future-completed-p good))
(should-error (url-future-call good))
- (setq saver nil)
+ (setq url-future-tests--saver nil)
(should (equal bad (url-future-call bad)))
(should-error (url-future-call bad))
- (should (equal saver (list bad '(arith-error))))
+ (should (equal url-future-tests--saver (list bad '(arith-error))))
(should (url-future-errored-p bad))
- (setq saver nil)
+ (setq url-future-tests--saver nil)
(should (equal (url-future-cancel tocancel) tocancel))
(should-error (url-future-call tocancel))
- (should (null saver))
+ (should (null url-future-tests--saver))
(should (url-future-cancelled-p tocancel))))
(provide 'url-future-tests)
diff --git a/test/lisp/url/url-handlers-tests.el b/test/lisp/url/url-handlers-tests.el
new file mode 100644
index 00000000000..f43e9651f5e
--- /dev/null
+++ b/test/lisp/url/url-handlers-tests.el
@@ -0,0 +1,76 @@
+;;; url-handlers-tests.el --- Test suite for url-handlers.el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2018-2022 Free Software Foundation, Inc.
+
+;; Author: Nicolas Petton <nicolas@petton.fr>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'url-handlers)
+
+(defmacro with-url-handler-mode (&rest body)
+ "Evaluate BODY with `url-handler-mode' turned on."
+ (declare (indent 0) (debug t))
+ (let ((url-handler-mode-active (make-symbol "url-handler-mode-active")))
+ `(let ((,url-handler-mode-active url-handler-mode))
+ (unwind-protect
+ (progn
+ (unless ,url-handler-mode-active
+ (url-handler-mode))
+ ,@body)
+ (unless ,url-handler-mode-active
+ (url-handler-mode -1))))))
+
+(ert-deftest url-handlers-file-name-directory/preserve-url-types ()
+ (with-url-handler-mode
+ (should (equal (file-name-directory "https://gnu.org/index.html")
+ "https://gnu.org/"))
+ (should (equal (file-name-directory "http://gnu.org/index.html")
+ "http://gnu.org/"))
+ (should (equal (file-name-directory "ftp://gnu.org/index.html")
+ "ftp://gnu.org/"))))
+
+(ert-deftest url-handlers-file-name-directory/should-not-handle-non-url-file-names ()
+ (with-url-handler-mode
+ (should-not (equal (file-name-directory "not-uri://gnu.org")
+ "not-uri://gnu.org/"))))
+
+(ert-deftest url-handlers-file-name-directory/sub-directories ()
+ (with-url-handler-mode
+ (should (equal (file-name-directory "https://foo/bar/baz/index.html")
+ "https://foo/bar/baz/"))))
+
+(ert-deftest url-handlers-file-name-directory/file-urls ()
+ (with-url-handler-mode
+ (should (equal (file-name-directory "file:///foo/bar/baz.txt")
+ "file:///foo/bar/"))
+ (should (equal (file-name-directory "file:///")
+ "file:///"))))
+
+;; Regression test for bug#30444
+(ert-deftest url-handlers-file-name-directory/no-filename ()
+ (with-url-handler-mode
+ (should (equal (file-name-directory "https://foo.org")
+ "https://foo.org/"))
+ (should (equal (file-name-directory "https://foo.org/")
+ "https://foo.org/"))))
+
+;;; url-handlers-tests.el ends here
diff --git a/test/lisp/url/url-misc-tests.el b/test/lisp/url/url-misc-tests.el
new file mode 100644
index 00000000000..df561eb8887
--- /dev/null
+++ b/test/lisp/url/url-misc-tests.el
@@ -0,0 +1,41 @@
+;;; url-misc-tests.el --- Test suite for url-misc. -*- lexical-binding: t -*-
+
+;; Copyright (C) 2018-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'url-misc)
+(require 'ert)
+
+(ert-deftest url-misc-data ()
+ "Test reading data: URL."
+ (should (equal
+ (with-current-buffer
+ (url-data (url-generic-parse-url "data:;,some%20text"))
+ (goto-char (point-min))
+ (forward-paragraph)
+ (forward-line)
+ (prog1 (buffer-substring (point) (point-max))
+ (kill-buffer)))
+ "some text")))
+
+(provide 'url-misc-tests)
+
+;;; url-misc-tests.el ends here
diff --git a/test/lisp/url/url-parse-tests.el b/test/lisp/url/url-parse-tests.el
index 56be313b776..c115da1e4ba 100644
--- a/test/lisp/url/url-parse-tests.el
+++ b/test/lisp/url/url-parse-tests.el
@@ -1,6 +1,6 @@
-;;; url-parse-tests.el --- Test suite for URI/URL parsing.
+;;; url-parse-tests.el --- Test suite for URI/URL parsing. -*- lexical-binding:t -*-
-;; Copyright (C) 2012-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2022 Free Software Foundation, Inc.
;; Author: Alain Schneble <a.s@realize.ch>
;; Version: 1.0
@@ -23,7 +23,7 @@
;;; Commentary:
;; Test cases covering generic URI syntax as described in RFC3986,
-;; section 3. Syntax Components and 4. Usage. See also appendix
+;; section 3. Syntax Components and 4. Usage. See also appendix
;; A. Collected ABNF for URI, as the example given here are all
;; productions of this grammar.
diff --git a/test/lisp/url/url-tramp-tests.el b/test/lisp/url/url-tramp-tests.el
new file mode 100644
index 00000000000..369de0e2457
--- /dev/null
+++ b/test/lisp/url/url-tramp-tests.el
@@ -0,0 +1,91 @@
+;;; url-tramp-tests.el --- Test suite for Tramp / URL conversion. -*- lexical-binding:t -*-
+
+;; Copyright (C) 2017-2022 Free Software Foundation, Inc.
+
+;; Author: Michael Albinus <michael.albinus@gmx.de>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'url-tramp)
+(require 'ert)
+
+(ert-deftest url-tramp-test-convert-url-to-tramp ()
+ "Test that URLs are converted into proper Tramp file names."
+ (should
+ (string-equal
+ (url-tramp-convert-url-to-tramp "ftp://ftp.is.co.za/rfc/rfc1808.txt")
+ "/ftp:ftp.is.co.za:/rfc/rfc1808.txt"))
+
+ (should
+ (string-equal
+ (url-tramp-convert-url-to-tramp "ssh://user@localhost")
+ "/ssh:user@localhost:"))
+
+ (should
+ (string-equal
+ (url-tramp-convert-url-to-tramp "telnet://remotehost:42")
+ "/telnet:remotehost#42:"))
+
+ ;; The password will be added to the cache. The password cache key
+ ;; is the remote file name identification of the Tramp file.
+ (should
+ (string-equal
+ (url-tramp-convert-url-to-tramp "scp://user:geheim@somewhere/localfile")
+ "/scp:user@somewhere:/localfile"))
+ (let ((key
+ (file-remote-p
+ (url-tramp-convert-url-to-tramp "scp://user@somewhere/localfile"))))
+ (should (password-in-cache-p key))
+ (should (string-equal (password-read-from-cache key) "geheim"))
+ (password-cache-remove key)
+ (should-not (password-in-cache-p key)))
+
+ ;; "http" does not belong to `url-tramp-protocols'. The string
+ ;; isn't changed, therefore.
+ (should
+ (string-equal
+ (url-tramp-convert-url-to-tramp "http://www.gnu.org")
+ "http://www.gnu.org")))
+
+(ert-deftest url-tramp-test-convert-tramp-to-url ()
+ "Test that Tramp file names are converted into proper URLs."
+ (should
+ (string-equal
+ (url-tramp-convert-tramp-to-url "/ftp:ftp.is.co.za:/rfc/rfc1808.txt")
+ "ftp://ftp.is.co.za/rfc/rfc1808.txt"))
+
+ (should
+ (string-equal
+ (url-tramp-convert-tramp-to-url "/ssh:user@localhost:")
+ "ssh://user@localhost"))
+
+ (should
+ (string-equal
+ (url-tramp-convert-tramp-to-url "/telnet:user@remotehost#42:")
+ "telnet://user@remotehost:42"))
+
+ ;; "sftp" does not belong to `url-tramp-protocols'. The string
+ ;; isn't changed, therefore.
+ (should
+ (string-equal
+ (url-tramp-convert-tramp-to-url "/sftp:user@localhost:")
+ "/sftp:user@localhost:")))
+
+(provide 'url-tramp-tests)
+
+;;; url-tramp-tests.el ends here
diff --git a/test/lisp/url/url-util-tests.el b/test/lisp/url/url-util-tests.el
index 0d9ad9074d2..cfc2d93c890 100644
--- a/test/lisp/url/url-util-tests.el
+++ b/test/lisp/url/url-util-tests.el
@@ -1,6 +1,6 @@
-;;; url-util-tests.el --- Test suite for url-util.
+;;; url-util-tests.el --- Test suite for url-util. -*- lexical-binding:t -*-
-;; Copyright (C) 2012-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2022 Free Software Foundation, Inc.
;; Author: Teodor Zlatanov <tzz@lifelogs.com>
;; Keywords: data
@@ -46,6 +46,38 @@
("key2" "val2")
("key1" "val1")))))
+(ert-deftest url-unhex-string-tests ()
+ (should (equal (url-unhex-string "foo%20bar")
+ "foo bar"))
+ (should (equal (decode-coding-string (url-unhex-string "Fran%C3%A7ois") 'utf-8)
+ "François"))
+ (should (equal (url-unhex-string "%20%21%23%24%25%26%27%28%29%2A")
+ " !#$%&'()*"))
+ (should (equal (url-unhex-string "%2B%2C%2F%3A%3B%3D%3F%40%5B%5D")
+ "+,/:;=?@[]")))
+
+(ert-deftest url-hexify-string-tests ()
+ (should (equal (url-hexify-string "foo bar")
+ "foo%20bar"))
+ (should (equal (url-hexify-string "François")
+ "Fran%C3%A7ois"))
+ (should (equal (url-hexify-string " !#$%&'()*")
+ "%20%21%23%24%25%26%27%28%29%2A"))
+ (should (equal (url-hexify-string "+,/:;=?@[]")
+ "%2B%2C%2F%3A%3B%3D%3F%40%5B%5D")))
+
+(ert-deftest url-domain-tests ()
+ (should (equal (url-domain (url-generic-parse-url "http://www.fsf.co.uk"))
+ "fsf.co.uk"))
+ (should (equal (url-domain (url-generic-parse-url "http://fsf.co.uk"))
+ "fsf.co.uk"))
+ (should (equal (url-domain (url-generic-parse-url "http://co.uk"))
+ nil))
+ (should (equal (url-domain (url-generic-parse-url "http://www.fsf.com"))
+ "fsf.com"))
+ (should (equal (url-domain (url-generic-parse-url "http://192.168.0.1"))
+ nil)))
+
(provide 'url-util-tests)
;;; url-util-tests.el ends here
diff --git a/test/lisp/vc/add-log-tests.el b/test/lisp/vc/add-log-tests.el
index 746c21644a3..bb6841b6453 100644
--- a/test/lisp/vc/add-log-tests.el
+++ b/test/lisp/vc/add-log-tests.el
@@ -1,6 +1,6 @@
-;;; add-log-tests.el --- Test suite for add-log.
+;;; add-log-tests.el --- Test suite for add-log. -*- lexical-binding:t -*-
-;; Copyright (C) 2013-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2022 Free Software Foundation, Inc.
;; Author: Masatake YAMATO <yamato@redhat.com>
;; Keywords: vc tools
@@ -25,12 +25,12 @@
(require 'ert)
(require 'add-log)
-(defmacro add-log-current-defun-deftest (name doc major-mode
+(defmacro add-log-current-defun-deftest (name doc mode
content marker expected-defun)
"Generate an ert test for mode-own `add-log-current-defun-function'.
-Run `add-log-current-defun' at the point where MARKER specifies in a
-buffer which content is CONTENT under MAJOR-MODE. Then it compares the
-result with EXPECTED-DEFUN."
+Run `add-log-current-defun' at the point where MARKER specifies
+in a buffer which content is CONTENT under major mode MODE.
+Then it compares the result with EXPECTED-DEFUN."
(let ((xname (intern (concat "add-log-current-defun-test-"
(symbol-name name)
))))
@@ -39,7 +39,7 @@ result with EXPECTED-DEFUN."
(with-temp-buffer
(insert ,content)
(goto-char (point-min))
- (funcall ',major-mode)
+ (funcall ',mode)
(should (equal (when (search-forward ,marker nil t)
(replace-match "" nil t)
(add-log-current-defun))
diff --git a/test/lisp/vc/diff-mode-resources/hello_emacs.c b/test/lisp/vc/diff-mode-resources/hello_emacs.c
new file mode 100644
index 00000000000..c7ed7538c3a
--- /dev/null
+++ b/test/lisp/vc/diff-mode-resources/hello_emacs.c
@@ -0,0 +1,6 @@
+#include <stdio.h>
+int main()
+{
+ printf("Hello, Emacs!\n");
+ return 0;
+}
diff --git a/test/lisp/vc/diff-mode-resources/hello_emacs_1.c b/test/lisp/vc/diff-mode-resources/hello_emacs_1.c
new file mode 100644
index 00000000000..62145a6b44a
--- /dev/null
+++ b/test/lisp/vc/diff-mode-resources/hello_emacs_1.c
@@ -0,0 +1 @@
+int main() { printf("Hello, Emacs!\n"); return 0; } \ No newline at end of file
diff --git a/test/lisp/vc/diff-mode-resources/hello_world.c b/test/lisp/vc/diff-mode-resources/hello_world.c
new file mode 100644
index 00000000000..dcbe06c6012
--- /dev/null
+++ b/test/lisp/vc/diff-mode-resources/hello_world.c
@@ -0,0 +1,6 @@
+#include <stdio.h>
+int main()
+{
+ printf("Hello, World!\n");
+ return 0;
+}
diff --git a/test/lisp/vc/diff-mode-resources/hello_world_1.c b/test/lisp/vc/diff-mode-resources/hello_world_1.c
new file mode 100644
index 00000000000..606afb371cb
--- /dev/null
+++ b/test/lisp/vc/diff-mode-resources/hello_world_1.c
@@ -0,0 +1 @@
+int main() { printf("Hello, World!\n"); return 0; } \ No newline at end of file
diff --git a/test/lisp/vc/diff-mode-tests.el b/test/lisp/vc/diff-mode-tests.el
index d27ea668131..19e3dbb42a6 100644
--- a/test/lisp/vc/diff-mode-tests.el
+++ b/test/lisp/vc/diff-mode-tests.el
@@ -1,4 +1,6 @@
-;; Copyright (C) 2017 Free Software Foundation, Inc
+;;; diff-mode-tests.el --- Tests for diff-mode.el -*- lexical-binding:t -*-
+
+;; Copyright (C) 2017-2022 Free Software Foundation, Inc.
;; Author: Dima Kogan <dima@secretsauce.net>
;; Maintainer: emacs-devel@gnu.org
@@ -20,8 +22,10 @@
;;; Code:
+(require 'ert)
+(require 'ert-x)
(require 'diff-mode)
-
+(require 'diff)
(ert-deftest diff-mode-test-ignore-trailing-dashes ()
"Check to make sure we successfully ignore trailing -- made by
@@ -169,35 +173,310 @@ wristwatches
wrongheadedly
wrongheadedness
youthfulness
-")
- (temp-dir (make-temp-file "diff-mode-test" 'dir)))
-
- (let ((buf (find-file-noselect (format "%s/%s" temp-dir "fil" )))
- (buf2 (find-file-noselect (format "%s/%s" temp-dir "fil2"))))
- (unwind-protect
- (progn
- (with-current-buffer buf (insert fil_before) (save-buffer))
- (with-current-buffer buf2 (insert fil2_before) (save-buffer))
-
- (with-temp-buffer
- (cd temp-dir)
- (insert patch)
- (beginning-of-buffer)
- (diff-apply-hunk)
- (diff-apply-hunk)
- (diff-apply-hunk))
-
- (should (equal (with-current-buffer buf (buffer-string))
- fil_after))
- (should (equal (with-current-buffer buf2 (buffer-string))
- fil2_after)))
-
- (ignore-errors
- (with-current-buffer buf (set-buffer-modified-p nil))
- (kill-buffer buf)
- (with-current-buffer buf2 (set-buffer-modified-p nil))
- (kill-buffer buf2)
- (delete-directory temp-dir 'recursive))))))
+"))
+ (ert-with-temp-directory temp-dir
+ (let ((buf (find-file-noselect (format "%s/%s" temp-dir "fil" )))
+ (buf2 (find-file-noselect (format "%s/%s" temp-dir "fil2"))))
+ (unwind-protect
+ (progn
+ (with-current-buffer buf (insert fil_before) (save-buffer))
+ (with-current-buffer buf2 (insert fil2_before) (save-buffer))
+
+ (with-temp-buffer
+ (cd temp-dir)
+ (insert patch)
+ (goto-char (point-min))
+ (diff-apply-hunk)
+ (diff-apply-hunk)
+ (diff-apply-hunk))
+
+ (should (equal (with-current-buffer buf (buffer-string))
+ fil_after))
+ (should (equal (with-current-buffer buf2 (buffer-string))
+ fil2_after)))
+
+ (ignore-errors
+ (with-current-buffer buf (set-buffer-modified-p nil))
+ (kill-buffer buf)
+ (with-current-buffer buf2 (set-buffer-modified-p nil))
+ (kill-buffer buf2)))))))
+
+(ert-deftest diff-mode-test-hunk-text-no-newline ()
+ "Check output of `diff-hunk-text' with no newline at end of file."
+
+ ;; First check unified change/remove/add cases with newline
+ (let ((hunk "\
+@@ -1 +1 @@
+-foo
++bar
+"))
+ (should (equal (diff-hunk-text hunk nil nil) "\
+foo
+"))
+ (should (equal (diff-hunk-text hunk t nil) "\
+bar
+")))
+
+ (let ((hunk "\
+@@ -1 +0,0 @@
+-foo
+"))
+ (should (equal (diff-hunk-text hunk nil nil) "\
+foo
+"))
+ (should (equal (diff-hunk-text hunk t nil) "\
+")))
+
+ (let ((hunk "\
+@@ -0,0 +1 @@
++bar
+"))
+ (should (equal (diff-hunk-text hunk nil nil) "\
+"))
+ (should (equal (diff-hunk-text hunk t nil) "\
+bar
+")))
+
+ ;; Check unified change/remove cases with no newline in old file
+ (let ((hunk "\
+@@ -1 +1 @@
+-foo
+\\ No newline at end of file
++bar
+"))
+ (should (equal (diff-hunk-text hunk nil nil) "\
+foo"))
+ (should (equal (diff-hunk-text hunk t nil) "\
+bar
+")))
+
+ (let ((hunk "\
+@@ -1 +0,0 @@
+-foo
+\\ No newline at end of file
+"))
+ (should (equal (diff-hunk-text hunk nil nil) "\
+foo"))
+ (should (equal (diff-hunk-text hunk t nil) "\
+")))
+
+ ;; Check unified change/add cases with no newline in new file
+ (let ((hunk "\
+@@ -1 +1 @@
+-foo
++bar
+\\ No newline at end of file
+"))
+ (should (equal (diff-hunk-text hunk nil nil) "\
+foo
+"))
+ (should (equal (diff-hunk-text hunk t nil) "\
+bar")))
+
+ (let ((hunk "\
+@@ -0,0 +1 @@
++bar
+\\ No newline at end of file
+"))
+ (should (equal (diff-hunk-text hunk nil nil) "\
+"))
+ (should (equal (diff-hunk-text hunk t nil) "\
+bar")))
+
+ ;; Check unified change case with no newline in both old/new file
+ (let ((hunk "\
+@@ -1 +1 @@
+-foo
+\\ No newline at end of file
++bar
+\\ No newline at end of file
+"))
+ (should (equal (diff-hunk-text hunk nil nil) "\
+foo"))
+ (should (equal (diff-hunk-text hunk t nil) "\
+bar")))
+
+ ;; Check context-after unified change case with no newline in both old/new file
+ (let ((hunk "\
+@@ -1,2 +1,2 @@
+-foo
++bar
+ baz
+\\ No newline at end of file
+"))
+ (should (equal (diff-hunk-text hunk nil nil) "\
+foo
+baz"))
+ (should (equal (diff-hunk-text hunk t nil) "\
+bar
+baz")))
+
+ (let ((hunk "\
+@@ -1,2 +1,2 @@
+-foo
+-baz
+\\ No newline at end of file
++bar
++baz
+"))
+ (should (equal (diff-hunk-text hunk nil nil) "\
+foo
+baz"))
+ (should (equal (diff-hunk-text hunk t nil) "\
+bar
+baz
+")))
+
+ (let ((hunk "\
+@@ -1,2 +1,2 @@
+-foo
+-baz
++bar
++baz
+\\ No newline at end of file
+"))
+ (should (equal (diff-hunk-text hunk nil nil) "\
+foo
+baz
+"))
+ (should (equal (diff-hunk-text hunk t nil) "\
+bar
+baz"))))
+
+(ert-deftest diff-mode-test-font-lock ()
+ "Check font-locking of diff hunks."
+ ;; See comments in diff-hunk-file-names about nonascii.
+ ;; In such cases, the diff-font-lock-syntax portion of this fails.
+ :expected-result (if (string-match-p "[[:nonascii:]]"
+ (ert-resource-directory))
+ :failed :passed)
+ (skip-unless (executable-find shell-file-name))
+ (skip-unless (executable-find diff-command))
+ (let ((default-directory (ert-resource-directory))
+ (old "hello_world.c")
+ (new "hello_emacs.c")
+ (diff-buffer (get-buffer-create "*Diff*"))
+ (diff-refine 'font-lock)
+ (diff-font-lock-syntax t)
+ diff-beg)
+ (diff-no-select old new '("-u") 'no-async diff-buffer)
+ (with-current-buffer diff-buffer
+ (font-lock-ensure)
+ (narrow-to-region (progn (diff-hunk-next)
+ (setq diff-beg (diff-beginning-of-hunk)))
+ (diff-end-of-hunk))
+
+ (should (equal-including-properties
+ (buffer-string)
+ #("@@ -1,6 +1,6 @@
+ #include <stdio.h>
+ int main()
+ {
+- printf(\"Hello, World!\\n\");
++ printf(\"Hello, Emacs!\\n\");
+ return 0;
+ }
+"
+ 0 15 (face diff-hunk-header)
+ 16 36 (face diff-context)
+ 36 48 (face diff-context)
+ 48 51 (face diff-context)
+ 51 52 (face diff-indicator-removed)
+ 52 81 (face diff-removed)
+ 81 82 (face diff-indicator-added)
+ 82 111 (face diff-added)
+ 111 124 (face diff-context)
+ 124 127 (face diff-context))))
+
+ ;; Test diff-font-lock-syntax.
+ (should (equal (mapcar (lambda (o)
+ (list (- (overlay-start o) diff-beg)
+ (- (overlay-end o) diff-beg)
+ (append (and (overlay-get o 'diff-mode)
+ `(diff-mode ,(overlay-get o 'diff-mode)))
+ (and (overlay-get o 'face)
+ `(face ,(overlay-get o 'face))))))
+ (sort (overlays-in (point-min) (point-max))
+ (lambda (a b) (< (overlay-start a) (overlay-start b)))))
+ '((0 127 (diff-mode fine))
+ (0 127 (diff-mode syntax))
+ (17 25 (diff-mode syntax face font-lock-preprocessor-face))
+ (26 35 (diff-mode syntax face font-lock-string-face))
+ (37 40 (diff-mode syntax face font-lock-type-face))
+ (41 45 (diff-mode syntax face font-lock-function-name-face))
+ (61 78 (diff-mode syntax face font-lock-string-face))
+ (69 74 (diff-mode fine face diff-refine-removed))
+ (91 108 (diff-mode syntax face font-lock-string-face))
+ (99 104 (diff-mode fine face diff-refine-added))
+ (114 120 (diff-mode syntax face font-lock-keyword-face))))))))
+
+(ert-deftest diff-mode-test-font-lock-syntax-one-line ()
+ "Check diff syntax highlighting for one line with no newline at end."
+ :expected-result (if (string-match-p "[[:nonascii:]]"
+ (ert-resource-directory))
+ :failed :passed)
+ (skip-unless (executable-find shell-file-name))
+ (skip-unless (executable-find diff-command))
+ (let ((default-directory (ert-resource-directory))
+ (old "hello_world_1.c")
+ (new "hello_emacs_1.c")
+ (diff-buffer (get-buffer-create "*Diff*"))
+ (diff-refine nil)
+ (diff-font-lock-syntax t)
+ diff-beg)
+ (diff-no-select old new '("-u") 'no-async diff-buffer)
+ (with-current-buffer diff-buffer
+ (font-lock-ensure)
+ (narrow-to-region (progn (diff-hunk-next)
+ (setq diff-beg (diff-beginning-of-hunk)))
+ (diff-end-of-hunk))
+
+ (should (equal-including-properties
+ (buffer-string)
+ #("@@ -1 +1 @@
+-int main() { printf(\"Hello, World!\\n\"); return 0; }
+\\ No newline at end of file
++int main() { printf(\"Hello, Emacs!\\n\"); return 0; }
+\\ No newline at end of file
+"
+ 0 11 (face diff-hunk-header)
+ 12 13 (face diff-indicator-removed)
+ 13 65 (face diff-removed)
+ 65 93 (face diff-context)
+ 93 94 (face diff-indicator-added)
+ 94 146 (face diff-added)
+ 146 174 (face diff-context))))
+
+ (should (equal (mapcar (lambda (o)
+ (list (- (overlay-start o) diff-beg)
+ (- (overlay-end o) diff-beg)
+ (append (and (overlay-get o 'diff-mode)
+ `(diff-mode ,(overlay-get o 'diff-mode)))
+ (and (overlay-get o 'face)
+ `(face ,(overlay-get o 'face))))))
+ (sort (overlays-in (point-min) (point-max))
+ (lambda (a b) (< (overlay-start a) (overlay-start b)))))
+ '((0 174 (diff-mode syntax))
+ (13 16 (diff-mode syntax face font-lock-type-face))
+ (17 21 (diff-mode syntax face font-lock-function-name-face))
+ (33 50 (diff-mode syntax face font-lock-string-face))
+ (53 59 (diff-mode syntax face font-lock-keyword-face))
+ (94 97 (diff-mode syntax face font-lock-type-face))
+ (98 102 (diff-mode syntax face font-lock-function-name-face))
+ (114 131 (diff-mode syntax face font-lock-string-face))
+ (134 140 (diff-mode syntax face font-lock-keyword-face))))))))
+(ert-deftest test-hunk-file-names ()
+ (with-temp-buffer
+ (insert "diff -c /tmp/ange-ftp13518wvE.el /tmp/ange-ftp1351895K.el\n")
+ (goto-char (point-min))
+ (should (equal (diff-hunk-file-names)
+ '("/tmp/ange-ftp1351895K.el" "/tmp/ange-ftp13518wvE.el"))))
+ (with-temp-buffer
+ (insert "diff -c -L /ftp:slbhao:/home/albinus/src/tramp/lisp/tramp.el -L /ftp:slbhao:/home/albinus/src/emacs/lisp/net/tramp.el /tmp/ange-ftp13518wvE.el /tmp/ange-ftp1351895K.el\n")
+ (goto-char (point-min))
+ (should (equal (diff-hunk-file-names)
+ '("/tmp/ange-ftp1351895K.el" "/tmp/ange-ftp13518wvE.el")))))
(provide 'diff-mode-tests)
+;;; diff-mode-tests.el ends here
diff --git a/test/lisp/vc/ediff-diff-tests.el b/test/lisp/vc/ediff-diff-tests.el
index 09aa106027e..b0ceb4792c3 100644
--- a/test/lisp/vc/ediff-diff-tests.el
+++ b/test/lisp/vc/ediff-diff-tests.el
@@ -1,6 +1,6 @@
;;; ediff-diff-tests.el --- Unit tests for ediff-diff.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2017 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2022 Free Software Foundation, Inc.
;; Author: Philipp Stephani <phst@google.com>
diff --git a/test/lisp/vc/ediff-ptch-tests.el b/test/lisp/vc/ediff-ptch-tests.el
index 368d00ae4cb..935046198f3 100644
--- a/test/lisp/vc/ediff-ptch-tests.el
+++ b/test/lisp/vc/ediff-ptch-tests.el
@@ -1,25 +1,28 @@
-;;; ediff-ptch-tests.el --- Tests for ediff-ptch.el
+;;; ediff-ptch-tests.el --- Tests for ediff-ptch.el -*- lexical-binding:t -*-
-;; Copyright (C) 2016-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2022 Free Software Foundation, Inc.
;; Author: Tino Calancha <tino.calancha@gmail.com>
-;; This program is free software: you can redistribute it and/or
+;; This file is part of GNU Emacs.
+;;
+;; GNU Emacs is free software: you can redistribute it and/or
;; modify it under the terms of the GNU General Public License as
;; published by the Free Software Foundation, either version 3 of the
;; License, or (at your option) any later version.
;;
-;; This program is distributed in the hope that it will be useful, but
+;; GNU Emacs is distributed in the hope that it will be useful, but
;; WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
;; General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
-;; along with this program. If not, see `https://www.gnu.org/licenses/'.
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Code:
(require 'ert)
+(require 'ert-x)
(require 'ediff-ptch)
(ert-deftest ediff-ptch-test-bug25010 ()
@@ -43,34 +46,33 @@ index 6a07f80..6e8e947 100644
"Test for https://debbugs.gnu.org/26084 ."
(skip-unless (executable-find "git"))
(skip-unless (executable-find ediff-patch-program))
- (let* ((tmpdir (make-temp-file "ediff-ptch-test" t))
- (default-directory (file-name-as-directory tmpdir))
- (patch (make-temp-file "ediff-ptch-test"))
- (qux (expand-file-name "qux.txt" tmpdir))
- (bar (expand-file-name "bar.txt" tmpdir))
- (git-program (executable-find "git")))
- ;; Create repository.
- (with-temp-buffer
- (insert "qux here\n")
- (write-region nil nil qux nil 'silent)
- (erase-buffer)
- (insert "bar here\n")
- (write-region nil nil bar nil 'silent))
- (call-process git-program nil nil nil "init")
- (call-process git-program nil nil nil "add" ".")
- (call-process git-program nil nil nil "commit" "-m" "Test repository.")
- ;; Update repo., save the diff and reset to initial state.
- (with-temp-buffer
- (insert "foo here\n")
- (write-region nil nil qux nil 'silent)
- (write-region nil nil bar nil 'silent))
- (call-process git-program nil `(:file ,patch) nil "diff")
- (call-process git-program nil nil nil "reset" "--hard" "HEAD")
- ;; Visit the diff file i.e., patch; extract from it the parts
- ;; affecting just each of the files: store in patch-bar the part
- ;; affecting 'bar', and in patch-qux the part affecting 'qux'.
- (find-file patch)
- (unwind-protect
+ (ert-with-temp-directory tmpdir
+ (ert-with-temp-file patch
+ (let* ((default-directory (file-name-as-directory tmpdir))
+ (qux (expand-file-name "qux.txt" tmpdir))
+ (bar (expand-file-name "bar.txt" tmpdir))
+ (git-program (executable-find "git")))
+ ;; Create repository.
+ (with-temp-buffer
+ (insert "qux here\n")
+ (write-region nil nil qux nil 'silent)
+ (erase-buffer)
+ (insert "bar here\n")
+ (write-region nil nil bar nil 'silent))
+ (call-process git-program nil nil nil "init")
+ (call-process git-program nil nil nil "add" ".")
+ (call-process git-program nil nil nil "commit" "-m" "Test repository.")
+ ;; Update repo., save the diff and reset to initial state.
+ (with-temp-buffer
+ (insert "foo here\n")
+ (write-region nil nil qux nil 'silent)
+ (write-region nil nil bar nil 'silent))
+ (call-process git-program nil `(:file ,patch) nil "diff")
+ (call-process git-program nil nil nil "reset" "--hard" "HEAD")
+ ;; Visit the diff file i.e., patch; extract from it the parts
+ ;; affecting just each of the files: store in patch-bar the part
+ ;; affecting 'bar', and in patch-qux the part affecting 'qux'.
+ (find-file patch)
(let* ((info
(progn (ediff-map-patch-buffer (current-buffer)) ediff-patch-map))
(patch-bar
@@ -114,9 +116,7 @@ index 6a07f80..6e8e947 100644
(buffer-string))
(with-temp-buffer
(insert-file-contents backup)
- (buffer-string)))))))
- (delete-directory tmpdir 'recursive)
- (delete-file patch)))))
+ (buffer-string))))))))))))
(provide 'ediff-ptch-tests)
diff --git a/test/lisp/vc/log-edit-tests.el b/test/lisp/vc/log-edit-tests.el
new file mode 100644
index 00000000000..e1fe8fcf1c8
--- /dev/null
+++ b/test/lisp/vc/log-edit-tests.el
@@ -0,0 +1,137 @@
+;;; log-edit-tests.el --- Unit tests for log-edit.el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2019-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Unit tests for lisp/vc/log-edit.el.
+
+;;; Code:
+
+(require 'log-edit)
+(require 'ert)
+
+(ert-deftest log-edit-fill-entry ()
+ (with-temp-buffer
+ (insert "\
+* dir/file.ext (fun1):
+\(fun2):
+\(fun3):
+* file2.txt (fun4):
+\(fun5):
+\(fun6):
+\(fun7): Some prose.
+\(fun8): A longer description of a complicated change.\
+ Spread over a couple of sentences.\
+ Long enough to be filled for several lines.
+\(fun9): Etc.")
+ (goto-char (point-min))
+ (let ((fill-column 72)) (log-edit-fill-entry))
+ (should (equal (buffer-string) "\
+* dir/file.ext (fun1, fun2, fun3):
+* file2.txt (fun4, fun5, fun6, fun7): Some prose.
+\(fun8): A longer description of a complicated change. Spread over a
+couple of sentences. Long enough to be filled for several lines.
+\(fun9): Etc."))
+ (let ((fill-column 20)) (log-edit-fill-entry))
+ (should (equal (buffer-string) "\
+* dir/file.ext (fun1)
+\(fun2, fun3):
+* file2.txt (fun4)
+\(fun5, fun6, fun7):
+Some prose.
+\(fun8): A longer
+description of a
+complicated change.
+Spread over a couple
+of sentences. Long
+enough to be filled
+for several lines.
+\(fun9): Etc."))
+ (let ((fill-column 40)) (log-edit-fill-entry))
+ (should (equal (buffer-string) "\
+* dir/file.ext (fun1, fun2, fun3):
+* file2.txt (fun4, fun5, fun6, fun7):
+Some prose.
+\(fun8): A longer description of a
+complicated change. Spread over a
+couple of sentences. Long enough to be
+filled for several lines.
+\(fun9): Etc."))))
+
+(ert-deftest log-edit-fill-entry-indented-func-entries ()
+ ;; Indenting function entries is a typical mistake caused by using a
+ ;; misconfigured or non-ChangeLog specific fill function.
+ (with-temp-buffer
+ (insert "\
+* dir/file.ext (fun1):
+ (fun2):
+ (fun3):
+* file2.txt (fun4):
+ (fun5):
+ (fun6):
+ (fun7): Some prose.
+ (fun8): A longer description of a complicated change.\
+ Spread over a couple of sentences.\
+ Long enough to be filled for several lines.
+ (fun9): Etc.")
+ (goto-char (point-min))
+ (let ((fill-column 72)) (log-edit-fill-entry))
+ (should (equal (buffer-string) "\
+* dir/file.ext (fun1, fun2, fun3):
+* file2.txt (fun4, fun5, fun6, fun7): Some prose.
+\(fun8): A longer description of a complicated change. Spread over a
+couple of sentences. Long enough to be filled for several lines.
+\(fun9): Etc."))))
+
+(ert-deftest log-edit-fill-entry-trailing-prose ()
+ (with-temp-buffer
+ (insert "\
+* dir/file.ext (fun1): A longer description of a complicated change.\
+ Spread over a couple of sentences.\
+ Long enough to be filled for several lines.")
+ (let ((fill-column 72)) (log-edit-fill-entry))
+ (should (equal (buffer-string) "\
+* dir/file.ext (fun1): A longer description of a complicated change.
+Spread over a couple of sentences. Long enough to be filled for several
+lines."))))
+
+(ert-deftest log-edit-fill-entry-joining ()
+ ;; Join short enough function names on the same line.
+ (with-temp-buffer
+ (insert "* dir/file.ext (fun1):\n(fun2):")
+ (let ((fill-column 72)) (log-edit-fill-entry))
+ (should (equal (buffer-string) "* dir/file.ext (fun1, fun2):")))
+ ;; Don't combine them if they're too long.
+ (with-temp-buffer
+ (insert "* dir/long-file-name.ext (a-really-long-function-name):
+\(another-very-long-function-name):")
+ (let ((fill-column 72)) (log-edit-fill-entry))
+ (should (equal (buffer-string) "* dir/long-file-name.ext (a-really-long-function-name)
+\(another-very-long-function-name):")))
+ ;; Put function name on next line, if the file name is too long.
+ (with-temp-buffer
+ (insert "\
+* a-very-long-directory-name/another-long-directory-name/and-a-long-file-name.ext\
+ (a-really-long-function-name):")
+ (let ((fill-column 72)) (log-edit-fill-entry))
+ (should (equal (buffer-string) "\
+* a-very-long-directory-name/another-long-directory-name/and-a-long-file-name.ext
+\(a-really-long-function-name):"))))
+
+;;; log-edit-tests.el ends here
diff --git a/test/lisp/vc/smerge-mode-tests.el b/test/lisp/vc/smerge-mode-tests.el
index 10d090632da..713df4c6e76 100644
--- a/test/lisp/vc/smerge-mode-tests.el
+++ b/test/lisp/vc/smerge-mode-tests.el
@@ -1,4 +1,6 @@
-;; Copyright (C) 2017 Free Software Foundation, Inc
+;;; smerge-mode-tests.el --- Tests for smerge-mode.el -*- lexical-binding:t -*-
+
+;; Copyright (C) 2017-2022 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
@@ -32,3 +34,5 @@
(should (equal (buffer-substring (point-min) (point-max)) ""))))
(provide 'smerge-mode-tests)
+
+;;; smerge-mode-tests.el ends here
diff --git a/test/lisp/vc/vc-bzr-tests.el b/test/lisp/vc/vc-bzr-tests.el
index 85f401eb37b..52f06df5bcd 100644
--- a/test/lisp/vc/vc-bzr-tests.el
+++ b/test/lisp/vc/vc-bzr-tests.el
@@ -1,6 +1,6 @@
-;;; vc-bzr.el --- tests for vc/vc-bzr.el
+;;; vc-bzr-tests.el --- tests for vc/vc-bzr.el -*- lexical-binding: t -*-
-;; Copyright (C) 2011-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2022 Free Software Foundation, Inc.
;; Author: Glenn Morris <rgm@gnu.org>
;; Maintainer: emacs-devel@gnu.org
@@ -25,6 +25,7 @@
;;; Code:
(require 'ert)
+(require 'ert-x)
(require 'vc-bzr)
(require 'vc-dir)
@@ -37,104 +38,111 @@
;; commands (eg `bzr status') want to access ~/.bazaar, and will
;; abort if they cannot. I could not figure out how to stop bzr
;; doing that, so just give it a temporary homedir for the duration.
- ;; http://bugs.launchpad.net/bzr/+bug/137407 ?
- (let* ((homedir (make-temp-file "vc-bzr-test" t))
- (bzrdir (expand-file-name "bzr" homedir))
- (ignored-dir (progn
- (make-directory bzrdir)
- (expand-file-name "ignored-dir" bzrdir)))
- (default-directory (file-name-as-directory bzrdir))
- (process-environment (cons (format "BZR_HOME=%s" homedir)
- process-environment)))
- (unwind-protect
- (progn
- (make-directory ignored-dir)
- (with-temp-buffer
- (insert (file-name-nondirectory ignored-dir))
- (write-region nil nil (expand-file-name ".bzrignore" bzrdir)
- nil 'silent))
- (call-process vc-bzr-program nil nil nil "init")
- (call-process vc-bzr-program nil nil nil "add")
- (call-process vc-bzr-program nil nil nil "commit" "-m" "Commit 1")
- (with-temp-buffer
- (insert "unregistered file")
- (write-region nil nil (expand-file-name "testfile2" ignored-dir)
- nil 'silent))
- (vc-dir ignored-dir)
- (while (vc-dir-busy)
- (sit-for 0.1))
- ;; FIXME better to explicitly test for error from process sentinel.
- (with-current-buffer "*vc-dir*"
- (goto-char (point-min))
- (should (search-forward "unregistered" nil t))))
- (delete-directory homedir t))))
+ ;; https://bugs.launchpad.net/bzr/+bug/137407 ?
+ ;;
+ ;; Note that with bzr 2.x, this works:
+ ;; mkdir /tmp/bzr
+ ;; HOME=/nonexistent BZR_HOME=/tmp/bzr bzr status
+ ;; but with brz 3.1, it complains:
+ ;; "failed to open trace file: [Errno 13] Permission denied: '/nonexistent'"
+ ;; which confuses vc-dir.
+ ;; We can quieten brz by adding either BRZ_LOG=/dev/null, or
+ ;; XDG_CACHE_HOME=/tmp/bzr (log defaults to XDG_CACHE_HOME/breezy/brz.log),
+ ;; but it seems simpler to just set HOME to a newly created
+ ;; temporary directory.
+ ;; TODO does this means tests should be setting XDG_ variables (not
+ ;; just HOME) to temporary values too?
+ (ert-with-temp-directory homedir
+ (let* ((bzrdir (expand-file-name "bzr" homedir))
+ (ignored-dir (progn
+ (make-directory bzrdir)
+ (expand-file-name "ignored-dir" bzrdir)))
+ (default-directory (file-name-as-directory bzrdir))
+ (process-environment (cons (format "HOME=%s" homedir)
+ process-environment)))
+ (make-directory ignored-dir)
+ (with-temp-buffer
+ (insert (file-name-nondirectory ignored-dir))
+ (write-region nil nil (expand-file-name ".bzrignore" bzrdir)
+ nil 'silent))
+ (skip-unless (eq 0 ; some internal bzr error
+ (call-process vc-bzr-program nil nil nil "init")))
+ (call-process vc-bzr-program nil nil nil "add")
+ (call-process vc-bzr-program nil nil nil "commit" "-m" "Commit 1")
+ (with-temp-buffer
+ (insert "unregistered file")
+ (write-region nil nil (expand-file-name "testfile2" ignored-dir)
+ nil 'silent))
+ (vc-dir ignored-dir)
+ (while (vc-dir-busy)
+ (sit-for 0.1))
+ ;; FIXME better to explicitly test for error from process sentinel.
+ (with-current-buffer "*vc-dir*"
+ (goto-char (point-min))
+ (should (search-forward "unregistered" nil t))))))
;; Not specific to bzr.
(ert-deftest vc-bzr-test-bug9781 ()
"Test for https://debbugs.gnu.org/9781 ."
(skip-unless (executable-find vc-bzr-program))
- (let* ((homedir (make-temp-file "vc-bzr-test" t))
- (bzrdir (expand-file-name "bzr" homedir))
- (subdir (progn
- (make-directory bzrdir)
- (expand-file-name "subdir" bzrdir)))
- (file (expand-file-name "file" bzrdir))
- (default-directory (file-name-as-directory bzrdir))
- (process-environment (cons (format "BZR_HOME=%s" homedir)
- process-environment)))
- (unwind-protect
- (progn
- (call-process vc-bzr-program nil nil nil "init")
- (make-directory subdir)
- (with-temp-buffer
- (insert "text")
- (write-region nil nil file nil 'silent)
- (write-region nil nil (expand-file-name "subfile" subdir)
- nil 'silent))
- (call-process vc-bzr-program nil nil nil "add")
- (call-process vc-bzr-program nil nil nil "commit" "-m" "Commit 1")
- (call-process vc-bzr-program nil nil nil "remove" subdir)
- (with-temp-buffer
- (insert "different text")
- (write-region nil nil file nil 'silent))
- (vc-dir bzrdir)
- (while (vc-dir-busy)
- (sit-for 0.1))
- (vc-dir-mark-all-files t)
- (cl-letf (((symbol-function 'y-or-n-p) (lambda (_) t)))
- (vc-next-action nil))
- (should (get-buffer "*vc-log*")))
- (delete-directory homedir t))))
+ (ert-with-temp-directory homedir
+ (let* ((bzrdir (expand-file-name "bzr" homedir))
+ (subdir (progn
+ (make-directory bzrdir)
+ (expand-file-name "subdir" bzrdir)))
+ (file (expand-file-name "file" bzrdir))
+ (default-directory (file-name-as-directory bzrdir))
+ (process-environment (cons (format "HOME=%s" homedir)
+ process-environment)))
+ (skip-unless (eq 0 ; some internal bzr error
+ (call-process vc-bzr-program nil nil nil "init")))
+ (make-directory subdir)
+ (with-temp-buffer
+ (insert "text")
+ (write-region nil nil file nil 'silent)
+ (write-region nil nil (expand-file-name "subfile" subdir)
+ nil 'silent))
+ (call-process vc-bzr-program nil nil nil "add")
+ (call-process vc-bzr-program nil nil nil "commit" "-m" "Commit 1")
+ (call-process vc-bzr-program nil nil nil "remove" subdir)
+ (with-temp-buffer
+ (insert "different text")
+ (write-region nil nil file nil 'silent))
+ (vc-dir bzrdir)
+ (while (vc-dir-busy)
+ (sit-for 0.1))
+ (vc-dir-mark-all-files t)
+ (cl-letf (((symbol-function 'y-or-n-p) (lambda (_) t)))
+ (vc-next-action nil))
+ (should (get-buffer "*vc-log*")))))
-;; https://lists.gnu.org/archive/html/help-gnu-emacs/2012-04/msg00145.html
+;; https://lists.gnu.org/r/help-gnu-emacs/2012-04/msg00145.html
(ert-deftest vc-bzr-test-faulty-bzr-autoloads ()
"Test we can generate autoloads in a bzr directory when bzr is faulty."
(skip-unless (executable-find vc-bzr-program))
- (let* ((homedir (make-temp-file "vc-bzr-test" t))
- (bzrdir (expand-file-name "bzr" homedir))
- (file (progn
- (make-directory bzrdir)
- (expand-file-name "foo.el" bzrdir)))
- (default-directory (file-name-as-directory bzrdir))
- (generated-autoload-file (expand-file-name "loaddefs.el" bzrdir))
- (process-environment (cons (format "BZR_HOME=%s" homedir)
- process-environment)))
- (unwind-protect
- (progn
- (call-process vc-bzr-program nil nil nil "init")
- (with-temp-buffer
- (insert ";;;###autoload
+ (ert-with-temp-directory homedir
+ (let* ((bzrdir (expand-file-name "bzr" homedir))
+ (file (progn
+ (make-directory bzrdir)
+ (expand-file-name "foo.el" bzrdir)))
+ (default-directory (file-name-as-directory bzrdir))
+ (process-environment (cons (format "HOME=%s" homedir)
+ process-environment)))
+ (call-process vc-bzr-program nil nil nil "init")
+ (with-temp-buffer
+ (insert ";;;###autoload
\(defun foo () \"foo\" (interactive) (message \"foo!\"))")
- (write-region nil nil file nil 'silent))
- (call-process vc-bzr-program nil nil nil "add")
- (call-process vc-bzr-program nil nil nil "commit" "-m" "Commit 1")
- ;; Deleting dirstate ensures both that vc-bzr's status heuristic
- ;; fails, so it has to call the external bzr status, and
- ;; causes bzr status to fail. This simulates a broken bzr
- ;; installation.
- (delete-file ".bzr/checkout/dirstate")
- (should (progn (update-directory-autoloads default-directory)
- t)))
- (delete-directory homedir t))))
+ (write-region nil nil file nil 'silent))
+ (call-process vc-bzr-program nil nil nil "add")
+ (call-process vc-bzr-program nil nil nil "commit" "-m" "Commit 1")
+ ;; Deleting dirstate ensures both that vc-bzr's status heuristic
+ ;; fails, so it has to call the external bzr status, and
+ ;; causes bzr status to fail. This simulates a broken bzr
+ ;; installation.
+ (delete-file ".bzr/checkout/dirstate")
+ (should (progn (loaddefs-generate
+ default-directory
+ (expand-file-name "loaddefs.el" bzrdir))
+ t)))))
-;;; vc-bzr.el ends here
+;;; vc-bzr-tests.el ends here
diff --git a/test/lisp/vc/vc-git-tests.el b/test/lisp/vc/vc-git-tests.el
new file mode 100644
index 00000000000..dc9641ed46b
--- /dev/null
+++ b/test/lisp/vc/vc-git-tests.el
@@ -0,0 +1,67 @@
+;;; vc-git-tests.el --- tests for vc/vc-git.el -*- lexical-binding:t -*-
+
+;; Copyright (C) 2016-2022 Free Software Foundation, Inc.
+
+;; Author: Justin Schell <justinmschell@gmail.com>
+;; Maintainer: emacs-devel@gnu.org
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'vc-git)
+
+(ert-deftest vc-git-test-program-version-general ()
+ (vc-git-test--run-program-version-test
+ "git version 2.30.1.0"
+ "2.30.1.0"))
+
+(ert-deftest vc-git-test-program-version-windows ()
+ (vc-git-test--run-program-version-test
+ "git version 2.30.1.1.windows.1"
+ "2.30.1.1"))
+
+(ert-deftest vc-git-test-program-version-apple ()
+ (vc-git-test--run-program-version-test
+ "git version 2.30.1.2 (Apple Git-130)"
+ "2.30.1.2"))
+
+(ert-deftest vc-git-test-program-version-other ()
+ (vc-git-test--run-program-version-test
+ "git version 2.30.1.3.foo.bar"
+ "2.30.1.3"))
+
+(ert-deftest vc-git-test-program-version-invalid-leading-string ()
+ (vc-git-test--run-program-version-test
+ "git version foo.bar.2.30.1.4"
+ "0"))
+
+(ert-deftest vc-git-test-program-version-invalid-leading-dot ()
+ (vc-git-test--run-program-version-test
+ "git version .2.30.1.5"
+ "0"))
+
+(defun vc-git-test--run-program-version-test
+ (mock-version-string expected-output)
+ (cl-letf* (((symbol-function 'vc-git--run-command-string)
+ (lambda (_file _args) mock-version-string))
+ (vc-git--program-version nil)
+ (actual-output (vc-git--program-version)))
+ (should (equal actual-output expected-output))))
+
+;;; vc-git-tests.el ends here
diff --git a/test/lisp/vc/vc-hg-tests.el b/test/lisp/vc/vc-hg-tests.el
index 96fc41e9971..2cceceb2c80 100644
--- a/test/lisp/vc/vc-hg-tests.el
+++ b/test/lisp/vc/vc-hg-tests.el
@@ -1,6 +1,6 @@
-;;; vc-hg-tests.el --- tests for vc/vc-hg.el
+;;; vc-hg-tests.el --- tests for vc/vc-hg.el -*- lexical-binding:t -*-
-;; Copyright (C) 2016-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2022 Free Software Foundation, Inc.
;; Author: Dmitry Gutov <dgutov@yandex.ru>
;; Maintainer: emacs-devel@gnu.org
diff --git a/test/lisp/vc/vc-tests.el b/test/lisp/vc/vc-tests.el
index b970be8909c..dc4d3af6999 100644
--- a/test/lisp/vc/vc-tests.el
+++ b/test/lisp/vc/vc-tests.el
@@ -1,21 +1,23 @@
-;;; vc-tests.el --- Tests of different backends of vc.el
+;;; vc-tests.el --- Tests of different backends of vc.el -*- lexical-binding:t -*-
-;; Copyright (C) 2014-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2022 Free Software Foundation, Inc.
;; Author: Michael Albinus <michael.albinus@gmx.de>
-;; This program is free software: you can redistribute it and/or
+;; This file is part of GNU Emacs.
+;;
+;; GNU Emacs is free software: you can redistribute it and/or
;; modify it under the terms of the GNU General Public License as
;; published by the Free Software Foundation, either version 3 of the
;; License, or (at your option) any later version.
;;
-;; This program is distributed in the hope that it will be useful, but
+;; GNU Emacs is distributed in the hope that it will be useful, but
;; WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
;; General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
-;; along with this program. If not, see `https://www.gnu.org/licenses/'.
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
@@ -50,7 +52,7 @@
;; - responsible-p (file)
;; - receive-file (file rev)
;; - unregister (file) DONE
-;; * checkin (files comment)
+;; * checkin (files comment) DONE
;; * find-revision (file rev buffer)
;; * checkout (file &optional rev)
;; * revert (file &optional contents-done)
@@ -73,7 +75,7 @@
;; - show-log-entry (revision)
;; - comment-history (file)
;; - update-changelog (files)
-;; * diff (files &optional async rev1 rev2 buffer)
+;; * diff (files &optional async rev1 rev2 buffer) DONE
;; - revision-completion-table (files)
;; - annotate-command (file buf &optional rev)
;; - annotate-time ()
@@ -98,7 +100,7 @@
;; - log-edit-mode ()
;; - check-headers ()
;; - delete-file (file)
-;; - rename-file (old new)
+;; - rename-file (old new) DONE
;; - find-file-hook ()
;; - extra-menu ()
;; - extra-dir-menu ()
@@ -107,9 +109,11 @@
;;; Code:
(require 'ert)
+(require 'ert-x)
(require 'vc)
+(require 'log-edit)
-(declare-function w32-application-type "w32proc")
+(declare-function w32-application-type "w32proc.c")
;; The working horses.
@@ -149,7 +153,7 @@ For backends which dont support it, it is emulated."
(delete-directory "module" 'recursive)
;; We must cleanup the "remote" CVS repo as well.
(add-hook 'vc-test--cleanup-hook
- `(lambda () (delete-directory ,tmp-dir 'recursive)))))
+ (lambda () (delete-directory tmp-dir 'recursive)))))
((eq backend 'Arch)
(let ((archive-name (format "%s--%s" user-mail-address (random))))
@@ -175,41 +179,39 @@ For backends which dont support it, it is emulated."
(defun vc-test--create-repo (backend)
"Create a test repository in `default-directory', a temporary directory."
-
- (let ((vc-handled-backends `(,backend))
- (default-directory
- (file-name-as-directory
- (expand-file-name
- (make-temp-name "vc-test") temporary-file-directory)))
- (process-environment process-environment)
- tempdir
- vc-test--cleanup-hook)
- (when (eq backend 'Bzr)
- (setq tempdir (make-temp-file "vc-test--create-repo" t)
- process-environment (cons (format "BZR_HOME=%s" tempdir)
- process-environment)))
-
- (unwind-protect
- (progn
- ;; Cleanup.
- (add-hook
- 'vc-test--cleanup-hook
- `(lambda () (delete-directory ,default-directory 'recursive)))
-
- ;; Check the revision granularity.
- (should (memq (vc-test--revision-granularity-function backend)
- '(file repository)))
-
- ;; Create empty repository.
- (make-directory default-directory)
- (should (file-directory-p default-directory))
- (vc-test--create-repo-function backend)
- (should (eq (vc-responsible-backend default-directory) backend)))
-
- ;; Save exit.
- (ignore-errors
- (if tempdir (delete-directory tempdir t))
- (run-hooks 'vc-test--cleanup-hook)))))
+ (ert-with-temp-directory tempdir
+ (let ((vc-handled-backends `(,backend))
+ (default-directory
+ (file-name-as-directory
+ (expand-file-name
+ (make-temp-name "vc-test") temporary-file-directory)))
+ (process-environment process-environment)
+ vc-test--cleanup-hook)
+ (when (eq backend 'Bzr)
+ (setq process-environment (cons (format "BZR_HOME=%s" tempdir)
+ process-environment)))
+
+ (unwind-protect
+ (progn
+ ;; Cleanup.
+ (add-hook
+ 'vc-test--cleanup-hook
+ (let ((dir default-directory))
+ (lambda () (delete-directory dir 'recursive))))
+
+ ;; Check the revision granularity.
+ (should (memq (vc-test--revision-granularity-function backend)
+ '(file repository)))
+
+ ;; Create empty repository.
+ (make-directory default-directory)
+ (should (file-directory-p default-directory))
+ (vc-test--create-repo-function backend)
+ (should (eq (vc-responsible-backend default-directory) backend)))
+
+ ;; Save exit.
+ (ignore-errors
+ (run-hooks 'vc-test--cleanup-hook))))))
;; FIXME: Why isn't there `vc-unregister'?
(defun vc-test--unregister-function (backend file)
@@ -224,326 +226,443 @@ For backends which don't support it, `vc-not-supported' is signaled."
(defmacro vc-test--run-maybe-unsupported-function (func &rest args)
"Run FUNC with ARGS as arguments.
Catch the `vc-not-supported' error."
- `(let (err)
- (condition-case err
- (funcall ,func ,@args)
- (vc-not-supported 'vc-not-supported)
- (t (signal (car err) (cdr err))))))
+ `(condition-case err
+ (funcall ,func ,@args)
+ (vc-not-supported 'vc-not-supported)
+ (t (signal (car err) (cdr err)))))
(defun vc-test--register (backend)
"Register and unregister a file.
This checks also `vc-backend' and `vc-responsible-backend'."
-
- (let ((vc-handled-backends `(,backend))
- (default-directory
- (file-name-as-directory
- (expand-file-name
- (make-temp-name "vc-test") temporary-file-directory)))
- (process-environment process-environment)
- tempdir
- vc-test--cleanup-hook)
- (when (eq backend 'Bzr)
- (setq tempdir (make-temp-file "vc-test--register" t)
- process-environment (cons (format "BZR_HOME=%s" tempdir)
- process-environment)))
- (unwind-protect
- (progn
- ;; Cleanup.
- (add-hook
- 'vc-test--cleanup-hook
- `(lambda () (delete-directory ,default-directory 'recursive)))
-
- ;; Create empty repository.
- (make-directory default-directory)
- (vc-test--create-repo-function backend)
- ;; For file oriented backends CVS, RCS and SVN the backend is
- ;; returned, and the directory is registered already.
- (should (if (vc-backend default-directory)
- (vc-registered default-directory)
- (not (vc-registered default-directory))))
- (should (eq (vc-responsible-backend default-directory) backend))
-
- (let ((tmp-name1 (expand-file-name "foo" default-directory))
- (tmp-name2 "bla"))
- ;; Register files. Check for it.
- (write-region "foo" nil tmp-name1 nil 'nomessage)
- (should (file-exists-p tmp-name1))
- (should-not (vc-backend tmp-name1))
- (should (eq (vc-responsible-backend tmp-name1) backend))
- (should-not (vc-registered tmp-name1))
-
- (write-region "bla" nil tmp-name2 nil 'nomessage)
- (should (file-exists-p tmp-name2))
- (should-not (vc-backend tmp-name2))
- (should (eq (vc-responsible-backend tmp-name2) backend))
- (should-not (vc-registered tmp-name2))
-
- (vc-register (list backend (list tmp-name1 tmp-name2)))
- (should (file-exists-p tmp-name1))
- (should (eq (vc-backend tmp-name1) backend))
- (should (eq (vc-responsible-backend tmp-name1) backend))
- (should (vc-registered tmp-name1))
-
- (should (file-exists-p tmp-name2))
- (should (eq (vc-backend tmp-name2) backend))
- (should (eq (vc-responsible-backend tmp-name2) backend))
- (should (vc-registered tmp-name2))
-
- ;; `vc-backend' accepts also a list of files,
- ;; `vc-responsible-backend' doesn't.
- (should (vc-backend (list tmp-name1 tmp-name2)))
-
- ;; Unregister the files.
- (unless (eq (vc-test--run-maybe-unsupported-function
- 'vc-test--unregister-function backend tmp-name1)
- 'vc-not-supported)
+ (ert-with-temp-directory tempdir
+ (let ((vc-handled-backends `(,backend))
+ (default-directory
+ (file-name-as-directory
+ (expand-file-name
+ (make-temp-name "vc-test") temporary-file-directory)))
+ (process-environment process-environment)
+ vc-test--cleanup-hook)
+ (when (eq backend 'Bzr)
+ (setq process-environment (cons (format "BZR_HOME=%s" tempdir)
+ process-environment)))
+ (unwind-protect
+ (progn
+ ;; Cleanup.
+ (add-hook
+ 'vc-test--cleanup-hook
+ (let ((dir default-directory))
+ (lambda () (delete-directory dir 'recursive))))
+
+ ;; Create empty repository.
+ (make-directory default-directory)
+ (vc-test--create-repo-function backend)
+ ;; For file oriented backends CVS, RCS and SVN the backend is
+ ;; returned, and the directory is registered already.
+ (should (if (vc-backend default-directory)
+ (vc-registered default-directory)
+ (not (vc-registered default-directory))))
+ (should (eq (vc-responsible-backend default-directory) backend))
+
+ (let ((tmp-name1 (expand-file-name "foo" default-directory))
+ (tmp-name2 "bla"))
+ ;; Register files. Check for it.
+ (write-region "foo" nil tmp-name1 nil 'nomessage)
+ (should (file-exists-p tmp-name1))
(should-not (vc-backend tmp-name1))
- (should-not (vc-registered tmp-name1)))
- (unless (eq (vc-test--run-maybe-unsupported-function
- 'vc-test--unregister-function backend tmp-name2)
- 'vc-not-supported)
- (should-not (vc-backend tmp-name2))
- (should-not (vc-registered tmp-name2)))
-
- ;; The files should still exist.
- (should (file-exists-p tmp-name1))
- (should (file-exists-p tmp-name2))))
+ (should (eq (vc-responsible-backend tmp-name1) backend))
+ (should-not (vc-registered tmp-name1))
- ;; Save exit.
- (ignore-errors
- (if tempdir (delete-directory tempdir t))
- (run-hooks 'vc-test--cleanup-hook)))))
+ (write-region "bla" nil tmp-name2 nil 'nomessage)
+ (should (file-exists-p tmp-name2))
+ (should-not (vc-backend tmp-name2))
+ (should (eq (vc-responsible-backend tmp-name2) backend))
+ (should-not (vc-registered tmp-name2))
+
+ (vc-register (list backend (list tmp-name1 tmp-name2)))
+ (should (file-exists-p tmp-name1))
+ (should (eq (vc-backend tmp-name1) backend))
+ (should (eq (vc-responsible-backend tmp-name1) backend))
+ (should (vc-registered tmp-name1))
+
+ (should (file-exists-p tmp-name2))
+ (should (eq (vc-backend tmp-name2) backend))
+ (should (eq (vc-responsible-backend tmp-name2) backend))
+ (should (vc-registered tmp-name2))
+
+ ;; `vc-backend' accepts also a list of files,
+ ;; `vc-responsible-backend' doesn't.
+ (should (vc-backend (list tmp-name1 tmp-name2)))
+
+ ;; Unregister the files.
+ (unless (eq (vc-test--run-maybe-unsupported-function
+ 'vc-test--unregister-function backend tmp-name1)
+ 'vc-not-supported)
+ (should-not (vc-backend tmp-name1))
+ (should-not (vc-registered tmp-name1)))
+ (unless (eq (vc-test--run-maybe-unsupported-function
+ 'vc-test--unregister-function backend tmp-name2)
+ 'vc-not-supported)
+ (should-not (vc-backend tmp-name2))
+ (should-not (vc-registered tmp-name2)))
+
+ ;; The files should still exist.
+ (should (file-exists-p tmp-name1))
+ (should (file-exists-p tmp-name2))))
+
+ ;; Save exit.
+ (ignore-errors
+ (run-hooks 'vc-test--cleanup-hook))))))
(defun vc-test--state (backend)
"Check the different states of a file."
-
- (let ((vc-handled-backends `(,backend))
- (default-directory
- (file-name-as-directory
- (expand-file-name
- (make-temp-name "vc-test") temporary-file-directory)))
- (process-environment process-environment)
- tempdir
- vc-test--cleanup-hook)
- (when (eq backend 'Bzr)
- (setq tempdir (make-temp-file "vc-test--state" t)
- process-environment (cons (format "BZR_HOME=%s" tempdir)
- process-environment)))
- (unwind-protect
- (progn
- ;; Cleanup.
- (add-hook
- 'vc-test--cleanup-hook
- `(lambda () (delete-directory ,default-directory 'recursive)))
-
- ;; Create empty repository.
- (make-directory default-directory)
- (vc-test--create-repo-function backend)
-
- (let ((tmp-name (expand-file-name "foo" default-directory)))
- ;; Check state of a nonexistent file.
-
- (message "vc-state2 %s" (vc-state tmp-name))
- (should (null (vc-state tmp-name)))
-
- ;; Write a new file. Check state.
- (write-region "foo" nil tmp-name nil 'nomessage)
-
- ;; nil: Mtn
- ;; unregistered: Bzr CVS Git Hg SVN RCS
- (message "vc-state3 %s %s" backend (vc-state tmp-name backend))
- (should (memq (vc-state tmp-name backend) '(nil unregistered)))
-
- ;; Register a file. Check state.
- (vc-register
- (list backend (list (file-name-nondirectory tmp-name))))
-
- ;; FIXME: nil is definitely wrong.
- ;; nil: SRC
- ;; added: Bzr CVS Git Hg Mtn SVN
- ;; up-to-date: RCS SCCS
- (message "vc-state4 %s" (vc-state tmp-name))
- (should (memq (vc-state tmp-name) '(nil added up-to-date)))
-
- ;; Unregister the file. Check state.
- (if (eq (vc-test--run-maybe-unsupported-function
- 'vc-test--unregister-function backend tmp-name)
- 'vc-not-supported)
- (message "vc-state5 unsupported")
- ;; unregistered: Bzr Git RCS Hg
- ;; unsupported: CVS Mtn SCCS SRC SVN
- (message "vc-state5 %s %s" backend (vc-state tmp-name backend))
- (should (memq (vc-state tmp-name backend)
- '(nil unregistered))))))
-
- ;; Save exit.
- (ignore-errors
- (if tempdir (delete-directory tempdir t))
- (run-hooks 'vc-test--cleanup-hook)))))
+ (ert-with-temp-directory tempdir
+ (let ((vc-handled-backends `(,backend))
+ (default-directory
+ (file-name-as-directory
+ (expand-file-name
+ (make-temp-name "vc-test") temporary-file-directory)))
+ (process-environment process-environment)
+ vc-test--cleanup-hook)
+ (when (eq backend 'Bzr)
+ (setq process-environment (cons (format "BZR_HOME=%s" tempdir)
+ process-environment)))
+ (unwind-protect
+ (progn
+ ;; Cleanup.
+ (add-hook
+ 'vc-test--cleanup-hook
+ (let ((dir default-directory))
+ (lambda () (delete-directory dir 'recursive))))
+
+ ;; Create empty repository.
+ (make-directory default-directory)
+ (vc-test--create-repo-function backend)
+
+ (let ((tmp-name (expand-file-name "foo" default-directory)))
+ ;; Check state of a nonexistent file.
+
+ (message "vc-state2 %s" (vc-state tmp-name))
+ (should (null (vc-state tmp-name)))
+
+ ;; Write a new file. Check state.
+ (write-region "foo" nil tmp-name nil 'nomessage)
+
+ ;; nil: Mtn
+ ;; unregistered: Bzr CVS Git Hg SVN RCS
+ (message "vc-state3 %s %s" backend (vc-state tmp-name backend))
+ (should (memq (vc-state tmp-name backend) '(nil unregistered)))
+
+ ;; Register a file. Check state.
+ (vc-register
+ (list backend (list (file-name-nondirectory tmp-name))))
+
+ ;; FIXME: nil is definitely wrong.
+ ;; nil: SRC
+ ;; added: Bzr CVS Git Hg Mtn SVN
+ ;; up-to-date: RCS SCCS
+ (message "vc-state4 %s" (vc-state tmp-name))
+ (should (memq (vc-state tmp-name) '(nil added up-to-date)))
+
+ ;; Unregister the file. Check state.
+ (if (eq (vc-test--run-maybe-unsupported-function
+ 'vc-test--unregister-function backend tmp-name)
+ 'vc-not-supported)
+ (message "vc-state5 unsupported")
+ ;; unregistered: Bzr Git RCS Hg
+ ;; unsupported: CVS Mtn SCCS SRC SVN
+ (message "vc-state5 %s %s" backend (vc-state tmp-name backend))
+ (should (memq (vc-state tmp-name backend)
+ '(nil unregistered))))))
+
+ ;; Save exit.
+ (ignore-errors
+ (run-hooks 'vc-test--cleanup-hook))))))
(defun vc-test--working-revision (backend)
"Check the working revision of a repository."
-
- (let ((vc-handled-backends `(,backend))
- (default-directory
- (file-name-as-directory
- (expand-file-name
- (make-temp-name "vc-test") temporary-file-directory)))
- (process-environment process-environment)
- tempdir
- vc-test--cleanup-hook)
- (when (eq backend 'Bzr)
- (setq tempdir (make-temp-file "vc-test--working-revision" t)
- process-environment (cons (format "BZR_HOME=%s" tempdir)
- process-environment)))
-
- (unwind-protect
- (progn
- ;; Cleanup.
- (add-hook
- 'vc-test--cleanup-hook
- `(lambda () (delete-directory ,default-directory 'recursive)))
-
- ;; Create empty repository. Check working revision of
- ;; repository, should be nil.
- (make-directory default-directory)
- (vc-test--create-repo-function backend)
-
- ;; FIXME: Is the value for SVN correct?
- ;; nil: Bzr CVS Git Hg Mtn RCS SCCS SRC
- ;; "0": SVN
- (message
- "vc-working-revision1 %s" (vc-working-revision default-directory))
- (should (member (vc-working-revision default-directory) '(nil "0")))
-
- (let ((tmp-name (expand-file-name "foo" default-directory)))
- ;; Check initial working revision, should be nil until
- ;; it's registered.
-
- (message "vc-working-revision2 %s" (vc-working-revision tmp-name))
- (should-not (vc-working-revision tmp-name))
-
- ;; Write a new file. Check working revision.
- (write-region "foo" nil tmp-name nil 'nomessage)
-
- (message "vc-working-revision3 %s" (vc-working-revision tmp-name))
- (should-not (vc-working-revision tmp-name))
-
- ;; Register a file. Check working revision.
- (vc-register
- (list backend (list (file-name-nondirectory tmp-name))))
-
- ;; XXX: nil is fine, at least in Git's case, because
- ;; `vc-register' only makes the file `added' in this case.
- ;; nil: Git Mtn
- ;; "0": Bzr CVS Hg SRC SVN
- ;; "1.1": RCS SCCS
- (message "vc-working-revision4 %s" (vc-working-revision tmp-name))
- (should (member (vc-working-revision tmp-name) '(nil "0" "1.1")))
-
- ;; TODO: Call `vc-checkin', and check the resulting
- ;; working revision. None of the return values should be
- ;; nil then.
-
- ;; Unregister the file. Check working revision.
- (if (eq (vc-test--run-maybe-unsupported-function
- 'vc-test--unregister-function backend tmp-name)
- 'vc-not-supported)
- (message "vc-working-revision5 unsupported")
- ;; nil: Bzr Git Hg RCS
- ;; unsupported: CVS Mtn SCCS SRC SVN
- (message "vc-working-revision5 %s" (vc-working-revision tmp-name))
- (should-not (vc-working-revision tmp-name)))))
-
- ;; Save exit.
- (ignore-errors
- (if tempdir (delete-directory tempdir t))
- (run-hooks 'vc-test--cleanup-hook)))))
+ (ert-with-temp-directory tempdir
+ (let ((vc-handled-backends `(,backend))
+ (default-directory
+ (file-name-as-directory
+ (expand-file-name
+ (make-temp-name "vc-test") temporary-file-directory)))
+ (process-environment process-environment)
+ vc-test--cleanup-hook)
+ (when (eq backend 'Bzr)
+ (setq process-environment (cons (format "BZR_HOME=%s" tempdir)
+ process-environment)))
+
+ (unwind-protect
+ (progn
+ ;; Cleanup.
+ (add-hook
+ 'vc-test--cleanup-hook
+ (let ((dir default-directory))
+ (lambda () (delete-directory dir 'recursive))))
+
+ ;; Create empty repository. Check working revision of
+ ;; repository, should be nil.
+ (make-directory default-directory)
+ (vc-test--create-repo-function backend)
+
+ ;; FIXME: Is the value for SVN correct?
+ ;; nil: Bzr CVS Git Hg Mtn RCS SCCS SRC
+ ;; "0": SVN
+ (message
+ "vc-working-revision1 %s" (vc-working-revision default-directory))
+ (should (member (vc-working-revision default-directory) '(nil "0")))
+
+ (let ((tmp-name (expand-file-name "foo" default-directory)))
+ ;; Check initial working revision, should be nil until
+ ;; it's registered.
+
+ (message "vc-working-revision2 %s" (vc-working-revision tmp-name))
+ (should-not (vc-working-revision tmp-name))
+
+ ;; Write a new file. Check working revision.
+ (write-region "foo" nil tmp-name nil 'nomessage)
+
+ (message "vc-working-revision3 %s" (vc-working-revision tmp-name))
+ (should-not (vc-working-revision tmp-name))
+
+ ;; Register a file. Check working revision.
+ (vc-register
+ (list backend (list (file-name-nondirectory tmp-name))))
+
+ ;; XXX: nil is fine, at least in Git's case, because
+ ;; `vc-register' only makes the file `added' in this case.
+ ;; nil: Git Mtn
+ ;; "0": Bzr CVS Hg SRC SVN
+ ;; "1.1": RCS SCCS
+ ;; "-1": Hg versions before 5 (probably)
+ (message "vc-working-revision4 %s" (vc-working-revision tmp-name))
+ (should (member (vc-working-revision tmp-name) '(nil "0" "1.1" "-1")))
+
+ ;; TODO: Call `vc-checkin', and check the resulting
+ ;; working revision. None of the return values should be
+ ;; nil then.
+
+ ;; Unregister the file. Check working revision.
+ (if (eq (vc-test--run-maybe-unsupported-function
+ 'vc-test--unregister-function backend tmp-name)
+ 'vc-not-supported)
+ (message "vc-working-revision5 unsupported")
+ ;; nil: Bzr Git Hg RCS
+ ;; unsupported: CVS Mtn SCCS SRC SVN
+ (message "vc-working-revision5 %s" (vc-working-revision tmp-name))
+ (should-not (vc-working-revision tmp-name)))))
+
+ ;; Save exit.
+ (ignore-errors
+ (run-hooks 'vc-test--cleanup-hook))))))
(defun vc-test--checkout-model (backend)
"Check the checkout model of a repository."
-
- (let ((vc-handled-backends `(,backend))
- (default-directory
- (file-name-as-directory
- (expand-file-name
- (make-temp-name "vc-test") temporary-file-directory)))
- (process-environment process-environment)
- tempdir
- vc-test--cleanup-hook)
- (when (eq backend 'Bzr)
- (setq tempdir (make-temp-file "vc-test--checkout-model" t)
- process-environment (cons (format "BZR_HOME=%s" tempdir)
- process-environment)))
-
- (unwind-protect
- (progn
- ;; Cleanup.
- (add-hook
- 'vc-test--cleanup-hook
- `(lambda () (delete-directory ,default-directory 'recursive)))
-
- ;; Create empty repository. Check repository checkout model.
- (make-directory default-directory)
- (vc-test--create-repo-function backend)
-
- ;; Surprisingly, none of the backends returns 'announce.
- ;; implicit: Bzr CVS Git Hg Mtn SRC SVN
- ;; locking: RCS SCCS
- (message
- "vc-checkout-model1 %s"
- (vc-checkout-model backend default-directory))
- (should (memq (vc-checkout-model backend default-directory)
- '(announce implicit locking)))
-
- (let ((tmp-name (expand-file-name "foo" default-directory)))
- ;; Check checkout model of a nonexistent file.
-
- ;; implicit: Bzr CVS Git Hg Mtn SRC SVN
- ;; locking: RCS SCCS
+ (ert-with-temp-directory tempdir
+ (let ((vc-handled-backends `(,backend))
+ (default-directory
+ (file-name-as-directory
+ (expand-file-name
+ (make-temp-name "vc-test") temporary-file-directory)))
+ (process-environment process-environment)
+ vc-test--cleanup-hook)
+ (when (eq backend 'Bzr)
+ (setq process-environment (cons (format "BZR_HOME=%s" tempdir)
+ process-environment)))
+
+ (unwind-protect
+ (progn
+ ;; Cleanup.
+ (add-hook
+ 'vc-test--cleanup-hook
+ (let ((dir default-directory))
+ (lambda () (delete-directory dir 'recursive))))
+
+ ;; Create empty repository. Check repository checkout model.
+ (make-directory default-directory)
+ (vc-test--create-repo-function backend)
+
+ ;; Surprisingly, none of the backends returns 'announce.
+ ;; implicit: Bzr CVS Git Hg Mtn SRC SVN
+ ;; locking: RCS SCCS
(message
- "vc-checkout-model2 %s" (vc-checkout-model backend tmp-name))
- (should (memq (vc-checkout-model backend tmp-name)
- '(announce implicit locking)))
+ "vc-checkout-model1 %s"
+ (vc-checkout-model backend default-directory))
+ (should (memq (vc-checkout-model backend default-directory)
+ '(announce implicit locking)))
- ;; Write a new file. Check checkout model.
- (write-region "foo" nil tmp-name nil 'nomessage)
+ (let ((tmp-name (expand-file-name "foo" default-directory)))
+ ;; Check checkout model of a nonexistent file.
- ;; implicit: Bzr CVS Git Hg Mtn SRC SVN
- ;; locking: RCS SCCS
- (message
- "vc-checkout-model3 %s" (vc-checkout-model backend tmp-name))
- (should (memq (vc-checkout-model backend tmp-name)
- '(announce implicit locking)))
+ ;; implicit: Bzr CVS Git Hg Mtn SRC SVN
+ ;; locking: RCS SCCS
+ (message
+ "vc-checkout-model2 %s" (vc-checkout-model backend tmp-name))
+ (should (memq (vc-checkout-model backend tmp-name)
+ '(announce implicit locking)))
- ;; Register a file. Check checkout model.
- (vc-register
- (list backend (list (file-name-nondirectory tmp-name))))
+ ;; Write a new file. Check checkout model.
+ (write-region "foo" nil tmp-name nil 'nomessage)
- ;; implicit: Bzr CVS Git Hg Mtn SRC SVN
- ;; locking: RCS SCCS
- (message
- "vc-checkout-model4 %s" (vc-checkout-model backend tmp-name))
- (should (memq (vc-checkout-model backend tmp-name)
- '(announce implicit locking)))
-
- ;; Unregister the file. Check checkout model.
- (if (eq (vc-test--run-maybe-unsupported-function
- 'vc-test--unregister-function backend tmp-name)
- 'vc-not-supported)
- (message "vc-checkout-model5 unsupported")
- ;; implicit: Bzr Git Hg
- ;; locking: RCS
- ;; unsupported: CVS Mtn SCCS SRC SVN
+ ;; implicit: Bzr CVS Git Hg Mtn SRC SVN
+ ;; locking: RCS SCCS
(message
- "vc-checkout-model5 %s" (vc-checkout-model backend tmp-name))
+ "vc-checkout-model3 %s" (vc-checkout-model backend tmp-name))
(should (memq (vc-checkout-model backend tmp-name)
- '(announce implicit locking))))))
+ '(announce implicit locking)))
- ;; Save exit.
- (ignore-errors
- (if tempdir (delete-directory tempdir t))
- (run-hooks 'vc-test--cleanup-hook)))))
+ ;; Register a file. Check checkout model.
+ (vc-register
+ (list backend (list (file-name-nondirectory tmp-name))))
+
+ ;; implicit: Bzr CVS Git Hg Mtn SRC SVN
+ ;; locking: RCS SCCS
+ (message
+ "vc-checkout-model4 %s" (vc-checkout-model backend tmp-name))
+ (should (memq (vc-checkout-model backend tmp-name)
+ '(announce implicit locking)))
+
+ ;; Unregister the file. Check checkout model.
+ (if (eq (vc-test--run-maybe-unsupported-function
+ 'vc-test--unregister-function backend tmp-name)
+ 'vc-not-supported)
+ (message "vc-checkout-model5 unsupported")
+ ;; implicit: Bzr Git Hg
+ ;; locking: RCS
+ ;; unsupported: CVS Mtn SCCS SRC SVN
+ (message
+ "vc-checkout-model5 %s" (vc-checkout-model backend tmp-name))
+ (should (memq (vc-checkout-model backend tmp-name)
+ '(announce implicit locking))))))
+
+ ;; Save exit.
+ (ignore-errors
+ (run-hooks 'vc-test--cleanup-hook))))))
+
+(defun vc-test--rename-file (backend)
+ "Check the rename-file action."
+ (ert-with-temp-directory tempdir
+ (let ((vc-handled-backends `(,backend))
+ (default-directory
+ (file-name-as-directory
+ (expand-file-name
+ (make-temp-name "vc-test") temporary-file-directory)))
+ (process-environment process-environment)
+ vc-test--cleanup-hook)
+ (when (eq backend 'Bzr)
+ (setq process-environment (cons (format "BZR_HOME=%s" tempdir)
+ process-environment)))
+
+ (unwind-protect
+ (progn
+ ;; Cleanup.
+ (add-hook
+ 'vc-test--cleanup-hook
+ (let ((dir default-directory))
+ (lambda () (delete-directory dir 'recursive))))
+
+ ;; Create empty repository.
+ (make-directory default-directory)
+ (vc-test--create-repo-function backend)
+
+ (let ((tmp-name (expand-file-name "foo" default-directory))
+ (new-name (expand-file-name "bar" default-directory)))
+ ;; Write a new file.
+ (write-region "foo" nil tmp-name nil 'nomessage)
+
+ ;; Register it. Renaming can fail otherwise.
+ (vc-register
+ (list backend (list (file-name-nondirectory tmp-name))))
+
+ (vc-rename-file tmp-name new-name)
+
+ (should (not (file-exists-p tmp-name)))
+ (should (file-exists-p new-name))
+
+ (should (equal (vc-state new-name)
+ (if (memq backend '(RCS SCCS))
+ 'up-to-date
+ 'added)))))
+
+ ;; Save exit.
+ (ignore-errors
+ (run-hooks 'vc-test--cleanup-hook))))))
+
+(declare-function log-edit-done "vc/log-edit")
+
+(defun vc-test--version-diff (backend)
+ "Check the diff version of a repository."
+ (ert-with-temp-directory tempdir
+ (let ((vc-handled-backends `(,backend))
+ (default-directory
+ (file-name-as-directory
+ (expand-file-name
+ (make-temp-name "vc-test") temporary-file-directory)))
+ (process-environment process-environment)
+ vc-test--cleanup-hook)
+ (when (eq backend 'Bzr)
+ (setq process-environment (cons (format "BZR_HOME=%s" tempdir)
+ process-environment)))
+ ;; git tries various approaches to guess a user name and email,
+ ;; which can fail depending on how the system is configured.
+ ;; Eg if the user account has no GECOS, git commit can fail with
+ ;; status 128 "fatal: empty ident name".
+ (when (memq backend '(Bzr Git))
+ (setq process-environment (cons "EMAIL=john@doe.ee"
+ process-environment)))
+ (if (eq backend 'Git)
+ (setq process-environment (append '("GIT_AUTHOR_NAME=A"
+ "GIT_COMMITTER_NAME=C")
+ process-environment)))
+ (unwind-protect
+ (progn
+ ;; Cleanup.
+ (add-hook
+ 'vc-test--cleanup-hook
+ (let ((dir default-directory))
+ (lambda () (delete-directory dir 'recursive))))
+
+ ;; Create empty repository. Check repository checkout model.
+ (make-directory default-directory)
+ (vc-test--create-repo-function backend)
+
+ (let* ((tmp-name (expand-file-name "foo" default-directory))
+ (files (list (file-name-nondirectory tmp-name))))
+ ;; Write and register a new file.
+ (write-region "originaltext" nil tmp-name nil 'nomessage)
+ (vc-register (list backend files))
+
+ (let ((buff (find-file tmp-name)))
+ (with-current-buffer buff
+ (progn
+ ;; Optionally checkout file.
+ (when (memq backend '(RCS CVS SCCS))
+ (vc-checkout tmp-name))
+
+ ;; Checkin file.
+ (vc-checkin files backend)
+ (insert "Testing vc-version-diff")
+ (log-edit-done))))
+
+ ;; Modify file content.
+ (when (memq backend '(RCS CVS SCCS))
+ (vc-checkout tmp-name))
+ (write-region "updatedtext" nil tmp-name nil 'nomessage)
+
+ ;; Check version diff.
+ (vc-version-diff files nil nil)
+ (should (bufferp (get-buffer "*vc-diff*")))
+
+ (with-current-buffer "*vc-diff*"
+ (progn
+ (let ((rawtext (buffer-substring-no-properties (point-min)
+ (point-max))))
+ (should (string-search "-originaltext" rawtext))
+ (should (string-search "+updatedtext" rawtext)))))))
+
+ ;; Save exit.
+ (ignore-errors
+ (run-hooks 'vc-test--cleanup-hook))))))
;; Create the test cases.
@@ -555,7 +674,8 @@ This checks also `vc-backend' and `vc-responsible-backend'."
(defvar vc-svn-program)
(defun vc-test--svn-enabled ()
- (executable-find vc-svn-program))
+ (and (executable-find "svnadmin")
+ (executable-find vc-svn-program)))
(defun vc-test--sccs-enabled ()
(executable-find "sccs"))
@@ -645,7 +765,39 @@ This checks also `vc-backend' and `vc-responsible-backend'."
(ert-get-test
',(intern
(format "vc-test-%s01-register" backend-string))))))
- (vc-test--checkout-model ',backend))))))
+ (vc-test--checkout-model ',backend))
+
+ (ert-deftest
+ ,(intern (format "vc-test-%s05-rename-file" backend-string)) ()
+ ,(format "Check `vc-rename-file' for the %s backend."
+ backend-string)
+ (skip-unless
+ (ert-test-passed-p
+ (ert-test-most-recent-result
+ (ert-get-test
+ ',(intern
+ (format "vc-test-%s01-register" backend-string))))))
+ ;; CVS calls vc-delete-file, which insists on prompting
+ ;; "Really want to delete ...?", and `vc-mtn.el' does not implement
+ ;; `delete-file' at all.
+ (skip-unless (not (memq ',backend '(CVS Mtn))))
+ (vc-test--rename-file ',backend))
+
+ (ert-deftest
+ ,(intern (format "vc-test-%s06-version-diff" backend-string)) ()
+ ,(format "Check `vc-version-diff' for the %s backend."
+ backend-string)
+ (skip-unless
+ (ert-test-passed-p
+ (ert-test-most-recent-result
+ (ert-get-test
+ ',(intern
+ (format "vc-test-%s01-register" backend-string))))))
+ ;; `vc-mtn.el' gives me:
+ ;; "Failed (status 1): mtn commit -m Testing vc-version-diff\n\n foo"
+ (skip-unless (not (memq ',backend '(Mtn))))
+ (vc-test--version-diff ',backend))
+ ))))
(provide 'vc-tests)
;;; vc-tests.el ends here
diff --git a/test/lisp/version-tests.el b/test/lisp/version-tests.el
new file mode 100644
index 00000000000..25dcc3d30cb
--- /dev/null
+++ b/test/lisp/version-tests.el
@@ -0,0 +1,31 @@
+;;; version-tests.el --- Tests for version.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+
+(ert-deftest test-emacs-version ()
+ (should (string-match emacs-version (emacs-version)))
+ (should (string-match system-configuration (emacs-version))))
+
+(provide 'version-tests)
+;;; version-tests.el ends here
diff --git a/test/lisp/wdired-tests.el b/test/lisp/wdired-tests.el
new file mode 100644
index 00000000000..58caa1deda8
--- /dev/null
+++ b/test/lisp/wdired-tests.el
@@ -0,0 +1,193 @@
+;;; wdired-tests.el --- tests for wdired.el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2018-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'ert-x)
+(require 'dired)
+(require 'dired-x)
+(require 'wdired)
+
+(defvar dired-query) ; Pacify byte compiler.
+
+(ert-deftest wdired-test-bug32173-01 ()
+ "Test using non-nil wdired-use-interactive-rename.
+Partially modifying a file name should succeed."
+ (ert-with-temp-directory test-dir
+ (let* ((test-file (concat (file-name-as-directory test-dir) "foo.c"))
+ (replace "bar")
+ (new-file (string-replace "foo" replace test-file))
+ (wdired-use-interactive-rename t))
+ (write-region "" nil test-file nil 'silent)
+ (advice-add 'dired-query ; Don't ask confirmation to overwrite a file.
+ :override
+ (lambda (_sym _prompt &rest _args) (setq dired-query t))
+ '((name . "advice-dired-query")))
+ (let ((buf (find-file-noselect test-dir)))
+ (unwind-protect
+ (with-current-buffer buf
+ (should (equal (dired-file-name-at-point) test-file))
+ (dired-toggle-read-only)
+ (kill-region (point) (progn (search-forward ".")
+ (forward-char -1) (point)))
+ (insert replace)
+ (wdired-finish-edit)
+ (should (equal (dired-file-name-at-point) new-file)))
+ (if buf (kill-buffer buf)))))))
+
+(ert-deftest wdired-test-bug32173-02 ()
+ "Test using non-nil wdired-use-interactive-rename.
+Aborting an edit should leaving original file name unchanged."
+ (ert-with-temp-directory test-dir
+ (let* ((test-file (concat (file-name-as-directory test-dir) "foo.c"))
+ (wdired-use-interactive-rename t))
+ (write-region "" nil test-file nil 'silent)
+ ;; Make dired-do-create-files-regexp a noop to mimic typing C-g
+ ;; at its prompt before wdired-finish-edit returns.
+ (advice-add 'dired-do-create-files-regexp
+ :override
+ (lambda (&rest _) (ignore))
+ '((name . "advice-dired-do-create-files-regexp")))
+ (let ((buf (find-file-noselect test-dir)))
+ (unwind-protect
+ (with-current-buffer buf
+ (should (equal (dired-file-name-at-point) test-file))
+ (dired-toggle-read-only)
+ (kill-region (point) (progn (search-forward ".")
+ (forward-char -1) (point)))
+ (insert "bar")
+ (wdired-finish-edit)
+ (should (equal (dired-get-filename) test-file)))
+ (if buf (kill-buffer buf)))))))
+
+(ert-deftest wdired-test-symlink-name ()
+ "Test the file name of a symbolic link.
+The Dired and WDired functions returning the name should include
+only the name before the link arrow."
+ (ert-with-temp-directory test-dir
+ (let* ((link-name "foo"))
+ (let ((buf (find-file-noselect test-dir)))
+ (unwind-protect
+ (with-current-buffer buf
+ (skip-unless
+ ;; This check is for wdired, not symbolic links, so skip
+ ;; it when make-symbolic-link fails for any reason (like
+ ;; insufficient privileges).
+ (ignore-errors (make-symbolic-link "./bar/baz" link-name) t))
+ (revert-buffer)
+ (let* ((file-name (dired-get-filename))
+ (dir-part (file-name-directory file-name))
+ (lf-name (concat dir-part link-name)))
+ (should (equal file-name lf-name))
+ (dired-toggle-read-only)
+ (should (equal (wdired-get-filename) lf-name))
+ (dired-toggle-read-only)))
+ (if buf (kill-buffer buf)))))))
+
+(ert-deftest wdired-test-unfinished-edit-01 ()
+ "Test editing a file name without saving the change.
+Finding the new name should be possible while still in
+wdired-mode."
+ (ert-with-temp-directory test-dir
+ (let* ((test-file (concat (file-name-as-directory test-dir) "foo.c"))
+ (replace "bar")
+ (new-file (string-replace "foo" replace test-file)))
+ (write-region "" nil test-file nil 'silent)
+ (let ((buf (find-file-noselect test-dir)))
+ (unwind-protect
+ (with-current-buffer buf
+ (should (equal (dired-file-name-at-point) test-file))
+ (dired-toggle-read-only)
+ (kill-region (point) (progn (search-forward ".")
+ (forward-char -1) (point)))
+ (insert replace)
+ (should (equal (dired-get-filename) new-file)))
+ (when buf
+ (with-current-buffer buf
+ ;; Prevent kill-buffer-query-functions from chiming in.
+ (set-buffer-modified-p nil)
+ (kill-buffer buf))))))))
+
+(ert-deftest wdired-test-bug34915 ()
+ "Test editing when dired-listing-switches includes -F.
+Appended file indicators should not count as part of the file
+name, either before or after editing. Since
+dired-move-to-end-of-filename handles indicator characters, it
+suffices to compare the return values of dired-get-filename and
+wdired-get-filename before and after editing."
+ ;; FIXME: Add a test for a door (indicator ">") only under Solaris?
+ (ert-with-temp-directory test-dir
+ (let* ((dired-listing-switches "-Fl")
+ (dired-ls-F-marks-symlinks (eq system-type 'darwin))
+ (buf (find-file-noselect test-dir))
+ proc)
+ (unwind-protect
+ (progn
+ (with-current-buffer buf
+ (dired-create-empty-file "foo")
+ (set-file-modes "foo" (file-modes-symbolic-to-number "+x"))
+ (make-symbolic-link "foo" "bar")
+ (make-directory "foodir")
+ (dired-smart-shell-command "mkfifo foopipe")
+ (when (featurep 'make-network-process '(:family local))
+ (setq proc (make-network-process
+ :name "foo"
+ :family 'local
+ :server t
+ :service (expand-file-name "foosocket" test-dir))))
+ (kill-buffer buf))
+ (dired test-dir)
+ (dired-toggle-read-only)
+ (let (names)
+ ;; Test that the file names are the same in Dired and WDired.
+ (while (not (eobp))
+ (should (equal (dired-get-filename 'no-dir t)
+ (wdired-get-filename t)))
+ (insert "w")
+ (push (wdired-get-filename t) names)
+ (dired-next-line 1))
+ (wdired-finish-edit)
+ ;; Test that editing the file names ignores the indicator
+ ;; character.
+ (let (dir)
+ (while (and (dired-previous-line 1)
+ (setq dir (dired-get-filename 'no-dir t)))
+ (should (equal dir (pop names)))))))
+ (kill-buffer (get-buffer test-dir))
+ (ignore-errors (delete-process proc))))))
+
+(ert-deftest wdired-test-bug39280 ()
+ "Test for https://debbugs.gnu.org/39280."
+ (ert-with-temp-directory test-dir
+ (let* ((fname "foo")
+ (full-fname (expand-file-name fname test-dir)))
+ (make-empty-file full-fname)
+ (let ((buf (find-file-noselect test-dir)))
+ (unwind-protect
+ (with-current-buffer buf
+ (dired-toggle-read-only)
+ (dolist (old '(t nil))
+ (should (equal fname (wdired-get-filename 'nodir old)))
+ (should (equal full-fname (wdired-get-filename nil old))))
+ (wdired-finish-edit))
+ (if buf (kill-buffer buf)))))))
+
+(provide 'wdired-tests)
+;;; wdired-tests.el ends here
diff --git a/test/lisp/whitespace-tests.el b/test/lisp/whitespace-tests.el
index ba99ddcdec4..97c30c4d627 100644
--- a/test/lisp/whitespace-tests.el
+++ b/test/lisp/whitespace-tests.el
@@ -1,6 +1,6 @@
;;; whitespace-tests.el --- Test suite for whitespace -*- lexical-binding: t -*-
-;; Copyright (C) 2016-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2022 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -20,8 +20,35 @@
;;; Code:
(require 'ert)
+(require 'ert-x)
+(require 'faceup)
(require 'whitespace)
+(defmacro whitespace-tests--with-test-buffer (style &rest body)
+ "Run BODY in a buffer with `whitespace-mode' style STYLE.
+The buffer is displayed in `selected-window', and
+`noninteractive' is set to nil even in batch mode."
+ (declare (debug ((style form) def-body))
+ (indent 1))
+ `(ert-with-test-buffer-selected ()
+ ;; In case global-*-mode is enabled.
+ (whitespace-mode -1)
+ (font-lock-mode -1)
+ (let ((noninteractive nil)
+ (whitespace-style ,style))
+ (font-lock-mode 1)
+ (whitespace-mode 1)
+ ,@body)))
+
+(defun whitespace-tests--faceup (&rest lines)
+ "Convenience wrapper around `faceup-test-font-lock-buffer'.
+Returns non-nil if the concatenated LINES match the current
+buffer's content."
+ (faceup-test-font-lock-buffer nil (apply #'concat lines)))
+(let ((x (get 'faceup-test-font-lock-buffer 'ert-explainer)))
+ (put 'whitespace-tests--faceup 'ert-explainer
+ (lambda (&rest lines) (funcall x nil (apply #'concat lines)))))
+
(defun whitespace-tests--cleanup-string (string)
(with-temp-buffer
(insert string)
@@ -51,10 +78,10 @@
;; We cannot call whitespace-mode because it will do nothing in batch
;; mode. So we call its innards instead.
(defun whitespace-tests-whitespace-mode-on ()
- "Turn whitespace-mode on even in batch mode."
+ "Turn `whitespace-mode' on even in batch mode."
+ (setq whitespace-mode t)
(whitespace-turn-on)
- (whitespace-action-when-on)
- (setq whitespace-mode t))
+ (whitespace-action-when-on))
(ert-deftest whitespace-tests-display-tables ()
"Test whitespace stores and restores the buffer display table - bug26892."
@@ -77,10 +104,212 @@
;test the stored display table is preserved
(should (equal nil
(progn (whitespace-tests-whitespace-mode-on)
- (whitespace-tests-whitespace-mode-on)
(whitespace-turn-off)
buffer-display-table))))))
+(ert-deftest whitespace-tests--empty-bob ()
+ (whitespace-tests--with-test-buffer '(face empty)
+ (electric-indent-mode -1)
+
+ ;; Insert some empty lines. None of the lines should be
+ ;; highlighted even though point is on the last line because the
+ ;; entire buffer is empty lines.
+ (execute-kbd-macro (kbd "SPC RET C-q TAB RET RET SPC"))
+ (should (equal (buffer-string) " \n\t\n\n "))
+ (should (equal (line-number-at-pos) 4))
+ (should (whitespace-tests--faceup " \n"
+ "\t\n"
+ "\n"
+ " "))
+
+ ;; Adding content on the last line (and keeping point there)
+ ;; should cause the previous lines to be highlighted. Note that
+ ;; the `whitespace-empty' face applies to the newline just before
+ ;; the last line, which has the desired property of extending the
+ ;; highlight the full width of the window.
+ (execute-kbd-macro (kbd "x"))
+ (should (equal (buffer-string) " \n\t\n\n x"))
+ (should (equal (line-number-at-pos) 4))
+ (should (whitespace-tests--faceup "«:whitespace-empty: \n"
+ "\t\n"
+ "\n"
+ "» x"))
+
+ ;; Lines should become un-highlighted as point moves up into the
+ ;; empty lines.
+ (execute-kbd-macro (kbd "<up>"))
+ (should (equal (line-number-at-pos) 3))
+ (should (whitespace-tests--faceup "«:whitespace-empty: \n"
+ "\t\n"
+ "»\n"
+ " x"))
+ (execute-kbd-macro (kbd "<up>"))
+ (should (equal (line-number-at-pos) 2))
+ (should (whitespace-tests--faceup "«:whitespace-empty: \n"
+ "»\t\n"
+ "\n"
+ " x"))
+ (execute-kbd-macro (kbd "<up> C-a"))
+ (should (equal (point) 1))
+ (should (whitespace-tests--faceup " \n"
+ "\t\n"
+ "\n"
+ " x"))
+
+ ;; Line 1 should be un-highlighted when point is in line 1 even if
+ ;; point is not bobp.
+ (execute-kbd-macro (kbd "<right>"))
+ (should (equal (line-number-at-pos) 1))
+ (should (> (point) 1))
+ (should (whitespace-tests--faceup " \n"
+ "\t\n"
+ "\n"
+ " x"))
+
+ ;; Make sure lines become re-highlighted as point moves down.
+ (execute-kbd-macro (kbd "<down>"))
+ (should (equal (line-number-at-pos) 2))
+ (should (whitespace-tests--faceup "«:whitespace-empty: \n"
+ "»\t\n"
+ "\n"
+ " x"))
+ (execute-kbd-macro (kbd "<down>"))
+ (should (equal (line-number-at-pos) 3))
+ (should (whitespace-tests--faceup "«:whitespace-empty: \n"
+ "\t\n"
+ "»\n"
+ " x"))
+ (execute-kbd-macro (kbd "<down>"))
+ (should (equal (line-number-at-pos) 4))
+ (should (whitespace-tests--faceup "«:whitespace-empty: \n"
+ "\t\n"
+ "\n"
+ "» x"))
+
+ ;; Inserting content on line 2 should un-highlight lines 2 and 3.
+ (execute-kbd-macro (kbd "<up> <up> C-e"))
+ (should (equal (line-number-at-pos) 2))
+ (should (equal (- (point) (line-beginning-position)) 1))
+ (execute-kbd-macro (kbd "y <down> <down>"))
+ (should (equal (line-number-at-pos) 4))
+ (should (whitespace-tests--faceup "«:whitespace-empty: \n"
+ "»\ty\n"
+ "\n"
+ " x"))
+
+ ;; Removing the content on line 2 should re-highlight lines 2 and
+ ;; 3.
+ (execute-kbd-macro (kbd "<up> <up> C-e"))
+ (should (equal (line-number-at-pos) 2))
+ (should (equal (- (point) (line-beginning-position)) 2))
+ (execute-kbd-macro (kbd "DEL <down> <down>"))
+ (should (equal (line-number-at-pos) 4))
+ (should (whitespace-tests--faceup "«:whitespace-empty: \n"
+ "\t\n"
+ "\n"
+ "» x"))))
+
+(ert-deftest whitespace-tests--empty-eob ()
+ (whitespace-tests--with-test-buffer '(face empty)
+ (electric-indent-mode -1)
+
+ ;; Insert some empty lines. None of the lines should be
+ ;; highlighted even though point is on line 1 because the entire
+ ;; buffer is empty lines.
+ (execute-kbd-macro (kbd "RET RET C-q TAB RET SPC C-<home>"))
+ (should (equal (buffer-string) "\n\n\t\n "))
+ (should (equal (line-number-at-pos) 1))
+ (should (whitespace-tests--faceup "\n"
+ "\n"
+ "\t\n"
+ " "))
+
+ ;; Adding content on the first line (and keeping point there)
+ ;; should cause the subsequent lines to be highlighted.
+ (execute-kbd-macro (kbd "x"))
+ (should (equal (buffer-string) "x\n\n\t\n "))
+ (should (equal (line-number-at-pos) 1))
+ (should (whitespace-tests--faceup "x\n"
+ "«:whitespace-empty:\n"
+ "\t\n"
+ " »"))
+
+ ;; Lines should become un-highlighted as point moves down into the
+ ;; empty lines.
+ (execute-kbd-macro (kbd "<down>"))
+ (should (equal (line-number-at-pos) 2))
+ (should (whitespace-tests--faceup "x\n"
+ "\n"
+ "«:whitespace-empty:\t\n"
+ " »"))
+ (execute-kbd-macro (kbd "<down>"))
+ (should (equal (line-number-at-pos) 3))
+ (should (whitespace-tests--faceup "x\n"
+ "\n"
+ "\t\n"
+ "«:whitespace-empty: »"))
+ (execute-kbd-macro (kbd "C-<end>"))
+ (should (equal (line-number-at-pos) 4))
+ (should (eobp))
+ (should (equal (- (point) (line-beginning-position)) 1))
+ (should (whitespace-tests--faceup "x\n"
+ "\n"
+ "\t\n"
+ " "))
+
+ ;; The last line should be un-highlighted when point is in that
+ ;; line even if point is not eobp.
+ (execute-kbd-macro (kbd "<left>"))
+ (should (equal (line-number-at-pos) 4))
+ (should (not (eobp)))
+ (should (whitespace-tests--faceup "x\n"
+ "\n"
+ "\t\n"
+ " "))
+
+ ;; Make sure lines become re-highlighted as point moves up.
+ (execute-kbd-macro (kbd "<up>"))
+ (should (equal (line-number-at-pos) 3))
+ (should (whitespace-tests--faceup "x\n"
+ "\n"
+ "\t\n"
+ "«:whitespace-empty: »"))
+ (execute-kbd-macro (kbd "<up>"))
+ (should (equal (line-number-at-pos) 2))
+ (should (whitespace-tests--faceup "x\n"
+ "\n"
+ "«:whitespace-empty:\t\n"
+ " »"))
+ (execute-kbd-macro (kbd "<up>"))
+ (should (equal (line-number-at-pos) 1))
+ (should (whitespace-tests--faceup "x\n"
+ "«:whitespace-empty:\n"
+ "\t\n"
+ " »"))
+
+ ;; Inserting content on line 3 should un-highlight lines 2 and 3.
+ (execute-kbd-macro (kbd "<down> <down> C-a"))
+ (should (equal (line-number-at-pos) 3))
+ (should (equal (- (point) (line-beginning-position)) 0))
+ (execute-kbd-macro (kbd "y <up> <up>"))
+ (should (equal (line-number-at-pos) 1))
+ (should (whitespace-tests--faceup "x\n"
+ "\n"
+ "y\t\n"
+ "«:whitespace-empty: »"))
+
+ ;; Removing the content on line 3 should re-highlight lines 2 and
+ ;; 3.
+ (execute-kbd-macro (kbd "<down> <down> C-a"))
+ (should (equal (line-number-at-pos) 3))
+ (should (equal (- (point) (line-beginning-position)) 0))
+ (execute-kbd-macro (kbd "<deletechar> <up> <up>"))
+ (should (equal (line-number-at-pos) 1))
+ (should (whitespace-tests--faceup "x\n"
+ "«:whitespace-empty:\n"
+ "\t\n"
+ " »"))))
+
(provide 'whitespace-tests)
;;; whitespace-tests.el ends here
diff --git a/test/lisp/wid-edit-tests.el b/test/lisp/wid-edit-tests.el
new file mode 100644
index 00000000000..34c96f1c934
--- /dev/null
+++ b/test/lisp/wid-edit-tests.el
@@ -0,0 +1,336 @@
+;;; wid-edit-tests.el --- tests for wid-edit.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2019-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'wid-edit)
+
+(ert-deftest widget-at ()
+ "Test `widget-at' behavior."
+ (with-temp-buffer
+ (should-not (widget-at))
+ (let ((marco (widget-create 'link "link widget"))
+ (polo (widget-at (1- (point)))))
+ (should (widgetp polo))
+ (should (eq marco polo)))
+ ;; Buttons and widgets are incompatible (bug#34506).
+ (insert-text-button "text button")
+ (should-not (widget-at (1- (point))))
+ (insert-button "overlay button")
+ (should-not (widget-at (1- (point))))))
+
+;; The following three tests compare the effect of using either %n or \n at the
+;; end of a format string, as well as using %n at the end or in the middle of
+;; the format string. (Bug#12533)
+
+(ert-deftest widget-test-indentation-after-%n ()
+ "Fail when %n is used at the end of a format string."
+ :expected-result :failed
+ (with-temp-buffer
+ (let (wid indented)
+ (widget-insert "Testing indentation.\n")
+ ;; If we use %n at the end of the format string of the widget `other', we
+ ;; screw up indentation of the following widgets.
+ (setq wid (widget-create
+ '(repeat :indent 4
+ (cons
+ string (choice (other :tag "Other" :format "%t%n" c))))))
+ (goto-char (widget-get wid :value-pos))
+ ;; Since we indent the `repeat' widget, we skip the space characters
+ ;; inserted.
+ (skip-chars-forward " ")
+ (setq indented (current-column)) ; Save the column to which we indented.
+ (should (eq indented (or (widget-get wid :indent) 0)))
+ ;; Insert an entry. This simulates a click or RET at the INS button.
+ (widget-apply (widget-at) :action)
+ (goto-char (widget-get wid :value-pos))
+ (skip-chars-forward " ")
+ ;; This fails, because the button is not at the right column.
+ (should (eq (current-column) indented)))))
+
+(ert-deftest widget-test-indentation-after-newline ()
+ "Pass when the newline is used at the end of a format string."
+ (with-temp-buffer
+ (let (wid indented)
+ (widget-insert "Testing indentation.\n")
+ (setq wid (widget-create
+ '(repeat :indent 4
+ (cons
+ string
+ (choice (other :tag "Other" :format "%t\n" c))))))
+ (goto-char (widget-get wid :value-pos))
+ (skip-chars-forward " ")
+ (setq indented (current-column))
+ (should (eq (current-column) (or (widget-get wid :indent) 0)))
+ (widget-apply (widget-at) :action)
+ (goto-char (widget-get wid :value-pos))
+ (skip-chars-forward " ")
+ ;; Because we used \n in the format string, this pass.
+ (should (eq (current-column) indented)))))
+
+(ert-deftest widget-test-newline-and-indent-same-widget ()
+ "It's OK to use the %n escape sequence in the middle of the format string."
+ (with-temp-buffer
+ (let (wid indented)
+ (widget-insert "Testing indentation.\n")
+ (setq wid (widget-create
+ '(repeat :indent 4
+ :format "%{%t%}:%n%v%i\n"
+ (cons
+ string
+ (choice (other :tag "Other" :format "%t\n" c))))))
+ (goto-char (widget-get wid :value-pos))
+ (skip-chars-forward " ")
+ (setq indented (current-column))
+ (should (eq indented (or (widget-get wid :indent) 0)))
+ (widget-apply (widget-at) :action)
+ (goto-char (widget-get wid :value-pos))
+ (skip-chars-forward " ")
+ (should (eq (current-column) indented))
+
+ ;; Also, the children are indented correctly.
+ (let ((grandchild
+ ;; This gets the `string' widget.
+ (car (widget-get (car (widget-get wid :children)) :children))))
+ (goto-char (widget-get grandchild :from))
+ (should (eq (current-column)
+ (widget-get grandchild :indent)))))))
+
+(ert-deftest widget-test-character-widget-value ()
+ "Check that we get the character widget's value correctly."
+ (with-temp-buffer
+ (let ((wid (widget-create '(character :value ?\n))))
+ (goto-char (widget-get wid :from))
+ (should (string= (widget-apply wid :value-get) "\n"))
+ (should (char-equal (widget-value wid) ?\n))
+ (should-not (widget-apply wid :validate)))))
+
+(ert-deftest widget-test-editable-field-widget-value ()
+ "Test that we get the editable field widget's value correctly."
+ (with-temp-buffer
+ (let ((wid (widget-create '(editable-field :value ""))))
+ (widget-insert "And some non-widget text.")
+ (should (string= (widget-apply wid :value-get) "")))))
+
+(ert-deftest widget-test-moving-editable-list-item ()
+ "Check that we can move an editable list item up or down, via delete+insert."
+ (with-temp-buffer
+ (widget-insert "Testing editable-list.\n\n")
+ (let ((lst (widget-create 'editable-list
+ :value '("beg" "end" "middle")
+ '(editable-field :value "unknown"))))
+ (use-local-map widget-keymap)
+ (widget-setup)
+ ;; Go to the DEL button for the 2nd element and action it.
+ (goto-char (widget-get (nth 2 (widget-get lst :buttons)) :from))
+ (widget-apply-action (widget-at))
+ ;; Go to the INS button and action it.
+ (goto-char (widget-get lst :to))
+ (widget-backward 1)
+ (widget-apply-action (widget-at))
+ ;; Check that we effectively moved the item to the last position.
+ (should (equal (widget-value lst) '("beg" "middle" "end"))))))
+
+(ert-deftest widget-test-choice-match-no-inline ()
+ "Test that a no-inline choice widget can match its values."
+ (let* ((choice '(choice (const nil) (const t) string function))
+ (widget (widget-convert choice)))
+ (should (widget-apply widget :match nil))
+ (should (widget-apply widget :match t))
+ (should (widget-apply widget :match ""))
+ (should (widget-apply widget :match 'ignore))))
+
+(ert-deftest widget-test-choice-match-all-inline ()
+ "Test that a choice widget with all inline members can match its values."
+ (let* ((lst '(list (choice (list :inline t symbol number)
+ (list :inline t symbol regexp))))
+ (widget (widget-convert lst)))
+ (should-not (widget-apply widget :match nil))
+ (should (widget-apply widget :match '(:test 2)))
+ (should (widget-apply widget :match '(:test ".*")))
+ (should-not (widget-apply widget :match '(:test ignore)))))
+
+(ert-deftest widget-test-choice-match-some-inline ()
+ "Test that a choice widget with some inline members can match its values."
+ (let* ((lst '(list string
+ (choice (const t)
+ (list :inline t symbol number)
+ (list :inline t symbol regexp))))
+ (widget (widget-convert lst)))
+ (should-not (widget-apply widget :match nil))
+ (should (widget-apply widget :match '("" t)))
+ (should (widget-apply widget :match '("" :test 2)))
+ (should (widget-apply widget :match '("" :test ".*")))
+ (should-not (widget-apply widget :match '(:test ignore)))))
+
+(ert-deftest widget-test-inline-p ()
+ "Test `widget-inline-p'.
+For widgets without an :inline t property, `widget-inline-p' has to return nil.
+But if the widget is a choice widget, it has to return nil if passed nil as
+the bubblep argument, or non-nil if one of the members of the choice widget has
+an :inline t property and we pass a non-nil bubblep argument. If no members of
+the choice widget have an :inline t property, then `widget-inline-p' has to
+return nil, even with a non-nil bubblep argument."
+ (with-temp-buffer
+ (widget-insert "Testing.\n\n")
+ (let* ((widget (widget-create 'repeat
+ :value '(nil)
+ '(choice (const nil) (const t)
+ (list :inline t symbol number))
+ '(choice (const nil) (const t)
+ (list function string))))
+ (children (widget-get widget :children))
+ (child-1 (car children))
+ (child-2 (cadr children)))
+ (should-not (widget-inline-p widget))
+ (should-not (widget-inline-p child-1))
+ (should (widget-inline-p child-1 'bubble))
+ (should-not (widget-inline-p child-2))
+ (should-not (widget-inline-p child-2 'bubble)))))
+
+(ert-deftest widget-test-repeat-can-handle-choice ()
+ "Test that we can create a repeat widget with a choice correctly."
+ (with-temp-buffer
+ (widget-insert "Testing.\n\n")
+ (let* ((widget (widget-create 'repeat
+ :entry-format "%i %d %v"
+ :value '((:test 2))
+ '(choice (const nil) (const t)
+ (list symbol number))))
+ (child (car (widget-get widget :children))))
+ (widget-insert "\n")
+ (use-local-map widget-keymap)
+ (widget-setup)
+ (should child)
+ (should (equal (widget-value widget) '((:test 2)))))))
+
+(ert-deftest widget-test-repeat-can-handle-inlinable-choice ()
+ "Test that we can create a repeat widget with an inlinable choice correctly."
+ (with-temp-buffer
+ (widget-insert "Testing.\n\n")
+ (let* ((widget (widget-create 'repeat
+ :entry-format "%i %d %v"
+ :value '(:test 2)
+ '(choice (const nil) (const t)
+ (list :inline t symbol number))))
+ (child (widget-get widget :children)))
+ (widget-insert "\n")
+ (use-local-map widget-keymap)
+ (widget-setup)
+ (should child)
+ (should (equal (widget-value widget) '(:test 2))))))
+
+(ert-deftest widget-test-list-can-handle-choice ()
+ "Test that we can create a list widget with a choice correctly."
+ (with-temp-buffer
+ (widget-insert "Testing.\n\n")
+ (let* ((widget (widget-create 'list
+ :value '((1 "One"))
+ '(choice string
+ (list number string))))
+ (child (car (widget-get widget :children))))
+ (widget-insert "\n")
+ (use-local-map widget-keymap)
+ (widget-setup)
+ (should child)
+ (should (equal (widget-value widget) '((1 "One")))))))
+
+(ert-deftest widget-test-list-can-handle-inlinable-choice ()
+ "Test that we can create a list widget with an inlinable choice correctly."
+ (with-temp-buffer
+ (widget-insert "Testing.\n\n")
+ (let* ((widget (widget-create 'list
+ :value '(1 "One")
+ '(choice string
+ (list :inline t number string))))
+ (child (car (widget-get widget :children))))
+ (widget-insert "\n")
+ (use-local-map widget-keymap)
+ (widget-setup)
+ (should child)
+ (should (equal (widget-value widget) '(1 "One"))))))
+
+(ert-deftest widget-test-option-can-handle-choice ()
+ "Test that we can create a option widget with a choice correctly."
+ (with-temp-buffer
+ (widget-insert "Testing.\n\n")
+ (let* ((widget (widget-create 'repeat
+ :value '(("foo"))
+ '(list (option
+ (choice string
+ (list :inline t
+ number string))))))
+ (child (car (widget-get widget :children))))
+ (widget-insert "\n")
+ (use-local-map widget-keymap)
+ (widget-setup)
+ (should child)
+ (should (equal (widget-value widget) '(("foo")))))))
+
+(ert-deftest widget-test-option-can-handle-inlinable-choice ()
+ "Test that we can create a option widget with an inlinable choice correctly."
+ (with-temp-buffer
+ (widget-insert "Testing.\n\n")
+ (let* ((widget (widget-create 'repeat
+ :value '((1 "One"))
+ '(list (option
+ (choice string
+ (list :inline t
+ number string))))))
+ (child (car (widget-get widget :children))))
+ (widget-insert "\n")
+ (use-local-map widget-keymap)
+ (widget-setup)
+ (should child)
+ (should (equal (widget-value widget) '((1 "One")))))))
+
+(ert-deftest widget-test-widget-move ()
+ "Test moving with `widget-forward' and `widget-backward'."
+ (with-temp-buffer
+ (dolist (el '("First" "Second" "Third"))
+ (widget-create 'push-button el))
+ (widget-insert "\n")
+ (use-local-map widget-keymap)
+ (widget-setup)
+ (goto-char (point-min))
+ ;; Check that moving from the widget's start works.
+ (widget-forward 2)
+ (should (string= "Third" (widget-value (widget-at))))
+ (widget-backward 1)
+ (should (string= "Second" (widget-value (widget-at))))
+ ;; Check that moving from inside the widget works.
+ (goto-char (point-min))
+ (widget-forward 2)
+ (forward-char)
+ (widget-backward 1)
+ (should (string= "Second" (widget-value (widget-at))))))
+
+(ert-deftest widget-test-color-match ()
+ "Test that the :match function for the color widget works."
+ (let ((widget (widget-convert 'color)))
+ (should (widget-apply widget :match "red"))
+ (should (widget-apply widget :match "#fa3"))
+ (should (widget-apply widget :match "#ff0000"))
+ (should (widget-apply widget :match "#111222333"))
+ (should (widget-apply widget :match "#111122223333"))
+ (should-not (widget-apply widget :match "someundefinedcolorihope"))
+ (should-not (widget-apply widget :match "#11223"))))
+
+;;; wid-edit-tests.el ends here
diff --git a/test/lisp/x-dnd-tests.el b/test/lisp/x-dnd-tests.el
new file mode 100644
index 00000000000..55994e9b724
--- /dev/null
+++ b/test/lisp/x-dnd-tests.el
@@ -0,0 +1,206 @@
+;;; dnd-tests.el --- Tests for X DND support -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Tests for stuff in x-dnd.el that doesn't require a window system.
+
+;;; Code:
+
+(require 'x-dnd)
+(require 'cl-lib)
+
+(when (display-graphic-p)
+ (error "This test cannot be run under X"))
+
+;; Dummy replacements.
+
+(defconst x-dnd-tests-drag-window-xid 3948573
+ "XID of the drag window returned during the test.")
+
+(defvar x-dnd-tests-xds-property-value nil
+ "The value of the `XdndDirectSave0' window property.")
+
+(defconst x-dnd-tests-targets-table
+ (base64-decode-string
+ "bAArAKIBAAAGAB8AAABqAQAANgIAAJMCAAAFAwAABgMAAAEAkMJbAAEAINNbAAUAHwAAAGoBAAA2
+AgAAkwIAANkfAAALAB8AAABqAQAANgIAAJMCAADyAgAA2R8AANwfAADgHwAA4R8AAOIfAADjHwAA
+AQDQMAgCAQBQTggCAQCwe5IAAQDQmZIABgDyAgAA9wIAABcRAADgHwAAvSEAAI3AAAABAHC52AAB
+AGDY2AABAABq3QABAGBw3QAIAB8AAAA2AgAA8gIAANwfAADgHwAA4R8AAOIfAADjHwAAAQBwBOEA
+AQCACuEAAQAwLwUCAQDwPgUCAQBQxoQBAQCQ3YQBAQCQBYoBAQDACYoBAQCgMooBAQCgOIoBAQAf
+AAAAAQDATrcDAQAQ1LcDAQCw/sADAQAgBcEDAQBQt7oDAQAAUsIDAQCAc7wDAQAwerwDAQBAIKUE
+AQAALKUEAQDwfKUEAQDgg6UEAQCgjesEAQAAmusEAQCA7+sEAQCw9usECAAfAAAAagEAADYCAACT
+AgAABQMAAAYDAAATGwAAGhsAAA==")
+ "Predefined Motif targets table used to test the targets table parser.")
+
+(defconst x-dnd-tests-lispy-targets-table [[31 362 566 659 773 774] [6013584] [6017824]
+ [31 362 566 659 8153]
+ [31 362 566 659 754 8153 8156 8160 8161 8162 8163]
+ [34091216] [34098768] [9599920]
+ [9607632] [754 759 4375 8160 8637 49293]
+ [14203248] [14211168] [14510592]
+ [14512224] [31 566 754 8156 8160 8161 8162 8163]
+ [14746736] [14748288] [33894192] [33898224]
+ [25478736] [25484688] [25822608] [25823680]
+ [25834144] [25835680] [31] [62344896] [62379024]
+ [62979760] [62981408] [62568272] [63066624]
+ [62681984] [62683696] [77930560] [77933568]
+ [77954288] [77956064] [82546080] [82549248]
+ [82571136] [82572976] [31 362 566 659 773 774 6931 6938]]
+ "The expected result of parsing that targets table.")
+
+(defalias 'x-window-property
+ (lambda (prop &optional _frame type window-id delete-p _vector-ret-p)
+ (cond
+ ((and (equal prop "_MOTIF_DRAG_WINDOW")
+ (zerop window-id) (equal type "WINDOW"))
+ x-dnd-tests-drag-window-xid)
+ ((and (equal prop "_MOTIF_DRAG_TARGETS")
+ (equal type "_MOTIF_DRAG_TARGETS")
+ (equal window-id x-dnd-tests-drag-window-xid))
+ x-dnd-tests-targets-table)
+ ((and (equal prop "XdndDirectSave0")
+ (or (equal type "text/plain")
+ (equal type "AnyPropertyType")))
+ (prog1 x-dnd-tests-xds-property-value
+ (when delete-p
+ (setq x-dnd-tests-xds-property-value nil)))))))
+
+;; This test also serves to exercise most of the Motif value
+;; extraction code.
+(ert-deftest x-dnd-tests-read-xm-targets-table ()
+ (should (equal (x-dnd-xm-read-targets-table nil)
+ x-dnd-tests-lispy-targets-table)))
+
+;;; XDS tests.
+
+(defvar x-dnd-xds-testing)
+
+(defvar x-dnd-tests-xds-target-dir nil
+ "The name of the target directory where the file will be saved.")
+
+(defvar x-dnd-tests-xds-name nil
+ "The name that the dragged file should be saved under.")
+
+(defvar x-dnd-tests-xds-include-hostname nil
+ "Whether or not to include the hostname inside the XDS URI.")
+
+(defun x-dnd-tests-call-xds-converter ()
+ "Look up the XDS selection converter and call it.
+Return the result of the selection."
+ (let ((conv (cdr (assq 'XdndDirectSave0
+ selection-converter-alist))))
+ (should (functionp conv))
+ (funcall conv 'XdndDirectSave0 'XdndDirectSave0 nil)))
+
+(defalias 'x-begin-drag
+ (lambda (_targets &optional action frame &rest _)
+ ;; Verify that frame is either nil or a valid frame.
+ (when (and frame (not (frame-live-p frame)))
+ (signal 'wrong-type-argument frame))
+ (prog1 'XdndActionDirectSave
+ ;; Verify that the action is `XdndActionDirectSave'.
+ (should (eq action 'XdndActionDirectSave))
+ ;; Set the property value to the URI of the new file.
+ (should (and (stringp x-dnd-tests-xds-property-value)
+ (not (multibyte-string-p x-dnd-tests-xds-property-value))))
+ (let ((uri (if x-dnd-tests-xds-include-hostname
+ (format "file://%s%s" (system-name)
+ (expand-file-name x-dnd-tests-xds-property-value
+ x-dnd-tests-xds-target-dir))
+ (concat "file://" (expand-file-name x-dnd-tests-xds-property-value
+ x-dnd-tests-xds-target-dir)))))
+ (setq x-dnd-tests-xds-property-value
+ (encode-coding-string (url-encode-url uri)
+ 'raw-text)))
+ ;; Convert the selection and verify its success.
+ (should (equal (x-dnd-tests-call-xds-converter)
+ '(STRING . "S"))))))
+
+(defalias 'x-change-window-property
+ (lambda (prop value &optional _frame type format outer-p _window-id)
+ ;; Check that the properties are the right type.
+ (should (equal prop "XdndDirectSave0"))
+ (should (equal value (encode-coding-string
+ x-dnd-tests-xds-name
+ (or file-name-coding-system
+ default-file-name-coding-system))))
+ (should (equal type "text/plain"))
+ (should (equal format 8))
+ (should (not outer-p))
+ (setq x-dnd-tests-xds-property-value value)))
+
+(defalias 'x-delete-window-property
+ (lambda (&rest _args)
+ ;; This function shouldn't ever be reached during XDS.
+ (setq x-dnd-tests-xds-property-value nil)))
+
+(defun x-dnd-tests-do-direct-save-internal (include-hostname)
+ "Test the behavior of `x-dnd-do-direct-save'.
+Make it perform a direct save to a randomly generated directory,
+and check that the file exists. If INCLUDE-HOSTNAME, include the
+hostname in the target URI."
+ (let ((x-dnd-tests-xds-include-hostname include-hostname)
+ (x-dnd-tests-xds-target-dir
+ (file-name-as-directory (expand-file-name
+ (make-temp-name "x-dnd-test")
+ temporary-file-directory)))
+ (original-file (expand-file-name
+ (make-temp-name "x-dnd-test")
+ temporary-file-directory))
+ (x-dnd-tests-xds-name (make-temp-name "x-dnd-test-target"))
+ (x-dnd-xds-testing t))
+ ;; The call to `gui-set-selection' is only used for providing the
+ ;; conventional `text/uri-list' target and can be ignored.
+ (cl-flet ((gui-set-selection #'ignore))
+ (unwind-protect
+ (progn
+ ;; Touch `original-file' if it doesn't exist.
+ (unless (file-exists-p original-file)
+ (write-region "" 0 original-file))
+ ;; Create `x-dnd-tests-xds-target-dir'.
+ (make-directory x-dnd-tests-xds-target-dir)
+ ;; Start the direct save and verify it returns the correct action.
+ (should (eq (x-dnd-do-direct-save original-file
+ x-dnd-tests-xds-name
+ nil nil)
+ 'XdndActionDirectSave))
+ ;; Now verify that the new file exists.
+ (should (file-exists-p
+ (expand-file-name x-dnd-tests-xds-name
+ x-dnd-tests-xds-target-dir)))
+ ;; The XDS protocol makes very clear that the window
+ ;; property must be deleted after the drag-and-drop
+ ;; operation completes.
+ (should (not x-dnd-tests-xds-property-value)))
+ ;; Clean up after ourselves.
+ (ignore-errors
+ (delete-file original-file))
+ (ignore-errors
+ (delete-directory x-dnd-tests-xds-target-dir t))))))
+
+(ert-deftest x-dnd-tests-do-direct-save ()
+ ;; TODO: add tests for application/octet-stream transfer.
+ (x-dnd-tests-do-direct-save-internal nil)
+ ;; Test with both kinds of file: URIs, since different programs
+ ;; generate different kinds.
+ (x-dnd-tests-do-direct-save-internal t))
+
+(provide 'x-dnd-tests)
+;;; x-dnd-tests.el ends here
diff --git a/test/data/xdg/l10n.desktop b/test/lisp/xdg-resources/l10n.desktop
index 42da83910da..42da83910da 100644
--- a/test/data/xdg/l10n.desktop
+++ b/test/lisp/xdg-resources/l10n.desktop
diff --git a/test/data/xdg/malformed.desktop b/test/lisp/xdg-resources/malformed.desktop
index 144a3f719d5..144a3f719d5 100644
--- a/test/data/xdg/malformed.desktop
+++ b/test/lisp/xdg-resources/malformed.desktop
diff --git a/test/data/xdg/mimeapps.list b/test/lisp/xdg-resources/mimeapps.list
index 27fbd94b16b..27fbd94b16b 100644
--- a/test/data/xdg/mimeapps.list
+++ b/test/lisp/xdg-resources/mimeapps.list
diff --git a/test/data/xdg/mimeinfo.cache b/test/lisp/xdg-resources/mimeinfo.cache
index 6e54f604fa0..6e54f604fa0 100644
--- a/test/data/xdg/mimeinfo.cache
+++ b/test/lisp/xdg-resources/mimeinfo.cache
diff --git a/test/data/xdg/test.desktop b/test/lisp/xdg-resources/test.desktop
index b848cef5b0f..b848cef5b0f 100644
--- a/test/data/xdg/test.desktop
+++ b/test/lisp/xdg-resources/test.desktop
diff --git a/test/data/xdg/wrong.desktop b/test/lisp/xdg-resources/wrong.desktop
index e0b4c221cf9..e0b4c221cf9 100644
--- a/test/data/xdg/wrong.desktop
+++ b/test/lisp/xdg-resources/wrong.desktop
diff --git a/test/lisp/xdg-tests.el b/test/lisp/xdg-tests.el
index eaf03ab9a03..882160743a2 100644
--- a/test/lisp/xdg-tests.el
+++ b/test/lisp/xdg-tests.el
@@ -1,9 +1,9 @@
;;; xdg-tests.el --- tests for xdg.el -*- lexical-binding: t -*-
-;; Copyright (C) 2017 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2022 Free Software Foundation, Inc.
-;; Maintainer: emacs-devel@gnu.org
;; Author: Mark Oteiza <mvoteiza@udel.edu>
+;; Maintainer: emacs-devel@gnu.org
;; This file is part of GNU Emacs.
@@ -25,26 +25,20 @@
;;; Code:
(require 'ert)
+(require 'ert-x)
(require 'xdg)
-(defconst xdg-tests-data-dir
- (expand-file-name "test/data/xdg" source-directory))
-
(ert-deftest xdg-desktop-parsing ()
"Test `xdg-desktop-read-file' parsing of .desktop files."
- (let ((tab1 (xdg-desktop-read-file
- (expand-file-name "test.desktop" xdg-tests-data-dir)))
- (tab2 (xdg-desktop-read-file
- (expand-file-name "test.desktop" xdg-tests-data-dir)
+ (let ((tab1 (xdg-desktop-read-file (ert-resource-file "test.desktop")))
+ (tab2 (xdg-desktop-read-file (ert-resource-file "test.desktop")
"Another Section")))
(should (equal (gethash "Name" tab1) "Test"))
(should (eq 'default (gethash "Exec" tab1 'default)))
(should (equal "frobnicate" (gethash "Exec" tab2))))
(should-error
- (xdg-desktop-read-file
- (expand-file-name "malformed.desktop" xdg-tests-data-dir)))
- (let ((tab (xdg-desktop-read-file
- (expand-file-name "l10n.desktop" xdg-tests-data-dir)))
+ (xdg-desktop-read-file (ert-resource-file "malformed.desktop")))
+ (let ((tab (xdg-desktop-read-file (ert-resource-file "l10n.desktop")))
(env (getenv "LC_MESSAGES")))
(unwind-protect
(progn
@@ -65,10 +59,20 @@
(should (equal (xdg-desktop-strings " ") nil))
(should (equal (xdg-desktop-strings "a; ;") '("a" " "))))
+(ert-deftest xdg-current-desktop ()
+ (let ((env (getenv "XDG_CURRENT_DESKTOP")))
+ (unwind-protect
+ (progn
+ (setenv "XDG_CURRENT_DESKTOP" "KDE")
+ (should (equal (xdg-current-desktop) '("KDE")))
+ (setenv "XDG_CURRENT_DESKTOP" "ubuntu:GNOME")
+ (should (equal (xdg-current-desktop) '("ubuntu" "GNOME"))))
+ (setenv "XDG_CURRENT_DESKTOP" env))))
+
(ert-deftest xdg-mime-associations ()
"Test reading MIME associations from files."
- (let* ((apps (expand-file-name "mimeapps.list" xdg-tests-data-dir))
- (cache (expand-file-name "mimeinfo.cache" xdg-tests-data-dir))
+ (let* ((apps (ert-resource-file "mimeapps.list"))
+ (cache (ert-resource-file "mimeinfo.cache"))
(fs (list apps cache)))
(should (equal (xdg-mime-collect-associations "x-test/foo" fs)
'("a.desktop" "b.desktop")))
diff --git a/test/lisp/xml-tests.el b/test/lisp/xml-tests.el
index ba693490e24..0040e5c7bab 100644
--- a/test/lisp/xml-tests.el
+++ b/test/lisp/xml-tests.el
@@ -1,6 +1,6 @@
-;;; xml-parse-tests.el --- Test suite for XML parsing.
+;;; xml-tests.el --- Test suite for XML parsing. -*- lexical-binding:t -*-
-;; Copyright (C) 2012-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2022 Free Software Foundation, Inc.
;; Author: Chong Yidong <cyd@stupidchicken.com>
;; Keywords: internal
@@ -78,7 +78,7 @@
;; Bug#16344
"<!----><x>< /x>"
"<a>< b/></a>")
- "List of XML strings that should signal an error in the parser")
+ "List of XML strings that should signal an error in the parser.")
(defvar xml-parse-tests--qnames
'( ;; Test data for name expansion
@@ -97,7 +97,7 @@
((("FOOBAR:" . "something") nil "hi there"))
((FOOBAR:something nil "hi there"))))
"List of strings which are parsed using namespace expansion.
-Parser is called with and without 'symbol-qnames argument.")
+Parser is called with and without `symbol-qnames' argument.")
(ert-deftest xml-parse-tests ()
"Test XML parsing."
@@ -164,8 +164,35 @@ Parser is called with and without 'symbol-qnames argument.")
(should (equal (cdr xml-parse-test--namespace-attribute-qnames)
(xml-parse-region nil nil nil nil 'symbol-qnames)))))
-;; Local Variables:
-;; no-byte-compile: t
-;; End:
-
-;;; xml-parse-tests.el ends here.
+(ert-deftest xml-print-invalid-cdata ()
+ "Check that Bug#41094 is fixed."
+ (with-temp-buffer
+ (should (equal (should-error (xml-print '((foo () "\0")))
+ :type 'xml-invalid-character)
+ '(xml-invalid-character 0 1)))
+ (should (equal (should-error (xml-print '((foo () "\u00FF \xFF")))
+ :type 'xml-invalid-character)
+ '(xml-invalid-character #x3FFFFF 3)))))
+
+(defvar xml-tests--data-with-comments
+ `(;; simple case
+ ("<?xml version=\"1.0\"?><foo baz=\"true\">bar</foo>"
+ . ((foo ((baz . "true")) "bar")))
+ ;; toplevel comments -- first document child must not get lost
+ (,(concat "<?xml version=\"1.0\"?><foo>bar</foo><!--comment-1-->"
+ "<!--comment-2-->")
+ . ((foo nil "bar")))
+ (,(concat "<?xml version=\"1.0\"?><!--comment-a--><foo a=\"b\">"
+ "<bar>blub</bar></foo><!--comment-b--><!--comment-c-->")
+ . ((foo ((a . "b")) (bar nil "blub")))))
+ "Alist of XML strings and their expected parse trees for discarded comments.")
+
+(ert-deftest xml-remove-comments ()
+ (dolist (test xml-tests--data-with-comments)
+ (erase-buffer)
+ (insert (car test))
+ (xml-remove-comments (point-min) (point-max))
+ (should (equal (cdr test)
+ (xml-parse-region (point-min) (point-max))))))
+
+;;; xml-tests.el ends here
diff --git a/test/lisp/xt-mouse-tests.el b/test/lisp/xt-mouse-tests.el
index 53844a6e991..379ad7bf039 100644
--- a/test/lisp/xt-mouse-tests.el
+++ b/test/lisp/xt-mouse-tests.el
@@ -1,6 +1,6 @@
;;; xt-mouse-tests.el --- Test suite for xt-mouse. -*- lexical-binding: t; -*-
-;; Copyright (C) 2016-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2022 Free Software Foundation, Inc.
;; Author: Philipp Stephani <phst@google.com>
@@ -28,34 +28,40 @@
(defmacro with-xterm-mouse-mode (&rest body)
"Run BODY with `xterm-mouse-mode' temporarily enabled."
(declare (indent 0))
- ;; Make the frame huge so that the test input events below don't hit
- ;; the menu bar.
- `(cl-letf (((frame-width nil) 2000)
- ((frame-height nil) 2000)
- ;; Reset XTerm parameters so that the tests don't get
- ;; confused.
- ((terminal-parameter nil 'xterm-mouse-x) nil)
- ((terminal-parameter nil 'xterm-mouse-y) nil)
- ((terminal-parameter nil 'xterm-mouse-last-down) nil)
- ((terminal-parameter nil 'xterm-mouse-last-click) nil))
- (if xterm-mouse-mode
- (progn ,@body)
- (unwind-protect
- (progn
- ;; `xterm-mouse-mode' doesn't work in the initial
- ;; terminal. Since we can't create a second terminal in
- ;; batch mode, fake it temporarily.
- (cl-letf (((symbol-function 'terminal-name)
- (lambda (&optional _terminal) "fake-terminal")))
- (xterm-mouse-mode))
- ,@body)
- (xterm-mouse-mode 0)))))
+ `(let ((width (frame-width))
+ (height (frame-height)))
+ (unwind-protect
+ (progn
+ ;; Make the frame huge so that the test input events below
+ ;; don't hit the menu bar.
+ (set-frame-width nil (max width 2000))
+ (set-frame-height nil (max height 2000))
+ (cl-letf (;; Reset XTerm parameters so that the tests don't
+ ;; get confused.
+ ((terminal-parameter nil 'xterm-mouse-x) nil)
+ ((terminal-parameter nil 'xterm-mouse-y) nil)
+ ((terminal-parameter nil 'xterm-mouse-last-down) nil)
+ ((terminal-parameter nil 'xterm-mouse-last-click) nil))
+ (if xterm-mouse-mode
+ ,(macroexp-progn body)
+ (unwind-protect
+ (progn
+ ;; `xterm-mouse-mode' doesn't work in the initial
+ ;; terminal. Since we can't create a second
+ ;; terminal in batch mode, fake it temporarily.
+ (cl-letf (((symbol-function 'terminal-name)
+ (lambda (&optional _terminal) "fake-terminal")))
+ (xterm-mouse-mode))
+ ,@body)
+ (xterm-mouse-mode 0)))))
+ (set-frame-width nil width)
+ (set-frame-height nil height))))
(ert-deftest xt-mouse-tracking-basic ()
(should (equal (xterm-mouse-tracking-enable-sequence)
- "\e[?1000h\e[?1002h\e[?1006h"))
+ "\e[?1000h\e[?1003h\e[?1006h"))
(should (equal (xterm-mouse-tracking-disable-sequence)
- "\e[?1006l\e[?1002l\e[?1000l"))
+ "\e[?1006l\e[?1003l\e[?1000l"))
(with-xterm-mouse-mode
(should xterm-mouse-mode)
(should (terminal-parameter nil 'xterm-mouse-mode))
@@ -73,9 +79,9 @@
(ert-deftest xt-mouse-tracking-utf-8 ()
(let ((xterm-mouse-utf-8 t))
(should (equal (xterm-mouse-tracking-enable-sequence)
- "\e[?1000h\e[?1002h\e[?1005h\e[?1006h"))
+ "\e[?1000h\e[?1003h\e[?1005h\e[?1006h"))
(should (equal (xterm-mouse-tracking-disable-sequence)
- "\e[?1006l\e[?1005l\e[?1002l\e[?1000l"))
+ "\e[?1006l\e[?1005l\e[?1003l\e[?1000l"))
(with-xterm-mouse-mode
(should xterm-mouse-mode)
(should (terminal-parameter nil 'xterm-mouse-mode))
diff --git a/test/lisp/yank-media-tests.el b/test/lisp/yank-media-tests.el
new file mode 100644
index 00000000000..4487ae150da
--- /dev/null
+++ b/test/lisp/yank-media-tests.el
@@ -0,0 +1,38 @@
+;;; yank-media-tests.el --- Tests for yank-media.el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;
+
+;;; Code:
+
+(require 'yank-media)
+(require 'ert)
+(require 'ert-x)
+
+(ert-deftest test-utf-16 ()
+ (should-not (yank-media--utf-16-p "f"))
+ (should-not (yank-media--utf-16-p "fo"))
+ (should-not (yank-media--utf-16-p "\000ofo"))
+ (should (eq (yank-media--utf-16-p "\000o\000o") 'utf-16-be))
+ (should (eq (yank-media--utf-16-p "o\000o\000") 'utf-16-le))
+ (should-not (yank-media--utf-16-p "o\000\000o")))
+
+;;; yank-media-tests.el ends here
diff --git a/test/manual/BidiCharacterTest.txt b/test/manual/BidiCharacterTest.txt
index a3d2b46cc40..619d4b4412b 100644
--- a/test/manual/BidiCharacterTest.txt
+++ b/test/manual/BidiCharacterTest.txt
@@ -1,14 +1,14 @@
-# BidiCharacterTest-10.0.0.txt
-# Date: 2017-03-09, 00:30:00 GMT [LI]
-# © 2017 Unicode®, Inc.
-# For terms of use, see http://www.unicode.org/terms_of_use.html
+# BidiCharacterTest-15.0.0.txt
+# Date: 2022-05-03, 18:46:00 GMT [LI]
+# © 2022 Unicode®, Inc.
+# For terms of use, see https://www.unicode.org/terms_of_use.html
#
# Unicode Character Database
-# For documentation, see http://www.unicode.org/reports/tr44/
+# For documentation, see https://www.unicode.org/reports/tr44/
#
# This file provides a conformance test for implementations of the
# Unicode Bidirectional Algorithm, specified in UAX #9: Unicode
-# Bidirectional Algorithm, at http://www.unicode.org/reports/tr9/
+# Bidirectional Algorithm, at https://www.unicode.org/reports/tr9/
#
# The test data has been generated with a few constraints. Each test case
# is a single paragraph, so the test data does not contain any characters
@@ -87,6 +87,32 @@
0661 0028 0662 0029 0331;0;0;2 1 2 1 1;4 3 2 1 0
0661 0028 0332 0662 0029 0333;0;0;2 1 1 2 1 1;5 4 3 2 1 0
+# Nonspacing marks applied to paired brackets [added to test cases for Unicode 14.0]
+# These cases exercise the ignoring of bc=BN characters (such as ZWJ or ZWSP)
+# that appear between the base bracket character and the nonspacing mark,
+# in a context where the brackets have been forced to a strong R direction.
+#
+# Note that due to an implementation error in the N0 rule in the Bidi Reference C
+# test code for UBA 8.0, versions of that reference test code through UBA 12.0 will fail for
+# precisely these newly added tests. The bug in the implementation of the N0 rule in the Bidi Reference C
+# test code was fixed for Unicode 13.0, and that updated test code now performs correctly
+# for all versions of UBA.
+#
+# These test cases first test a combining mark following a ZWJ after the trailing bracket of a pair:
+0041 200F 005B 05D0 005D 200D 20D6;0;0;0 1 1 1 1 x 1;0 6 4 3 2 1
+0041 200F 005B 05D0 005D 200D 20D6;1;1;2 1 1 1 1 x 1;6 4 3 2 1 0
+# Then a combining mark following a ZWJ after the leading bracket of a pair:
+0041 200F 005B 200D 20D6 05D0 005D;0;0;0 1 1 x 1 1 1;0 6 5 4 2 1
+0041 200F 005B 200D 20D6 05D0 005D;1;1;2 1 1 x 1 1 1;6 5 4 2 1 0
+# Then a combining mark following a ZWJ after both brackets of a pair:
+0041 200F 005B 200D 20D6 05D0 005D 200D 20D6;0;0;0 1 1 x 1 1 1 x 1;0 8 6 5 4 2 1
+0041 200F 005B 200D 20D6 05D0 005D 200D 20D6;1;1;2 1 1 x 1 1 1 x 1;8 6 5 4 2 1 0
+# Then the intervention of a ZWSP in these same sequences.
+# (The ZWSP formally breaks the combining character sequence, but should
+# not block the identification of the combining mark for the application of rule N0.)
+0041 200F 005B 200D 200B 20D6 05D0 005D 200B 200D 20D6;0;0;0 1 1 x x 1 1 1 x x 1;0 10 7 6 5 2 1
+0041 200F 005B 200D 200B 20D6 05D0 005D 200B 200D 20D6;1;1;2 1 1 x x 1 1 1 x x 1;10 7 6 5 2 1 0
+
# Nested bracket pairs that reach and exceed the fixed capacity of the bracket stack
# a ( ( ... ( b ) ) ... ) with 62, 63, and 64 nested bracket pairs
0061 0028 0028 0028 0028 0028 0028 0028 0028 0028 0028 0028 0028 0028 0028 0028 0028 0028 0028 0028 0028 0028 0028 0028 0028 0028 0028 0028 0028 0028 0028 0028 0028 0028 0028 0028 0028 0028 0028 0028 0028 0028 0028 0028 0028 0028 0028 0028 0028 0028 0028 0028 0028 0028 0028 0028 0028 0028 0028 0028 0028 0028 0028 0062 0029 0029 0029 0029 0029 0029 0029 0029 0029 0029 0029 0029 0029 0029 0029 0029 0029 0029 0029 0029 0029 0029 0029 0029 0029 0029 0029 0029 0029 0029 0029 0029 0029 0029 0029 0029 0029 0029 0029 0029 0029 0029 0029 0029 0029 0029 0029 0029 0029 0029 0029 0029 0029 0029 0029 0029 0029 0029 0029 0029 0029 0029;1;1;2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2;0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
diff --git a/test/manual/biditest.el b/test/manual/biditest.el
index 667e537d991..d7fa359bf8d 100644
--- a/test/manual/biditest.el
+++ b/test/manual/biditest.el
@@ -1,17 +1,19 @@
-;;; biditest.el --- test bidi reordering in GNU Emacs display engine.
+;;; biditest.el --- test bidi reordering in GNU Emacs display engine. -*- lexical-binding: t; -*-
-;; Copyright (C) 2013-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2022 Free Software Foundation, Inc.
;; Author: Eli Zaretskii
;; Maintainer: emacs-devel@gnu.org
;; Package: emacs
-;; This program is free software: you can redistribute it and/or modify
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
-;; This program is distributed in the hope that it will be useful,
+;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
@@ -34,7 +36,7 @@
INPUT-FILE should be in the format of the BidiCharacterTest.txt file
available from the Unicode site, as part of the UCD database, see
-http://www.unicode.org/Public/UCD/latest/ucd/BidiCharacterTest.txt.
+https://www.unicode.org/Public/UCD/latest/ucd/BidiCharacterTest.txt.
The resulting file should be viewed with `inhibit-bidi-mirroring' set to t."
(let ((output-buf (get-buffer-create "*biditest-output*"))
@@ -52,7 +54,7 @@ The resulting file should be viewed with `inhibit-bidi-mirroring' set to t."
(resolved-paragraph (match-string 3))
;; FIXME: Should compare LEVELS with what the display
;; engine actually produced.
- (levels (match-string 4))
+ ;;(levels (match-string 4))
(indices (match-string 5)))
(setq codes (split-string codes " ")
indices (split-string indices " "))
@@ -118,4 +120,6 @@ BidiCharacterTest.txt file."
(interactive)
(message "%s" (bidi-resolved-levels)))
-(define-key global-map [f8] 'bidi-levels)
+(define-key global-map [f8] #'bidi-levels)
+
+;;; biditest.el ends here
diff --git a/test/manual/cedet/cedet-utests.el b/test/manual/cedet/cedet-utests.el
index 19a144f2abb..b365908c639 100644
--- a/test/manual/cedet/cedet-utests.el
+++ b/test/manual/cedet/cedet-utests.el
@@ -1,8 +1,8 @@
-;;; cedet-utests.el --- Run all unit tests in the CEDET suite.
+;;; cedet-utests.el --- Run all unit tests in the CEDET suite. -*- lexical-binding: t; -*-
-;; Copyright (C) 2008-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2022 Free Software Foundation, Inc.
-;; Author: Eric M. Ludlam <eric@siege-engine.com>
+;; Author: Eric M. Ludlam <zappo@gnu.org>
;; This file is part of GNU Emacs.
@@ -26,6 +26,18 @@
;; into one command.
(require 'cedet)
+
+(defvar cedet-utest-directory
+ (let* ((C (file-name-directory (locate-library "cedet")))
+ (D (expand-file-name "../../test/manual/cedet/" C)))
+ D)
+ "Location of test files for this test suite.")
+
+(defvar cedet-utest-libs '("ede-tests"
+ "semantic-tests"
+ )
+ "List of test srcs that need to be loaded.")
+
;;; Code:
(defvar cedet-utest-test-alist
'(
@@ -34,30 +46,35 @@
;;
;; Test inversion
- ("inversion" . inversion-unit-test)
+ ;; ("inversion" . inversion-unit-test) ; moved to automated suite
;; EZ Image dumping.
("ezimage associations" . ezimage-image-association-dump)
- ("ezimage images" . ezimage-image-dump)
+ ("ezimage images" . (lambda ()
+ (ezimage-image-dump)
+ (kill-buffer "*Ezimage Images*")))
;; Pulse
("pulse interactive test" . (lambda () (pulse-test t)))
;; Files
- ("cedet file conversion" . cedet-files-utest)
+ ;; ("cedet file conversion" . cedet-files-utest) ; moved to automated suite
;;
;; EIEIO
;;
- ("eieio" . (lambda () (let ((lib (locate-library "eieio-tests.el"
- t)))
- (load-file lib))))
- ("eieio: browser" . eieio-browse)
+
+ ("eieio: browser" . (lambda ()
+ (eieio-browse)
+ (kill-buffer "*EIEIO OBJECT BROWSE*")))
("eieio: custom" . (lambda ()
(require 'eieio-custom)
- (customize-variable 'eieio-widget-test)))
+ (customize-variable 'eieio-widget-test)
+ (kill-buffer "*Customize Option: Eieio Widget Test*")
+ ))
("eieio: chart" . (lambda ()
- (if (cedet-utest-noninteractive)
+ (require 'chart)
+ (if noninteractive
(message " ** Skipping test in noninteractive mode.")
(chart-test-it-all))))
;;
@@ -71,24 +88,27 @@
;; SEMANTIC
;;
("semantic: lex spp table write" . semantic-lex-spp-write-utest)
- ("semantic: multi-lang parsing" . semantic-utest-main)
- ("semantic: C preprocessor" . semantic-utest-c)
- ("semantic: analyzer tests" . semantic-ia-utest)
+ ;;("semantic: multi-lang parsing" . semantic-utest-main)
+ ;;("semantic: C preprocessor" . semantic-utest-c) - Now in automated suite
+ ;;("semantic: analyzer tests" . semantic-ia-utest)
("semanticdb: data cache" . semantic-test-data-cache)
("semantic: throw-on-input" .
(lambda ()
- (if (cedet-utest-noninteractive)
+ (if noninteractive
(message " ** Skipping test in noninteractive mode.")
(semantic-test-throw-on-input))))
- ("semantic: gcc: output parse test" . semantic-gcc-test-output-parser)
+ ;;("semantic: gcc: output parse test" . semantic-gcc-test-output-parser) ; moved to automated suite
+
;;
;; SRECODE
;;
- ("srecode: fields" . srecode-field-utest)
- ("srecode: templates" . srecode-utest-template-output)
+
+ ;; TODO - fix the fields test
+ ;;("srecode: fields" . srecode-field-utest) ; moved to automated suite
+ ;;("srecode: templates" . srecode-utest-template-output)
("srecode: show maps" . srecode-get-maps)
- ("srecode: getset" . srecode-utest-getset-output)
+ ;;("srecode: getset" . srecode-utest-getset-output)
)
"Alist of all the tests in CEDET we should run.")
@@ -100,9 +120,11 @@
EXIT-ON-ERROR causes the test suite to exit on an error, instead
of just logging the error."
(interactive)
- (if (or (not (featurep 'semanticdb-mode))
- (not (semanticdb-minor-mode-p)))
- (error "CEDET Tests require: M-x semantic-load-enable-minimum-features"))
+ (unless (and (fboundp 'semanticdb-minor-mode-p)
+ (semanticdb-minor-mode-p))
+ (error "CEDET Tests require semantic-mode to be enabled"))
+ (dolist (L cedet-utest-libs)
+ (load-file (expand-file-name (concat L ".el") cedet-utest-directory)))
(cedet-utest-log-setup "ALL TESTS")
(let ((tl cedet-utest-test-alist)
(notes nil)
@@ -126,7 +148,7 @@ of just logging the error."
;; Cleanup stray input and events that are in the way.
;; Not doing this causes sit-for to not refresh the screen.
;; Doing this causes the user to need to press keys more frequently.
- (when (and (interactive-p) (input-pending-p))
+ (when (and (called-interactively-p 'interactive) (input-pending-p))
(if (fboundp 'read-event)
(read-event)
(read-char)))
@@ -145,18 +167,20 @@ of just logging the error."
(defun cedet-utest-noninteractive ()
"Return non-nil if running non-interactively."
- (if (featurep 'xemacs)
- (noninteractive)
- noninteractive))
+ (declare (obsolete nil "27.1"))
+ noninteractive)
+
+(defvar srecode-map-save-file)
;;;###autoload
(defun cedet-utest-batch ()
"Run the CEDET unit test in BATCH mode."
- (unless (cedet-utest-noninteractive)
+ (unless noninteractive
(error "`cedet-utest-batch' is to be used only with -batch"))
(condition-case err
(when (catch 'cedet-utest-exit-on-error
;; Get basic semantic features up.
+ ;; FIXME: I can't see any such function in our code!
(semantic-load-enable-minimum-features)
;; Disables all caches related to semantic DB so all
;; tests run as if we have bootstrapped CEDET for the
@@ -200,7 +224,7 @@ of just logging the error."
"Setup a frame and buffer for unit testing.
Optional argument TITLE is the title of this testing session."
(setq cedet-utest-log-timer (current-time))
- (if (cedet-utest-noninteractive)
+ (if noninteractive
(message "\n>> Setting up %s tests to run @ %s\n"
(or title "")
(current-time-string))
@@ -210,8 +234,7 @@ Optional argument TITLE is the title of this testing session."
(setq cedet-utest-frame (make-frame cedet-utest-frame-parameters)))
(when (or (not cedet-utest-buffer) (not (buffer-live-p cedet-utest-buffer)))
(setq cedet-utest-buffer (get-buffer-create "*CEDET utest log*")))
- (save-excursion
- (set-buffer cedet-utest-buffer)
+ (with-current-buffer cedet-utest-buffer
(setq cedet-utest-last-log-item nil)
(when (not cedet-running-master-tests)
(erase-buffer))
@@ -229,11 +252,9 @@ Optional argument TITLE is the title of this testing session."
(defun cedet-utest-elapsed-time (start end)
"Copied from elp.el. Was elp-elapsed-time.
Argument START and END bound the time being calculated."
- (+ (* (- (car end) (car start)) 65536.0)
- (- (car (cdr end)) (car (cdr start)))
- (/ (- (car (cdr (cdr end))) (car (cdr (cdr start)))) 1000000.0)))
+ (float-time (time-subtract start end)))
-(defun cedet-utest-log-shutdown (title &optional errorcondition)
+(defun cedet-utest-log-shutdown (title &optional _errorcondition)
"Shut-down a larger test suite.
TITLE is the section that is done.
ERRORCONDITION is some error that may have occurred during testing."
@@ -245,7 +266,7 @@ ERRORCONDITION is some error that may have occurred during testing."
(defun cedet-utest-log-shutdown-msg (title startime endtime)
"Show a shutdown message with TITLE, STARTIME, and ENDTIME."
- (if (cedet-utest-noninteractive)
+ (if noninteractive
(progn
(message "\n>> Test Suite %s ended at @ %s"
title
@@ -253,8 +274,7 @@ ERRORCONDITION is some error that may have occurred during testing."
(message " Elapsed Time %.2f Seconds\n"
(cedet-utest-elapsed-time startime endtime)))
- (save-excursion
- (set-buffer cedet-utest-buffer)
+ (with-current-buffer cedet-utest-buffer
(goto-char (point-max))
(insert "\n>> Test Suite " title " ended at @ "
(format-time-string "%c" endtime) "\n"
@@ -266,7 +286,7 @@ ERRORCONDITION is some error that may have occurred during testing."
(defun cedet-utest-show-log-end ()
"Show the end of the current unit test log."
- (unless (cedet-utest-noninteractive)
+ (unless noninteractive
(let* ((cb (current-buffer))
(cf (selected-frame))
(bw (or (get-buffer-window cedet-utest-buffer t)
@@ -282,14 +302,13 @@ ERRORCONDITION is some error that may have occurred during testing."
(defun cedet-utest-post-command-hook ()
"Hook run after the current log command was run."
- (if (cedet-utest-noninteractive)
+ (if noninteractive
(message "")
- (save-excursion
- (set-buffer cedet-utest-buffer)
+ (with-current-buffer cedet-utest-buffer
(goto-char (point-max))
(insert "\n\n")))
(setq cedet-utest-last-log-item nil)
- (remove-hook 'post-command-hook 'cedet-utest-post-command-hook)
+ (remove-hook 'post-command-hook #'cedet-utest-post-command-hook)
)
(defun cedet-utest-add-log-item-start (item)
@@ -297,12 +316,11 @@ ERRORCONDITION is some error that may have occurred during testing."
(unless (equal item cedet-utest-last-log-item)
(setq cedet-utest-last-log-item item)
;; This next line makes sure we clear out status during logging.
- (add-hook 'post-command-hook 'cedet-utest-post-command-hook)
+ (add-hook 'post-command-hook #'cedet-utest-post-command-hook)
- (if (cedet-utest-noninteractive)
+ (if noninteractive
(message " - Running %s ..." item)
- (save-excursion
- (set-buffer cedet-utest-buffer)
+ (with-current-buffer cedet-utest-buffer
(goto-char (point-max))
(when (not (bolp)) (insert "\n"))
(insert "Running " item " ... ")
@@ -316,14 +334,13 @@ ERRORCONDITION is some error that may have occurred during testing."
Apply NOTES to the doneness of the log.
Apply ERR if there was an error in previous item.
Optional argument PRECR indicates to prefix the done msg w/ a newline."
- (if (cedet-utest-noninteractive)
+ (if noninteractive
;; Non-interactive-mode - show a message.
(if notes
(message " * %s {%s}" (or err "done") notes)
(message " * %s" (or err "done")))
;; Interactive-mode - insert into the buffer.
- (save-excursion
- (set-buffer cedet-utest-buffer)
+ (with-current-buffer cedet-utest-buffer
(goto-char (point-max))
(when precr (insert "\n"))
(if err
@@ -353,132 +370,42 @@ Optional argument PRECR indicates to prefix the done msg w/ a newline."
(cedet-utest-add-log-item-start testname)
))
-(defun cedet-utest-log(format &rest args)
+(defun cedet-utest-log (format &rest args)
"Log the text string FORMAT.
The rest of the ARGS are used to fill in FORMAT with `format'."
- (if (cedet-utest-noninteractive)
- (apply 'message format args)
- (save-excursion
- (set-buffer cedet-utest-buffer)
+ (if noninteractive
+ (apply #'message format args)
+ (with-current-buffer cedet-utest-buffer
(goto-char (point-max))
(when (not (bolp)) (insert "\n"))
- (insert (apply 'format format args))
+ (insert (apply #'format format args))
(insert "\n")
(sit-for 0)
))
(cedet-utest-show-log-end)
)
-;;; Inversion tests
-
-(defun inversion-unit-test ()
- "Test inversion to make sure it can identify different version strings."
- (interactive)
- (let ((c1 (inversion-package-version 'inversion))
- (c1i (inversion-package-incompatibility-version 'inversion))
- (c2 (inversion-decode-version "1.3alpha2"))
- (c3 (inversion-decode-version "1.3beta4"))
- (c4 (inversion-decode-version "1.3 beta5"))
- (c5 (inversion-decode-version "1.3.4"))
- (c6 (inversion-decode-version "2.3alpha"))
- (c7 (inversion-decode-version "1.3"))
- (c8 (inversion-decode-version "1.3pre1"))
- (c9 (inversion-decode-version "2.4 (patch 2)"))
- (c10 (inversion-decode-version "2.4 (patch 3)"))
- (c11 (inversion-decode-version "2.4.2.1"))
- (c12 (inversion-decode-version "2.4.2.2"))
- )
- (if (not (and
- (inversion-= c1 c1)
- (inversion-< c1i c1)
- (inversion-< c2 c3)
- (inversion-< c3 c4)
- (inversion-< c4 c5)
- (inversion-< c5 c6)
- (inversion-< c2 c4)
- (inversion-< c2 c5)
- (inversion-< c2 c6)
- (inversion-< c3 c5)
- (inversion-< c3 c6)
- (inversion-< c7 c6)
- (inversion-< c4 c7)
- (inversion-< c2 c7)
- (inversion-< c8 c6)
- (inversion-< c8 c7)
- (inversion-< c4 c8)
- (inversion-< c2 c8)
- (inversion-< c9 c10)
- (inversion-< c10 c11)
- (inversion-< c11 c12)
- ;; Negatives
- (not (inversion-< c3 c2))
- (not (inversion-< c4 c3))
- (not (inversion-< c5 c4))
- (not (inversion-< c6 c5))
- (not (inversion-< c7 c2))
- (not (inversion-< c7 c8))
- (not (inversion-< c12 c11))
- ;; Test the tester on inversion
- (not (inversion-test 'inversion inversion-version))
- ;; Test that we throw an error
- (inversion-test 'inversion "0.0.0")
- (inversion-test 'inversion "1000.0")
- ))
- (error "Inversion tests failed")
- (message "Inversion tests passed."))))
-
-;;; cedet-files unit test
-
-(defvar cedet-files-utest-list
- '(
- ( "/home/me/src/myproj/src/foo.c" . "!home!me!src!myproj!src!foo.c" )
- ( "c:/work/myproj/foo.el" . "!drive_c!work!myproj!foo.el" )
- ( "//windows/proj/foo.java" . "!!windows!proj!foo.java" )
- ( "/home/me/proj!bang/foo.c" . "!home!me!proj!!bang!foo.c" )
- )
- "List of different file names to test.
-Each entry is a cons cell of ( FNAME . CONVERTED )
-where FNAME is some file name, and CONVERTED is what it should be
-converted into.")
-
-(defun cedet-files-utest ()
- "Test out some file name conversions."
- (interactive)
- (let ((idx 0))
- (dolist (FT cedet-files-utest-list)
-
- (setq idx (+ idx 1))
-
- (let ((dir->file (cedet-directory-name-to-file-name (car FT) t))
- (file->dir (cedet-file-name-to-directory-name (cdr FT) t))
- )
-
- (unless (string= (cdr FT) dir->file)
- (error "Failed: %d. Found: %S Wanted: %S"
- idx dir->file (cdr FT))
- )
-
- (unless (string= file->dir (car FT))
- (error "Failed: %d. Found: %S Wanted: %S"
- idx file->dir (car FT)))))))
-
;;; pulse test
(defun pulse-test (&optional no-error)
"Test the lightening function for pulsing a line.
When optional NO-ERROR don't throw an error if we can't run tests."
(interactive)
- (if (or (not pulse-flag) (not (pulse-available-p)))
+ (if (not (and (bound-and-true-p pulse-flag)
+ (fboundp 'pulse-available-p)
+ (pulse-available-p)))
(if no-error
nil
(error (concat "Pulse test only works on versions of Emacs"
" that support pulsing")))
+ (declare-function pulse-momentary-highlight-overlay
+ "pulse.el" (o &optional face))
;; Run the tests
- (when (interactive-p)
+ (when (called-interactively-p 'interactive)
(message "<Press a key> Pulse one line.")
(read-char))
(pulse-momentary-highlight-one-line (point))
- (when (interactive-p)
+ (when (called-interactively-p 'interactive)
(message "<Press a key> Pulse a region.")
(read-char))
(pulse-momentary-highlight-region (point)
@@ -487,11 +414,11 @@ When optional NO-ERROR don't throw an error if we can't run tests."
(forward-char 30)
(error nil))
(point)))
- (when (interactive-p)
+ (when (called-interactively-p 'interactive)
(message "<Press a key> Pulse line a specific color.")
(read-char))
- (pulse-momentary-highlight-one-line (point) 'modeline)
- (when (interactive-p)
+ (pulse-momentary-highlight-one-line (point) 'mode-line)
+ (when (called-interactively-p 'interactive)
(message "<Press a key> Pulse a pre-existing overlay.")
(read-char))
(let* ((start (point-at-bol))
@@ -507,7 +434,7 @@ When optional NO-ERROR don't throw an error if we can't run tests."
(delete-overlay o)
(error "Non-temporary overlay was deleted!"))
)
- (when (interactive-p)
+ (when (called-interactively-p 'interactive)
(message "Done!"))))
(provide 'cedet-utests)
diff --git a/test/manual/cedet/ede-tests.el b/test/manual/cedet/ede-tests.el
index e24bdf7f9f0..c23e0984816 100644
--- a/test/manual/cedet/ede-tests.el
+++ b/test/manual/cedet/ede-tests.el
@@ -1,8 +1,8 @@
-;;; ede-tests.el --- Some tests for the Emacs Development Environment
+;;; ede-tests.el --- Some tests for the Emacs Development Environment -*- lexical-binding: t -*-
-;; Copyright (C) 2008-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2022 Free Software Foundation, Inc.
-;; Author: Eric M. Ludlam <eric@siege-engine.com>
+;; Author: Eric M. Ludlam <zappo@gnu.org>
;; This file is part of GNU Emacs.
@@ -42,8 +42,7 @@ The search is done with the current EDE root."
(ede-toplevel)))))
(data-debug-new-buffer "*EDE Locate ADEBUG*")
(ede-locate-file-in-project loc file)
- (data-debug-insert-object-slots loc "]"))
- )
+ (data-debug-insert-object-slots loc "]")))
(defun ede-locate-test-global (file)
"Test EDE Locate on FILE using GNU Global type.
@@ -55,8 +54,7 @@ The search is done with the current EDE root."
(ede-toplevel)))))
(data-debug-new-buffer "*EDE Locate ADEBUG*")
(ede-locate-file-in-project loc file)
- (data-debug-insert-object-slots loc "]"))
- )
+ (data-debug-insert-object-slots loc "]")))
(defun ede-locate-test-idutils (file)
"Test EDE Locate on FILE using ID Utils type.
@@ -68,8 +66,7 @@ The search is done with the current EDE root."
(ede-toplevel)))))
(data-debug-new-buffer "*EDE Locate ADEBUG*")
(ede-locate-file-in-project loc file)
- (data-debug-insert-object-slots loc "]"))
- )
+ (data-debug-insert-object-slots loc "]")))
(defun ede-locate-test-cscope (file)
"Test EDE Locate on FILE using CScope type.
@@ -81,7 +78,6 @@ The search is done with the current EDE root."
(ede-toplevel)))))
(data-debug-new-buffer "*EDE Locate ADEBUG*")
(ede-locate-file-in-project loc file)
- (data-debug-insert-object-slots loc "]"))
- )
+ (data-debug-insert-object-slots loc "]")))
-;;; ede-test.el ends here
+;;; ede-tests.el ends here
diff --git a/test/manual/cedet/semantic-tests.el b/test/manual/cedet/semantic-tests.el
index 3a19328ac79..dcdeb45b0a3 100644
--- a/test/manual/cedet/semantic-tests.el
+++ b/test/manual/cedet/semantic-tests.el
@@ -1,6 +1,6 @@
-;;; semantic-utest.el --- Miscellaneous Semantic tests.
+;;; semantic-tests.el --- Miscellaneous Semantic tests. -*- lexical-binding: t; -*-
-;;; Copyright (C) 2003-2004, 2007-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2022 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
@@ -24,6 +24,8 @@
;; Originally, there are many test functions scattered among the
;; Semantic source files. This file consolidates them.
+;;; Code:
+
(require 'data-debug)
;;; From semantic-complete
@@ -46,7 +48,7 @@
All systems are different. Ask questions along the way."
(interactive)
(let ((doload nil))
- (when (y-or-n-p "Create a system database to test with? ")
+ (when (y-or-n-p "Create a system database to test with?")
(call-interactively 'semanticdb-create-ebrowse-database)
(setq doload t))
;; Should we load in caches
@@ -64,10 +66,12 @@ run the test again")))
"Find the first loaded ebrowse table, and dump out the contents."
(interactive)
(let ((db semanticdb-database-list)
- (ab nil))
+ ;; (ab nil)
+ )
(while db
(when (semanticdb-project-database-ebrowse-p (car db))
- (setq ab (data-debug-new-buffer "*EBROWSE Database*"))
+ ;; (setq ab
+ (data-debug-new-buffer "*EBROWSE Database*") ;;)
(data-debug-insert-thing (car db) "*" "")
(setq db nil)
)
@@ -100,7 +104,7 @@ If optional arg STANDARDFILE is non-nil, use a standard file w/ global enabled."
(set-buffer (find-file-noselect semanticdb-test-gnu-global-startfile)))
(semanticdb-enable-gnu-global-in-buffer))))
- (let* ((db (semanticdb-project-database-global "global"))
+ (let* ((db (semanticdb-project-database-global)) ;; "global"
(tab (semanticdb-file-table db (buffer-file-name)))
(result (semanticdb-deep-find-tags-for-completion-method tab searchfor))
)
@@ -127,8 +131,7 @@ Optional argument ARG specifies not to use color."
(princ (car fns))
(princ ":\n ")
(let ((s (funcall (car fns) tag par (not arg))))
- (save-excursion
- (set-buffer "*format-tag*")
+ (with-current-buffer "*format-tag*"
(goto-char (point-max))
(insert s)))
(setq fns (cdr fns))))
@@ -138,21 +141,6 @@ Optional argument ARG specifies not to use color."
(require 'semantic/fw)
-(defun semantic-test-data-cache ()
- "Test the data cache."
- (interactive)
- (let ((data '(a b c)))
- (save-excursion
- (set-buffer (get-buffer-create " *semantic-test-data-cache*"))
- (erase-buffer)
- (insert "The Moose is Loose")
- (goto-char (point-min))
- (semantic-cache-data-to-buffer (current-buffer) (point) (+ (point) 5)
- data 'moose 'exit-cache-zone)
- (if (equal (semantic-get-cache-data 'moose) data)
- (message "Successfully retrieved cached data.")
- (error "Failed to retrieve cached data")))))
-
(defun semantic-test-throw-on-input ()
"Test that throw on input will work."
(interactive)
@@ -178,9 +166,8 @@ Optional argument ARG specifies not to use color."
"Test `semantic-idle-scheduler-work-parse-neighboring-files' and time it."
(interactive)
(let ((start (current-time))
- (junk (semantic-idle-scheduler-work-parse-neighboring-files))
- (end (current-time)))
- (message "Work took %.2f seconds." (semantic-elapsed-time start end))))
+ (_junk (semantic-idle-scheduler-work-parse-neighboring-files)))
+ (message "Work took %.2f seconds." (semantic-elapsed-time start nil))))
;;; From semantic-lex:
@@ -195,10 +182,9 @@ If universal argument ARG, then try the whole buffer."
(result (semantic-lex
(if arg (point-min) (point))
(point-max)
- 100))
- (end (current-time)))
+ 100)))
(message "Elapsed Time: %.2f seconds."
- (semantic-elapsed-time start end))
+ (semantic-elapsed-time start nil))
(pop-to-buffer "*Lexer Output*")
(require 'pp)
(erase-buffer)
@@ -227,16 +213,21 @@ Analyze the area between BEG and END."
(semantic-lex-spp-table-write-slot-value
(semantic-lex-spp-save-table))))
+(defvar cedet-utest-directory) ;From test/manual/cedet/cedet-utests.el?
+
(defun semantic-lex-spp-write-utest ()
"Unit test using the test spp file to test the slot write fcn."
(interactive)
- (let* ((sem (locate-library "semantic-lex-spp.el"))
- (dir (file-name-directory sem)))
- (save-excursion
- (set-buffer (find-file-noselect
- (expand-file-name "tests/testsppreplace.c"
- dir)))
- (semantic-lex-spp-write-test))))
+ (save-excursion
+ (let ((buff (find-file-noselect
+ (expand-file-name "tests/testsppreplace.c"
+ cedet-utest-directory))))
+ (set-buffer buff)
+ (semantic-lex-spp-write-test)
+ (kill-buffer buff)
+ (when (not (called-interactively-p 'interactive))
+ (kill-buffer "*SPP Write Test*"))
+ )))
;;; From semantic-tag-write:
@@ -272,118 +263,13 @@ tag that contains point, and return that."
(Lcount 0))
(when (semantic-tag-p target)
(semantic-symref-hits-in-region
- target (lambda (start end prefix) (setq Lcount (1+ Lcount)))
+ target (lambda (_start _end _prefix) (setq Lcount (1+ Lcount)))
(semantic-tag-start tag)
(semantic-tag-end tag))
- (when (interactive-p)
+ (when (called-interactively-p 'interactive)
(message "Found %d occurrences of %s in %.2f seconds"
Lcount (semantic-tag-name target)
- (semantic-elapsed-time start (current-time))))
+ (semantic-elapsed-time start nil)))
Lcount)))
-;;; From bovine-gcc:
-
-(require 'semantic/bovine/gcc)
-
-;; Example output of "gcc -v"
-(defvar semantic-gcc-test-strings
- '(;; My old box:
- "Reading specs from /usr/lib/gcc-lib/i386-redhat-linux/3.2.2/specs
-Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --disable-checking --with-system-zlib --enable-__cxa_atexit --host=i386-redhat-linux
-Thread model: posix
-gcc version 3.2.2 20030222 (Red Hat Linux 3.2.2-5)"
- ;; Alex Ott:
- "Using built-in specs.
-Target: i486-linux-gnu
-Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.3.1-9ubuntu1' --with-bugurl=file:///usr/share/doc/gcc-4.3/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --enable-nls --with-gxx-include-dir=/usr/include/c++/4.3 --program-suffix=-4.3 --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --enable-mpfr --enable-targets=all --enable-checking=release --build=i486-linux-gnu --host=i486-linux-gnu --target=i486-linux-gnu
-Thread model: posix
-gcc version 4.3.1 (Ubuntu 4.3.1-9ubuntu1)"
- ;; My debian box:
- "Using built-in specs.
-Target: x86_64-unknown-linux-gnu
-Configured with: ../../../sources/gcc/configure --prefix=/usr/local/glibc-2.3.6/x86_64/apps/gcc-4.2.3 --with-gmp=/usr/local/gcc/gmp --with-mpfr=/usr/local/gcc/mpfr --enable-languages=c,c++,fortran --with-as=/usr/local/glibc-2.3.6/x86_64/apps/gcc-4.2.3/bin/as --with-ld=/usr/local/glibc-2.3.6/x86_64/apps/gcc-4.2.3/bin/ld --disable-multilib
-Thread model: posix
-gcc version 4.2.3"
- ;; My mac:
- "Using built-in specs.
-Target: i686-apple-darwin8
-Configured with: /private/var/tmp/gcc/gcc-5341.obj~1/src/configure --disable-checking -enable-werror --prefix=/usr --mandir=/share/man --enable-languages=c,objc,c++,obj-c++ --program-transform-name=/^[cg][^.-]*$/s/$/-4.0/ --with-gxx-include-dir=/include/c++/4.0.0 --with-slibdir=/usr/lib --build=powerpc-apple-darwin8 --with-arch=pentium-m --with-tune=prescott --program-prefix= --host=i686-apple-darwin8 --target=i686-apple-darwin8
-Thread model: posix
-gcc version 4.0.1 (Apple Computer, Inc. build 5341)"
- ;; Ubuntu Intrepid
- "Using built-in specs.
-Target: x86_64-linux-gnu
-Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.3.2-1ubuntu12' --with-bugurl=file:///usr/share/doc/gcc-4.3/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --enable-nls --with-gxx-include-dir=/usr/include/c++/4.3 --program-suffix=-4.3 --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --enable-mpfr --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
-Thread model: posix
-gcc version 4.3.2 (Ubuntu 4.3.2-1ubuntu12)"
- ;; Red Hat EL4
- "Reading specs from /usr/lib/gcc/x86_64-redhat-linux/3.4.6/specs
-Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --disable-checking --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-java-awt=gtk --host=x86_64-redhat-linux
-Thread model: posix
-gcc version 3.4.6 20060404 (Red Hat 3.4.6-10)"
- ;; Red Hat EL5
- "Using built-in specs.
-Target: x86_64-redhat-linux
-Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-libgcj-multifile --enable-languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk --disable-dssi --enable-plugin --with-java-home=/usr/lib/jvm/java-1.4.2-gcj-1.4.2.0/jre --with-cpu=generic --host=x86_64-redhat-linux
-Thread model: posix
-gcc version 4.1.2 20080704 (Red Hat 4.1.2-44)"
- ;; David Engster's german gcc on ubuntu 4.3
- "Es werden eingebaute Spezifikationen verwendet.
-Ziel: i486-linux-gnu
-Konfiguriert mit: ../src/configure -v --with-pkgversion='Ubuntu 4.3.2-1ubuntu12' --with-bugurl=file:///usr/share/doc/gcc-4.3/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --enable-nls --with-gxx-include-dir=/usr/include/c++/4.3 --program-suffix=-4.3 --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --enable-mpfr --enable-targets=all --enable-checking=release --build=i486-linux-gnu --host=i486-linux-gnu --target=i486-linux-gnu
-Thread-Modell: posix
-gcc-Version 4.3.2 (Ubuntu 4.3.2-1ubuntu12)"
- ;; Damien Deville bsd
- "Using built-in specs.
-Target: i386-undermydesk-freebsd
-Configured with: FreeBSD/i386 system compiler
-Thread model: posix
-gcc version 4.2.1 20070719 [FreeBSD]"
- )
- "A bunch of sample gcc -v outputs from different machines.")
-
-(defvar semantic-gcc-test-strings-fail
- '(;; A really old solaris box I found
- "Reading specs from /usr/local/gcc-2.95.2/lib/gcc-lib/sparc-sun-solaris2.6/2.95.2/specs
-gcc version 2.95.2 19991024 (release)"
- )
- "A bunch of sample gcc -v outputs that fail to provide the info we want.")
-
-(defun semantic-gcc-test-output-parser ()
- "Test the output parser against some collected strings."
- (interactive)
- (let ((fail nil))
- (dolist (S semantic-gcc-test-strings)
- (let* ((fields (semantic-gcc-fields S))
- (v (cdr (assoc 'version fields)))
- (h (or (cdr (assoc 'target fields))
- (cdr (assoc '--target fields))
- (cdr (assoc '--host fields))))
- (p (cdr (assoc '--prefix fields)))
- )
- ;; No longer test for prefixes.
- (when (not (and v h))
- (let ((strs (split-string S "\n")))
- (message "Test failed on %S\nV H P:\n%S %S %S" (car strs) v h p))
- (setq fail t))
- ))
- (dolist (S semantic-gcc-test-strings-fail)
- (let* ((fields (semantic-gcc-fields S))
- (v (cdr (assoc 'version fields)))
- (h (or (cdr (assoc '--host fields))
- (cdr (assoc 'target fields))))
- (p (cdr (assoc '--prefix fields)))
- )
- (when (and v h p)
- (message "Negative test failed on %S" S)
- (setq fail t))
- ))
- (if (not fail) (message "Tests passed."))
- ))
-
-(defun semantic-gcc-test-output-parser-this-machine ()
- "Test the output parser against the machine currently running Emacs."
- (interactive)
- (let ((semantic-gcc-test-strings (list (semantic-gcc-query "gcc" "-v"))))
- (semantic-gcc-test-output-parser))
- )
+;;; semantic-tests.el ends here
diff --git a/test/manual/cedet/semantic-utest-c.el b/test/manual/cedet/semantic-utest-c.el
deleted file mode 100644
index 6adfb1f2144..00000000000
--- a/test/manual/cedet/semantic-utest-c.el
+++ /dev/null
@@ -1,72 +0,0 @@
-;;; semantic-utest-c.el --- C based parsing tests.
-
-;; Copyright (C) 2008-2017 Free Software Foundation, Inc.
-
-;; Author: Eric M. Ludlam <eric@siege-engine.com>
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software: you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation, either version 3 of the License, or
-;; (at your option) any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
-
-;;; Commentary:
-;;
-;; Run some C based parsing tests.
-
-(require 'semantic)
-
-(defvar semantic-utest-c-comparisons
- '( ("testsppreplace.c" . "testsppreplaced.c")
- )
- "List of files to parse and compare against each other.")
-
-;;; Code:
-;;;###autoload
-(defun semantic-utest-c ()
- "Run parsing test for C from the test directory."
- (interactive)
- (dolist (fp semantic-utest-c-comparisons)
- (let* ((sem (locate-library "semantic"))
- (sdir (file-name-directory sem))
- (semantic-lex-c-nested-namespace-ignore-second nil)
- (tags-actual
- (save-excursion
- (set-buffer (find-file-noselect (expand-file-name (concat "tests/" (car fp)) sdir)))
- (semantic-clear-toplevel-cache)
- (semantic-fetch-tags)))
- (tags-expected
- (save-excursion
- (set-buffer (find-file-noselect (expand-file-name (concat "tests/" (cdr fp)) sdir)))
- (semantic-clear-toplevel-cache)
- (semantic-fetch-tags))))
- ;; Now that we have the tags, compare them for SPP accuracy.
- (dolist (tag tags-actual)
- (if (and (semantic-tag-of-class-p tag 'variable)
- (semantic-tag-variable-constant-p tag))
- nil ; skip the macros.
- (if (semantic-tag-similar-with-subtags-p tag (car tags-expected))
- (setq tags-expected (cdr tags-expected))
- (with-mode-local c-mode
- (error "Found: >> %s << Expected: >> %s <<"
- (semantic-format-tag-prototype tag nil t)
- (semantic-format-tag-prototype (car tags-expected) nil t)
- )))
- ))
- ;; Passed?
- (message "PASSED!")
- )))
-
-
-(provide 'semantic-utest-c)
-
-;;; semantic-utest-c.el ends here
diff --git a/test/manual/cedet/tests/test.c b/test/manual/cedet/tests/test.c
index c5958c4cbac..6efaa8a75eb 100644
--- a/test/manual/cedet/tests/test.c
+++ b/test/manual/cedet/tests/test.c
@@ -1,8 +1,8 @@
/* test.c --- Semantic unit test for C.
- Copyright (C) 2001-2017 Free Software Foundation, Inc.
+ Copyright (C) 2001-2022 Free Software Foundation, Inc.
- Author: Eric M. Ludlam <eric@siege-engine.com>
+ Author: Eric M. Ludlam <zappo@gnu.org>
This file is part of GNU Emacs.
diff --git a/test/manual/cedet/tests/test.el b/test/manual/cedet/tests/test.el
index 299bea0bd5d..a523438f68f 100644
--- a/test/manual/cedet/tests/test.el
+++ b/test/manual/cedet/tests/test.el
@@ -1,8 +1,8 @@
-;;; test.el --- Unit test file for Semantic Emacs Lisp support.
+;;; test.el --- Unit test file for Semantic Emacs Lisp support. -*- lexical-binding: t -*-
-;; Copyright (C) 2005-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2005-2022 Free Software Foundation, Inc.
-;; Author: Eric M. Ludlam <eric@siege-engine.com>
+;; Author: Eric M. Ludlam <zappo@gnu.org>
;; This file is part of GNU Emacs.
@@ -19,31 +19,29 @@
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
-;;; Require
-;;
+;;; Code:
+
(require 'semantic)
(require 'eieio "../eieio")
;; tags encapsulated in eval-when-compile and eval-and-compile
;; should be expanded out into the outer environment.
(eval-when-compile
- (require 'semantic-imenu)
- )
+ (require 'semantic-imenu))
(eval-and-compile
(defconst const-1 nil)
(defun function-1 (arg)
- nil)
- )
+ nil))
;;; Functions
;;
(defun a-defun (arg1 arg2 &optional arg3)
- "doc a"
+ "Doc a."
nil)
(defun a-defun-interactive (arg1 arg2 &optional arg3)
- "doc a that is a command"
+ "Doc a that is a command."
(interactive "R")
nil)
@@ -52,24 +50,24 @@
nil)
(defsubst a-defsubst (arg1 arg2 &optional arg3)
- "doc a-subst"
+ "Doc a-subst."
nil)
(defmacro a-defmacro (arg1 arg2 &optional arg3)
- "doc a-macro"
+ "Doc a-macro."
nil)
(define-overload a-overload (arg)
- "doc a-overload"
+ "Doc a-overload."
nil)
;;; Methods
;;
-(defmethod a-method ((obj some-class) &optional arg2)
+(cl-defmethod a-method ((obj some-class) &optional arg2)
"Doc String for a method."
(call-next-method))
-(defgeneric a-generic (arg1 arg2)
+(cl-defgeneric a-generic (arg1 arg2)
"General description of a-generic.")
;;; Advice
@@ -81,15 +79,16 @@
;;; Variables
;;
(defvar a-defvar (cons 1 2)
- "Variable a")
+ "Variable a.")
+;; FIXME: This practice is not recommended in recent Emacs. Remove?
(defvar a-defvar-star (cons 1 2)
- "*User visible var a")
+ "*User visible var a.")
-(defconst a-defconst 'a "var doc const")
+(defconst a-defconst 'a "Var doc const.")
(defcustom a-defcustom nil
- "doc custom"
+ "Doc custom."
:group 'a-defgroup
:type 'boolean)
@@ -110,7 +109,7 @@
(defgroup a-defgroup nil
- "Group for `emacs-lisp' regression-test")
+ "Group for `emacs-lisp' regression-test.")
;;; Classes
;;
@@ -152,7 +151,6 @@
(defvar-mode-local emacs-lisp-mode a-mode-local-def
"some value")
-
-;;; Provide
-;;
(provide 'test)
+
+;;; test.el ends here
diff --git a/test/manual/cedet/tests/test.make b/test/manual/cedet/tests/test.make
index ff169576f7c..80c0c8051c4 100644
--- a/test/manual/cedet/tests/test.make
+++ b/test/manual/cedet/tests/test.make
@@ -1,8 +1,8 @@
# test.make --- Semantic unit test for Make -*- makefile -*-
-# Copyright (C) 2001-2002, 2010-2017 Free Software Foundation, Inc.
+# Copyright (C) 2001-2002, 2010-2022 Free Software Foundation, Inc.
-# Author: Eric M. Ludlam <eric@siege-engine.com>
+# Author: Eric M. Ludlam <zappo@gnu.org>
# This file is part of GNU Emacs.
diff --git a/test/manual/cedet/tests/testnsp.cpp b/test/manual/cedet/tests/testnsp.cpp
deleted file mode 100644
index 012dc660600..00000000000
--- a/test/manual/cedet/tests/testnsp.cpp
+++ /dev/null
@@ -1,29 +0,0 @@
-// Test NSP (Name space parent)
-//
-// Test dereferencing parents based on local parent scope.
-//
-// Derived from data David Engster provided.
-
-namespace nsp {
-
- class rootclass {
- public:
- int fromroot() {};
- };
-
-}
-
-namespace nsp {
- class childclass : public rootclass {
- public:
- int fromchild() {};
- };
-}
-
-void myfcn_not_in_ns (void) {
- nsp::childclass test;
-
- test.// -1-
- ; // #1# ( "fromchild" "fromroot" )
-}
-
diff --git a/test/manual/cedet/tests/testpolymorph.cpp b/test/manual/cedet/tests/testpolymorph.cpp
index 86bc75c6f27..ba64e39a7a5 100644
--- a/test/manual/cedet/tests/testpolymorph.cpp
+++ b/test/manual/cedet/tests/testpolymorph.cpp
@@ -1,8 +1,8 @@
/** testpolymorph.cpp --- A sequence of polymorphism examples.
*
- * Copyright (C) 2009-2017 Free Software Foundation, Inc.
+ * Copyright (C) 2009-2022 Free Software Foundation, Inc.
*
- * Author: Eric M. Ludlam <eric@siege-engine.com>
+ * Author: Eric M. Ludlam <zappo@gnu.org>
*
* This file is part of GNU Emacs.
*
diff --git a/test/manual/cedet/tests/testspp.c b/test/manual/cedet/tests/testspp.c
index dc8f4a54bae..74b336172cd 100644
--- a/test/manual/cedet/tests/testspp.c
+++ b/test/manual/cedet/tests/testspp.c
@@ -1,8 +1,8 @@
/* testspp.cpp --- Semantic unit test for the C preprocessor
- Copyright (C) 2007-2017 Free Software Foundation, Inc.
+ Copyright (C) 2007-2022 Free Software Foundation, Inc.
- Author: Eric M. Ludlam <eric@siege-engine.com>
+ Author: Eric M. Ludlam <zappo@gnu.org>
This file is part of GNU Emacs.
diff --git a/test/manual/cedet/tests/testsppcomplete.c b/test/manual/cedet/tests/testsppcomplete.c
deleted file mode 100644
index d7899942285..00000000000
--- a/test/manual/cedet/tests/testsppcomplete.c
+++ /dev/null
@@ -1,30 +0,0 @@
-/* Example provided by Hannes Janetzek */
-
-struct Test { int test; };
-
-#define BLA(_type) \
- _type *bla = (_type*) malloc(sizeof(_type));
-
-#define BLUB(_type) \
- (_type*)malloc(sizeof(_type));
-
-#define FOO(_type) \
- _type *foo = BLUB(_type);
-
-#define BAR(_type) \
- _type *bar = (*_type)BLUB(_type);
-
-int main(int argc, char *argv[]) {
- BLA(Test);
- bla->// -1-
- ; // #1# ( "test" )
-
- FOO(Test);
- foo->// -2-
- ; // #2# ( "test" )
-
- BAR(Test);
- bar->// -3-
- ; // #3# ( "test" )
-}
-
diff --git a/test/manual/cedet/tests/testsppreplace.c b/test/manual/cedet/tests/testsppreplace.c
index 5c63a09a368..54ae3f0323e 100644
--- a/test/manual/cedet/tests/testsppreplace.c
+++ b/test/manual/cedet/tests/testsppreplace.c
@@ -1,7 +1,7 @@
/* testsppreplace.c --- unit test for CPP/SPP Replacement
- Copyright (C) 2007-2017 Free Software Foundation, Inc.
+ Copyright (C) 2007-2022 Free Software Foundation, Inc.
- Author: Eric M. Ludlam <eric@siege-engine.com>
+ Author: Eric M. Ludlam <zappo@gnu.org>
This file is part of GNU Emacs.
diff --git a/test/manual/cedet/tests/testsppreplaced.c b/test/manual/cedet/tests/testsppreplaced.c
index f60be8bcfb2..c359fa7d690 100644
--- a/test/manual/cedet/tests/testsppreplaced.c
+++ b/test/manual/cedet/tests/testsppreplaced.c
@@ -1,7 +1,7 @@
/* testsppreplaced.c --- unit test for CPP/SPP Replacement
- Copyright (C) 2007-2017 Free Software Foundation, Inc.
+ Copyright (C) 2007-2022 Free Software Foundation, Inc.
- Author: Eric M. Ludlam <eric@siege-engine.com>
+ Author: Eric M. Ludlam <zappo@gnu.org>
This file is part of GNU Emacs.
diff --git a/test/manual/etags/CTAGS.good b/test/manual/etags/CTAGS.good
index 519315c6fdd..84a56b23cfa 100644
--- a/test/manual/etags/CTAGS.good
+++ b/test/manual/etags/CTAGS.good
@@ -759,6 +759,7 @@ Install_Abort_Handler/p ada-src/2ataspri.ads /^ procedure Install_Abort_Handle
Install_Error_Handler/p ada-src/2ataspri.adb /^ procedure Install_Error_Handler (Handler : Syst/
Install_Error_Handler/p ada-src/2ataspri.ads /^ procedure Install_Error_Handler (Handler : Syst/
Invoking gzip tex-src/gzip.texi /^@node Invoking gzip, Advanced usage, Sample, Top$/
+IpAddrKind rs-src/test.rs 3
IsControlChar pas-src/common.pas /^function IsControlChar; (*($/
IsControlCharName pas-src/common.pas /^function IsControlCharName($/
Is_Set/f ada-src/2ataspri.adb /^ function Is_Set (Cell : in TAS_Cell) return Bo/
@@ -984,6 +985,7 @@ MoveLayerBottom lua-src/allegro.lua /^function MoveLayerBottom ()$/
MoveLayerTop lua-src/allegro.lua /^function MoveLayerTop ()$/
Mtest.go go-src/test.go 1
Mtest.go go-src/test.go /^func main() {$/
+Mtest.rs rs-src/test.rs /^fn main() {$/
Mtest1.go go-src/test1.go 1
Mtest1.go go-src/test1.go /^func main() {$/
Mx.cc cp-src/x.cc /^main(int argc, char *argv[])$/
@@ -1153,7 +1155,6 @@ Python_help c-src/etags.c 660
Python_suffixes c-src/etags.c 658
QUIT c-src/emacs/src/lisp.h 3101
QUITP c-src/emacs/src/lisp.h 3112
-Qpre_abbrev_expand_hook c-src/abbrev.c 83
RANGED_INTEGERP c-src/emacs/src/lisp.h /^RANGED_INTEGERP (intmax_t lo, Lisp_Object x, intma/
RCSid objc-src/PackInsp.m 30
READABLE_EVENTS_DO_TIMERS_NOW c-src/emacs/src/keyboard.c 346
@@ -1498,7 +1499,6 @@ Vglobal_abbrev_table c-src/abbrev.c 48
Vlast_abbrev c-src/abbrev.c 70
Vlast_abbrev_text c-src/abbrev.c 75
Vlispy_mouse_stem c-src/emacs/src/keyboard.c 5172
-Vpre_abbrev_expand_hook c-src/abbrev.c 83
WAIT_READING_MAX c-src/emacs/src/lisp.h 4281
WAIT_READING_MAX c-src/emacs/src/lisp.h 4283
WARNINGS make-src/Makefile /^WARNINGS=-pedantic -Wall -Wpointer-arith -Winline /
@@ -1732,7 +1732,6 @@ Z c-src/h.h 100
\1 c-src/abbrev.c /^ DEFVAR_PER_BUFFER ("local-abbrev-table", &curren/
\1 c-src/abbrev.c /^ DEFVAR_BOOL ("abbrevs-changed", &abbrevs_changed/
\1 c-src/abbrev.c /^ DEFVAR_BOOL ("abbrev-all-caps", &abbrev_all_caps/
-\1 c-src/abbrev.c /^ DEFVAR_LISP ("pre-abbrev-expand-hook", &Vpre_abb/
\1 c-src/emacs/src/keyboard.c /^ DEFVAR_LISP ("internal--top-level-message", Vint/
\1 c-src/emacs/src/keyboard.c /^ DEFVAR_LISP ("last-command-event", last_command_/
\1 c-src/emacs/src/keyboard.c /^ DEFVAR_LISP ("last-nonmenu-event", last_nonmenu_/
@@ -1835,7 +1834,7 @@ Z c-src/h.h 100
\Ealphaenumerate tex-src/texinfo.tex /^\\def\\Ealphaenumerate{\\Eenumerate}$/
\Ecapsenumerate tex-src/texinfo.tex /^\\def\\Ecapsenumerate{\\Eenumerate}$/
\Ecartouche tex-src/texinfo.tex /^\\def\\Ecartouche{%$/
-\Edescription tex-src/texinfo.tex /^\\def\\Edescription{\\Etable}% Neccessary kludge.$/
+\Edescription tex-src/texinfo.tex /^\\def\\Edescription{\\Etable}% Necessary kludge.$/
\Edisplay tex-src/texinfo.tex /^\\def\\Edisplay{\\endgroup\\afterenvbreak}%$/
\Eexample tex-src/texinfo.tex /^\\def\\Eexample{\\Elisp}$/
\Eflushleft tex-src/texinfo.tex /^\\def\\Eflushleft{\\endgroup\\afterenvbreak}%$/
@@ -2462,8 +2461,47 @@ abs/f ada-src/etags-test-for.ada /^ function "abs" (Right : Complex) return
absolute_dirname c-src/etags.c /^absolute_dirname (char *file, char *dir)$/
absolute_filename c-src/etags.c /^absolute_filename (char *file, char *dir)$/
abt cp-src/c.C 55
+acc_pred_info merc-src/accumulator.m /^:- pred acc_pred_info(list(mer_type)::in, list(pro/
+acc_proc_info merc-src/accumulator.m /^:- pred acc_proc_info(list(prog_var)::in, prog_var/
+acc_unification merc-src/accumulator.m /^:- pred acc_unification(pair(prog_var)::in, hlds_g/
+acc_var_subst_init merc-src/accumulator.m /^:- pred acc_var_subst_init(list(prog_var)::in,$/
accent_key_syms c-src/emacs/src/keyboard.c 4625
access_keymap_keyremap c-src/emacs/src/keyboard.c /^access_keymap_keyremap (Lisp_Object map, Lisp_Obje/
+accu_assoc merc-src/accumulator.m /^:- pred accu_assoc(module_info::in, vartypes::in, /
+accu_assoc merc-src/accumulator.m /^:- type accu_assoc$/
+accu_base merc-src/accumulator.m /^:- type accu_base$/
+accu_before merc-src/accumulator.m /^:- pred accu_before(module_info::in, vartypes::in,/
+accu_case merc-src/accumulator.m /^:- type accu_case$/
+accu_construct merc-src/accumulator.m /^:- pred accu_construct(module_info::in, vartypes::/
+accu_construct_assoc merc-src/accumulator.m /^:- pred accu_construct_assoc(module_info::in, vart/
+accu_create_goal merc-src/accumulator.m /^:- pred accu_create_goal(accu_goal_id::in, list(pr/
+accu_divide_base_case merc-src/accumulator.m /^:- pred accu_divide_base_case(module_info::in, var/
+accu_goal_id merc-src/accumulator.m /^:- type accu_goal_id$/
+accu_goal_list merc-src/accumulator.m /^:- func accu_goal_list(list(accu_goal_id), accu_go/
+accu_goal_store merc-src/accumulator.m /^:- type accu_goal_store == goal_store(accu_goal_id/
+accu_has_heuristic merc-src/accumulator.m /^:- pred accu_has_heuristic(module_name::in, string/
+accu_heuristic merc-src/accumulator.m /^:- pred accu_heuristic(module_name::in, string::in/
+accu_is_associative merc-src/accumulator.m /^:- pred accu_is_associative(module_info::in, pred_/
+accu_is_update merc-src/accumulator.m /^:- pred accu_is_update(module_info::in, pred_id::i/
+accu_process_assoc_set merc-src/accumulator.m /^:- pred accu_process_assoc_set(module_info::in, ac/
+accu_process_update_set merc-src/accumulator.m /^:- pred accu_process_update_set(module_info::in, a/
+accu_related merc-src/accumulator.m /^:- pred accu_related(module_info::in, vartypes::in/
+accu_rename merc-src/accumulator.m /^:- func accu_rename(list(accu_goal_id), accu_subst/
+accu_sets merc-src/accumulator.m /^:- type accu_sets$/
+accu_sets_init merc-src/accumulator.m /^:- pred accu_sets_init(accu_sets::out) is det.$/
+accu_stage1 merc-src/accumulator.m /^:- pred accu_stage1(module_info::in, vartypes::in,/
+accu_stage1_2 merc-src/accumulator.m /^:- pred accu_stage1_2(module_info::in, vartypes::i/
+accu_stage2 merc-src/accumulator.m /^:- pred accu_stage2(module_info::in, proc_info::in/
+accu_stage3 merc-src/accumulator.m /^:- pred accu_stage3(accu_goal_id::in, list(prog_va/
+accu_standardize merc-src/accumulator.m /^:- pred accu_standardize(hlds_goal::in, hlds_goal:/
+accu_store merc-src/accumulator.m /^:- pred accu_store(accu_case::in, hlds_goal::in,$/
+accu_subst merc-src/accumulator.m /^:- type accu_subst == map(prog_var, prog_var).$/
+accu_substs merc-src/accumulator.m /^:- type accu_substs$/
+accu_substs_init merc-src/accumulator.m /^:- pred accu_substs_init(list(prog_var)::in, prog_/
+accu_top_level merc-src/accumulator.m /^:- pred accu_top_level(top_level::in, hlds_goal::i/
+accu_transform_proc merc-src/accumulator.m /^:- pred accu_transform_proc(pred_proc_id::in, pred/
+accu_update merc-src/accumulator.m /^:- pred accu_update(module_info::in, vartypes::in,/
+accu_warning merc-src/accumulator.m /^:- type accu_warning$/
act prol-src/natded.prolog /^act(OutForm,OutSyn,Ws):-$/
action prol-src/natded.prolog /^action(KeyVals):-$/
active_maps c-src/emacs/src/keyboard.c /^active_maps (Lisp_Object first_event)$/
@@ -2535,6 +2573,8 @@ assemby-code-word forth-src/test-forth.fth /^code assemby-code-word ( dunno what
assert c-src/etags.c 135
assert c-src/etags.c /^# define assert(x) ((void) 0)$/
assign_neighbor cp-src/clheir.hpp /^ void assign_neighbor(int direction, location */
+assoc_list merc-src/accumulator.m /^:- import_module assoc_list.$/
+associativity_assertion merc-src/accumulator.m /^:- pred associativity_assertion(module_info::in, l/
at_end c-src/etags.c 249
at_filename c-src/etags.c 247
at_language c-src/etags.c 245
@@ -2568,6 +2608,8 @@ bas_syn prol-src/natded.prolog /^bas_syn(n(_)).$/
base c-src/emacs/src/lisp.h 2188
base cp-src/c.C /^double base (void) const { return rng_base; }$/
base cp-src/Range.h /^ double base (void) const { return rng_base; }$/
+base_case_ids merc-src/accumulator.m /^:- func base_case_ids(accu_goal_store) = list(accu/
+base_case_ids_set merc-src/accumulator.m /^:- func base_case_ids_set(accu_goal_store) = set(a/
baz= ruby-src/test1.ru /^ :baz,$/
bb c.c 275
bbb c.c 251
@@ -2605,6 +2647,7 @@ bodyindent tex-src/texinfo.tex /^\\exdentamount=\\defbodyindent$/
bodyindent tex-src/texinfo.tex /^\\advance\\leftskip by \\defbodyindent \\advance \\righ/
bodyindent tex-src/texinfo.tex /^\\exdentamount=\\defbodyindent$/
bool c.c 222
+bool merc-src/accumulator.m /^:- import_module bool.$/
bool_header_size c-src/emacs/src/lisp.h 1472
bool_vector_bitref c-src/emacs/src/lisp.h /^bool_vector_bitref (Lisp_Object a, EMACS_INT i)$/
bool_vector_bytes c-src/emacs/src/lisp.h /^bool_vector_bytes (EMACS_INT size)$/
@@ -2646,6 +2689,7 @@ c_ext c-src/etags.c 2271
caccacacca c.c /^caccacacca (a,b,c,d,e,f,g)$/
cacheLRUEntry_s c.c 172
cacheLRUEntry_t c.c 177
+calculate_goal_info merc-src/accumulator.m /^:- pred calculate_goal_info(hlds_goal_expr::in, hl/
calloc c-src/emacs/src/gmalloc.c 66
calloc c-src/emacs/src/gmalloc.c 70
calloc c-src/emacs/src/gmalloc.c /^calloc (size_t nmemb, size_t size)$/
@@ -2666,6 +2710,8 @@ cgrep html-src/software.html /^cgrep$/
chain c-src/emacs/src/lisp.h 1162
chain c-src/emacs/src/lisp.h 2206
chain c-src/emacs/src/lisp.h 2396
+chain_subst merc-src/accumulator.m /^:- func chain_subst(accu_subst, accu_subst) = accu/
+chain_subst_2 merc-src/accumulator.m /^:- pred chain_subst_2(list(A)::in, map(A, B)::in, /
char_bits c-src/emacs/src/lisp.h 2443
char_table_specials c-src/emacs/src/lisp.h 1692
charpos c-src/emacs/src/lisp.h 2011
@@ -2708,6 +2754,7 @@ command_loop_1 c-src/emacs/src/keyboard.c /^command_loop_1 (void)$/
command_loop_2 c-src/emacs/src/keyboard.c /^command_loop_2 (Lisp_Object ignore)$/
command_loop_level c-src/emacs/src/keyboard.c 195
comment php-src/lce_functions.php /^ function comment($line, $class)$/
+commutativity_assertion merc-src/accumulator.m /^:- pred commutativity_assertion(module_info::in,li/
compile_empty prol-src/natded.prolog /^compile_empty:-$/
compile_lex prol-src/natded.prolog /^compile_lex(File):-$/
complete prol-src/natded.prolog /^complete(Cat):-$/
@@ -2741,6 +2788,13 @@ create-bar forth-src/test-forth.fth /^: create-bar foo ;$/
createPOEntries php-src/lce_functions.php /^ function createPOEntries()$/
createWidgets pyt-src/server.py /^ def createWidgets(self, host):$/
createWidgets pyt-src/server.py /^ def createWidgets(self):$/
+create_acc_call merc-src/accumulator.m /^:- func create_acc_call(hlds_goal::in(goal_plain_c/
+create_acc_goal merc-src/accumulator.m /^:- pred create_acc_goal(hlds_goal::in, accu_substs/
+create_new_base_goals merc-src/accumulator.m /^:- func create_new_base_goals(set(accu_goal_id), a/
+create_new_orig_recursive_goals merc-src/accumulator.m /^:- func create_new_orig_recursive_goals(set(accu_g/
+create_new_recursive_goals merc-src/accumulator.m /^:- func create_new_recursive_goals(set(accu_goal_i/
+create_new_var merc-src/accumulator.m /^:- pred create_new_var(prog_var::in, string::in, p/
+create_orig_goal merc-src/accumulator.m /^:- pred create_orig_goal(hlds_goal::in, accu_subst/
cscInitTime cp-src/c.C 7
cscSegmentationTime cp-src/c.C 8
cstack c-src/etags.c 2523
@@ -3048,6 +3102,7 @@ foperator c-src/etags.c 2411
force_auto_save_soon c-src/emacs/src/keyboard.c /^force_auto_save_soon (void)$/
force_explicit_name c-src/etags.c 265
force_quit_count c-src/emacs/src/keyboard.c 10387
+foreign_export merc-src/accumulator.m /^:- pragma foreign_export("C", unravel_univ(in, out/
formatSize objc-src/PackInsp.m /^-(const char *)formatSize:(const char *)size inBuf/
found c-src/emacs/src/lisp.h 2344
fracas html-src/software.html /^Fracas$/
@@ -3105,6 +3160,8 @@ gcpro c-src/emacs/src/lisp.h 3042
gcpro c-src/emacs/src/lisp.h 3132
gen_help_event c-src/emacs/src/keyboard.c /^gen_help_event (Lisp_Object help, Lisp_Object fram/
genalgorithm html-src/algrthms.html /^Generating the Data<\/font><\/i><\/b>$/
+generate_warning merc-src/accumulator.m /^:- pred generate_warning(module_info::in, prog_var/
+generate_warnings merc-src/accumulator.m /^:- pred generate_warnings(module_info::in, prog_va/
generic_object cp-src/clheir.cpp /^generic_object::generic_object(void)$/
generic_object cp-src/clheir.hpp 13
getArchs objc-src/PackInsp.m /^-(void)getArchs$/
@@ -3173,6 +3230,7 @@ help_char_p c-src/emacs/src/keyboard.c /^help_char_p (Lisp_Object c)$/
help_form_saved_window_configs c-src/emacs/src/keyboard.c 2156
helpwin pyt-src/server.py /^def helpwin(helpdict):$/
hide_cursor cp-src/screen.cpp /^void hide_cursor(void)$/
+hlds merc-src/accumulator.m /^:- import_module hlds.$/
htmltreelist prol-src/natded.prolog /^htmltreelist([]).$/
hybrid_aligned_alloc c-src/emacs/src/gmalloc.c /^hybrid_aligned_alloc (size_t alignment, size_t siz/
hybrid_calloc c-src/emacs/src/gmalloc.c /^hybrid_calloc (size_t nmemb, size_t size)$/
@@ -3192,12 +3250,16 @@ ialpage tex-src/texinfo.tex /^ \\dimen@=\\pageheight \\advance\\dimen@ by-\\ht\
ialpage tex-src/texinfo.tex /^ \\availdimen@=\\pageheight \\advance\\availdimen@ by/
ialpage tex-src/texinfo.tex /^ \\dimen@=\\pageheight \\advance\\dimen@ by-\\ht\\pa/
ialpage= tex-src/texinfo.tex /^ \\output={\\global\\setbox\\partialpage=$/
+identify_goal_type merc-src/accumulator.m /^:- pred identify_goal_type(pred_id::in, proc_id::i/
+identify_out_and_out_prime merc-src/accumulator.m /^:- pred identify_out_and_out_prime(module_info::in/
+identify_recursive_calls merc-src/accumulator.m /^:- pred identify_recursive_calls(pred_id::in, proc/
idx c-src/emacs/src/lisp.h 3150
ignore_case c-src/etags.c 266
ignore_mouse_drag_p c-src/emacs/src/keyboard.c 1256
ill=\relax tex-src/texinfo.tex /^\\let\\refill=\\relax$/
immediate_quit c-src/emacs/src/keyboard.c 174
impatto html-src/softwarelibero.html /^Impatto pratico del software libero$/
+implementation merc-src/accumulator.m /^:- implementation.$/
in_word_set c-src/etags.c /^in_word_set (register const char *str, register un/
inattribute c-src/etags.c 2400
inc cp-src/Range.h /^ double inc (void) const { return rng_inc; }$/
@@ -3221,6 +3283,7 @@ inita c.c /^static void inita () {}$/
initb c.c /^static void initb () {}$/
initial_kboard c-src/emacs/src/keyboard.c 84
initialize-new-tags-table el-src/emacs/lisp/progmodes/etags.el /^(defun initialize-new-tags-table ()$/
+initialize_goal_store merc-src/accumulator.m /^:- func initialize_goal_store(list(hlds_goal), ins/
initialize_random_junk y-src/cccp.y /^initialize_random_junk ()$/
input-pending-p c-src/emacs/src/keyboard.c /^DEFUN ("input-pending-p", Finput_pending_p, Sinput/
input_available_clear_time c-src/emacs/src/keyboard.c 324
@@ -3236,6 +3299,7 @@ instance_method_exclamation! ruby-src/test.rb /^ def instance_method_excl
instance_method_question? ruby-src/test.rb /^ def instance_method_question?$/
instr y-src/parse.y 81
instruct c-src/etags.c 2527
+int merc-src/accumulator.m /^:- import_module int.$/
intNumber go-src/test1.go 13
integer c-src/emacs/src/lisp.h 2127
integer y-src/cccp.y 112
@@ -3244,6 +3308,7 @@ integertonmstr pas-src/common.pas /^function integertonmstr; (* (TheInteger : in
intensity1 f-src/entry.for /^ & intensity1(efv,fv,svin,svquad,sfpv,maxp,val/
intensity1 f-src/entry.strange_suffix /^ & intensity1(efv,fv,svin,svquad,sfpv,maxp,val/
intensity1 f-src/entry.strange /^ & intensity1(efv,fv,svin,svquad,sfpv,maxp,val/
+interface merc-src/accumulator.m /^:- interface.$/
interface_locate c-src/c.c /^interface_locate(void)$/
intern c-src/emacs/src/lisp.h /^intern (const char *str)$/
intern_c_string c-src/emacs/src/lisp.h /^intern_c_string (const char *str)$/
@@ -3258,6 +3323,7 @@ intoken c-src/etags.c /^#define intoken(c) (_itk[CHAR (c)]) \/* c can be in/
intspec c-src/emacs/src/lisp.h 1688
intvar c-src/emacs/src/lisp.h 2277
invalidate_nodes c-src/etags.c /^invalidate_nodes (fdesc *badfdp, node **npp)$/
+io merc-src/accumulator.m /^:- import_module io.$/
ipc3dCSC19 cp-src/c.C 6
ipc3dChannelType cp-src/c.C 1
ipc3dIslandHierarchy cp-src/c.C 1
@@ -3267,6 +3333,7 @@ irregular_location cp-src/clheir.hpp /^ irregular_location(double xi, double
isComment php-src/lce_functions.php /^ function isComment($class)$/
isHoliday cp-src/functions.cpp /^bool isHoliday ( Date d ){$/
isLeap cp-src/functions.cpp /^bool isLeap ( int year ){$/
+is_associative_construction merc-src/accumulator.m /^:- pred is_associative_construction(module_info::i/
is_curly_brace_form c-src/h.h 54
is_explicit c-src/h.h 49
is_func c-src/etags.c 221
@@ -3275,6 +3342,7 @@ is_idchar y-src/cccp.y 948
is_idstart y-src/cccp.y 950
is_muldiv_operation cp-src/c.C /^is_muldiv_operation(pc)$/
is_ordset prol-src/ordsets.prolog /^is_ordset(X) :- var(X), !, fail.$/
+is_recursive_case merc-src/accumulator.m /^:- pred is_recursive_case(list(hlds_goal)::in, pre/
iso_lispy_function_keys c-src/emacs/src/keyboard.c 5151
isoperator prol-src/natded.prolog /^isoperator(Char):-$/
isoptab prol-src/natded.prolog /^isoptab('%').$/
@@ -3371,6 +3439,7 @@ letter: tex-src/texinfo.tex /^\\xdef\\thischapter{Appendix \\appendixletter: \\n
level c-src/emacs/src/lisp.h 3153
lex prol-src/natded.prolog /^lex(W,SynOut,Sem):-$/
lexptr y-src/cccp.y 332
+libs merc-src/accumulator.m /^:- import_module libs.$/
licenze html-src/softwarelibero.html /^Licenze d'uso di un programma$/
limit cp-src/Range.h /^ double limit (void) const { return rng_limit; }$/
line c-src/etags.c 2493
@@ -3428,6 +3497,7 @@ lispy_modifier_list c-src/emacs/src/keyboard.c /^lispy_modifier_list (int modifi
lispy_multimedia_keys c-src/emacs/src/keyboard.c 4962
lispy_wheel_names c-src/emacs/src/keyboard.c 5174
list c-src/emacs/src/gmalloc.c 186
+list merc-src/accumulator.m /^:- import_module list.$/
list-tags el-src/emacs/lisp/progmodes/etags.el /^(defun list-tags (file &optional _next-match)$/
list-tags-function el-src/emacs/lisp/progmodes/etags.el /^(defvar list-tags-function nil$/
list2i c-src/emacs/src/lisp.h /^list2i (EMACS_INT x, EMACS_INT y)$/
@@ -3444,6 +3514,7 @@ local_if_set c-src/emacs/src/lisp.h 2338
location cp-src/clheir.hpp 33
location cp-src/clheir.hpp /^ location() { }$/
lookup y-src/cccp.y /^lookup (name, len, hash)$/
+lookup_call merc-src/accumulator.m /^:- pred lookup_call(accu_goal_store::in, accu_goal/
lowcase c-src/etags.c /^#define lowcase(c) tolower (CHAR (c))$/
lucid_event_type_list_p c-src/emacs/src/keyboard.c /^lucid_event_type_list_p (Lisp_Object object)$/
mabort c-src/emacs/src/gmalloc.c /^mabort (enum mcheck_status status)$/
@@ -3489,6 +3560,7 @@ mallochook c-src/emacs/src/gmalloc.c /^mallochook (size_t size)$/
man manpage make-src/Makefile /^man manpage: etags.1.man$/
mao c-src/h.h 101
map c-src/emacs/src/keyboard.c 8748
+map merc-src/accumulator.m /^:- import_module map.$/
map_word prol-src/natded.prolog /^map_word([[_]|Ws],Exp):-$/
mapping html-src/algrthms.html /^Mapping the Channel Symbols$/
mapsyn prol-src/natded.prolog /^mapsyn(A\/B,AM\/BM):-$/
@@ -3502,15 +3574,18 @@ max_args c-src/emacs/src/lisp.h 1686
max_num_directions cp-src/clheir.hpp 31
max_num_generic_objects cp-src/clheir.cpp 9
maxargs c-src/emacs/src/lisp.h 2831
+maybe merc-src/accumulator.m /^:- import_module maybe.$/
maybe_gc c-src/emacs/src/lisp.h /^maybe_gc (void)$/
mcCSC cp-src/c.C 6
mcheck c-src/emacs/src/gmalloc.c /^mcheck (void (*func) (enum mcheck_status))$/
mcheck_status c-src/emacs/src/gmalloc.c 283
mcheck_used c-src/emacs/src/gmalloc.c 2012
+mdbcomp merc-src/accumulator.m /^:- import_module mdbcomp.$/
me22b lua-src/test.lua /^ local function test.me22b (one)$/
me_22a lua-src/test.lua /^ function test.me_22a(one, two)$/
memalign c-src/emacs/src/gmalloc.c /^memalign (size_t alignment, size_t size)$/
member prol-src/natded.prolog /^member(X,[X|_]).$/
+member_lessthan_goalid merc-src/accumulator.m /^:- pred member_lessthan_goalid(accu_goal_store::in/
memclear c-src/emacs/src/lisp.h /^memclear (void *p, ptrdiff_t nbytes)$/
menu_bar_item c-src/emacs/src/keyboard.c /^menu_bar_item (Lisp_Object key, Lisp_Object item, /
menu_bar_items c-src/emacs/src/keyboard.c /^menu_bar_items (Lisp_Object old)$/
@@ -3781,6 +3856,7 @@ pMu c-src/emacs/src/lisp.h 151
pMu c-src/emacs/src/lisp.h 156
p_next c-src/etags.c 258
pagesize c-src/emacs/src/gmalloc.c 1703
+pair merc-src/accumulator.m /^:- import_module pair.$/
parent c-src/emacs/src/keyboard.c 8745
parent c-src/emacs/src/lisp.h 1590
parse prol-src/natded.prolog /^parse(Ws,Cat):-$/
@@ -3798,6 +3874,7 @@ parse_return y-src/parse.y 74
parse_return_error y-src/cccp.y 70
parse_solitary_modifier c-src/emacs/src/keyboard.c /^parse_solitary_modifier (Lisp_Object symbol)$/
parse_tool_bar_item c-src/emacs/src/keyboard.c /^parse_tool_bar_item (Lisp_Object key, Lisp_Object /
+parse_tree merc-src/accumulator.m /^:- import_module parse_tree.$/
pat c-src/etags.c 262
pattern c-src/etags.c 260
pdlcount c-src/emacs/src/lisp.h 3046
@@ -3990,6 +4067,7 @@ removeexp prol-src/natded.prolog /^removeexp(E,E,'NIL'):-!.$/
reorder_modifiers c-src/emacs/src/keyboard.c /^reorder_modifiers (Lisp_Object symbol)$/
request c.c /^request request (a, b)$/
requeued_events_pending_p c-src/emacs/src/keyboard.c /^requeued_events_pending_p (void)$/
+require merc-src/accumulator.m /^:- import_module require.$/
required_argument c-src/getopt.h 90
reset-this-command-lengths c-src/emacs/src/keyboard.c /^DEFUN ("reset-this-command-lengths", Freset_this_c/
restore_getcjmp c-src/emacs/src/keyboard.c /^restore_getcjmp (sys_jmp_buf temp)$/
@@ -4062,6 +4140,7 @@ separator_names c-src/emacs/src/keyboard.c 7372
serializeToVars php-src/lce_functions.php /^ function serializeToVars($prefix)$/
serializeToVars php-src/lce_functions.php /^ function serializeToVars($prefix)$/
set cp-src/conway.hpp /^ void set(void) { alive = 1; }$/
+set merc-src/accumulator.m /^:- import_module set.$/
set-input-interrupt-mode c-src/emacs/src/keyboard.c /^DEFUN ("set-input-interrupt-mode", Fset_input_inte/
set-input-meta-mode c-src/emacs/src/keyboard.c /^DEFUN ("set-input-meta-mode", Fset_input_meta_mode/
set-input-mode c-src/emacs/src/keyboard.c /^DEFUN ("set-input-mode", Fset_input_mode, Sset_inp/
@@ -4089,11 +4168,14 @@ set_sub_char_table_contents c-src/emacs/src/lisp.h /^set_sub_char_table_contents
set_symbol_function c-src/emacs/src/lisp.h /^set_symbol_function (Lisp_Object sym, Lisp_Object /
set_symbol_next c-src/emacs/src/lisp.h /^set_symbol_next (Lisp_Object sym, struct Lisp_Symb/
set_symbol_plist c-src/emacs/src/lisp.h /^set_symbol_plist (Lisp_Object sym, Lisp_Object pli/
+set_upto merc-src/accumulator.m /^:- func set_upto(accu_case, int) = set(accu_goal_i/
set_waiting_for_input c-src/emacs/src/keyboard.c /^set_waiting_for_input (struct timespec *time_to_cl/
setref tex-src/texinfo.tex /^\\expandafter\\expandafter\\expandafter\\appendixsetre/
setup cp-src/c.C 5
shift cp-src/functions.cpp /^void Date::shift ( void ){\/\/Shift this date to pre/
shouldLoad objc-src/PackInsp.m /^-(BOOL)shouldLoad$/
+should_attempt_accu_transform merc-src/accumulator.m /^:- pred should_attempt_accu_transform(module_info:/
+should_attempt_accu_transform_2 merc-src/accumulator.m /^:- pred should_attempt_accu_transform_2(module_inf/
should_see_this_array_type cp-src/c.C 156
should_see_this_function_pointer cp-src/c.C 153
should_see_this_one_enclosed_in_extern_C cp-src/c.C 149
@@ -4123,6 +4205,7 @@ skip_non_spaces c-src/etags.c /^skip_non_spaces (char *cp)$/
skip_spaces c-src/etags.c /^skip_spaces (char *cp)$/
snarf-tag-function el-src/emacs/lisp/progmodes/etags.el /^(defvar snarf-tag-function nil$/
snone c-src/etags.c 2443
+solutions merc-src/accumulator.m /^:- import_module solutions.$/
some_mouse_moved c-src/emacs/src/keyboard.c /^some_mouse_moved (void)$/
space tex-src/texinfo.tex /^ {#2\\labelspace #1}\\dotfill\\doshortpageno{#3}}%/
space tex-src/texinfo.tex /^ \\dosubsubsecentry{#2.#3.#4.#5\\labelspace#1}{#6}}/
@@ -4172,10 +4255,13 @@ step cp-src/conway.hpp /^ void step(void) { alive = next_alive; }$/
step cp-src/clheir.hpp /^ virtual void step(void) { }$/
step_everybody cp-src/clheir.cpp /^void step_everybody(void)$/
stop_polling c-src/emacs/src/keyboard.c /^stop_polling (void)$/
+store_info merc-src/accumulator.m /^:- type store_info$/
store_user_signal_events c-src/emacs/src/keyboard.c /^store_user_signal_events (void)$/
+stored_goal_plain_call merc-src/accumulator.m /^:- inst stored_goal_plain_call for goal_store.stor/
str go-src/test1.go 9
strcaseeq c-src/etags.c /^#define strcaseeq(s,t) (assert ((s)!=NULL && (t)!=/
streq c-src/etags.c /^#define streq(s,t) (assert ((s)!=NULL || (t)!=NULL/
+string merc-src/accumulator.m /^:- import_module string.$/
string_intervals c-src/emacs/src/lisp.h /^string_intervals (Lisp_Object s)$/
stripLine php-src/lce_functions.php /^ function stripLine($line, $class)$/
stripname pas-src/common.pas /^function stripname; (* ($/
@@ -4315,6 +4401,7 @@ tee ruby-src/test1.ru /^ attr_accessor :tee$/
tee= ruby-src/test1.ru /^ attr_accessor :tee$/
temporarily_switch_to_single_kboard c-src/emacs/src/keyboard.c /^temporarily_switch_to_single_kboard (struct frame /
tend c-src/etags.c 2432
+term merc-src/accumulator.m /^:- import_module term.$/
terminate objc-src/Subprocess.m /^- terminate:sender$/
terminateInput objc-src/Subprocess.m /^- terminateInput$/
test c-src/emacs/src/lisp.h 1871
@@ -4326,6 +4413,7 @@ test php-src/ptest.php /^test $/
test-begin scm-src/test.scm /^(define-syntax test-begin$/
test.me22b lua-src/test.lua /^ local function test.me22b (one)$/
test.me_22a lua-src/test.lua /^ function test.me_22a(one, two)$/
+test1 rs-src/test.rs /^fn test1() {$/
test_undefined c-src/emacs/src/keyboard.c /^test_undefined (Lisp_Object binding)$/
texttreelist prol-src/natded.prolog /^texttreelist([]).$/
there-is-a-=-in-the-middle! scm-src/test.scm /^(define (there-is-a-=-in-the-middle!) #t)$/
@@ -4365,6 +4453,7 @@ tool_bar_items c-src/emacs/src/keyboard.c /^tool_bar_items (Lisp_Object reuse, i
tool_bar_items_vector c-src/emacs/src/keyboard.c 7965
toolkit_menubar_in_use c-src/emacs/src/keyboard.c /^toolkit_menubar_in_use (struct frame *f)$/
top-level c-src/emacs/src/keyboard.c /^DEFUN ("top-level", Ftop_level, Stop_level, 0, 0, /
+top_level merc-src/accumulator.m /^:- type top_level$/
top_level_1 c-src/emacs/src/keyboard.c /^top_level_1 (Lisp_Object ignore)$/
top_level_2 c-src/emacs/src/keyboard.c /^top_level_2 (void)$/
total_keys c-src/emacs/src/keyboard.c 97
@@ -4421,12 +4510,15 @@ unblock_input c-src/emacs/src/keyboard.c /^unblock_input (void)$/
unblock_input_to c-src/emacs/src/keyboard.c /^unblock_input_to (int level)$/
unchar c-src/h.h 99
unexpand-abbrev c-src/abbrev.c /^DEFUN ("unexpand-abbrev", Funexpand_abbrev, Sunexp/
+univ merc-src/accumulator.m /^:- import_module univ.$/
+unravel_univ merc-src/accumulator.m /^:- some [T] pred unravel_univ(univ::in, T::out) is/
unread_switch_frame c-src/emacs/src/keyboard.c 204
unsignedp y-src/cccp.y 112
unwind c-src/emacs/src/lisp.h 2962
unwind_int c-src/emacs/src/lisp.h 2972
unwind_ptr c-src/emacs/src/lisp.h 2967
unwind_void c-src/emacs/src/lisp.h 2976
+update_accumulator_pred merc-src/accumulator.m /^:- pred update_accumulator_pred(pred_id::in, proc_/
uprintmax_t c-src/emacs/src/lisp.h 149
uprintmax_t c-src/emacs/src/lisp.h 154
usage perl-src/yagrip.pl /^sub usage {$/
@@ -4458,6 +4550,7 @@ varargs tex-src/texinfo.tex /^\\defvarargs {#3}\\endgroup %$/
varargs tex-src/texinfo.tex /^\\defvarargs {#3}\\endgroup %$/
varargs tex-src/texinfo.tex /^\\defvarargs {#2}\\endgroup %$/
varargs tex-src/texinfo.tex /^\\defvarargs {#2}\\endgroup %$/
+varset merc-src/accumulator.m /^:- import_module varset.$/
vcopy c-src/emacs/src/lisp.h /^vcopy (Lisp_Object v, ptrdiff_t offset, Lisp_Objec/
vectorlike_header c-src/emacs/src/lisp.h 1343
verde cp-src/c.C 40
diff --git a/test/manual/etags/ETAGS.good_1 b/test/manual/etags/ETAGS.good_1
index cd9cd4a8450..4baaff4c425 100644
--- a/test/manual/etags/ETAGS.good_1
+++ b/test/manual/etags/ETAGS.good_1
@@ -175,7 +175,7 @@ package body Truc.Bidule Truc.Bidule/b138,2153
protected body Bidule Bidule/b139,2181
protected body Machin_T Machin_T/b146,2281
-c-src/abbrev.c,2072
+c-src/abbrev.c,1957
Lisp_Object Vabbrev_table_name_list;43,1429
Lisp_Object Vglobal_abbrev_table;48,1574
Lisp_Object Vfundamental_mode_abbrev_table;52,1685
@@ -186,33 +186,31 @@ Lisp_Object Vabbrev_start_location_buffer;66,2046
Lisp_Object Vlast_abbrev;70,2155
Lisp_Object Vlast_abbrev_text;75,2324
int last_abbrev_point;79,2414
-Lisp_Object Vpre_abbrev_expand_hook,83,2487
-Lisp_Object Vpre_abbrev_expand_hook, Qpre_abbrev_expand_hook;83,2487
-DEFUN ("make-abbrev-table", Fmake_abbrev_table,85,2551
-DEFUN ("make-abbrev-table", Fmake_abbrev_table,make-abbrev-table85,2551
-DEFUN ("clear-abbrev-table", Fclear_abbrev_table,92,2743
-DEFUN ("clear-abbrev-table", Fclear_abbrev_table,clear-abbrev-table92,2743
-DEFUN ("define-abbrev", Fdefine_abbrev,107,3124
-DEFUN ("define-abbrev", Fdefine_abbrev,define-abbrev107,3124
-DEFUN ("define-global-abbrev", Fdefine_global_abbrev,149,4443
-DEFUN ("define-global-abbrev", Fdefine_global_abbrev,define-global-abbrev149,4443
-DEFUN ("define-mode-abbrev", Fdefine_mode_abbrev,160,4814
-DEFUN ("define-mode-abbrev", Fdefine_mode_abbrev,define-mode-abbrev160,4814
-DEFUN ("abbrev-symbol", Fabbrev_symbol,174,5282
-DEFUN ("abbrev-symbol", Fabbrev_symbol,abbrev-symbol174,5282
-DEFUN ("abbrev-expansion", Fabbrev_expansion,202,6246
-DEFUN ("abbrev-expansion", Fabbrev_expansion,abbrev-expansion202,6246
-DEFUN ("expand-abbrev", Fexpand_abbrev,218,6761
-DEFUN ("expand-abbrev", Fexpand_abbrev,expand-abbrev218,6761
-DEFUN ("unexpand-abbrev", Funexpand_abbrev,389,11682
-DEFUN ("unexpand-abbrev", Funexpand_abbrev,unexpand-abbrev389,11682
-write_abbrev 426,12889
-describe_abbrev 445,13324
-DEFUN ("insert-abbrev-table-description", Finsert_abbrev_table_description,466,13839
-DEFUN ("insert-abbrev-table-description", Finsert_abbrev_table_description,insert-abbrev-table-description466,13839
-DEFUN ("define-abbrev-table", Fdefine_abbrev_table,506,14995
-DEFUN ("define-abbrev-table", Fdefine_abbrev_table,define-abbrev-table506,14995
-syms_of_abbrev 540,16072
+DEFUN ("make-abbrev-table", Fmake_abbrev_table,82,2440
+DEFUN ("make-abbrev-table", Fmake_abbrev_table,make-abbrev-table82,2440
+DEFUN ("clear-abbrev-table", Fclear_abbrev_table,89,2632
+DEFUN ("clear-abbrev-table", Fclear_abbrev_table,clear-abbrev-table89,2632
+DEFUN ("define-abbrev", Fdefine_abbrev,104,3013
+DEFUN ("define-abbrev", Fdefine_abbrev,define-abbrev104,3013
+DEFUN ("define-global-abbrev", Fdefine_global_abbrev,146,4332
+DEFUN ("define-global-abbrev", Fdefine_global_abbrev,define-global-abbrev146,4332
+DEFUN ("define-mode-abbrev", Fdefine_mode_abbrev,157,4703
+DEFUN ("define-mode-abbrev", Fdefine_mode_abbrev,define-mode-abbrev157,4703
+DEFUN ("abbrev-symbol", Fabbrev_symbol,171,5171
+DEFUN ("abbrev-symbol", Fabbrev_symbol,abbrev-symbol171,5171
+DEFUN ("abbrev-expansion", Fabbrev_expansion,199,6135
+DEFUN ("abbrev-expansion", Fabbrev_expansion,abbrev-expansion199,6135
+DEFUN ("expand-abbrev", Fexpand_abbrev,215,6650
+DEFUN ("expand-abbrev", Fexpand_abbrev,expand-abbrev215,6650
+DEFUN ("unexpand-abbrev", Funexpand_abbrev,383,11495
+DEFUN ("unexpand-abbrev", Funexpand_abbrev,unexpand-abbrev383,11495
+write_abbrev 420,12702
+describe_abbrev 439,13137
+DEFUN ("insert-abbrev-table-description", Finsert_abbrev_table_description,460,13652
+DEFUN ("insert-abbrev-table-description", Finsert_abbrev_table_description,insert-abbrev-table-description460,13652
+DEFUN ("define-abbrev-table", Fdefine_abbrev_table,500,14808
+DEFUN ("define-abbrev-table", Fdefine_abbrev_table,define-abbrev-table500,14808
+syms_of_abbrev 534,15885
c-src/torture.c,197
(*tag1 tag118,452
@@ -235,324 +233,324 @@ struct option73,2795
#define optional_argument 91,3173
c-src/etags.c,10045
-char pot_etags_version[pot_etags_version81,3470
-# undef DEBUG84,3552
-# define DEBUG 85,3567
-# define DEBUG 87,3594
-# define NDEBUG 88,3617
-# define _GNU_SOURCE 94,3705
-# undef MSDOS100,3876
-# undef WINDOWSNT101,3890
-# define WINDOWSNT102,3909
-# undef MSDOS106,3968
-# define MSDOS 107,3982
-# define MSDOS 110,4032
-# define MAXPATHLEN 115,4111
-# undef HAVE_NTGUI116,4141
-# undef DOS_NT117,4160
-# define DOS_NT118,4176
-# undef assert 135,4482
-# define assert(136,4541
-# undef CTAGS146,4857
-# define CTAGS 147,4872
-# define CTAGS 149,4898
-#define streq(152,4927
-#define strcaseeq(153,4996
-#define strneq(154,5075
-#define strncaseeq(155,5151
-#define CHARS 157,5238
-#define CHAR(158,5278
-#define iswhite(159,5329
-#define notinname(160,5394
-#define begtoken(161,5469
-#define intoken(162,5542
-#define endtoken(163,5614
-#define ISALNUM(165,5684
-#define ISALPHA(166,5722
-#define ISDIGIT(167,5760
-#define ISLOWER(168,5798
-#define lowcase(170,5837
-#define xnew(179,6015
-#define xrnew(180,6083
-typedef void Lang_function 182,6164
-} compressor;188,6365
-} language;199,6835
-typedef struct fdesc201,6848
-} fdesc;212,7366
-typedef struct node_st214,7376
-} node;225,7894
-} linebuffer;239,8248
- at_language,245,8344
- at_regexp,246,8393
- at_filename,247,8437
- at_stdin,248,8473
- at_end 249,8516
-} argument;253,8698
-typedef struct regexp256,8758
-} regexp;268,9325
-static void error 311,10780
-# undef STDIN408,15073
-#define STDIN 411,15095
-static compressor compressors[compressors457,17664
-static const char *Ada_suffixes Ada_suffixes473,17907
-static const char Ada_help 475,17977
-static const char *Asm_suffixes Asm_suffixes493,18580
-static const char Asm_help 504,18976
-static const char *default_C_suffixes default_C_suffixes512,19312
-static const char default_C_help 515,19413
-static const char default_C_help 523,19850
-static const char *Cplusplus_suffixes Cplusplus_suffixes535,20460
-static const char Cplusplus_help 540,20658
-static const char *Cjava_suffixes Cjava_suffixes549,21113
-static char Cjava_help 551,21172
-static const char *Cobol_suffixes Cobol_suffixes556,21337
-static char Cobol_help 558,21402
-static const char *Cstar_suffixes Cstar_suffixes562,21543
-static const char *Erlang_suffixes Erlang_suffixes565,21607
-static const char Erlang_help 567,21673
-const char *Forth_suffixes Forth_suffixes571,21799
-static const char Forth_help 573,21857
-static const char *Fortran_suffixes Fortran_suffixes577,22008
-static const char Fortran_help 579,22085
-static const char *HTML_suffixes HTML_suffixes582,22190
-static const char HTML_help 584,22264
-static const char *Lisp_suffixes Lisp_suffixes589,22452
-static const char Lisp_help 591,22556
-static const char *Lua_suffixes Lua_suffixes598,22871
-static const char Lua_help 600,22934
-static const char *Makefile_filenames Makefile_filenames603,23010
-static const char Makefile_help 605,23133
-static const char *Objc_suffixes Objc_suffixes609,23277
-static const char Objc_help 613,23399
-static const char *Pascal_suffixes Pascal_suffixes619,23714
-static const char Pascal_help 621,23778
-static const char *Perl_suffixes Perl_suffixes626,23966
-static const char *Perl_interpreters Perl_interpreters628,24028
-static const char Perl_help 630,24100
-static const char *PHP_suffixes PHP_suffixes637,24451
-static const char PHP_help 639,24523
-static const char *plain_C_suffixes plain_C_suffixes643,24678
-static const char *PS_suffixes PS_suffixes647,24762
-static const char PS_help 649,24848
-static const char *Prolog_suffixes Prolog_suffixes652,24931
-static const char Prolog_help 654,24993
-static const char *Python_suffixes Python_suffixes658,25107
-static const char Python_help 660,25165
-static const char *Scheme_suffixes Scheme_suffixes665,25347
-static const char Scheme_help 667,25460
-static const char *TeX_suffixes TeX_suffixes672,25683
-static const char TeX_help 674,25781
-static const char *Texinfo_suffixes Texinfo_suffixes686,26316
-static const char Texinfo_help 688,26395
-static const char *Yacc_suffixes Yacc_suffixes691,26492
-static const char Yacc_help 693,26606
-static const char auto_help 699,26856
-static const char none_help 703,27020
-static const char no_lang_help 707,27143
-static language lang_names 718,27355
-print_language_names 753,29532
-# define EMACS_NAME 786,30755
-# define VERSION 789,30811
-print_version 792,30869
-# define PRINT_UNDOCUMENTED_OPTIONS_HELP 804,31173
-print_help 808,31250
-main 981,37438
-get_compressor_from_suffix 1319,46217
-get_language_from_langname 1355,47158
-get_language_from_interpreter 1377,47545
-get_language_from_filename 1399,47976
-process_file_name 1433,48834
-process_file 1555,51665
-init 1632,54150
-find_entries 1656,54901
-make_tag 1814,59707
-pfnote 1856,60942
-free_tree 1917,62744
-free_fdesc 1935,63029
-add_node 1955,63472
-invalidate_nodes 2035,65537
-static int number_len 2068,66193
-total_size_of_entries 2087,66694
-put_entries 2107,67154
-#define C_EXT 2193,68995
-#define C_PLAIN 2194,69037
-#define C_PLPL 2195,69070
-#define C_STAR 2196,69104
-#define C_JAVA 2197,69137
-#define C_AUTO 2198,69172
-#define YACC 2199,69242
-enum sym_type2204,69312
- st_none,2206,69328
- st_C_objprot,2207,69339
- st_C_objprot, st_C_objimpl,2207,69339
- st_C_objprot, st_C_objimpl, st_C_objend,2207,69339
- st_C_gnumacro,2208,69382
- st_C_ignore,2209,69399
- st_C_ignore, st_C_attribute,2209,69399
- st_C_javastruct,2210,69430
- st_C_operator,2211,69449
- st_C_class,2212,69466
- st_C_class, st_C_template,2212,69466
- st_C_struct,2213,69495
- st_C_struct, st_C_extern,2213,69495
- st_C_struct, st_C_extern, st_C_enum,2213,69495
- st_C_struct, st_C_extern, st_C_enum, st_C_define,2213,69495
- st_C_struct, st_C_extern, st_C_enum, st_C_define, st_C_typedef2213,69495
-struct C_stab_entry 2271,71278
-hash 2275,71409
-in_word_set 2321,72937
- TOTAL_KEYWORDS 2325,73018
- MIN_WORD_LENGTH 2326,73045
- MAX_WORD_LENGTH 2327,73072
- MIN_HASH_VALUE 2328,73100
- MAX_HASH_VALUE 2329,73126
-C_symtype 2387,74985
-static bool inattribute;2400,75234
- fvnone,2408,75435
- fdefunkey,2409,75466
- fdefunname,2410,75512
- foperator,2411,75556
- fvnameseen,2412,75613
- fstartlist,2413,75666
- finlist,2414,75722
- flistseen,2415,75765
- fignore,2416,75813
- vignore 2417,75856
-} fvdef;2418,75901
-static bool fvextern;2420,75911
- tnone,2428,76089
- tkeyseen,2429,76119
- ttypeseen,2430,76160
- tinbody,2431,76199
- tend,2432,76238
- tignore 2433,76279
-} typdef;2434,76320
- snone,2443,76499
- skeyseen,2445,76575
- stagseen,2446,76620
- scolonseen 2447,76661
-} structdef;2448,76715
-static const char *objtag objtag2453,76809
- dnone,2460,76942
- dsharpseen,2461,76972
- ddefineseen,2462,77025
- dignorerest 2463,77070
-} definedef;2464,77112
- onone,2472,77267
- oprotocol,2473,77297
- oimplementation,2474,77347
- otagseen,2475,77395
- oparenseen,2476,77431
- ocatseen,2477,77486
- oinbody,2478,77525
- omethodsign,2479,77568
- omethodtag,2480,77626
- omethodcolon,2481,77666
- omethodparm,2482,77709
- oignore 2483,77755
-} objdef;2484,77787
-static struct tok2491,77944
-} token;2508,78626
-} cstack;2523,79136
-#define nestlev 2525,79264
-#define instruct 2527,79369
-pushclass_above 2531,79489
-popclass_above 2550,79948
-write_classname 2564,80162
-consider_token 2613,81341
-} lbs[lbs2924,88532
-#define current_lb_is_new 2926,88543
-#define switch_line_buffers(2927,88588
-#define curlb 2929,88641
-#define newlb 2930,88672
-#define curlinepos 2931,88703
-#define newlinepos 2932,88744
-#define plainc 2934,88786
-#define cplpl 2935,88830
-#define cjava 2936,88861
-#define CNL_SAVE_DEFINEDEF(2938,88905
-#define CNL(2947,89117
-make_C_tag 2960,89375
-C_entries 2986,90194
-default_C_entries 3833,110156
-plain_C_entries 3840,110276
-Cplusplus_entries 3847,110364
-Cjava_entries 3854,110460
-Cstar_entries 3861,110550
-Yacc_entries 3868,110642
-#define LOOP_ON_INPUT_LINES(3875,110720
-#define LOOKING_AT(3884,111056
-#define LOOKING_AT_NOCASE(3891,111461
-just_read_file 3901,111861
-F_takeprec 3914,112039
-F_getit 3937,112366
-Fortran_functions 3961,112840
-Ada_getit 4052,114669
-Ada_funcs 4115,116044
-Asm_labels 4228,118582
-Perl_functions 4261,119549
-Python_functions 4357,122057
-PHP_functions 4387,122684
-Cobol_paragraphs 4466,124471
-Makefile_targets 4494,125029
-Pascal_functions 4529,125950
-L_getit 4709,130318
-Lisp_functions 4725,130664
-Lua_functions 4785,131850
-PS_functions 4811,132385
-Forth_words 4841,133053
-Scheme_functions 4877,134092
-static linebuffer *TEX_toktab TEX_toktab4908,134781
-static const char *TEX_defenv TEX_defenv4912,134974
-static char TEX_esc 4920,135261
-static char TEX_opgrp 4921,135289
-static char TEX_clgrp 4922,135318
-TeX_commands 4928,135395
-#define TEX_LESC 4986,136652
-#define TEX_SESC 4987,136674
-TEX_mode 4992,136804
-TEX_decode_env 5026,137509
-Texinfo_nodes 5071,138554
-HTML_labels 5094,139013
-Prolog_functions 5219,142347
-prolog_skip_comment 5255,143128
-prolog_pr 5281,143736
-prolog_atom 5319,144628
-Erlang_functions 5379,145666
-erlang_func 5438,146965
-erlang_attribute 5476,147642
-erlang_atom 5496,148061
-scan_separators 5534,149080
-analyze_regex 5586,150460
-add_regex 5654,152050
-substitute 5767,154797
-free_regexps 5814,155837
-regex_tag_multiline 5836,156291
-nocase_tail 5913,158263
-get_tag 5928,158519
-readline_internal 5959,159455
-readline 6037,161296
-savestr 6230,167243
-savenstr 6240,167473
-skip_spaces 6249,167679
-skip_non_spaces 6258,167833
-skip_name 6267,167983
-fatal 6277,168156
-pfatal 6284,168253
-suggest_asking_for_help 6291,168332
-error 6300,168554
-concat 6313,168846
-etags_getcwd 6329,169259
-relative_filename 6350,169725
-absolute_filename 6389,170751
-absolute_dirname 6453,172416
-filename_is_absolute 6472,172845
-canonicalize_filename 6484,173096
-# define ISUPPER(6491,173235
-linebuffer_init 6514,173656
-linebuffer_setlen 6524,173887
-xmalloc 6536,174148
-xrealloc 6545,174314
+char pot_etags_version[pot_etags_version81,3471
+# undef DEBUG84,3553
+# define DEBUG 85,3568
+# define DEBUG 87,3595
+# define NDEBUG 88,3618
+# define _GNU_SOURCE 94,3706
+# undef MSDOS100,3877
+# undef WINDOWSNT101,3891
+# define WINDOWSNT102,3910
+# undef MSDOS106,3969
+# define MSDOS 107,3983
+# define MSDOS 110,4033
+# define MAXPATHLEN 115,4112
+# undef HAVE_NTGUI116,4142
+# undef DOS_NT117,4161
+# define DOS_NT118,4177
+# undef assert 135,4483
+# define assert(136,4542
+# undef CTAGS146,4858
+# define CTAGS 147,4873
+# define CTAGS 149,4899
+#define streq(152,4928
+#define strcaseeq(153,4997
+#define strneq(154,5076
+#define strncaseeq(155,5152
+#define CHARS 157,5239
+#define CHAR(158,5279
+#define iswhite(159,5330
+#define notinname(160,5395
+#define begtoken(161,5470
+#define intoken(162,5543
+#define endtoken(163,5615
+#define ISALNUM(165,5685
+#define ISALPHA(166,5723
+#define ISDIGIT(167,5761
+#define ISLOWER(168,5799
+#define lowcase(170,5838
+#define xnew(179,6016
+#define xrnew(180,6084
+typedef void Lang_function 182,6165
+} compressor;188,6366
+} language;199,6836
+typedef struct fdesc201,6849
+} fdesc;212,7367
+typedef struct node_st214,7377
+} node;225,7895
+} linebuffer;239,8249
+ at_language,245,8345
+ at_regexp,246,8394
+ at_filename,247,8438
+ at_stdin,248,8474
+ at_end 249,8517
+} argument;253,8699
+typedef struct regexp256,8759
+} regexp;268,9326
+static void error 311,10781
+# undef STDIN408,15074
+#define STDIN 411,15096
+static compressor compressors[compressors457,17665
+static const char *Ada_suffixes Ada_suffixes473,17908
+static const char Ada_help 475,17978
+static const char *Asm_suffixes Asm_suffixes493,18581
+static const char Asm_help 504,18977
+static const char *default_C_suffixes default_C_suffixes512,19313
+static const char default_C_help 515,19414
+static const char default_C_help 523,19851
+static const char *Cplusplus_suffixes Cplusplus_suffixes535,20461
+static const char Cplusplus_help 540,20659
+static const char *Cjava_suffixes Cjava_suffixes549,21114
+static char Cjava_help 551,21173
+static const char *Cobol_suffixes Cobol_suffixes556,21338
+static char Cobol_help 558,21403
+static const char *Cstar_suffixes Cstar_suffixes562,21544
+static const char *Erlang_suffixes Erlang_suffixes565,21608
+static const char Erlang_help 567,21674
+const char *Forth_suffixes Forth_suffixes571,21800
+static const char Forth_help 573,21858
+static const char *Fortran_suffixes Fortran_suffixes577,22009
+static const char Fortran_help 579,22086
+static const char *HTML_suffixes HTML_suffixes582,22191
+static const char HTML_help 584,22265
+static const char *Lisp_suffixes Lisp_suffixes589,22453
+static const char Lisp_help 591,22557
+static const char *Lua_suffixes Lua_suffixes598,22872
+static const char Lua_help 600,22935
+static const char *Makefile_filenames Makefile_filenames603,23011
+static const char Makefile_help 605,23134
+static const char *Objc_suffixes Objc_suffixes609,23278
+static const char Objc_help 613,23400
+static const char *Pascal_suffixes Pascal_suffixes619,23715
+static const char Pascal_help 621,23779
+static const char *Perl_suffixes Perl_suffixes626,23967
+static const char *Perl_interpreters Perl_interpreters628,24029
+static const char Perl_help 630,24101
+static const char *PHP_suffixes PHP_suffixes637,24452
+static const char PHP_help 639,24524
+static const char *plain_C_suffixes plain_C_suffixes643,24679
+static const char *PS_suffixes PS_suffixes647,24763
+static const char PS_help 649,24849
+static const char *Prolog_suffixes Prolog_suffixes652,24932
+static const char Prolog_help 654,24994
+static const char *Python_suffixes Python_suffixes658,25108
+static const char Python_help 660,25166
+static const char *Scheme_suffixes Scheme_suffixes665,25348
+static const char Scheme_help 667,25461
+static const char *TeX_suffixes TeX_suffixes672,25684
+static const char TeX_help 674,25782
+static const char *Texinfo_suffixes Texinfo_suffixes686,26317
+static const char Texinfo_help 688,26396
+static const char *Yacc_suffixes Yacc_suffixes691,26493
+static const char Yacc_help 693,26607
+static const char auto_help 699,26857
+static const char none_help 703,27021
+static const char no_lang_help 707,27144
+static language lang_names 718,27356
+print_language_names 753,29533
+# define EMACS_NAME 786,30756
+# define VERSION 789,30812
+print_version 792,30870
+# define PRINT_UNDOCUMENTED_OPTIONS_HELP 804,31174
+print_help 808,31251
+main 981,37439
+get_compressor_from_suffix 1319,46218
+get_language_from_langname 1355,47159
+get_language_from_interpreter 1377,47546
+get_language_from_filename 1399,47977
+process_file_name 1433,48835
+process_file 1555,51666
+init 1632,54151
+find_entries 1656,54902
+make_tag 1814,59708
+pfnote 1856,60943
+free_tree 1917,62745
+free_fdesc 1935,63030
+add_node 1955,63473
+invalidate_nodes 2035,65538
+static int number_len 2068,66194
+total_size_of_entries 2087,66695
+put_entries 2107,67155
+#define C_EXT 2193,68996
+#define C_PLAIN 2194,69038
+#define C_PLPL 2195,69071
+#define C_STAR 2196,69105
+#define C_JAVA 2197,69138
+#define C_AUTO 2198,69173
+#define YACC 2199,69243
+enum sym_type2204,69313
+ st_none,2206,69329
+ st_C_objprot,2207,69340
+ st_C_objprot, st_C_objimpl,2207,69340
+ st_C_objprot, st_C_objimpl, st_C_objend,2207,69340
+ st_C_gnumacro,2208,69383
+ st_C_ignore,2209,69400
+ st_C_ignore, st_C_attribute,2209,69400
+ st_C_javastruct,2210,69431
+ st_C_operator,2211,69450
+ st_C_class,2212,69467
+ st_C_class, st_C_template,2212,69467
+ st_C_struct,2213,69496
+ st_C_struct, st_C_extern,2213,69496
+ st_C_struct, st_C_extern, st_C_enum,2213,69496
+ st_C_struct, st_C_extern, st_C_enum, st_C_define,2213,69496
+ st_C_struct, st_C_extern, st_C_enum, st_C_define, st_C_typedef2213,69496
+struct C_stab_entry 2271,71279
+hash 2275,71410
+in_word_set 2321,72938
+ TOTAL_KEYWORDS 2325,73019
+ MIN_WORD_LENGTH 2326,73046
+ MAX_WORD_LENGTH 2327,73073
+ MIN_HASH_VALUE 2328,73101
+ MAX_HASH_VALUE 2329,73127
+C_symtype 2387,74986
+static bool inattribute;2400,75235
+ fvnone,2408,75436
+ fdefunkey,2409,75467
+ fdefunname,2410,75513
+ foperator,2411,75557
+ fvnameseen,2412,75614
+ fstartlist,2413,75667
+ finlist,2414,75723
+ flistseen,2415,75766
+ fignore,2416,75814
+ vignore 2417,75857
+} fvdef;2418,75902
+static bool fvextern;2420,75912
+ tnone,2428,76090
+ tkeyseen,2429,76120
+ ttypeseen,2430,76161
+ tinbody,2431,76200
+ tend,2432,76239
+ tignore 2433,76280
+} typdef;2434,76321
+ snone,2443,76500
+ skeyseen,2445,76576
+ stagseen,2446,76621
+ scolonseen 2447,76662
+} structdef;2448,76716
+static const char *objtag objtag2453,76810
+ dnone,2460,76943
+ dsharpseen,2461,76973
+ ddefineseen,2462,77026
+ dignorerest 2463,77071
+} definedef;2464,77113
+ onone,2472,77268
+ oprotocol,2473,77298
+ oimplementation,2474,77348
+ otagseen,2475,77396
+ oparenseen,2476,77432
+ ocatseen,2477,77487
+ oinbody,2478,77526
+ omethodsign,2479,77569
+ omethodtag,2480,77627
+ omethodcolon,2481,77667
+ omethodparm,2482,77710
+ oignore 2483,77756
+} objdef;2484,77788
+static struct tok2491,77945
+} token;2508,78627
+} cstack;2523,79137
+#define nestlev 2525,79265
+#define instruct 2527,79370
+pushclass_above 2531,79490
+popclass_above 2550,79949
+write_classname 2564,80163
+consider_token 2613,81342
+} lbs[lbs2924,88533
+#define current_lb_is_new 2926,88544
+#define switch_line_buffers(2927,88589
+#define curlb 2929,88642
+#define newlb 2930,88673
+#define curlinepos 2931,88704
+#define newlinepos 2932,88745
+#define plainc 2934,88787
+#define cplpl 2935,88831
+#define cjava 2936,88862
+#define CNL_SAVE_DEFINEDEF(2938,88906
+#define CNL(2947,89118
+make_C_tag 2960,89376
+C_entries 2986,90195
+default_C_entries 3833,110157
+plain_C_entries 3840,110277
+Cplusplus_entries 3847,110365
+Cjava_entries 3854,110461
+Cstar_entries 3861,110551
+Yacc_entries 3868,110643
+#define LOOP_ON_INPUT_LINES(3875,110721
+#define LOOKING_AT(3884,111057
+#define LOOKING_AT_NOCASE(3891,111462
+just_read_file 3901,111862
+F_takeprec 3914,112040
+F_getit 3937,112367
+Fortran_functions 3961,112841
+Ada_getit 4052,114670
+Ada_funcs 4115,116045
+Asm_labels 4228,118583
+Perl_functions 4261,119550
+Python_functions 4357,122058
+PHP_functions 4387,122685
+Cobol_paragraphs 4466,124472
+Makefile_targets 4494,125030
+Pascal_functions 4529,125951
+L_getit 4709,130319
+Lisp_functions 4725,130665
+Lua_functions 4785,131851
+PS_functions 4811,132386
+Forth_words 4841,133054
+Scheme_functions 4877,134093
+static linebuffer *TEX_toktab TEX_toktab4908,134782
+static const char *TEX_defenv TEX_defenv4912,134975
+static char TEX_esc 4920,135262
+static char TEX_opgrp 4921,135290
+static char TEX_clgrp 4922,135319
+TeX_commands 4928,135396
+#define TEX_LESC 4986,136653
+#define TEX_SESC 4987,136675
+TEX_mode 4992,136805
+TEX_decode_env 5026,137510
+Texinfo_nodes 5071,138555
+HTML_labels 5094,139014
+Prolog_functions 5219,142348
+prolog_skip_comment 5255,143129
+prolog_pr 5281,143737
+prolog_atom 5319,144629
+Erlang_functions 5379,145667
+erlang_func 5438,146966
+erlang_attribute 5476,147643
+erlang_atom 5496,148062
+scan_separators 5534,149081
+analyze_regex 5586,150461
+add_regex 5654,152051
+substitute 5767,154798
+free_regexps 5814,155838
+regex_tag_multiline 5836,156292
+nocase_tail 5913,158264
+get_tag 5928,158520
+readline_internal 5959,159456
+readline 6037,161297
+savestr 6230,167244
+savenstr 6240,167474
+skip_spaces 6249,167680
+skip_non_spaces 6258,167834
+skip_name 6267,167984
+fatal 6277,168157
+pfatal 6284,168254
+suggest_asking_for_help 6291,168333
+error 6300,168555
+concat 6313,168847
+etags_getcwd 6329,169260
+relative_filename 6350,169726
+absolute_filename 6389,170752
+absolute_dirname 6453,172417
+filename_is_absolute 6472,172846
+canonicalize_filename 6484,173097
+# define ISUPPER(6491,173236
+linebuffer_init 6514,173657
+linebuffer_setlen 6524,173888
+xmalloc 6536,174149
+xrealloc 6545,174315
c-src/exit.c,47
} __libc_atexit;30,1022
@@ -604,1237 +602,1237 @@ pp287,1504
pp3(100,1616
c-src/emacs/src/gmalloc.c,3539
-#define USE_PTHREAD25,1002
-#undef get_current_dir_name33,1126
-#undef malloc64,2110
-#undef realloc65,2124
-#undef calloc66,2139
-#undef free67,2153
-#define malloc 68,2165
-#define realloc 69,2188
-#define calloc 70,2213
-#define aligned_alloc 71,2236
-#define free 72,2273
-#define DUMPED 80,2472
-#define ALLOCATED_BEFORE_DUMPING(81,2507
-extern void *malloc malloc94,2718
-#define INT_BIT 124,3934
-#define BLOCKLOG 125,3977
-#define BLOCKSIZE 126,4018
-#define BLOCKIFY(127,4052
-#define HEAP 131,4215
-#define FINAL_FREE_BLOCKS 135,4391
- } malloc_info;167,5388
-#define BLOCK(176,5620
-#define ADDRESS(177,5682
-struct list186,5939
-struct alignlist196,6153
-#define LOCK(223,7064
-#define UNLOCK(228,7195
-#define LOCK_ALIGNED_BLOCKS(233,7329
-#define UNLOCK_ALIGNED_BLOCKS(238,7484
-#define LOCK(244,7649
-#define UNLOCK(245,7664
-#define LOCK_ALIGNED_BLOCKS(246,7681
-#define UNLOCK_ALIGNED_BLOCKS(247,7711
-enum mcheck_status283,9092
- MCHECK_DISABLED 285,9115
- MCHECK_OK,286,9187
- MCHECK_FREE,287,9226
- MCHECK_HEAD,288,9270
- MCHECK_TAIL 289,9334
-struct mstats308,10153
-char *_heapbase;_heapbase355,11829
-malloc_info *_heapinfo;_heapinfo358,11927
-static size_t heapsize;361,11983
-size_t _heapindex;364,12047
-size_t _heaplimit;367,12109
-struct list _fraghead[_fraghead370,12171
-size_t _chunks_used;373,12229
-size_t _bytes_used;374,12250
-size_t _chunks_free;375,12270
-size_t _bytes_free;376,12291
-int __malloc_initialized;379,12340
-size_t __malloc_extra_blocks;381,12367
-static int state_protected_p;400,12912
-static size_t last_state_size;401,12942
-static malloc_info *last_heapinfo;last_heapinfo402,12973
-protect_malloc_state 405,13014
-#define PROTECT_MALLOC_STATE(426,13627
-#define PROTECT_MALLOC_STATE(429,13697
-align 435,13794
-get_contiguous_space 466,14616
-register_heapinfo 497,15325
-pthread_mutex_t _malloc_mutex 517,15879
-pthread_mutex_t _aligned_blocks_mutex 518,15938
-int _malloc_thread_enabled_p;519,16005
-malloc_atfork_handler_prepare 522,16048
-malloc_atfork_handler_parent 529,16139
-malloc_atfork_handler_child 536,16233
-malloc_enable_thread 544,16375
-malloc_initialize_1 563,16961
-__malloc_initialize 594,17793
-static int morecore_recursing;604,17926
-morecore_nolock 609,18066
-_malloc_internal_nolock 722,21584
-_malloc_internal 920,28102
-malloc 932,28247
-_malloc 961,29140
-_free 967,29196
-_realloc 973,29240
-struct alignlist *_aligned_blocks _aligned_blocks1004,30345
-_free_internal_nolock 1009,30474
-_free_internal 1255,38476
-free 1265,38603
-weak_alias 1277,38799
-#define min(1306,39813
-_realloc_internal_nolock 1319,40309
-_realloc_internal 1435,43563
-realloc 1447,43726
-calloc 1478,44894
-#define __sbrk 1513,46042
-__default_morecore 1525,46511
-aligned_alloc 1557,47522
-memalign 1647,49704
-posix_memalign 1656,49909
-static size_t pagesize;1703,51317
-valloc 1706,51349
-#undef malloc1715,51490
-#undef realloc1716,51504
-#undef calloc1717,51519
-#undef aligned_alloc1718,51533
-#undef free1719,51554
-hybrid_malloc 1736,52083
-hybrid_calloc 1744,52188
-hybrid_free 1752,52319
-hybrid_aligned_alloc 1765,52626
-hybrid_realloc 1780,52984
-hybrid_get_current_dir_name 1811,53797
-#define MAGICWORD 1854,55206
-#define MAGICFREE 1855,55261
-#define MAGICBYTE 1856,55316
-#define MALLOCFLOOD 1857,55348
-#define FREEFLOOD 1858,55382
-struct hdr1860,55415
-checkhdr 1867,55581
-freehook 1891,56022
-mallochook 1927,56804
-reallochook 1944,57143
-mabort 1978,57901
-static int mcheck_used 2012,58586
-mcheck 2015,58619
-mprobe 2035,59138
+#define USE_PTHREAD25,1003
+#undef get_current_dir_name33,1127
+#undef malloc64,2111
+#undef realloc65,2125
+#undef calloc66,2140
+#undef free67,2154
+#define malloc 68,2166
+#define realloc 69,2189
+#define calloc 70,2214
+#define aligned_alloc 71,2237
+#define free 72,2274
+#define DUMPED 80,2473
+#define ALLOCATED_BEFORE_DUMPING(81,2508
+extern void *malloc malloc94,2719
+#define INT_BIT 124,3935
+#define BLOCKLOG 125,3978
+#define BLOCKSIZE 126,4019
+#define BLOCKIFY(127,4053
+#define HEAP 131,4216
+#define FINAL_FREE_BLOCKS 135,4392
+ } malloc_info;167,5389
+#define BLOCK(176,5621
+#define ADDRESS(177,5683
+struct list186,5940
+struct alignlist196,6154
+#define LOCK(223,7065
+#define UNLOCK(228,7196
+#define LOCK_ALIGNED_BLOCKS(233,7330
+#define UNLOCK_ALIGNED_BLOCKS(238,7485
+#define LOCK(244,7650
+#define UNLOCK(245,7665
+#define LOCK_ALIGNED_BLOCKS(246,7682
+#define UNLOCK_ALIGNED_BLOCKS(247,7712
+enum mcheck_status283,9093
+ MCHECK_DISABLED 285,9116
+ MCHECK_OK,286,9188
+ MCHECK_FREE,287,9227
+ MCHECK_HEAD,288,9271
+ MCHECK_TAIL 289,9335
+struct mstats308,10154
+char *_heapbase;_heapbase355,11831
+malloc_info *_heapinfo;_heapinfo358,11929
+static size_t heapsize;361,11985
+size_t _heapindex;364,12049
+size_t _heaplimit;367,12111
+struct list _fraghead[_fraghead370,12173
+size_t _chunks_used;373,12231
+size_t _bytes_used;374,12252
+size_t _chunks_free;375,12272
+size_t _bytes_free;376,12293
+int __malloc_initialized;379,12342
+size_t __malloc_extra_blocks;381,12369
+static int state_protected_p;400,12914
+static size_t last_state_size;401,12944
+static malloc_info *last_heapinfo;last_heapinfo402,12975
+protect_malloc_state 405,13016
+#define PROTECT_MALLOC_STATE(426,13629
+#define PROTECT_MALLOC_STATE(429,13699
+align 435,13796
+get_contiguous_space 466,14618
+register_heapinfo 497,15327
+pthread_mutex_t _malloc_mutex 517,15881
+pthread_mutex_t _aligned_blocks_mutex 518,15940
+int _malloc_thread_enabled_p;519,16007
+malloc_atfork_handler_prepare 522,16050
+malloc_atfork_handler_parent 529,16141
+malloc_atfork_handler_child 536,16235
+malloc_enable_thread 544,16377
+malloc_initialize_1 563,16963
+__malloc_initialize 594,17795
+static int morecore_recursing;604,17928
+morecore_nolock 609,18068
+_malloc_internal_nolock 722,21586
+_malloc_internal 920,28104
+malloc 932,28249
+_malloc 961,29142
+_free 967,29198
+_realloc 973,29242
+struct alignlist *_aligned_blocks _aligned_blocks1004,30348
+_free_internal_nolock 1009,30477
+_free_internal 1255,38479
+free 1265,38606
+weak_alias 1277,38802
+#define min(1306,39817
+_realloc_internal_nolock 1319,40313
+_realloc_internal 1435,43567
+realloc 1447,43730
+calloc 1478,44899
+#define __sbrk 1513,46048
+__default_morecore 1525,46517
+aligned_alloc 1557,47529
+memalign 1647,49711
+posix_memalign 1656,49916
+static size_t pagesize;1703,51325
+valloc 1706,51357
+#undef malloc1715,51498
+#undef realloc1716,51512
+#undef calloc1717,51527
+#undef aligned_alloc1718,51541
+#undef free1719,51562
+hybrid_malloc 1736,52091
+hybrid_calloc 1744,52196
+hybrid_free 1752,52327
+hybrid_aligned_alloc 1765,52634
+hybrid_realloc 1780,52990
+hybrid_get_current_dir_name 1811,53803
+#define MAGICWORD 1854,55213
+#define MAGICFREE 1855,55268
+#define MAGICBYTE 1856,55323
+#define MALLOCFLOOD 1857,55355
+#define FREEFLOOD 1858,55389
+struct hdr1860,55422
+checkhdr 1867,55588
+freehook 1891,56029
+mallochook 1927,56811
+reallochook 1944,57150
+mabort 1978,57908
+static int mcheck_used 2012,58593
+mcheck 2015,58626
+mprobe 2035,59145
c-src/emacs/src/regex.h,3761
-#define _REGEX_H 21,836
-typedef unsigned long reg_syntax_t;43,1577
-#define RE_BACKSLASH_ESCAPE_IN_LISTS 47,1749
-#define RE_BK_PLUS_QM 52,1969
-#define RE_CHAR_CLASSES 58,2298
-#define RE_CONTEXT_INDEP_ANCHORS 72,3032
-#define RE_CONTEXT_INDEP_OPS 80,3458
-#define RE_CONTEXT_INVALID_OPS 84,3658
-#define RE_DOT_NEWLINE 88,3801
-#define RE_DOT_NOT_NULL 92,3937
-#define RE_HAT_LISTS_NOT_NEWLINE 96,4082
-#define RE_INTERVALS 101,4292
-#define RE_LIMITED_OPS 105,4441
-#define RE_NEWLINE_ALT 109,4583
-#define RE_NO_BK_BRACES 114,4773
-#define RE_NO_BK_PARENS 118,4964
-#define RE_NO_BK_REFS 122,5120
-#define RE_NO_BK_VBAR 126,5316
-#define RE_NO_EMPTY_RANGES 132,5610
-#define RE_UNMATCHED_RIGHT_PAREN_ORD 136,5766
-#define RE_NO_POSIX_BACKTRACKING 140,5937
-#define RE_NO_GNU_OPS 144,6133
-#define RE_FRUGAL 147,6253
-#define RE_SHY_GROUPS 150,6360
-#define RE_NO_NEWLINE_ANCHOR 153,6468
-#define RE_DEBUG 161,6884
-#define RE_SYNTAX_EMACS 183,7684
-#define RE_SYNTAX_AWK 186,7780
-#define RE_SYNTAX_GNU_AWK 193,8084
-#define RE_SYNTAX_POSIX_AWK 197,8255
-#define RE_SYNTAX_GREP 201,8393
-#define RE_SYNTAX_EGREP 206,8549
-#define RE_SYNTAX_POSIX_EGREP 212,8765
-#define RE_SYNTAX_ED 216,8910
-#define RE_SYNTAX_SED 218,8954
-#define _RE_SYNTAX_POSIX_COMMON 221,9072
-#define RE_SYNTAX_POSIX_BASIC 225,9215
-#define RE_SYNTAX_POSIX_MINIMAL_BASIC 231,9508
-#define RE_SYNTAX_POSIX_EXTENDED 234,9598
-#define RE_SYNTAX_POSIX_MINIMAL_EXTENDED 242,9967
-# undef RE_DUP_MAX253,10454
-#define RE_DUP_MAX 256,10540
-#define REG_EXTENDED 263,10762
-#define REG_ICASE 267,10886
-#define REG_NEWLINE 272,11070
-#define REG_NOSUB 276,11248
-#define REG_NOTBOL 286,11614
-#define REG_NOTEOL 289,11688
- REG_ENOSYS 297,11859
- REG_NOERROR 300,11941
- REG_NOMATCH,301,11976
- REG_BADPAT,305,12123
- REG_ECOLLATE,306,12162
- REG_ECTYPE,307,12203
- REG_EESCAPE,308,12255
- REG_ESUBREG,309,12298
- REG_EBRACK,310,12345
- REG_EPAREN,311,12391
- REG_EBRACE,312,12436
- REG_BADBR,313,12472
- REG_ERANGE,314,12519
- REG_ESPACE,315,12560
- REG_BADRPT,316,12601
- REG_EEND,319,12693
- REG_ESIZE,320,12728
- REG_ERPAREN,321,12790
- REG_ERANGEX 322,12859
-} reg_errcode_t;323,12911
-# define RE_TRANSLATE_TYPE 332,13273
-struct re_pattern_buffer335,13315
-#define REGS_UNALLOCATED 376,14889
-#define REGS_REALLOCATE 377,14916
-#define REGS_FIXED 378,14942
-typedef struct re_pattern_buffer regex_t;416,16098
-typedef ssize_t regoff_t;423,16492
-struct re_registers428,16652
-# define RE_NREGS 440,16942
-} regmatch_t;451,17317
-# define _Restrict_ 540,20886
-# define _Restrict_ 542,20979
-# define _Restrict_544,21018
-# define _Restrict_arr_ 555,21418
-# define _Restrict_arr_557,21461
-# define CHAR_CLASS_MAX_LENGTH 593,22470
-# define CHAR_CLASS_MAX_LENGTH 597,22648
-typedef wctype_t re_wctype_t;599,22692
-typedef wchar_t re_wchar_t;600,22722
-# define re_wctype 601,22750
-# define re_iswctype 602,22776
-# define re_wctype_to_bit(603,22806
-# define CHAR_CLASS_MAX_LENGTH 605,22844
-# define btowc(606,22906
-typedef enum { RECC_ERROR 609,22953
- RECC_ALNUM,610,22984
- RECC_ALNUM, RECC_ALPHA,610,22984
- RECC_ALNUM, RECC_ALPHA, RECC_WORD,610,22984
- RECC_GRAPH,611,23027
- RECC_GRAPH, RECC_PRINT,611,23027
- RECC_LOWER,612,23059
- RECC_LOWER, RECC_UPPER,612,23059
- RECC_PUNCT,613,23091
- RECC_PUNCT, RECC_CNTRL,613,23091
- RECC_DIGIT,614,23123
- RECC_DIGIT, RECC_XDIGIT,614,23123
- RECC_BLANK,615,23156
- RECC_BLANK, RECC_SPACE,615,23156
- RECC_MULTIBYTE,616,23188
- RECC_MULTIBYTE, RECC_NONASCII,616,23188
- RECC_ASCII,617,23227
- RECC_ASCII, RECC_UNIBYTE617,23227
-} re_wctype_t;618,23260
-typedef int re_wchar_t;623,23387
+#define _REGEX_H 21,837
+typedef unsigned long reg_syntax_t;43,1578
+#define RE_BACKSLASH_ESCAPE_IN_LISTS 47,1750
+#define RE_BK_PLUS_QM 52,1970
+#define RE_CHAR_CLASSES 58,2299
+#define RE_CONTEXT_INDEP_ANCHORS 72,3033
+#define RE_CONTEXT_INDEP_OPS 80,3459
+#define RE_CONTEXT_INVALID_OPS 84,3659
+#define RE_DOT_NEWLINE 88,3802
+#define RE_DOT_NOT_NULL 92,3938
+#define RE_HAT_LISTS_NOT_NEWLINE 96,4083
+#define RE_INTERVALS 101,4293
+#define RE_LIMITED_OPS 105,4442
+#define RE_NEWLINE_ALT 109,4584
+#define RE_NO_BK_BRACES 114,4774
+#define RE_NO_BK_PARENS 118,4965
+#define RE_NO_BK_REFS 122,5121
+#define RE_NO_BK_VBAR 126,5317
+#define RE_NO_EMPTY_RANGES 132,5611
+#define RE_UNMATCHED_RIGHT_PAREN_ORD 136,5767
+#define RE_NO_POSIX_BACKTRACKING 140,5938
+#define RE_NO_GNU_OPS 144,6134
+#define RE_FRUGAL 147,6254
+#define RE_SHY_GROUPS 150,6361
+#define RE_NO_NEWLINE_ANCHOR 153,6469
+#define RE_DEBUG 161,6885
+#define RE_SYNTAX_EMACS 183,7685
+#define RE_SYNTAX_AWK 186,7781
+#define RE_SYNTAX_GNU_AWK 193,8085
+#define RE_SYNTAX_POSIX_AWK 197,8256
+#define RE_SYNTAX_GREP 201,8394
+#define RE_SYNTAX_EGREP 206,8550
+#define RE_SYNTAX_POSIX_EGREP 212,8766
+#define RE_SYNTAX_ED 216,8911
+#define RE_SYNTAX_SED 218,8955
+#define _RE_SYNTAX_POSIX_COMMON 221,9073
+#define RE_SYNTAX_POSIX_BASIC 225,9216
+#define RE_SYNTAX_POSIX_MINIMAL_BASIC 231,9509
+#define RE_SYNTAX_POSIX_EXTENDED 234,9599
+#define RE_SYNTAX_POSIX_MINIMAL_EXTENDED 242,9968
+# undef RE_DUP_MAX253,10455
+#define RE_DUP_MAX 256,10541
+#define REG_EXTENDED 263,10763
+#define REG_ICASE 267,10887
+#define REG_NEWLINE 272,11071
+#define REG_NOSUB 276,11249
+#define REG_NOTBOL 286,11615
+#define REG_NOTEOL 289,11689
+ REG_ENOSYS 297,11860
+ REG_NOERROR 300,11942
+ REG_NOMATCH,301,11977
+ REG_BADPAT,305,12124
+ REG_ECOLLATE,306,12163
+ REG_ECTYPE,307,12204
+ REG_EESCAPE,308,12256
+ REG_ESUBREG,309,12299
+ REG_EBRACK,310,12346
+ REG_EPAREN,311,12392
+ REG_EBRACE,312,12437
+ REG_BADBR,313,12473
+ REG_ERANGE,314,12520
+ REG_ESPACE,315,12561
+ REG_BADRPT,316,12602
+ REG_EEND,319,12694
+ REG_ESIZE,320,12729
+ REG_ERPAREN,321,12791
+ REG_ERANGEX 322,12860
+} reg_errcode_t;323,12912
+# define RE_TRANSLATE_TYPE 332,13274
+struct re_pattern_buffer335,13316
+#define REGS_UNALLOCATED 376,14890
+#define REGS_REALLOCATE 377,14917
+#define REGS_FIXED 378,14943
+typedef struct re_pattern_buffer regex_t;416,16099
+typedef ssize_t regoff_t;423,16493
+struct re_registers428,16653
+# define RE_NREGS 440,16943
+} regmatch_t;451,17318
+# define _Restrict_ 540,20887
+# define _Restrict_ 542,20980
+# define _Restrict_544,21019
+# define _Restrict_arr_ 555,21419
+# define _Restrict_arr_557,21462
+# define CHAR_CLASS_MAX_LENGTH 593,22471
+# define CHAR_CLASS_MAX_LENGTH 597,22649
+typedef wctype_t re_wctype_t;599,22693
+typedef wchar_t re_wchar_t;600,22723
+# define re_wctype 601,22751
+# define re_iswctype 602,22777
+# define re_wctype_to_bit(603,22807
+# define CHAR_CLASS_MAX_LENGTH 605,22845
+# define btowc(606,22907
+typedef enum { RECC_ERROR 609,22954
+ RECC_ALNUM,610,22985
+ RECC_ALNUM, RECC_ALPHA,610,22985
+ RECC_ALNUM, RECC_ALPHA, RECC_WORD,610,22985
+ RECC_GRAPH,611,23028
+ RECC_GRAPH, RECC_PRINT,611,23028
+ RECC_LOWER,612,23060
+ RECC_LOWER, RECC_UPPER,612,23060
+ RECC_PUNCT,613,23092
+ RECC_PUNCT, RECC_CNTRL,613,23092
+ RECC_DIGIT,614,23124
+ RECC_DIGIT, RECC_XDIGIT,614,23124
+ RECC_BLANK,615,23157
+ RECC_BLANK, RECC_SPACE,615,23157
+ RECC_MULTIBYTE,616,23189
+ RECC_MULTIBYTE, RECC_NONASCII,616,23189
+ RECC_ASCII,617,23228
+ RECC_ASCII, RECC_UNIBYTE617,23228
+} re_wctype_t;618,23261
+typedef int re_wchar_t;623,23388
c-src/emacs/src/keyboard.c,15539
-volatile int interrupt_input_blocked;76,1808
-volatile bool pending_signals;80,1944
-#define KBD_BUFFER_SIZE 82,1976
-KBOARD *initial_kboard;initial_kboard84,2006
-KBOARD *current_kboard;current_kboard85,2030
-static KBOARD *all_kboards;all_kboards86,2054
-static bool single_kboard;89,2154
-#define NUM_RECENT_KEYS 91,2182
-static int recent_keys_index;94,2269
-static int total_keys;97,2357
-static Lisp_Object recent_keys;100,2443
-Lisp_Object this_command_keys;107,2777
-ptrdiff_t this_command_key_count;108,2808
-static bool this_command_key_count_reset;112,2922
-static Lisp_Object raw_keybuf;116,3074
-static int raw_keybuf_count;117,3105
-#define GROW_RAW_KEYBUF 119,3135
-static ptrdiff_t this_single_command_key_start;125,3350
-static ptrdiff_t before_command_key_count;129,3498
-static ptrdiff_t before_command_echo_length;130,3541
-sigjmp_buf return_to_command_loop;135,3677
-static Lisp_Object recover_top_level_message;138,3791
-static Lisp_Object regular_top_level_message;143,3930
-static sys_jmp_buf getcjmp;147,4031
-bool waiting_for_input;150,4095
-static bool echoing;154,4186
-static struct kboard *ok_to_echo_at_next_pause;ok_to_echo_at_next_pause159,4328
-struct kboard *echo_kboard;echo_kboard166,4632
-Lisp_Object echo_message_buffer;171,4744
-bool immediate_quit;174,4837
-int quit_char;192,5623
-EMACS_INT command_loop_level;195,5680
-Lisp_Object unread_switch_frame;204,6108
-static ptrdiff_t last_non_minibuf_size;207,6216
-uintmax_t num_input_events;210,6334
-static EMACS_INT last_auto_save;214,6428
-static ptrdiff_t last_point_position;217,6523
-Lisp_Object internal_last_event_frame;228,7028
-static Lisp_Object read_key_sequence_cmd;232,7168
-static Lisp_Object read_key_sequence_remapped;233,7210
-static FILE *dribble;dribble236,7310
-bool input_pending;239,7368
-static bool input_was_pending;287,10022
-static struct input_event kbd_buffer[kbd_buffer291,10107
-static struct input_event *kbd_fetch_ptr;kbd_fetch_ptr297,10386
-static struct input_event * volatile kbd_store_ptr;302,10601
-unsigned timers_run;320,11296
-struct timespec *input_available_clear_time;input_available_clear_time324,11408
-bool interrupt_input;328,11573
-bool interrupts_deferred;331,11671
-static struct timespec timer_idleness_start_time;335,11746
-static struct timespec timer_last_idleness_start_time;340,11916
-#define READABLE_EVENTS_DO_TIMERS_NOW 346,12046
-#define READABLE_EVENTS_FILTER_EVENTS 347,12094
-#define READABLE_EVENTS_IGNORE_SQUEEZABLES 348,12142
-kset_echo_string 392,14088
-kset_kbd_queue 397,14184
-kset_keyboard_translate_table 402,14276
-kset_last_prefix_arg 407,14399
-kset_last_repeatable_command 412,14504
-kset_local_function_key_map 417,14625
-kset_overriding_terminal_local_map 422,14744
-kset_real_last_command 427,14877
-kset_system_key_syms 432,14986
-echo_add_key 443,15249
-echo_char 527,17527
-echo_dash 541,17813
-echo_now 586,19140
-cancel_echoing 635,20614
-echo_length 648,20922
-echo_truncate 660,21253
-add_command_key 672,21582
-recursive_edit_1 697,22406
-record_auto_save 742,23848
-force_auto_save_soon 751,24016
-DEFUN ("recursive-edit", Frecursive_edit,759,24137
-DEFUN ("recursive-edit", Frecursive_edit,recursive-edit759,24137
-recursive_edit_unwind 804,25747
-any_kboard_state 817,26013
-single_kboard_state 838,26665
-not_single_kboard_state 848,26803
-struct kboard_stack858,27065
-static struct kboard_stack *kboard_stack;kboard_stack864,27138
-push_kboard 867,27186
-pop_kboard 879,27375
-temporarily_switch_to_single_kboard 914,28263
-record_single_kboard_state 943,29437
-restore_kboard_configuration 952,29621
-cmd_error 970,30077
-cmd_error_internal 1024,31510
-DEFUN ("command-error-default-function", Fcommand_error_default_function,1043,32030
-DEFUN ("command-error-default-function", Fcommand_error_default_function,command-error-default-function1043,32030
-command_loop 1094,33916
-command_loop_2 1134,35135
-top_level_2 1146,35339
-top_level_1 1152,35417
-DEFUN ("top-level", Ftop_level,1164,35787
-DEFUN ("top-level", Ftop_level,top-level1164,35787
-user_error 1183,36288
-DEFUN ("exit-recursive-edit", Fexit_recursive_edit,1189,36429
-DEFUN ("exit-recursive-edit", Fexit_recursive_edit,exit-recursive-edit1189,36429
-DEFUN ("abort-recursive-edit", Fabort_recursive_edit,1201,36819
-DEFUN ("abort-recursive-edit", Fabort_recursive_edit,abort-recursive-edit1201,36819
-tracking_off 1216,37281
-DEFUN ("internal--track-mouse", Ftrack_mouse,1234,37816
-DEFUN ("internal--track-mouse", Ftrack_mouse,track-mouse1234,37816
-bool ignore_mouse_drag_p;1256,38392
-some_mouse_moved 1259,38441
-Lisp_Object last_undo_boundary;1287,39032
-command_loop_1 1294,39273
-read_menu_command 1649,50889
-adjust_point_for_property 1678,51617
-safe_run_hooks_1 1831,57339
-safe_run_hooks_error 1841,57569
-safe_run_hook_funcall 1878,58576
-safe_run_hooks 1893,59058
-int poll_suppress_count;1908,59397
-static struct atimer *poll_timer;poll_timer1915,59487
-poll_for_input_1 1919,59589
-poll_for_input 1930,59789
-start_polling 1942,60053
-input_polling_used 1979,61091
-stop_polling 1994,61390
-set_poll_suppress_count 2009,61759
-bind_polling_period 2029,62141
-make_ctrl_char 2048,62492
-show_help_echo 2113,64455
-static Lisp_Object help_form_saved_window_configs;2156,65638
-read_char_help_form_unwind 2158,65701
-#define STOP_POLLING 2166,65959
-#define RESUME_POLLING 2170,66084
-read_event_from_main_queue 2175,66229
-read_decoded_event_from_main_queue 2249,68417
-#define MAX_ENCODED_BYTES 2254,68664
-echo_keystrokes_p 2342,71556
-read_char 2376,72848
-record_menu_key 3225,98949
-help_char_p 3258,99674
-record_char 3273,99953
-save_getcjmp 3412,104235
-restore_getcjmp 3418,104326
-readable_events 3430,104697
-int stop_character EXTERNALLY_VISIBLE;3497,106437
-event_to_kboard 3500,106493
-kbd_buffer_nr_stored 3522,107142
-kbd_buffer_store_event 3534,107483
-kbd_buffer_store_event_hold 3550,108025
-kbd_buffer_unget_event 3684,111617
-#define INPUT_EVENT_POS_MAX 3698,112018
-#define INPUT_EVENT_POS_MIN 3701,112147
-position_to_Time 3706,112287
-Time_to_position 3716,112514
-gen_help_event 3738,113171
-kbd_buffer_store_help_event 3756,113611
-discard_mouse_events 3773,113976
-kbd_buffer_events_waiting 3803,114711
-clear_event 3823,115068
-kbd_buffer_get_event 3836,115408
-process_special_events 4258,127881
-swallow_events 4322,129705
-timer_start_idle 4339,130098
-timer_stop_idle 4355,130576
-timer_resume_idle 4363,130720
-struct input_event last_timer_event EXTERNALLY_VISIBLE;4372,130912
-Lisp_Object pending_funcalls;4377,131172
-decode_timer 4381,131293
-timer_check_2 4414,132246
-timer_check 4572,136817
-DEFUN ("current-idle-time", Fcurrent_idle_time,4607,137662
-DEFUN ("current-idle-time", Fcurrent_idle_time,current-idle-time4607,137662
-static Lisp_Object accent_key_syms;4625,138239
-static Lisp_Object func_key_syms;4626,138275
-static Lisp_Object mouse_syms;4627,138309
-static Lisp_Object wheel_syms;4628,138340
-static Lisp_Object drag_n_drop_syms;4629,138371
-static const int lispy_accent_codes[lispy_accent_codes4634,138516
-static const char *const lispy_accent_keys[lispy_accent_keys4741,139878
-#define FUNCTION_KEY_OFFSET 4766,140314
-const char *const lispy_function_keys[lispy_function_keys4768,140347
-static const char *const lispy_multimedia_keys[lispy_multimedia_keys4962,148901
-static const char *const lispy_kana_keys[lispy_kana_keys5026,150135
-#define FUNCTION_KEY_OFFSET 5061,151751
-static const char *const lispy_function_keys[lispy_function_keys5065,151894
-#define ISO_FUNCTION_KEY_OFFSET 5149,154429
-static const char *const iso_lispy_function_keys[iso_lispy_function_keys5151,154469
-static Lisp_Object Vlispy_mouse_stem;5172,155328
-static const char *const lispy_wheel_names[lispy_wheel_names5174,155367
-static const char *const lispy_drag_n_drop_names[lispy_drag_n_drop_names5181,155619
-static short const scroll_bar_parts[scroll_bar_parts5189,155885
-static Lisp_Object button_down_location;5210,156910
-static int last_mouse_button;5215,157065
-static int last_mouse_x;5216,157095
-static int last_mouse_y;5217,157120
-static Time button_down_time;5218,157145
-static int double_click_count;5222,157229
-make_lispy_position 5228,157390
-toolkit_menubar_in_use 5456,163953
-make_scroll_bar_position 5469,164321
-make_lispy_event 5485,164967
-make_lispy_movement 6104,183531
-make_lispy_switch_frame 6131,184262
-make_lispy_focus_in 6137,184369
-make_lispy_focus_out 6145,184495
-parse_modifiers_uncached 6163,184945
-#define SINGLE_LETTER_MOD(6185,185465
-#undef SINGLE_LETTER_MOD6212,185906
-#define MULTI_LETTER_MOD(6214,185932
-#undef MULTI_LETTER_MOD6231,186400
-apply_modifiers_uncached 6273,187574
-static const char *const modifier_names[modifier_names6319,189193
-#define NUM_MOD_NAMES 6325,189399
-static Lisp_Object modifier_symbols;6327,189449
-lispy_modifier_list 6331,189586
-#define KEY_TO_CHAR(6353,190252
-parse_modifiers 6356,190328
-DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,6399,191517
-DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,event-symbol-parse-modifiers6399,191517
-apply_modifiers 6422,192391
-reorder_modifiers 6491,194720
-modify_event_symbol 6536,196528
-DEFUN ("event-convert-list", Fevent_convert_list,6628,199244
-DEFUN ("event-convert-list", Fevent_convert_list,event-convert-list6628,199244
-parse_solitary_modifier 6695,201135
-#define SINGLE_LETTER_MOD(6701,201258
-#define MULTI_LETTER_MOD(6705,201343
-#undef SINGLE_LETTER_MOD6763,202641
-#undef MULTI_LETTER_MOD6764,202666
-lucid_event_type_list_p 6775,202889
-get_input_pending 6814,203960
-record_asynch_buffer_change 6834,204579
-gobble_input 6872,205702
-tty_read_avail_input 6967,208310
-handle_async_input 7149,214039
-process_pending_signals 7165,214359
-unblock_input_to 7177,214645
-unblock_input 7200,215277
-totally_unblock_input 7209,215445
-handle_input_available_signal 7217,215529
-deliver_input_available_signal 7226,215700
-struct user_signal_info7235,215865
-static struct user_signal_info *user_signals user_signals7250,216090
-add_user_signal 7253,216149
-handle_user_signal 7275,216598
-deliver_user_signal 7316,217558
-find_user_signal_name 7322,217659
-store_user_signal_events 7334,217841
-static Lisp_Object menu_bar_one_keymap_changed_items;7363,218416
-static Lisp_Object menu_bar_items_vector;7368,218630
-static int menu_bar_items_index;7369,218672
-static const char *separator_names[separator_names7372,218707
-menu_separator_name_p 7393,219148
-menu_bar_items 7426,219852
-Lisp_Object item_properties;7568,224603
-menu_bar_item 7571,224645
-menu_item_eval_property_1 7647,227175
-eval_dyn 7658,227465
-menu_item_eval_property 7666,227675
-parse_menu_item 7686,228341
-static Lisp_Object tool_bar_items_vector;7965,236336
-static Lisp_Object tool_bar_item_properties;7970,236510
-static int ntool_bar_items;7974,236606
-tool_bar_items 7990,237083
-process_tool_bar_item 8075,239892
-#define PROP(8112,240969
-set_prop 8114,241038
-parse_tool_bar_item 8167,242453
-#undef PROP8379,248844
-init_tool_bar_items 8387,248969
-append_tool_bar_item 8401,249261
-read_char_x_menu_prompt 8443,250771
-read_char_minibuf_menu_prompt 8503,252445
-#define PUSH_C_STR(8527,253014
-follow_key 8726,258553
-active_maps 8733,258695
-typedef struct keyremap8742,259021
-} keyremap;8754,259464
-access_keymap_keyremap 8764,259808
-keyremap_step 8811,261450
-test_undefined 8867,262934
-read_key_sequence 8916,264861
-read_key_sequence_vs 9826,295821
-DEFUN ("read-key-sequence", Fread_key_sequence,9885,297294
-DEFUN ("read-key-sequence", Fread_key_sequence,read-key-sequence9885,297294
-DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,9938,299982
-DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,read-key-sequence-vector9938,299982
-detect_input_pending 9950,300488
-detect_input_pending_ignore_squeezables 9959,300654
-detect_input_pending_run_timers 9967,300870
-clear_input_pending 9985,301362
-requeued_events_pending_p 9997,301732
-DEFUN ("input-pending-p", Finput_pending_p,10002,301813
-DEFUN ("input-pending-p", Finput_pending_p,input-pending-p10002,301813
-DEFUN ("recent-keys", Frecent_keys,10024,302596
-DEFUN ("recent-keys", Frecent_keys,recent-keys10024,302596
-DEFUN ("this-command-keys", Fthis_command_keys,10055,303517
-DEFUN ("this-command-keys", Fthis_command_keys,this-command-keys10055,303517
-DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,10068,303958
-DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,this-command-keys-vector10068,303958
-DEFUN ("this-single-command-keys", Fthis_single_command_keys,10080,304380
-DEFUN ("this-single-command-keys", Fthis_single_command_keys,this-single-command-keys10080,304380
-DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,10096,304955
-DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,this-single-command-raw-keys10096,304955
-DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,10109,305495
-DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,reset-this-command-lengths10109,305495
-DEFUN ("clear-this-command-keys", Fclear_this_command_keys,10136,306510
-DEFUN ("clear-this-command-keys", Fclear_this_command_keys,clear-this-command-keys10136,306510
-DEFUN ("recursion-depth", Frecursion_depth,10158,307069
-DEFUN ("recursion-depth", Frecursion_depth,recursion-depth10158,307069
-DEFUN ("open-dribble-file", Fopen_dribble_file,10169,307406
-DEFUN ("open-dribble-file", Fopen_dribble_file,open-dribble-file10169,307406
-DEFUN ("discard-input", Fdiscard_input,10203,308447
-DEFUN ("discard-input", Fdiscard_input,discard-input10203,308447
-DEFUN ("suspend-emacs", Fsuspend_emacs,10225,308949
-DEFUN ("suspend-emacs", Fsuspend_emacs,suspend-emacs10225,308949
-stuff_buffered_input 10285,311045
-set_waiting_for_input 10323,312016
-clear_waiting_for_input 10337,312390
-handle_interrupt_signal 10351,312754
-deliver_interrupt_signal 10378,313642
-static int volatile force_quit_count;10387,313932
-handle_interrupt 10401,314414
-quit_throw_to_read_char 10541,318711
-DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,10562,319288
-DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,set-input-interrupt-mode10562,319288
-DEFUN ("set-output-flow-control", Fset_output_flow_control,10609,320516
-DEFUN ("set-output-flow-control", Fset_output_flow_control,set-output-flow-control10609,320516
-DEFUN ("set-input-meta-mode", Fset_input_meta_mode,10643,321432
-DEFUN ("set-input-meta-mode", Fset_input_meta_mode,set-input-meta-mode10643,321432
-DEFUN ("set-quit-char", Fset_quit_char,10694,322706
-DEFUN ("set-quit-char", Fset_quit_char,set-quit-char10694,322706
-DEFUN ("set-input-mode", Fset_input_mode,10729,323570
-DEFUN ("set-input-mode", Fset_input_mode,set-input-mode10729,323570
-DEFUN ("current-input-mode", Fcurrent_input_mode,10750,324459
-DEFUN ("current-input-mode", Fcurrent_input_mode,current-input-mode10750,324459
-DEFUN ("posn-at-x-y", Fposn_at_x_y,10787,325837
-DEFUN ("posn-at-x-y", Fposn_at_x_y,posn-at-x-y10787,325837
-DEFUN ("posn-at-point", Fposn_at_point,10824,327060
-DEFUN ("posn-at-point", Fposn_at_point,posn-at-point10824,327060
-init_kboard 10861,328214
-allocate_kboard 10893,329284
-wipe_kboard 10909,329637
-delete_kboard 10917,329751
-init_keyboard 10942,330281
-struct event_head11021,332696
-static const struct event_head head_table[head_table11027,332747
-syms_of_keyboard 11045,333577
-keys_of_keyboard 11841,367115
-mark_kboards 11916,370434
+volatile int interrupt_input_blocked;76,1809
+volatile bool pending_signals;80,1945
+#define KBD_BUFFER_SIZE 82,1977
+KBOARD *initial_kboard;initial_kboard84,2007
+KBOARD *current_kboard;current_kboard85,2031
+static KBOARD *all_kboards;all_kboards86,2055
+static bool single_kboard;89,2155
+#define NUM_RECENT_KEYS 91,2183
+static int recent_keys_index;94,2270
+static int total_keys;97,2358
+static Lisp_Object recent_keys;100,2444
+Lisp_Object this_command_keys;107,2778
+ptrdiff_t this_command_key_count;108,2809
+static bool this_command_key_count_reset;112,2923
+static Lisp_Object raw_keybuf;116,3075
+static int raw_keybuf_count;117,3106
+#define GROW_RAW_KEYBUF 119,3136
+static ptrdiff_t this_single_command_key_start;125,3351
+static ptrdiff_t before_command_key_count;129,3499
+static ptrdiff_t before_command_echo_length;130,3542
+sigjmp_buf return_to_command_loop;135,3678
+static Lisp_Object recover_top_level_message;138,3792
+static Lisp_Object regular_top_level_message;143,3931
+static sys_jmp_buf getcjmp;147,4032
+bool waiting_for_input;150,4096
+static bool echoing;154,4187
+static struct kboard *ok_to_echo_at_next_pause;ok_to_echo_at_next_pause159,4329
+struct kboard *echo_kboard;echo_kboard166,4633
+Lisp_Object echo_message_buffer;171,4745
+bool immediate_quit;174,4838
+int quit_char;192,5624
+EMACS_INT command_loop_level;195,5681
+Lisp_Object unread_switch_frame;204,6109
+static ptrdiff_t last_non_minibuf_size;207,6217
+uintmax_t num_input_events;210,6335
+static EMACS_INT last_auto_save;214,6429
+static ptrdiff_t last_point_position;217,6524
+Lisp_Object internal_last_event_frame;228,7029
+static Lisp_Object read_key_sequence_cmd;232,7169
+static Lisp_Object read_key_sequence_remapped;233,7211
+static FILE *dribble;dribble236,7311
+bool input_pending;239,7369
+static bool input_was_pending;287,10023
+static struct input_event kbd_buffer[kbd_buffer291,10108
+static struct input_event *kbd_fetch_ptr;kbd_fetch_ptr297,10387
+static struct input_event * volatile kbd_store_ptr;302,10602
+unsigned timers_run;320,11297
+struct timespec *input_available_clear_time;input_available_clear_time324,11409
+bool interrupt_input;328,11574
+bool interrupts_deferred;331,11672
+static struct timespec timer_idleness_start_time;335,11747
+static struct timespec timer_last_idleness_start_time;340,11917
+#define READABLE_EVENTS_DO_TIMERS_NOW 346,12047
+#define READABLE_EVENTS_FILTER_EVENTS 347,12095
+#define READABLE_EVENTS_IGNORE_SQUEEZABLES 348,12143
+kset_echo_string 392,14089
+kset_kbd_queue 397,14185
+kset_keyboard_translate_table 402,14277
+kset_last_prefix_arg 407,14400
+kset_last_repeatable_command 412,14505
+kset_local_function_key_map 417,14626
+kset_overriding_terminal_local_map 422,14745
+kset_real_last_command 427,14878
+kset_system_key_syms 432,14987
+echo_add_key 443,15250
+echo_char 527,17528
+echo_dash 541,17814
+echo_now 586,19141
+cancel_echoing 635,20615
+echo_length 648,20923
+echo_truncate 660,21254
+add_command_key 672,21583
+recursive_edit_1 697,22407
+record_auto_save 742,23849
+force_auto_save_soon 751,24017
+DEFUN ("recursive-edit", Frecursive_edit,759,24138
+DEFUN ("recursive-edit", Frecursive_edit,recursive-edit759,24138
+recursive_edit_unwind 804,25751
+any_kboard_state 817,26017
+single_kboard_state 838,26669
+not_single_kboard_state 848,26807
+struct kboard_stack858,27069
+static struct kboard_stack *kboard_stack;kboard_stack864,27142
+push_kboard 867,27190
+pop_kboard 879,27379
+temporarily_switch_to_single_kboard 914,28267
+record_single_kboard_state 943,29441
+restore_kboard_configuration 952,29625
+cmd_error 970,30081
+cmd_error_internal 1024,31514
+DEFUN ("command-error-default-function", Fcommand_error_default_function,1043,32034
+DEFUN ("command-error-default-function", Fcommand_error_default_function,command-error-default-function1043,32034
+command_loop 1094,33920
+command_loop_2 1134,35139
+top_level_2 1146,35343
+top_level_1 1152,35421
+DEFUN ("top-level", Ftop_level,1164,35791
+DEFUN ("top-level", Ftop_level,top-level1164,35791
+user_error 1183,36292
+DEFUN ("exit-recursive-edit", Fexit_recursive_edit,1189,36433
+DEFUN ("exit-recursive-edit", Fexit_recursive_edit,exit-recursive-edit1189,36433
+DEFUN ("abort-recursive-edit", Fabort_recursive_edit,1201,36823
+DEFUN ("abort-recursive-edit", Fabort_recursive_edit,abort-recursive-edit1201,36823
+tracking_off 1216,37285
+DEFUN ("internal--track-mouse", Ftrack_mouse,1234,37820
+DEFUN ("internal--track-mouse", Ftrack_mouse,track-mouse1234,37820
+bool ignore_mouse_drag_p;1256,38396
+some_mouse_moved 1259,38445
+Lisp_Object last_undo_boundary;1287,39036
+command_loop_1 1294,39277
+read_menu_command 1649,50893
+adjust_point_for_property 1678,51621
+safe_run_hooks_1 1831,57343
+safe_run_hooks_error 1841,57573
+safe_run_hook_funcall 1878,58580
+safe_run_hooks 1893,59062
+int poll_suppress_count;1908,59401
+static struct atimer *poll_timer;poll_timer1915,59491
+poll_for_input_1 1919,59593
+poll_for_input 1930,59793
+start_polling 1942,60057
+input_polling_used 1979,61095
+stop_polling 1994,61394
+set_poll_suppress_count 2009,61763
+bind_polling_period 2029,62145
+make_ctrl_char 2048,62496
+show_help_echo 2113,64459
+static Lisp_Object help_form_saved_window_configs;2156,65642
+read_char_help_form_unwind 2158,65705
+#define STOP_POLLING 2166,65963
+#define RESUME_POLLING 2170,66088
+read_event_from_main_queue 2175,66233
+read_decoded_event_from_main_queue 2249,68421
+#define MAX_ENCODED_BYTES 2254,68668
+echo_keystrokes_p 2342,71560
+read_char 2376,72852
+record_menu_key 3225,98953
+help_char_p 3258,99678
+record_char 3273,99957
+save_getcjmp 3412,104239
+restore_getcjmp 3418,104330
+readable_events 3430,104701
+int stop_character EXTERNALLY_VISIBLE;3497,106441
+event_to_kboard 3500,106497
+kbd_buffer_nr_stored 3522,107146
+kbd_buffer_store_event 3534,107487
+kbd_buffer_store_event_hold 3550,108029
+kbd_buffer_unget_event 3684,111621
+#define INPUT_EVENT_POS_MAX 3698,112022
+#define INPUT_EVENT_POS_MIN 3701,112151
+position_to_Time 3706,112291
+Time_to_position 3716,112518
+gen_help_event 3738,113175
+kbd_buffer_store_help_event 3756,113615
+discard_mouse_events 3773,113980
+kbd_buffer_events_waiting 3803,114715
+clear_event 3823,115072
+kbd_buffer_get_event 3836,115412
+process_special_events 4258,127885
+swallow_events 4322,129709
+timer_start_idle 4339,130102
+timer_stop_idle 4355,130580
+timer_resume_idle 4363,130724
+struct input_event last_timer_event EXTERNALLY_VISIBLE;4372,130916
+Lisp_Object pending_funcalls;4377,131176
+decode_timer 4381,131297
+timer_check_2 4414,132250
+timer_check 4572,136821
+DEFUN ("current-idle-time", Fcurrent_idle_time,4607,137666
+DEFUN ("current-idle-time", Fcurrent_idle_time,current-idle-time4607,137666
+static Lisp_Object accent_key_syms;4625,138243
+static Lisp_Object func_key_syms;4626,138279
+static Lisp_Object mouse_syms;4627,138313
+static Lisp_Object wheel_syms;4628,138344
+static Lisp_Object drag_n_drop_syms;4629,138375
+static const int lispy_accent_codes[lispy_accent_codes4634,138520
+static const char *const lispy_accent_keys[lispy_accent_keys4741,139882
+#define FUNCTION_KEY_OFFSET 4766,140318
+const char *const lispy_function_keys[lispy_function_keys4768,140351
+static const char *const lispy_multimedia_keys[lispy_multimedia_keys4962,148905
+static const char *const lispy_kana_keys[lispy_kana_keys5026,150139
+#define FUNCTION_KEY_OFFSET 5061,151755
+static const char *const lispy_function_keys[lispy_function_keys5065,151898
+#define ISO_FUNCTION_KEY_OFFSET 5149,154433
+static const char *const iso_lispy_function_keys[iso_lispy_function_keys5151,154473
+static Lisp_Object Vlispy_mouse_stem;5172,155332
+static const char *const lispy_wheel_names[lispy_wheel_names5174,155371
+static const char *const lispy_drag_n_drop_names[lispy_drag_n_drop_names5181,155623
+static short const scroll_bar_parts[scroll_bar_parts5189,155889
+static Lisp_Object button_down_location;5210,156914
+static int last_mouse_button;5215,157069
+static int last_mouse_x;5216,157099
+static int last_mouse_y;5217,157124
+static Time button_down_time;5218,157149
+static int double_click_count;5222,157233
+make_lispy_position 5228,157394
+toolkit_menubar_in_use 5456,163957
+make_scroll_bar_position 5469,164325
+make_lispy_event 5485,164971
+make_lispy_movement 6104,183534
+make_lispy_switch_frame 6131,184265
+make_lispy_focus_in 6137,184372
+make_lispy_focus_out 6145,184498
+parse_modifiers_uncached 6163,184948
+#define SINGLE_LETTER_MOD(6185,185468
+#undef SINGLE_LETTER_MOD6212,185909
+#define MULTI_LETTER_MOD(6214,185935
+#undef MULTI_LETTER_MOD6231,186403
+apply_modifiers_uncached 6273,187577
+static const char *const modifier_names[modifier_names6319,189196
+#define NUM_MOD_NAMES 6325,189402
+static Lisp_Object modifier_symbols;6327,189452
+lispy_modifier_list 6331,189589
+#define KEY_TO_CHAR(6353,190255
+parse_modifiers 6356,190331
+DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,6399,191520
+DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,event-symbol-parse-modifiers6399,191520
+apply_modifiers 6422,192394
+reorder_modifiers 6491,194723
+modify_event_symbol 6536,196531
+DEFUN ("event-convert-list", Fevent_convert_list,6628,199247
+DEFUN ("event-convert-list", Fevent_convert_list,event-convert-list6628,199247
+parse_solitary_modifier 6695,201138
+#define SINGLE_LETTER_MOD(6701,201261
+#define MULTI_LETTER_MOD(6705,201346
+#undef SINGLE_LETTER_MOD6763,202644
+#undef MULTI_LETTER_MOD6764,202669
+lucid_event_type_list_p 6775,202892
+get_input_pending 6814,203963
+record_asynch_buffer_change 6834,204582
+gobble_input 6872,205705
+tty_read_avail_input 6967,208313
+handle_async_input 7149,214042
+process_pending_signals 7165,214362
+unblock_input_to 7177,214648
+unblock_input 7200,215280
+totally_unblock_input 7209,215448
+handle_input_available_signal 7217,215532
+deliver_input_available_signal 7226,215703
+struct user_signal_info7235,215868
+static struct user_signal_info *user_signals user_signals7250,216093
+add_user_signal 7253,216152
+handle_user_signal 7275,216601
+deliver_user_signal 7316,217561
+find_user_signal_name 7322,217662
+store_user_signal_events 7334,217844
+static Lisp_Object menu_bar_one_keymap_changed_items;7363,218419
+static Lisp_Object menu_bar_items_vector;7368,218633
+static int menu_bar_items_index;7369,218675
+static const char *separator_names[separator_names7372,218710
+menu_separator_name_p 7393,219151
+menu_bar_items 7426,219855
+Lisp_Object item_properties;7568,224606
+menu_bar_item 7571,224648
+menu_item_eval_property_1 7647,227178
+eval_dyn 7658,227468
+menu_item_eval_property 7666,227678
+parse_menu_item 7686,228344
+static Lisp_Object tool_bar_items_vector;7965,236339
+static Lisp_Object tool_bar_item_properties;7970,236513
+static int ntool_bar_items;7974,236609
+tool_bar_items 7990,237086
+process_tool_bar_item 8075,239895
+#define PROP(8112,240972
+set_prop 8114,241041
+parse_tool_bar_item 8167,242456
+#undef PROP8379,248847
+init_tool_bar_items 8387,248972
+append_tool_bar_item 8401,249264
+read_char_x_menu_prompt 8443,250774
+read_char_minibuf_menu_prompt 8503,252448
+#define PUSH_C_STR(8527,253017
+follow_key 8726,258556
+active_maps 8733,258698
+typedef struct keyremap8742,259024
+} keyremap;8754,259467
+access_keymap_keyremap 8764,259811
+keyremap_step 8811,261453
+test_undefined 8867,262937
+read_key_sequence 8916,264864
+read_key_sequence_vs 9826,295824
+DEFUN ("read-key-sequence", Fread_key_sequence,9885,297297
+DEFUN ("read-key-sequence", Fread_key_sequence,read-key-sequence9885,297297
+DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,9938,299985
+DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,read-key-sequence-vector9938,299985
+detect_input_pending 9950,300491
+detect_input_pending_ignore_squeezables 9959,300657
+detect_input_pending_run_timers 9967,300873
+clear_input_pending 9985,301365
+requeued_events_pending_p 9997,301735
+DEFUN ("input-pending-p", Finput_pending_p,10002,301816
+DEFUN ("input-pending-p", Finput_pending_p,input-pending-p10002,301816
+DEFUN ("recent-keys", Frecent_keys,10024,302599
+DEFUN ("recent-keys", Frecent_keys,recent-keys10024,302599
+DEFUN ("this-command-keys", Fthis_command_keys,10055,303520
+DEFUN ("this-command-keys", Fthis_command_keys,this-command-keys10055,303520
+DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,10068,303961
+DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,this-command-keys-vector10068,303961
+DEFUN ("this-single-command-keys", Fthis_single_command_keys,10080,304383
+DEFUN ("this-single-command-keys", Fthis_single_command_keys,this-single-command-keys10080,304383
+DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,10096,304958
+DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,this-single-command-raw-keys10096,304958
+DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,10109,305498
+DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,reset-this-command-lengths10109,305498
+DEFUN ("clear-this-command-keys", Fclear_this_command_keys,10136,306513
+DEFUN ("clear-this-command-keys", Fclear_this_command_keys,clear-this-command-keys10136,306513
+DEFUN ("recursion-depth", Frecursion_depth,10158,307072
+DEFUN ("recursion-depth", Frecursion_depth,recursion-depth10158,307072
+DEFUN ("open-dribble-file", Fopen_dribble_file,10169,307409
+DEFUN ("open-dribble-file", Fopen_dribble_file,open-dribble-file10169,307409
+DEFUN ("discard-input", Fdiscard_input,10203,308450
+DEFUN ("discard-input", Fdiscard_input,discard-input10203,308450
+DEFUN ("suspend-emacs", Fsuspend_emacs,10225,308952
+DEFUN ("suspend-emacs", Fsuspend_emacs,suspend-emacs10225,308952
+stuff_buffered_input 10285,311048
+set_waiting_for_input 10323,312019
+clear_waiting_for_input 10337,312393
+handle_interrupt_signal 10351,312757
+deliver_interrupt_signal 10378,313645
+static int volatile force_quit_count;10387,313935
+handle_interrupt 10401,314417
+quit_throw_to_read_char 10541,318714
+DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,10562,319291
+DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,set-input-interrupt-mode10562,319291
+DEFUN ("set-output-flow-control", Fset_output_flow_control,10609,320519
+DEFUN ("set-output-flow-control", Fset_output_flow_control,set-output-flow-control10609,320519
+DEFUN ("set-input-meta-mode", Fset_input_meta_mode,10643,321435
+DEFUN ("set-input-meta-mode", Fset_input_meta_mode,set-input-meta-mode10643,321435
+DEFUN ("set-quit-char", Fset_quit_char,10694,322709
+DEFUN ("set-quit-char", Fset_quit_char,set-quit-char10694,322709
+DEFUN ("set-input-mode", Fset_input_mode,10729,323573
+DEFUN ("set-input-mode", Fset_input_mode,set-input-mode10729,323573
+DEFUN ("current-input-mode", Fcurrent_input_mode,10750,324462
+DEFUN ("current-input-mode", Fcurrent_input_mode,current-input-mode10750,324462
+DEFUN ("posn-at-x-y", Fposn_at_x_y,10787,325840
+DEFUN ("posn-at-x-y", Fposn_at_x_y,posn-at-x-y10787,325840
+DEFUN ("posn-at-point", Fposn_at_point,10824,327063
+DEFUN ("posn-at-point", Fposn_at_point,posn-at-point10824,327063
+init_kboard 10861,328217
+allocate_kboard 10893,329287
+wipe_kboard 10909,329640
+delete_kboard 10917,329754
+init_keyboard 10942,330284
+struct event_head11021,332699
+static const struct event_head head_table[head_table11027,332750
+syms_of_keyboard 11045,333580
+keys_of_keyboard 11841,367118
+mark_kboards 11916,370437
c-src/emacs/src/lisp.h,20276
-#define EMACS_LISP_H22,800
-#define DECLARE_GDB_SYM(47,1421
-# define DEFINE_GDB_SYMBOL_BEGIN(49,1508
-# define DEFINE_GDB_SYMBOL_END(50,1578
-# define DEFINE_GDB_SYMBOL_BEGIN(52,1625
-# define DEFINE_GDB_SYMBOL_END(53,1702
-#undef min57,1790
-#undef max58,1801
-#define max(59,1812
-#define min(60,1854
-#define ARRAYELTS(63,1936
-#define GCTYPEBITS 67,2079
-DEFINE_GDB_SYMBOL_BEGIN GCTYPEBITS66,2037
-# define NONPOINTER_BITS 78,2567
-# define NONPOINTER_BITS 80,2600
-typedef int EMACS_INT;91,3023
-typedef unsigned int EMACS_UINT;92,3046
-# define EMACS_INT_MAX 93,3079
-# define pI 94,3111
-typedef long int EMACS_INT;96,3203
-typedef unsigned long EMACS_UINT;97,3231
-# define EMACS_INT_MAX 98,3265
-# define pI 99,3298
-typedef long long int EMACS_INT;103,3477
-typedef unsigned long long int EMACS_UINT;104,3510
-# define EMACS_INT_MAX 105,3553
-# define pI 106,3587
-enum { BOOL_VECTOR_BITS_PER_CHAR 114,3804
-#define BOOL_VECTOR_BITS_PER_CHAR 115,3840
-typedef size_t bits_word;123,4165
-# define BITS_WORD_MAX 124,4191
-enum { BITS_PER_BITS_WORD 125,4223
-typedef unsigned char bits_word;127,4290
-# define BITS_WORD_MAX 128,4323
-enum { BITS_PER_BITS_WORD 129,4386
- BITS_PER_CHAR 136,4570
- BITS_PER_SHORT 137,4605
- BITS_PER_LONG 138,4657
- BITS_PER_EMACS_INT 139,4712
-typedef intmax_t printmax_t;148,5089
-typedef uintmax_t uprintmax_t;149,5118
-# define pMd 150,5149
-# define pMu 151,5170
-typedef EMACS_INT printmax_t;153,5197
-typedef EMACS_UINT uprintmax_t;154,5227
-# define pMd 155,5259
-# define pMu 156,5278
-# define pD 165,5664
-# define pD 167,5709
-# define pD 169,5756
-# define pD 171,5779
-# define eassert(200,7062
-# define eassume(201,7140
-# define eassert(208,7319
-# define eassume(212,7450
-enum Lisp_Bits239,8519
-#define GCALIGNMENT 243,8647
- VALBITS 246,8742
- INTTYPEBITS 249,8838
- FIXNUM_BITS 252,8945
-#define VAL_MAX 263,9327
-#define USE_LSB_TAG 271,9777
-DEFINE_GDB_SYMBOL_BEGIN USE_LSB_TAG270,9733
-# define alignas(281,10077
-# define GCALIGNED 288,10227
-# define GCALIGNED 290,10292
-# define lisp_h_XLI(327,11642
-# define lisp_h_XIL(328,11673
-# define lisp_h_XLI(330,11724
-# define lisp_h_XIL(331,11751
-#define lisp_h_CHECK_LIST_CONS(333,11785
-#define lisp_h_CHECK_NUMBER(334,11856
-#define lisp_h_CHECK_SYMBOL(335,11927
-#define lisp_h_CHECK_TYPE(336,11996
-#define lisp_h_CONSP(338,12107
-#define lisp_h_EQ(339,12156
-#define lisp_h_FLOATP(340,12201
-#define lisp_h_INTEGERP(341,12252
-#define lisp_h_MARKERP(342,12333
-#define lisp_h_MISCP(343,12408
-#define lisp_h_NILP(344,12457
-#define lisp_h_SET_SYMBOL_VAL(345,12493
-#define lisp_h_SYMBOL_CONSTANT_P(347,12607
-#define lisp_h_SYMBOL_VAL(348,12671
-#define lisp_h_SYMBOLP(350,12772
-#define lisp_h_VECTORLIKEP(351,12825
-#define lisp_h_XCAR(352,12886
-#define lisp_h_XCDR(353,12924
-#define lisp_h_XCONS(354,12964
-#define lisp_h_XHASH(356,13059
-#define lisp_h_XPNTR(357,13093
-# define lisp_h_check_cons_list(360,13221
-# define lisp_h_make_number(363,13289
-# define lisp_h_XFASTINT(365,13392
-# define lisp_h_XINT(366,13429
-# define lisp_h_XSYMBOL(367,13478
-# define lisp_h_XTYPE(371,13631
-# define lisp_h_XUNTAG(372,13696
-# define XLI(381,14086
-# define XIL(382,14117
-# define CHECK_LIST_CONS(383,14148
-# define CHECK_NUMBER(384,14209
-# define CHECK_SYMBOL(385,14258
-# define CHECK_TYPE(386,14307
-# define CONSP(387,14382
-# define EQ(388,14417
-# define FLOATP(389,14452
-# define INTEGERP(390,14489
-# define MARKERP(391,14530
-# define MISCP(392,14569
-# define NILP(393,14604
-# define SET_SYMBOL_VAL(394,14637
-# define SYMBOL_CONSTANT_P(395,14700
-# define SYMBOL_VAL(396,14763
-# define SYMBOLP(397,14812
-# define VECTORLIKEP(398,14851
-# define XCAR(399,14898
-# define XCDR(400,14931
-# define XCONS(401,14964
-# define XHASH(402,14999
-# define XPNTR(403,15034
-# define check_cons_list(405,15097
-# define make_number(408,15176
-# define XFASTINT(409,15224
-# define XINT(410,15266
-# define XSYMBOL(411,15300
-# define XTYPE(412,15340
-# define XUNTAG(413,15376
-#define LISP_MACRO_DEFUN(421,15672
-#define LISP_MACRO_DEFUN_VOID(425,15845
-#define INTMASK 437,16289
-#define case_Lisp_Int 438,16342
-#define ENUM_BF(445,16681
-#define ENUM_BF(447,16722
-enum Lisp_Type451,16763
- Lisp_Symbol 454,16851
- Lisp_Misc 458,16993
- Lisp_Int0 461,17067
- Lisp_Int1 462,17086
- Lisp_String 466,17264
- Lisp_Vectorlike 472,17543
- Lisp_Cons 475,17632
- Lisp_Float 477,17670
-enum Lisp_Misc_Type485,18016
- Lisp_Misc_Free 487,18040
- Lisp_Misc_Marker,488,18069
- Lisp_Misc_Overlay,489,18091
- Lisp_Misc_Save_Value,490,18114
- Lisp_Misc_Finalizer,491,18140
- Lisp_Misc_Float,494,18275
- Lisp_Misc_Limit496,18359
-enum Lisp_Fwd_Type502,18543
- Lisp_Fwd_Int,504,18566
- Lisp_Fwd_Bool,505,18619
- Lisp_Fwd_Obj,506,18670
- Lisp_Fwd_Buffer_Obj,507,18729
- Lisp_Fwd_Kboard_Obj 508,18800
-typedef struct { EMACS_INT i; } Lisp_Object;567,21781
-#define LISP_INITIALLY(569,21827
-#undef CHECK_LISP_OBJECT_TYPE571,21858
-enum CHECK_LISP_OBJECT_TYPE 572,21888
-enum CHECK_LISP_OBJECT_TYPE { CHECK_LISP_OBJECT_TYPE 572,21888
-typedef EMACS_INT Lisp_Object;577,22064
-#define LISP_INITIALLY(578,22095
-enum CHECK_LISP_OBJECT_TYPE 579,22125
-enum CHECK_LISP_OBJECT_TYPE { CHECK_LISP_OBJECT_TYPE 579,22125
-#define LISP_INITIALLY_ZERO 582,22226
-enum symbol_interned639,24199
- SYMBOL_UNINTERNED 641,24222
- SYMBOL_INTERNED 642,24247
- SYMBOL_INTERNED_IN_INITIAL_OBARRAY 643,24270
-enum symbol_redirect646,24315
- SYMBOL_PLAINVAL 648,24338
- SYMBOL_VARALIAS 649,24362
- SYMBOL_LOCALIZED 650,24386
- SYMBOL_FORWARDED 651,24410
-struct Lisp_Symbol654,24437
-#define EXFUN(707,26252
-#define DEFUN_ARGS_MANY 712,26446
-#define DEFUN_ARGS_UNEVALLED 713,26498
-#define DEFUN_ARGS_0 714,26541
-#define DEFUN_ARGS_1 715,26569
-#define DEFUN_ARGS_2 716,26604
-#define DEFUN_ARGS_3 717,26652
-#define DEFUN_ARGS_4 718,26713
-#define DEFUN_ARGS_5 719,26787
-#define DEFUN_ARGS_6 721,26880
-#define DEFUN_ARGS_7 723,26986
-#define DEFUN_ARGS_8 725,27105
-#define TAG_PTR(729,27296
-#define TAG_SYMOFFSET(734,27543
-#define XLI_BUILTIN_LISPSYM(741,27842
-#define DEFINE_LISP_SYMBOL(746,28101
-# define DEFINE_NON_NIL_Q_SYMBOL_MACROS 755,28572
-LISP_MACRO_DEFUN 762,28777
-# define ARRAY_MARK_FLAG 768,29024
-# define PSEUDOVECTOR_FLAG 774,29267
-enum pvec_type780,29568
- PVEC_NORMAL_VECTOR,782,29585
- PVEC_FREE,783,29607
- PVEC_PROCESS,784,29620
- PVEC_FRAME,785,29636
- PVEC_WINDOW,786,29650
- PVEC_BOOL_VECTOR,787,29665
- PVEC_BUFFER,788,29685
- PVEC_HASH_TABLE,789,29700
- PVEC_TERMINAL,790,29719
- PVEC_WINDOW_CONFIGURATION,791,29736
- PVEC_SUBR,792,29765
- PVEC_OTHER,793,29778
- PVEC_COMPILED,795,29856
- PVEC_CHAR_TABLE,796,29873
- PVEC_SUB_CHAR_TABLE,797,29892
- PVEC_FONT 798,29915
-enum More_Lisp_Bits801,29991
- PSEUDOVECTOR_SIZE_BITS 808,30382
- PSEUDOVECTOR_SIZE_MASK 809,30415
- PSEUDOVECTOR_REST_BITS 813,30625
- PSEUDOVECTOR_REST_MASK 814,30658
- PSEUDOVECTOR_AREA_BITS 818,30823
- PVEC_TYPE_MASK 819,30901
-# define VALMASK 829,31302
-DEFINE_GDB_SYMBOL_BEGIN VALMASK828,31257
-#define MOST_POSITIVE_FIXNUM 834,31532
-#define MOST_NEGATIVE_FIXNUM 835,31592
-XINT 874,32684
-XFASTINT 889,33035
-XSYMBOL 899,33263
-XTYPE 910,33481
-XUNTAG 918,33661
-LISP_MACRO_DEFUN 927,33857
-LISP_MACRO_DEFUN 940,34242
-#define FIXNUM_OVERFLOW_P(958,34855
-LISP_MACRO_DEFUN FIXNUM_OVERFLOW_P952,34632
-LISP_MACRO_DEFUN 970,35171
-XSTRING 980,35391
-#define SYMBOL_INDEX(988,35575
-XFLOAT 991,35636
-XPROCESS 1000,35778
-XWINDOW 1007,35895
-XTERMINAL 1014,36012
-XSUBR 1021,36134
-XBUFFER 1028,36245
-XCHAR_TABLE 1035,36369
-XSUB_CHAR_TABLE 1042,36506
-XBOOL_VECTOR 1049,36648
-make_lisp_ptr 1058,36827
-make_lisp_symbol 1066,37013
-builtin_lisp_symbol 1074,37197
-#define XSETINT(1079,37279
-#define XSETFASTINT(1080,37325
-#define XSETCONS(1081,37375
-#define XSETVECTOR(1082,37435
-#define XSETSTRING(1083,37503
-#define XSETSYMBOL(1084,37567
-#define XSETFLOAT(1085,37621
-#define XSETMISC(1086,37683
-#define XSETPVECTYPE(1090,37772
-#define XSETPVECTYPESIZE(1092,37888
-#define XSETPSEUDOVECTOR(1099,38185
-#define XSETTYPED_PSEUDOVECTOR(1105,38369
-#define XSETWINDOW_CONFIGURATION(1110,38579
-#define XSETPROCESS(1112,38675
-#define XSETWINDOW(1113,38741
-#define XSETTERMINAL(1114,38805
-#define XSETSUBR(1115,38873
-#define XSETCOMPILED(1116,38933
-#define XSETBUFFER(1117,39001
-#define XSETCHAR_TABLE(1118,39065
-#define XSETBOOL_VECTOR(1119,39137
-#define XSETSUB_CHAR_TABLE(1120,39211
-XINTPTR 1128,39581
-make_pointer_integer 1134,39661
-LISP_MACRO_DEFUN_VOID 1143,39826
-typedef struct interval *INTERVAL;INTERVAL1149,39987
-xcar_addr 1174,40760
-xcdr_addr 1179,40837
-LISP_MACRO_DEFUN 1185,40931
-XSETCDR 1198,41307
-CAR 1205,41457
-CDR 1212,41591
-CAR_SAFE 1221,41791
-CDR_SAFE 1226,41877
-STRING_MULTIBYTE 1243,42250
-#define STRING_BYTES_BOUND 1261,43057
-#define STRING_SET_UNIBYTE(1265,43201
-#define STRING_SET_MULTIBYTE(1275,43516
-SDATA 1286,43830
-SSDATA 1291,43908
-SREF 1297,44037
-SSET 1302,44128
-SCHARS 1307,44242
-STRING_BYTES 1316,44415
-SBYTES 1326,44595
-STRING_SET_CHARS 1331,44681
-struct vectorlike_header1343,45232
-struct Lisp_Vector1369,46482
- ALIGNOF_STRUCT_LISP_VECTOR1378,46681
-struct Lisp_Bool_Vector1384,46864
-bool_vector_size 1399,47385
-bool_vector_data 1407,47523
-bool_vector_uchar_data 1413,47617
-bool_vector_words 1421,47803
-bool_vector_bytes 1428,47998
-bool_vector_bitref 1437,48238
-bool_vector_ref 1445,48478
-bool_vector_set 1453,48618
- header_size 1471,49047
- bool_header_size 1472,49106
- word_size 1473,49171
-AREF 1479,49284
-aref_addr 1485,49391
-ASIZE 1491,49501
-ASET 1497,49583
-gc_aset 1504,49742
-enum { NIL_IS_ZERO 1515,50269
-memclear 1520,50464
-#define VECSIZE(1531,50762
-#define PSEUDOVECSIZE(1538,51047
-#define UNSIGNED_CMP(1546,51480
-#define ASCII_CHAR_P(1552,51734
-enum CHARTAB_SIZE_BITS1565,52489
- CHARTAB_SIZE_BITS_0 1567,52516
- CHARTAB_SIZE_BITS_1 1568,52545
- CHARTAB_SIZE_BITS_2 1569,52574
- CHARTAB_SIZE_BITS_3 1570,52603
-struct Lisp_Char_Table1575,52672
-struct Lisp_Sub_Char_Table1606,53752
-CHAR_TABLE_REF_ASCII 1628,54566
-CHAR_TABLE_REF 1648,55113
-CHAR_TABLE_SET 1658,55402
-struct Lisp_Subr1670,55786
-enum char_table_specials1692,56798
- CHAR_TABLE_STANDARD_SLOTS 1697,56993
- SUB_CHAR_TABLE_OFFSET 1701,57214
-CHAR_TABLE_EXTRA_SLOTS 1707,57377
-LISP_MACRO_DEFUN 1723,57921
-SYMBOL_BLV 1732,58181
-SYMBOL_FWD 1738,58316
-LISP_MACRO_DEFUN_VOID 1744,58428
-SET_SYMBOL_BLV 1754,58691
-SET_SYMBOL_FWD 1760,58850
-SYMBOL_NAME 1767,59001
-SYMBOL_INTERNED_P 1775,59130
-SYMBOL_INTERNED_IN_INITIAL_OBARRAY_P 1783,59299
-#define DEFSYM(1796,59809
-LISP_MACRO_DEFUN DEFSYM1792,59630
-struct hash_table_test1805,60062
-struct Lisp_Hash_Table1823,60555
-XHASH_TABLE 1880,62531
-#define XSET_HASH_TABLE(1885,62602
-HASH_TABLE_P 1889,62703
-HASH_KEY 1896,62860
-HASH_VALUE 1903,63040
-HASH_NEXT 1911,63254
-HASH_HASH 1918,63431
-HASH_INDEX 1926,63677
-HASH_TABLE_SIZE 1933,63826
-enum DEFAULT_HASH_SIZE 1940,63956
-enum DEFAULT_HASH_SIZE { DEFAULT_HASH_SIZE 1940,63956
-static double const DEFAULT_REHASH_THRESHOLD 1946,64176
-static double const DEFAULT_REHASH_SIZE 1950,64299
-sxhash_combine 1956,64465
-SXHASH_REDUCE 1964,64648
-struct Lisp_Misc_Any 1971,64806
-struct Lisp_Marker1978,64980
-struct Lisp_Overlay2021,66841
- SAVE_UNUSED,2047,67644
- SAVE_INTEGER,2048,67661
- SAVE_FUNCPOINTER,2049,67679
- SAVE_POINTER,2050,67701
- SAVE_OBJECT2051,67719
-enum { SAVE_SLOT_BITS 2055,67804
-enum { SAVE_VALUE_SLOTS 2058,67901
-enum { SAVE_TYPE_BITS 2062,68009
-enum Lisp_Save_Type2064,68075
- SAVE_TYPE_INT_INT 2066,68099
- SAVE_TYPE_INT_INT_INT2067,68172
- SAVE_TYPE_OBJ_OBJ 2069,68262
- SAVE_TYPE_OBJ_OBJ_OBJ 2070,68333
- SAVE_TYPE_OBJ_OBJ_OBJ_OBJ2071,68414
- SAVE_TYPE_PTR_INT 2073,68509
- SAVE_TYPE_PTR_OBJ 2074,68582
- SAVE_TYPE_PTR_PTR 2075,68654
- SAVE_TYPE_FUNCPTR_PTR_OBJ2076,68727
- SAVE_TYPE_MEMORY 2080,68885
-typedef void (*voidfuncptr)voidfuncptr2108,69839
-struct Lisp_Save_Value2110,69876
-save_type 2134,70755
-XSAVE_POINTER 2143,70985
-set_save_pointer 2149,71147
-XSAVE_FUNCPOINTER 2155,71329
-XSAVE_INTEGER 2164,71549
-set_save_integer 2170,71711
-XSAVE_OBJECT 2179,71932
-struct Lisp_Finalizer2186,72109
-struct Lisp_Free2201,72584
-union Lisp_Misc2212,72885
-XMISC 2223,73184
-XMISCANY 2229,73273
-XMISCTYPE 2236,73382
-XMARKER 2242,73470
-XOVERLAY 2249,73585
-XSAVE_VALUE 2256,73706
-XFINALIZER 2263,73835
-struct Lisp_Intfwd2274,74120
-struct Lisp_Boolfwd2284,74414
-struct Lisp_Objfwd2294,74705
-struct Lisp_Buffer_Objfwd2302,74937
-struct Lisp_Buffer_Local_Value2334,76473
-struct Lisp_Kboard_Objfwd2362,77732
-union Lisp_Fwd2368,77841
-XFWDTYPE 2378,78087
-XBUFFER_OBJFWD 2384,78183
-struct Lisp_Float2391,78319
-XFLOAT_DATA 2401,78437
- IEEE_FLOATING_POINT2415,78946
-#define _UCHAR_T2423,79269
-typedef unsigned char UCHAR;2424,79286
-enum Lisp_Compiled2429,79369
- COMPILED_ARGLIST 2431,79392
- COMPILED_BYTECODE 2432,79418
- COMPILED_CONSTANTS 2433,79445
- COMPILED_STACK_DEPTH 2434,79473
- COMPILED_DOC_STRING 2435,79503
- COMPILED_INTERACTIVE 2436,79532
-enum char_bits2443,79834
- CHAR_ALT 2445,79853
- CHAR_SUPER 2446,79879
- CHAR_HYPER 2447,79907
- CHAR_SHIFT 2448,79935
- CHAR_CTL 2449,79963
- CHAR_META 2450,79989
- CHAR_MODIFIER_MASK 2452,80017
- CHARACTERBITS 2457,80212
-LISP_MACRO_DEFUN 2462,80270
-NATNUMP 2470,80412
-RANGED_INTEGERP 2476,80493
-#define TYPE_RANGED_INTEGERP(2481,80615
-LISP_MACRO_DEFUN 2486,80800
-VECTORP 2500,81273
-OVERLAYP 2505,81376
-SAVE_VALUEP 2510,81475
-FINALIZERP 2516,81581
-AUTOLOADP 2522,81685
-BUFFER_OBJFWDP 2528,81776
-PSEUDOVECTOR_TYPEP 2534,81874
-PSEUDOVECTORP 2542,82127
-WINDOW_CONFIGURATIONP 2558,82479
-PROCESSP 2564,82589
-WINDOWP 2570,82673
-TERMINALP 2576,82755
-SUBRP 2582,82841
-COMPILEDP 2588,82919
-BUFFERP 2594,83005
-CHAR_TABLE_P 2600,83087
-SUB_CHAR_TABLE_P 2606,83178
-BOOL_VECTOR_P 2612,83277
-FRAMEP 2618,83370
-IMAGEP 2625,83487
-ARRAYP 2632,83592
-CHECK_LIST 2638,83711
-LISP_MACRO_DEFUN_VOID 2643,83792
-CHECK_STRING_CAR 2653,84089
-CHECK_CONS 2658,84193
-CHECK_VECTOR 2663,84273
-CHECK_BOOL_VECTOR 2668,84359
-CHECK_VECTOR_OR_STRING 2674,84536
-CHECK_ARRAY 2683,84710
-CHECK_BUFFER 2688,84818
-CHECK_WINDOW 2693,84904
-CHECK_PROCESS 2699,85010
-CHECK_NATNUM 2705,85106
-#define CHECK_RANGED_INTEGER(2710,85183
-#define CHECK_TYPE_RANGED_INTEGER(2721,85566
-#define CHECK_NUMBER_COERCE_MARKER(2729,85836
-XFLOATINT 2738,86089
-CHECK_NUMBER_OR_FLOAT 2744,86160
-#define CHECK_NUMBER_OR_FLOAT_COERCE_MARKER(2749,86259
-CHECK_NUMBER_CAR 2760,86669
-CHECK_NUMBER_CDR 2768,86791
-#define DEFUN(2803,88386
-#define DEFUN(2812,88854
-FUNCTIONP 2822,89209
-enum maxargs2831,89404
- MANY 2833,89421
- UNEVALLED 2834,89436
-#define CALLMANY(2838,89539
-#define CALLN(2844,89892
-#define DEFVAR_LISP(2869,91097
-#define DEFVAR_LISP_NOPRO(2874,91269
-#define DEFVAR_BOOL(2879,91451
-#define DEFVAR_INT(2884,91624
-#define DEFVAR_BUFFER_DEFAULTS(2890,91795
-#define DEFVAR_KBOARD(2896,91999
-typedef jmp_buf sys_jmp_buf;2906,92323
-# define sys_setjmp(2907,92352
-# define sys_longjmp(2908,92387
-typedef sigjmp_buf sys_jmp_buf;2910,92459
-# define sys_setjmp(2911,92491
-# define sys_longjmp(2912,92531
-typedef jmp_buf sys_jmp_buf;2916,92690
-# define sys_setjmp(2917,92719
-# define sys_longjmp(2918,92753
-enum specbind_tag 2943,93805
- SPECPDL_UNWIND,2944,93825
- SPECPDL_UNWIND_PTR,2945,93894
- SPECPDL_UNWIND_INT,2946,93945
- SPECPDL_UNWIND_VOID,2947,93993
- SPECPDL_BACKTRACE,2948,94047
- SPECPDL_LET,2949,94105
- SPECPDL_LET_LOCAL,2951,94235
- SPECPDL_LET_DEFAULT 2952,94292
-union specbinding2955,94364
-SPECPDL_INDEX 2996,95388
-enum handlertype 3021,96410
-enum handlertype { CATCHER,3021,96410
-enum handlertype { CATCHER, CONDITION_CASE 3021,96410
-struct handler3023,96457
-#define PUSH_HANDLER(3053,97446
-#define QUIT 3101,99223
-#define QUITP 3112,99473
-struct gcpro3132,100316
-#define GC_USE_GCPROS_AS_BEFORE 3171,101297
-#define GC_MAKE_GCPROS_NOOPS 3172,101332
-#define GC_MARK_STACK_CHECK_GCPROS 3173,101364
-#define GC_USE_GCPROS_CHECK_ZOMBIES 3174,101401
-#define GC_MARK_STACK 3177,101462
-#define BYTE_MARK_STACK 3181,101562
-#define GCPRO1(3190,101833
-#define GCPRO2(3191,101873
-#define GCPRO3(3192,101939
-#define GCPRO4(3194,102034
-#define GCPRO5(3196,102154
-#define GCPRO6(3198,102299
-#define GCPRO7(3201,102474
-#define UNGCPRO 3202,102553
-#define GCPRO1(3208,102653
-#define GCPRO2(3212,102775
-#define GCPRO3(3217,102967
-#define GCPRO4(3223,103229
-#define GCPRO5(3230,103560
-#define GCPRO6(3238,103961
-#define GCPRO7(3247,104431
-#define UNGCPRO 3257,104971
-#define GCPRO1(3263,105065
-#define GCPRO2(3269,105299
-#define GCPRO3(3278,105717
-#define GCPRO4(3289,106274
-#define GCPRO5(3302,106972
-#define GCPRO6(3317,107812
-#define GCPRO7(3334,108793
-#define UNGCPRO 3353,109916
-#define RETURN_UNGCPRO(3363,110183
-vcopy 3384,110657
-set_hash_key_slot 3393,110932
-set_hash_value_slot 3399,111071
-set_symbol_function 3408,111306
-set_symbol_plist 3414,111421
-set_symbol_next 3420,111524
-blv_found 3428,111697
-set_overlay_plist 3437,111880
-string_intervals 3445,112031
-set_string_intervals 3453,112153
-set_char_table_defalt 3462,112355
-set_char_table_purpose 3467,112467
-set_char_table_extras 3475,112636
-set_char_table_contents 3482,112845
-set_sub_char_table_contents 3489,113040
-enum Arith_Comparison 3497,113303
- ARITH_EQUAL,3498,113327
- ARITH_NOTEQUAL,3499,113342
- ARITH_LESS,3500,113360
- ARITH_GRTR,3501,113374
- ARITH_LESS_OR_EQUAL,3502,113388
- ARITH_GRTR_OR_EQUAL3503,113411
-#define INTEGER_TO_CONS(3511,113762
-#define CONS_TO_INTEGER(3529,114625
-enum { NEXT_ALMOST_PRIME_LIMIT 3573,116329
-extern EMACS_INT next_almost_prime 3574,116368
-enum constype 3739,123820
-enum constype {CONSTYPE_HEAP,CONSTYPE_HEAP3739,123820
-enum constype {CONSTYPE_HEAP, CONSTYPE_PURE}CONSTYPE_PURE3739,123820
-list2i 3745,124010
-list3i 3751,124119
-list4i 3757,124258
-extern Lisp_Object make_formatted_string 3767,124634
-build_pure_c_string 3792,125662
-build_string 3801,125867
-make_uninit_vector 3820,126438
-make_uninit_sub_char_table 3833,126657
-#define ALLOCATE_PSEUDOVECTOR(3850,127201
-#define ALLOCATE_ZEROED_PSEUDOVECTOR(3858,127537
-INLINE void 3890,128943
-extern void *r_alloc r_alloc3895,129064
-#define FLOAT_TO_STRING_BUFSIZE 3927,130527
-intern 3968,132134
-intern_c_string 3974,132222
-extern _Noreturn void error 4034,135601
-fast_string_match_ignore_case 4136,140089
-INLINE void fixup_locale 4241,143854
-INLINE void synchronize_system_messages_locale 4242,143889
-INLINE void synchronize_system_time_locale 4243,143946
-#define IS_DAEMON 4257,144419
-#define DAEMON_RUNNING 4258,144459
-#define IS_DAEMON 4261,144558
-#define DAEMON_RUNNING 4262,144603
-# define WAIT_READING_MAX 4281,145422
-# define WAIT_READING_MAX 4283,145494
-extern _Noreturn void emacs_abort 4374,148386
-egetenv 4532,152809
-#define eabs(4545,153305
-#define make_fixnum_or_float(4550,153438
-enum MAX_ALLOCA 4556,153689
-enum MAX_ALLOCA { MAX_ALLOCA 4556,153689
-extern void *record_xmalloc record_xmalloc4558,153734
-#define USE_SAFE_ALLOCA 4560,153800
-#define AVAIL_ALLOCA(4564,153933
-#define SAFE_ALLOCA(4568,154044
-#define SAFE_NALLOCA(4576,154385
-#define SAFE_ALLOCA_STRING(4590,154861
-#define SAFE_FREE(4598,155113
-#define SAFE_ALLOCA_LISP(4625,155691
-# define USE_STACK_LISP_OBJECTS 4652,156813
-# undef USE_STACK_LISP_OBJECTS4658,156979
-# define USE_STACK_LISP_OBJECTS 4659,157010
-enum { defined_GC_CHECK_STRING_BYTES 4663,157085
-enum { defined_GC_CHECK_STRING_BYTES 4665,157138
-union Aligned_Cons4670,157272
-union Aligned_String4676,157352
- USE_STACK_CONS 4689,157707
- USE_STACK_STRING 4691,157813
-#define STACK_CONS(4699,158150
-#define AUTO_CONS_EXPR(4701,158247
-#define AUTO_CONS(4709,158610
-#define AUTO_LIST1(4710,158681
-#define AUTO_LIST2(4712,158789
-#define AUTO_LIST3(4716,158944
-#define AUTO_LIST4(4720,159119
-# define verify_ascii(4732,159510
-#define AUTO_STRING(4740,159818
-#define FOR_EACH_TAIL(4752,160282
-#define FOR_EACH_ALIST_VALUE(4766,160773
-maybe_gc 4774,161060
-functionp 4784,161299
+#define EMACS_LISP_H22,801
+#define DECLARE_GDB_SYM(47,1422
+# define DEFINE_GDB_SYMBOL_BEGIN(49,1509
+# define DEFINE_GDB_SYMBOL_END(50,1579
+# define DEFINE_GDB_SYMBOL_BEGIN(52,1626
+# define DEFINE_GDB_SYMBOL_END(53,1703
+#undef min57,1791
+#undef max58,1802
+#define max(59,1813
+#define min(60,1855
+#define ARRAYELTS(63,1937
+#define GCTYPEBITS 67,2080
+DEFINE_GDB_SYMBOL_BEGIN GCTYPEBITS66,2038
+# define NONPOINTER_BITS 78,2568
+# define NONPOINTER_BITS 80,2601
+typedef int EMACS_INT;91,3024
+typedef unsigned int EMACS_UINT;92,3047
+# define EMACS_INT_MAX 93,3080
+# define pI 94,3112
+typedef long int EMACS_INT;96,3204
+typedef unsigned long EMACS_UINT;97,3232
+# define EMACS_INT_MAX 98,3266
+# define pI 99,3299
+typedef long long int EMACS_INT;103,3478
+typedef unsigned long long int EMACS_UINT;104,3511
+# define EMACS_INT_MAX 105,3554
+# define pI 106,3588
+enum { BOOL_VECTOR_BITS_PER_CHAR 114,3805
+#define BOOL_VECTOR_BITS_PER_CHAR 115,3841
+typedef size_t bits_word;123,4166
+# define BITS_WORD_MAX 124,4192
+enum { BITS_PER_BITS_WORD 125,4224
+typedef unsigned char bits_word;127,4291
+# define BITS_WORD_MAX 128,4324
+enum { BITS_PER_BITS_WORD 129,4387
+ BITS_PER_CHAR 136,4571
+ BITS_PER_SHORT 137,4606
+ BITS_PER_LONG 138,4658
+ BITS_PER_EMACS_INT 139,4713
+typedef intmax_t printmax_t;148,5090
+typedef uintmax_t uprintmax_t;149,5119
+# define pMd 150,5150
+# define pMu 151,5171
+typedef EMACS_INT printmax_t;153,5198
+typedef EMACS_UINT uprintmax_t;154,5228
+# define pMd 155,5260
+# define pMu 156,5279
+# define pD 165,5665
+# define pD 167,5710
+# define pD 169,5757
+# define pD 171,5780
+# define eassert(200,7063
+# define eassume(201,7141
+# define eassert(208,7320
+# define eassume(212,7451
+enum Lisp_Bits239,8520
+#define GCALIGNMENT 243,8648
+ VALBITS 246,8743
+ INTTYPEBITS 249,8839
+ FIXNUM_BITS 252,8946
+#define VAL_MAX 263,9328
+#define USE_LSB_TAG 271,9778
+DEFINE_GDB_SYMBOL_BEGIN USE_LSB_TAG270,9734
+# define alignas(281,10078
+# define GCALIGNED 288,10228
+# define GCALIGNED 290,10293
+# define lisp_h_XLI(327,11643
+# define lisp_h_XIL(328,11674
+# define lisp_h_XLI(330,11725
+# define lisp_h_XIL(331,11752
+#define lisp_h_CHECK_LIST_CONS(333,11786
+#define lisp_h_CHECK_NUMBER(334,11857
+#define lisp_h_CHECK_SYMBOL(335,11928
+#define lisp_h_CHECK_TYPE(336,11997
+#define lisp_h_CONSP(338,12108
+#define lisp_h_EQ(339,12157
+#define lisp_h_FLOATP(340,12202
+#define lisp_h_INTEGERP(341,12253
+#define lisp_h_MARKERP(342,12334
+#define lisp_h_MISCP(343,12409
+#define lisp_h_NILP(344,12458
+#define lisp_h_SET_SYMBOL_VAL(345,12494
+#define lisp_h_SYMBOL_CONSTANT_P(347,12608
+#define lisp_h_SYMBOL_VAL(348,12672
+#define lisp_h_SYMBOLP(350,12773
+#define lisp_h_VECTORLIKEP(351,12826
+#define lisp_h_XCAR(352,12887
+#define lisp_h_XCDR(353,12925
+#define lisp_h_XCONS(354,12965
+#define lisp_h_XHASH(356,13060
+#define lisp_h_XPNTR(357,13094
+# define lisp_h_check_cons_list(360,13222
+# define lisp_h_make_number(363,13290
+# define lisp_h_XFASTINT(365,13393
+# define lisp_h_XINT(366,13430
+# define lisp_h_XSYMBOL(367,13479
+# define lisp_h_XTYPE(371,13632
+# define lisp_h_XUNTAG(372,13697
+# define XLI(381,14087
+# define XIL(382,14118
+# define CHECK_LIST_CONS(383,14149
+# define CHECK_NUMBER(384,14210
+# define CHECK_SYMBOL(385,14259
+# define CHECK_TYPE(386,14308
+# define CONSP(387,14383
+# define EQ(388,14418
+# define FLOATP(389,14453
+# define INTEGERP(390,14490
+# define MARKERP(391,14531
+# define MISCP(392,14570
+# define NILP(393,14605
+# define SET_SYMBOL_VAL(394,14638
+# define SYMBOL_CONSTANT_P(395,14701
+# define SYMBOL_VAL(396,14764
+# define SYMBOLP(397,14813
+# define VECTORLIKEP(398,14852
+# define XCAR(399,14899
+# define XCDR(400,14932
+# define XCONS(401,14965
+# define XHASH(402,15000
+# define XPNTR(403,15035
+# define check_cons_list(405,15098
+# define make_number(408,15177
+# define XFASTINT(409,15225
+# define XINT(410,15267
+# define XSYMBOL(411,15301
+# define XTYPE(412,15341
+# define XUNTAG(413,15377
+#define LISP_MACRO_DEFUN(421,15673
+#define LISP_MACRO_DEFUN_VOID(425,15846
+#define INTMASK 437,16290
+#define case_Lisp_Int 438,16343
+#define ENUM_BF(445,16682
+#define ENUM_BF(447,16723
+enum Lisp_Type451,16764
+ Lisp_Symbol 454,16852
+ Lisp_Misc 458,16994
+ Lisp_Int0 461,17068
+ Lisp_Int1 462,17087
+ Lisp_String 466,17265
+ Lisp_Vectorlike 472,17544
+ Lisp_Cons 475,17633
+ Lisp_Float 477,17671
+enum Lisp_Misc_Type485,18017
+ Lisp_Misc_Free 487,18041
+ Lisp_Misc_Marker,488,18070
+ Lisp_Misc_Overlay,489,18092
+ Lisp_Misc_Save_Value,490,18115
+ Lisp_Misc_Finalizer,491,18141
+ Lisp_Misc_Float,494,18276
+ Lisp_Misc_Limit496,18360
+enum Lisp_Fwd_Type502,18544
+ Lisp_Fwd_Int,504,18567
+ Lisp_Fwd_Bool,505,18620
+ Lisp_Fwd_Obj,506,18671
+ Lisp_Fwd_Buffer_Obj,507,18730
+ Lisp_Fwd_Kboard_Obj 508,18801
+typedef struct { EMACS_INT i; } Lisp_Object;567,21772
+#define LISP_INITIALLY(569,21818
+#undef CHECK_LISP_OBJECT_TYPE571,21849
+enum CHECK_LISP_OBJECT_TYPE 572,21879
+enum CHECK_LISP_OBJECT_TYPE { CHECK_LISP_OBJECT_TYPE 572,21879
+typedef EMACS_INT Lisp_Object;577,22055
+#define LISP_INITIALLY(578,22086
+enum CHECK_LISP_OBJECT_TYPE 579,22116
+enum CHECK_LISP_OBJECT_TYPE { CHECK_LISP_OBJECT_TYPE 579,22116
+#define LISP_INITIALLY_ZERO 582,22217
+enum symbol_interned639,24190
+ SYMBOL_UNINTERNED 641,24213
+ SYMBOL_INTERNED 642,24238
+ SYMBOL_INTERNED_IN_INITIAL_OBARRAY 643,24261
+enum symbol_redirect646,24306
+ SYMBOL_PLAINVAL 648,24329
+ SYMBOL_VARALIAS 649,24353
+ SYMBOL_LOCALIZED 650,24377
+ SYMBOL_FORWARDED 651,24401
+struct Lisp_Symbol654,24428
+#define EXFUN(707,26243
+#define DEFUN_ARGS_MANY 712,26437
+#define DEFUN_ARGS_UNEVALLED 713,26489
+#define DEFUN_ARGS_0 714,26532
+#define DEFUN_ARGS_1 715,26560
+#define DEFUN_ARGS_2 716,26595
+#define DEFUN_ARGS_3 717,26643
+#define DEFUN_ARGS_4 718,26704
+#define DEFUN_ARGS_5 719,26778
+#define DEFUN_ARGS_6 721,26871
+#define DEFUN_ARGS_7 723,26977
+#define DEFUN_ARGS_8 725,27096
+#define TAG_PTR(729,27287
+#define TAG_SYMOFFSET(734,27534
+#define XLI_BUILTIN_LISPSYM(741,27833
+#define DEFINE_LISP_SYMBOL(746,28092
+# define DEFINE_NON_NIL_Q_SYMBOL_MACROS 755,28563
+LISP_MACRO_DEFUN 762,28768
+# define ARRAY_MARK_FLAG 768,29015
+# define PSEUDOVECTOR_FLAG 774,29258
+enum pvec_type780,29559
+ PVEC_NORMAL_VECTOR,782,29576
+ PVEC_FREE,783,29598
+ PVEC_PROCESS,784,29611
+ PVEC_FRAME,785,29627
+ PVEC_WINDOW,786,29641
+ PVEC_BOOL_VECTOR,787,29656
+ PVEC_BUFFER,788,29676
+ PVEC_HASH_TABLE,789,29691
+ PVEC_TERMINAL,790,29710
+ PVEC_WINDOW_CONFIGURATION,791,29727
+ PVEC_SUBR,792,29756
+ PVEC_OTHER,793,29769
+ PVEC_COMPILED,795,29847
+ PVEC_CHAR_TABLE,796,29864
+ PVEC_SUB_CHAR_TABLE,797,29883
+ PVEC_FONT 798,29906
+enum More_Lisp_Bits801,29982
+ PSEUDOVECTOR_SIZE_BITS 808,30373
+ PSEUDOVECTOR_SIZE_MASK 809,30406
+ PSEUDOVECTOR_REST_BITS 813,30616
+ PSEUDOVECTOR_REST_MASK 814,30649
+ PSEUDOVECTOR_AREA_BITS 818,30814
+ PVEC_TYPE_MASK 819,30892
+# define VALMASK 829,31293
+DEFINE_GDB_SYMBOL_BEGIN VALMASK828,31248
+#define MOST_POSITIVE_FIXNUM 834,31523
+#define MOST_NEGATIVE_FIXNUM 835,31583
+XINT 874,32675
+XFASTINT 889,33026
+XSYMBOL 899,33254
+XTYPE 910,33472
+XUNTAG 918,33652
+LISP_MACRO_DEFUN 927,33848
+LISP_MACRO_DEFUN 940,34233
+#define FIXNUM_OVERFLOW_P(958,34846
+LISP_MACRO_DEFUN FIXNUM_OVERFLOW_P952,34623
+LISP_MACRO_DEFUN 970,35162
+XSTRING 980,35382
+#define SYMBOL_INDEX(988,35566
+XFLOAT 991,35627
+XPROCESS 1000,35769
+XWINDOW 1007,35886
+XTERMINAL 1014,36003
+XSUBR 1021,36125
+XBUFFER 1028,36236
+XCHAR_TABLE 1035,36360
+XSUB_CHAR_TABLE 1042,36497
+XBOOL_VECTOR 1049,36639
+make_lisp_ptr 1058,36818
+make_lisp_symbol 1066,37004
+builtin_lisp_symbol 1074,37188
+#define XSETINT(1079,37270
+#define XSETFASTINT(1080,37316
+#define XSETCONS(1081,37366
+#define XSETVECTOR(1082,37426
+#define XSETSTRING(1083,37494
+#define XSETSYMBOL(1084,37558
+#define XSETFLOAT(1085,37612
+#define XSETMISC(1086,37674
+#define XSETPVECTYPE(1090,37763
+#define XSETPVECTYPESIZE(1092,37879
+#define XSETPSEUDOVECTOR(1099,38176
+#define XSETTYPED_PSEUDOVECTOR(1105,38360
+#define XSETWINDOW_CONFIGURATION(1110,38570
+#define XSETPROCESS(1112,38666
+#define XSETWINDOW(1113,38732
+#define XSETTERMINAL(1114,38796
+#define XSETSUBR(1115,38864
+#define XSETCOMPILED(1116,38924
+#define XSETBUFFER(1117,38992
+#define XSETCHAR_TABLE(1118,39056
+#define XSETBOOL_VECTOR(1119,39128
+#define XSETSUB_CHAR_TABLE(1120,39202
+XINTPTR 1128,39572
+make_pointer_integer 1134,39652
+LISP_MACRO_DEFUN_VOID 1143,39817
+typedef struct interval *INTERVAL;INTERVAL1149,39978
+xcar_addr 1174,40751
+xcdr_addr 1179,40828
+LISP_MACRO_DEFUN 1185,40922
+XSETCDR 1198,41298
+CAR 1205,41448
+CDR 1212,41582
+CAR_SAFE 1221,41782
+CDR_SAFE 1226,41868
+STRING_MULTIBYTE 1243,42241
+#define STRING_BYTES_BOUND 1261,43048
+#define STRING_SET_UNIBYTE(1265,43192
+#define STRING_SET_MULTIBYTE(1275,43507
+SDATA 1286,43821
+SSDATA 1291,43899
+SREF 1297,44028
+SSET 1302,44119
+SCHARS 1307,44233
+STRING_BYTES 1316,44406
+SBYTES 1326,44586
+STRING_SET_CHARS 1331,44672
+struct vectorlike_header1343,45223
+struct Lisp_Vector1369,46473
+ ALIGNOF_STRUCT_LISP_VECTOR1378,46672
+struct Lisp_Bool_Vector1384,46855
+bool_vector_size 1399,47376
+bool_vector_data 1407,47514
+bool_vector_uchar_data 1413,47608
+bool_vector_words 1421,47794
+bool_vector_bytes 1428,47989
+bool_vector_bitref 1437,48229
+bool_vector_ref 1445,48469
+bool_vector_set 1453,48609
+ header_size 1471,49038
+ bool_header_size 1472,49097
+ word_size 1473,49162
+AREF 1479,49275
+aref_addr 1485,49382
+ASIZE 1491,49492
+ASET 1497,49574
+gc_aset 1504,49733
+enum { NIL_IS_ZERO 1515,50260
+memclear 1520,50455
+#define VECSIZE(1531,50753
+#define PSEUDOVECSIZE(1538,51038
+#define UNSIGNED_CMP(1546,51471
+#define ASCII_CHAR_P(1552,51725
+enum CHARTAB_SIZE_BITS1565,52480
+ CHARTAB_SIZE_BITS_0 1567,52507
+ CHARTAB_SIZE_BITS_1 1568,52536
+ CHARTAB_SIZE_BITS_2 1569,52565
+ CHARTAB_SIZE_BITS_3 1570,52594
+struct Lisp_Char_Table1575,52663
+struct Lisp_Sub_Char_Table1606,53743
+CHAR_TABLE_REF_ASCII 1628,54557
+CHAR_TABLE_REF 1648,55104
+CHAR_TABLE_SET 1658,55393
+struct Lisp_Subr1670,55777
+enum char_table_specials1692,56789
+ CHAR_TABLE_STANDARD_SLOTS 1697,56984
+ SUB_CHAR_TABLE_OFFSET 1701,57205
+CHAR_TABLE_EXTRA_SLOTS 1707,57368
+LISP_MACRO_DEFUN 1723,57912
+SYMBOL_BLV 1732,58172
+SYMBOL_FWD 1738,58307
+LISP_MACRO_DEFUN_VOID 1744,58419
+SET_SYMBOL_BLV 1754,58682
+SET_SYMBOL_FWD 1760,58841
+SYMBOL_NAME 1767,58992
+SYMBOL_INTERNED_P 1775,59121
+SYMBOL_INTERNED_IN_INITIAL_OBARRAY_P 1783,59290
+#define DEFSYM(1796,59800
+LISP_MACRO_DEFUN DEFSYM1792,59621
+struct hash_table_test1805,60053
+struct Lisp_Hash_Table1823,60546
+XHASH_TABLE 1880,62522
+#define XSET_HASH_TABLE(1885,62593
+HASH_TABLE_P 1889,62694
+HASH_KEY 1896,62851
+HASH_VALUE 1903,63031
+HASH_NEXT 1911,63245
+HASH_HASH 1918,63422
+HASH_INDEX 1926,63668
+HASH_TABLE_SIZE 1933,63817
+enum DEFAULT_HASH_SIZE 1940,63947
+enum DEFAULT_HASH_SIZE { DEFAULT_HASH_SIZE 1940,63947
+static double const DEFAULT_REHASH_THRESHOLD 1946,64167
+static double const DEFAULT_REHASH_SIZE 1950,64290
+sxhash_combine 1956,64456
+SXHASH_REDUCE 1964,64639
+struct Lisp_Misc_Any 1971,64797
+struct Lisp_Marker1978,64971
+struct Lisp_Overlay2021,66832
+ SAVE_UNUSED,2047,67635
+ SAVE_INTEGER,2048,67652
+ SAVE_FUNCPOINTER,2049,67670
+ SAVE_POINTER,2050,67692
+ SAVE_OBJECT2051,67710
+enum { SAVE_SLOT_BITS 2055,67795
+enum { SAVE_VALUE_SLOTS 2058,67892
+enum { SAVE_TYPE_BITS 2062,68000
+enum Lisp_Save_Type2064,68066
+ SAVE_TYPE_INT_INT 2066,68090
+ SAVE_TYPE_INT_INT_INT2067,68163
+ SAVE_TYPE_OBJ_OBJ 2069,68253
+ SAVE_TYPE_OBJ_OBJ_OBJ 2070,68324
+ SAVE_TYPE_OBJ_OBJ_OBJ_OBJ2071,68405
+ SAVE_TYPE_PTR_INT 2073,68500
+ SAVE_TYPE_PTR_OBJ 2074,68573
+ SAVE_TYPE_PTR_PTR 2075,68645
+ SAVE_TYPE_FUNCPTR_PTR_OBJ2076,68718
+ SAVE_TYPE_MEMORY 2080,68876
+typedef void (*voidfuncptr)voidfuncptr2108,69830
+struct Lisp_Save_Value2110,69867
+save_type 2134,70746
+XSAVE_POINTER 2143,70976
+set_save_pointer 2149,71138
+XSAVE_FUNCPOINTER 2155,71320
+XSAVE_INTEGER 2164,71540
+set_save_integer 2170,71702
+XSAVE_OBJECT 2179,71923
+struct Lisp_Finalizer2186,72100
+struct Lisp_Free2201,72575
+union Lisp_Misc2212,72876
+XMISC 2223,73175
+XMISCANY 2229,73264
+XMISCTYPE 2236,73373
+XMARKER 2242,73461
+XOVERLAY 2249,73576
+XSAVE_VALUE 2256,73697
+XFINALIZER 2263,73826
+struct Lisp_Intfwd2274,74111
+struct Lisp_Boolfwd2284,74405
+struct Lisp_Objfwd2294,74696
+struct Lisp_Buffer_Objfwd2302,74928
+struct Lisp_Buffer_Local_Value2334,76464
+struct Lisp_Kboard_Objfwd2362,77723
+union Lisp_Fwd2368,77832
+XFWDTYPE 2378,78078
+XBUFFER_OBJFWD 2384,78174
+struct Lisp_Float2391,78310
+XFLOAT_DATA 2401,78428
+ IEEE_FLOATING_POINT2415,78937
+#define _UCHAR_T2423,79260
+typedef unsigned char UCHAR;2424,79277
+enum Lisp_Compiled2429,79360
+ COMPILED_ARGLIST 2431,79383
+ COMPILED_BYTECODE 2432,79409
+ COMPILED_CONSTANTS 2433,79436
+ COMPILED_STACK_DEPTH 2434,79464
+ COMPILED_DOC_STRING 2435,79494
+ COMPILED_INTERACTIVE 2436,79523
+enum char_bits2443,79825
+ CHAR_ALT 2445,79844
+ CHAR_SUPER 2446,79870
+ CHAR_HYPER 2447,79898
+ CHAR_SHIFT 2448,79926
+ CHAR_CTL 2449,79954
+ CHAR_META 2450,79980
+ CHAR_MODIFIER_MASK 2452,80008
+ CHARACTERBITS 2457,80203
+LISP_MACRO_DEFUN 2462,80261
+NATNUMP 2470,80403
+RANGED_INTEGERP 2476,80484
+#define TYPE_RANGED_INTEGERP(2481,80606
+LISP_MACRO_DEFUN 2486,80791
+VECTORP 2500,81264
+OVERLAYP 2505,81367
+SAVE_VALUEP 2510,81466
+FINALIZERP 2516,81572
+AUTOLOADP 2522,81676
+BUFFER_OBJFWDP 2528,81767
+PSEUDOVECTOR_TYPEP 2534,81865
+PSEUDOVECTORP 2542,82118
+WINDOW_CONFIGURATIONP 2558,82470
+PROCESSP 2564,82580
+WINDOWP 2570,82664
+TERMINALP 2576,82746
+SUBRP 2582,82832
+COMPILEDP 2588,82910
+BUFFERP 2594,82996
+CHAR_TABLE_P 2600,83078
+SUB_CHAR_TABLE_P 2606,83169
+BOOL_VECTOR_P 2612,83268
+FRAMEP 2618,83361
+IMAGEP 2625,83478
+ARRAYP 2632,83583
+CHECK_LIST 2638,83702
+LISP_MACRO_DEFUN_VOID 2643,83783
+CHECK_STRING_CAR 2653,84080
+CHECK_CONS 2658,84184
+CHECK_VECTOR 2663,84264
+CHECK_BOOL_VECTOR 2668,84350
+CHECK_VECTOR_OR_STRING 2674,84527
+CHECK_ARRAY 2683,84701
+CHECK_BUFFER 2688,84809
+CHECK_WINDOW 2693,84895
+CHECK_PROCESS 2699,85001
+CHECK_NATNUM 2705,85097
+#define CHECK_RANGED_INTEGER(2710,85174
+#define CHECK_TYPE_RANGED_INTEGER(2721,85557
+#define CHECK_NUMBER_COERCE_MARKER(2729,85827
+XFLOATINT 2738,86080
+CHECK_NUMBER_OR_FLOAT 2744,86151
+#define CHECK_NUMBER_OR_FLOAT_COERCE_MARKER(2749,86250
+CHECK_NUMBER_CAR 2760,86660
+CHECK_NUMBER_CDR 2768,86782
+#define DEFUN(2803,88377
+#define DEFUN(2812,88845
+FUNCTIONP 2822,89200
+enum maxargs2831,89395
+ MANY 2833,89412
+ UNEVALLED 2834,89427
+#define CALLMANY(2838,89530
+#define CALLN(2844,89883
+#define DEFVAR_LISP(2869,91088
+#define DEFVAR_LISP_NOPRO(2874,91260
+#define DEFVAR_BOOL(2879,91442
+#define DEFVAR_INT(2884,91615
+#define DEFVAR_BUFFER_DEFAULTS(2890,91786
+#define DEFVAR_KBOARD(2896,91990
+typedef jmp_buf sys_jmp_buf;2906,92314
+# define sys_setjmp(2907,92343
+# define sys_longjmp(2908,92378
+typedef sigjmp_buf sys_jmp_buf;2910,92450
+# define sys_setjmp(2911,92482
+# define sys_longjmp(2912,92522
+typedef jmp_buf sys_jmp_buf;2916,92681
+# define sys_setjmp(2917,92710
+# define sys_longjmp(2918,92744
+enum specbind_tag 2943,93796
+ SPECPDL_UNWIND,2944,93816
+ SPECPDL_UNWIND_PTR,2945,93885
+ SPECPDL_UNWIND_INT,2946,93936
+ SPECPDL_UNWIND_VOID,2947,93984
+ SPECPDL_BACKTRACE,2948,94038
+ SPECPDL_LET,2949,94096
+ SPECPDL_LET_LOCAL,2951,94226
+ SPECPDL_LET_DEFAULT 2952,94283
+union specbinding2955,94355
+SPECPDL_INDEX 2996,95379
+enum handlertype 3021,96401
+enum handlertype { CATCHER,3021,96401
+enum handlertype { CATCHER, CONDITION_CASE 3021,96401
+struct handler3023,96448
+#define PUSH_HANDLER(3053,97437
+#define QUIT 3101,99214
+#define QUITP 3112,99464
+struct gcpro3132,100307
+#define GC_USE_GCPROS_AS_BEFORE 3171,101288
+#define GC_MAKE_GCPROS_NOOPS 3172,101323
+#define GC_MARK_STACK_CHECK_GCPROS 3173,101355
+#define GC_USE_GCPROS_CHECK_ZOMBIES 3174,101392
+#define GC_MARK_STACK 3177,101453
+#define BYTE_MARK_STACK 3181,101553
+#define GCPRO1(3190,101824
+#define GCPRO2(3191,101864
+#define GCPRO3(3192,101930
+#define GCPRO4(3194,102025
+#define GCPRO5(3196,102145
+#define GCPRO6(3198,102290
+#define GCPRO7(3201,102465
+#define UNGCPRO 3202,102544
+#define GCPRO1(3208,102644
+#define GCPRO2(3212,102766
+#define GCPRO3(3217,102958
+#define GCPRO4(3223,103220
+#define GCPRO5(3230,103551
+#define GCPRO6(3238,103952
+#define GCPRO7(3247,104422
+#define UNGCPRO 3257,104962
+#define GCPRO1(3263,105056
+#define GCPRO2(3269,105290
+#define GCPRO3(3278,105708
+#define GCPRO4(3289,106265
+#define GCPRO5(3302,106963
+#define GCPRO6(3317,107803
+#define GCPRO7(3334,108784
+#define UNGCPRO 3353,109907
+#define RETURN_UNGCPRO(3363,110174
+vcopy 3384,110648
+set_hash_key_slot 3393,110923
+set_hash_value_slot 3399,111062
+set_symbol_function 3408,111297
+set_symbol_plist 3414,111412
+set_symbol_next 3420,111515
+blv_found 3428,111688
+set_overlay_plist 3437,111871
+string_intervals 3445,112022
+set_string_intervals 3453,112144
+set_char_table_defalt 3462,112346
+set_char_table_purpose 3467,112458
+set_char_table_extras 3475,112627
+set_char_table_contents 3482,112836
+set_sub_char_table_contents 3489,113031
+enum Arith_Comparison 3497,113294
+ ARITH_EQUAL,3498,113318
+ ARITH_NOTEQUAL,3499,113333
+ ARITH_LESS,3500,113351
+ ARITH_GRTR,3501,113365
+ ARITH_LESS_OR_EQUAL,3502,113379
+ ARITH_GRTR_OR_EQUAL3503,113402
+#define INTEGER_TO_CONS(3511,113753
+#define CONS_TO_INTEGER(3529,114616
+enum { NEXT_ALMOST_PRIME_LIMIT 3573,116320
+extern EMACS_INT next_almost_prime 3574,116359
+enum constype 3739,123811
+enum constype {CONSTYPE_HEAP,CONSTYPE_HEAP3739,123811
+enum constype {CONSTYPE_HEAP, CONSTYPE_PURE}CONSTYPE_PURE3739,123811
+list2i 3745,124001
+list3i 3751,124110
+list4i 3757,124249
+extern Lisp_Object make_formatted_string 3767,124625
+build_pure_c_string 3792,125653
+build_string 3801,125858
+make_uninit_vector 3820,126429
+make_uninit_sub_char_table 3833,126648
+#define ALLOCATE_PSEUDOVECTOR(3850,127192
+#define ALLOCATE_ZEROED_PSEUDOVECTOR(3858,127528
+INLINE void 3890,128934
+extern void *r_alloc r_alloc3895,129055
+#define FLOAT_TO_STRING_BUFSIZE 3927,130518
+intern 3968,132125
+intern_c_string 3974,132213
+extern _Noreturn void error 4034,135592
+fast_string_match_ignore_case 4136,140080
+INLINE void fixup_locale 4241,143845
+INLINE void synchronize_system_messages_locale 4242,143880
+INLINE void synchronize_system_time_locale 4243,143937
+#define IS_DAEMON 4257,144410
+#define DAEMON_RUNNING 4258,144450
+#define IS_DAEMON 4261,144549
+#define DAEMON_RUNNING 4262,144594
+# define WAIT_READING_MAX 4281,145413
+# define WAIT_READING_MAX 4283,145485
+extern _Noreturn void emacs_abort 4374,148377
+egetenv 4532,152800
+#define eabs(4545,153296
+#define make_fixnum_or_float(4550,153429
+enum MAX_ALLOCA 4556,153680
+enum MAX_ALLOCA { MAX_ALLOCA 4556,153680
+extern void *record_xmalloc record_xmalloc4558,153725
+#define USE_SAFE_ALLOCA 4560,153791
+#define AVAIL_ALLOCA(4564,153924
+#define SAFE_ALLOCA(4568,154035
+#define SAFE_NALLOCA(4576,154376
+#define SAFE_ALLOCA_STRING(4590,154852
+#define SAFE_FREE(4598,155104
+#define SAFE_ALLOCA_LISP(4625,155682
+# define USE_STACK_LISP_OBJECTS 4652,156804
+# undef USE_STACK_LISP_OBJECTS4658,156970
+# define USE_STACK_LISP_OBJECTS 4659,157001
+enum { defined_GC_CHECK_STRING_BYTES 4663,157076
+enum { defined_GC_CHECK_STRING_BYTES 4665,157129
+union Aligned_Cons4670,157263
+union Aligned_String4676,157343
+ USE_STACK_CONS 4689,157698
+ USE_STACK_STRING 4691,157804
+#define STACK_CONS(4699,158141
+#define AUTO_CONS_EXPR(4701,158238
+#define AUTO_CONS(4709,158601
+#define AUTO_LIST1(4710,158672
+#define AUTO_LIST2(4712,158780
+#define AUTO_LIST3(4716,158935
+#define AUTO_LIST4(4720,159110
+# define verify_ascii(4732,159501
+#define AUTO_STRING(4740,159809
+#define FOR_EACH_TAIL(4752,160273
+#define FOR_EACH_ALIST_VALUE(4766,160764
+maybe_gc 4774,161051
+functionp 4784,161290
c-src/machsyscalls.c,23
#define SYSCALL(6,113
@@ -1993,27 +1991,27 @@ cp-src/burton.cpp,124
cp-src/functions.cpp,778
void Date::setDate setDate5,148
-void Date::plus plus32,939
-void Date::minus minus42,1229
-void Date::shift shift52,1407
-Date & Date::operator = operator =62,1628
-Date & Date::operator += operator +=69,1789
-Date & Date::operator -= operator -=78,1939
-Date & Date::operator ++ operator ++87,2080
-Date & Date::operator -- operator --96,2216
-int Date::operator - operator -104,2331
-int Date::operator < operator <112,2483
-int Date::operator > operator >116,2557
-int Date::operator == operator ==120,2631
-ostream& operator << operator <<124,2707
-istream& operator >> operator >>133,2943
-bool isLeap 159,3543
-bool isHoliday 163,3629
-void asort(173,3865
-void ReadVacation 186,4064
-void Debug 201,4523
-int WorkingDays(211,4867
-Date StartDay(226,5129
+void Date::plus plus32,938
+void Date::minus minus42,1226
+void Date::shift shift52,1404
+Date & Date::operator = operator =62,1625
+Date & Date::operator += operator +=69,1786
+Date & Date::operator -= operator -=78,1935
+Date & Date::operator ++ operator ++87,2076
+Date & Date::operator -- operator --96,2212
+int Date::operator - operator -104,2327
+int Date::operator < operator <112,2479
+int Date::operator > operator >116,2553
+int Date::operator == operator ==120,2627
+ostream& operator << operator <<124,2703
+istream& operator >> operator >>133,2939
+bool isLeap 159,3539
+bool isHoliday 163,3625
+void asort(173,3861
+void ReadVacation 186,4060
+void Debug 201,4519
+int WorkingDays(211,4863
+Date StartDay(226,5125
cp-src/MDiagArray2.h,482
#define octave_MDiagArray2_h 29,870
@@ -2143,134 +2141,134 @@ main(37,571
class D 41,622
D(43,659
-el-src/TAGTEST.EL,179
-(foo::defmumble bletch 1,0
-(defun foo==bar foo==bar2,33
-(defalias 'pending-delete-mode pending-delete-mode6,149
-(defalias (quote explicitly-quoted-pending-delete-mode)9,222
+el-src/TAGTEST.EL,181
+(foo::defmumble bletch 3,33
+(defun foo==bar foo==bar4,66
+(defalias 'pending-delete-mode pending-delete-mode8,182
+(defalias (quote explicitly-quoted-pending-delete-mode)11,255
el-src/emacs/lisp/progmodes/etags.el,5069
-(defvar tags-file-name 34,1034
-(defgroup etags 43,1498
-(defcustom tags-case-fold-search 47,1566
-(defcustom tags-table-list 59,2051
-(defcustom tags-compression-info-list69,2449
-(defcustom tags-add-tables 88,3231
-(defcustom tags-revert-without-query 98,3627
-(defvar tags-table-computed-list 103,3778
-(defvar tags-table-computed-list-for 112,4262
-(defvar tags-table-list-pointer 117,4510
-(defvar tags-table-list-started-at 121,4701
-(defvar tags-table-set-list 124,4821
-(defcustom find-tag-hook 129,5000
-(defcustom find-tag-default-function 137,5263
-(define-obsolete-variable-alias 'find-tag-marker-ring-lengthfind-tag-marker-ring-length145,5602
-(defcustom tags-tag-face 148,5699
-(defcustom tags-apropos-verbose 154,5834
-(defcustom tags-apropos-additional-actions 160,5998
-(defvaralias 'find-tag-marker-ring find-tag-marker-ring183,6917
-(defvar default-tags-table-function 189,7097
-(defvar tags-location-ring 194,7323
-(defvar tags-table-files 201,7599
-(defvar tags-completion-table 206,7766
-(defvar tags-included-tables 209,7858
-(defvar next-file-list 212,7953
-(defvar tags-table-format-functions 217,8059
-(defvar file-of-tag-function 224,8440
-(defvar tags-table-files-function 228,8634
-(defvar tags-completion-table-function 230,8745
-(defvar snarf-tag-function 232,8840
-(defvar goto-tag-location-function 236,9049
-(defvar find-tag-regexp-search-function 239,9222
-(defvar find-tag-regexp-tag-order 241,9343
-(defvar find-tag-regexp-next-line-after-failure-p 243,9452
-(defvar find-tag-search-function 245,9572
-(defvar find-tag-tag-order 247,9679
-(defvar find-tag-next-line-after-failure-p 249,9774
-(defvar list-tags-function 251,9880
-(defvar tags-apropos-function 253,9968
-(defvar tags-included-tables-function 255,10062
-(defvar verify-tags-table-function 257,10181
-(defun initialize-new-tags-table 260,10292
-(defun tags-table-mode 276,10980
-(defun visit-tags-table 285,11245
-(defun tags-table-check-computed-list 321,12783
-(defun tags-table-extend-computed-list 360,14654
-(defun tags-expand-table-name 400,16367
-(defun tags-table-list-member 409,16710
-(defun tags-verify-table 421,17182
-(defun tags-table-including 470,19302
-(defun tags-next-table 522,21346
-(defun visit-tags-table-buffer 543,22203
-(defun tags-reset-tags-tables 712,28513
-(defun file-of-tag 731,29170
-(defun tags-table-files 740,29519
-(defun tags-included-tables 749,29869
-(defun tags-completion-table 755,30115
-(defun tags-lazy-completion-table 783,31309
-(defun tags-completion-at-point-function 799,31944
-(defun find-tag-tag 818,32694
-(defvar last-tag 837,33367
-(defun find-tag-interactive 840,33426
-(defvar find-tag-history 852,33841
-(defun find-tag-noselect 860,34011
-(defun find-tag 932,37125
-(defun find-tag-other-window 959,38341
-(defun find-tag-other-frame 1000,40269
-(defun find-tag-regexp 1025,41443
-(defalias 'pop-tag-mark pop-tag-mark1049,42605
-(defvar tag-lines-already-matched 1052,42656
-(defun find-tag-in-order 1055,42763
-(defun tag-find-file-of-tag-noselect 1167,47109
-(defun tag-find-file-of-tag 1200,48955
-(defun etags-recognize-tags-table 1208,49181
-(defun etags-verify-tags-table 1241,50812
-(defun etags-file-of-tag 1246,51010
-(defun etags-tags-completion-table 1256,51345
-(defun etags-snarf-tag 1286,52551
-(defun etags-goto-tag-location 1324,54120
-(defun etags-list-tags 1388,56563
-(defmacro tags-with-face 1423,57838
-(defun etags-tags-apropos-additional 1431,58171
-(defun etags-tags-apropos 1465,59408
-(defun etags-tags-table-files 1527,61617
-(defun etags-tags-included-tables 1542,62053
-(defun tags-recognize-empty-tags-table 1559,62593
-(defun tag-exact-file-name-match-p 1587,63739
-(defun tag-file-name-match-p 1596,64132
-(defun tag-exact-match-p 1609,64688
-(defun tag-implicit-name-match-p 1620,65256
-(defun tag-symbol-match-p 1633,65856
-(defun tag-word-match-p 1643,66292
-(defun tag-partial-file-name-match-p 1652,66690
-(defun tag-any-match-p 1662,67134
-(defun tag-re-match-p 1667,67318
-(defcustom tags-loop-revert-buffers 1675,67567
-(defun next-file 1685,67976
-(defvar tags-loop-operate 1760,70890
-(defvar tags-loop-scan1763,70984
-(defun tags-loop-eval 1771,71313
-(defun tags-loop-continue 1782,71642
-(defun tags-search 1850,73948
-(defun tags-query-replace 1871,74774
-(defun tags-complete-tags-table-file 1896,75998
-(defun list-tags 1906,76377
-(defun tags-apropos 1934,77330
-(define-button-type 'tags-select-tags-tabletags-select-tags-table1957,78156
-(defun select-tags-table 1964,78395
-(defvar select-tags-table-mode-map 2019,80522
-(define-derived-mode select-tags-table-mode 2030,80905
-(defun select-tags-table-select 2034,81089
-(defun select-tags-table-quit 2043,81455
-(defun complete-tag 2049,81610
-(defconst etags--xref-limit 2074,82551
-(defvar etags-xref-find-definitions-tag-order 2076,82586
-(defun etags-xref-find 2082,82876
-(defun etags--xref-find-definitions 2096,83405
-(defclass xref-etags-location 2129,85119
-(defun xref-make-etags-location 2135,85342
-(cl-defmethod xref-location-marker 2139,85497
-(cl-defmethod xref-location-line 2146,85741
+(defvar tags-file-name 34,1035
+(defgroup etags 43,1499
+(defcustom tags-case-fold-search 47,1567
+(defcustom tags-table-list 59,2052
+(defcustom tags-compression-info-list69,2450
+(defcustom tags-add-tables 88,3232
+(defcustom tags-revert-without-query 98,3628
+(defvar tags-table-computed-list 103,3779
+(defvar tags-table-computed-list-for 112,4263
+(defvar tags-table-list-pointer 117,4511
+(defvar tags-table-list-started-at 121,4702
+(defvar tags-table-set-list 124,4822
+(defcustom find-tag-hook 129,5001
+(defcustom find-tag-default-function 137,5264
+(define-obsolete-variable-alias 'find-tag-marker-ring-lengthfind-tag-marker-ring-length145,5603
+(defcustom tags-tag-face 148,5700
+(defcustom tags-apropos-verbose 154,5835
+(defcustom tags-apropos-additional-actions 160,5999
+(defvaralias 'find-tag-marker-ring find-tag-marker-ring183,6921
+(defvar default-tags-table-function 189,7101
+(defvar tags-location-ring 194,7327
+(defvar tags-table-files 201,7603
+(defvar tags-completion-table 206,7770
+(defvar tags-included-tables 209,7862
+(defvar next-file-list 212,7957
+(defvar tags-table-format-functions 217,8063
+(defvar file-of-tag-function 224,8444
+(defvar tags-table-files-function 228,8638
+(defvar tags-completion-table-function 230,8749
+(defvar snarf-tag-function 232,8844
+(defvar goto-tag-location-function 236,9053
+(defvar find-tag-regexp-search-function 239,9226
+(defvar find-tag-regexp-tag-order 241,9347
+(defvar find-tag-regexp-next-line-after-failure-p 243,9456
+(defvar find-tag-search-function 245,9576
+(defvar find-tag-tag-order 247,9683
+(defvar find-tag-next-line-after-failure-p 249,9778
+(defvar list-tags-function 251,9884
+(defvar tags-apropos-function 253,9972
+(defvar tags-included-tables-function 255,10066
+(defvar verify-tags-table-function 257,10185
+(defun initialize-new-tags-table 260,10296
+(defun tags-table-mode 276,10984
+(defun visit-tags-table 285,11249
+(defun tags-table-check-computed-list 321,12787
+(defun tags-table-extend-computed-list 360,14658
+(defun tags-expand-table-name 400,16371
+(defun tags-table-list-member 409,16714
+(defun tags-verify-table 421,17186
+(defun tags-table-including 470,19306
+(defun tags-next-table 522,21350
+(defun visit-tags-table-buffer 543,22207
+(defun tags-reset-tags-tables 712,28517
+(defun file-of-tag 731,29174
+(defun tags-table-files 740,29524
+(defun tags-included-tables 749,29874
+(defun tags-completion-table 755,30120
+(defun tags-lazy-completion-table 783,31314
+(defun tags-completion-at-point-function 799,31949
+(defun find-tag-tag 818,32699
+(defvar last-tag 837,33372
+(defun find-tag-interactive 840,33431
+(defvar find-tag-history 852,33846
+(defun find-tag-noselect 860,34016
+(defun find-tag 932,37130
+(defun find-tag-other-window 959,38346
+(defun find-tag-other-frame 1000,40274
+(defun find-tag-regexp 1025,41448
+(defalias 'pop-tag-mark pop-tag-mark1049,42610
+(defvar tag-lines-already-matched 1052,42661
+(defun find-tag-in-order 1055,42768
+(defun tag-find-file-of-tag-noselect 1167,47114
+(defun tag-find-file-of-tag 1200,48960
+(defun etags-recognize-tags-table 1208,49186
+(defun etags-verify-tags-table 1241,50817
+(defun etags-file-of-tag 1246,51015
+(defun etags-tags-completion-table 1256,51350
+(defun etags-snarf-tag 1286,52556
+(defun etags-goto-tag-location 1324,54125
+(defun etags-list-tags 1388,56568
+(defmacro tags-with-face 1423,57843
+(defun etags-tags-apropos-additional 1431,58176
+(defun etags-tags-apropos 1465,59413
+(defun etags-tags-table-files 1527,61622
+(defun etags-tags-included-tables 1542,62058
+(defun tags-recognize-empty-tags-table 1559,62598
+(defun tag-exact-file-name-match-p 1587,63744
+(defun tag-file-name-match-p 1596,64137
+(defun tag-exact-match-p 1609,64693
+(defun tag-implicit-name-match-p 1620,65261
+(defun tag-symbol-match-p 1633,65861
+(defun tag-word-match-p 1643,66297
+(defun tag-partial-file-name-match-p 1652,66695
+(defun tag-any-match-p 1662,67139
+(defun tag-re-match-p 1667,67323
+(defcustom tags-loop-revert-buffers 1675,67572
+(defun next-file 1685,67981
+(defvar tags-loop-operate 1760,70895
+(defvar tags-loop-scan1763,70989
+(defun tags-loop-eval 1771,71318
+(defun tags-loop-continue 1782,71647
+(defun tags-search 1850,73953
+(defun tags-query-replace 1871,74779
+(defun tags-complete-tags-table-file 1896,76003
+(defun list-tags 1906,76382
+(defun tags-apropos 1934,77335
+(define-button-type 'tags-select-tags-tabletags-select-tags-table1957,78161
+(defun select-tags-table 1964,78400
+(defvar select-tags-table-mode-map 2019,80527
+(define-derived-mode select-tags-table-mode 2030,80910
+(defun select-tags-table-select 2034,81094
+(defun select-tags-table-quit 2043,81460
+(defun complete-tag 2049,81615
+(defconst etags--xref-limit 2074,82556
+(defvar etags-xref-find-definitions-tag-order 2076,82591
+(defun etags-xref-find 2082,82881
+(defun etags--xref-find-definitions 2096,83410
+(defclass xref-etags-location 2129,85124
+(defun xref-make-etags-location 2135,85347
+(cl-defmethod xref-location-marker 2139,85502
+(cl-defmethod xref-location-line 2146,85746
erl-src/gs_dialog.erl,98
-define(VERSION2,32
@@ -2341,10 +2339,10 @@ func main(29,285
html-src/softwarelibero.html,200
Cos'è il software libero?4,38
-Licenze d'uso di un programmalicenze65,2500
-Sfatiamo alcuni miti138,6118
-Il movimento open sourceoss191,8037
-Impatto pratico del software liberoimpatto231,10066
+Licenze d'uso di un programmalicenze65,2502
+Sfatiamo alcuni miti138,6122
+Il movimento open sourceoss191,8041
+Impatto pratico del software liberoimpatto231,10070
html-src/index.shtml,104
&nbsp;8,281
@@ -2370,13 +2368,13 @@ MTGmtg41,1482
Fracasfracas65,2624
GaliLEOgalileo101,4232
Leasqrleasqr114,4677
-Free software that I wrote for the GNU project or for my personal or workgnu142,6065
-Etagsetags148,6180
-checkiso161,6729
-cgrep178,7547
-debian-bug.eldebian-bug190,7979
-tcpdump205,8564
-Links to interesting softwarelinks216,8891
+Free software that I wrote for the GNU project or for my personal or workgnu142,6066
+Etagsetags148,6181
+checkiso161,6731
+cgrep178,7549
+debian-bug.eldebian-bug190,7981
+tcpdump205,8566
+Links to interesting softwarelinks216,8893
lua-src/allegro.lua,400
local function get_layer_by_name 7,175
@@ -2906,22 +2904,22 @@ ord_add_element(71,1867
ord_del_element(85,2344
ord_disjoint(100,2783
ord_intersect(108,2953
-ord_intersection(126,3552
-ord_intersection3(130,3691
-ord_intersection(150,4531
-ord_intersection4(154,4703
-ord_intersection(176,5664
-ord_intersection2(181,5812
-ord_member(200,6318
-ord_seteq(216,6683
-ord_setproduct(225,6971
-ord_subset(240,7377
-ord_subtract(257,7861
-ord_symdiff(265,8054
-ord_union(288,8887
-ord_union4(303,9352
-ord_union(324,10171
-ord_union_all(329,10313
+ord_intersection(126,3553
+ord_intersection3(130,3692
+ord_intersection(150,4533
+ord_intersection4(154,4705
+ord_intersection(176,5666
+ord_intersection2(181,5814
+ord_member(200,6320
+ord_seteq(216,6685
+ord_setproduct(225,6973
+ord_subset(240,7379
+ord_subtract(257,7863
+ord_symdiff(265,8056
+ord_union(288,8889
+ord_union4(303,9354
+ord_union(324,10173
+ord_union_all(329,10315
prol-src/natded.prolog,2319
expandmng(100,2879
@@ -2943,92 +2941,92 @@ complete(328,10055
add_active(340,10527
parse(353,10949
derived_analyses(364,11341
-build(378,11965
-buildact(392,12521
-mapsyn(412,13542
-add_edge(434,14278
-findcats(447,14758
-normalize_tree(465,15478
-normalize_trees(475,15856
-expandmng_tree(486,16248
-expandmng_trees(496,16614
-cat(511,17013
-subtree(644,21266
-hypothetical_mem(653,21565
-make_coor(667,22130
-start_up:-start_up688,23013
-tokenizeatom(710,23921
-tokenize(720,24348
-isoperator(752,25377
-isoptab(756,25431
-specialsymbol(765,25756
-sstab(771,25861
-parse_cgi(787,26347
-keyvalseq(792,26510
-andkeyvalseq(796,26609
-keyval(799,26688
-valseq(807,26920
-plusvalseq(810,27007
-val(816,27109
-argvals(824,27426
-commaargvals(828,27503
-atomval(833,27578
-atom(836,27640
-action(846,28004
-keyvalcgi(864,28649
-keyvalscgi(865,28670
-outsyn(868,28726
-act(876,29060
-actout(901,29906
-texttreelist(912,30089
-htmltreelist(918,30190
-fitchtreelist(924,30304
-pp_html_table_tree(938,30759
-pp_html_tree(949,31113
-pp_html_trees(988,32381
-pp_html_table_fitch_tree(999,32769
-pp_html_fitch_tree(1017,33672
-removeexp(1129,39002
-splitexp(1142,39490
-pp_exp(1155,39990
-map_word(1168,40249
-pp_exps(1180,40474
-pp_tree(1188,40777
-pp_trees(1216,41807
-pp_word_list(1225,42128
-pp_word(1231,42262
-pp_word_list_rest(1238,42569
-pp_cat(1248,42929
-pp_syn(1255,43196
-pp_syn_paren(1276,43899
-pp_paren(1293,44377
-pp_syn_back(1300,44661
-pp_bas_cat(1311,45001
-writecat(1322,45409
-writesubs(1351,46455
-writesups(1361,46757
-writelistsubs(1371,47090
-pp_lam(1380,47408
-pp_lam_bracket(1398,48022
-pp_lam_paren(1407,48338
-pp_rule(1429,49238
-member(1447,49866
-append_list(1451,49919
-append(1456,50010
-at_least_one_member(1460,50076
-numbervars(1464,50171
-reverse(1467,50209
-select(1471,50290
-select_last(1475,50357
-cat_atoms(1479,50436
-writelist(1485,50524
-write_lex_cat(1492,50676
-writebreaklex(1500,50988
-write_lex(1513,51265
-writebreak(1521,51541
-tt:-tt1531,51713
-mt:-mt1534,51784
-cmt:-cmt1537,51878
+build(378,11967
+buildact(392,12523
+mapsyn(412,13544
+add_edge(434,14280
+findcats(447,14760
+normalize_tree(465,15480
+normalize_trees(475,15858
+expandmng_tree(486,16250
+expandmng_trees(496,16616
+cat(511,17015
+subtree(644,21268
+hypothetical_mem(653,21567
+make_coor(667,22132
+start_up:-start_up688,23015
+tokenizeatom(710,23923
+tokenize(720,24350
+isoperator(752,25379
+isoptab(756,25433
+specialsymbol(765,25758
+sstab(771,25863
+parse_cgi(787,26349
+keyvalseq(792,26512
+andkeyvalseq(796,26611
+keyval(799,26690
+valseq(807,26922
+plusvalseq(810,27009
+val(816,27111
+argvals(824,27428
+commaargvals(828,27505
+atomval(833,27580
+atom(836,27642
+action(846,28006
+keyvalcgi(864,28651
+keyvalscgi(865,28672
+outsyn(868,28728
+act(876,29062
+actout(901,29908
+texttreelist(912,30091
+htmltreelist(918,30192
+fitchtreelist(924,30306
+pp_html_table_tree(938,30761
+pp_html_tree(949,31115
+pp_html_trees(988,32383
+pp_html_table_fitch_tree(999,32771
+pp_html_fitch_tree(1017,33674
+removeexp(1129,39004
+splitexp(1142,39492
+pp_exp(1155,39992
+map_word(1168,40251
+pp_exps(1180,40476
+pp_tree(1188,40779
+pp_trees(1216,41809
+pp_word_list(1225,42130
+pp_word(1231,42264
+pp_word_list_rest(1238,42571
+pp_cat(1248,42931
+pp_syn(1255,43198
+pp_syn_paren(1276,43901
+pp_paren(1293,44379
+pp_syn_back(1300,44663
+pp_bas_cat(1311,45003
+writecat(1322,45411
+writesubs(1351,46457
+writesups(1361,46759
+writelistsubs(1371,47092
+pp_lam(1380,47410
+pp_lam_bracket(1398,48024
+pp_lam_paren(1407,48340
+pp_rule(1429,49240
+member(1447,49868
+append_list(1451,49921
+append(1456,50012
+at_least_one_member(1460,50078
+numbervars(1464,50173
+reverse(1467,50211
+select(1471,50292
+select_last(1475,50359
+cat_atoms(1479,50438
+writelist(1485,50526
+write_lex_cat(1492,50678
+writebreaklex(1500,50990
+write_lex(1513,51267
+writebreak(1521,51543
+tt:-tt1531,51715
+mt:-mt1534,51786
+cmt:-cmt1537,51880
pyt-src/server.py,1438
class Controls:Controls17,358
@@ -3136,6 +3134,11 @@ module A9,57
alias_method ( :foo2,foo237,586
A::Constant Constant42,655
+rs-src/test.rs,52
+enum IpAddrKind 3,11
+fn test1(8,48
+fn main(12,88
+
scm-src/test.scm,260
(define hello 1,0
(set! hello 3,32
@@ -3153,730 +3156,825 @@ tex-src/gzip.texi,303
@node Top,62,2139
@node Copying,80,2652
@node Overview,83,2705
-@node Sample,166,7272
-@node Invoking gzip,Invoking gzip210,8828
-@node Advanced usage,Advanced usage357,13496
-@node Environment,420,15208
-@node Tapes,437,15769
-@node Problems,460,16768
-@node Concept Index,Concept Index473,17288
+@node Sample,166,7273
+@node Invoking gzip,Invoking gzip210,8829
+@node Advanced usage,Advanced usage357,13497
+@node Environment,420,15209
+@node Tapes,437,15770
+@node Problems,460,16769
+@node Concept Index,Concept Index473,17289
tex-src/texinfo.tex,30627
-\def\texinfoversion{\texinfoversion26,1032
-\def\tie{\tie49,1523
-\def\gloggingall{\gloggingall72,2273
-\def\loggingall{\loggingall73,2342
-\def\onepageout#1{\onepageout99,3279
-\def\croppageout#1{\croppageout115,4029
-\def\cropmarks{\cropmarks142,5089
-\def\pagebody#1{\pagebody144,5136
-\def\ewtop{\ewtop157,5591
-\def\nstop{\nstop158,5655
-\def\ewbot{\ewbot160,5738
-\def\nsbot{\nsbot161,5802
-\def\parsearg #1{\parsearg170,6101
-\def\parseargx{\parseargx172,6179
-\def\parseargline{\parseargline182,6419
-\def\flushcr{\flushcr186,6540
-\newif\ifENV \ENVfalse \def\inENV{\inENV190,6739
-\def\ENVcheck{\ENVcheck191,6803
-\outer\def\begin{\begin198,7050
-\def\beginxxx #1{\beginxxx200,7088
-\def\end{\end208,7343
-\def\endxxx #1{\endxxx210,7371
-\def\errorE#1{\errorE216,7560
-\def\singlespace{\singlespace222,7754
-\def\@{\@232,7977
-\def\`{\`236,8077
-\def\'{\'237,8089
-\def\mylbrace {\mylbrace241,8137
-\def\myrbrace {\myrbrace242,8170
-\def\:{\:247,8284
-\def\*{\*250,8338
-\def\.{\.253,8414
-\def\w#1{\w258,8645
-\def\group{\group268,9128
- \def\Egroup{\Egroup273,9292
-\def\need{\need289,9734
-\def\needx#1{\needx300,10011
-\def\dots{\dots339,11397
-\def\page{\page343,11461
-\def\exdent{\exdent353,11788
-\def\exdentyyy #1{\exdentyyy354,11821
-\def\nofillexdent{\nofillexdent357,11965
-\def\nofillexdentyyy #1{\nofillexdentyyy358,12010
-\def\include{\include365,12194
-\def\includezzz #1{\includezzz366,12229
-\def\thisfile{\thisfile369,12280
-\def\center{\center373,12343
-\def\centerzzz #1{\centerzzz374,12376
-\def\sp{\sp380,12518
-\def\spxxx #1{\spxxx381,12543
-\def\comment{\comment387,12717
-\def\commentxxx #1{\commentxxx390,12814
-\def\ignoresections{\ignoresections396,12983
-\let\chapter=\relax=\relax397,13005
-\let\section=\relax=\relax406,13250
-\let\subsection=\relax=\relax409,13311
-\let\subsubsection=\relax=\relax410,13334
-\let\appendix=\relax=\relax411,13360
-\let\appendixsec=\relaxsec=\relax412,13381
-\let\appendixsection=\relaxsection=\relax413,13405
-\let\appendixsubsec=\relaxsubsec=\relax414,13433
-\let\appendixsubsection=\relaxsubsection=\relax415,13460
-\let\appendixsubsubsec=\relaxsubsubsec=\relax416,13491
-\let\appendixsubsubsection=\relaxsubsubsection=\relax417,13521
-\def\ignore{\ignore423,13623
-\long\def\ignorexxx #1\end ignore{\ignorexxx427,13763
-\def\direntry{\direntry429,13822
-\long\def\direntryxxx #1\end direntry{\direntryxxx430,13861
-\def\ifset{\ifset434,13971
-\def\ifsetxxx #1{\ifsetxxx436,14029
-\def\Eifset{\Eifset440,14156
-\def\ifsetfail{\ifsetfail441,14170
-\long\def\ifsetfailxxx #1\end ifset{\ifsetfailxxx442,14226
-\def\ifclear{\ifclear444,14287
-\def\ifclearxxx #1{\ifclearxxx446,14349
-\def\Eifclear{\Eifclear450,14480
-\def\ifclearfail{\ifclearfail451,14496
-\long\def\ifclearfailxxx #1\end ifclear{\ifclearfailxxx452,14556
-\def\set{\set456,14707
-\def\setxxx #1{\setxxx457,14734
-\def\clear{\clear460,14796
-\def\clearxxx #1{\clearxxx461,14827
-\def\iftex{\iftex466,14944
-\def\Eiftex{\Eiftex467,14957
-\def\ifinfo{\ifinfo468,14971
-\long\def\ifinfoxxx #1\end ifinfo{\ifinfoxxx469,15021
-\long\def\menu #1\end menu{\menu471,15080
-\def\asis#1{\asis472,15109
-\def\math#1{\math485,15652
-\def\node{\node487,15696
-\def\nodezzz#1{\nodezzz488,15734
-\def\nodexxx[#1,#2]{\nodexxx[489,15765
-\def\donoderef{\donoderef492,15827
-\def\unnumbnoderef{\unnumbnoderef496,15948
-\def\appendixnoderef{\appendixnoderef500,16079
-\expandafter\expandafter\expandafter\appendixsetref{setref501,16125
-\let\refill=\relaxill=\relax504,16214
-\def\setfilename{\setfilename509,16428
-\outer\def\bye{\bye518,16674
-\def\inforef #1{\inforef520,16730
-\def\inforefzzz #1,#2,#3,#4**{\inforefzzz521,16768
-\def\losespace #1{\losespace523,16865
-\def\sf{\sf532,17069
-\font\defbf=cmbx10 scaled \magstep1 %was 1314bf=cmbx10558,17864
-\font\deftt=cmtt10 scaled \magstep1tt=cmtt10559,17910
-\def\df{\df560,17946
-\def\resetmathfonts{\resetmathfonts635,20540
-\def\textfonts{\textfonts648,21129
-\def\chapfonts{\chapfonts653,21344
-\def\secfonts{\secfonts658,21560
-\def\subsecfonts{\subsecfonts663,21765
-\def\indexfonts{\indexfonts668,21982
-\def\smartitalicx{\smartitalicx691,22714
-\def\smartitalic#1{\smartitalic692,22790
-\let\cite=\smartitalic=\smartitalic698,22935
-\def\b#1{\b700,22959
-\def\t#1{\t703,22994
-\def\samp #1{\samp706,23146
-\def\key #1{\key707,23179
-\def\ctrl #1{\ctrl708,23240
-\def\tclose#1{\tclose716,23442
-\def\ {\720,23608
-\def\xkey{\xkey728,23877
-\def\kbdfoo#1#2#3\par{\kbdfoo729,23893
-\def\dmn#1{\dmn738,24194
-\def\kbd#1{\kbd740,24221
-\def\l#1{\l742,24278
-\def\r#1{\r744,24307
-\def\sc#1{\sc746,24375
-\def\ii#1{\ii747,24418
-\def\titlefont#1{\titlefont755,24651
-\def\titlepage{\titlepage761,24754
- \def\subtitlefont{\subtitlefont766,24981
- \def\authorfont{\authorfont768,25065
- \def\title{\title774,25275
- \def\titlezzz##1{\titlezzz775,25310
- \def\subtitle{\subtitle783,25625
- \def\subtitlezzz##1{\subtitlezzz784,25666
- \def\author{\author787,25784
- \def\authorzzz##1{\authorzzz788,25821
- \def\page{\page794,26112
-\def\Etitlepage{\Etitlepage804,26281
-\def\finishtitlepage{\finishtitlepage817,26669
-\def\evenheading{\evenheading846,27677
-\def\oddheading{\oddheading847,27720
-\def\everyheading{\everyheading848,27761
-\def\evenfooting{\evenfooting850,27807
-\def\oddfooting{\oddfooting851,27850
-\def\everyfooting{\everyfooting852,27891
-\def\headings #1 {\headings893,29583
-\def\HEADINGSoff{\HEADINGSoff895,29632
-\def\HEADINGSdouble{\HEADINGSdouble904,30059
-\def\HEADINGSsingle{\HEADINGSsingle914,30379
-\def\HEADINGSon{\HEADINGSon922,30600
-\def\HEADINGSafter{\HEADINGSafter924,30634
-\def\HEADINGSdoublex{\HEADINGSdoublex926,30729
-\def\HEADINGSsingleafter{\HEADINGSsingleafter933,30917
-\def\HEADINGSsinglex{\HEADINGSsinglex934,30978
-\def\today{\today943,31253
-\def\thistitle{\thistitle958,31798
-\def\settitle{\settitle959,31823
-\def\settitlezzz #1{\settitlezzz960,31860
-\def\internalBitem{\internalBitem992,32790
-\def\internalBitemx{\internalBitemx993,32840
-\def\internalBxitem "#1"{\internalBxitem995,32885
-\def\internalBxitemx "#1"{\internalBxitemx996,32965
-\def\internalBkitem{\internalBkitem998,33040
-\def\internalBkitemx{\internalBkitemx999,33092
-\def\kitemzzz #1{\kitemzzz1001,33139
-\def\xitemzzz #1{\xitemzzz1004,33241
-\def\itemzzz #1{\itemzzz1007,33344
-\def\item{\item1037,34415
-\def\itemx{\itemx1038,34466
-\def\kitem{\kitem1039,34519
-\def\kitemx{\kitemx1040,34572
-\def\xitem{\xitem1041,34627
-\def\xitemx{\xitemx1042,34680
-\def\description{\description1045,34790
-\def\table{\table1047,34840
-\def\ftable{\ftable1052,34984
-\def\Eftable{\Eftable1056,35130
-\def\vtable{\vtable1059,35199
-\def\Evtable{\Evtable1063,35345
-\def\dontindex #1{\dontindex1066,35414
-\def\fnitemindex #1{\fnitemindex1067,35434
-\def\vritemindex #1{\vritemindex1068,35479
-\def\tablez #1#2#3#4#5#6{\tablez1074,35628
-\def\Edescription{\Edescription1077,35686
-\def\itemfont{\itemfont1082,35888
-\def\Etable{\Etable1090,36114
-\def\itemize{\itemize1103,36438
-\def\itemizezzz #1{\itemizezzz1105,36474
-\def\itemizey #1#2{\itemizey1110,36569
-\def#2{1119,36815
-\def\itemcontents{\itemcontents1120,36856
-\def\bullet{\bullet1123,36904
-\def\minus{\minus1124,36931
-\def\frenchspacing{\frenchspacing1128,37039
-\def\splitoff#1#2\endmark{\splitoff1134,37264
-\def\enumerate{\enumerate1140,37494
-\def\enumeratezzz #1{\enumeratezzz1141,37533
-\def\enumeratey #1 #2\endenumeratey{\enumeratey1142,37586
- \def\thearg{\thearg1146,37733
- \ifx\thearg\empty \def\thearg{\thearg1147,37752
-\def\numericenumerate{\numericenumerate1184,39086
-\def\lowercaseenumerate{\lowercaseenumerate1190,39216
-\def\uppercaseenumerate{\uppercaseenumerate1203,39563
-\def\startenumeration#1{\startenumeration1219,40053
-\def\alphaenumerate{\alphaenumerate1227,40235
-\def\capsenumerate{\capsenumerate1228,40270
-\def\Ealphaenumerate{\Ealphaenumerate1229,40304
-\def\Ecapsenumerate{\Ecapsenumerate1230,40338
-\def\itemizeitem{\itemizeitem1234,40418
-\def\newindex #1{\newindex1259,41275
-\def\defindex{\defindex1268,41564
-\def\newcodeindex #1{\newcodeindex1272,41672
-\def\defcodeindex{\defcodeindex1279,41932
-\def\synindex #1 #2 {\synindex1283,42112
-\def\syncodeindex #1 #2 {\syncodeindex1292,42452
-\def\doindex#1{\doindex1309,43131
-\def\singleindexer #1{\singleindexer1310,43190
-\def\docodeindex#1{\docodeindex1313,43302
-\def\singlecodeindexer #1{\singlecodeindexer1314,43369
-\def\indexdummies{\indexdummies1316,43427
-\def\_{\_1317,43447
-\def\w{\w1318,43475
-\def\bf{\bf1319,43502
-\def\rm{\rm1320,43531
-\def\sl{\sl1321,43560
-\def\sf{\sf1322,43589
-\def\tt{\tt1323,43617
-\def\gtr{\gtr1324,43645
-\def\less{\less1325,43675
-\def\hat{\hat1326,43707
-\def\char{\char1327,43737
-\def\TeX{\TeX1328,43769
-\def\dots{\dots1329,43799
-\def\copyright{\copyright1330,43832
-\def\tclose##1{\tclose1331,43875
-\def\code##1{\code1332,43920
-\def\samp##1{\samp1333,43961
-\def\t##1{\t1334,44002
-\def\r##1{\r1335,44037
-\def\i##1{\i1336,44072
-\def\b##1{\b1337,44107
-\def\cite##1{\cite1338,44142
-\def\key##1{\key1339,44183
-\def\file##1{\file1340,44222
-\def\var##1{\var1341,44263
-\def\kbd##1{\kbd1342,44302
-\def\indexdummyfont#1{\indexdummyfont1347,44458
-\def\indexdummytex{\indexdummytex1348,44484
-\def\indexdummydots{\indexdummydots1349,44508
-\def\indexnofonts{\indexnofonts1351,44534
-\let\w=\indexdummyfontdummyfont1352,44554
-\let\t=\indexdummyfontdummyfont1353,44577
-\let\r=\indexdummyfontdummyfont1354,44600
-\let\i=\indexdummyfontdummyfont1355,44623
-\let\b=\indexdummyfontdummyfont1356,44646
-\let\emph=\indexdummyfontdummyfont1357,44669
-\let\strong=\indexdummyfontdummyfont1358,44695
-\let\cite=\indexdummyfont=\indexdummyfont1359,44723
-\let\sc=\indexdummyfontdummyfont1360,44749
-\let\tclose=\indexdummyfontdummyfont1364,44921
-\let\code=\indexdummyfontdummyfont1365,44949
-\let\file=\indexdummyfontdummyfont1366,44975
-\let\samp=\indexdummyfontdummyfont1367,45001
-\let\kbd=\indexdummyfontdummyfont1368,45027
-\let\key=\indexdummyfontdummyfont1369,45052
-\let\var=\indexdummyfontdummyfont1370,45077
-\let\TeX=\indexdummytexdummytex1371,45102
-\let\dots=\indexdummydotsdummydots1372,45126
-\let\indexbackslash=0 %overridden during \printindex.backslash=01382,45378
-\def\doind #1#2{\doind1384,45434
-{\indexdummies % Must do this here, since \bf, etc expand at this stagedummies1386,45477
-\def\rawbackslashxx{\rawbackslashxx1389,45617
-{\indexnofontsnofonts1394,45879
-\def\dosubind #1#2#3{\dosubind1405,46190
-{\indexdummies % Must do this here, since \bf, etc expand at this stagedummies1407,46238
-\def\rawbackslashxx{\rawbackslashxx1410,46342
-{\indexnofontsnofonts1414,46496
-\def\findex {\findex1443,47427
-\def\kindex {\kindex1444,47450
-\def\cindex {\cindex1445,47473
-\def\vindex {\vindex1446,47496
-\def\tindex {\tindex1447,47519
-\def\pindex {\pindex1448,47542
-\def\cindexsub {\cindexsub1450,47566
-\def\printindex{\printindex1462,47893
-\def\doprintindex#1{\doprintindex1464,47934
- \def\indexbackslash{\indexbackslash1481,48419
- \indexfonts\rm \tolerance=9500 \advance\baselineskip -1ptfonts\rm1482,48458
-\def\initial #1{\initial1517,49530
-\def\entry #1#2{\entry1523,49737
- \null\nobreak\indexdotfill % Have leaders before the page number.dotfill1540,50384
-\def\indexdotfill{\indexdotfill1549,50712
-\def\primary #1{\primary1552,50818
-\def\secondary #1#2{\secondary1556,50900
-\noindent\hskip\secondaryindent\hbox{#1}\indexdotfill #2\pardotfill1559,50982
-\newbox\partialpageialpage1566,51155
-\def\begindoublecolumns{\begindoublecolumns1572,51313
- \output={\global\setbox\partialpage=ialpage=1573,51349
-\def\enddoublecolumns{\enddoublecolumns1577,51537
-\def\doublecolumnout{\doublecolumnout1580,51622
- \dimen@=\pageheight \advance\dimen@ by-\ht\partialpageialpage1581,51691
-\def\pagesofar{\pagesofar1584,51869
-\def\balancecolumns{\balancecolumns1588,52106
- \availdimen@=\pageheight \advance\availdimen@ by-\ht\partialpageialpage1594,52277
- \dimen@=\pageheight \advance\dimen@ by-\ht\partialpageialpage1600,52538
-\newcount \appendixno \appendixno = `\@no1627,53443
-\def\appendixletter{\appendixletter1628,53484
-\def\opencontents{\opencontents1632,53587
-\def\thischapter{\thischapter1637,53768
-\def\seccheck#1{\seccheck1638,53806
-\def\chapternofonts{\chapternofonts1643,53910
-\def\result{\result1646,53985
-\def\equiv{\equiv1647,54020
-\def\expansion{\expansion1648,54053
-\def\print{\print1649,54094
-\def\TeX{\TeX1650,54127
-\def\dots{\dots1651,54156
-\def\copyright{\copyright1652,54187
-\def\tt{\tt1653,54228
-\def\bf{\bf1654,54255
-\def\w{\w1655,54283
-\def\less{\less1656,54308
-\def\gtr{\gtr1657,54339
-\def\hat{\hat1658,54368
-\def\char{\char1659,54397
-\def\tclose##1{\tclose1660,54428
-\def\code##1{\code1661,54472
-\def\samp##1{\samp1662,54512
-\def\r##1{\r1663,54552
-\def\b##1{\b1664,54586
-\def\key##1{\key1665,54620
-\def\file##1{\file1666,54658
-\def\kbd##1{\kbd1667,54698
-\def\i##1{\i1669,54806
-\def\cite##1{\cite1670,54840
-\def\var##1{\var1671,54880
-\def\emph##1{\emph1672,54918
-\def\dfn##1{\dfn1673,54958
-\def\thischaptername{\thischaptername1676,54999
-\outer\def\chapter{\chapter1677,55038
-\def\chapterzzz #1{\chapterzzz1678,55079
-{\chapternofonts%nofonts%1687,55475
-\global\let\section = \numberedsec=1692,55628
-\global\let\subsection = \numberedsubsec=1693,55663
-\global\let\subsubsection = \numberedsubsubsec=1694,55704
-\outer\def\appendix{\appendix1697,55755
-\def\appendixzzz #1{\appendixzzz1698,55798
-\global\advance \appendixno by 1 \message{no1700,55875
-\chapmacro {#1}{Appendix \appendixletter}letter1701,55944
-\xdef\thischapter{Appendix \appendixletter: \noexpand\thischaptername}letter:1704,56037
-{\chapternofonts%nofonts%1705,56109
- {#1}{Appendix \appendixletter}letter1707,56165
-\appendixnoderef %noderef1710,56265
-\global\let\section = \appendixsec=1711,56284
-\global\let\subsection = \appendixsubsec=1712,56319
-\global\let\subsubsection = \appendixsubsubsec=1713,56360
-\outer\def\top{\top1716,56411
-\outer\def\unnumbered{\unnumbered1717,56451
-\def\unnumberedzzz #1{\unnumberedzzz1718,56498
-{\chapternofonts%nofonts%1722,56661
-\global\let\section = \unnumberedsec=1727,56811
-\global\let\subsection = \unnumberedsubsec=1728,56848
-\global\let\subsubsection = \unnumberedsubsubsec=1729,56891
-\outer\def\numberedsec{\numberedsec1732,56944
-\def\seczzz #1{\seczzz1733,56985
-{\chapternofonts%nofonts%1736,57141
-\outer\def\appendixsection{\appendixsection1745,57327
-\outer\def\appendixsec{\appendixsec1746,57384
-\def\appendixsectionzzz #1{\appendixsectionzzz1747,57437
-\gdef\thissection{#1}\secheading {#1}{\appendixletter}letter1749,57549
-{\chapternofonts%nofonts%1750,57617
-{#1}{\appendixletter}letter1752,57673
-\appendixnoderef %noderef1755,57773
-\outer\def\unnumberedsec{\unnumberedsec1759,57813
-\def\unnumberedseczzz #1{\unnumberedseczzz1760,57866
-{\chapternofonts%nofonts%1762,57961
-\outer\def\numberedsubsec{\numberedsubsec1770,58129
-\def\numberedsubseczzz #1{\numberedsubseczzz1771,58184
-{\chapternofonts%nofonts%1774,58363
-\outer\def\appendixsubsec{\appendixsubsec1783,58567
-\def\appendixsubseczzz #1{\appendixsubseczzz1784,58622
-\subsecheading {#1}{\appendixletter}letter1786,58744
-{\chapternofonts%nofonts%1787,58809
-{#1}{\appendixletter}letter1789,58868
-\appendixnoderef %noderef1792,58983
-\outer\def\unnumberedsubsec{\unnumberedsubsec1796,59023
-\def\unnumberedsubseczzz #1{\unnumberedsubseczzz1797,59082
-{\chapternofonts%nofonts%1799,59183
-\outer\def\numberedsubsubsec{\numberedsubsubsec1807,59354
-\def\numberedsubsubseczzz #1{\numberedsubsubseczzz1808,59415
-{\chapternofonts%nofonts%1812,59612
-\outer\def\appendixsubsubsec{\appendixsubsubsec1823,59845
-\def\appendixsubsubseczzz #1{\appendixsubsubseczzz1824,59906
- {\appendixletter}letter1827,60045
-{\chapternofonts%nofonts%1828,60111
- {\appendixletter}letter1830,60176
-\appendixnoderef %noderef1834,60310
-\outer\def\unnumberedsubsubsec{\unnumberedsubsubsec1838,60350
-\def\unnumberedsubsubseczzz #1{\unnumberedsubsubseczzz1839,60415
-{\chapternofonts%nofonts%1841,60522
-\def\infotop{\infotop1851,60851
-\def\infounnumbered{\infounnumbered1852,60889
-\def\infounnumberedsec{\infounnumberedsec1853,60934
-\def\infounnumberedsubsec{\infounnumberedsubsec1854,60985
-\def\infounnumberedsubsubsec{\infounnumberedsubsubsec1855,61042
-\def\infoappendix{\infoappendix1857,61106
-\def\infoappendixsec{\infoappendixsec1858,61147
-\def\infoappendixsubsec{\infoappendixsubsec1859,61194
-\def\infoappendixsubsubsec{\infoappendixsubsubsec1860,61247
-\def\infochapter{\infochapter1862,61307
-\def\infosection{\infosection1863,61346
-\def\infosubsection{\infosubsection1864,61385
-\def\infosubsubsection{\infosubsubsection1865,61430
-\global\let\section = \numberedsec=1870,61667
-\global\let\subsection = \numberedsubsec=1871,61702
-\global\let\subsubsection = \numberedsubsubsec=1872,61743
-\def\majorheading{\majorheading1886,62250
-\def\majorheadingzzz #1{\majorheadingzzz1887,62295
-\def\chapheading{\chapheading1893,62528
-\def\chapheadingzzz #1{\chapheadingzzz1894,62571
-\def\heading{\heading1899,62766
-\def\subheading{\subheading1901,62803
-\def\subsubheading{\subsubheading1903,62846
-\def\dobreak#1#2{\dobreak1910,63123
-\def\setchapterstyle #1 {\setchapterstyle1912,63201
-\def\chapbreak{\chapbreak1919,63456
-\def\chappager{\chappager1920,63506
-\def\chapoddpage{\chapoddpage1921,63544
-\def\setchapternewpage #1 {\setchapternewpage1923,63623
-\def\CHAPPAGoff{\CHAPPAGoff1925,63680
-\def\CHAPPAGon{\CHAPPAGon1929,63774
-\global\def\HEADINGSon{\HEADINGSon1932,63865
-\def\CHAPPAGodd{\CHAPPAGodd1934,63907
-\global\def\HEADINGSon{\HEADINGSon1937,64003
-\def\CHAPFplain{\CHAPFplain1941,64057
-\def\chfplain #1#2{\chfplain1945,64149
-\def\unnchfplain #1{\unnchfplain1956,64372
-\def\unnchfopen #1{\unnchfopen1964,64601
-\def\chfopen #1#2{\chfopen1970,64809
-\def\CHAPFopen{\CHAPFopen1975,64953
-\def\subsecheadingbreak{\subsecheadingbreak1982,65171
-\def\secheadingbreak{\secheadingbreak1985,65300
-\def\secheading #1#2#3{\secheading1993,65582
-\def\plainsecheading #1{\plainsecheading1994,65638
-\def\secheadingi #1{\secheadingi1995,65681
-\def\subsecheading #1#2#3#4{\subsecheading2006,66049
-\def\subsecheadingi #1{\subsecheadingi2007,66116
-\def\subsubsecfonts{\subsubsecfonts2014,66413
-\def\subsubsecheading #1#2#3#4#5{\subsubsecheading2017,66536
-\def\subsubsecheadingi #1{\subsubsecheadingi2018,66614
-\def\startcontents#1{\startcontents2032,67086
- \unnumbchapmacro{#1}\def\thischapter{\thischapter2040,67359
-\outer\def\contents{\contents2049,67718
-\outer\def\summarycontents{\summarycontents2057,67862
- \def\secentry ##1##2##3##4{\secentry2067,68233
- \def\unnumbsecentry ##1##2{\unnumbsecentry2068,68268
- \def\subsecentry ##1##2##3##4##5{\subsecentry2069,68303
- \def\unnumbsubsecentry ##1##2{\unnumbsubsecentry2070,68344
- \def\subsubsecentry ##1##2##3##4##5##6{\subsubsecentry2071,68382
- \def\unnumbsubsubsecentry ##1##2{\unnumbsubsubsecentry2072,68429
-\def\chapentry#1#2#3{\chapentry2085,68863
-\def\shortchapentry#1#2#3{\shortchapentry2088,68980
- {#2\labelspace #1}space2091,69090
-\def\unnumbchapentry#1#2{\unnumbchapentry2094,69144
-\def\shortunnumberedentry#1#2{\shortunnumberedentry2095,69191
-\def\secentry#1#2#3#4{\secentry2102,69355
-\def\unnumbsecentry#1#2{\unnumbsecentry2103,69414
-\def\subsecentry#1#2#3#4#5{\subsecentry2106,69475
-\def\unnumbsubsecentry#1#2{\unnumbsubsecentry2107,69545
-\def\subsubsecentry#1#2#3#4#5#6{\subsubsecentry2110,69619
- \dosubsubsecentry{#2.#3.#4.#5\labelspace#1}space2111,69653
-\def\unnumbsubsubsecentry#1#2{\unnumbsubsubsecentry2112,69704
-\def\dochapentry#1#2{\dochapentry2123,70078
-\def\dosecentry#1#2{\dosecentry2138,70683
-\def\dosubsecentry#1#2{\dosubsecentry2145,70861
-\def\dosubsubsecentry#1#2{\dosubsubsecentry2152,71046
-\def\labelspace{\labelspace2160,71297
-\def\dopageno#1{\dopageno2162,71332
-\def\doshortpageno#1{\doshortpageno2163,71358
-\def\chapentryfonts{\chapentryfonts2165,71390
-\def\secentryfonts{\secentryfonts2166,71425
-\def\point{\point2192,72384
-\def\result{\result2194,72405
-\def\expansion{\expansion2195,72478
-\def\print{\print2196,72549
-\def\equiv{\equiv2198,72616
-\def\error{\error2218,73389
-\def\tex{\tex2224,73618
-\def\@{\@2242,74001
-\gdef\sepspaces{\def {\ }}}\2265,74733
-\def\aboveenvbreak{\aboveenvbreak2268,74815
-\def\afterenvbreak{\afterenvbreak2272,74981
-\def\ctl{\ctl2286,75492
-\def\ctr{\ctr2287,75564
-\def\cbl{\cbl2288,75603
-\def\cbr{\cbr2289,75643
-\def\carttop{\carttop2290,75682
-\def\cartbot{\cartbot2293,75790
-\long\def\cartouche{\cartouche2299,75930
-\def\Ecartouche{\Ecartouche2326,76718
-\def\lisp{\lisp2338,76853
-\def\Elisp{\Elisp2348,77200
-\def\next##1{\next2360,77526
-\def\Eexample{\Eexample2364,77568
-\def\Esmallexample{\Esmallexample2367,77615
-\def\smalllispx{\smalllispx2373,77793
-\def\Esmalllisp{\Esmalllisp2383,78147
-\obeyspaces \obeylines \ninett \indexfonts \rawbackslashfonts2396,78503
-\def\next##1{\next2397,78560
-\def\display{\display2401,78640
-\def\Edisplay{\Edisplay2410,78959
-\def\next##1{\next2422,79270
-\def\format{\format2426,79373
-\def\Eformat{\Eformat2434,79669
-\def\next##1{\next2437,79758
-\def\flushleft{\flushleft2441,79810
-\def\Eflushleft{\Eflushleft2451,80181
-\def\next##1{\next2454,80274
-\def\flushright{\flushright2456,80296
-\def\Eflushright{\Eflushright2466,80668
-\def\next##1{\next2470,80799
-\def\quotation{\quotation2474,80857
-\def\Equotation{\Equotation2480,81049
-\def\setdeffont #1 {\setdeffont2493,81447
-\newskip\defbodyindent \defbodyindent=.4inbodyindent2495,81493
-\newskip\defargsindent \defargsindent=50ptargsindent2496,81536
-\newskip\deftypemargin \deftypemargin=12pttypemargin2497,81579
-\newskip\deflastargmargin \deflastargmargin=18ptlastargmargin2498,81622
-\def\activeparens{\activeparens2503,81820
-\def\opnr{\opnr2529,83032
-\def\lbrb{\lbrb2530,83097
-\def\defname #1#2{\defname2536,83298
-\advance\dimen2 by -\defbodyindentbodyindent2540,83416
-\advance\dimen3 by -\defbodyindentbodyindent2542,83470
-\setbox0=\hbox{\hskip \deflastargmargin{lastargmargin2544,83524
-\dimen1=\hsize \advance \dimen1 by -\defargsindent %size for continuationsargsindent2546,83666
-\parshape 2 0in \dimen0 \defargsindent \dimen1 %argsindent2547,83741
-\rlap{\rightline{{\rm #2}\hskip \deftypemargin}typemargin2554,84110
-\advance\leftskip by -\defbodyindentbodyindent2557,84244
-\exdentamount=\defbodyindentbodyindent2558,84281
-\def\defparsebody #1#2#3{\defparsebody2568,84640
-\def#1{2572,84824
-\def#2{2573,84860
-\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2575,84932
-\exdentamount=\defbodyindentbodyindent2576,85006
-\def\defmethparsebody #1#2#3#4 {\defmethparsebody2581,85110
-\def#1{2585,85271
-\def#2##1 {2586,85307
-\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2588,85390
-\exdentamount=\defbodyindentbodyindent2589,85464
-\def\defopparsebody #1#2#3#4#5 {\defopparsebody2592,85549
-\def#1{2596,85710
-\def#2##1 ##2 {2597,85746
-\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2600,85846
-\exdentamount=\defbodyindentbodyindent2601,85920
-\def\defvarparsebody #1#2#3{\defvarparsebody2608,86191
-\def#1{2612,86378
-\def#2{2613,86414
-\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2615,86473
-\exdentamount=\defbodyindentbodyindent2616,86547
-\def\defvrparsebody #1#2#3#4 {\defvrparsebody2621,86638
-\def#1{2625,86797
-\def#2##1 {2626,86833
-\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2628,86903
-\exdentamount=\defbodyindentbodyindent2629,86977
-\def\defopvarparsebody #1#2#3#4#5 {\defopvarparsebody2632,87049
-\def#1{2636,87213
-\def#2##1 ##2 {2637,87249
-\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2640,87336
-\exdentamount=\defbodyindentbodyindent2641,87410
-\def\defunargs #1{\defunargs2664,88170
-\def\deftypefunargs #1{\deftypefunargs2676,88552
-\def\deffn{\deffn2690,88934
-\def\deffnheader #1#2#3{\deffnheader2692,88991
-\begingroup\defname {name2693,89039
-\def\defun{\defun2699,89184
-\def\defunheader #1#2{\defunheader2701,89237
-\begingroup\defname {name2702,89312
-\defunargs {unargs2703,89348
-\def\deftypefun{\deftypefun2709,89496
-\def\deftypefunheader #1#2{\deftypefunheader2712,89618
-\def\deftypefunheaderx #1#2 #3\relax{\deftypefunheaderx2714,89727
-\begingroup\defname {name2716,89819
-\deftypefunargs {typefunargs2717,89865
-\def\deftypefn{\deftypefn2723,90036
-\def\deftypefnheader #1#2#3{\deftypefnheader2726,90185
-\def\deftypefnheaderx #1#2#3 #4\relax{\deftypefnheaderx2728,90321
-\begingroup\defname {name2730,90414
-\deftypefunargs {typefunargs2731,90454
-\def\defmac{\defmac2737,90575
-\def\defmacheader #1#2{\defmacheader2739,90632
-\begingroup\defname {name2740,90708
-\defunargs {unargs2741,90741
-\def\defspec{\defspec2747,90865
-\def\defspecheader #1#2{\defspecheader2749,90926
-\begingroup\defname {name2750,91003
-\defunargs {unargs2751,91043
-\def\deffnx #1 {\deffnx2758,91238
-\def\defunx #1 {\defunx2759,91295
-\def\defmacx #1 {\defmacx2760,91352
-\def\defspecx #1 {\defspecx2761,91411
-\def\deftypefnx #1 {\deftypefnx2762,91472
-\def\deftypeunx #1 {\deftypeunx2763,91537
-\def\defop #1 {\defop2769,91683
-\defopparsebody\Edefop\defopx\defopheader\defoptype}opparsebody\Edefop\defopx\defopheader\defoptype2770,91718
-\def\defopheader #1#2#3{\defopheader2772,91772
-\begingroup\defname {name2774,91861
-\defunargs {unargs2775,91907
-\def\defmethod{\defmethod2780,91968
-\def\defmethodheader #1#2#3{\defmethodheader2782,92041
-\begingroup\defname {name2784,92129
-\defunargs {unargs2785,92169
-\def\defcv #1 {\defcv2790,92243
-\defopvarparsebody\Edefcv\defcvx\defcvarheader\defcvtype}opvarparsebody\Edefcv\defcvx\defcvarheader\defcvtype2791,92278
-\def\defcvarheader #1#2#3{\defcvarheader2793,92337
-\begingroup\defname {name2795,92423
-\defvarargs {varargs2796,92469
-\def\defivar{\defivar2801,92542
-\def\defivarheader #1#2#3{\defivarheader2803,92605
-\begingroup\defname {name2805,92691
-\defvarargs {varargs2806,92742
-\def\defopx #1 {\defopx2812,92891
-\def\defmethodx #1 {\defmethodx2813,92948
-\def\defcvx #1 {\defcvx2814,93013
-\def\defivarx #1 {\defivarx2815,93070
-\def\defvarargs #1{\defvarargs2822,93341
-\def\defvr{\defvr2828,93485
-\def\defvrheader #1#2#3{\defvrheader2830,93540
-\begingroup\defname {name2831,93588
-\def\defvar{\defvar2835,93673
-\def\defvarheader #1#2{\defvarheader2837,93733
-\begingroup\defname {name2838,93804
-\defvarargs {varargs2839,93840
-\def\defopt{\defopt2844,93906
-\def\defoptheader #1#2{\defoptheader2846,93966
-\begingroup\defname {name2847,94037
-\defvarargs {varargs2848,94076
-\def\deftypevar{\deftypevar2853,94133
-\def\deftypevarheader #1#2{\deftypevarheader2856,94249
-\begingroup\defname {name2858,94332
-\def\deftypevr{\deftypevr2865,94506
-\def\deftypevrheader #1#2#3{\deftypevrheader2867,94577
-\begingroup\defname {name2868,94629
-\def\defvrx #1 {\defvrx2876,94866
-\def\defvarx #1 {\defvarx2877,94923
-\def\defoptx #1 {\defoptx2878,94982
-\def\deftypevarx #1 {\deftypevarx2879,95041
-\def\deftypevrx #1 {\deftypevrx2880,95108
-\def\deftpargs #1{\deftpargs2885,95257
-\def\deftp{\deftp2889,95337
-\def\deftpheader #1#2#3{\deftpheader2891,95392
-\begingroup\defname {name2892,95440
-\def\deftpx #1 {\deftpx2897,95599
-\def\setref#1{\setref2908,95920
-\def\unnumbsetref#1{\unnumbsetref2913,96034
-\def\appendixsetref#1{\appendixsetref2918,96141
-\def\pxref#1{\pxref2929,96552
-\def\xref#1{\xref2930,96588
-\def\ref#1{\ref2931,96623
-\def\xrefX[#1,#2,#3,#4,#5,#6]{\xrefX[2932,96653
-\def\printedmanual{\printedmanual2933,96696
-\def\printednodename{\printednodename2934,96734
-\def\printednodename{\printednodename2939,96859
-section ``\printednodename'' in \cite{\printedmanual}\printedmanual2954,97492
-\refx{x2957,97570
-\def\dosetq #1#2{\dosetq2965,97790
-\def\internalsetq #1#2{\internalsetq2973,98048
-\def\Ypagenumber{\Ypagenumber2977,98149
-\def\Ytitle{\Ytitle2979,98175
-\def\Ynothing{\Ynothing2981,98202
-\def\Ysectionnumberandtype{\Ysectionnumberandtype2983,98219
-\def\Yappendixletterandtype{\Yappendixletterandtype2992,98535
-\ifnum\secno=0 Appendix\xreftie'char\the\appendixno{no2993,98565
-\else \ifnum \subsecno=0 Section\xreftie'char\the\appendixno.\the\secno %no.\the\secno2994,98620
-Section\xreftie'char\the\appendixno.\the\secno.\the\subsecno %no.\the\secno.\the\subsecno2996,98724
-Section\xreftie'char\the\appendixno.\the\secno.\the\subsecno.\the\subsubsecno %no.\the\secno.\the\subsecno.\the\subsubsecno2998,98795
- \def\linenumber{\linenumber3009,99134
-\def\refx#1#2{\refx3015,99318
-\def\xrdef #1#2{\xrdef3037,99944
-\def\readauxfile{\readauxfile3040,100029
-\def\supereject{\supereject3110,101810
-\footstrut\parindent=\defaultparindent\hang\textindent{aultparindent\hang\textindent3131,102495
-\def\openindices{\openindices3139,102681
-\newdimen\defaultparindent \defaultparindent = 15ptaultparindent3151,102906
-\parindent = \defaultparindentaultparindent3152,102958
-\def\smallbook{\smallbook3175,103682
-\global\def\Esmallexample{\Esmallexample3192,104109
-\def\afourpaper{\afourpaper3196,104200
-\def\finalout{\finalout3224,105008
-\def\normaldoublequote{\normaldoublequote3235,105269
-\def\normaltilde{\normaltilde3236,105295
-\def\normalcaret{\normalcaret3237,105315
-\def\normalunderscore{\normalunderscore3238,105335
-\def\normalverticalbar{\normalverticalbar3239,105360
-\def\normalless{\normalless3240,105386
-\def\normalgreater{\normalgreater3241,105405
-\def\normalplus{\normalplus3242,105427
-\def\ifusingtt#1#2{\ifusingtt3253,105919
-\def\activedoublequote{\activedoublequote3261,106247
-\def~{~3264,106333
-\def^{^3267,106394
-\def_{_3270,106433
-\def\_{\_3272,106507
-\def\lvvmode{\lvvmode3279,106844
-\def|{|3282,106894
-\def<{<3285,106957
-\def>{>3288,107014
-\def+{+3290,107052
-\def\turnoffactive{\turnoffactive3296,107213
-\global\def={=3307,107499
-\def\normalbackslash{\normalbackslash3321,107881
+\def\texinfoversion{\texinfoversion26,1035
+\def\tie{\tie49,1526
+\def\gloggingall{\gloggingall72,2276
+\def\loggingall{\loggingall73,2345
+\def\onepageout#1{\onepageout99,3282
+\def\croppageout#1{\croppageout115,4032
+\def\cropmarks{\cropmarks142,5092
+\def\pagebody#1{\pagebody144,5139
+\def\ewtop{\ewtop157,5594
+\def\nstop{\nstop158,5658
+\def\ewbot{\ewbot160,5741
+\def\nsbot{\nsbot161,5805
+\def\parsearg #1{\parsearg170,6104
+\def\parseargx{\parseargx172,6182
+\def\parseargline{\parseargline182,6422
+\def\flushcr{\flushcr186,6543
+\newif\ifENV \ENVfalse \def\inENV{\inENV190,6742
+\def\ENVcheck{\ENVcheck191,6806
+\outer\def\begin{\begin198,7053
+\def\beginxxx #1{\beginxxx200,7091
+\def\end{\end208,7346
+\def\endxxx #1{\endxxx210,7374
+\def\errorE#1{\errorE216,7563
+\def\singlespace{\singlespace222,7757
+\def\@{\@232,7980
+\def\`{\`236,8080
+\def\'{\'237,8092
+\def\mylbrace {\mylbrace241,8140
+\def\myrbrace {\myrbrace242,8173
+\def\:{\:247,8287
+\def\*{\*250,8341
+\def\.{\.253,8417
+\def\w#1{\w258,8648
+\def\group{\group268,9131
+ \def\Egroup{\Egroup273,9295
+\def\need{\need289,9737
+\def\needx#1{\needx300,10014
+\def\dots{\dots339,11400
+\def\page{\page343,11464
+\def\exdent{\exdent353,11791
+\def\exdentyyy #1{\exdentyyy354,11824
+\def\nofillexdent{\nofillexdent357,11968
+\def\nofillexdentyyy #1{\nofillexdentyyy358,12013
+\def\include{\include365,12197
+\def\includezzz #1{\includezzz366,12232
+\def\thisfile{\thisfile369,12283
+\def\center{\center373,12346
+\def\centerzzz #1{\centerzzz374,12379
+\def\sp{\sp380,12521
+\def\spxxx #1{\spxxx381,12546
+\def\comment{\comment387,12720
+\def\commentxxx #1{\commentxxx390,12817
+\def\ignoresections{\ignoresections396,12986
+\let\chapter=\relax=\relax397,13008
+\let\section=\relax=\relax406,13253
+\let\subsection=\relax=\relax409,13314
+\let\subsubsection=\relax=\relax410,13337
+\let\appendix=\relax=\relax411,13363
+\let\appendixsec=\relaxsec=\relax412,13384
+\let\appendixsection=\relaxsection=\relax413,13408
+\let\appendixsubsec=\relaxsubsec=\relax414,13436
+\let\appendixsubsection=\relaxsubsection=\relax415,13463
+\let\appendixsubsubsec=\relaxsubsubsec=\relax416,13494
+\let\appendixsubsubsection=\relaxsubsubsection=\relax417,13524
+\def\ignore{\ignore423,13626
+\long\def\ignorexxx #1\end ignore{\ignorexxx427,13766
+\def\direntry{\direntry429,13825
+\long\def\direntryxxx #1\end direntry{\direntryxxx430,13864
+\def\ifset{\ifset434,13974
+\def\ifsetxxx #1{\ifsetxxx436,14032
+\def\Eifset{\Eifset440,14159
+\def\ifsetfail{\ifsetfail441,14173
+\long\def\ifsetfailxxx #1\end ifset{\ifsetfailxxx442,14229
+\def\ifclear{\ifclear444,14290
+\def\ifclearxxx #1{\ifclearxxx446,14352
+\def\Eifclear{\Eifclear450,14483
+\def\ifclearfail{\ifclearfail451,14499
+\long\def\ifclearfailxxx #1\end ifclear{\ifclearfailxxx452,14559
+\def\set{\set456,14710
+\def\setxxx #1{\setxxx457,14737
+\def\clear{\clear460,14799
+\def\clearxxx #1{\clearxxx461,14830
+\def\iftex{\iftex466,14947
+\def\Eiftex{\Eiftex467,14960
+\def\ifinfo{\ifinfo468,14974
+\long\def\ifinfoxxx #1\end ifinfo{\ifinfoxxx469,15024
+\long\def\menu #1\end menu{\menu471,15083
+\def\asis#1{\asis472,15112
+\def\math#1{\math485,15655
+\def\node{\node487,15699
+\def\nodezzz#1{\nodezzz488,15737
+\def\nodexxx[#1,#2]{\nodexxx[489,15768
+\def\donoderef{\donoderef492,15830
+\def\unnumbnoderef{\unnumbnoderef496,15951
+\def\appendixnoderef{\appendixnoderef500,16082
+\expandafter\expandafter\expandafter\appendixsetref{setref501,16128
+\let\refill=\relaxill=\relax504,16217
+\def\setfilename{\setfilename509,16431
+\outer\def\bye{\bye518,16677
+\def\inforef #1{\inforef520,16733
+\def\inforefzzz #1,#2,#3,#4**{\inforefzzz521,16771
+\def\losespace #1{\losespace523,16868
+\def\sf{\sf532,17072
+\font\defbf=cmbx10 scaled \magstep1 %was 1314bf=cmbx10558,17867
+\font\deftt=cmtt10 scaled \magstep1tt=cmtt10559,17913
+\def\df{\df560,17949
+\def\resetmathfonts{\resetmathfonts635,20543
+\def\textfonts{\textfonts648,21132
+\def\chapfonts{\chapfonts653,21347
+\def\secfonts{\secfonts658,21563
+\def\subsecfonts{\subsecfonts663,21768
+\def\indexfonts{\indexfonts668,21985
+\def\smartitalicx{\smartitalicx691,22717
+\def\smartitalic#1{\smartitalic692,22793
+\let\cite=\smartitalic=\smartitalic698,22938
+\def\b#1{\b700,22962
+\def\t#1{\t703,22997
+\def\samp #1{\samp706,23149
+\def\key #1{\key707,23182
+\def\ctrl #1{\ctrl708,23243
+\def\tclose#1{\tclose716,23445
+\def\ {\720,23611
+\def\xkey{\xkey728,23880
+\def\kbdfoo#1#2#3\par{\kbdfoo729,23896
+\def\dmn#1{\dmn738,24197
+\def\kbd#1{\kbd740,24224
+\def\l#1{\l742,24281
+\def\r#1{\r744,24310
+\def\sc#1{\sc746,24378
+\def\ii#1{\ii747,24421
+\def\titlefont#1{\titlefont755,24654
+\def\titlepage{\titlepage761,24757
+ \def\subtitlefont{\subtitlefont766,24984
+ \def\authorfont{\authorfont768,25068
+ \def\title{\title774,25278
+ \def\titlezzz##1{\titlezzz775,25313
+ \def\subtitle{\subtitle783,25628
+ \def\subtitlezzz##1{\subtitlezzz784,25669
+ \def\author{\author787,25787
+ \def\authorzzz##1{\authorzzz788,25824
+ \def\page{\page794,26115
+\def\Etitlepage{\Etitlepage804,26284
+\def\finishtitlepage{\finishtitlepage817,26672
+\def\evenheading{\evenheading846,27680
+\def\oddheading{\oddheading847,27723
+\def\everyheading{\everyheading848,27764
+\def\evenfooting{\evenfooting850,27810
+\def\oddfooting{\oddfooting851,27853
+\def\everyfooting{\everyfooting852,27894
+\def\headings #1 {\headings893,29586
+\def\HEADINGSoff{\HEADINGSoff895,29635
+\def\HEADINGSdouble{\HEADINGSdouble904,30062
+\def\HEADINGSsingle{\HEADINGSsingle914,30382
+\def\HEADINGSon{\HEADINGSon922,30603
+\def\HEADINGSafter{\HEADINGSafter924,30637
+\def\HEADINGSdoublex{\HEADINGSdoublex926,30732
+\def\HEADINGSsingleafter{\HEADINGSsingleafter933,30920
+\def\HEADINGSsinglex{\HEADINGSsinglex934,30981
+\def\today{\today943,31256
+\def\thistitle{\thistitle958,31801
+\def\settitle{\settitle959,31826
+\def\settitlezzz #1{\settitlezzz960,31863
+\def\internalBitem{\internalBitem992,32793
+\def\internalBitemx{\internalBitemx993,32843
+\def\internalBxitem "#1"{\internalBxitem995,32888
+\def\internalBxitemx "#1"{\internalBxitemx996,32968
+\def\internalBkitem{\internalBkitem998,33043
+\def\internalBkitemx{\internalBkitemx999,33095
+\def\kitemzzz #1{\kitemzzz1001,33142
+\def\xitemzzz #1{\xitemzzz1004,33244
+\def\itemzzz #1{\itemzzz1007,33347
+\def\item{\item1037,34418
+\def\itemx{\itemx1038,34469
+\def\kitem{\kitem1039,34522
+\def\kitemx{\kitemx1040,34575
+\def\xitem{\xitem1041,34630
+\def\xitemx{\xitemx1042,34683
+\def\description{\description1045,34793
+\def\table{\table1047,34843
+\def\ftable{\ftable1052,34987
+\def\Eftable{\Eftable1056,35133
+\def\vtable{\vtable1059,35202
+\def\Evtable{\Evtable1063,35348
+\def\dontindex #1{\dontindex1066,35417
+\def\fnitemindex #1{\fnitemindex1067,35437
+\def\vritemindex #1{\vritemindex1068,35482
+\def\tablez #1#2#3#4#5#6{\tablez1074,35631
+\def\Edescription{\Edescription1077,35689
+\def\itemfont{\itemfont1082,35890
+\def\Etable{\Etable1090,36116
+\def\itemize{\itemize1103,36440
+\def\itemizezzz #1{\itemizezzz1105,36476
+\def\itemizey #1#2{\itemizey1110,36571
+\def#2{1119,36817
+\def\itemcontents{\itemcontents1120,36858
+\def\bullet{\bullet1123,36906
+\def\minus{\minus1124,36933
+\def\frenchspacing{\frenchspacing1128,37041
+\def\splitoff#1#2\endmark{\splitoff1134,37266
+\def\enumerate{\enumerate1140,37496
+\def\enumeratezzz #1{\enumeratezzz1141,37535
+\def\enumeratey #1 #2\endenumeratey{\enumeratey1142,37588
+ \def\thearg{\thearg1146,37735
+ \ifx\thearg\empty \def\thearg{\thearg1147,37754
+\def\numericenumerate{\numericenumerate1184,39088
+\def\lowercaseenumerate{\lowercaseenumerate1190,39218
+\def\uppercaseenumerate{\uppercaseenumerate1203,39565
+\def\startenumeration#1{\startenumeration1219,40055
+\def\alphaenumerate{\alphaenumerate1227,40237
+\def\capsenumerate{\capsenumerate1228,40272
+\def\Ealphaenumerate{\Ealphaenumerate1229,40306
+\def\Ecapsenumerate{\Ecapsenumerate1230,40340
+\def\itemizeitem{\itemizeitem1234,40420
+\def\newindex #1{\newindex1259,41277
+\def\defindex{\defindex1268,41566
+\def\newcodeindex #1{\newcodeindex1272,41674
+\def\defcodeindex{\defcodeindex1279,41934
+\def\synindex #1 #2 {\synindex1283,42114
+\def\syncodeindex #1 #2 {\syncodeindex1292,42454
+\def\doindex#1{\doindex1309,43133
+\def\singleindexer #1{\singleindexer1310,43192
+\def\docodeindex#1{\docodeindex1313,43304
+\def\singlecodeindexer #1{\singlecodeindexer1314,43371
+\def\indexdummies{\indexdummies1316,43429
+\def\_{\_1317,43449
+\def\w{\w1318,43477
+\def\bf{\bf1319,43504
+\def\rm{\rm1320,43533
+\def\sl{\sl1321,43562
+\def\sf{\sf1322,43591
+\def\tt{\tt1323,43619
+\def\gtr{\gtr1324,43647
+\def\less{\less1325,43677
+\def\hat{\hat1326,43709
+\def\char{\char1327,43739
+\def\TeX{\TeX1328,43771
+\def\dots{\dots1329,43801
+\def\copyright{\copyright1330,43834
+\def\tclose##1{\tclose1331,43877
+\def\code##1{\code1332,43922
+\def\samp##1{\samp1333,43963
+\def\t##1{\t1334,44004
+\def\r##1{\r1335,44039
+\def\i##1{\i1336,44074
+\def\b##1{\b1337,44109
+\def\cite##1{\cite1338,44144
+\def\key##1{\key1339,44185
+\def\file##1{\file1340,44224
+\def\var##1{\var1341,44265
+\def\kbd##1{\kbd1342,44304
+\def\indexdummyfont#1{\indexdummyfont1347,44460
+\def\indexdummytex{\indexdummytex1348,44486
+\def\indexdummydots{\indexdummydots1349,44510
+\def\indexnofonts{\indexnofonts1351,44536
+\let\w=\indexdummyfontdummyfont1352,44556
+\let\t=\indexdummyfontdummyfont1353,44579
+\let\r=\indexdummyfontdummyfont1354,44602
+\let\i=\indexdummyfontdummyfont1355,44625
+\let\b=\indexdummyfontdummyfont1356,44648
+\let\emph=\indexdummyfontdummyfont1357,44671
+\let\strong=\indexdummyfontdummyfont1358,44697
+\let\cite=\indexdummyfont=\indexdummyfont1359,44725
+\let\sc=\indexdummyfontdummyfont1360,44751
+\let\tclose=\indexdummyfontdummyfont1364,44923
+\let\code=\indexdummyfontdummyfont1365,44951
+\let\file=\indexdummyfontdummyfont1366,44977
+\let\samp=\indexdummyfontdummyfont1367,45003
+\let\kbd=\indexdummyfontdummyfont1368,45029
+\let\key=\indexdummyfontdummyfont1369,45054
+\let\var=\indexdummyfontdummyfont1370,45079
+\let\TeX=\indexdummytexdummytex1371,45104
+\let\dots=\indexdummydotsdummydots1372,45128
+\let\indexbackslash=0 %overridden during \printindex.backslash=01382,45380
+\def\doind #1#2{\doind1384,45436
+{\indexdummies % Must do this here, since \bf, etc expand at this stagedummies1386,45479
+\def\rawbackslashxx{\rawbackslashxx1389,45619
+{\indexnofontsnofonts1394,45881
+\def\dosubind #1#2#3{\dosubind1405,46192
+{\indexdummies % Must do this here, since \bf, etc expand at this stagedummies1407,46240
+\def\rawbackslashxx{\rawbackslashxx1410,46344
+{\indexnofontsnofonts1414,46498
+\def\findex {\findex1443,47429
+\def\kindex {\kindex1444,47452
+\def\cindex {\cindex1445,47475
+\def\vindex {\vindex1446,47498
+\def\tindex {\tindex1447,47521
+\def\pindex {\pindex1448,47544
+\def\cindexsub {\cindexsub1450,47568
+\def\printindex{\printindex1462,47895
+\def\doprintindex#1{\doprintindex1464,47936
+ \def\indexbackslash{\indexbackslash1481,48421
+ \indexfonts\rm \tolerance=9500 \advance\baselineskip -1ptfonts\rm1482,48460
+\def\initial #1{\initial1517,49532
+\def\entry #1#2{\entry1523,49739
+ \null\nobreak\indexdotfill % Have leaders before the page number.dotfill1540,50386
+\def\indexdotfill{\indexdotfill1549,50714
+\def\primary #1{\primary1552,50820
+\def\secondary #1#2{\secondary1556,50902
+\noindent\hskip\secondaryindent\hbox{#1}\indexdotfill #2\pardotfill1559,50984
+\newbox\partialpageialpage1566,51157
+\def\begindoublecolumns{\begindoublecolumns1572,51315
+ \output={\global\setbox\partialpage=ialpage=1573,51351
+\def\enddoublecolumns{\enddoublecolumns1577,51539
+\def\doublecolumnout{\doublecolumnout1580,51624
+ \dimen@=\pageheight \advance\dimen@ by-\ht\partialpageialpage1581,51693
+\def\pagesofar{\pagesofar1584,51871
+\def\balancecolumns{\balancecolumns1588,52108
+ \availdimen@=\pageheight \advance\availdimen@ by-\ht\partialpageialpage1594,52279
+ \dimen@=\pageheight \advance\dimen@ by-\ht\partialpageialpage1600,52540
+\newcount \appendixno \appendixno = `\@no1627,53445
+\def\appendixletter{\appendixletter1628,53486
+\def\opencontents{\opencontents1632,53589
+\def\thischapter{\thischapter1637,53770
+\def\seccheck#1{\seccheck1638,53808
+\def\chapternofonts{\chapternofonts1643,53912
+\def\result{\result1646,53987
+\def\equiv{\equiv1647,54022
+\def\expansion{\expansion1648,54055
+\def\print{\print1649,54096
+\def\TeX{\TeX1650,54129
+\def\dots{\dots1651,54158
+\def\copyright{\copyright1652,54189
+\def\tt{\tt1653,54230
+\def\bf{\bf1654,54257
+\def\w{\w1655,54285
+\def\less{\less1656,54310
+\def\gtr{\gtr1657,54341
+\def\hat{\hat1658,54370
+\def\char{\char1659,54399
+\def\tclose##1{\tclose1660,54430
+\def\code##1{\code1661,54474
+\def\samp##1{\samp1662,54514
+\def\r##1{\r1663,54554
+\def\b##1{\b1664,54588
+\def\key##1{\key1665,54622
+\def\file##1{\file1666,54660
+\def\kbd##1{\kbd1667,54700
+\def\i##1{\i1669,54808
+\def\cite##1{\cite1670,54842
+\def\var##1{\var1671,54882
+\def\emph##1{\emph1672,54920
+\def\dfn##1{\dfn1673,54960
+\def\thischaptername{\thischaptername1676,55001
+\outer\def\chapter{\chapter1677,55040
+\def\chapterzzz #1{\chapterzzz1678,55081
+{\chapternofonts%nofonts%1687,55477
+\global\let\section = \numberedsec=1692,55630
+\global\let\subsection = \numberedsubsec=1693,55665
+\global\let\subsubsection = \numberedsubsubsec=1694,55706
+\outer\def\appendix{\appendix1697,55757
+\def\appendixzzz #1{\appendixzzz1698,55800
+\global\advance \appendixno by 1 \message{no1700,55877
+\chapmacro {#1}{Appendix \appendixletter}letter1701,55946
+\xdef\thischapter{Appendix \appendixletter: \noexpand\thischaptername}letter:1704,56039
+{\chapternofonts%nofonts%1705,56111
+ {#1}{Appendix \appendixletter}letter1707,56167
+\appendixnoderef %noderef1710,56267
+\global\let\section = \appendixsec=1711,56286
+\global\let\subsection = \appendixsubsec=1712,56321
+\global\let\subsubsection = \appendixsubsubsec=1713,56362
+\outer\def\top{\top1716,56413
+\outer\def\unnumbered{\unnumbered1717,56453
+\def\unnumberedzzz #1{\unnumberedzzz1718,56500
+{\chapternofonts%nofonts%1722,56663
+\global\let\section = \unnumberedsec=1727,56813
+\global\let\subsection = \unnumberedsubsec=1728,56850
+\global\let\subsubsection = \unnumberedsubsubsec=1729,56893
+\outer\def\numberedsec{\numberedsec1732,56946
+\def\seczzz #1{\seczzz1733,56987
+{\chapternofonts%nofonts%1736,57143
+\outer\def\appendixsection{\appendixsection1745,57329
+\outer\def\appendixsec{\appendixsec1746,57386
+\def\appendixsectionzzz #1{\appendixsectionzzz1747,57439
+\gdef\thissection{#1}\secheading {#1}{\appendixletter}letter1749,57551
+{\chapternofonts%nofonts%1750,57619
+{#1}{\appendixletter}letter1752,57675
+\appendixnoderef %noderef1755,57775
+\outer\def\unnumberedsec{\unnumberedsec1759,57815
+\def\unnumberedseczzz #1{\unnumberedseczzz1760,57868
+{\chapternofonts%nofonts%1762,57963
+\outer\def\numberedsubsec{\numberedsubsec1770,58131
+\def\numberedsubseczzz #1{\numberedsubseczzz1771,58186
+{\chapternofonts%nofonts%1774,58365
+\outer\def\appendixsubsec{\appendixsubsec1783,58569
+\def\appendixsubseczzz #1{\appendixsubseczzz1784,58624
+\subsecheading {#1}{\appendixletter}letter1786,58746
+{\chapternofonts%nofonts%1787,58811
+{#1}{\appendixletter}letter1789,58870
+\appendixnoderef %noderef1792,58985
+\outer\def\unnumberedsubsec{\unnumberedsubsec1796,59025
+\def\unnumberedsubseczzz #1{\unnumberedsubseczzz1797,59084
+{\chapternofonts%nofonts%1799,59185
+\outer\def\numberedsubsubsec{\numberedsubsubsec1807,59356
+\def\numberedsubsubseczzz #1{\numberedsubsubseczzz1808,59417
+{\chapternofonts%nofonts%1812,59614
+\outer\def\appendixsubsubsec{\appendixsubsubsec1823,59847
+\def\appendixsubsubseczzz #1{\appendixsubsubseczzz1824,59908
+ {\appendixletter}letter1827,60047
+{\chapternofonts%nofonts%1828,60113
+ {\appendixletter}letter1830,60178
+\appendixnoderef %noderef1834,60312
+\outer\def\unnumberedsubsubsec{\unnumberedsubsubsec1838,60352
+\def\unnumberedsubsubseczzz #1{\unnumberedsubsubseczzz1839,60417
+{\chapternofonts%nofonts%1841,60524
+\def\infotop{\infotop1851,60853
+\def\infounnumbered{\infounnumbered1852,60891
+\def\infounnumberedsec{\infounnumberedsec1853,60936
+\def\infounnumberedsubsec{\infounnumberedsubsec1854,60987
+\def\infounnumberedsubsubsec{\infounnumberedsubsubsec1855,61044
+\def\infoappendix{\infoappendix1857,61108
+\def\infoappendixsec{\infoappendixsec1858,61149
+\def\infoappendixsubsec{\infoappendixsubsec1859,61196
+\def\infoappendixsubsubsec{\infoappendixsubsubsec1860,61249
+\def\infochapter{\infochapter1862,61309
+\def\infosection{\infosection1863,61348
+\def\infosubsection{\infosubsection1864,61387
+\def\infosubsubsection{\infosubsubsection1865,61432
+\global\let\section = \numberedsec=1870,61669
+\global\let\subsection = \numberedsubsec=1871,61704
+\global\let\subsubsection = \numberedsubsubsec=1872,61745
+\def\majorheading{\majorheading1886,62252
+\def\majorheadingzzz #1{\majorheadingzzz1887,62297
+\def\chapheading{\chapheading1893,62530
+\def\chapheadingzzz #1{\chapheadingzzz1894,62573
+\def\heading{\heading1899,62768
+\def\subheading{\subheading1901,62805
+\def\subsubheading{\subsubheading1903,62848
+\def\dobreak#1#2{\dobreak1910,63125
+\def\setchapterstyle #1 {\setchapterstyle1912,63203
+\def\chapbreak{\chapbreak1919,63458
+\def\chappager{\chappager1920,63508
+\def\chapoddpage{\chapoddpage1921,63546
+\def\setchapternewpage #1 {\setchapternewpage1923,63625
+\def\CHAPPAGoff{\CHAPPAGoff1925,63682
+\def\CHAPPAGon{\CHAPPAGon1929,63776
+\global\def\HEADINGSon{\HEADINGSon1932,63867
+\def\CHAPPAGodd{\CHAPPAGodd1934,63909
+\global\def\HEADINGSon{\HEADINGSon1937,64005
+\def\CHAPFplain{\CHAPFplain1941,64059
+\def\chfplain #1#2{\chfplain1945,64151
+\def\unnchfplain #1{\unnchfplain1956,64374
+\def\unnchfopen #1{\unnchfopen1964,64603
+\def\chfopen #1#2{\chfopen1970,64811
+\def\CHAPFopen{\CHAPFopen1975,64955
+\def\subsecheadingbreak{\subsecheadingbreak1982,65173
+\def\secheadingbreak{\secheadingbreak1985,65302
+\def\secheading #1#2#3{\secheading1993,65584
+\def\plainsecheading #1{\plainsecheading1994,65640
+\def\secheadingi #1{\secheadingi1995,65683
+\def\subsecheading #1#2#3#4{\subsecheading2006,66051
+\def\subsecheadingi #1{\subsecheadingi2007,66118
+\def\subsubsecfonts{\subsubsecfonts2014,66415
+\def\subsubsecheading #1#2#3#4#5{\subsubsecheading2017,66538
+\def\subsubsecheadingi #1{\subsubsecheadingi2018,66616
+\def\startcontents#1{\startcontents2032,67088
+ \unnumbchapmacro{#1}\def\thischapter{\thischapter2040,67361
+\outer\def\contents{\contents2049,67720
+\outer\def\summarycontents{\summarycontents2057,67864
+ \def\secentry ##1##2##3##4{\secentry2067,68235
+ \def\unnumbsecentry ##1##2{\unnumbsecentry2068,68270
+ \def\subsecentry ##1##2##3##4##5{\subsecentry2069,68305
+ \def\unnumbsubsecentry ##1##2{\unnumbsubsecentry2070,68346
+ \def\subsubsecentry ##1##2##3##4##5##6{\subsubsecentry2071,68384
+ \def\unnumbsubsubsecentry ##1##2{\unnumbsubsubsecentry2072,68431
+\def\chapentry#1#2#3{\chapentry2085,68865
+\def\shortchapentry#1#2#3{\shortchapentry2088,68982
+ {#2\labelspace #1}space2091,69092
+\def\unnumbchapentry#1#2{\unnumbchapentry2094,69146
+\def\shortunnumberedentry#1#2{\shortunnumberedentry2095,69193
+\def\secentry#1#2#3#4{\secentry2102,69357
+\def\unnumbsecentry#1#2{\unnumbsecentry2103,69416
+\def\subsecentry#1#2#3#4#5{\subsecentry2106,69477
+\def\unnumbsubsecentry#1#2{\unnumbsubsecentry2107,69547
+\def\subsubsecentry#1#2#3#4#5#6{\subsubsecentry2110,69621
+ \dosubsubsecentry{#2.#3.#4.#5\labelspace#1}space2111,69655
+\def\unnumbsubsubsecentry#1#2{\unnumbsubsubsecentry2112,69706
+\def\dochapentry#1#2{\dochapentry2123,70080
+\def\dosecentry#1#2{\dosecentry2138,70685
+\def\dosubsecentry#1#2{\dosubsecentry2145,70863
+\def\dosubsubsecentry#1#2{\dosubsubsecentry2152,71048
+\def\labelspace{\labelspace2160,71299
+\def\dopageno#1{\dopageno2162,71334
+\def\doshortpageno#1{\doshortpageno2163,71360
+\def\chapentryfonts{\chapentryfonts2165,71392
+\def\secentryfonts{\secentryfonts2166,71427
+\def\point{\point2192,72386
+\def\result{\result2194,72407
+\def\expansion{\expansion2195,72480
+\def\print{\print2196,72551
+\def\equiv{\equiv2198,72618
+\def\error{\error2218,73391
+\def\tex{\tex2224,73620
+\def\@{\@2242,74003
+\gdef\sepspaces{\def {\ }}}\2265,74735
+\def\aboveenvbreak{\aboveenvbreak2268,74817
+\def\afterenvbreak{\afterenvbreak2272,74983
+\def\ctl{\ctl2286,75494
+\def\ctr{\ctr2287,75566
+\def\cbl{\cbl2288,75605
+\def\cbr{\cbr2289,75645
+\def\carttop{\carttop2290,75684
+\def\cartbot{\cartbot2293,75792
+\long\def\cartouche{\cartouche2299,75932
+\def\Ecartouche{\Ecartouche2326,76720
+\def\lisp{\lisp2338,76855
+\def\Elisp{\Elisp2348,77202
+\def\next##1{\next2360,77528
+\def\Eexample{\Eexample2364,77570
+\def\Esmallexample{\Esmallexample2367,77617
+\def\smalllispx{\smalllispx2373,77795
+\def\Esmalllisp{\Esmalllisp2383,78149
+\obeyspaces \obeylines \ninett \indexfonts \rawbackslashfonts2396,78505
+\def\next##1{\next2397,78562
+\def\display{\display2401,78642
+\def\Edisplay{\Edisplay2410,78961
+\def\next##1{\next2422,79272
+\def\format{\format2426,79375
+\def\Eformat{\Eformat2434,79671
+\def\next##1{\next2437,79760
+\def\flushleft{\flushleft2441,79812
+\def\Eflushleft{\Eflushleft2451,80183
+\def\next##1{\next2454,80276
+\def\flushright{\flushright2456,80298
+\def\Eflushright{\Eflushright2466,80670
+\def\next##1{\next2470,80801
+\def\quotation{\quotation2474,80859
+\def\Equotation{\Equotation2480,81051
+\def\setdeffont #1 {\setdeffont2493,81449
+\newskip\defbodyindent \defbodyindent=.4inbodyindent2495,81495
+\newskip\defargsindent \defargsindent=50ptargsindent2496,81538
+\newskip\deftypemargin \deftypemargin=12pttypemargin2497,81581
+\newskip\deflastargmargin \deflastargmargin=18ptlastargmargin2498,81624
+\def\activeparens{\activeparens2503,81822
+\def\opnr{\opnr2529,83034
+\def\lbrb{\lbrb2530,83099
+\def\defname #1#2{\defname2536,83300
+\advance\dimen2 by -\defbodyindentbodyindent2540,83418
+\advance\dimen3 by -\defbodyindentbodyindent2542,83472
+\setbox0=\hbox{\hskip \deflastargmargin{lastargmargin2544,83526
+\dimen1=\hsize \advance \dimen1 by -\defargsindent %size for continuationsargsindent2546,83668
+\parshape 2 0in \dimen0 \defargsindent \dimen1 %argsindent2547,83743
+\rlap{\rightline{{\rm #2}\hskip \deftypemargin}typemargin2554,84112
+\advance\leftskip by -\defbodyindentbodyindent2557,84246
+\exdentamount=\defbodyindentbodyindent2558,84283
+\def\defparsebody #1#2#3{\defparsebody2568,84642
+\def#1{2572,84826
+\def#2{2573,84862
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2575,84934
+\exdentamount=\defbodyindentbodyindent2576,85008
+\def\defmethparsebody #1#2#3#4 {\defmethparsebody2581,85112
+\def#1{2585,85273
+\def#2##1 {2586,85309
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2588,85392
+\exdentamount=\defbodyindentbodyindent2589,85466
+\def\defopparsebody #1#2#3#4#5 {\defopparsebody2592,85551
+\def#1{2596,85712
+\def#2##1 ##2 {2597,85748
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2600,85848
+\exdentamount=\defbodyindentbodyindent2601,85922
+\def\defvarparsebody #1#2#3{\defvarparsebody2608,86193
+\def#1{2612,86380
+\def#2{2613,86416
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2615,86475
+\exdentamount=\defbodyindentbodyindent2616,86549
+\def\defvrparsebody #1#2#3#4 {\defvrparsebody2621,86640
+\def#1{2625,86799
+\def#2##1 {2626,86835
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2628,86905
+\exdentamount=\defbodyindentbodyindent2629,86979
+\def\defopvarparsebody #1#2#3#4#5 {\defopvarparsebody2632,87051
+\def#1{2636,87215
+\def#2##1 ##2 {2637,87251
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2640,87338
+\exdentamount=\defbodyindentbodyindent2641,87412
+\def\defunargs #1{\defunargs2664,88172
+\def\deftypefunargs #1{\deftypefunargs2676,88554
+\def\deffn{\deffn2690,88936
+\def\deffnheader #1#2#3{\deffnheader2692,88993
+\begingroup\defname {name2693,89041
+\def\defun{\defun2699,89186
+\def\defunheader #1#2{\defunheader2701,89239
+\begingroup\defname {name2702,89314
+\defunargs {unargs2703,89350
+\def\deftypefun{\deftypefun2709,89498
+\def\deftypefunheader #1#2{\deftypefunheader2712,89620
+\def\deftypefunheaderx #1#2 #3\relax{\deftypefunheaderx2714,89729
+\begingroup\defname {name2716,89821
+\deftypefunargs {typefunargs2717,89867
+\def\deftypefn{\deftypefn2723,90038
+\def\deftypefnheader #1#2#3{\deftypefnheader2726,90187
+\def\deftypefnheaderx #1#2#3 #4\relax{\deftypefnheaderx2728,90323
+\begingroup\defname {name2730,90416
+\deftypefunargs {typefunargs2731,90456
+\def\defmac{\defmac2737,90577
+\def\defmacheader #1#2{\defmacheader2739,90634
+\begingroup\defname {name2740,90710
+\defunargs {unargs2741,90743
+\def\defspec{\defspec2747,90867
+\def\defspecheader #1#2{\defspecheader2749,90928
+\begingroup\defname {name2750,91005
+\defunargs {unargs2751,91045
+\def\deffnx #1 {\deffnx2758,91240
+\def\defunx #1 {\defunx2759,91297
+\def\defmacx #1 {\defmacx2760,91354
+\def\defspecx #1 {\defspecx2761,91413
+\def\deftypefnx #1 {\deftypefnx2762,91474
+\def\deftypeunx #1 {\deftypeunx2763,91539
+\def\defop #1 {\defop2769,91685
+\defopparsebody\Edefop\defopx\defopheader\defoptype}opparsebody\Edefop\defopx\defopheader\defoptype2770,91720
+\def\defopheader #1#2#3{\defopheader2772,91774
+\begingroup\defname {name2774,91863
+\defunargs {unargs2775,91909
+\def\defmethod{\defmethod2780,91970
+\def\defmethodheader #1#2#3{\defmethodheader2782,92043
+\begingroup\defname {name2784,92131
+\defunargs {unargs2785,92171
+\def\defcv #1 {\defcv2790,92245
+\defopvarparsebody\Edefcv\defcvx\defcvarheader\defcvtype}opvarparsebody\Edefcv\defcvx\defcvarheader\defcvtype2791,92280
+\def\defcvarheader #1#2#3{\defcvarheader2793,92339
+\begingroup\defname {name2795,92425
+\defvarargs {varargs2796,92471
+\def\defivar{\defivar2801,92544
+\def\defivarheader #1#2#3{\defivarheader2803,92607
+\begingroup\defname {name2805,92693
+\defvarargs {varargs2806,92744
+\def\defopx #1 {\defopx2812,92893
+\def\defmethodx #1 {\defmethodx2813,92950
+\def\defcvx #1 {\defcvx2814,93015
+\def\defivarx #1 {\defivarx2815,93072
+\def\defvarargs #1{\defvarargs2822,93343
+\def\defvr{\defvr2828,93487
+\def\defvrheader #1#2#3{\defvrheader2830,93542
+\begingroup\defname {name2831,93590
+\def\defvar{\defvar2835,93675
+\def\defvarheader #1#2{\defvarheader2837,93735
+\begingroup\defname {name2838,93806
+\defvarargs {varargs2839,93842
+\def\defopt{\defopt2844,93908
+\def\defoptheader #1#2{\defoptheader2846,93968
+\begingroup\defname {name2847,94039
+\defvarargs {varargs2848,94078
+\def\deftypevar{\deftypevar2853,94135
+\def\deftypevarheader #1#2{\deftypevarheader2856,94251
+\begingroup\defname {name2858,94334
+\def\deftypevr{\deftypevr2865,94508
+\def\deftypevrheader #1#2#3{\deftypevrheader2867,94579
+\begingroup\defname {name2868,94631
+\def\defvrx #1 {\defvrx2876,94868
+\def\defvarx #1 {\defvarx2877,94925
+\def\defoptx #1 {\defoptx2878,94984
+\def\deftypevarx #1 {\deftypevarx2879,95043
+\def\deftypevrx #1 {\deftypevrx2880,95110
+\def\deftpargs #1{\deftpargs2885,95259
+\def\deftp{\deftp2889,95339
+\def\deftpheader #1#2#3{\deftpheader2891,95394
+\begingroup\defname {name2892,95442
+\def\deftpx #1 {\deftpx2897,95601
+\def\setref#1{\setref2908,95922
+\def\unnumbsetref#1{\unnumbsetref2913,96036
+\def\appendixsetref#1{\appendixsetref2918,96143
+\def\pxref#1{\pxref2929,96554
+\def\xref#1{\xref2930,96590
+\def\ref#1{\ref2931,96625
+\def\xrefX[#1,#2,#3,#4,#5,#6]{\xrefX[2932,96655
+\def\printedmanual{\printedmanual2933,96698
+\def\printednodename{\printednodename2934,96736
+\def\printednodename{\printednodename2939,96861
+section ``\printednodename'' in \cite{\printedmanual}\printedmanual2954,97493
+\refx{x2957,97571
+\def\dosetq #1#2{\dosetq2965,97791
+\def\internalsetq #1#2{\internalsetq2973,98049
+\def\Ypagenumber{\Ypagenumber2977,98150
+\def\Ytitle{\Ytitle2979,98176
+\def\Ynothing{\Ynothing2981,98203
+\def\Ysectionnumberandtype{\Ysectionnumberandtype2983,98220
+\def\Yappendixletterandtype{\Yappendixletterandtype2992,98536
+\ifnum\secno=0 Appendix\xreftie'char\the\appendixno{no2993,98566
+\else \ifnum \subsecno=0 Section\xreftie'char\the\appendixno.\the\secno %no.\the\secno2994,98621
+Section\xreftie'char\the\appendixno.\the\secno.\the\subsecno %no.\the\secno.\the\subsecno2996,98725
+Section\xreftie'char\the\appendixno.\the\secno.\the\subsecno.\the\subsubsecno %no.\the\secno.\the\subsecno.\the\subsubsecno2998,98796
+ \def\linenumber{\linenumber3009,99135
+\def\refx#1#2{\refx3015,99319
+\def\xrdef #1#2{\xrdef3037,99945
+\def\readauxfile{\readauxfile3040,100030
+\def\supereject{\supereject3110,101811
+\footstrut\parindent=\defaultparindent\hang\textindent{aultparindent\hang\textindent3131,102496
+\def\openindices{\openindices3139,102682
+\newdimen\defaultparindent \defaultparindent = 15ptaultparindent3151,102907
+\parindent = \defaultparindentaultparindent3152,102959
+\def\smallbook{\smallbook3175,103683
+\global\def\Esmallexample{\Esmallexample3192,104110
+\def\afourpaper{\afourpaper3196,104201
+\def\finalout{\finalout3224,105009
+\def\normaldoublequote{\normaldoublequote3235,105270
+\def\normaltilde{\normaltilde3236,105296
+\def\normalcaret{\normalcaret3237,105316
+\def\normalunderscore{\normalunderscore3238,105336
+\def\normalverticalbar{\normalverticalbar3239,105361
+\def\normalless{\normalless3240,105387
+\def\normalgreater{\normalgreater3241,105406
+\def\normalplus{\normalplus3242,105428
+\def\ifusingtt#1#2{\ifusingtt3253,105920
+\def\activedoublequote{\activedoublequote3261,106248
+\def~{~3264,106334
+\def^{^3267,106395
+\def_{_3270,106434
+\def\_{\_3272,106508
+\def\lvvmode{\lvvmode3279,106845
+\def|{|3282,106895
+\def<{<3285,106958
+\def>{>3288,107015
+\def+{+3290,107053
+\def\turnoffactive{\turnoffactive3296,107214
+\global\def={=3307,107500
+\def\normalbackslash{\normalbackslash3321,107882
+
+merc-src/accumulator.m,3228
+:- interface146,5371
+:- import_module hlds148,5386
+:- import_module univ152,5478
+:- pred accu_transform_proc159,5793
+:- implementation166,6115
+:- import_module libs180,6552
+:- import_module mdbcomp184,6681
+:- import_module parse_tree186,6742
+:- import_module assoc_list194,7013
+:- import_module bool195,7042
+:- import_module int196,7065
+:- import_module io197,7087
+:- import_module list198,7108
+:- import_module map199,7131
+:- import_module maybe200,7153
+:- import_module pair201,7177
+:- import_module require202,7200
+:- import_module set203,7226
+:- import_module solutions204,7248
+:- import_module string205,7276
+:- import_module term206,7301
+:- import_module varset207,7324
+:- type top_level213,7499
+:- type accu_goal_id225,7900
+:- type accu_case228,7964
+:- type accu_goal_store234,8091
+:- type accu_subst238,8216
+:- type accu_warning240,8264
+:- pred generate_warnings334,12550
+:- pred generate_warning342,12895
+:- pred should_attempt_accu_transform365,13886
+:- pred should_attempt_accu_transform_2398,15406
+:- pred accu_standardize440,17390
+:- pred identify_goal_type465,18169
+:- pred is_recursive_case549,21175
+:- type store_info560,21713
+:- func initialize_goal_store570,22060
+:- pred accu_store580,22421
+:- pred identify_recursive_calls601,23288
+:- pred identify_out_and_out_prime626,24397
+:- type accu_sets676,26426
+:- pred accu_stage1689,26978
+:- pred accu_stage1_2727,28348
+:- pred accu_sets_init781,30558
+:- func set_upto796,30985
+:- pred accu_before812,31499
+:- pred accu_assoc835,32478
+:- pred accu_construct862,33713
+:- pred accu_construct_assoc896,35308
+:- pred accu_update938,37070
+:- pred member_lessthan_goalid964,38220
+:- type accu_assoc975,38653
+:- pred accu_is_associative986,39139
+:- pred associativity_assertion1014,40264
+:- pred commutativity_assertion1037,41243
+:- pred accu_is_update1057,41953
+:- pred is_associative_construction1078,42803
+:- type accu_substs1095,43481
+:- type accu_base1103,43745
+:- pred accu_stage21124,44606
+:- pred accu_substs_init1179,46958
+:- pred acc_var_subst_init1194,47574
+:- pred create_new_var1207,48148
+:- pred accu_process_assoc_set1223,48863
+:- pred accu_has_heuristic1297,52082
+:- pred accu_heuristic1304,52337
+:- pred accu_process_update_set1318,52907
+:- pred accu_divide_base_case1380,55845
+:- pred accu_related1412,57147
+:- inst stored_goal_plain_call1444,58416
+:- pred lookup_call1449,58602
+:- pred accu_stage31470,59433
+:- pred acc_proc_info1508,61327
+:- pred acc_pred_info1556,63450
+:- pred accu_create_goal1600,65286
+:- func create_acc_call1621,66401
+:- pred create_orig_goal1634,66988
+:- pred create_acc_goal1662,68158
+:- func create_new_orig_recursive_goals1709,70226
+:- func create_new_recursive_goals1723,70919
+:- func create_new_base_goals1738,71718
+:- pred acc_unification1749,72157
+:- pred accu_top_level1766,72897
+:- pred update_accumulator_pred1856,76291
+:- func accu_rename1876,77254
+:- func base_case_ids1889,77785
+:- func base_case_ids_set1898,78049
+:- func accu_goal_list1905,78270
+:- pred calculate_goal_info1916,78681
+:- func chain_subst1932,79320
+:- pred chain_subst_21938,79483
+:- some [T] pred unravel_univ1956,80061
+:- pragma foreign_export1957,80117
c-src/c.c,76
T f(1,0
@@ -3984,13 +4082,13 @@ yyerror FUN1(286,5948
make_list FUN2(293,6028
#define ERROR 304,6228
yylex FUN0(315,6405
-parse_cell_or_range FUN2(587,11771
-#define CK_ABS_R(671,13213
-#define CK_REL_R(675,13292
-#define CK_ABS_C(680,13421
-#define CK_REL_C(684,13500
-#define MAYBEREL(689,13629
-str_to_col FUN1(847,16830
+parse_cell_or_range FUN2(587,11772
+#define CK_ABS_R(671,13214
+#define CK_REL_R(675,13293
+#define CK_ABS_C(680,13422
+#define CK_REL_C(684,13501
+#define MAYBEREL(689,13630
+str_to_col FUN1(847,16831
y-src/parse.c,520
#define YYBISON 4,64
diff --git a/test/manual/etags/ETAGS.good_2 b/test/manual/etags/ETAGS.good_2
index 54fd00e95da..6e90f1e8e05 100644
--- a/test/manual/etags/ETAGS.good_2
+++ b/test/manual/etags/ETAGS.good_2
@@ -175,7 +175,7 @@ package body Truc.Bidule Truc.Bidule/b138,2153
protected body Bidule Bidule/b139,2181
protected body Machin_T Machin_T/b146,2281
-c-src/abbrev.c,2072
+c-src/abbrev.c,1957
Lisp_Object Vabbrev_table_name_list;43,1429
Lisp_Object Vglobal_abbrev_table;48,1574
Lisp_Object Vfundamental_mode_abbrev_table;52,1685
@@ -186,33 +186,31 @@ Lisp_Object Vabbrev_start_location_buffer;66,2046
Lisp_Object Vlast_abbrev;70,2155
Lisp_Object Vlast_abbrev_text;75,2324
int last_abbrev_point;79,2414
-Lisp_Object Vpre_abbrev_expand_hook,83,2487
-Lisp_Object Vpre_abbrev_expand_hook, Qpre_abbrev_expand_hook;83,2487
-DEFUN ("make-abbrev-table", Fmake_abbrev_table,85,2551
-DEFUN ("make-abbrev-table", Fmake_abbrev_table,make-abbrev-table85,2551
-DEFUN ("clear-abbrev-table", Fclear_abbrev_table,92,2743
-DEFUN ("clear-abbrev-table", Fclear_abbrev_table,clear-abbrev-table92,2743
-DEFUN ("define-abbrev", Fdefine_abbrev,107,3124
-DEFUN ("define-abbrev", Fdefine_abbrev,define-abbrev107,3124
-DEFUN ("define-global-abbrev", Fdefine_global_abbrev,149,4443
-DEFUN ("define-global-abbrev", Fdefine_global_abbrev,define-global-abbrev149,4443
-DEFUN ("define-mode-abbrev", Fdefine_mode_abbrev,160,4814
-DEFUN ("define-mode-abbrev", Fdefine_mode_abbrev,define-mode-abbrev160,4814
-DEFUN ("abbrev-symbol", Fabbrev_symbol,174,5282
-DEFUN ("abbrev-symbol", Fabbrev_symbol,abbrev-symbol174,5282
-DEFUN ("abbrev-expansion", Fabbrev_expansion,202,6246
-DEFUN ("abbrev-expansion", Fabbrev_expansion,abbrev-expansion202,6246
-DEFUN ("expand-abbrev", Fexpand_abbrev,218,6761
-DEFUN ("expand-abbrev", Fexpand_abbrev,expand-abbrev218,6761
-DEFUN ("unexpand-abbrev", Funexpand_abbrev,389,11682
-DEFUN ("unexpand-abbrev", Funexpand_abbrev,unexpand-abbrev389,11682
-write_abbrev 426,12889
-describe_abbrev 445,13324
-DEFUN ("insert-abbrev-table-description", Finsert_abbrev_table_description,466,13839
-DEFUN ("insert-abbrev-table-description", Finsert_abbrev_table_description,insert-abbrev-table-description466,13839
-DEFUN ("define-abbrev-table", Fdefine_abbrev_table,506,14995
-DEFUN ("define-abbrev-table", Fdefine_abbrev_table,define-abbrev-table506,14995
-syms_of_abbrev 540,16072
+DEFUN ("make-abbrev-table", Fmake_abbrev_table,82,2440
+DEFUN ("make-abbrev-table", Fmake_abbrev_table,make-abbrev-table82,2440
+DEFUN ("clear-abbrev-table", Fclear_abbrev_table,89,2632
+DEFUN ("clear-abbrev-table", Fclear_abbrev_table,clear-abbrev-table89,2632
+DEFUN ("define-abbrev", Fdefine_abbrev,104,3013
+DEFUN ("define-abbrev", Fdefine_abbrev,define-abbrev104,3013
+DEFUN ("define-global-abbrev", Fdefine_global_abbrev,146,4332
+DEFUN ("define-global-abbrev", Fdefine_global_abbrev,define-global-abbrev146,4332
+DEFUN ("define-mode-abbrev", Fdefine_mode_abbrev,157,4703
+DEFUN ("define-mode-abbrev", Fdefine_mode_abbrev,define-mode-abbrev157,4703
+DEFUN ("abbrev-symbol", Fabbrev_symbol,171,5171
+DEFUN ("abbrev-symbol", Fabbrev_symbol,abbrev-symbol171,5171
+DEFUN ("abbrev-expansion", Fabbrev_expansion,199,6135
+DEFUN ("abbrev-expansion", Fabbrev_expansion,abbrev-expansion199,6135
+DEFUN ("expand-abbrev", Fexpand_abbrev,215,6650
+DEFUN ("expand-abbrev", Fexpand_abbrev,expand-abbrev215,6650
+DEFUN ("unexpand-abbrev", Funexpand_abbrev,383,11495
+DEFUN ("unexpand-abbrev", Funexpand_abbrev,unexpand-abbrev383,11495
+write_abbrev 420,12702
+describe_abbrev 439,13137
+DEFUN ("insert-abbrev-table-description", Finsert_abbrev_table_description,460,13652
+DEFUN ("insert-abbrev-table-description", Finsert_abbrev_table_description,insert-abbrev-table-description460,13652
+DEFUN ("define-abbrev-table", Fdefine_abbrev_table,500,14808
+DEFUN ("define-abbrev-table", Fdefine_abbrev_table,define-abbrev-table500,14808
+syms_of_abbrev 534,15885
c-src/torture.c,197
(*tag1 tag118,452
@@ -247,379 +245,379 @@ extern int getopt_long_only 116,4187
extern int _getopt_internal 118,4220
c-src/etags.c,12175
-char pot_etags_version[pot_etags_version81,3470
-# undef DEBUG84,3552
-# define DEBUG 85,3567
-# define DEBUG 87,3594
-# define NDEBUG 88,3617
-# define _GNU_SOURCE 94,3705
-# undef MSDOS100,3876
-# undef WINDOWSNT101,3890
-# define WINDOWSNT102,3909
-# undef MSDOS106,3968
-# define MSDOS 107,3982
-# define MSDOS 110,4032
-# define MAXPATHLEN 115,4111
-# undef HAVE_NTGUI116,4141
-# undef DOS_NT117,4160
-# define DOS_NT118,4176
-# undef assert 135,4482
-# define assert(136,4541
-# undef CTAGS146,4857
-# define CTAGS 147,4872
-# define CTAGS 149,4898
-#define streq(152,4927
-#define strcaseeq(153,4996
-#define strneq(154,5075
-#define strncaseeq(155,5151
-#define CHARS 157,5238
-#define CHAR(158,5278
-#define iswhite(159,5329
-#define notinname(160,5394
-#define begtoken(161,5469
-#define intoken(162,5542
-#define endtoken(163,5614
-#define ISALNUM(165,5684
-#define ISALPHA(166,5722
-#define ISDIGIT(167,5760
-#define ISLOWER(168,5798
-#define lowcase(170,5837
-#define xnew(179,6015
-#define xrnew(180,6083
-typedef void Lang_function 182,6164
-} compressor;188,6365
-} language;199,6835
-typedef struct fdesc201,6848
-} fdesc;212,7366
-typedef struct node_st214,7376
-} node;225,7894
-} linebuffer;239,8248
- at_language,245,8344
- at_regexp,246,8393
- at_filename,247,8437
- at_stdin,248,8473
- at_end 249,8516
-} argument;253,8698
-typedef struct regexp256,8758
-} regexp;268,9325
-static void Ada_funcs 274,9428
-static void Asm_labels 275,9460
-static void C_entries 276,9493
-static void default_C_entries 277,9536
-static void plain_C_entries 278,9576
-static void Cjava_entries 279,9614
-static void Cobol_paragraphs 280,9650
-static void Cplusplus_entries 281,9689
-static void Cstar_entries 282,9729
-static void Erlang_functions 283,9765
-static void Forth_words 284,9804
-static void Fortran_functions 285,9838
-static void HTML_labels 286,9878
-static void Lisp_functions 287,9912
-static void Lua_functions 288,9949
-static void Makefile_targets 289,9985
-static void Pascal_functions 290,10024
-static void Perl_functions 291,10063
-static void PHP_functions 292,10100
-static void PS_functions 293,10136
-static void Prolog_functions 294,10171
-static void Python_functions 295,10210
-static void Scheme_functions 296,10249
-static void TeX_commands 297,10288
-static void Texinfo_nodes 298,10323
-static void Yacc_entries 299,10359
-static void just_read_file 300,10394
-static language *get_language_from_langname get_language_from_langname302,10432
-static void readline 303,10492
-static long readline_internal 304,10537
-static bool nocase_tail 305,10591
-static void get_tag 306,10631
-static void analyze_regex 308,10671
-static void free_regexps 309,10707
-static void regex_tag_multiline 310,10740
-static void error 311,10780
-# undef STDIN408,15073
-#define STDIN 411,15095
-static compressor compressors[compressors457,17664
-static const char *Ada_suffixes Ada_suffixes473,17907
-static const char Ada_help 475,17977
-static const char *Asm_suffixes Asm_suffixes493,18580
-static const char Asm_help 504,18976
-static const char *default_C_suffixes default_C_suffixes512,19312
-static const char default_C_help 515,19413
-static const char default_C_help 523,19850
-static const char *Cplusplus_suffixes Cplusplus_suffixes535,20460
-static const char Cplusplus_help 540,20658
-static const char *Cjava_suffixes Cjava_suffixes549,21113
-static char Cjava_help 551,21172
-static const char *Cobol_suffixes Cobol_suffixes556,21337
-static char Cobol_help 558,21402
-static const char *Cstar_suffixes Cstar_suffixes562,21543
-static const char *Erlang_suffixes Erlang_suffixes565,21607
-static const char Erlang_help 567,21673
-const char *Forth_suffixes Forth_suffixes571,21799
-static const char Forth_help 573,21857
-static const char *Fortran_suffixes Fortran_suffixes577,22008
-static const char Fortran_help 579,22085
-static const char *HTML_suffixes HTML_suffixes582,22190
-static const char HTML_help 584,22264
-static const char *Lisp_suffixes Lisp_suffixes589,22452
-static const char Lisp_help 591,22556
-static const char *Lua_suffixes Lua_suffixes598,22871
-static const char Lua_help 600,22934
-static const char *Makefile_filenames Makefile_filenames603,23010
-static const char Makefile_help 605,23133
-static const char *Objc_suffixes Objc_suffixes609,23277
-static const char Objc_help 613,23399
-static const char *Pascal_suffixes Pascal_suffixes619,23714
-static const char Pascal_help 621,23778
-static const char *Perl_suffixes Perl_suffixes626,23966
-static const char *Perl_interpreters Perl_interpreters628,24028
-static const char Perl_help 630,24100
-static const char *PHP_suffixes PHP_suffixes637,24451
-static const char PHP_help 639,24523
-static const char *plain_C_suffixes plain_C_suffixes643,24678
-static const char *PS_suffixes PS_suffixes647,24762
-static const char PS_help 649,24848
-static const char *Prolog_suffixes Prolog_suffixes652,24931
-static const char Prolog_help 654,24993
-static const char *Python_suffixes Python_suffixes658,25107
-static const char Python_help 660,25165
-static const char *Scheme_suffixes Scheme_suffixes665,25347
-static const char Scheme_help 667,25460
-static const char *TeX_suffixes TeX_suffixes672,25683
-static const char TeX_help 674,25781
-static const char *Texinfo_suffixes Texinfo_suffixes686,26316
-static const char Texinfo_help 688,26395
-static const char *Yacc_suffixes Yacc_suffixes691,26492
-static const char Yacc_help 693,26606
-static const char auto_help 699,26856
-static const char none_help 703,27020
-static const char no_lang_help 707,27143
-static language lang_names 718,27355
-print_language_names 753,29532
-# define EMACS_NAME 786,30755
-# define VERSION 789,30811
-print_version 792,30869
-# define PRINT_UNDOCUMENTED_OPTIONS_HELP 804,31173
-print_help 808,31250
-main 981,37438
-get_compressor_from_suffix 1319,46217
-get_language_from_langname 1355,47158
-get_language_from_interpreter 1377,47545
-get_language_from_filename 1399,47976
-process_file_name 1433,48834
-process_file 1555,51665
-init 1632,54150
-find_entries 1656,54901
-make_tag 1814,59707
-pfnote 1856,60942
-free_tree 1917,62744
-free_fdesc 1935,63029
-add_node 1955,63472
-invalidate_nodes 2035,65537
-static int total_size_of_entries 2067,66150
-static int number_len 2068,66193
-total_size_of_entries 2087,66694
-put_entries 2107,67154
-#define C_EXT 2193,68995
-#define C_PLAIN 2194,69037
-#define C_PLPL 2195,69070
-#define C_STAR 2196,69104
-#define C_JAVA 2197,69137
-#define C_AUTO 2198,69172
-#define YACC 2199,69242
-enum sym_type2204,69312
- st_none,2206,69328
- st_C_objprot,2207,69339
- st_C_objprot, st_C_objimpl,2207,69339
- st_C_objprot, st_C_objimpl, st_C_objend,2207,69339
- st_C_gnumacro,2208,69382
- st_C_ignore,2209,69399
- st_C_ignore, st_C_attribute,2209,69399
- st_C_javastruct,2210,69430
- st_C_operator,2211,69449
- st_C_class,2212,69466
- st_C_class, st_C_template,2212,69466
- st_C_struct,2213,69495
- st_C_struct, st_C_extern,2213,69495
- st_C_struct, st_C_extern, st_C_enum,2213,69495
- st_C_struct, st_C_extern, st_C_enum, st_C_define,2213,69495
- st_C_struct, st_C_extern, st_C_enum, st_C_define, st_C_typedef2213,69495
-struct C_stab_entry 2271,71278
-hash 2275,71409
-in_word_set 2321,72937
- TOTAL_KEYWORDS 2325,73018
- MIN_WORD_LENGTH 2326,73045
- MAX_WORD_LENGTH 2327,73072
- MIN_HASH_VALUE 2328,73100
- MAX_HASH_VALUE 2329,73126
-C_symtype 2387,74985
-static bool inattribute;2400,75234
- fvnone,2408,75435
- fdefunkey,2409,75466
- fdefunname,2410,75512
- foperator,2411,75556
- fvnameseen,2412,75613
- fstartlist,2413,75666
- finlist,2414,75722
- flistseen,2415,75765
- fignore,2416,75813
- vignore 2417,75856
-} fvdef;2418,75901
-static bool fvextern;2420,75911
- tnone,2428,76089
- tkeyseen,2429,76119
- ttypeseen,2430,76160
- tinbody,2431,76199
- tend,2432,76238
- tignore 2433,76279
-} typdef;2434,76320
- snone,2443,76499
- skeyseen,2445,76575
- stagseen,2446,76620
- scolonseen 2447,76661
-} structdef;2448,76715
-static const char *objtag objtag2453,76809
- dnone,2460,76942
- dsharpseen,2461,76972
- ddefineseen,2462,77025
- dignorerest 2463,77070
-} definedef;2464,77112
- onone,2472,77267
- oprotocol,2473,77297
- oimplementation,2474,77347
- otagseen,2475,77395
- oparenseen,2476,77431
- ocatseen,2477,77486
- oinbody,2478,77525
- omethodsign,2479,77568
- omethodtag,2480,77626
- omethodcolon,2481,77666
- omethodparm,2482,77709
- oignore 2483,77755
-} objdef;2484,77787
-static struct tok2491,77944
-} token;2508,78626
-static void pushclass_above 2514,78784
-static void popclass_above 2515,78832
-static void write_classname 2516,78866
-} cstack;2523,79136
-#define nestlev 2525,79264
-#define instruct 2527,79369
-pushclass_above 2531,79489
-popclass_above 2550,79948
-write_classname 2564,80162
-static bool consider_token 2592,80761
-static void make_C_tag 2593,80833
-consider_token 2613,81341
-} lbs[lbs2924,88532
-#define current_lb_is_new 2926,88543
-#define switch_line_buffers(2927,88588
-#define curlb 2929,88641
-#define newlb 2930,88672
-#define curlinepos 2931,88703
-#define newlinepos 2932,88744
-#define plainc 2934,88786
-#define cplpl 2935,88830
-#define cjava 2936,88861
-#define CNL_SAVE_DEFINEDEF(2938,88905
-#define CNL(2947,89117
-make_C_tag 2960,89375
-C_entries 2986,90194
-default_C_entries 3833,110156
-plain_C_entries 3840,110276
-Cplusplus_entries 3847,110364
-Cjava_entries 3854,110460
-Cstar_entries 3861,110550
-Yacc_entries 3868,110642
-#define LOOP_ON_INPUT_LINES(3875,110720
-#define LOOKING_AT(3884,111056
-#define LOOKING_AT_NOCASE(3891,111461
-just_read_file 3901,111861
-static void F_takeprec 3910,111965
-static void F_getit 3911,111996
-F_takeprec 3914,112039
-F_getit 3937,112366
-Fortran_functions 3961,112840
-Ada_getit 4052,114669
-Ada_funcs 4115,116044
-Asm_labels 4228,118582
-Perl_functions 4261,119549
-Python_functions 4357,122057
-PHP_functions 4387,122684
-Cobol_paragraphs 4466,124471
-Makefile_targets 4494,125029
-Pascal_functions 4529,125950
-static void L_getit 4706,130277
-L_getit 4709,130318
-Lisp_functions 4725,130664
-Lua_functions 4785,131850
-PS_functions 4811,132385
-Forth_words 4841,133053
-Scheme_functions 4877,134092
-static linebuffer *TEX_toktab TEX_toktab4908,134781
-static const char *TEX_defenv TEX_defenv4912,134974
-static void TEX_mode 4917,135172
-static void TEX_decode_env 4918,135203
-static char TEX_esc 4920,135261
-static char TEX_opgrp 4921,135289
-static char TEX_clgrp 4922,135318
-TeX_commands 4928,135395
-#define TEX_LESC 4986,136652
-#define TEX_SESC 4987,136674
-TEX_mode 4992,136804
-TEX_decode_env 5026,137509
-Texinfo_nodes 5071,138554
-HTML_labels 5094,139013
-static size_t prolog_pr 5214,142192
-static void prolog_skip_comment 5215,142234
-static size_t prolog_atom 5216,142290
-Prolog_functions 5219,142347
-prolog_skip_comment 5255,143128
-prolog_pr 5281,143736
-prolog_atom 5319,144628
-static int erlang_func 5374,145540
-static void erlang_attribute 5375,145581
-static int erlang_atom 5376,145620
-Erlang_functions 5379,145666
-erlang_func 5438,146965
-erlang_attribute 5476,147642
-erlang_atom 5496,148061
-static char *scan_separators scan_separators5520,148487
-static void add_regex 5521,148526
-static char *substitute substitute5522,148570
-scan_separators 5534,149080
-analyze_regex 5586,150460
-add_regex 5654,152050
-substitute 5767,154797
-free_regexps 5814,155837
-regex_tag_multiline 5836,156291
-nocase_tail 5913,158263
-get_tag 5928,158519
-readline_internal 5959,159455
-readline 6037,161296
-savestr 6230,167243
-savenstr 6240,167473
-skip_spaces 6249,167679
-skip_non_spaces 6258,167833
-skip_name 6267,167983
-fatal 6277,168156
-pfatal 6284,168253
-suggest_asking_for_help 6291,168332
-error 6300,168554
-concat 6313,168846
-etags_getcwd 6329,169259
-relative_filename 6350,169725
-absolute_filename 6389,170751
-absolute_dirname 6453,172416
-filename_is_absolute 6472,172845
-canonicalize_filename 6484,173096
-# define ISUPPER(6491,173235
-linebuffer_init 6514,173656
-linebuffer_setlen 6524,173887
-xmalloc 6536,174148
-xrealloc 6545,174314
+char pot_etags_version[pot_etags_version81,3471
+# undef DEBUG84,3553
+# define DEBUG 85,3568
+# define DEBUG 87,3595
+# define NDEBUG 88,3618
+# define _GNU_SOURCE 94,3706
+# undef MSDOS100,3877
+# undef WINDOWSNT101,3891
+# define WINDOWSNT102,3910
+# undef MSDOS106,3969
+# define MSDOS 107,3983
+# define MSDOS 110,4033
+# define MAXPATHLEN 115,4112
+# undef HAVE_NTGUI116,4142
+# undef DOS_NT117,4161
+# define DOS_NT118,4177
+# undef assert 135,4483
+# define assert(136,4542
+# undef CTAGS146,4858
+# define CTAGS 147,4873
+# define CTAGS 149,4899
+#define streq(152,4928
+#define strcaseeq(153,4997
+#define strneq(154,5076
+#define strncaseeq(155,5152
+#define CHARS 157,5239
+#define CHAR(158,5279
+#define iswhite(159,5330
+#define notinname(160,5395
+#define begtoken(161,5470
+#define intoken(162,5543
+#define endtoken(163,5615
+#define ISALNUM(165,5685
+#define ISALPHA(166,5723
+#define ISDIGIT(167,5761
+#define ISLOWER(168,5799
+#define lowcase(170,5838
+#define xnew(179,6016
+#define xrnew(180,6084
+typedef void Lang_function 182,6165
+} compressor;188,6366
+} language;199,6836
+typedef struct fdesc201,6849
+} fdesc;212,7367
+typedef struct node_st214,7377
+} node;225,7895
+} linebuffer;239,8249
+ at_language,245,8345
+ at_regexp,246,8394
+ at_filename,247,8438
+ at_stdin,248,8474
+ at_end 249,8517
+} argument;253,8699
+typedef struct regexp256,8759
+} regexp;268,9326
+static void Ada_funcs 274,9429
+static void Asm_labels 275,9461
+static void C_entries 276,9494
+static void default_C_entries 277,9537
+static void plain_C_entries 278,9577
+static void Cjava_entries 279,9615
+static void Cobol_paragraphs 280,9651
+static void Cplusplus_entries 281,9690
+static void Cstar_entries 282,9730
+static void Erlang_functions 283,9766
+static void Forth_words 284,9805
+static void Fortran_functions 285,9839
+static void HTML_labels 286,9879
+static void Lisp_functions 287,9913
+static void Lua_functions 288,9950
+static void Makefile_targets 289,9986
+static void Pascal_functions 290,10025
+static void Perl_functions 291,10064
+static void PHP_functions 292,10101
+static void PS_functions 293,10137
+static void Prolog_functions 294,10172
+static void Python_functions 295,10211
+static void Scheme_functions 296,10250
+static void TeX_commands 297,10289
+static void Texinfo_nodes 298,10324
+static void Yacc_entries 299,10360
+static void just_read_file 300,10395
+static language *get_language_from_langname get_language_from_langname302,10433
+static void readline 303,10493
+static long readline_internal 304,10538
+static bool nocase_tail 305,10592
+static void get_tag 306,10632
+static void analyze_regex 308,10672
+static void free_regexps 309,10708
+static void regex_tag_multiline 310,10741
+static void error 311,10781
+# undef STDIN408,15074
+#define STDIN 411,15096
+static compressor compressors[compressors457,17665
+static const char *Ada_suffixes Ada_suffixes473,17908
+static const char Ada_help 475,17978
+static const char *Asm_suffixes Asm_suffixes493,18581
+static const char Asm_help 504,18977
+static const char *default_C_suffixes default_C_suffixes512,19313
+static const char default_C_help 515,19414
+static const char default_C_help 523,19851
+static const char *Cplusplus_suffixes Cplusplus_suffixes535,20461
+static const char Cplusplus_help 540,20659
+static const char *Cjava_suffixes Cjava_suffixes549,21114
+static char Cjava_help 551,21173
+static const char *Cobol_suffixes Cobol_suffixes556,21338
+static char Cobol_help 558,21403
+static const char *Cstar_suffixes Cstar_suffixes562,21544
+static const char *Erlang_suffixes Erlang_suffixes565,21608
+static const char Erlang_help 567,21674
+const char *Forth_suffixes Forth_suffixes571,21800
+static const char Forth_help 573,21858
+static const char *Fortran_suffixes Fortran_suffixes577,22009
+static const char Fortran_help 579,22086
+static const char *HTML_suffixes HTML_suffixes582,22191
+static const char HTML_help 584,22265
+static const char *Lisp_suffixes Lisp_suffixes589,22453
+static const char Lisp_help 591,22557
+static const char *Lua_suffixes Lua_suffixes598,22872
+static const char Lua_help 600,22935
+static const char *Makefile_filenames Makefile_filenames603,23011
+static const char Makefile_help 605,23134
+static const char *Objc_suffixes Objc_suffixes609,23278
+static const char Objc_help 613,23400
+static const char *Pascal_suffixes Pascal_suffixes619,23715
+static const char Pascal_help 621,23779
+static const char *Perl_suffixes Perl_suffixes626,23967
+static const char *Perl_interpreters Perl_interpreters628,24029
+static const char Perl_help 630,24101
+static const char *PHP_suffixes PHP_suffixes637,24452
+static const char PHP_help 639,24524
+static const char *plain_C_suffixes plain_C_suffixes643,24679
+static const char *PS_suffixes PS_suffixes647,24763
+static const char PS_help 649,24849
+static const char *Prolog_suffixes Prolog_suffixes652,24932
+static const char Prolog_help 654,24994
+static const char *Python_suffixes Python_suffixes658,25108
+static const char Python_help 660,25166
+static const char *Scheme_suffixes Scheme_suffixes665,25348
+static const char Scheme_help 667,25461
+static const char *TeX_suffixes TeX_suffixes672,25684
+static const char TeX_help 674,25782
+static const char *Texinfo_suffixes Texinfo_suffixes686,26317
+static const char Texinfo_help 688,26396
+static const char *Yacc_suffixes Yacc_suffixes691,26493
+static const char Yacc_help 693,26607
+static const char auto_help 699,26857
+static const char none_help 703,27021
+static const char no_lang_help 707,27144
+static language lang_names 718,27356
+print_language_names 753,29533
+# define EMACS_NAME 786,30756
+# define VERSION 789,30812
+print_version 792,30870
+# define PRINT_UNDOCUMENTED_OPTIONS_HELP 804,31174
+print_help 808,31251
+main 981,37439
+get_compressor_from_suffix 1319,46218
+get_language_from_langname 1355,47159
+get_language_from_interpreter 1377,47546
+get_language_from_filename 1399,47977
+process_file_name 1433,48835
+process_file 1555,51666
+init 1632,54151
+find_entries 1656,54902
+make_tag 1814,59708
+pfnote 1856,60943
+free_tree 1917,62745
+free_fdesc 1935,63030
+add_node 1955,63473
+invalidate_nodes 2035,65538
+static int total_size_of_entries 2067,66151
+static int number_len 2068,66194
+total_size_of_entries 2087,66695
+put_entries 2107,67155
+#define C_EXT 2193,68996
+#define C_PLAIN 2194,69038
+#define C_PLPL 2195,69071
+#define C_STAR 2196,69105
+#define C_JAVA 2197,69138
+#define C_AUTO 2198,69173
+#define YACC 2199,69243
+enum sym_type2204,69313
+ st_none,2206,69329
+ st_C_objprot,2207,69340
+ st_C_objprot, st_C_objimpl,2207,69340
+ st_C_objprot, st_C_objimpl, st_C_objend,2207,69340
+ st_C_gnumacro,2208,69383
+ st_C_ignore,2209,69400
+ st_C_ignore, st_C_attribute,2209,69400
+ st_C_javastruct,2210,69431
+ st_C_operator,2211,69450
+ st_C_class,2212,69467
+ st_C_class, st_C_template,2212,69467
+ st_C_struct,2213,69496
+ st_C_struct, st_C_extern,2213,69496
+ st_C_struct, st_C_extern, st_C_enum,2213,69496
+ st_C_struct, st_C_extern, st_C_enum, st_C_define,2213,69496
+ st_C_struct, st_C_extern, st_C_enum, st_C_define, st_C_typedef2213,69496
+struct C_stab_entry 2271,71279
+hash 2275,71410
+in_word_set 2321,72938
+ TOTAL_KEYWORDS 2325,73019
+ MIN_WORD_LENGTH 2326,73046
+ MAX_WORD_LENGTH 2327,73073
+ MIN_HASH_VALUE 2328,73101
+ MAX_HASH_VALUE 2329,73127
+C_symtype 2387,74986
+static bool inattribute;2400,75235
+ fvnone,2408,75436
+ fdefunkey,2409,75467
+ fdefunname,2410,75513
+ foperator,2411,75557
+ fvnameseen,2412,75614
+ fstartlist,2413,75667
+ finlist,2414,75723
+ flistseen,2415,75766
+ fignore,2416,75814
+ vignore 2417,75857
+} fvdef;2418,75902
+static bool fvextern;2420,75912
+ tnone,2428,76090
+ tkeyseen,2429,76120
+ ttypeseen,2430,76161
+ tinbody,2431,76200
+ tend,2432,76239
+ tignore 2433,76280
+} typdef;2434,76321
+ snone,2443,76500
+ skeyseen,2445,76576
+ stagseen,2446,76621
+ scolonseen 2447,76662
+} structdef;2448,76716
+static const char *objtag objtag2453,76810
+ dnone,2460,76943
+ dsharpseen,2461,76973
+ ddefineseen,2462,77026
+ dignorerest 2463,77071
+} definedef;2464,77113
+ onone,2472,77268
+ oprotocol,2473,77298
+ oimplementation,2474,77348
+ otagseen,2475,77396
+ oparenseen,2476,77432
+ ocatseen,2477,77487
+ oinbody,2478,77526
+ omethodsign,2479,77569
+ omethodtag,2480,77627
+ omethodcolon,2481,77667
+ omethodparm,2482,77710
+ oignore 2483,77756
+} objdef;2484,77788
+static struct tok2491,77945
+} token;2508,78627
+static void pushclass_above 2514,78785
+static void popclass_above 2515,78833
+static void write_classname 2516,78867
+} cstack;2523,79137
+#define nestlev 2525,79265
+#define instruct 2527,79370
+pushclass_above 2531,79490
+popclass_above 2550,79949
+write_classname 2564,80163
+static bool consider_token 2592,80762
+static void make_C_tag 2593,80834
+consider_token 2613,81342
+} lbs[lbs2924,88533
+#define current_lb_is_new 2926,88544
+#define switch_line_buffers(2927,88589
+#define curlb 2929,88642
+#define newlb 2930,88673
+#define curlinepos 2931,88704
+#define newlinepos 2932,88745
+#define plainc 2934,88787
+#define cplpl 2935,88831
+#define cjava 2936,88862
+#define CNL_SAVE_DEFINEDEF(2938,88906
+#define CNL(2947,89118
+make_C_tag 2960,89376
+C_entries 2986,90195
+default_C_entries 3833,110157
+plain_C_entries 3840,110277
+Cplusplus_entries 3847,110365
+Cjava_entries 3854,110461
+Cstar_entries 3861,110551
+Yacc_entries 3868,110643
+#define LOOP_ON_INPUT_LINES(3875,110721
+#define LOOKING_AT(3884,111057
+#define LOOKING_AT_NOCASE(3891,111462
+just_read_file 3901,111862
+static void F_takeprec 3910,111966
+static void F_getit 3911,111997
+F_takeprec 3914,112040
+F_getit 3937,112367
+Fortran_functions 3961,112841
+Ada_getit 4052,114670
+Ada_funcs 4115,116045
+Asm_labels 4228,118583
+Perl_functions 4261,119550
+Python_functions 4357,122058
+PHP_functions 4387,122685
+Cobol_paragraphs 4466,124472
+Makefile_targets 4494,125030
+Pascal_functions 4529,125951
+static void L_getit 4706,130278
+L_getit 4709,130319
+Lisp_functions 4725,130665
+Lua_functions 4785,131851
+PS_functions 4811,132386
+Forth_words 4841,133054
+Scheme_functions 4877,134093
+static linebuffer *TEX_toktab TEX_toktab4908,134782
+static const char *TEX_defenv TEX_defenv4912,134975
+static void TEX_mode 4917,135173
+static void TEX_decode_env 4918,135204
+static char TEX_esc 4920,135262
+static char TEX_opgrp 4921,135290
+static char TEX_clgrp 4922,135319
+TeX_commands 4928,135396
+#define TEX_LESC 4986,136653
+#define TEX_SESC 4987,136675
+TEX_mode 4992,136805
+TEX_decode_env 5026,137510
+Texinfo_nodes 5071,138555
+HTML_labels 5094,139014
+static size_t prolog_pr 5214,142193
+static void prolog_skip_comment 5215,142235
+static size_t prolog_atom 5216,142291
+Prolog_functions 5219,142348
+prolog_skip_comment 5255,143129
+prolog_pr 5281,143737
+prolog_atom 5319,144629
+static int erlang_func 5374,145541
+static void erlang_attribute 5375,145582
+static int erlang_atom 5376,145621
+Erlang_functions 5379,145667
+erlang_func 5438,146966
+erlang_attribute 5476,147643
+erlang_atom 5496,148062
+static char *scan_separators scan_separators5520,148488
+static void add_regex 5521,148527
+static char *substitute substitute5522,148571
+scan_separators 5534,149081
+analyze_regex 5586,150461
+add_regex 5654,152051
+substitute 5767,154798
+free_regexps 5814,155838
+regex_tag_multiline 5836,156292
+nocase_tail 5913,158264
+get_tag 5928,158520
+readline_internal 5959,159456
+readline 6037,161297
+savestr 6230,167244
+savenstr 6240,167474
+skip_spaces 6249,167680
+skip_non_spaces 6258,167834
+skip_name 6267,167984
+fatal 6277,168157
+pfatal 6284,168254
+suggest_asking_for_help 6291,168333
+error 6300,168555
+concat 6313,168847
+etags_getcwd 6329,169260
+relative_filename 6350,169726
+absolute_filename 6389,170752
+absolute_dirname 6453,172417
+filename_is_absolute 6472,172846
+canonicalize_filename 6484,173097
+# define ISUPPER(6491,173236
+linebuffer_init 6514,173657
+linebuffer_setlen 6524,173888
+xmalloc 6536,174149
+xrealloc 6545,174315
c-src/exit.c,47
} __libc_atexit;30,1022
@@ -671,1668 +669,1668 @@ pp287,1504
pp3(100,1616
c-src/emacs/src/gmalloc.c,6643
-#define USE_PTHREAD25,1002
-#undef get_current_dir_name33,1126
-extern void emacs_abort 47,1305
-#undef malloc64,2110
-#undef realloc65,2124
-#undef calloc66,2139
-#undef free67,2153
-#define malloc 68,2165
-#define realloc 69,2188
-#define calloc 70,2213
-#define aligned_alloc 71,2236
-#define free 72,2273
-extern void *bss_sbrk bss_sbrk76,2335
-extern int bss_sbrk_did_unexec;77,2375
-extern char bss_sbrk_buffer[bss_sbrk_buffer78,2407
-extern void *bss_sbrk_buffer_end;bss_sbrk_buffer_end79,2438
-#define DUMPED 80,2472
-#define ALLOCATED_BEFORE_DUMPING(81,2507
-extern void *malloc malloc94,2718
-#define INT_BIT 124,3934
-#define BLOCKLOG 125,3977
-#define BLOCKSIZE 126,4018
-#define BLOCKIFY(127,4052
-#define HEAP 131,4215
-#define FINAL_FREE_BLOCKS 135,4391
- } malloc_info;167,5388
-extern char *_heapbase;_heapbase170,5449
-extern malloc_info *_heapinfo;_heapinfo173,5541
-#define BLOCK(176,5620
-#define ADDRESS(177,5682
-extern size_t _heapindex;180,5797
-extern size_t _heaplimit;183,5866
-struct list186,5939
-extern struct list _fraghead[_fraghead193,6056
-struct alignlist196,6153
-extern struct alignlist *_aligned_blocks;_aligned_blocks202,6334
-extern size_t _chunks_used;205,6401
-extern size_t _bytes_used;206,6429
-extern size_t _chunks_free;207,6456
-extern size_t _bytes_free;208,6484
-extern void *_malloc_internal _malloc_internal213,6673
-extern void *_realloc_internal _realloc_internal214,6713
-extern void _free_internal 215,6762
-extern void *_malloc_internal_nolock _malloc_internal_nolock216,6799
-extern void *_realloc_internal_nolock _realloc_internal_nolock217,6846
-extern void _free_internal_nolock 218,6902
-extern pthread_mutex_t _malloc_mutex,221,6966
-extern pthread_mutex_t _malloc_mutex, _aligned_blocks_mutex;221,6966
-extern int _malloc_thread_enabled_p;222,7027
-#define LOCK(223,7064
-#define UNLOCK(228,7195
-#define LOCK_ALIGNED_BLOCKS(233,7329
-#define UNLOCK_ALIGNED_BLOCKS(238,7484
-#define LOCK(244,7649
-#define UNLOCK(245,7664
-#define LOCK_ALIGNED_BLOCKS(246,7681
-#define UNLOCK_ALIGNED_BLOCKS(247,7711
-extern void *malloc_find_object_address malloc_find_object_address252,7865
-extern void *(*__morecore)__morecore256,8021
-extern void *__default_morecore __default_morecore259,8105
-extern void (*__after_morecore_hook)__after_morecore_hook263,8269
-extern size_t __malloc_extra_blocks;267,8442
-extern int __malloc_initialized;270,8552
-extern int __malloc_initialize 272,8646
-extern void (*__malloc_initialize_hook)__malloc_initialize_hook275,8723
-extern void (*__free_hook)__free_hook276,8771
-extern void *(*__malloc_hook)__malloc_hook277,8811
-extern void *(*__realloc_hook)__realloc_hook278,8856
-extern void *(*__memalign_hook)__memalign_hook279,8913
-enum mcheck_status283,9092
- MCHECK_DISABLED 285,9115
- MCHECK_OK,286,9187
- MCHECK_FREE,287,9226
- MCHECK_HEAD,288,9270
- MCHECK_TAIL 289,9334
-extern int mcheck 296,9701
-extern enum mcheck_status mprobe 301,9952
-extern void mtrace 304,10055
-extern void muntrace 305,10082
-struct mstats308,10153
-extern struct mstats mstats 318,10518
-extern void memory_warnings 321,10625
-void *(*__malloc_hook)__malloc_hook352,11743
-char *_heapbase;_heapbase355,11829
-malloc_info *_heapinfo;_heapinfo358,11927
-static size_t heapsize;361,11983
-size_t _heapindex;364,12047
-size_t _heaplimit;367,12109
-struct list _fraghead[_fraghead370,12171
-size_t _chunks_used;373,12229
-size_t _bytes_used;374,12250
-size_t _chunks_free;375,12270
-size_t _bytes_free;376,12291
-int __malloc_initialized;379,12340
-size_t __malloc_extra_blocks;381,12367
-void (*__malloc_initialize_hook)__malloc_initialize_hook383,12398
-void (*__after_morecore_hook)__after_morecore_hook384,12439
-static int state_protected_p;400,12912
-static size_t last_state_size;401,12942
-static malloc_info *last_heapinfo;last_heapinfo402,12973
-protect_malloc_state 405,13014
-#define PROTECT_MALLOC_STATE(426,13627
-#define PROTECT_MALLOC_STATE(429,13697
-align 435,13794
-get_contiguous_space 466,14616
-register_heapinfo 497,15325
-pthread_mutex_t _malloc_mutex 517,15879
-pthread_mutex_t _aligned_blocks_mutex 518,15938
-int _malloc_thread_enabled_p;519,16005
-malloc_atfork_handler_prepare 522,16048
-malloc_atfork_handler_parent 529,16139
-malloc_atfork_handler_child 536,16233
-malloc_enable_thread 544,16375
-malloc_initialize_1 563,16961
-__malloc_initialize 594,17793
-static int morecore_recursing;604,17926
-morecore_nolock 609,18066
-_malloc_internal_nolock 722,21584
-_malloc_internal 920,28102
-malloc 932,28247
-extern void *_malloc _malloc956,29033
-extern void _free 957,29064
-extern void *_realloc _realloc958,29092
-_malloc 961,29140
-_free 967,29196
-_realloc 973,29240
-void (*__free_hook)__free_hook1001,30259
-struct alignlist *_aligned_blocks _aligned_blocks1004,30345
-_free_internal_nolock 1009,30474
-_free_internal 1255,38476
-free 1265,38603
-weak_alias 1277,38799
-#define min(1306,39813
-void *(*__realloc_hook)__realloc_hook1310,39898
-_realloc_internal_nolock 1319,40309
-_realloc_internal 1435,43563
-realloc 1447,43726
-calloc 1478,44894
-#define __sbrk 1513,46042
-extern void *__sbrk __sbrk1518,46247
-__default_morecore 1525,46511
-void *(*__memalign_hook)__memalign_hook1554,47456
-aligned_alloc 1557,47522
-memalign 1647,49704
-posix_memalign 1656,49909
-extern void *valloc valloc1695,51140
-extern int getpagesize 1700,51278
-static size_t pagesize;1703,51317
-valloc 1706,51349
-#undef malloc1715,51490
-#undef realloc1716,51504
-#undef calloc1717,51519
-#undef aligned_alloc1718,51533
-#undef free1719,51554
-extern void *malloc malloc1722,51609
-extern void *realloc realloc1723,51644
-extern void *calloc calloc1724,51691
-extern void free 1725,51740
-extern void *aligned_alloc aligned_alloc1727,51796
-extern int posix_memalign 1729,51890
-hybrid_malloc 1736,52083
-hybrid_calloc 1744,52188
-hybrid_free 1752,52319
-hybrid_aligned_alloc 1765,52626
-hybrid_realloc 1780,52984
-char *gget_current_dir_name gget_current_dir_name1808,53753
-hybrid_get_current_dir_name 1811,53797
-static void (*old_free_hook)old_free_hook1846,54921
-static void *(*old_malloc_hook)old_malloc_hook1847,54963
-static void *(*old_realloc_hook)old_realloc_hook1848,55010
-static void (*abortfunc)abortfunc1851,55124
-#define MAGICWORD 1854,55206
-#define MAGICFREE 1855,55261
-#define MAGICBYTE 1856,55316
-#define MALLOCFLOOD 1857,55348
-#define FREEFLOOD 1858,55382
-struct hdr1860,55415
-checkhdr 1867,55581
-freehook 1891,56022
-mallochook 1927,56804
-reallochook 1944,57143
-mabort 1978,57901
-static int mcheck_used 2012,58586
-mcheck 2015,58619
-mprobe 2035,59138
+#define USE_PTHREAD25,1003
+#undef get_current_dir_name33,1127
+extern void emacs_abort 47,1306
+#undef malloc64,2111
+#undef realloc65,2125
+#undef calloc66,2140
+#undef free67,2154
+#define malloc 68,2166
+#define realloc 69,2189
+#define calloc 70,2214
+#define aligned_alloc 71,2237
+#define free 72,2274
+extern void *bss_sbrk bss_sbrk76,2336
+extern int bss_sbrk_did_unexec;77,2376
+extern char bss_sbrk_buffer[bss_sbrk_buffer78,2408
+extern void *bss_sbrk_buffer_end;bss_sbrk_buffer_end79,2439
+#define DUMPED 80,2473
+#define ALLOCATED_BEFORE_DUMPING(81,2508
+extern void *malloc malloc94,2719
+#define INT_BIT 124,3935
+#define BLOCKLOG 125,3978
+#define BLOCKSIZE 126,4019
+#define BLOCKIFY(127,4053
+#define HEAP 131,4216
+#define FINAL_FREE_BLOCKS 135,4392
+ } malloc_info;167,5389
+extern char *_heapbase;_heapbase170,5450
+extern malloc_info *_heapinfo;_heapinfo173,5542
+#define BLOCK(176,5621
+#define ADDRESS(177,5683
+extern size_t _heapindex;180,5798
+extern size_t _heaplimit;183,5867
+struct list186,5940
+extern struct list _fraghead[_fraghead193,6057
+struct alignlist196,6154
+extern struct alignlist *_aligned_blocks;_aligned_blocks202,6335
+extern size_t _chunks_used;205,6402
+extern size_t _bytes_used;206,6430
+extern size_t _chunks_free;207,6457
+extern size_t _bytes_free;208,6485
+extern void *_malloc_internal _malloc_internal213,6674
+extern void *_realloc_internal _realloc_internal214,6714
+extern void _free_internal 215,6763
+extern void *_malloc_internal_nolock _malloc_internal_nolock216,6800
+extern void *_realloc_internal_nolock _realloc_internal_nolock217,6847
+extern void _free_internal_nolock 218,6903
+extern pthread_mutex_t _malloc_mutex,221,6967
+extern pthread_mutex_t _malloc_mutex, _aligned_blocks_mutex;221,6967
+extern int _malloc_thread_enabled_p;222,7028
+#define LOCK(223,7065
+#define UNLOCK(228,7196
+#define LOCK_ALIGNED_BLOCKS(233,7330
+#define UNLOCK_ALIGNED_BLOCKS(238,7485
+#define LOCK(244,7650
+#define UNLOCK(245,7665
+#define LOCK_ALIGNED_BLOCKS(246,7682
+#define UNLOCK_ALIGNED_BLOCKS(247,7712
+extern void *malloc_find_object_address malloc_find_object_address252,7866
+extern void *(*__morecore)__morecore256,8022
+extern void *__default_morecore __default_morecore259,8106
+extern void (*__after_morecore_hook)__after_morecore_hook263,8270
+extern size_t __malloc_extra_blocks;267,8443
+extern int __malloc_initialized;270,8553
+extern int __malloc_initialize 272,8647
+extern void (*__malloc_initialize_hook)__malloc_initialize_hook275,8724
+extern void (*__free_hook)__free_hook276,8772
+extern void *(*__malloc_hook)__malloc_hook277,8812
+extern void *(*__realloc_hook)__realloc_hook278,8857
+extern void *(*__memalign_hook)__memalign_hook279,8914
+enum mcheck_status283,9093
+ MCHECK_DISABLED 285,9116
+ MCHECK_OK,286,9188
+ MCHECK_FREE,287,9227
+ MCHECK_HEAD,288,9271
+ MCHECK_TAIL 289,9335
+extern int mcheck 296,9702
+extern enum mcheck_status mprobe 301,9953
+extern void mtrace 304,10056
+extern void muntrace 305,10083
+struct mstats308,10154
+extern struct mstats mstats 318,10519
+extern void memory_warnings 321,10626
+void *(*__malloc_hook)__malloc_hook352,11745
+char *_heapbase;_heapbase355,11831
+malloc_info *_heapinfo;_heapinfo358,11929
+static size_t heapsize;361,11985
+size_t _heapindex;364,12049
+size_t _heaplimit;367,12111
+struct list _fraghead[_fraghead370,12173
+size_t _chunks_used;373,12231
+size_t _bytes_used;374,12252
+size_t _chunks_free;375,12272
+size_t _bytes_free;376,12293
+int __malloc_initialized;379,12342
+size_t __malloc_extra_blocks;381,12369
+void (*__malloc_initialize_hook)__malloc_initialize_hook383,12400
+void (*__after_morecore_hook)__after_morecore_hook384,12441
+static int state_protected_p;400,12914
+static size_t last_state_size;401,12944
+static malloc_info *last_heapinfo;last_heapinfo402,12975
+protect_malloc_state 405,13016
+#define PROTECT_MALLOC_STATE(426,13629
+#define PROTECT_MALLOC_STATE(429,13699
+align 435,13796
+get_contiguous_space 466,14618
+register_heapinfo 497,15327
+pthread_mutex_t _malloc_mutex 517,15881
+pthread_mutex_t _aligned_blocks_mutex 518,15940
+int _malloc_thread_enabled_p;519,16007
+malloc_atfork_handler_prepare 522,16050
+malloc_atfork_handler_parent 529,16141
+malloc_atfork_handler_child 536,16235
+malloc_enable_thread 544,16377
+malloc_initialize_1 563,16963
+__malloc_initialize 594,17795
+static int morecore_recursing;604,17928
+morecore_nolock 609,18068
+_malloc_internal_nolock 722,21586
+_malloc_internal 920,28104
+malloc 932,28249
+extern void *_malloc _malloc956,29035
+extern void _free 957,29066
+extern void *_realloc _realloc958,29094
+_malloc 961,29142
+_free 967,29198
+_realloc 973,29242
+void (*__free_hook)__free_hook1001,30262
+struct alignlist *_aligned_blocks _aligned_blocks1004,30348
+_free_internal_nolock 1009,30477
+_free_internal 1255,38479
+free 1265,38606
+weak_alias 1277,38802
+#define min(1306,39817
+void *(*__realloc_hook)__realloc_hook1310,39902
+_realloc_internal_nolock 1319,40313
+_realloc_internal 1435,43567
+realloc 1447,43730
+calloc 1478,44899
+#define __sbrk 1513,46048
+extern void *__sbrk __sbrk1518,46253
+__default_morecore 1525,46517
+void *(*__memalign_hook)__memalign_hook1554,47463
+aligned_alloc 1557,47529
+memalign 1647,49711
+posix_memalign 1656,49916
+extern void *valloc valloc1695,51148
+extern int getpagesize 1700,51286
+static size_t pagesize;1703,51325
+valloc 1706,51357
+#undef malloc1715,51498
+#undef realloc1716,51512
+#undef calloc1717,51527
+#undef aligned_alloc1718,51541
+#undef free1719,51562
+extern void *malloc malloc1722,51617
+extern void *realloc realloc1723,51652
+extern void *calloc calloc1724,51699
+extern void free 1725,51748
+extern void *aligned_alloc aligned_alloc1727,51804
+extern int posix_memalign 1729,51898
+hybrid_malloc 1736,52091
+hybrid_calloc 1744,52196
+hybrid_free 1752,52327
+hybrid_aligned_alloc 1765,52634
+hybrid_realloc 1780,52990
+char *gget_current_dir_name gget_current_dir_name1808,53759
+hybrid_get_current_dir_name 1811,53803
+static void (*old_free_hook)old_free_hook1846,54928
+static void *(*old_malloc_hook)old_malloc_hook1847,54970
+static void *(*old_realloc_hook)old_realloc_hook1848,55017
+static void (*abortfunc)abortfunc1851,55131
+#define MAGICWORD 1854,55213
+#define MAGICFREE 1855,55268
+#define MAGICBYTE 1856,55323
+#define MALLOCFLOOD 1857,55355
+#define FREEFLOOD 1858,55389
+struct hdr1860,55422
+checkhdr 1867,55588
+freehook 1891,56029
+mallochook 1927,56811
+reallochook 1944,57150
+mabort 1978,57908
+static int mcheck_used 2012,58593
+mcheck 2015,58626
+mprobe 2035,59145
c-src/emacs/src/regex.h,4576
-#define _REGEX_H 21,836
-typedef unsigned long reg_syntax_t;43,1577
-#define RE_BACKSLASH_ESCAPE_IN_LISTS 47,1749
-#define RE_BK_PLUS_QM 52,1969
-#define RE_CHAR_CLASSES 58,2298
-#define RE_CONTEXT_INDEP_ANCHORS 72,3032
-#define RE_CONTEXT_INDEP_OPS 80,3458
-#define RE_CONTEXT_INVALID_OPS 84,3658
-#define RE_DOT_NEWLINE 88,3801
-#define RE_DOT_NOT_NULL 92,3937
-#define RE_HAT_LISTS_NOT_NEWLINE 96,4082
-#define RE_INTERVALS 101,4292
-#define RE_LIMITED_OPS 105,4441
-#define RE_NEWLINE_ALT 109,4583
-#define RE_NO_BK_BRACES 114,4773
-#define RE_NO_BK_PARENS 118,4964
-#define RE_NO_BK_REFS 122,5120
-#define RE_NO_BK_VBAR 126,5316
-#define RE_NO_EMPTY_RANGES 132,5610
-#define RE_UNMATCHED_RIGHT_PAREN_ORD 136,5766
-#define RE_NO_POSIX_BACKTRACKING 140,5937
-#define RE_NO_GNU_OPS 144,6133
-#define RE_FRUGAL 147,6253
-#define RE_SHY_GROUPS 150,6360
-#define RE_NO_NEWLINE_ANCHOR 153,6468
-#define RE_DEBUG 161,6884
-extern reg_syntax_t re_syntax_options;167,7170
-extern Lisp_Object re_match_object;172,7344
-extern size_t re_max_failures;176,7454
-#define RE_SYNTAX_EMACS 183,7684
-#define RE_SYNTAX_AWK 186,7780
-#define RE_SYNTAX_GNU_AWK 193,8084
-#define RE_SYNTAX_POSIX_AWK 197,8255
-#define RE_SYNTAX_GREP 201,8393
-#define RE_SYNTAX_EGREP 206,8549
-#define RE_SYNTAX_POSIX_EGREP 212,8765
-#define RE_SYNTAX_ED 216,8910
-#define RE_SYNTAX_SED 218,8954
-#define _RE_SYNTAX_POSIX_COMMON 221,9072
-#define RE_SYNTAX_POSIX_BASIC 225,9215
-#define RE_SYNTAX_POSIX_MINIMAL_BASIC 231,9508
-#define RE_SYNTAX_POSIX_EXTENDED 234,9598
-#define RE_SYNTAX_POSIX_MINIMAL_EXTENDED 242,9967
-# undef RE_DUP_MAX253,10454
-#define RE_DUP_MAX 256,10540
-#define REG_EXTENDED 263,10762
-#define REG_ICASE 267,10886
-#define REG_NEWLINE 272,11070
-#define REG_NOSUB 276,11248
-#define REG_NOTBOL 286,11614
-#define REG_NOTEOL 289,11688
- REG_ENOSYS 297,11859
- REG_NOERROR 300,11941
- REG_NOMATCH,301,11976
- REG_BADPAT,305,12123
- REG_ECOLLATE,306,12162
- REG_ECTYPE,307,12203
- REG_EESCAPE,308,12255
- REG_ESUBREG,309,12298
- REG_EBRACK,310,12345
- REG_EPAREN,311,12391
- REG_EBRACE,312,12436
- REG_BADBR,313,12472
- REG_ERANGE,314,12519
- REG_ESPACE,315,12560
- REG_BADRPT,316,12601
- REG_EEND,319,12693
- REG_ESIZE,320,12728
- REG_ERPAREN,321,12790
- REG_ERANGEX 322,12859
-} reg_errcode_t;323,12911
-# define RE_TRANSLATE_TYPE 332,13273
-struct re_pattern_buffer335,13315
-#define REGS_UNALLOCATED 376,14889
-#define REGS_REALLOCATE 377,14916
-#define REGS_FIXED 378,14942
-typedef struct re_pattern_buffer regex_t;416,16098
-typedef ssize_t regoff_t;423,16492
-struct re_registers428,16652
-# define RE_NREGS 440,16942
-} regmatch_t;451,17317
-extern reg_syntax_t re_set_syntax 457,17512
-extern const char *re_compile_pattern re_compile_pattern462,17776
-extern int re_compile_fastmap 469,18058
-extern regoff_t re_search 477,18466
-extern regoff_t re_search_2 485,18781
-extern regoff_t re_match 495,19177
-extern regoff_t re_match_2 501,19407
-extern void re_set_registers 520,20197
-extern char *re_comp re_comp528,20469
-extern int re_exec 529,20506
-# define _Restrict_ 540,20886
-# define _Restrict_ 542,20979
-# define _Restrict_544,21018
-# define _Restrict_arr_ 555,21418
-# define _Restrict_arr_557,21461
-extern reg_errcode_t regcomp 562,21530
-extern reg_errcode_t regexec 566,21656
-extern size_t regerror 571,21850
-extern void regfree 574,21956
-# define CHAR_CLASS_MAX_LENGTH 593,22470
-# define CHAR_CLASS_MAX_LENGTH 597,22648
-typedef wctype_t re_wctype_t;599,22692
-typedef wchar_t re_wchar_t;600,22722
-# define re_wctype 601,22750
-# define re_iswctype 602,22776
-# define re_wctype_to_bit(603,22806
-# define CHAR_CLASS_MAX_LENGTH 605,22844
-# define btowc(606,22906
-typedef enum { RECC_ERROR 609,22953
- RECC_ALNUM,610,22984
- RECC_ALNUM, RECC_ALPHA,610,22984
- RECC_ALNUM, RECC_ALPHA, RECC_WORD,610,22984
- RECC_GRAPH,611,23027
- RECC_GRAPH, RECC_PRINT,611,23027
- RECC_LOWER,612,23059
- RECC_LOWER, RECC_UPPER,612,23059
- RECC_PUNCT,613,23091
- RECC_PUNCT, RECC_CNTRL,613,23091
- RECC_DIGIT,614,23123
- RECC_DIGIT, RECC_XDIGIT,614,23123
- RECC_BLANK,615,23156
- RECC_BLANK, RECC_SPACE,615,23156
- RECC_MULTIBYTE,616,23188
- RECC_MULTIBYTE, RECC_NONASCII,616,23188
- RECC_ASCII,617,23227
- RECC_ASCII, RECC_UNIBYTE617,23227
-} re_wctype_t;618,23260
-extern char re_iswctype 620,23276
-extern re_wctype_t re_wctype 621,23329
-typedef int re_wchar_t;623,23387
-extern void re_set_whitespace_regexp 625,23412
+#define _REGEX_H 21,837
+typedef unsigned long reg_syntax_t;43,1578
+#define RE_BACKSLASH_ESCAPE_IN_LISTS 47,1750
+#define RE_BK_PLUS_QM 52,1970
+#define RE_CHAR_CLASSES 58,2299
+#define RE_CONTEXT_INDEP_ANCHORS 72,3033
+#define RE_CONTEXT_INDEP_OPS 80,3459
+#define RE_CONTEXT_INVALID_OPS 84,3659
+#define RE_DOT_NEWLINE 88,3802
+#define RE_DOT_NOT_NULL 92,3938
+#define RE_HAT_LISTS_NOT_NEWLINE 96,4083
+#define RE_INTERVALS 101,4293
+#define RE_LIMITED_OPS 105,4442
+#define RE_NEWLINE_ALT 109,4584
+#define RE_NO_BK_BRACES 114,4774
+#define RE_NO_BK_PARENS 118,4965
+#define RE_NO_BK_REFS 122,5121
+#define RE_NO_BK_VBAR 126,5317
+#define RE_NO_EMPTY_RANGES 132,5611
+#define RE_UNMATCHED_RIGHT_PAREN_ORD 136,5767
+#define RE_NO_POSIX_BACKTRACKING 140,5938
+#define RE_NO_GNU_OPS 144,6134
+#define RE_FRUGAL 147,6254
+#define RE_SHY_GROUPS 150,6361
+#define RE_NO_NEWLINE_ANCHOR 153,6469
+#define RE_DEBUG 161,6885
+extern reg_syntax_t re_syntax_options;167,7171
+extern Lisp_Object re_match_object;172,7345
+extern size_t re_max_failures;176,7455
+#define RE_SYNTAX_EMACS 183,7685
+#define RE_SYNTAX_AWK 186,7781
+#define RE_SYNTAX_GNU_AWK 193,8085
+#define RE_SYNTAX_POSIX_AWK 197,8256
+#define RE_SYNTAX_GREP 201,8394
+#define RE_SYNTAX_EGREP 206,8550
+#define RE_SYNTAX_POSIX_EGREP 212,8766
+#define RE_SYNTAX_ED 216,8911
+#define RE_SYNTAX_SED 218,8955
+#define _RE_SYNTAX_POSIX_COMMON 221,9073
+#define RE_SYNTAX_POSIX_BASIC 225,9216
+#define RE_SYNTAX_POSIX_MINIMAL_BASIC 231,9509
+#define RE_SYNTAX_POSIX_EXTENDED 234,9599
+#define RE_SYNTAX_POSIX_MINIMAL_EXTENDED 242,9968
+# undef RE_DUP_MAX253,10455
+#define RE_DUP_MAX 256,10541
+#define REG_EXTENDED 263,10763
+#define REG_ICASE 267,10887
+#define REG_NEWLINE 272,11071
+#define REG_NOSUB 276,11249
+#define REG_NOTBOL 286,11615
+#define REG_NOTEOL 289,11689
+ REG_ENOSYS 297,11860
+ REG_NOERROR 300,11942
+ REG_NOMATCH,301,11977
+ REG_BADPAT,305,12124
+ REG_ECOLLATE,306,12163
+ REG_ECTYPE,307,12204
+ REG_EESCAPE,308,12256
+ REG_ESUBREG,309,12299
+ REG_EBRACK,310,12346
+ REG_EPAREN,311,12392
+ REG_EBRACE,312,12437
+ REG_BADBR,313,12473
+ REG_ERANGE,314,12520
+ REG_ESPACE,315,12561
+ REG_BADRPT,316,12602
+ REG_EEND,319,12694
+ REG_ESIZE,320,12729
+ REG_ERPAREN,321,12791
+ REG_ERANGEX 322,12860
+} reg_errcode_t;323,12912
+# define RE_TRANSLATE_TYPE 332,13274
+struct re_pattern_buffer335,13316
+#define REGS_UNALLOCATED 376,14890
+#define REGS_REALLOCATE 377,14917
+#define REGS_FIXED 378,14943
+typedef struct re_pattern_buffer regex_t;416,16099
+typedef ssize_t regoff_t;423,16493
+struct re_registers428,16653
+# define RE_NREGS 440,16943
+} regmatch_t;451,17318
+extern reg_syntax_t re_set_syntax 457,17513
+extern const char *re_compile_pattern re_compile_pattern462,17777
+extern int re_compile_fastmap 469,18059
+extern regoff_t re_search 477,18467
+extern regoff_t re_search_2 485,18782
+extern regoff_t re_match 495,19178
+extern regoff_t re_match_2 501,19408
+extern void re_set_registers 520,20198
+extern char *re_comp re_comp528,20470
+extern int re_exec 529,20507
+# define _Restrict_ 540,20887
+# define _Restrict_ 542,20980
+# define _Restrict_544,21019
+# define _Restrict_arr_ 555,21419
+# define _Restrict_arr_557,21462
+extern reg_errcode_t regcomp 562,21531
+extern reg_errcode_t regexec 566,21657
+extern size_t regerror 571,21851
+extern void regfree 574,21957
+# define CHAR_CLASS_MAX_LENGTH 593,22471
+# define CHAR_CLASS_MAX_LENGTH 597,22649
+typedef wctype_t re_wctype_t;599,22693
+typedef wchar_t re_wchar_t;600,22723
+# define re_wctype 601,22751
+# define re_iswctype 602,22777
+# define re_wctype_to_bit(603,22807
+# define CHAR_CLASS_MAX_LENGTH 605,22845
+# define btowc(606,22907
+typedef enum { RECC_ERROR 609,22954
+ RECC_ALNUM,610,22985
+ RECC_ALNUM, RECC_ALPHA,610,22985
+ RECC_ALNUM, RECC_ALPHA, RECC_WORD,610,22985
+ RECC_GRAPH,611,23028
+ RECC_GRAPH, RECC_PRINT,611,23028
+ RECC_LOWER,612,23060
+ RECC_LOWER, RECC_UPPER,612,23060
+ RECC_PUNCT,613,23092
+ RECC_PUNCT, RECC_CNTRL,613,23092
+ RECC_DIGIT,614,23124
+ RECC_DIGIT, RECC_XDIGIT,614,23124
+ RECC_BLANK,615,23157
+ RECC_BLANK, RECC_SPACE,615,23157
+ RECC_MULTIBYTE,616,23189
+ RECC_MULTIBYTE, RECC_NONASCII,616,23189
+ RECC_ASCII,617,23228
+ RECC_ASCII, RECC_UNIBYTE617,23228
+} re_wctype_t;618,23261
+extern char re_iswctype 620,23277
+extern re_wctype_t re_wctype 621,23330
+typedef int re_wchar_t;623,23388
+extern void re_set_whitespace_regexp 625,23413
c-src/emacs/src/keyboard.c,17467
-volatile int interrupt_input_blocked;76,1808
-volatile bool pending_signals;80,1944
-#define KBD_BUFFER_SIZE 82,1976
-KBOARD *initial_kboard;initial_kboard84,2006
-KBOARD *current_kboard;current_kboard85,2030
-static KBOARD *all_kboards;all_kboards86,2054
-static bool single_kboard;89,2154
-#define NUM_RECENT_KEYS 91,2182
-static int recent_keys_index;94,2269
-static int total_keys;97,2357
-static Lisp_Object recent_keys;100,2443
-Lisp_Object this_command_keys;107,2777
-ptrdiff_t this_command_key_count;108,2808
-static bool this_command_key_count_reset;112,2922
-static Lisp_Object raw_keybuf;116,3074
-static int raw_keybuf_count;117,3105
-#define GROW_RAW_KEYBUF 119,3135
-static ptrdiff_t this_single_command_key_start;125,3350
-static ptrdiff_t before_command_key_count;129,3498
-static ptrdiff_t before_command_echo_length;130,3541
-sigjmp_buf return_to_command_loop;135,3677
-static Lisp_Object recover_top_level_message;138,3791
-static Lisp_Object regular_top_level_message;143,3930
-static sys_jmp_buf getcjmp;147,4031
-bool waiting_for_input;150,4095
-static bool echoing;154,4186
-static struct kboard *ok_to_echo_at_next_pause;ok_to_echo_at_next_pause159,4328
-struct kboard *echo_kboard;echo_kboard166,4632
-Lisp_Object echo_message_buffer;171,4744
-bool immediate_quit;174,4837
-int quit_char;192,5623
-EMACS_INT command_loop_level;195,5680
-Lisp_Object unread_switch_frame;204,6108
-static ptrdiff_t last_non_minibuf_size;207,6216
-uintmax_t num_input_events;210,6334
-static EMACS_INT last_auto_save;214,6428
-static ptrdiff_t last_point_position;217,6523
-Lisp_Object internal_last_event_frame;228,7028
-static Lisp_Object read_key_sequence_cmd;232,7168
-static Lisp_Object read_key_sequence_remapped;233,7210
-static FILE *dribble;dribble236,7310
-bool input_pending;239,7368
-static bool input_was_pending;287,10022
-static struct input_event kbd_buffer[kbd_buffer291,10107
-static struct input_event *kbd_fetch_ptr;kbd_fetch_ptr297,10386
-static struct input_event * volatile kbd_store_ptr;302,10601
-static void recursive_edit_unwind 313,11088
-static Lisp_Object command_loop 314,11144
-static void echo_now 316,11185
-static ptrdiff_t echo_length 317,11214
-unsigned timers_run;320,11296
-struct timespec *input_available_clear_time;input_available_clear_time324,11408
-bool interrupt_input;328,11573
-bool interrupts_deferred;331,11671
-static struct timespec timer_idleness_start_time;335,11746
-static struct timespec timer_last_idleness_start_time;340,11916
-#define READABLE_EVENTS_DO_TIMERS_NOW 346,12046
-#define READABLE_EVENTS_FILTER_EVENTS 347,12094
-#define READABLE_EVENTS_IGNORE_SQUEEZABLES 348,12142
-static void (*keyboard_init_hook)keyboard_init_hook351,12264
-static bool get_input_pending 353,12307
-static bool readable_events 354,12344
-static Lisp_Object read_char_x_menu_prompt 355,12379
-static Lisp_Object read_char_minibuf_menu_prompt 357,12502
-static Lisp_Object make_lispy_event 358,12571
-static Lisp_Object make_lispy_movement 359,12631
-static Lisp_Object modify_event_symbol 363,12840
-static Lisp_Object make_lispy_switch_frame 366,13050
-static Lisp_Object make_lispy_focus_in 367,13108
-static Lisp_Object make_lispy_focus_out 369,13188
-static bool help_char_p 371,13275
-static void save_getcjmp 372,13314
-static void restore_getcjmp 373,13354
-static Lisp_Object apply_modifiers 374,13397
-static void clear_event 375,13452
-static void restore_kboard_configuration 376,13500
-static void deliver_input_available_signal 378,13568
-static void handle_interrupt 380,13631
-static _Noreturn void quit_throw_to_read_char 381,13668
-static void process_special_events 382,13722
-static void timer_start_idle 383,13765
-static void timer_stop_idle 384,13802
-static void timer_resume_idle 385,13838
-static void deliver_user_signal 386,13876
-static char *find_user_signal_name find_user_signal_name387,13915
-static void store_user_signal_events 388,13957
-kset_echo_string 392,14088
-kset_kbd_queue 397,14184
-kset_keyboard_translate_table 402,14276
-kset_last_prefix_arg 407,14399
-kset_last_repeatable_command 412,14504
-kset_local_function_key_map 417,14625
-kset_overriding_terminal_local_map 422,14744
-kset_real_last_command 427,14877
-kset_system_key_syms 432,14986
-echo_add_key 443,15249
-echo_char 527,17527
-echo_dash 541,17813
-echo_now 586,19140
-cancel_echoing 635,20614
-echo_length 648,20922
-echo_truncate 660,21253
-add_command_key 672,21582
-recursive_edit_1 697,22406
-record_auto_save 742,23848
-force_auto_save_soon 751,24016
-DEFUN ("recursive-edit", Frecursive_edit,759,24137
-DEFUN ("recursive-edit", Frecursive_edit,recursive-edit759,24137
-recursive_edit_unwind 804,25747
-any_kboard_state 817,26013
-single_kboard_state 838,26665
-not_single_kboard_state 848,26803
-struct kboard_stack858,27065
-static struct kboard_stack *kboard_stack;kboard_stack864,27138
-push_kboard 867,27186
-pop_kboard 879,27375
-temporarily_switch_to_single_kboard 914,28263
-record_single_kboard_state 943,29437
-restore_kboard_configuration 952,29621
-cmd_error 970,30077
-cmd_error_internal 1024,31510
-DEFUN ("command-error-default-function", Fcommand_error_default_function,1043,32030
-DEFUN ("command-error-default-function", Fcommand_error_default_function,command-error-default-function1043,32030
-static Lisp_Object command_loop_2 1086,33637
-static Lisp_Object top_level_1 1087,33686
-command_loop 1094,33916
-command_loop_2 1134,35135
-top_level_2 1146,35339
-top_level_1 1152,35417
-DEFUN ("top-level", Ftop_level,1164,35787
-DEFUN ("top-level", Ftop_level,top-level1164,35787
-user_error 1183,36288
-DEFUN ("exit-recursive-edit", Fexit_recursive_edit,1189,36429
-DEFUN ("exit-recursive-edit", Fexit_recursive_edit,exit-recursive-edit1189,36429
-DEFUN ("abort-recursive-edit", Fabort_recursive_edit,1201,36819
-DEFUN ("abort-recursive-edit", Fabort_recursive_edit,abort-recursive-edit1201,36819
-tracking_off 1216,37281
-DEFUN ("internal--track-mouse", Ftrack_mouse,1234,37816
-DEFUN ("internal--track-mouse", Ftrack_mouse,track-mouse1234,37816
-bool ignore_mouse_drag_p;1256,38392
-some_mouse_moved 1259,38441
-static int read_key_sequence 1282,38799
-static void adjust_point_for_property 1284,38917
-Lisp_Object last_undo_boundary;1287,39032
-command_loop_1 1294,39273
-read_menu_command 1649,50889
-adjust_point_for_property 1678,51617
-safe_run_hooks_1 1831,57339
-safe_run_hooks_error 1841,57569
-safe_run_hook_funcall 1878,58576
-safe_run_hooks 1893,59058
-int poll_suppress_count;1908,59397
-static struct atimer *poll_timer;poll_timer1915,59487
-poll_for_input_1 1919,59589
-poll_for_input 1930,59789
-start_polling 1942,60053
-input_polling_used 1979,61091
-stop_polling 1994,61390
-set_poll_suppress_count 2009,61759
-bind_polling_period 2029,62141
-make_ctrl_char 2048,62492
-show_help_echo 2113,64455
-static Lisp_Object kbd_buffer_get_event 2152,65484
-static void record_char 2154,65596
-static Lisp_Object help_form_saved_window_configs;2156,65638
-read_char_help_form_unwind 2158,65701
-#define STOP_POLLING 2166,65959
-#define RESUME_POLLING 2170,66084
-read_event_from_main_queue 2175,66229
-read_decoded_event_from_main_queue 2249,68417
-#define MAX_ENCODED_BYTES 2254,68664
-echo_keystrokes_p 2342,71556
-read_char 2376,72848
-record_menu_key 3225,98949
-help_char_p 3258,99674
-record_char 3273,99953
-save_getcjmp 3412,104235
-restore_getcjmp 3418,104326
-readable_events 3430,104697
-int stop_character EXTERNALLY_VISIBLE;3497,106437
-event_to_kboard 3500,106493
-kbd_buffer_nr_stored 3522,107142
-kbd_buffer_store_event 3534,107483
-kbd_buffer_store_event_hold 3550,108025
-kbd_buffer_unget_event 3684,111617
-#define INPUT_EVENT_POS_MAX 3698,112018
-#define INPUT_EVENT_POS_MIN 3701,112147
-position_to_Time 3706,112287
-Time_to_position 3716,112514
-gen_help_event 3738,113171
-kbd_buffer_store_help_event 3756,113611
-discard_mouse_events 3773,113976
-kbd_buffer_events_waiting 3803,114711
-clear_event 3823,115068
-kbd_buffer_get_event 3836,115408
-process_special_events 4258,127881
-swallow_events 4322,129705
-timer_start_idle 4339,130098
-timer_stop_idle 4355,130576
-timer_resume_idle 4363,130720
-struct input_event last_timer_event EXTERNALLY_VISIBLE;4372,130912
-Lisp_Object pending_funcalls;4377,131172
-decode_timer 4381,131293
-timer_check_2 4414,132246
-timer_check 4572,136817
-DEFUN ("current-idle-time", Fcurrent_idle_time,4607,137662
-DEFUN ("current-idle-time", Fcurrent_idle_time,current-idle-time4607,137662
-static Lisp_Object accent_key_syms;4625,138239
-static Lisp_Object func_key_syms;4626,138275
-static Lisp_Object mouse_syms;4627,138309
-static Lisp_Object wheel_syms;4628,138340
-static Lisp_Object drag_n_drop_syms;4629,138371
-static const int lispy_accent_codes[lispy_accent_codes4634,138516
-static const char *const lispy_accent_keys[lispy_accent_keys4741,139878
-#define FUNCTION_KEY_OFFSET 4766,140314
-const char *const lispy_function_keys[lispy_function_keys4768,140347
-static const char *const lispy_multimedia_keys[lispy_multimedia_keys4962,148901
-static const char *const lispy_kana_keys[lispy_kana_keys5026,150135
-#define FUNCTION_KEY_OFFSET 5061,151751
-static const char *const lispy_function_keys[lispy_function_keys5065,151894
-#define ISO_FUNCTION_KEY_OFFSET 5149,154429
-static const char *const iso_lispy_function_keys[iso_lispy_function_keys5151,154469
-static Lisp_Object Vlispy_mouse_stem;5172,155328
-static const char *const lispy_wheel_names[lispy_wheel_names5174,155367
-static const char *const lispy_drag_n_drop_names[lispy_drag_n_drop_names5181,155619
-static short const scroll_bar_parts[scroll_bar_parts5189,155885
-static Lisp_Object button_down_location;5210,156910
-static int last_mouse_button;5215,157065
-static int last_mouse_x;5216,157095
-static int last_mouse_y;5217,157120
-static Time button_down_time;5218,157145
-static int double_click_count;5222,157229
-make_lispy_position 5228,157390
-toolkit_menubar_in_use 5456,163953
-make_scroll_bar_position 5469,164321
-make_lispy_event 5485,164967
-make_lispy_movement 6104,183531
-make_lispy_switch_frame 6131,184262
-make_lispy_focus_in 6137,184369
-make_lispy_focus_out 6145,184495
-parse_modifiers_uncached 6163,184945
-#define SINGLE_LETTER_MOD(6185,185465
-#undef SINGLE_LETTER_MOD6212,185906
-#define MULTI_LETTER_MOD(6214,185932
-#undef MULTI_LETTER_MOD6231,186400
-apply_modifiers_uncached 6273,187574
-static const char *const modifier_names[modifier_names6319,189193
-#define NUM_MOD_NAMES 6325,189399
-static Lisp_Object modifier_symbols;6327,189449
-lispy_modifier_list 6331,189586
-#define KEY_TO_CHAR(6353,190252
-parse_modifiers 6356,190328
-DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,6399,191517
-DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,event-symbol-parse-modifiers6399,191517
-apply_modifiers 6422,192391
-reorder_modifiers 6491,194720
-modify_event_symbol 6536,196528
-DEFUN ("event-convert-list", Fevent_convert_list,6628,199244
-DEFUN ("event-convert-list", Fevent_convert_list,event-convert-list6628,199244
-parse_solitary_modifier 6695,201135
-#define SINGLE_LETTER_MOD(6701,201258
-#define MULTI_LETTER_MOD(6705,201343
-#undef SINGLE_LETTER_MOD6763,202641
-#undef MULTI_LETTER_MOD6764,202666
-lucid_event_type_list_p 6775,202889
-get_input_pending 6814,203960
-record_asynch_buffer_change 6834,204579
-gobble_input 6872,205702
-tty_read_avail_input 6967,208310
-handle_async_input 7149,214039
-process_pending_signals 7165,214359
-unblock_input_to 7177,214645
-unblock_input 7200,215277
-totally_unblock_input 7209,215445
-handle_input_available_signal 7217,215529
-deliver_input_available_signal 7226,215700
-struct user_signal_info7235,215865
-static struct user_signal_info *user_signals user_signals7250,216090
-add_user_signal 7253,216149
-handle_user_signal 7275,216598
-deliver_user_signal 7316,217558
-find_user_signal_name 7322,217659
-store_user_signal_events 7334,217841
-static void menu_bar_item 7362,218341
-static Lisp_Object menu_bar_one_keymap_changed_items;7363,218416
-static Lisp_Object menu_bar_items_vector;7368,218630
-static int menu_bar_items_index;7369,218672
-static const char *separator_names[separator_names7372,218707
-menu_separator_name_p 7393,219148
-menu_bar_items 7426,219852
-Lisp_Object item_properties;7568,224603
-menu_bar_item 7571,224645
-menu_item_eval_property_1 7647,227175
-eval_dyn 7658,227465
-menu_item_eval_property 7666,227675
-parse_menu_item 7686,228341
-static Lisp_Object tool_bar_items_vector;7965,236336
-static Lisp_Object tool_bar_item_properties;7970,236510
-static int ntool_bar_items;7974,236606
-static void init_tool_bar_items 7978,236664
-static void process_tool_bar_item 7979,236711
-static bool parse_tool_bar_item 7981,236801
-static void append_tool_bar_item 7982,236861
-tool_bar_items 7990,237083
-process_tool_bar_item 8075,239892
-#define PROP(8112,240969
-set_prop 8114,241038
-parse_tool_bar_item 8167,242453
-#undef PROP8379,248844
-init_tool_bar_items 8387,248969
-append_tool_bar_item 8401,249261
-read_char_x_menu_prompt 8443,250771
-read_char_minibuf_menu_prompt 8503,252445
-#define PUSH_C_STR(8527,253014
-follow_key 8726,258553
-active_maps 8733,258695
-typedef struct keyremap8742,259021
-} keyremap;8754,259464
-access_keymap_keyremap 8764,259808
-keyremap_step 8811,261450
-test_undefined 8867,262934
-read_key_sequence 8916,264861
-read_key_sequence_vs 9826,295821
-DEFUN ("read-key-sequence", Fread_key_sequence,9885,297294
-DEFUN ("read-key-sequence", Fread_key_sequence,read-key-sequence9885,297294
-DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,9938,299982
-DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,read-key-sequence-vector9938,299982
-detect_input_pending 9950,300488
-detect_input_pending_ignore_squeezables 9959,300654
-detect_input_pending_run_timers 9967,300870
-clear_input_pending 9985,301362
-requeued_events_pending_p 9997,301732
-DEFUN ("input-pending-p", Finput_pending_p,10002,301813
-DEFUN ("input-pending-p", Finput_pending_p,input-pending-p10002,301813
-DEFUN ("recent-keys", Frecent_keys,10024,302596
-DEFUN ("recent-keys", Frecent_keys,recent-keys10024,302596
-DEFUN ("this-command-keys", Fthis_command_keys,10055,303517
-DEFUN ("this-command-keys", Fthis_command_keys,this-command-keys10055,303517
-DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,10068,303958
-DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,this-command-keys-vector10068,303958
-DEFUN ("this-single-command-keys", Fthis_single_command_keys,10080,304380
-DEFUN ("this-single-command-keys", Fthis_single_command_keys,this-single-command-keys10080,304380
-DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,10096,304955
-DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,this-single-command-raw-keys10096,304955
-DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,10109,305495
-DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,reset-this-command-lengths10109,305495
-DEFUN ("clear-this-command-keys", Fclear_this_command_keys,10136,306510
-DEFUN ("clear-this-command-keys", Fclear_this_command_keys,clear-this-command-keys10136,306510
-DEFUN ("recursion-depth", Frecursion_depth,10158,307069
-DEFUN ("recursion-depth", Frecursion_depth,recursion-depth10158,307069
-DEFUN ("open-dribble-file", Fopen_dribble_file,10169,307406
-DEFUN ("open-dribble-file", Fopen_dribble_file,open-dribble-file10169,307406
-DEFUN ("discard-input", Fdiscard_input,10203,308447
-DEFUN ("discard-input", Fdiscard_input,discard-input10203,308447
-DEFUN ("suspend-emacs", Fsuspend_emacs,10225,308949
-DEFUN ("suspend-emacs", Fsuspend_emacs,suspend-emacs10225,308949
-stuff_buffered_input 10285,311045
-set_waiting_for_input 10323,312016
-clear_waiting_for_input 10337,312390
-handle_interrupt_signal 10351,312754
-deliver_interrupt_signal 10378,313642
-static int volatile force_quit_count;10387,313932
-handle_interrupt 10401,314414
-quit_throw_to_read_char 10541,318711
-DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,10562,319288
-DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,set-input-interrupt-mode10562,319288
-DEFUN ("set-output-flow-control", Fset_output_flow_control,10609,320516
-DEFUN ("set-output-flow-control", Fset_output_flow_control,set-output-flow-control10609,320516
-DEFUN ("set-input-meta-mode", Fset_input_meta_mode,10643,321432
-DEFUN ("set-input-meta-mode", Fset_input_meta_mode,set-input-meta-mode10643,321432
-DEFUN ("set-quit-char", Fset_quit_char,10694,322706
-DEFUN ("set-quit-char", Fset_quit_char,set-quit-char10694,322706
-DEFUN ("set-input-mode", Fset_input_mode,10729,323570
-DEFUN ("set-input-mode", Fset_input_mode,set-input-mode10729,323570
-DEFUN ("current-input-mode", Fcurrent_input_mode,10750,324459
-DEFUN ("current-input-mode", Fcurrent_input_mode,current-input-mode10750,324459
-DEFUN ("posn-at-x-y", Fposn_at_x_y,10787,325837
-DEFUN ("posn-at-x-y", Fposn_at_x_y,posn-at-x-y10787,325837
-DEFUN ("posn-at-point", Fposn_at_point,10824,327060
-DEFUN ("posn-at-point", Fposn_at_point,posn-at-point10824,327060
-init_kboard 10861,328214
-allocate_kboard 10893,329284
-wipe_kboard 10909,329637
-delete_kboard 10917,329751
-init_keyboard 10942,330281
-struct event_head11021,332696
-static const struct event_head head_table[head_table11027,332747
-syms_of_keyboard 11045,333577
-keys_of_keyboard 11841,367115
-mark_kboards 11916,370434
+volatile int interrupt_input_blocked;76,1809
+volatile bool pending_signals;80,1945
+#define KBD_BUFFER_SIZE 82,1977
+KBOARD *initial_kboard;initial_kboard84,2007
+KBOARD *current_kboard;current_kboard85,2031
+static KBOARD *all_kboards;all_kboards86,2055
+static bool single_kboard;89,2155
+#define NUM_RECENT_KEYS 91,2183
+static int recent_keys_index;94,2270
+static int total_keys;97,2358
+static Lisp_Object recent_keys;100,2444
+Lisp_Object this_command_keys;107,2778
+ptrdiff_t this_command_key_count;108,2809
+static bool this_command_key_count_reset;112,2923
+static Lisp_Object raw_keybuf;116,3075
+static int raw_keybuf_count;117,3106
+#define GROW_RAW_KEYBUF 119,3136
+static ptrdiff_t this_single_command_key_start;125,3351
+static ptrdiff_t before_command_key_count;129,3499
+static ptrdiff_t before_command_echo_length;130,3542
+sigjmp_buf return_to_command_loop;135,3678
+static Lisp_Object recover_top_level_message;138,3792
+static Lisp_Object regular_top_level_message;143,3931
+static sys_jmp_buf getcjmp;147,4032
+bool waiting_for_input;150,4096
+static bool echoing;154,4187
+static struct kboard *ok_to_echo_at_next_pause;ok_to_echo_at_next_pause159,4329
+struct kboard *echo_kboard;echo_kboard166,4633
+Lisp_Object echo_message_buffer;171,4745
+bool immediate_quit;174,4838
+int quit_char;192,5624
+EMACS_INT command_loop_level;195,5681
+Lisp_Object unread_switch_frame;204,6109
+static ptrdiff_t last_non_minibuf_size;207,6217
+uintmax_t num_input_events;210,6335
+static EMACS_INT last_auto_save;214,6429
+static ptrdiff_t last_point_position;217,6524
+Lisp_Object internal_last_event_frame;228,7029
+static Lisp_Object read_key_sequence_cmd;232,7169
+static Lisp_Object read_key_sequence_remapped;233,7211
+static FILE *dribble;dribble236,7311
+bool input_pending;239,7369
+static bool input_was_pending;287,10023
+static struct input_event kbd_buffer[kbd_buffer291,10108
+static struct input_event *kbd_fetch_ptr;kbd_fetch_ptr297,10387
+static struct input_event * volatile kbd_store_ptr;302,10602
+static void recursive_edit_unwind 313,11089
+static Lisp_Object command_loop 314,11145
+static void echo_now 316,11186
+static ptrdiff_t echo_length 317,11215
+unsigned timers_run;320,11297
+struct timespec *input_available_clear_time;input_available_clear_time324,11409
+bool interrupt_input;328,11574
+bool interrupts_deferred;331,11672
+static struct timespec timer_idleness_start_time;335,11747
+static struct timespec timer_last_idleness_start_time;340,11917
+#define READABLE_EVENTS_DO_TIMERS_NOW 346,12047
+#define READABLE_EVENTS_FILTER_EVENTS 347,12095
+#define READABLE_EVENTS_IGNORE_SQUEEZABLES 348,12143
+static void (*keyboard_init_hook)keyboard_init_hook351,12265
+static bool get_input_pending 353,12308
+static bool readable_events 354,12345
+static Lisp_Object read_char_x_menu_prompt 355,12380
+static Lisp_Object read_char_minibuf_menu_prompt 357,12503
+static Lisp_Object make_lispy_event 358,12572
+static Lisp_Object make_lispy_movement 359,12632
+static Lisp_Object modify_event_symbol 363,12841
+static Lisp_Object make_lispy_switch_frame 366,13051
+static Lisp_Object make_lispy_focus_in 367,13109
+static Lisp_Object make_lispy_focus_out 369,13189
+static bool help_char_p 371,13276
+static void save_getcjmp 372,13315
+static void restore_getcjmp 373,13355
+static Lisp_Object apply_modifiers 374,13398
+static void clear_event 375,13453
+static void restore_kboard_configuration 376,13501
+static void deliver_input_available_signal 378,13569
+static void handle_interrupt 380,13632
+static _Noreturn void quit_throw_to_read_char 381,13669
+static void process_special_events 382,13723
+static void timer_start_idle 383,13766
+static void timer_stop_idle 384,13803
+static void timer_resume_idle 385,13839
+static void deliver_user_signal 386,13877
+static char *find_user_signal_name find_user_signal_name387,13916
+static void store_user_signal_events 388,13958
+kset_echo_string 392,14089
+kset_kbd_queue 397,14185
+kset_keyboard_translate_table 402,14277
+kset_last_prefix_arg 407,14400
+kset_last_repeatable_command 412,14505
+kset_local_function_key_map 417,14626
+kset_overriding_terminal_local_map 422,14745
+kset_real_last_command 427,14878
+kset_system_key_syms 432,14987
+echo_add_key 443,15250
+echo_char 527,17528
+echo_dash 541,17814
+echo_now 586,19141
+cancel_echoing 635,20615
+echo_length 648,20923
+echo_truncate 660,21254
+add_command_key 672,21583
+recursive_edit_1 697,22407
+record_auto_save 742,23849
+force_auto_save_soon 751,24017
+DEFUN ("recursive-edit", Frecursive_edit,759,24138
+DEFUN ("recursive-edit", Frecursive_edit,recursive-edit759,24138
+recursive_edit_unwind 804,25751
+any_kboard_state 817,26017
+single_kboard_state 838,26669
+not_single_kboard_state 848,26807
+struct kboard_stack858,27069
+static struct kboard_stack *kboard_stack;kboard_stack864,27142
+push_kboard 867,27190
+pop_kboard 879,27379
+temporarily_switch_to_single_kboard 914,28267
+record_single_kboard_state 943,29441
+restore_kboard_configuration 952,29625
+cmd_error 970,30081
+cmd_error_internal 1024,31514
+DEFUN ("command-error-default-function", Fcommand_error_default_function,1043,32034
+DEFUN ("command-error-default-function", Fcommand_error_default_function,command-error-default-function1043,32034
+static Lisp_Object command_loop_2 1086,33641
+static Lisp_Object top_level_1 1087,33690
+command_loop 1094,33920
+command_loop_2 1134,35139
+top_level_2 1146,35343
+top_level_1 1152,35421
+DEFUN ("top-level", Ftop_level,1164,35791
+DEFUN ("top-level", Ftop_level,top-level1164,35791
+user_error 1183,36292
+DEFUN ("exit-recursive-edit", Fexit_recursive_edit,1189,36433
+DEFUN ("exit-recursive-edit", Fexit_recursive_edit,exit-recursive-edit1189,36433
+DEFUN ("abort-recursive-edit", Fabort_recursive_edit,1201,36823
+DEFUN ("abort-recursive-edit", Fabort_recursive_edit,abort-recursive-edit1201,36823
+tracking_off 1216,37285
+DEFUN ("internal--track-mouse", Ftrack_mouse,1234,37820
+DEFUN ("internal--track-mouse", Ftrack_mouse,track-mouse1234,37820
+bool ignore_mouse_drag_p;1256,38396
+some_mouse_moved 1259,38445
+static int read_key_sequence 1282,38803
+static void adjust_point_for_property 1284,38921
+Lisp_Object last_undo_boundary;1287,39036
+command_loop_1 1294,39277
+read_menu_command 1649,50893
+adjust_point_for_property 1678,51621
+safe_run_hooks_1 1831,57343
+safe_run_hooks_error 1841,57573
+safe_run_hook_funcall 1878,58580
+safe_run_hooks 1893,59062
+int poll_suppress_count;1908,59401
+static struct atimer *poll_timer;poll_timer1915,59491
+poll_for_input_1 1919,59593
+poll_for_input 1930,59793
+start_polling 1942,60057
+input_polling_used 1979,61095
+stop_polling 1994,61394
+set_poll_suppress_count 2009,61763
+bind_polling_period 2029,62145
+make_ctrl_char 2048,62496
+show_help_echo 2113,64459
+static Lisp_Object kbd_buffer_get_event 2152,65488
+static void record_char 2154,65600
+static Lisp_Object help_form_saved_window_configs;2156,65642
+read_char_help_form_unwind 2158,65705
+#define STOP_POLLING 2166,65963
+#define RESUME_POLLING 2170,66088
+read_event_from_main_queue 2175,66233
+read_decoded_event_from_main_queue 2249,68421
+#define MAX_ENCODED_BYTES 2254,68668
+echo_keystrokes_p 2342,71560
+read_char 2376,72852
+record_menu_key 3225,98953
+help_char_p 3258,99678
+record_char 3273,99957
+save_getcjmp 3412,104239
+restore_getcjmp 3418,104330
+readable_events 3430,104701
+int stop_character EXTERNALLY_VISIBLE;3497,106441
+event_to_kboard 3500,106497
+kbd_buffer_nr_stored 3522,107146
+kbd_buffer_store_event 3534,107487
+kbd_buffer_store_event_hold 3550,108029
+kbd_buffer_unget_event 3684,111621
+#define INPUT_EVENT_POS_MAX 3698,112022
+#define INPUT_EVENT_POS_MIN 3701,112151
+position_to_Time 3706,112291
+Time_to_position 3716,112518
+gen_help_event 3738,113175
+kbd_buffer_store_help_event 3756,113615
+discard_mouse_events 3773,113980
+kbd_buffer_events_waiting 3803,114715
+clear_event 3823,115072
+kbd_buffer_get_event 3836,115412
+process_special_events 4258,127885
+swallow_events 4322,129709
+timer_start_idle 4339,130102
+timer_stop_idle 4355,130580
+timer_resume_idle 4363,130724
+struct input_event last_timer_event EXTERNALLY_VISIBLE;4372,130916
+Lisp_Object pending_funcalls;4377,131176
+decode_timer 4381,131297
+timer_check_2 4414,132250
+timer_check 4572,136821
+DEFUN ("current-idle-time", Fcurrent_idle_time,4607,137666
+DEFUN ("current-idle-time", Fcurrent_idle_time,current-idle-time4607,137666
+static Lisp_Object accent_key_syms;4625,138243
+static Lisp_Object func_key_syms;4626,138279
+static Lisp_Object mouse_syms;4627,138313
+static Lisp_Object wheel_syms;4628,138344
+static Lisp_Object drag_n_drop_syms;4629,138375
+static const int lispy_accent_codes[lispy_accent_codes4634,138520
+static const char *const lispy_accent_keys[lispy_accent_keys4741,139882
+#define FUNCTION_KEY_OFFSET 4766,140318
+const char *const lispy_function_keys[lispy_function_keys4768,140351
+static const char *const lispy_multimedia_keys[lispy_multimedia_keys4962,148905
+static const char *const lispy_kana_keys[lispy_kana_keys5026,150139
+#define FUNCTION_KEY_OFFSET 5061,151755
+static const char *const lispy_function_keys[lispy_function_keys5065,151898
+#define ISO_FUNCTION_KEY_OFFSET 5149,154433
+static const char *const iso_lispy_function_keys[iso_lispy_function_keys5151,154473
+static Lisp_Object Vlispy_mouse_stem;5172,155332
+static const char *const lispy_wheel_names[lispy_wheel_names5174,155371
+static const char *const lispy_drag_n_drop_names[lispy_drag_n_drop_names5181,155623
+static short const scroll_bar_parts[scroll_bar_parts5189,155889
+static Lisp_Object button_down_location;5210,156914
+static int last_mouse_button;5215,157069
+static int last_mouse_x;5216,157099
+static int last_mouse_y;5217,157124
+static Time button_down_time;5218,157149
+static int double_click_count;5222,157233
+make_lispy_position 5228,157394
+toolkit_menubar_in_use 5456,163957
+make_scroll_bar_position 5469,164325
+make_lispy_event 5485,164971
+make_lispy_movement 6104,183534
+make_lispy_switch_frame 6131,184265
+make_lispy_focus_in 6137,184372
+make_lispy_focus_out 6145,184498
+parse_modifiers_uncached 6163,184948
+#define SINGLE_LETTER_MOD(6185,185468
+#undef SINGLE_LETTER_MOD6212,185909
+#define MULTI_LETTER_MOD(6214,185935
+#undef MULTI_LETTER_MOD6231,186403
+apply_modifiers_uncached 6273,187577
+static const char *const modifier_names[modifier_names6319,189196
+#define NUM_MOD_NAMES 6325,189402
+static Lisp_Object modifier_symbols;6327,189452
+lispy_modifier_list 6331,189589
+#define KEY_TO_CHAR(6353,190255
+parse_modifiers 6356,190331
+DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,6399,191520
+DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,event-symbol-parse-modifiers6399,191520
+apply_modifiers 6422,192394
+reorder_modifiers 6491,194723
+modify_event_symbol 6536,196531
+DEFUN ("event-convert-list", Fevent_convert_list,6628,199247
+DEFUN ("event-convert-list", Fevent_convert_list,event-convert-list6628,199247
+parse_solitary_modifier 6695,201138
+#define SINGLE_LETTER_MOD(6701,201261
+#define MULTI_LETTER_MOD(6705,201346
+#undef SINGLE_LETTER_MOD6763,202644
+#undef MULTI_LETTER_MOD6764,202669
+lucid_event_type_list_p 6775,202892
+get_input_pending 6814,203963
+record_asynch_buffer_change 6834,204582
+gobble_input 6872,205705
+tty_read_avail_input 6967,208313
+handle_async_input 7149,214042
+process_pending_signals 7165,214362
+unblock_input_to 7177,214648
+unblock_input 7200,215280
+totally_unblock_input 7209,215448
+handle_input_available_signal 7217,215532
+deliver_input_available_signal 7226,215703
+struct user_signal_info7235,215868
+static struct user_signal_info *user_signals user_signals7250,216093
+add_user_signal 7253,216152
+handle_user_signal 7275,216601
+deliver_user_signal 7316,217561
+find_user_signal_name 7322,217662
+store_user_signal_events 7334,217844
+static void menu_bar_item 7362,218344
+static Lisp_Object menu_bar_one_keymap_changed_items;7363,218419
+static Lisp_Object menu_bar_items_vector;7368,218633
+static int menu_bar_items_index;7369,218675
+static const char *separator_names[separator_names7372,218710
+menu_separator_name_p 7393,219151
+menu_bar_items 7426,219855
+Lisp_Object item_properties;7568,224606
+menu_bar_item 7571,224648
+menu_item_eval_property_1 7647,227178
+eval_dyn 7658,227468
+menu_item_eval_property 7666,227678
+parse_menu_item 7686,228344
+static Lisp_Object tool_bar_items_vector;7965,236339
+static Lisp_Object tool_bar_item_properties;7970,236513
+static int ntool_bar_items;7974,236609
+static void init_tool_bar_items 7978,236667
+static void process_tool_bar_item 7979,236714
+static bool parse_tool_bar_item 7981,236804
+static void append_tool_bar_item 7982,236864
+tool_bar_items 7990,237086
+process_tool_bar_item 8075,239895
+#define PROP(8112,240972
+set_prop 8114,241041
+parse_tool_bar_item 8167,242456
+#undef PROP8379,248847
+init_tool_bar_items 8387,248972
+append_tool_bar_item 8401,249264
+read_char_x_menu_prompt 8443,250774
+read_char_minibuf_menu_prompt 8503,252448
+#define PUSH_C_STR(8527,253017
+follow_key 8726,258556
+active_maps 8733,258698
+typedef struct keyremap8742,259024
+} keyremap;8754,259467
+access_keymap_keyremap 8764,259811
+keyremap_step 8811,261453
+test_undefined 8867,262937
+read_key_sequence 8916,264864
+read_key_sequence_vs 9826,295824
+DEFUN ("read-key-sequence", Fread_key_sequence,9885,297297
+DEFUN ("read-key-sequence", Fread_key_sequence,read-key-sequence9885,297297
+DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,9938,299985
+DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,read-key-sequence-vector9938,299985
+detect_input_pending 9950,300491
+detect_input_pending_ignore_squeezables 9959,300657
+detect_input_pending_run_timers 9967,300873
+clear_input_pending 9985,301365
+requeued_events_pending_p 9997,301735
+DEFUN ("input-pending-p", Finput_pending_p,10002,301816
+DEFUN ("input-pending-p", Finput_pending_p,input-pending-p10002,301816
+DEFUN ("recent-keys", Frecent_keys,10024,302599
+DEFUN ("recent-keys", Frecent_keys,recent-keys10024,302599
+DEFUN ("this-command-keys", Fthis_command_keys,10055,303520
+DEFUN ("this-command-keys", Fthis_command_keys,this-command-keys10055,303520
+DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,10068,303961
+DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,this-command-keys-vector10068,303961
+DEFUN ("this-single-command-keys", Fthis_single_command_keys,10080,304383
+DEFUN ("this-single-command-keys", Fthis_single_command_keys,this-single-command-keys10080,304383
+DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,10096,304958
+DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,this-single-command-raw-keys10096,304958
+DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,10109,305498
+DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,reset-this-command-lengths10109,305498
+DEFUN ("clear-this-command-keys", Fclear_this_command_keys,10136,306513
+DEFUN ("clear-this-command-keys", Fclear_this_command_keys,clear-this-command-keys10136,306513
+DEFUN ("recursion-depth", Frecursion_depth,10158,307072
+DEFUN ("recursion-depth", Frecursion_depth,recursion-depth10158,307072
+DEFUN ("open-dribble-file", Fopen_dribble_file,10169,307409
+DEFUN ("open-dribble-file", Fopen_dribble_file,open-dribble-file10169,307409
+DEFUN ("discard-input", Fdiscard_input,10203,308450
+DEFUN ("discard-input", Fdiscard_input,discard-input10203,308450
+DEFUN ("suspend-emacs", Fsuspend_emacs,10225,308952
+DEFUN ("suspend-emacs", Fsuspend_emacs,suspend-emacs10225,308952
+stuff_buffered_input 10285,311048
+set_waiting_for_input 10323,312019
+clear_waiting_for_input 10337,312393
+handle_interrupt_signal 10351,312757
+deliver_interrupt_signal 10378,313645
+static int volatile force_quit_count;10387,313935
+handle_interrupt 10401,314417
+quit_throw_to_read_char 10541,318714
+DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,10562,319291
+DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,set-input-interrupt-mode10562,319291
+DEFUN ("set-output-flow-control", Fset_output_flow_control,10609,320519
+DEFUN ("set-output-flow-control", Fset_output_flow_control,set-output-flow-control10609,320519
+DEFUN ("set-input-meta-mode", Fset_input_meta_mode,10643,321435
+DEFUN ("set-input-meta-mode", Fset_input_meta_mode,set-input-meta-mode10643,321435
+DEFUN ("set-quit-char", Fset_quit_char,10694,322709
+DEFUN ("set-quit-char", Fset_quit_char,set-quit-char10694,322709
+DEFUN ("set-input-mode", Fset_input_mode,10729,323573
+DEFUN ("set-input-mode", Fset_input_mode,set-input-mode10729,323573
+DEFUN ("current-input-mode", Fcurrent_input_mode,10750,324462
+DEFUN ("current-input-mode", Fcurrent_input_mode,current-input-mode10750,324462
+DEFUN ("posn-at-x-y", Fposn_at_x_y,10787,325840
+DEFUN ("posn-at-x-y", Fposn_at_x_y,posn-at-x-y10787,325840
+DEFUN ("posn-at-point", Fposn_at_point,10824,327063
+DEFUN ("posn-at-point", Fposn_at_point,posn-at-point10824,327063
+init_kboard 10861,328217
+allocate_kboard 10893,329287
+wipe_kboard 10909,329640
+delete_kboard 10917,329754
+init_keyboard 10942,330284
+struct event_head11021,332699
+static const struct event_head head_table[head_table11027,332750
+syms_of_keyboard 11045,333580
+keys_of_keyboard 11841,367118
+mark_kboards 11916,370437
c-src/emacs/src/lisp.h,33840
-#define EMACS_LISP_H22,800
-#define DECLARE_GDB_SYM(47,1421
-# define DEFINE_GDB_SYMBOL_BEGIN(49,1508
-# define DEFINE_GDB_SYMBOL_END(50,1578
-# define DEFINE_GDB_SYMBOL_BEGIN(52,1625
-# define DEFINE_GDB_SYMBOL_END(53,1702
-#undef min57,1790
-#undef max58,1801
-#define max(59,1812
-#define min(60,1854
-#define ARRAYELTS(63,1936
-#define GCTYPEBITS 67,2079
-DEFINE_GDB_SYMBOL_BEGIN GCTYPEBITS66,2037
-# define NONPOINTER_BITS 78,2567
-# define NONPOINTER_BITS 80,2600
-typedef int EMACS_INT;91,3023
-typedef unsigned int EMACS_UINT;92,3046
-# define EMACS_INT_MAX 93,3079
-# define pI 94,3111
-typedef long int EMACS_INT;96,3203
-typedef unsigned long EMACS_UINT;97,3231
-# define EMACS_INT_MAX 98,3265
-# define pI 99,3298
-typedef long long int EMACS_INT;103,3477
-typedef unsigned long long int EMACS_UINT;104,3510
-# define EMACS_INT_MAX 105,3553
-# define pI 106,3587
-enum { BOOL_VECTOR_BITS_PER_CHAR 114,3804
-#define BOOL_VECTOR_BITS_PER_CHAR 115,3840
-typedef size_t bits_word;123,4165
-# define BITS_WORD_MAX 124,4191
-enum { BITS_PER_BITS_WORD 125,4223
-typedef unsigned char bits_word;127,4290
-# define BITS_WORD_MAX 128,4323
-enum { BITS_PER_BITS_WORD 129,4386
-verify 131,4450
- BITS_PER_CHAR 136,4570
- BITS_PER_SHORT 137,4605
- BITS_PER_LONG 138,4657
- BITS_PER_EMACS_INT 139,4712
-typedef intmax_t printmax_t;148,5089
-typedef uintmax_t uprintmax_t;149,5118
-# define pMd 150,5149
-# define pMu 151,5170
-typedef EMACS_INT printmax_t;153,5197
-typedef EMACS_UINT uprintmax_t;154,5227
-# define pMd 155,5259
-# define pMu 156,5278
-# define pD 165,5664
-# define pD 167,5709
-# define pD 169,5756
-# define pD 171,5779
-# define eassert(200,7062
-# define eassume(201,7140
-extern _Noreturn void die 204,7206
-extern bool suppress_checking EXTERNALLY_VISIBLE;206,7268
-# define eassert(208,7319
-# define eassume(212,7450
-enum Lisp_Bits239,8519
-#define GCALIGNMENT 243,8647
- VALBITS 246,8742
- INTTYPEBITS 249,8838
- FIXNUM_BITS 252,8945
-#define VAL_MAX 263,9327
-#define USE_LSB_TAG 271,9777
-DEFINE_GDB_SYMBOL_BEGIN USE_LSB_TAG270,9733
-# define alignas(281,10077
-# define GCALIGNED 288,10227
-# define GCALIGNED 290,10292
-# define lisp_h_XLI(327,11642
-# define lisp_h_XIL(328,11673
-# define lisp_h_XLI(330,11724
-# define lisp_h_XIL(331,11751
-#define lisp_h_CHECK_LIST_CONS(333,11785
-#define lisp_h_CHECK_NUMBER(334,11856
-#define lisp_h_CHECK_SYMBOL(335,11927
-#define lisp_h_CHECK_TYPE(336,11996
-#define lisp_h_CONSP(338,12107
-#define lisp_h_EQ(339,12156
-#define lisp_h_FLOATP(340,12201
-#define lisp_h_INTEGERP(341,12252
-#define lisp_h_MARKERP(342,12333
-#define lisp_h_MISCP(343,12408
-#define lisp_h_NILP(344,12457
-#define lisp_h_SET_SYMBOL_VAL(345,12493
-#define lisp_h_SYMBOL_CONSTANT_P(347,12607
-#define lisp_h_SYMBOL_VAL(348,12671
-#define lisp_h_SYMBOLP(350,12772
-#define lisp_h_VECTORLIKEP(351,12825
-#define lisp_h_XCAR(352,12886
-#define lisp_h_XCDR(353,12924
-#define lisp_h_XCONS(354,12964
-#define lisp_h_XHASH(356,13059
-#define lisp_h_XPNTR(357,13093
-# define lisp_h_check_cons_list(360,13221
-# define lisp_h_make_number(363,13289
-# define lisp_h_XFASTINT(365,13392
-# define lisp_h_XINT(366,13429
-# define lisp_h_XSYMBOL(367,13478
-# define lisp_h_XTYPE(371,13631
-# define lisp_h_XUNTAG(372,13696
-# define XLI(381,14086
-# define XIL(382,14117
-# define CHECK_LIST_CONS(383,14148
-# define CHECK_NUMBER(384,14209
-# define CHECK_SYMBOL(385,14258
-# define CHECK_TYPE(386,14307
-# define CONSP(387,14382
-# define EQ(388,14417
-# define FLOATP(389,14452
-# define INTEGERP(390,14489
-# define MARKERP(391,14530
-# define MISCP(392,14569
-# define NILP(393,14604
-# define SET_SYMBOL_VAL(394,14637
-# define SYMBOL_CONSTANT_P(395,14700
-# define SYMBOL_VAL(396,14763
-# define SYMBOLP(397,14812
-# define VECTORLIKEP(398,14851
-# define XCAR(399,14898
-# define XCDR(400,14931
-# define XCONS(401,14964
-# define XHASH(402,14999
-# define XPNTR(403,15034
-# define check_cons_list(405,15097
-# define make_number(408,15176
-# define XFASTINT(409,15224
-# define XINT(410,15266
-# define XSYMBOL(411,15300
-# define XTYPE(412,15340
-# define XUNTAG(413,15376
-#define LISP_MACRO_DEFUN(421,15672
-#define LISP_MACRO_DEFUN_VOID(425,15845
-#define INTMASK 437,16289
-#define case_Lisp_Int 438,16342
-#define ENUM_BF(445,16681
-#define ENUM_BF(447,16722
-enum Lisp_Type451,16763
- Lisp_Symbol 454,16851
- Lisp_Misc 458,16993
- Lisp_Int0 461,17067
- Lisp_Int1 462,17086
- Lisp_String 466,17264
- Lisp_Vectorlike 472,17543
- Lisp_Cons 475,17632
- Lisp_Float 477,17670
-enum Lisp_Misc_Type485,18016
- Lisp_Misc_Free 487,18040
- Lisp_Misc_Marker,488,18069
- Lisp_Misc_Overlay,489,18091
- Lisp_Misc_Save_Value,490,18114
- Lisp_Misc_Finalizer,491,18140
- Lisp_Misc_Float,494,18275
- Lisp_Misc_Limit496,18359
-enum Lisp_Fwd_Type502,18543
- Lisp_Fwd_Int,504,18566
- Lisp_Fwd_Bool,505,18619
- Lisp_Fwd_Obj,506,18670
- Lisp_Fwd_Buffer_Obj,507,18729
- Lisp_Fwd_Kboard_Obj 508,18800
-typedef struct { EMACS_INT i; } Lisp_Object;567,21781
-#define LISP_INITIALLY(569,21827
-#undef CHECK_LISP_OBJECT_TYPE571,21858
-enum CHECK_LISP_OBJECT_TYPE 572,21888
-enum CHECK_LISP_OBJECT_TYPE { CHECK_LISP_OBJECT_TYPE 572,21888
-typedef EMACS_INT Lisp_Object;577,22064
-#define LISP_INITIALLY(578,22095
-enum CHECK_LISP_OBJECT_TYPE 579,22125
-enum CHECK_LISP_OBJECT_TYPE { CHECK_LISP_OBJECT_TYPE 579,22125
-#define LISP_INITIALLY_ZERO 582,22226
-INLINE bool BOOL_VECTOR_P 588,22350
-INLINE bool BUFFER_OBJFWDP 589,22391
-INLINE bool BUFFERP 590,22438
-INLINE bool CHAR_TABLE_P 591,22473
-INLINE Lisp_Object CHAR_TABLE_REF_ASCII 592,22513
-INLINE bool 593,22579
-INLINE bool 594,22614
-INLINE bool functionp 595,22650
-INLINE bool 596,22687
-INLINE bool 597,22725
-INLINE bool 598,22762
-INLINE bool 599,22797
-INLINE bool OVERLAYP 600,22831
-INLINE bool PROCESSP 601,22867
-INLINE bool PSEUDOVECTORP 602,22903
-INLINE bool SAVE_VALUEP 603,22949
-INLINE bool FINALIZERP 604,22988
-INLINE void set_sub_char_table_contents 605,23026
-INLINE bool STRINGP 607,23116
-INLINE bool SUB_CHAR_TABLE_P 608,23151
-INLINE bool SUBRP 609,23195
-INLINE bool 610,23228
-INLINE bool 611,23265
-INLINE bool WINDOWP 612,23306
-INLINE bool TERMINALP 613,23341
-INLINE struct Lisp_Save_Value *XSAVE_VALUE XSAVE_VALUE614,23378
-INLINE struct Lisp_Finalizer *XFINALIZER XFINALIZER615,23436
-INLINE struct Lisp_Symbol *(XSYMBOL)616,23492
-INLINE void 617,23544
-extern Lisp_Object char_table_ref 620,23616
-extern void char_table_set 621,23670
-extern _Noreturn Lisp_Object wrong_type_argument 624,23757
-extern _Noreturn void wrong_choice 625,23834
-extern bool might_dump;628,23925
-extern bool initialized;631,24061
-extern double extract_float 634,24117
-enum symbol_interned639,24199
- SYMBOL_UNINTERNED 641,24222
- SYMBOL_INTERNED 642,24247
- SYMBOL_INTERNED_IN_INITIAL_OBARRAY 643,24270
-enum symbol_redirect646,24315
- SYMBOL_PLAINVAL 648,24338
- SYMBOL_VARALIAS 649,24362
- SYMBOL_LOCALIZED 650,24386
- SYMBOL_FORWARDED 651,24410
-struct Lisp_Symbol654,24437
-#define EXFUN(707,26252
-#define DEFUN_ARGS_MANY 712,26446
-#define DEFUN_ARGS_UNEVALLED 713,26498
-#define DEFUN_ARGS_0 714,26541
-#define DEFUN_ARGS_1 715,26569
-#define DEFUN_ARGS_2 716,26604
-#define DEFUN_ARGS_3 717,26652
-#define DEFUN_ARGS_4 718,26713
-#define DEFUN_ARGS_5 719,26787
-#define DEFUN_ARGS_6 721,26880
-#define DEFUN_ARGS_7 723,26986
-#define DEFUN_ARGS_8 725,27105
-#define TAG_PTR(729,27296
-#define TAG_SYMOFFSET(734,27543
-#define XLI_BUILTIN_LISPSYM(741,27842
-#define DEFINE_LISP_SYMBOL(746,28101
-# define DEFINE_NON_NIL_Q_SYMBOL_MACROS 755,28572
-LISP_MACRO_DEFUN 762,28777
-# define ARRAY_MARK_FLAG 768,29024
-# define PSEUDOVECTOR_FLAG 774,29267
-enum pvec_type780,29568
- PVEC_NORMAL_VECTOR,782,29585
- PVEC_FREE,783,29607
- PVEC_PROCESS,784,29620
- PVEC_FRAME,785,29636
- PVEC_WINDOW,786,29650
- PVEC_BOOL_VECTOR,787,29665
- PVEC_BUFFER,788,29685
- PVEC_HASH_TABLE,789,29700
- PVEC_TERMINAL,790,29719
- PVEC_WINDOW_CONFIGURATION,791,29736
- PVEC_SUBR,792,29765
- PVEC_OTHER,793,29778
- PVEC_COMPILED,795,29856
- PVEC_CHAR_TABLE,796,29873
- PVEC_SUB_CHAR_TABLE,797,29892
- PVEC_FONT 798,29915
-enum More_Lisp_Bits801,29991
- PSEUDOVECTOR_SIZE_BITS 808,30382
- PSEUDOVECTOR_SIZE_MASK 809,30415
- PSEUDOVECTOR_REST_BITS 813,30625
- PSEUDOVECTOR_REST_MASK 814,30658
- PSEUDOVECTOR_AREA_BITS 818,30823
- PVEC_TYPE_MASK 819,30901
-# define VALMASK 829,31302
-DEFINE_GDB_SYMBOL_BEGIN VALMASK828,31257
-#define MOST_POSITIVE_FIXNUM 834,31532
-#define MOST_NEGATIVE_FIXNUM 835,31592
-XINT 874,32684
-XFASTINT 889,33035
-XSYMBOL 899,33263
-XTYPE 910,33481
-XUNTAG 918,33661
-LISP_MACRO_DEFUN 927,33857
-LISP_MACRO_DEFUN 940,34242
-#define FIXNUM_OVERFLOW_P(958,34855
-LISP_MACRO_DEFUN FIXNUM_OVERFLOW_P952,34632
-LISP_MACRO_DEFUN 970,35171
-XSTRING 980,35391
-#define SYMBOL_INDEX(988,35575
-XFLOAT 991,35636
-XPROCESS 1000,35778
-XWINDOW 1007,35895
-XTERMINAL 1014,36012
-XSUBR 1021,36134
-XBUFFER 1028,36245
-XCHAR_TABLE 1035,36369
-XSUB_CHAR_TABLE 1042,36506
-XBOOL_VECTOR 1049,36648
-make_lisp_ptr 1058,36827
-make_lisp_symbol 1066,37013
-builtin_lisp_symbol 1074,37197
-#define XSETINT(1079,37279
-#define XSETFASTINT(1080,37325
-#define XSETCONS(1081,37375
-#define XSETVECTOR(1082,37435
-#define XSETSTRING(1083,37503
-#define XSETSYMBOL(1084,37567
-#define XSETFLOAT(1085,37621
-#define XSETMISC(1086,37683
-#define XSETPVECTYPE(1090,37772
-#define XSETPVECTYPESIZE(1092,37888
-#define XSETPSEUDOVECTOR(1099,38185
-#define XSETTYPED_PSEUDOVECTOR(1105,38369
-#define XSETWINDOW_CONFIGURATION(1110,38579
-#define XSETPROCESS(1112,38675
-#define XSETWINDOW(1113,38741
-#define XSETTERMINAL(1114,38805
-#define XSETSUBR(1115,38873
-#define XSETCOMPILED(1116,38933
-#define XSETBUFFER(1117,39001
-#define XSETCHAR_TABLE(1118,39065
-#define XSETBOOL_VECTOR(1119,39137
-#define XSETSUB_CHAR_TABLE(1120,39211
-XINTPTR 1128,39581
-make_pointer_integer 1134,39661
-LISP_MACRO_DEFUN_VOID 1143,39826
-typedef struct interval *INTERVAL;INTERVAL1149,39987
-xcar_addr 1174,40760
-xcdr_addr 1179,40837
-LISP_MACRO_DEFUN 1185,40931
-XSETCDR 1198,41307
-CAR 1205,41457
-CDR 1212,41591
-CAR_SAFE 1221,41791
-CDR_SAFE 1226,41877
-STRING_MULTIBYTE 1243,42250
-#define STRING_BYTES_BOUND 1261,43057
-#define STRING_SET_UNIBYTE(1265,43201
-#define STRING_SET_MULTIBYTE(1275,43516
-SDATA 1286,43830
-SSDATA 1291,43908
-SREF 1297,44037
-SSET 1302,44128
-SCHARS 1307,44242
-extern ptrdiff_t string_bytes 1313,44337
-STRING_BYTES 1316,44415
-SBYTES 1326,44595
-STRING_SET_CHARS 1331,44681
-struct vectorlike_header1343,45232
-struct Lisp_Vector1369,46482
- ALIGNOF_STRUCT_LISP_VECTOR1378,46681
-struct Lisp_Bool_Vector1384,46864
-bool_vector_size 1399,47385
-bool_vector_data 1407,47523
-bool_vector_uchar_data 1413,47617
-bool_vector_words 1421,47803
-bool_vector_bytes 1428,47998
-bool_vector_bitref 1437,48238
-bool_vector_ref 1445,48478
-bool_vector_set 1453,48618
- header_size 1471,49047
- bool_header_size 1472,49106
- word_size 1473,49171
-AREF 1479,49284
-aref_addr 1485,49391
-ASIZE 1491,49501
-ASET 1497,49583
-gc_aset 1504,49742
-enum { NIL_IS_ZERO 1515,50269
-memclear 1520,50464
-#define VECSIZE(1531,50762
-#define PSEUDOVECSIZE(1538,51047
-#define UNSIGNED_CMP(1546,51480
-#define ASCII_CHAR_P(1552,51734
-enum CHARTAB_SIZE_BITS1565,52489
- CHARTAB_SIZE_BITS_0 1567,52516
- CHARTAB_SIZE_BITS_1 1568,52545
- CHARTAB_SIZE_BITS_2 1569,52574
- CHARTAB_SIZE_BITS_3 1570,52603
-extern const int chartab_size[chartab_size1573,52637
-struct Lisp_Char_Table1575,52672
-struct Lisp_Sub_Char_Table1606,53752
-CHAR_TABLE_REF_ASCII 1628,54566
-CHAR_TABLE_REF 1648,55113
-CHAR_TABLE_SET 1658,55402
-struct Lisp_Subr1670,55786
-enum char_table_specials1692,56798
- CHAR_TABLE_STANDARD_SLOTS 1697,56993
- SUB_CHAR_TABLE_OFFSET 1701,57214
-CHAR_TABLE_EXTRA_SLOTS 1707,57377
-verify 1714,57596
-LISP_MACRO_DEFUN 1723,57921
-SYMBOL_BLV 1732,58181
-SYMBOL_FWD 1738,58316
-LISP_MACRO_DEFUN_VOID 1744,58428
-SET_SYMBOL_BLV 1754,58691
-SET_SYMBOL_FWD 1760,58850
-SYMBOL_NAME 1767,59001
-SYMBOL_INTERNED_P 1775,59130
-SYMBOL_INTERNED_IN_INITIAL_OBARRAY_P 1783,59299
-#define DEFSYM(1796,59809
-LISP_MACRO_DEFUN DEFSYM1792,59630
-struct hash_table_test1805,60062
-struct Lisp_Hash_Table1823,60555
-XHASH_TABLE 1880,62531
-#define XSET_HASH_TABLE(1885,62602
-HASH_TABLE_P 1889,62703
-HASH_KEY 1896,62860
-HASH_VALUE 1903,63040
-HASH_NEXT 1911,63254
-HASH_HASH 1918,63431
-HASH_INDEX 1926,63677
-HASH_TABLE_SIZE 1933,63826
-enum DEFAULT_HASH_SIZE 1940,63956
-enum DEFAULT_HASH_SIZE { DEFAULT_HASH_SIZE 1940,63956
-static double const DEFAULT_REHASH_THRESHOLD 1946,64176
-static double const DEFAULT_REHASH_SIZE 1950,64299
-sxhash_combine 1956,64465
-SXHASH_REDUCE 1964,64648
-struct Lisp_Misc_Any 1971,64806
-struct Lisp_Marker1978,64980
-struct Lisp_Overlay2021,66841
- SAVE_UNUSED,2047,67644
- SAVE_INTEGER,2048,67661
- SAVE_FUNCPOINTER,2049,67679
- SAVE_POINTER,2050,67701
- SAVE_OBJECT2051,67719
-enum { SAVE_SLOT_BITS 2055,67804
-enum { SAVE_VALUE_SLOTS 2058,67901
-enum { SAVE_TYPE_BITS 2062,68009
-enum Lisp_Save_Type2064,68075
- SAVE_TYPE_INT_INT 2066,68099
- SAVE_TYPE_INT_INT_INT2067,68172
- SAVE_TYPE_OBJ_OBJ 2069,68262
- SAVE_TYPE_OBJ_OBJ_OBJ 2070,68333
- SAVE_TYPE_OBJ_OBJ_OBJ_OBJ2071,68414
- SAVE_TYPE_PTR_INT 2073,68509
- SAVE_TYPE_PTR_OBJ 2074,68582
- SAVE_TYPE_PTR_PTR 2075,68654
- SAVE_TYPE_FUNCPTR_PTR_OBJ2076,68727
- SAVE_TYPE_MEMORY 2080,68885
-typedef void (*voidfuncptr)voidfuncptr2108,69839
-struct Lisp_Save_Value2110,69876
-save_type 2134,70755
-XSAVE_POINTER 2143,70985
-set_save_pointer 2149,71147
-XSAVE_FUNCPOINTER 2155,71329
-XSAVE_INTEGER 2164,71549
-set_save_integer 2170,71711
-XSAVE_OBJECT 2179,71932
-struct Lisp_Finalizer2186,72109
-struct Lisp_Free2201,72584
-union Lisp_Misc2212,72885
-XMISC 2223,73184
-XMISCANY 2229,73273
-XMISCTYPE 2236,73382
-XMARKER 2242,73470
-XOVERLAY 2249,73585
-XSAVE_VALUE 2256,73706
-XFINALIZER 2263,73835
-struct Lisp_Intfwd2274,74120
-struct Lisp_Boolfwd2284,74414
-struct Lisp_Objfwd2294,74705
-struct Lisp_Buffer_Objfwd2302,74937
-struct Lisp_Buffer_Local_Value2334,76473
-struct Lisp_Kboard_Objfwd2362,77732
-union Lisp_Fwd2368,77841
-XFWDTYPE 2378,78087
-XBUFFER_OBJFWD 2384,78183
-struct Lisp_Float2391,78319
-XFLOAT_DATA 2401,78437
- IEEE_FLOATING_POINT2415,78946
-#define _UCHAR_T2423,79269
-typedef unsigned char UCHAR;2424,79286
-enum Lisp_Compiled2429,79369
- COMPILED_ARGLIST 2431,79392
- COMPILED_BYTECODE 2432,79418
- COMPILED_CONSTANTS 2433,79445
- COMPILED_STACK_DEPTH 2434,79473
- COMPILED_DOC_STRING 2435,79503
- COMPILED_INTERACTIVE 2436,79532
-enum char_bits2443,79834
- CHAR_ALT 2445,79853
- CHAR_SUPER 2446,79879
- CHAR_HYPER 2447,79907
- CHAR_SHIFT 2448,79935
- CHAR_CTL 2449,79963
- CHAR_META 2450,79989
- CHAR_MODIFIER_MASK 2452,80017
- CHARACTERBITS 2457,80212
-LISP_MACRO_DEFUN 2462,80270
-NATNUMP 2470,80412
-RANGED_INTEGERP 2476,80493
-#define TYPE_RANGED_INTEGERP(2481,80615
-LISP_MACRO_DEFUN 2486,80800
-VECTORP 2500,81273
-OVERLAYP 2505,81376
-SAVE_VALUEP 2510,81475
-FINALIZERP 2516,81581
-AUTOLOADP 2522,81685
-BUFFER_OBJFWDP 2528,81776
-PSEUDOVECTOR_TYPEP 2534,81874
-PSEUDOVECTORP 2542,82127
-WINDOW_CONFIGURATIONP 2558,82479
-PROCESSP 2564,82589
-WINDOWP 2570,82673
-TERMINALP 2576,82755
-SUBRP 2582,82841
-COMPILEDP 2588,82919
-BUFFERP 2594,83005
-CHAR_TABLE_P 2600,83087
-SUB_CHAR_TABLE_P 2606,83178
-BOOL_VECTOR_P 2612,83277
-FRAMEP 2618,83370
-IMAGEP 2625,83487
-ARRAYP 2632,83592
-CHECK_LIST 2638,83711
-LISP_MACRO_DEFUN_VOID 2643,83792
-CHECK_STRING_CAR 2653,84089
-CHECK_CONS 2658,84193
-CHECK_VECTOR 2663,84273
-CHECK_BOOL_VECTOR 2668,84359
-CHECK_VECTOR_OR_STRING 2674,84536
-CHECK_ARRAY 2683,84710
-CHECK_BUFFER 2688,84818
-CHECK_WINDOW 2693,84904
-CHECK_PROCESS 2699,85010
-CHECK_NATNUM 2705,85106
-#define CHECK_RANGED_INTEGER(2710,85183
-#define CHECK_TYPE_RANGED_INTEGER(2721,85566
-#define CHECK_NUMBER_COERCE_MARKER(2729,85836
-XFLOATINT 2738,86089
-CHECK_NUMBER_OR_FLOAT 2744,86160
-#define CHECK_NUMBER_OR_FLOAT_COERCE_MARKER(2749,86259
-CHECK_NUMBER_CAR 2760,86669
-CHECK_NUMBER_CDR 2768,86791
-#define DEFUN(2803,88386
-#define DEFUN(2812,88854
-FUNCTIONP 2822,89209
-extern void defsubr 2829,89361
-enum maxargs2831,89404
- MANY 2833,89421
- UNEVALLED 2834,89436
-#define CALLMANY(2838,89539
-#define CALLN(2844,89892
-extern void defvar_lisp 2846,89962
-extern void defvar_lisp_nopro 2847,90039
-extern void defvar_bool 2848,90122
-extern void defvar_int 2849,90193
-extern void defvar_kboard 2850,90267
-#define DEFVAR_LISP(2869,91097
-#define DEFVAR_LISP_NOPRO(2874,91269
-#define DEFVAR_BOOL(2879,91451
-#define DEFVAR_INT(2884,91624
-#define DEFVAR_BUFFER_DEFAULTS(2890,91795
-#define DEFVAR_KBOARD(2896,91999
-typedef jmp_buf sys_jmp_buf;2906,92323
-# define sys_setjmp(2907,92352
-# define sys_longjmp(2908,92387
-typedef sigjmp_buf sys_jmp_buf;2910,92459
-# define sys_setjmp(2911,92491
-# define sys_longjmp(2912,92531
-typedef jmp_buf sys_jmp_buf;2916,92690
-# define sys_setjmp(2917,92719
-# define sys_longjmp(2918,92753
-enum specbind_tag 2943,93805
- SPECPDL_UNWIND,2944,93825
- SPECPDL_UNWIND_PTR,2945,93894
- SPECPDL_UNWIND_INT,2946,93945
- SPECPDL_UNWIND_VOID,2947,93993
- SPECPDL_BACKTRACE,2948,94047
- SPECPDL_LET,2949,94105
- SPECPDL_LET_LOCAL,2951,94235
- SPECPDL_LET_DEFAULT 2952,94292
-union specbinding2955,94364
-extern union specbinding *specpdl;specpdl2991,95265
-extern union specbinding *specpdl_ptr;specpdl_ptr2992,95300
-extern ptrdiff_t specpdl_size;2993,95339
-SPECPDL_INDEX 2996,95388
-enum handlertype 3021,96410
-enum handlertype { CATCHER,3021,96410
-enum handlertype { CATCHER, CONDITION_CASE 3021,96410
-struct handler3023,96457
-#define PUSH_HANDLER(3053,97446
-extern Lisp_Object memory_signal_data;3075,98152
-extern char *stack_bottom;stack_bottom3079,98285
-extern void process_pending_signals 3097,99102
-extern bool volatile pending_signals;3098,99146
-extern void process_quit_flag 3100,99185
-#define QUIT 3101,99223
-#define QUITP 3112,99473
-extern Lisp_Object Vascii_downcase_table;3114,99534
-extern Lisp_Object Vascii_canon_table;3115,99576
-extern struct gcpro *gcprolist;gcprolist3130,100283
-struct gcpro3132,100316
-#define GC_USE_GCPROS_AS_BEFORE 3171,101297
-#define GC_MAKE_GCPROS_NOOPS 3172,101332
-#define GC_MARK_STACK_CHECK_GCPROS 3173,101364
-#define GC_USE_GCPROS_CHECK_ZOMBIES 3174,101401
-#define GC_MARK_STACK 3177,101462
-#define BYTE_MARK_STACK 3181,101562
-#define GCPRO1(3190,101833
-#define GCPRO2(3191,101873
-#define GCPRO3(3192,101939
-#define GCPRO4(3194,102034
-#define GCPRO5(3196,102154
-#define GCPRO6(3198,102299
-#define GCPRO7(3201,102474
-#define UNGCPRO 3202,102553
-#define GCPRO1(3208,102653
-#define GCPRO2(3212,102775
-#define GCPRO3(3217,102967
-#define GCPRO4(3223,103229
-#define GCPRO5(3230,103560
-#define GCPRO6(3238,103961
-#define GCPRO7(3247,104431
-#define UNGCPRO 3257,104971
-extern int gcpro_level;3261,105040
-#define GCPRO1(3263,105065
-#define GCPRO2(3269,105299
-#define GCPRO3(3278,105717
-#define GCPRO4(3289,106274
-#define GCPRO5(3302,106972
-#define GCPRO6(3317,107812
-#define GCPRO7(3334,108793
-#define UNGCPRO 3353,109916
-#define RETURN_UNGCPRO(3363,110183
-void staticpro 3375,110456
-vcopy 3384,110657
-set_hash_key_slot 3393,110932
-set_hash_value_slot 3399,111071
-set_symbol_function 3408,111306
-set_symbol_plist 3414,111421
-set_symbol_next 3420,111524
-blv_found 3428,111697
-set_overlay_plist 3437,111880
-string_intervals 3445,112031
-set_string_intervals 3453,112153
-set_char_table_defalt 3462,112355
-set_char_table_purpose 3467,112467
-set_char_table_extras 3475,112636
-set_char_table_contents 3482,112845
-set_sub_char_table_contents 3489,113040
-extern Lisp_Object indirect_function 3495,113199
-extern Lisp_Object find_symbol_value 3496,113251
-enum Arith_Comparison 3497,113303
- ARITH_EQUAL,3498,113327
- ARITH_NOTEQUAL,3499,113342
- ARITH_LESS,3500,113360
- ARITH_GRTR,3501,113374
- ARITH_LESS_OR_EQUAL,3502,113388
- ARITH_GRTR_OR_EQUAL3503,113411
-extern Lisp_Object arithcompare 3505,113436
-#define INTEGER_TO_CONS(3511,113762
-#define CONS_TO_INTEGER(3529,114625
-extern intmax_t cons_to_signed 3533,114840
-extern uintmax_t cons_to_unsigned 3534,114906
-extern struct Lisp_Symbol *indirect_variable indirect_variable3536,114967
-extern _Noreturn void args_out_of_range 3537,115036
-extern _Noreturn void args_out_of_range_3 3538,115104
-extern Lisp_Object do_symval_forwarding 3540,115195
-extern void set_internal 3541,115255
-extern void syms_of_data 3542,115327
-extern void swap_in_global_binding 3543,115360
-extern void syms_of_cmds 3546,115444
-extern void keys_of_cmds 3547,115477
-extern Lisp_Object detect_coding_system 3550,115539
-extern void init_coding 3552,115692
-extern void init_coding_once 3553,115724
-extern void syms_of_coding 3554,115761
-extern ptrdiff_t chars_in_text 3557,115828
-extern ptrdiff_t multibyte_chars_in_text 3558,115895
-extern void syms_of_character 3559,115972
-extern void init_charset 3562,116040
-extern void init_charset_once 3563,116073
-extern void syms_of_charset 3564,116111
-extern void init_syntax_once 3569,116231
-extern void syms_of_syntax 3570,116268
-enum { NEXT_ALMOST_PRIME_LIMIT 3573,116329
-extern EMACS_INT next_almost_prime 3574,116368
-enum constype 3739,123820
-enum constype {CONSTYPE_HEAP,CONSTYPE_HEAP3739,123820
-enum constype {CONSTYPE_HEAP, CONSTYPE_PURE}CONSTYPE_PURE3739,123820
-extern Lisp_Object listn 3740,123866
-list2i 3745,124010
-list3i 3751,124119
-list4i 3757,124258
-extern Lisp_Object make_uninit_bool_vector 3763,124410
-extern Lisp_Object bool_vector_fill 3764,124466
-extern _Noreturn void string_overflow 3765,124530
-extern Lisp_Object make_string 3766,124576
-extern Lisp_Object make_formatted_string 3767,124634
-extern Lisp_Object make_multibyte_string 3779,124988
-extern Lisp_Object make_event_array 3780,125067
-extern Lisp_Object make_uninit_string 3781,125131
-extern Lisp_Object make_uninit_multibyte_string 3782,125182
-extern Lisp_Object make_string_from_bytes 3783,125254
-extern Lisp_Object make_specified_string 3784,125334
-extern Lisp_Object make_pure_string 3786,125426
-extern Lisp_Object make_pure_c_string 3787,125506
-build_pure_c_string 3792,125662
-build_string 3801,125867
-extern Lisp_Object pure_cons 3806,125945
-extern void make_byte_code 3807,126002
-extern struct Lisp_Vector *allocate_vector allocate_vector3808,126053
-make_uninit_vector 3820,126438
-make_uninit_sub_char_table 3833,126657
-extern struct Lisp_Vector *allocate_pseudovector allocate_pseudovector3844,126966
-#define ALLOCATE_PSEUDOVECTOR(3850,127201
-#define ALLOCATE_ZEROED_PSEUDOVECTOR(3858,127537
-extern bool gc_in_progress;3863,127738
-extern bool abort_on_gc;3864,127766
-extern Lisp_Object make_float 3865,127791
-extern void display_malloc_warning 3866,127831
-extern ptrdiff_t inhibit_garbage_collection 3867,127874
-extern Lisp_Object make_save_int_int_int 3868,127926
-extern Lisp_Object make_save_obj_obj_obj_obj 3869,128002
-extern Lisp_Object make_save_ptr 3871,128112
-extern Lisp_Object make_save_ptr_int 3872,128155
-extern Lisp_Object make_save_ptr_ptr 3873,128213
-extern Lisp_Object make_save_funcptr_ptr_obj 3874,128268
-extern Lisp_Object make_save_memory 3876,128364
-extern void free_save_value 3877,128428
-extern Lisp_Object build_overlay 3878,128471
-extern void free_marker 3879,128545
-extern void free_cons 3880,128584
-extern void init_alloc_once 3881,128628
-extern void init_alloc 3882,128664
-extern void syms_of_alloc 3883,128695
-extern struct buffer * allocate_buffer 3884,128729
-extern int valid_lisp_object_p 3885,128776
-extern int relocatable_string_data_p 3886,128822
-extern void check_cons_list 3888,128901
-INLINE void 3890,128943
-extern void *r_alloc r_alloc3895,129064
-#define FLOAT_TO_STRING_BUFSIZE 3927,130527
-extern int openp 3957,131676
-extern Lisp_Object string_to_number 3959,131786
-extern void map_obarray 3960,131849
-extern void dir_warning 3962,131963
-extern void init_obarray 3963,132016
-extern void init_lread 3964,132049
-extern void syms_of_lread 3965,132080
-intern 3968,132134
-intern_c_string 3974,132222
-extern EMACS_INT lisp_eval_depth;3980,132335
-extern Lisp_Object Vautoload_queue;3981,132369
-extern Lisp_Object Vrun_hooks;3982,132405
-extern Lisp_Object Vsignaling_function;3983,132436
-extern Lisp_Object inhibit_lisp_code;3984,132476
-extern struct handler *handlerlist;handlerlist3985,132514
-extern void run_hook 3994,132756
-extern void run_hook_with_args_2 3995,132792
-extern Lisp_Object run_hook_with_args 3996,132866
-extern _Noreturn void xsignal 3999,133025
-extern _Noreturn void xsignal0 4000,133083
-extern _Noreturn void xsignal1 4001,133129
-extern _Noreturn void xsignal2 4002,133188
-extern _Noreturn void xsignal3 4003,133260
-extern _Noreturn void signal_error 4005,133349
-extern Lisp_Object eval_sub 4006,133413
-extern Lisp_Object apply1 4007,133461
-extern Lisp_Object call0 4008,133515
-extern Lisp_Object call1 4009,133555
-extern Lisp_Object call2 4010,133608
-extern Lisp_Object call3 4011,133674
-extern Lisp_Object call4 4012,133753
-extern Lisp_Object call5 4013,133845
-extern Lisp_Object call6 4014,133950
-extern Lisp_Object call7 4015,134068
-extern Lisp_Object internal_catch 4016,134199
-extern Lisp_Object internal_lisp_condition_case 4017,134292
-extern Lisp_Object internal_condition_case 4018,134381
-extern Lisp_Object internal_condition_case_1 4019,134494
-extern Lisp_Object internal_condition_case_2 4020,134629
-extern Lisp_Object internal_condition_case_n4021,134790
-extern void specbind 4024,134986
-extern void record_unwind_protect 4025,135035
-extern void record_unwind_protect_ptr 4026,135108
-extern void record_unwind_protect_int 4027,135175
-extern void record_unwind_protect_void 4028,135236
-extern void record_unwind_protect_nothing 4029,135294
-extern void clear_unwind_protect 4030,135344
-extern void set_unwind_protect 4031,135390
-extern void set_unwind_protect_ptr 4032,135471
-extern Lisp_Object unbind_to 4033,135546
-extern _Noreturn void error 4034,135601
-fast_string_match_ignore_case 4136,140089
-extern ptrdiff_t fast_c_string_match_ignore_case 4141,140239
-extern ptrdiff_t fast_looking_at 4143,140336
-extern ptrdiff_t find_newline 4145,140475
-extern ptrdiff_t scan_newline 4147,140604
-extern ptrdiff_t scan_newline_from_point 4149,140707
-extern ptrdiff_t find_newline_no_quit 4150,140787
-extern ptrdiff_t find_before_next_newline 4152,140884
-extern void syms_of_search 4154,140982
-extern void clear_regexp_cache 4155,141017
-extern Lisp_Object Vminibuffer_list;4159,141087
-extern Lisp_Object last_minibuf_string;4160,141124
-extern Lisp_Object get_minibuffer 4161,141164
-extern void init_minibuf_once 4162,141211
-extern void syms_of_minibuf 4163,141249
-extern void syms_of_callint 4167,141316
-extern void syms_of_casefiddle 4171,141386
-extern void keys_of_casefiddle 4172,141425
-extern void init_casetab_once 4176,141495
-extern void syms_of_casetab 4177,141533
-extern Lisp_Object echo_message_buffer;4181,141601
-extern struct kboard *echo_kboard;echo_kboard4182,141641
-extern void cancel_echoing 4183,141676
-extern Lisp_Object last_undo_boundary;4184,141711
-extern bool input_pending;4185,141750
-extern sigjmp_buf return_to_command_loop;4187,141813
-extern Lisp_Object menu_bar_items 4189,141862
-extern Lisp_Object tool_bar_items 4190,141911
-extern void discard_mouse_events 4191,141967
-void handle_input_available_signal 4193,142028
-extern Lisp_Object pending_funcalls;4195,142077
-extern bool detect_input_pending 4196,142114
-extern bool detect_input_pending_ignore_squeezables 4197,142155
-extern bool detect_input_pending_run_timers 4198,142215
-extern void safe_run_hooks 4199,142267
-extern void cmd_error_internal 4200,142309
-extern Lisp_Object command_loop_1 4201,142369
-extern Lisp_Object read_menu_command 4202,142411
-extern Lisp_Object recursive_edit_1 4203,142456
-extern void record_auto_save 4204,142500
-extern void force_auto_save_soon 4205,142537
-extern void init_keyboard 4206,142578
-extern void syms_of_keyboard 4207,142612
-extern void keys_of_keyboard 4208,142649
-extern ptrdiff_t current_column 4211,142715
-extern void invalidate_current_column 4212,142755
-extern bool indented_beyond_p 4213,142801
-extern void syms_of_indent 4214,142866
-extern void store_frame_param 4217,142929
-extern void store_in_alist 4218,143003
-extern Lisp_Object do_switch_frame 4219,143073
-extern Lisp_Object get_frame_param 4220,143146
-extern void frames_discard_buffer 4221,143212
-extern void syms_of_frame 4222,143261
-extern char **initial_argv;initial_argv4225,143323
-extern int initial_argc;4226,143351
-extern bool display_arg;4228,143426
-extern Lisp_Object decode_env_path 4230,143458
-extern Lisp_Object empty_unibyte_string,4231,143529
-extern Lisp_Object empty_unibyte_string, empty_multibyte_string;4231,143529
-extern _Noreturn void terminate_due_to_signal 4232,143594
-extern Lisp_Object Vlibrary_cache;4234,143669
-void fixup_locale 4237,143730
-void synchronize_system_messages_locale 4238,143756
-void synchronize_system_time_locale 4239,143804
-INLINE void fixup_locale 4241,143854
-INLINE void synchronize_system_messages_locale 4242,143889
-INLINE void synchronize_system_time_locale 4243,143946
-extern void shut_down_emacs 4245,144006
-extern bool noninteractive;4248,144132
-extern bool no_site_lisp;4251,144224
-extern int daemon_pipe[daemon_pipe4256,144392
-#define IS_DAEMON 4257,144419
-#define DAEMON_RUNNING 4258,144459
-extern void *w32_daemon_event;w32_daemon_event4260,144527
-#define IS_DAEMON 4261,144558
-#define DAEMON_RUNNING 4262,144603
-extern bool fatal_error_in_progress;4266,144724
-extern bool inhibit_window_system;4269,144830
-extern bool running_asynch_code;4271,144923
-extern void kill_buffer_processes 4274,144986
-extern int wait_reading_process_output 4275,145035
-# define WAIT_READING_MAX 4281,145422
-# define WAIT_READING_MAX 4283,145494
-extern void add_timer_wait_descriptor 4286,145558
-extern void add_keyboard_wait_descriptor 4288,145610
-extern void delete_keyboard_wait_descriptor 4289,145658
-extern void add_gpm_wait_descriptor 4291,145725
-extern void delete_gpm_wait_descriptor 4292,145768
-extern void init_process_emacs 4294,145821
-extern void syms_of_process 4295,145860
-extern void setup_process_coding_systems 4296,145896
-extern int child_setup 4302,146016
-extern void init_callproc_1 4303,146084
-extern void init_callproc 4304,146120
-extern void set_initial_environment 4305,146154
-extern void syms_of_callproc 4306,146198
-extern Lisp_Object read_doc_string 4309,146261
-extern Lisp_Object get_doc_string 4310,146311
-extern void syms_of_doc 4311,146372
-extern int read_bytecode_char 4312,146404
-extern void syms_of_bytecode 4315,146473
-extern struct byte_stack *byte_stack_list;byte_stack_list4316,146510
-extern void mark_byte_stack 4318,146573
-extern void unmark_byte_stack 4320,146616
-extern Lisp_Object exec_byte_code 4321,146654
-extern void init_macros 4325,146804
-extern void syms_of_macros 4326,146836
-extern void truncate_undo_list 4329,146898
-extern void record_insert 4330,146948
-extern void record_delete 4331,146998
-extern void record_first_change 4332,147056
-extern void record_change 4333,147096
-extern void record_property_change 4334,147146
-extern void syms_of_undo 4337,147288
-extern void report_interval_modification 4340,147352
-extern void syms_of_menu 4343,147448
-extern void syms_of_xmenu 4346,147509
-extern char *get_current_dir_name get_current_dir_name4356,147711
-extern void stuff_char 4358,147760
-extern void init_foreground_group 4359,147793
-extern void sys_subshell 4360,147835
-extern void sys_suspend 4361,147868
-extern void discard_tty_input 4362,147900
-extern void init_sys_modes 4363,147938
-extern void reset_sys_modes 4364,147994
-extern void init_all_sys_modes 4365,148051
-extern void reset_all_sys_modes 4366,148090
-extern void child_setup_tty 4367,148130
-extern void setup_pty 4368,148165
-extern int set_window_size 4369,148194
-extern EMACS_INT get_random 4370,148238
-extern void seed_random 4371,148274
-extern void init_random 4372,148319
-extern void emacs_backtrace 4373,148351
-extern _Noreturn void emacs_abort 4374,148386
-extern void xputenv 4527,152700
-extern char *egetenv_internal egetenv_internal4529,152737
-egetenv 4532,152809
-extern void init_system_name 4539,153012
-#define eabs(4545,153305
-#define make_fixnum_or_float(4550,153438
-enum MAX_ALLOCA 4556,153689
-enum MAX_ALLOCA { MAX_ALLOCA 4556,153689
-extern void *record_xmalloc record_xmalloc4558,153734
-#define USE_SAFE_ALLOCA 4560,153800
-#define AVAIL_ALLOCA(4564,153933
-#define SAFE_ALLOCA(4568,154044
-#define SAFE_NALLOCA(4576,154385
-#define SAFE_ALLOCA_STRING(4590,154861
-#define SAFE_FREE(4598,155113
-#define SAFE_ALLOCA_LISP(4625,155691
-# define USE_STACK_LISP_OBJECTS 4652,156813
-# undef USE_STACK_LISP_OBJECTS4658,156979
-# define USE_STACK_LISP_OBJECTS 4659,157010
-enum { defined_GC_CHECK_STRING_BYTES 4663,157085
-enum { defined_GC_CHECK_STRING_BYTES 4665,157138
-union Aligned_Cons4670,157272
-union Aligned_String4676,157352
- USE_STACK_CONS 4689,157707
- USE_STACK_STRING 4691,157813
-#define STACK_CONS(4699,158150
-#define AUTO_CONS_EXPR(4701,158247
-#define AUTO_CONS(4709,158610
-#define AUTO_LIST1(4710,158681
-#define AUTO_LIST2(4712,158789
-#define AUTO_LIST3(4716,158944
-#define AUTO_LIST4(4720,159119
-extern const char *verify_ascii verify_ascii4730,159456
-# define verify_ascii(4732,159510
-#define AUTO_STRING(4740,159818
-#define FOR_EACH_TAIL(4752,160282
-#define FOR_EACH_ALIST_VALUE(4766,160773
-maybe_gc 4774,161060
-functionp 4784,161299
+#define EMACS_LISP_H22,801
+#define DECLARE_GDB_SYM(47,1422
+# define DEFINE_GDB_SYMBOL_BEGIN(49,1509
+# define DEFINE_GDB_SYMBOL_END(50,1579
+# define DEFINE_GDB_SYMBOL_BEGIN(52,1626
+# define DEFINE_GDB_SYMBOL_END(53,1703
+#undef min57,1791
+#undef max58,1802
+#define max(59,1813
+#define min(60,1855
+#define ARRAYELTS(63,1937
+#define GCTYPEBITS 67,2080
+DEFINE_GDB_SYMBOL_BEGIN GCTYPEBITS66,2038
+# define NONPOINTER_BITS 78,2568
+# define NONPOINTER_BITS 80,2601
+typedef int EMACS_INT;91,3024
+typedef unsigned int EMACS_UINT;92,3047
+# define EMACS_INT_MAX 93,3080
+# define pI 94,3112
+typedef long int EMACS_INT;96,3204
+typedef unsigned long EMACS_UINT;97,3232
+# define EMACS_INT_MAX 98,3266
+# define pI 99,3299
+typedef long long int EMACS_INT;103,3478
+typedef unsigned long long int EMACS_UINT;104,3511
+# define EMACS_INT_MAX 105,3554
+# define pI 106,3588
+enum { BOOL_VECTOR_BITS_PER_CHAR 114,3805
+#define BOOL_VECTOR_BITS_PER_CHAR 115,3841
+typedef size_t bits_word;123,4166
+# define BITS_WORD_MAX 124,4192
+enum { BITS_PER_BITS_WORD 125,4224
+typedef unsigned char bits_word;127,4291
+# define BITS_WORD_MAX 128,4324
+enum { BITS_PER_BITS_WORD 129,4387
+verify 131,4451
+ BITS_PER_CHAR 136,4571
+ BITS_PER_SHORT 137,4606
+ BITS_PER_LONG 138,4658
+ BITS_PER_EMACS_INT 139,4713
+typedef intmax_t printmax_t;148,5090
+typedef uintmax_t uprintmax_t;149,5119
+# define pMd 150,5150
+# define pMu 151,5171
+typedef EMACS_INT printmax_t;153,5198
+typedef EMACS_UINT uprintmax_t;154,5228
+# define pMd 155,5260
+# define pMu 156,5279
+# define pD 165,5665
+# define pD 167,5710
+# define pD 169,5757
+# define pD 171,5780
+# define eassert(200,7063
+# define eassume(201,7141
+extern _Noreturn void die 204,7207
+extern bool suppress_checking EXTERNALLY_VISIBLE;206,7269
+# define eassert(208,7320
+# define eassume(212,7451
+enum Lisp_Bits239,8520
+#define GCALIGNMENT 243,8648
+ VALBITS 246,8743
+ INTTYPEBITS 249,8839
+ FIXNUM_BITS 252,8946
+#define VAL_MAX 263,9328
+#define USE_LSB_TAG 271,9778
+DEFINE_GDB_SYMBOL_BEGIN USE_LSB_TAG270,9734
+# define alignas(281,10078
+# define GCALIGNED 288,10228
+# define GCALIGNED 290,10293
+# define lisp_h_XLI(327,11643
+# define lisp_h_XIL(328,11674
+# define lisp_h_XLI(330,11725
+# define lisp_h_XIL(331,11752
+#define lisp_h_CHECK_LIST_CONS(333,11786
+#define lisp_h_CHECK_NUMBER(334,11857
+#define lisp_h_CHECK_SYMBOL(335,11928
+#define lisp_h_CHECK_TYPE(336,11997
+#define lisp_h_CONSP(338,12108
+#define lisp_h_EQ(339,12157
+#define lisp_h_FLOATP(340,12202
+#define lisp_h_INTEGERP(341,12253
+#define lisp_h_MARKERP(342,12334
+#define lisp_h_MISCP(343,12409
+#define lisp_h_NILP(344,12458
+#define lisp_h_SET_SYMBOL_VAL(345,12494
+#define lisp_h_SYMBOL_CONSTANT_P(347,12608
+#define lisp_h_SYMBOL_VAL(348,12672
+#define lisp_h_SYMBOLP(350,12773
+#define lisp_h_VECTORLIKEP(351,12826
+#define lisp_h_XCAR(352,12887
+#define lisp_h_XCDR(353,12925
+#define lisp_h_XCONS(354,12965
+#define lisp_h_XHASH(356,13060
+#define lisp_h_XPNTR(357,13094
+# define lisp_h_check_cons_list(360,13222
+# define lisp_h_make_number(363,13290
+# define lisp_h_XFASTINT(365,13393
+# define lisp_h_XINT(366,13430
+# define lisp_h_XSYMBOL(367,13479
+# define lisp_h_XTYPE(371,13632
+# define lisp_h_XUNTAG(372,13697
+# define XLI(381,14087
+# define XIL(382,14118
+# define CHECK_LIST_CONS(383,14149
+# define CHECK_NUMBER(384,14210
+# define CHECK_SYMBOL(385,14259
+# define CHECK_TYPE(386,14308
+# define CONSP(387,14383
+# define EQ(388,14418
+# define FLOATP(389,14453
+# define INTEGERP(390,14490
+# define MARKERP(391,14531
+# define MISCP(392,14570
+# define NILP(393,14605
+# define SET_SYMBOL_VAL(394,14638
+# define SYMBOL_CONSTANT_P(395,14701
+# define SYMBOL_VAL(396,14764
+# define SYMBOLP(397,14813
+# define VECTORLIKEP(398,14852
+# define XCAR(399,14899
+# define XCDR(400,14932
+# define XCONS(401,14965
+# define XHASH(402,15000
+# define XPNTR(403,15035
+# define check_cons_list(405,15098
+# define make_number(408,15177
+# define XFASTINT(409,15225
+# define XINT(410,15267
+# define XSYMBOL(411,15301
+# define XTYPE(412,15341
+# define XUNTAG(413,15377
+#define LISP_MACRO_DEFUN(421,15673
+#define LISP_MACRO_DEFUN_VOID(425,15846
+#define INTMASK 437,16290
+#define case_Lisp_Int 438,16343
+#define ENUM_BF(445,16682
+#define ENUM_BF(447,16723
+enum Lisp_Type451,16764
+ Lisp_Symbol 454,16852
+ Lisp_Misc 458,16994
+ Lisp_Int0 461,17068
+ Lisp_Int1 462,17087
+ Lisp_String 466,17265
+ Lisp_Vectorlike 472,17544
+ Lisp_Cons 475,17633
+ Lisp_Float 477,17671
+enum Lisp_Misc_Type485,18017
+ Lisp_Misc_Free 487,18041
+ Lisp_Misc_Marker,488,18070
+ Lisp_Misc_Overlay,489,18092
+ Lisp_Misc_Save_Value,490,18115
+ Lisp_Misc_Finalizer,491,18141
+ Lisp_Misc_Float,494,18276
+ Lisp_Misc_Limit496,18360
+enum Lisp_Fwd_Type502,18544
+ Lisp_Fwd_Int,504,18567
+ Lisp_Fwd_Bool,505,18620
+ Lisp_Fwd_Obj,506,18671
+ Lisp_Fwd_Buffer_Obj,507,18730
+ Lisp_Fwd_Kboard_Obj 508,18801
+typedef struct { EMACS_INT i; } Lisp_Object;567,21772
+#define LISP_INITIALLY(569,21818
+#undef CHECK_LISP_OBJECT_TYPE571,21849
+enum CHECK_LISP_OBJECT_TYPE 572,21879
+enum CHECK_LISP_OBJECT_TYPE { CHECK_LISP_OBJECT_TYPE 572,21879
+typedef EMACS_INT Lisp_Object;577,22055
+#define LISP_INITIALLY(578,22086
+enum CHECK_LISP_OBJECT_TYPE 579,22116
+enum CHECK_LISP_OBJECT_TYPE { CHECK_LISP_OBJECT_TYPE 579,22116
+#define LISP_INITIALLY_ZERO 582,22217
+INLINE bool BOOL_VECTOR_P 588,22341
+INLINE bool BUFFER_OBJFWDP 589,22382
+INLINE bool BUFFERP 590,22429
+INLINE bool CHAR_TABLE_P 591,22464
+INLINE Lisp_Object CHAR_TABLE_REF_ASCII 592,22504
+INLINE bool 593,22570
+INLINE bool 594,22605
+INLINE bool functionp 595,22641
+INLINE bool 596,22678
+INLINE bool 597,22716
+INLINE bool 598,22753
+INLINE bool 599,22788
+INLINE bool OVERLAYP 600,22822
+INLINE bool PROCESSP 601,22858
+INLINE bool PSEUDOVECTORP 602,22894
+INLINE bool SAVE_VALUEP 603,22940
+INLINE bool FINALIZERP 604,22979
+INLINE void set_sub_char_table_contents 605,23017
+INLINE bool STRINGP 607,23107
+INLINE bool SUB_CHAR_TABLE_P 608,23142
+INLINE bool SUBRP 609,23186
+INLINE bool 610,23219
+INLINE bool 611,23256
+INLINE bool WINDOWP 612,23297
+INLINE bool TERMINALP 613,23332
+INLINE struct Lisp_Save_Value *XSAVE_VALUE XSAVE_VALUE614,23369
+INLINE struct Lisp_Finalizer *XFINALIZER XFINALIZER615,23427
+INLINE struct Lisp_Symbol *(XSYMBOL)616,23483
+INLINE void 617,23535
+extern Lisp_Object char_table_ref 620,23607
+extern void char_table_set 621,23661
+extern _Noreturn Lisp_Object wrong_type_argument 624,23748
+extern _Noreturn void wrong_choice 625,23825
+extern bool might_dump;628,23916
+extern bool initialized;631,24052
+extern double extract_float 634,24108
+enum symbol_interned639,24190
+ SYMBOL_UNINTERNED 641,24213
+ SYMBOL_INTERNED 642,24238
+ SYMBOL_INTERNED_IN_INITIAL_OBARRAY 643,24261
+enum symbol_redirect646,24306
+ SYMBOL_PLAINVAL 648,24329
+ SYMBOL_VARALIAS 649,24353
+ SYMBOL_LOCALIZED 650,24377
+ SYMBOL_FORWARDED 651,24401
+struct Lisp_Symbol654,24428
+#define EXFUN(707,26243
+#define DEFUN_ARGS_MANY 712,26437
+#define DEFUN_ARGS_UNEVALLED 713,26489
+#define DEFUN_ARGS_0 714,26532
+#define DEFUN_ARGS_1 715,26560
+#define DEFUN_ARGS_2 716,26595
+#define DEFUN_ARGS_3 717,26643
+#define DEFUN_ARGS_4 718,26704
+#define DEFUN_ARGS_5 719,26778
+#define DEFUN_ARGS_6 721,26871
+#define DEFUN_ARGS_7 723,26977
+#define DEFUN_ARGS_8 725,27096
+#define TAG_PTR(729,27287
+#define TAG_SYMOFFSET(734,27534
+#define XLI_BUILTIN_LISPSYM(741,27833
+#define DEFINE_LISP_SYMBOL(746,28092
+# define DEFINE_NON_NIL_Q_SYMBOL_MACROS 755,28563
+LISP_MACRO_DEFUN 762,28768
+# define ARRAY_MARK_FLAG 768,29015
+# define PSEUDOVECTOR_FLAG 774,29258
+enum pvec_type780,29559
+ PVEC_NORMAL_VECTOR,782,29576
+ PVEC_FREE,783,29598
+ PVEC_PROCESS,784,29611
+ PVEC_FRAME,785,29627
+ PVEC_WINDOW,786,29641
+ PVEC_BOOL_VECTOR,787,29656
+ PVEC_BUFFER,788,29676
+ PVEC_HASH_TABLE,789,29691
+ PVEC_TERMINAL,790,29710
+ PVEC_WINDOW_CONFIGURATION,791,29727
+ PVEC_SUBR,792,29756
+ PVEC_OTHER,793,29769
+ PVEC_COMPILED,795,29847
+ PVEC_CHAR_TABLE,796,29864
+ PVEC_SUB_CHAR_TABLE,797,29883
+ PVEC_FONT 798,29906
+enum More_Lisp_Bits801,29982
+ PSEUDOVECTOR_SIZE_BITS 808,30373
+ PSEUDOVECTOR_SIZE_MASK 809,30406
+ PSEUDOVECTOR_REST_BITS 813,30616
+ PSEUDOVECTOR_REST_MASK 814,30649
+ PSEUDOVECTOR_AREA_BITS 818,30814
+ PVEC_TYPE_MASK 819,30892
+# define VALMASK 829,31293
+DEFINE_GDB_SYMBOL_BEGIN VALMASK828,31248
+#define MOST_POSITIVE_FIXNUM 834,31523
+#define MOST_NEGATIVE_FIXNUM 835,31583
+XINT 874,32675
+XFASTINT 889,33026
+XSYMBOL 899,33254
+XTYPE 910,33472
+XUNTAG 918,33652
+LISP_MACRO_DEFUN 927,33848
+LISP_MACRO_DEFUN 940,34233
+#define FIXNUM_OVERFLOW_P(958,34846
+LISP_MACRO_DEFUN FIXNUM_OVERFLOW_P952,34623
+LISP_MACRO_DEFUN 970,35162
+XSTRING 980,35382
+#define SYMBOL_INDEX(988,35566
+XFLOAT 991,35627
+XPROCESS 1000,35769
+XWINDOW 1007,35886
+XTERMINAL 1014,36003
+XSUBR 1021,36125
+XBUFFER 1028,36236
+XCHAR_TABLE 1035,36360
+XSUB_CHAR_TABLE 1042,36497
+XBOOL_VECTOR 1049,36639
+make_lisp_ptr 1058,36818
+make_lisp_symbol 1066,37004
+builtin_lisp_symbol 1074,37188
+#define XSETINT(1079,37270
+#define XSETFASTINT(1080,37316
+#define XSETCONS(1081,37366
+#define XSETVECTOR(1082,37426
+#define XSETSTRING(1083,37494
+#define XSETSYMBOL(1084,37558
+#define XSETFLOAT(1085,37612
+#define XSETMISC(1086,37674
+#define XSETPVECTYPE(1090,37763
+#define XSETPVECTYPESIZE(1092,37879
+#define XSETPSEUDOVECTOR(1099,38176
+#define XSETTYPED_PSEUDOVECTOR(1105,38360
+#define XSETWINDOW_CONFIGURATION(1110,38570
+#define XSETPROCESS(1112,38666
+#define XSETWINDOW(1113,38732
+#define XSETTERMINAL(1114,38796
+#define XSETSUBR(1115,38864
+#define XSETCOMPILED(1116,38924
+#define XSETBUFFER(1117,38992
+#define XSETCHAR_TABLE(1118,39056
+#define XSETBOOL_VECTOR(1119,39128
+#define XSETSUB_CHAR_TABLE(1120,39202
+XINTPTR 1128,39572
+make_pointer_integer 1134,39652
+LISP_MACRO_DEFUN_VOID 1143,39817
+typedef struct interval *INTERVAL;INTERVAL1149,39978
+xcar_addr 1174,40751
+xcdr_addr 1179,40828
+LISP_MACRO_DEFUN 1185,40922
+XSETCDR 1198,41298
+CAR 1205,41448
+CDR 1212,41582
+CAR_SAFE 1221,41782
+CDR_SAFE 1226,41868
+STRING_MULTIBYTE 1243,42241
+#define STRING_BYTES_BOUND 1261,43048
+#define STRING_SET_UNIBYTE(1265,43192
+#define STRING_SET_MULTIBYTE(1275,43507
+SDATA 1286,43821
+SSDATA 1291,43899
+SREF 1297,44028
+SSET 1302,44119
+SCHARS 1307,44233
+extern ptrdiff_t string_bytes 1313,44328
+STRING_BYTES 1316,44406
+SBYTES 1326,44586
+STRING_SET_CHARS 1331,44672
+struct vectorlike_header1343,45223
+struct Lisp_Vector1369,46473
+ ALIGNOF_STRUCT_LISP_VECTOR1378,46672
+struct Lisp_Bool_Vector1384,46855
+bool_vector_size 1399,47376
+bool_vector_data 1407,47514
+bool_vector_uchar_data 1413,47608
+bool_vector_words 1421,47794
+bool_vector_bytes 1428,47989
+bool_vector_bitref 1437,48229
+bool_vector_ref 1445,48469
+bool_vector_set 1453,48609
+ header_size 1471,49038
+ bool_header_size 1472,49097
+ word_size 1473,49162
+AREF 1479,49275
+aref_addr 1485,49382
+ASIZE 1491,49492
+ASET 1497,49574
+gc_aset 1504,49733
+enum { NIL_IS_ZERO 1515,50260
+memclear 1520,50455
+#define VECSIZE(1531,50753
+#define PSEUDOVECSIZE(1538,51038
+#define UNSIGNED_CMP(1546,51471
+#define ASCII_CHAR_P(1552,51725
+enum CHARTAB_SIZE_BITS1565,52480
+ CHARTAB_SIZE_BITS_0 1567,52507
+ CHARTAB_SIZE_BITS_1 1568,52536
+ CHARTAB_SIZE_BITS_2 1569,52565
+ CHARTAB_SIZE_BITS_3 1570,52594
+extern const int chartab_size[chartab_size1573,52628
+struct Lisp_Char_Table1575,52663
+struct Lisp_Sub_Char_Table1606,53743
+CHAR_TABLE_REF_ASCII 1628,54557
+CHAR_TABLE_REF 1648,55104
+CHAR_TABLE_SET 1658,55393
+struct Lisp_Subr1670,55777
+enum char_table_specials1692,56789
+ CHAR_TABLE_STANDARD_SLOTS 1697,56984
+ SUB_CHAR_TABLE_OFFSET 1701,57205
+CHAR_TABLE_EXTRA_SLOTS 1707,57368
+verify 1714,57587
+LISP_MACRO_DEFUN 1723,57912
+SYMBOL_BLV 1732,58172
+SYMBOL_FWD 1738,58307
+LISP_MACRO_DEFUN_VOID 1744,58419
+SET_SYMBOL_BLV 1754,58682
+SET_SYMBOL_FWD 1760,58841
+SYMBOL_NAME 1767,58992
+SYMBOL_INTERNED_P 1775,59121
+SYMBOL_INTERNED_IN_INITIAL_OBARRAY_P 1783,59290
+#define DEFSYM(1796,59800
+LISP_MACRO_DEFUN DEFSYM1792,59621
+struct hash_table_test1805,60053
+struct Lisp_Hash_Table1823,60546
+XHASH_TABLE 1880,62522
+#define XSET_HASH_TABLE(1885,62593
+HASH_TABLE_P 1889,62694
+HASH_KEY 1896,62851
+HASH_VALUE 1903,63031
+HASH_NEXT 1911,63245
+HASH_HASH 1918,63422
+HASH_INDEX 1926,63668
+HASH_TABLE_SIZE 1933,63817
+enum DEFAULT_HASH_SIZE 1940,63947
+enum DEFAULT_HASH_SIZE { DEFAULT_HASH_SIZE 1940,63947
+static double const DEFAULT_REHASH_THRESHOLD 1946,64167
+static double const DEFAULT_REHASH_SIZE 1950,64290
+sxhash_combine 1956,64456
+SXHASH_REDUCE 1964,64639
+struct Lisp_Misc_Any 1971,64797
+struct Lisp_Marker1978,64971
+struct Lisp_Overlay2021,66832
+ SAVE_UNUSED,2047,67635
+ SAVE_INTEGER,2048,67652
+ SAVE_FUNCPOINTER,2049,67670
+ SAVE_POINTER,2050,67692
+ SAVE_OBJECT2051,67710
+enum { SAVE_SLOT_BITS 2055,67795
+enum { SAVE_VALUE_SLOTS 2058,67892
+enum { SAVE_TYPE_BITS 2062,68000
+enum Lisp_Save_Type2064,68066
+ SAVE_TYPE_INT_INT 2066,68090
+ SAVE_TYPE_INT_INT_INT2067,68163
+ SAVE_TYPE_OBJ_OBJ 2069,68253
+ SAVE_TYPE_OBJ_OBJ_OBJ 2070,68324
+ SAVE_TYPE_OBJ_OBJ_OBJ_OBJ2071,68405
+ SAVE_TYPE_PTR_INT 2073,68500
+ SAVE_TYPE_PTR_OBJ 2074,68573
+ SAVE_TYPE_PTR_PTR 2075,68645
+ SAVE_TYPE_FUNCPTR_PTR_OBJ2076,68718
+ SAVE_TYPE_MEMORY 2080,68876
+typedef void (*voidfuncptr)voidfuncptr2108,69830
+struct Lisp_Save_Value2110,69867
+save_type 2134,70746
+XSAVE_POINTER 2143,70976
+set_save_pointer 2149,71138
+XSAVE_FUNCPOINTER 2155,71320
+XSAVE_INTEGER 2164,71540
+set_save_integer 2170,71702
+XSAVE_OBJECT 2179,71923
+struct Lisp_Finalizer2186,72100
+struct Lisp_Free2201,72575
+union Lisp_Misc2212,72876
+XMISC 2223,73175
+XMISCANY 2229,73264
+XMISCTYPE 2236,73373
+XMARKER 2242,73461
+XOVERLAY 2249,73576
+XSAVE_VALUE 2256,73697
+XFINALIZER 2263,73826
+struct Lisp_Intfwd2274,74111
+struct Lisp_Boolfwd2284,74405
+struct Lisp_Objfwd2294,74696
+struct Lisp_Buffer_Objfwd2302,74928
+struct Lisp_Buffer_Local_Value2334,76464
+struct Lisp_Kboard_Objfwd2362,77723
+union Lisp_Fwd2368,77832
+XFWDTYPE 2378,78078
+XBUFFER_OBJFWD 2384,78174
+struct Lisp_Float2391,78310
+XFLOAT_DATA 2401,78428
+ IEEE_FLOATING_POINT2415,78937
+#define _UCHAR_T2423,79260
+typedef unsigned char UCHAR;2424,79277
+enum Lisp_Compiled2429,79360
+ COMPILED_ARGLIST 2431,79383
+ COMPILED_BYTECODE 2432,79409
+ COMPILED_CONSTANTS 2433,79436
+ COMPILED_STACK_DEPTH 2434,79464
+ COMPILED_DOC_STRING 2435,79494
+ COMPILED_INTERACTIVE 2436,79523
+enum char_bits2443,79825
+ CHAR_ALT 2445,79844
+ CHAR_SUPER 2446,79870
+ CHAR_HYPER 2447,79898
+ CHAR_SHIFT 2448,79926
+ CHAR_CTL 2449,79954
+ CHAR_META 2450,79980
+ CHAR_MODIFIER_MASK 2452,80008
+ CHARACTERBITS 2457,80203
+LISP_MACRO_DEFUN 2462,80261
+NATNUMP 2470,80403
+RANGED_INTEGERP 2476,80484
+#define TYPE_RANGED_INTEGERP(2481,80606
+LISP_MACRO_DEFUN 2486,80791
+VECTORP 2500,81264
+OVERLAYP 2505,81367
+SAVE_VALUEP 2510,81466
+FINALIZERP 2516,81572
+AUTOLOADP 2522,81676
+BUFFER_OBJFWDP 2528,81767
+PSEUDOVECTOR_TYPEP 2534,81865
+PSEUDOVECTORP 2542,82118
+WINDOW_CONFIGURATIONP 2558,82470
+PROCESSP 2564,82580
+WINDOWP 2570,82664
+TERMINALP 2576,82746
+SUBRP 2582,82832
+COMPILEDP 2588,82910
+BUFFERP 2594,82996
+CHAR_TABLE_P 2600,83078
+SUB_CHAR_TABLE_P 2606,83169
+BOOL_VECTOR_P 2612,83268
+FRAMEP 2618,83361
+IMAGEP 2625,83478
+ARRAYP 2632,83583
+CHECK_LIST 2638,83702
+LISP_MACRO_DEFUN_VOID 2643,83783
+CHECK_STRING_CAR 2653,84080
+CHECK_CONS 2658,84184
+CHECK_VECTOR 2663,84264
+CHECK_BOOL_VECTOR 2668,84350
+CHECK_VECTOR_OR_STRING 2674,84527
+CHECK_ARRAY 2683,84701
+CHECK_BUFFER 2688,84809
+CHECK_WINDOW 2693,84895
+CHECK_PROCESS 2699,85001
+CHECK_NATNUM 2705,85097
+#define CHECK_RANGED_INTEGER(2710,85174
+#define CHECK_TYPE_RANGED_INTEGER(2721,85557
+#define CHECK_NUMBER_COERCE_MARKER(2729,85827
+XFLOATINT 2738,86080
+CHECK_NUMBER_OR_FLOAT 2744,86151
+#define CHECK_NUMBER_OR_FLOAT_COERCE_MARKER(2749,86250
+CHECK_NUMBER_CAR 2760,86660
+CHECK_NUMBER_CDR 2768,86782
+#define DEFUN(2803,88377
+#define DEFUN(2812,88845
+FUNCTIONP 2822,89200
+extern void defsubr 2829,89352
+enum maxargs2831,89395
+ MANY 2833,89412
+ UNEVALLED 2834,89427
+#define CALLMANY(2838,89530
+#define CALLN(2844,89883
+extern void defvar_lisp 2846,89953
+extern void defvar_lisp_nopro 2847,90030
+extern void defvar_bool 2848,90113
+extern void defvar_int 2849,90184
+extern void defvar_kboard 2850,90258
+#define DEFVAR_LISP(2869,91088
+#define DEFVAR_LISP_NOPRO(2874,91260
+#define DEFVAR_BOOL(2879,91442
+#define DEFVAR_INT(2884,91615
+#define DEFVAR_BUFFER_DEFAULTS(2890,91786
+#define DEFVAR_KBOARD(2896,91990
+typedef jmp_buf sys_jmp_buf;2906,92314
+# define sys_setjmp(2907,92343
+# define sys_longjmp(2908,92378
+typedef sigjmp_buf sys_jmp_buf;2910,92450
+# define sys_setjmp(2911,92482
+# define sys_longjmp(2912,92522
+typedef jmp_buf sys_jmp_buf;2916,92681
+# define sys_setjmp(2917,92710
+# define sys_longjmp(2918,92744
+enum specbind_tag 2943,93796
+ SPECPDL_UNWIND,2944,93816
+ SPECPDL_UNWIND_PTR,2945,93885
+ SPECPDL_UNWIND_INT,2946,93936
+ SPECPDL_UNWIND_VOID,2947,93984
+ SPECPDL_BACKTRACE,2948,94038
+ SPECPDL_LET,2949,94096
+ SPECPDL_LET_LOCAL,2951,94226
+ SPECPDL_LET_DEFAULT 2952,94283
+union specbinding2955,94355
+extern union specbinding *specpdl;specpdl2991,95256
+extern union specbinding *specpdl_ptr;specpdl_ptr2992,95291
+extern ptrdiff_t specpdl_size;2993,95330
+SPECPDL_INDEX 2996,95379
+enum handlertype 3021,96401
+enum handlertype { CATCHER,3021,96401
+enum handlertype { CATCHER, CONDITION_CASE 3021,96401
+struct handler3023,96448
+#define PUSH_HANDLER(3053,97437
+extern Lisp_Object memory_signal_data;3075,98143
+extern char *stack_bottom;stack_bottom3079,98276
+extern void process_pending_signals 3097,99093
+extern bool volatile pending_signals;3098,99137
+extern void process_quit_flag 3100,99176
+#define QUIT 3101,99214
+#define QUITP 3112,99464
+extern Lisp_Object Vascii_downcase_table;3114,99525
+extern Lisp_Object Vascii_canon_table;3115,99567
+extern struct gcpro *gcprolist;gcprolist3130,100274
+struct gcpro3132,100307
+#define GC_USE_GCPROS_AS_BEFORE 3171,101288
+#define GC_MAKE_GCPROS_NOOPS 3172,101323
+#define GC_MARK_STACK_CHECK_GCPROS 3173,101355
+#define GC_USE_GCPROS_CHECK_ZOMBIES 3174,101392
+#define GC_MARK_STACK 3177,101453
+#define BYTE_MARK_STACK 3181,101553
+#define GCPRO1(3190,101824
+#define GCPRO2(3191,101864
+#define GCPRO3(3192,101930
+#define GCPRO4(3194,102025
+#define GCPRO5(3196,102145
+#define GCPRO6(3198,102290
+#define GCPRO7(3201,102465
+#define UNGCPRO 3202,102544
+#define GCPRO1(3208,102644
+#define GCPRO2(3212,102766
+#define GCPRO3(3217,102958
+#define GCPRO4(3223,103220
+#define GCPRO5(3230,103551
+#define GCPRO6(3238,103952
+#define GCPRO7(3247,104422
+#define UNGCPRO 3257,104962
+extern int gcpro_level;3261,105031
+#define GCPRO1(3263,105056
+#define GCPRO2(3269,105290
+#define GCPRO3(3278,105708
+#define GCPRO4(3289,106265
+#define GCPRO5(3302,106963
+#define GCPRO6(3317,107803
+#define GCPRO7(3334,108784
+#define UNGCPRO 3353,109907
+#define RETURN_UNGCPRO(3363,110174
+void staticpro 3375,110447
+vcopy 3384,110648
+set_hash_key_slot 3393,110923
+set_hash_value_slot 3399,111062
+set_symbol_function 3408,111297
+set_symbol_plist 3414,111412
+set_symbol_next 3420,111515
+blv_found 3428,111688
+set_overlay_plist 3437,111871
+string_intervals 3445,112022
+set_string_intervals 3453,112144
+set_char_table_defalt 3462,112346
+set_char_table_purpose 3467,112458
+set_char_table_extras 3475,112627
+set_char_table_contents 3482,112836
+set_sub_char_table_contents 3489,113031
+extern Lisp_Object indirect_function 3495,113190
+extern Lisp_Object find_symbol_value 3496,113242
+enum Arith_Comparison 3497,113294
+ ARITH_EQUAL,3498,113318
+ ARITH_NOTEQUAL,3499,113333
+ ARITH_LESS,3500,113351
+ ARITH_GRTR,3501,113365
+ ARITH_LESS_OR_EQUAL,3502,113379
+ ARITH_GRTR_OR_EQUAL3503,113402
+extern Lisp_Object arithcompare 3505,113427
+#define INTEGER_TO_CONS(3511,113753
+#define CONS_TO_INTEGER(3529,114616
+extern intmax_t cons_to_signed 3533,114831
+extern uintmax_t cons_to_unsigned 3534,114897
+extern struct Lisp_Symbol *indirect_variable indirect_variable3536,114958
+extern _Noreturn void args_out_of_range 3537,115027
+extern _Noreturn void args_out_of_range_3 3538,115095
+extern Lisp_Object do_symval_forwarding 3540,115186
+extern void set_internal 3541,115246
+extern void syms_of_data 3542,115318
+extern void swap_in_global_binding 3543,115351
+extern void syms_of_cmds 3546,115435
+extern void keys_of_cmds 3547,115468
+extern Lisp_Object detect_coding_system 3550,115530
+extern void init_coding 3552,115683
+extern void init_coding_once 3553,115715
+extern void syms_of_coding 3554,115752
+extern ptrdiff_t chars_in_text 3557,115819
+extern ptrdiff_t multibyte_chars_in_text 3558,115886
+extern void syms_of_character 3559,115963
+extern void init_charset 3562,116031
+extern void init_charset_once 3563,116064
+extern void syms_of_charset 3564,116102
+extern void init_syntax_once 3569,116222
+extern void syms_of_syntax 3570,116259
+enum { NEXT_ALMOST_PRIME_LIMIT 3573,116320
+extern EMACS_INT next_almost_prime 3574,116359
+enum constype 3739,123811
+enum constype {CONSTYPE_HEAP,CONSTYPE_HEAP3739,123811
+enum constype {CONSTYPE_HEAP, CONSTYPE_PURE}CONSTYPE_PURE3739,123811
+extern Lisp_Object listn 3740,123857
+list2i 3745,124001
+list3i 3751,124110
+list4i 3757,124249
+extern Lisp_Object make_uninit_bool_vector 3763,124401
+extern Lisp_Object bool_vector_fill 3764,124457
+extern _Noreturn void string_overflow 3765,124521
+extern Lisp_Object make_string 3766,124567
+extern Lisp_Object make_formatted_string 3767,124625
+extern Lisp_Object make_multibyte_string 3779,124979
+extern Lisp_Object make_event_array 3780,125058
+extern Lisp_Object make_uninit_string 3781,125122
+extern Lisp_Object make_uninit_multibyte_string 3782,125173
+extern Lisp_Object make_string_from_bytes 3783,125245
+extern Lisp_Object make_specified_string 3784,125325
+extern Lisp_Object make_pure_string 3786,125417
+extern Lisp_Object make_pure_c_string 3787,125497
+build_pure_c_string 3792,125653
+build_string 3801,125858
+extern Lisp_Object pure_cons 3806,125936
+extern void make_byte_code 3807,125993
+extern struct Lisp_Vector *allocate_vector allocate_vector3808,126044
+make_uninit_vector 3820,126429
+make_uninit_sub_char_table 3833,126648
+extern struct Lisp_Vector *allocate_pseudovector allocate_pseudovector3844,126957
+#define ALLOCATE_PSEUDOVECTOR(3850,127192
+#define ALLOCATE_ZEROED_PSEUDOVECTOR(3858,127528
+extern bool gc_in_progress;3863,127729
+extern bool abort_on_gc;3864,127757
+extern Lisp_Object make_float 3865,127782
+extern void display_malloc_warning 3866,127822
+extern ptrdiff_t inhibit_garbage_collection 3867,127865
+extern Lisp_Object make_save_int_int_int 3868,127917
+extern Lisp_Object make_save_obj_obj_obj_obj 3869,127993
+extern Lisp_Object make_save_ptr 3871,128103
+extern Lisp_Object make_save_ptr_int 3872,128146
+extern Lisp_Object make_save_ptr_ptr 3873,128204
+extern Lisp_Object make_save_funcptr_ptr_obj 3874,128259
+extern Lisp_Object make_save_memory 3876,128355
+extern void free_save_value 3877,128419
+extern Lisp_Object build_overlay 3878,128462
+extern void free_marker 3879,128536
+extern void free_cons 3880,128575
+extern void init_alloc_once 3881,128619
+extern void init_alloc 3882,128655
+extern void syms_of_alloc 3883,128686
+extern struct buffer * allocate_buffer 3884,128720
+extern int valid_lisp_object_p 3885,128767
+extern int relocatable_string_data_p 3886,128813
+extern void check_cons_list 3888,128892
+INLINE void 3890,128934
+extern void *r_alloc r_alloc3895,129055
+#define FLOAT_TO_STRING_BUFSIZE 3927,130518
+extern int openp 3957,131667
+extern Lisp_Object string_to_number 3959,131777
+extern void map_obarray 3960,131840
+extern void dir_warning 3962,131954
+extern void init_obarray 3963,132007
+extern void init_lread 3964,132040
+extern void syms_of_lread 3965,132071
+intern 3968,132125
+intern_c_string 3974,132213
+extern EMACS_INT lisp_eval_depth;3980,132326
+extern Lisp_Object Vautoload_queue;3981,132360
+extern Lisp_Object Vrun_hooks;3982,132396
+extern Lisp_Object Vsignaling_function;3983,132427
+extern Lisp_Object inhibit_lisp_code;3984,132467
+extern struct handler *handlerlist;handlerlist3985,132505
+extern void run_hook 3994,132747
+extern void run_hook_with_args_2 3995,132783
+extern Lisp_Object run_hook_with_args 3996,132857
+extern _Noreturn void xsignal 3999,133016
+extern _Noreturn void xsignal0 4000,133074
+extern _Noreturn void xsignal1 4001,133120
+extern _Noreturn void xsignal2 4002,133179
+extern _Noreturn void xsignal3 4003,133251
+extern _Noreturn void signal_error 4005,133340
+extern Lisp_Object eval_sub 4006,133404
+extern Lisp_Object apply1 4007,133452
+extern Lisp_Object call0 4008,133506
+extern Lisp_Object call1 4009,133546
+extern Lisp_Object call2 4010,133599
+extern Lisp_Object call3 4011,133665
+extern Lisp_Object call4 4012,133744
+extern Lisp_Object call5 4013,133836
+extern Lisp_Object call6 4014,133941
+extern Lisp_Object call7 4015,134059
+extern Lisp_Object internal_catch 4016,134190
+extern Lisp_Object internal_lisp_condition_case 4017,134283
+extern Lisp_Object internal_condition_case 4018,134372
+extern Lisp_Object internal_condition_case_1 4019,134485
+extern Lisp_Object internal_condition_case_2 4020,134620
+extern Lisp_Object internal_condition_case_n4021,134781
+extern void specbind 4024,134977
+extern void record_unwind_protect 4025,135026
+extern void record_unwind_protect_ptr 4026,135099
+extern void record_unwind_protect_int 4027,135166
+extern void record_unwind_protect_void 4028,135227
+extern void record_unwind_protect_nothing 4029,135285
+extern void clear_unwind_protect 4030,135335
+extern void set_unwind_protect 4031,135381
+extern void set_unwind_protect_ptr 4032,135462
+extern Lisp_Object unbind_to 4033,135537
+extern _Noreturn void error 4034,135592
+fast_string_match_ignore_case 4136,140080
+extern ptrdiff_t fast_c_string_match_ignore_case 4141,140230
+extern ptrdiff_t fast_looking_at 4143,140327
+extern ptrdiff_t find_newline 4145,140466
+extern ptrdiff_t scan_newline 4147,140595
+extern ptrdiff_t scan_newline_from_point 4149,140698
+extern ptrdiff_t find_newline_no_quit 4150,140778
+extern ptrdiff_t find_before_next_newline 4152,140875
+extern void syms_of_search 4154,140973
+extern void clear_regexp_cache 4155,141008
+extern Lisp_Object Vminibuffer_list;4159,141078
+extern Lisp_Object last_minibuf_string;4160,141115
+extern Lisp_Object get_minibuffer 4161,141155
+extern void init_minibuf_once 4162,141202
+extern void syms_of_minibuf 4163,141240
+extern void syms_of_callint 4167,141307
+extern void syms_of_casefiddle 4171,141377
+extern void keys_of_casefiddle 4172,141416
+extern void init_casetab_once 4176,141486
+extern void syms_of_casetab 4177,141524
+extern Lisp_Object echo_message_buffer;4181,141592
+extern struct kboard *echo_kboard;echo_kboard4182,141632
+extern void cancel_echoing 4183,141667
+extern Lisp_Object last_undo_boundary;4184,141702
+extern bool input_pending;4185,141741
+extern sigjmp_buf return_to_command_loop;4187,141804
+extern Lisp_Object menu_bar_items 4189,141853
+extern Lisp_Object tool_bar_items 4190,141902
+extern void discard_mouse_events 4191,141958
+void handle_input_available_signal 4193,142019
+extern Lisp_Object pending_funcalls;4195,142068
+extern bool detect_input_pending 4196,142105
+extern bool detect_input_pending_ignore_squeezables 4197,142146
+extern bool detect_input_pending_run_timers 4198,142206
+extern void safe_run_hooks 4199,142258
+extern void cmd_error_internal 4200,142300
+extern Lisp_Object command_loop_1 4201,142360
+extern Lisp_Object read_menu_command 4202,142402
+extern Lisp_Object recursive_edit_1 4203,142447
+extern void record_auto_save 4204,142491
+extern void force_auto_save_soon 4205,142528
+extern void init_keyboard 4206,142569
+extern void syms_of_keyboard 4207,142603
+extern void keys_of_keyboard 4208,142640
+extern ptrdiff_t current_column 4211,142706
+extern void invalidate_current_column 4212,142746
+extern bool indented_beyond_p 4213,142792
+extern void syms_of_indent 4214,142857
+extern void store_frame_param 4217,142920
+extern void store_in_alist 4218,142994
+extern Lisp_Object do_switch_frame 4219,143064
+extern Lisp_Object get_frame_param 4220,143137
+extern void frames_discard_buffer 4221,143203
+extern void syms_of_frame 4222,143252
+extern char **initial_argv;initial_argv4225,143314
+extern int initial_argc;4226,143342
+extern bool display_arg;4228,143417
+extern Lisp_Object decode_env_path 4230,143449
+extern Lisp_Object empty_unibyte_string,4231,143520
+extern Lisp_Object empty_unibyte_string, empty_multibyte_string;4231,143520
+extern _Noreturn void terminate_due_to_signal 4232,143585
+extern Lisp_Object Vlibrary_cache;4234,143660
+void fixup_locale 4237,143721
+void synchronize_system_messages_locale 4238,143747
+void synchronize_system_time_locale 4239,143795
+INLINE void fixup_locale 4241,143845
+INLINE void synchronize_system_messages_locale 4242,143880
+INLINE void synchronize_system_time_locale 4243,143937
+extern void shut_down_emacs 4245,143997
+extern bool noninteractive;4248,144123
+extern bool no_site_lisp;4251,144215
+extern int daemon_pipe[daemon_pipe4256,144383
+#define IS_DAEMON 4257,144410
+#define DAEMON_RUNNING 4258,144450
+extern void *w32_daemon_event;w32_daemon_event4260,144518
+#define IS_DAEMON 4261,144549
+#define DAEMON_RUNNING 4262,144594
+extern bool fatal_error_in_progress;4266,144715
+extern bool inhibit_window_system;4269,144821
+extern bool running_asynch_code;4271,144914
+extern void kill_buffer_processes 4274,144977
+extern int wait_reading_process_output 4275,145026
+# define WAIT_READING_MAX 4281,145413
+# define WAIT_READING_MAX 4283,145485
+extern void add_timer_wait_descriptor 4286,145549
+extern void add_keyboard_wait_descriptor 4288,145601
+extern void delete_keyboard_wait_descriptor 4289,145649
+extern void add_gpm_wait_descriptor 4291,145716
+extern void delete_gpm_wait_descriptor 4292,145759
+extern void init_process_emacs 4294,145812
+extern void syms_of_process 4295,145851
+extern void setup_process_coding_systems 4296,145887
+extern int child_setup 4302,146007
+extern void init_callproc_1 4303,146075
+extern void init_callproc 4304,146111
+extern void set_initial_environment 4305,146145
+extern void syms_of_callproc 4306,146189
+extern Lisp_Object read_doc_string 4309,146252
+extern Lisp_Object get_doc_string 4310,146302
+extern void syms_of_doc 4311,146363
+extern int read_bytecode_char 4312,146395
+extern void syms_of_bytecode 4315,146464
+extern struct byte_stack *byte_stack_list;byte_stack_list4316,146501
+extern void mark_byte_stack 4318,146564
+extern void unmark_byte_stack 4320,146607
+extern Lisp_Object exec_byte_code 4321,146645
+extern void init_macros 4325,146795
+extern void syms_of_macros 4326,146827
+extern void truncate_undo_list 4329,146889
+extern void record_insert 4330,146939
+extern void record_delete 4331,146989
+extern void record_first_change 4332,147047
+extern void record_change 4333,147087
+extern void record_property_change 4334,147137
+extern void syms_of_undo 4337,147279
+extern void report_interval_modification 4340,147343
+extern void syms_of_menu 4343,147439
+extern void syms_of_xmenu 4346,147500
+extern char *get_current_dir_name get_current_dir_name4356,147702
+extern void stuff_char 4358,147751
+extern void init_foreground_group 4359,147784
+extern void sys_subshell 4360,147826
+extern void sys_suspend 4361,147859
+extern void discard_tty_input 4362,147891
+extern void init_sys_modes 4363,147929
+extern void reset_sys_modes 4364,147985
+extern void init_all_sys_modes 4365,148042
+extern void reset_all_sys_modes 4366,148081
+extern void child_setup_tty 4367,148121
+extern void setup_pty 4368,148156
+extern int set_window_size 4369,148185
+extern EMACS_INT get_random 4370,148229
+extern void seed_random 4371,148265
+extern void init_random 4372,148310
+extern void emacs_backtrace 4373,148342
+extern _Noreturn void emacs_abort 4374,148377
+extern void xputenv 4527,152691
+extern char *egetenv_internal egetenv_internal4529,152728
+egetenv 4532,152800
+extern void init_system_name 4539,153003
+#define eabs(4545,153296
+#define make_fixnum_or_float(4550,153429
+enum MAX_ALLOCA 4556,153680
+enum MAX_ALLOCA { MAX_ALLOCA 4556,153680
+extern void *record_xmalloc record_xmalloc4558,153725
+#define USE_SAFE_ALLOCA 4560,153791
+#define AVAIL_ALLOCA(4564,153924
+#define SAFE_ALLOCA(4568,154035
+#define SAFE_NALLOCA(4576,154376
+#define SAFE_ALLOCA_STRING(4590,154852
+#define SAFE_FREE(4598,155104
+#define SAFE_ALLOCA_LISP(4625,155682
+# define USE_STACK_LISP_OBJECTS 4652,156804
+# undef USE_STACK_LISP_OBJECTS4658,156970
+# define USE_STACK_LISP_OBJECTS 4659,157001
+enum { defined_GC_CHECK_STRING_BYTES 4663,157076
+enum { defined_GC_CHECK_STRING_BYTES 4665,157129
+union Aligned_Cons4670,157263
+union Aligned_String4676,157343
+ USE_STACK_CONS 4689,157698
+ USE_STACK_STRING 4691,157804
+#define STACK_CONS(4699,158141
+#define AUTO_CONS_EXPR(4701,158238
+#define AUTO_CONS(4709,158601
+#define AUTO_LIST1(4710,158672
+#define AUTO_LIST2(4712,158780
+#define AUTO_LIST3(4716,158935
+#define AUTO_LIST4(4720,159110
+extern const char *verify_ascii verify_ascii4730,159447
+# define verify_ascii(4732,159501
+#define AUTO_STRING(4740,159809
+#define FOR_EACH_TAIL(4752,160273
+#define FOR_EACH_ALIST_VALUE(4766,160764
+maybe_gc 4774,161051
+functionp 4784,161290
c-src/machsyscalls.c,23
#define SYSCALL(6,113
@@ -2511,27 +2509,27 @@ cp-src/burton.cpp,124
cp-src/functions.cpp,778
void Date::setDate setDate5,148
-void Date::plus plus32,939
-void Date::minus minus42,1229
-void Date::shift shift52,1407
-Date & Date::operator = operator =62,1628
-Date & Date::operator += operator +=69,1789
-Date & Date::operator -= operator -=78,1939
-Date & Date::operator ++ operator ++87,2080
-Date & Date::operator -- operator --96,2216
-int Date::operator - operator -104,2331
-int Date::operator < operator <112,2483
-int Date::operator > operator >116,2557
-int Date::operator == operator ==120,2631
-ostream& operator << operator <<124,2707
-istream& operator >> operator >>133,2943
-bool isLeap 159,3543
-bool isHoliday 163,3629
-void asort(173,3865
-void ReadVacation 186,4064
-void Debug 201,4523
-int WorkingDays(211,4867
-Date StartDay(226,5129
+void Date::plus plus32,938
+void Date::minus minus42,1226
+void Date::shift shift52,1404
+Date & Date::operator = operator =62,1625
+Date & Date::operator += operator +=69,1786
+Date & Date::operator -= operator -=78,1935
+Date & Date::operator ++ operator ++87,2076
+Date & Date::operator -- operator --96,2212
+int Date::operator - operator -104,2327
+int Date::operator < operator <112,2479
+int Date::operator > operator >116,2553
+int Date::operator == operator ==120,2627
+ostream& operator << operator <<124,2703
+istream& operator >> operator >>133,2939
+bool isLeap 159,3539
+bool isHoliday 163,3625
+void asort(173,3861
+void ReadVacation 186,4060
+void Debug 201,4519
+int WorkingDays(211,4863
+Date StartDay(226,5125
cp-src/MDiagArray2.h,1194
#define octave_MDiagArray2_h 29,870
@@ -2712,137 +2710,137 @@ main(37,571
class D 41,622
D(43,659
-el-src/TAGTEST.EL,179
-(foo::defmumble bletch 1,0
-(defun foo==bar foo==bar2,33
-(defalias 'pending-delete-mode pending-delete-mode6,149
-(defalias (quote explicitly-quoted-pending-delete-mode)9,222
+el-src/TAGTEST.EL,181
+(foo::defmumble bletch 3,33
+(defun foo==bar foo==bar4,66
+(defalias 'pending-delete-mode pending-delete-mode8,182
+(defalias (quote explicitly-quoted-pending-delete-mode)11,255
el-src/emacs/lisp/progmodes/etags.el,5188
-(defvar tags-file-name 34,1034
-(defgroup etags 43,1498
-(defcustom tags-case-fold-search 47,1566
-(defcustom tags-table-list 59,2051
-(defcustom tags-compression-info-list69,2449
-(defcustom tags-add-tables 88,3231
-(defcustom tags-revert-without-query 98,3627
-(defvar tags-table-computed-list 103,3778
-(defvar tags-table-computed-list-for 112,4262
-(defvar tags-table-list-pointer 117,4510
-(defvar tags-table-list-started-at 121,4701
-(defvar tags-table-set-list 124,4821
-(defcustom find-tag-hook 129,5000
-(defcustom find-tag-default-function 137,5263
-(define-obsolete-variable-alias 'find-tag-marker-ring-lengthfind-tag-marker-ring-length145,5602
-(defcustom tags-tag-face 148,5699
-(defcustom tags-apropos-verbose 154,5834
-(defcustom tags-apropos-additional-actions 160,5998
-(defvaralias 'find-tag-marker-ring find-tag-marker-ring183,6917
-(defvar default-tags-table-function 189,7097
-(defvar tags-location-ring 194,7323
-(defvar tags-table-files 201,7599
-(defvar tags-completion-table 206,7766
-(defvar tags-included-tables 209,7858
-(defvar next-file-list 212,7953
-(defvar tags-table-format-functions 217,8059
-(defvar file-of-tag-function 224,8440
-(defvar tags-table-files-function 228,8634
-(defvar tags-completion-table-function 230,8745
-(defvar snarf-tag-function 232,8840
-(defvar goto-tag-location-function 236,9049
-(defvar find-tag-regexp-search-function 239,9222
-(defvar find-tag-regexp-tag-order 241,9343
-(defvar find-tag-regexp-next-line-after-failure-p 243,9452
-(defvar find-tag-search-function 245,9572
-(defvar find-tag-tag-order 247,9679
-(defvar find-tag-next-line-after-failure-p 249,9774
-(defvar list-tags-function 251,9880
-(defvar tags-apropos-function 253,9968
-(defvar tags-included-tables-function 255,10062
-(defvar verify-tags-table-function 257,10181
-(defun initialize-new-tags-table 260,10292
-(defun tags-table-mode 276,10980
-(defun visit-tags-table 285,11245
-(defun tags-table-check-computed-list 321,12783
-(defun tags-table-extend-computed-list 360,14654
-(defun tags-expand-table-name 400,16367
-(defun tags-table-list-member 409,16710
-(defun tags-verify-table 421,17182
-(defun tags-table-including 470,19302
-(defun tags-next-table 522,21346
-(defun visit-tags-table-buffer 543,22203
-(defun tags-reset-tags-tables 712,28513
-(defun file-of-tag 731,29170
-(defun tags-table-files 740,29519
-(defun tags-included-tables 749,29869
-(defun tags-completion-table 755,30115
-(defun tags-lazy-completion-table 783,31309
-(defun tags-completion-at-point-function 799,31944
-(defun find-tag-tag 818,32694
-(defvar last-tag 837,33367
-(defun find-tag-interactive 840,33426
-(defvar find-tag-history 852,33841
-(defvar etags-case-fold-search)855,33906
-(defvar etags-syntax-table)856,33938
-(defvar local-find-tag-hook)857,33966
-(defun find-tag-noselect 860,34011
-(defun find-tag 932,37125
-(defun find-tag-other-window 959,38341
-(defun find-tag-other-frame 1000,40269
-(defun find-tag-regexp 1025,41443
-(defalias 'pop-tag-mark pop-tag-mark1049,42605
-(defvar tag-lines-already-matched 1052,42656
-(defun find-tag-in-order 1055,42763
-(defun tag-find-file-of-tag-noselect 1167,47109
-(defun tag-find-file-of-tag 1200,48955
-(defun etags-recognize-tags-table 1208,49181
-(defun etags-verify-tags-table 1241,50812
-(defun etags-file-of-tag 1246,51010
-(defun etags-tags-completion-table 1256,51345
-(defun etags-snarf-tag 1286,52551
-(defun etags-goto-tag-location 1324,54120
-(defun etags-list-tags 1388,56563
-(defmacro tags-with-face 1423,57838
-(defun etags-tags-apropos-additional 1431,58171
-(defun etags-tags-apropos 1465,59408
-(defun etags-tags-table-files 1527,61617
-(defun etags-tags-included-tables 1542,62053
-(defun tags-recognize-empty-tags-table 1559,62593
-(defun tag-exact-file-name-match-p 1587,63739
-(defun tag-file-name-match-p 1596,64132
-(defun tag-exact-match-p 1609,64688
-(defun tag-implicit-name-match-p 1620,65256
-(defun tag-symbol-match-p 1633,65856
-(defun tag-word-match-p 1643,66292
-(defun tag-partial-file-name-match-p 1652,66690
-(defun tag-any-match-p 1662,67134
-(defun tag-re-match-p 1667,67318
-(defcustom tags-loop-revert-buffers 1675,67567
-(defun next-file 1685,67976
-(defvar tags-loop-operate 1760,70890
-(defvar tags-loop-scan1763,70984
-(defun tags-loop-eval 1771,71313
-(defun tags-loop-continue 1782,71642
-(defun tags-search 1850,73948
-(defun tags-query-replace 1871,74774
-(defun tags-complete-tags-table-file 1896,75998
-(defun list-tags 1906,76377
-(defun tags-apropos 1934,77330
-(define-button-type 'tags-select-tags-tabletags-select-tags-table1957,78156
-(defun select-tags-table 1964,78395
-(defvar select-tags-table-mode-map 2019,80522
-(define-derived-mode select-tags-table-mode 2030,80905
-(defun select-tags-table-select 2034,81089
-(defun select-tags-table-quit 2043,81455
-(defun complete-tag 2049,81610
-(defconst etags--xref-limit 2074,82551
-(defvar etags-xref-find-definitions-tag-order 2076,82586
-(defun etags-xref-find 2082,82876
-(defun etags--xref-find-definitions 2096,83405
-(defclass xref-etags-location 2129,85119
-(defun xref-make-etags-location 2135,85342
-(cl-defmethod xref-location-marker 2139,85497
-(cl-defmethod xref-location-line 2146,85741
+(defvar tags-file-name 34,1035
+(defgroup etags 43,1499
+(defcustom tags-case-fold-search 47,1567
+(defcustom tags-table-list 59,2052
+(defcustom tags-compression-info-list69,2450
+(defcustom tags-add-tables 88,3232
+(defcustom tags-revert-without-query 98,3628
+(defvar tags-table-computed-list 103,3779
+(defvar tags-table-computed-list-for 112,4263
+(defvar tags-table-list-pointer 117,4511
+(defvar tags-table-list-started-at 121,4702
+(defvar tags-table-set-list 124,4822
+(defcustom find-tag-hook 129,5001
+(defcustom find-tag-default-function 137,5264
+(define-obsolete-variable-alias 'find-tag-marker-ring-lengthfind-tag-marker-ring-length145,5603
+(defcustom tags-tag-face 148,5700
+(defcustom tags-apropos-verbose 154,5835
+(defcustom tags-apropos-additional-actions 160,5999
+(defvaralias 'find-tag-marker-ring find-tag-marker-ring183,6921
+(defvar default-tags-table-function 189,7101
+(defvar tags-location-ring 194,7327
+(defvar tags-table-files 201,7603
+(defvar tags-completion-table 206,7770
+(defvar tags-included-tables 209,7862
+(defvar next-file-list 212,7957
+(defvar tags-table-format-functions 217,8063
+(defvar file-of-tag-function 224,8444
+(defvar tags-table-files-function 228,8638
+(defvar tags-completion-table-function 230,8749
+(defvar snarf-tag-function 232,8844
+(defvar goto-tag-location-function 236,9053
+(defvar find-tag-regexp-search-function 239,9226
+(defvar find-tag-regexp-tag-order 241,9347
+(defvar find-tag-regexp-next-line-after-failure-p 243,9456
+(defvar find-tag-search-function 245,9576
+(defvar find-tag-tag-order 247,9683
+(defvar find-tag-next-line-after-failure-p 249,9778
+(defvar list-tags-function 251,9884
+(defvar tags-apropos-function 253,9972
+(defvar tags-included-tables-function 255,10066
+(defvar verify-tags-table-function 257,10185
+(defun initialize-new-tags-table 260,10296
+(defun tags-table-mode 276,10984
+(defun visit-tags-table 285,11249
+(defun tags-table-check-computed-list 321,12787
+(defun tags-table-extend-computed-list 360,14658
+(defun tags-expand-table-name 400,16371
+(defun tags-table-list-member 409,16714
+(defun tags-verify-table 421,17186
+(defun tags-table-including 470,19306
+(defun tags-next-table 522,21350
+(defun visit-tags-table-buffer 543,22207
+(defun tags-reset-tags-tables 712,28517
+(defun file-of-tag 731,29174
+(defun tags-table-files 740,29524
+(defun tags-included-tables 749,29874
+(defun tags-completion-table 755,30120
+(defun tags-lazy-completion-table 783,31314
+(defun tags-completion-at-point-function 799,31949
+(defun find-tag-tag 818,32699
+(defvar last-tag 837,33372
+(defun find-tag-interactive 840,33431
+(defvar find-tag-history 852,33846
+(defvar etags-case-fold-search)855,33911
+(defvar etags-syntax-table)856,33943
+(defvar local-find-tag-hook)857,33971
+(defun find-tag-noselect 860,34016
+(defun find-tag 932,37130
+(defun find-tag-other-window 959,38346
+(defun find-tag-other-frame 1000,40274
+(defun find-tag-regexp 1025,41448
+(defalias 'pop-tag-mark pop-tag-mark1049,42610
+(defvar tag-lines-already-matched 1052,42661
+(defun find-tag-in-order 1055,42768
+(defun tag-find-file-of-tag-noselect 1167,47114
+(defun tag-find-file-of-tag 1200,48960
+(defun etags-recognize-tags-table 1208,49186
+(defun etags-verify-tags-table 1241,50817
+(defun etags-file-of-tag 1246,51015
+(defun etags-tags-completion-table 1256,51350
+(defun etags-snarf-tag 1286,52556
+(defun etags-goto-tag-location 1324,54125
+(defun etags-list-tags 1388,56568
+(defmacro tags-with-face 1423,57843
+(defun etags-tags-apropos-additional 1431,58176
+(defun etags-tags-apropos 1465,59413
+(defun etags-tags-table-files 1527,61622
+(defun etags-tags-included-tables 1542,62058
+(defun tags-recognize-empty-tags-table 1559,62598
+(defun tag-exact-file-name-match-p 1587,63744
+(defun tag-file-name-match-p 1596,64137
+(defun tag-exact-match-p 1609,64693
+(defun tag-implicit-name-match-p 1620,65261
+(defun tag-symbol-match-p 1633,65861
+(defun tag-word-match-p 1643,66297
+(defun tag-partial-file-name-match-p 1652,66695
+(defun tag-any-match-p 1662,67139
+(defun tag-re-match-p 1667,67323
+(defcustom tags-loop-revert-buffers 1675,67572
+(defun next-file 1685,67981
+(defvar tags-loop-operate 1760,70895
+(defvar tags-loop-scan1763,70989
+(defun tags-loop-eval 1771,71318
+(defun tags-loop-continue 1782,71647
+(defun tags-search 1850,73953
+(defun tags-query-replace 1871,74779
+(defun tags-complete-tags-table-file 1896,76003
+(defun list-tags 1906,76382
+(defun tags-apropos 1934,77335
+(define-button-type 'tags-select-tags-tabletags-select-tags-table1957,78161
+(defun select-tags-table 1964,78400
+(defvar select-tags-table-mode-map 2019,80527
+(define-derived-mode select-tags-table-mode 2030,80910
+(defun select-tags-table-select 2034,81094
+(defun select-tags-table-quit 2043,81460
+(defun complete-tag 2049,81615
+(defconst etags--xref-limit 2074,82556
+(defvar etags-xref-find-definitions-tag-order 2076,82591
+(defun etags-xref-find 2082,82881
+(defun etags--xref-find-definitions 2096,83410
+(defclass xref-etags-location 2129,85124
+(defun xref-make-etags-location 2135,85347
+(cl-defmethod xref-location-marker 2139,85502
+(cl-defmethod xref-location-line 2146,85746
erl-src/gs_dialog.erl,98
-define(VERSION2,32
@@ -2913,10 +2911,10 @@ func main(29,285
html-src/softwarelibero.html,200
Cos'è il software libero?4,38
-Licenze d'uso di un programmalicenze65,2500
-Sfatiamo alcuni miti138,6118
-Il movimento open sourceoss191,8037
-Impatto pratico del software liberoimpatto231,10066
+Licenze d'uso di un programmalicenze65,2502
+Sfatiamo alcuni miti138,6122
+Il movimento open sourceoss191,8041
+Impatto pratico del software liberoimpatto231,10070
html-src/index.shtml,104
&nbsp;8,281
@@ -2942,13 +2940,13 @@ MTGmtg41,1482
Fracasfracas65,2624
GaliLEOgalileo101,4232
Leasqrleasqr114,4677
-Free software that I wrote for the GNU project or for my personal or workgnu142,6065
-Etagsetags148,6180
-checkiso161,6729
-cgrep178,7547
-debian-bug.eldebian-bug190,7979
-tcpdump205,8564
-Links to interesting softwarelinks216,8891
+Free software that I wrote for the GNU project or for my personal or workgnu142,6066
+Etagsetags148,6181
+checkiso161,6731
+cgrep178,7549
+debian-bug.eldebian-bug190,7981
+tcpdump205,8566
+Links to interesting softwarelinks216,8893
lua-src/allegro.lua,400
local function get_layer_by_name 7,175
@@ -3479,22 +3477,22 @@ ord_add_element(71,1867
ord_del_element(85,2344
ord_disjoint(100,2783
ord_intersect(108,2953
-ord_intersection(126,3552
-ord_intersection3(130,3691
-ord_intersection(150,4531
-ord_intersection4(154,4703
-ord_intersection(176,5664
-ord_intersection2(181,5812
-ord_member(200,6318
-ord_seteq(216,6683
-ord_setproduct(225,6971
-ord_subset(240,7377
-ord_subtract(257,7861
-ord_symdiff(265,8054
-ord_union(288,8887
-ord_union4(303,9352
-ord_union(324,10171
-ord_union_all(329,10313
+ord_intersection(126,3553
+ord_intersection3(130,3692
+ord_intersection(150,4533
+ord_intersection4(154,4705
+ord_intersection(176,5666
+ord_intersection2(181,5814
+ord_member(200,6320
+ord_seteq(216,6685
+ord_setproduct(225,6973
+ord_subset(240,7379
+ord_subtract(257,7863
+ord_symdiff(265,8056
+ord_union(288,8889
+ord_union4(303,9354
+ord_union(324,10173
+ord_union_all(329,10315
prol-src/natded.prolog,2319
expandmng(100,2879
@@ -3516,92 +3514,92 @@ complete(328,10055
add_active(340,10527
parse(353,10949
derived_analyses(364,11341
-build(378,11965
-buildact(392,12521
-mapsyn(412,13542
-add_edge(434,14278
-findcats(447,14758
-normalize_tree(465,15478
-normalize_trees(475,15856
-expandmng_tree(486,16248
-expandmng_trees(496,16614
-cat(511,17013
-subtree(644,21266
-hypothetical_mem(653,21565
-make_coor(667,22130
-start_up:-start_up688,23013
-tokenizeatom(710,23921
-tokenize(720,24348
-isoperator(752,25377
-isoptab(756,25431
-specialsymbol(765,25756
-sstab(771,25861
-parse_cgi(787,26347
-keyvalseq(792,26510
-andkeyvalseq(796,26609
-keyval(799,26688
-valseq(807,26920
-plusvalseq(810,27007
-val(816,27109
-argvals(824,27426
-commaargvals(828,27503
-atomval(833,27578
-atom(836,27640
-action(846,28004
-keyvalcgi(864,28649
-keyvalscgi(865,28670
-outsyn(868,28726
-act(876,29060
-actout(901,29906
-texttreelist(912,30089
-htmltreelist(918,30190
-fitchtreelist(924,30304
-pp_html_table_tree(938,30759
-pp_html_tree(949,31113
-pp_html_trees(988,32381
-pp_html_table_fitch_tree(999,32769
-pp_html_fitch_tree(1017,33672
-removeexp(1129,39002
-splitexp(1142,39490
-pp_exp(1155,39990
-map_word(1168,40249
-pp_exps(1180,40474
-pp_tree(1188,40777
-pp_trees(1216,41807
-pp_word_list(1225,42128
-pp_word(1231,42262
-pp_word_list_rest(1238,42569
-pp_cat(1248,42929
-pp_syn(1255,43196
-pp_syn_paren(1276,43899
-pp_paren(1293,44377
-pp_syn_back(1300,44661
-pp_bas_cat(1311,45001
-writecat(1322,45409
-writesubs(1351,46455
-writesups(1361,46757
-writelistsubs(1371,47090
-pp_lam(1380,47408
-pp_lam_bracket(1398,48022
-pp_lam_paren(1407,48338
-pp_rule(1429,49238
-member(1447,49866
-append_list(1451,49919
-append(1456,50010
-at_least_one_member(1460,50076
-numbervars(1464,50171
-reverse(1467,50209
-select(1471,50290
-select_last(1475,50357
-cat_atoms(1479,50436
-writelist(1485,50524
-write_lex_cat(1492,50676
-writebreaklex(1500,50988
-write_lex(1513,51265
-writebreak(1521,51541
-tt:-tt1531,51713
-mt:-mt1534,51784
-cmt:-cmt1537,51878
+build(378,11967
+buildact(392,12523
+mapsyn(412,13544
+add_edge(434,14280
+findcats(447,14760
+normalize_tree(465,15480
+normalize_trees(475,15858
+expandmng_tree(486,16250
+expandmng_trees(496,16616
+cat(511,17015
+subtree(644,21268
+hypothetical_mem(653,21567
+make_coor(667,22132
+start_up:-start_up688,23015
+tokenizeatom(710,23923
+tokenize(720,24350
+isoperator(752,25379
+isoptab(756,25433
+specialsymbol(765,25758
+sstab(771,25863
+parse_cgi(787,26349
+keyvalseq(792,26512
+andkeyvalseq(796,26611
+keyval(799,26690
+valseq(807,26922
+plusvalseq(810,27009
+val(816,27111
+argvals(824,27428
+commaargvals(828,27505
+atomval(833,27580
+atom(836,27642
+action(846,28006
+keyvalcgi(864,28651
+keyvalscgi(865,28672
+outsyn(868,28728
+act(876,29062
+actout(901,29908
+texttreelist(912,30091
+htmltreelist(918,30192
+fitchtreelist(924,30306
+pp_html_table_tree(938,30761
+pp_html_tree(949,31115
+pp_html_trees(988,32383
+pp_html_table_fitch_tree(999,32771
+pp_html_fitch_tree(1017,33674
+removeexp(1129,39004
+splitexp(1142,39492
+pp_exp(1155,39992
+map_word(1168,40251
+pp_exps(1180,40476
+pp_tree(1188,40779
+pp_trees(1216,41809
+pp_word_list(1225,42130
+pp_word(1231,42264
+pp_word_list_rest(1238,42571
+pp_cat(1248,42931
+pp_syn(1255,43198
+pp_syn_paren(1276,43901
+pp_paren(1293,44379
+pp_syn_back(1300,44663
+pp_bas_cat(1311,45003
+writecat(1322,45411
+writesubs(1351,46457
+writesups(1361,46759
+writelistsubs(1371,47092
+pp_lam(1380,47410
+pp_lam_bracket(1398,48024
+pp_lam_paren(1407,48340
+pp_rule(1429,49240
+member(1447,49868
+append_list(1451,49921
+append(1456,50012
+at_least_one_member(1460,50078
+numbervars(1464,50173
+reverse(1467,50211
+select(1471,50292
+select_last(1475,50359
+cat_atoms(1479,50438
+writelist(1485,50526
+write_lex_cat(1492,50678
+writebreaklex(1500,50990
+write_lex(1513,51267
+writebreak(1521,51543
+tt:-tt1531,51715
+mt:-mt1534,51786
+cmt:-cmt1537,51880
pyt-src/server.py,1438
class Controls:Controls17,358
@@ -3709,6 +3707,11 @@ module A9,57
alias_method ( :foo2,foo237,586
A::Constant Constant42,655
+rs-src/test.rs,52
+enum IpAddrKind 3,11
+fn test1(8,48
+fn main(12,88
+
scm-src/test.scm,260
(define hello 1,0
(set! hello 3,32
@@ -3726,730 +3729,884 @@ tex-src/gzip.texi,303
@node Top,62,2139
@node Copying,80,2652
@node Overview,83,2705
-@node Sample,166,7272
-@node Invoking gzip,Invoking gzip210,8828
-@node Advanced usage,Advanced usage357,13496
-@node Environment,420,15208
-@node Tapes,437,15769
-@node Problems,460,16768
-@node Concept Index,Concept Index473,17288
+@node Sample,166,7273
+@node Invoking gzip,Invoking gzip210,8829
+@node Advanced usage,Advanced usage357,13497
+@node Environment,420,15209
+@node Tapes,437,15770
+@node Problems,460,16769
+@node Concept Index,Concept Index473,17289
tex-src/texinfo.tex,30627
-\def\texinfoversion{\texinfoversion26,1032
-\def\tie{\tie49,1523
-\def\gloggingall{\gloggingall72,2273
-\def\loggingall{\loggingall73,2342
-\def\onepageout#1{\onepageout99,3279
-\def\croppageout#1{\croppageout115,4029
-\def\cropmarks{\cropmarks142,5089
-\def\pagebody#1{\pagebody144,5136
-\def\ewtop{\ewtop157,5591
-\def\nstop{\nstop158,5655
-\def\ewbot{\ewbot160,5738
-\def\nsbot{\nsbot161,5802
-\def\parsearg #1{\parsearg170,6101
-\def\parseargx{\parseargx172,6179
-\def\parseargline{\parseargline182,6419
-\def\flushcr{\flushcr186,6540
-\newif\ifENV \ENVfalse \def\inENV{\inENV190,6739
-\def\ENVcheck{\ENVcheck191,6803
-\outer\def\begin{\begin198,7050
-\def\beginxxx #1{\beginxxx200,7088
-\def\end{\end208,7343
-\def\endxxx #1{\endxxx210,7371
-\def\errorE#1{\errorE216,7560
-\def\singlespace{\singlespace222,7754
-\def\@{\@232,7977
-\def\`{\`236,8077
-\def\'{\'237,8089
-\def\mylbrace {\mylbrace241,8137
-\def\myrbrace {\myrbrace242,8170
-\def\:{\:247,8284
-\def\*{\*250,8338
-\def\.{\.253,8414
-\def\w#1{\w258,8645
-\def\group{\group268,9128
- \def\Egroup{\Egroup273,9292
-\def\need{\need289,9734
-\def\needx#1{\needx300,10011
-\def\dots{\dots339,11397
-\def\page{\page343,11461
-\def\exdent{\exdent353,11788
-\def\exdentyyy #1{\exdentyyy354,11821
-\def\nofillexdent{\nofillexdent357,11965
-\def\nofillexdentyyy #1{\nofillexdentyyy358,12010
-\def\include{\include365,12194
-\def\includezzz #1{\includezzz366,12229
-\def\thisfile{\thisfile369,12280
-\def\center{\center373,12343
-\def\centerzzz #1{\centerzzz374,12376
-\def\sp{\sp380,12518
-\def\spxxx #1{\spxxx381,12543
-\def\comment{\comment387,12717
-\def\commentxxx #1{\commentxxx390,12814
-\def\ignoresections{\ignoresections396,12983
-\let\chapter=\relax=\relax397,13005
-\let\section=\relax=\relax406,13250
-\let\subsection=\relax=\relax409,13311
-\let\subsubsection=\relax=\relax410,13334
-\let\appendix=\relax=\relax411,13360
-\let\appendixsec=\relaxsec=\relax412,13381
-\let\appendixsection=\relaxsection=\relax413,13405
-\let\appendixsubsec=\relaxsubsec=\relax414,13433
-\let\appendixsubsection=\relaxsubsection=\relax415,13460
-\let\appendixsubsubsec=\relaxsubsubsec=\relax416,13491
-\let\appendixsubsubsection=\relaxsubsubsection=\relax417,13521
-\def\ignore{\ignore423,13623
-\long\def\ignorexxx #1\end ignore{\ignorexxx427,13763
-\def\direntry{\direntry429,13822
-\long\def\direntryxxx #1\end direntry{\direntryxxx430,13861
-\def\ifset{\ifset434,13971
-\def\ifsetxxx #1{\ifsetxxx436,14029
-\def\Eifset{\Eifset440,14156
-\def\ifsetfail{\ifsetfail441,14170
-\long\def\ifsetfailxxx #1\end ifset{\ifsetfailxxx442,14226
-\def\ifclear{\ifclear444,14287
-\def\ifclearxxx #1{\ifclearxxx446,14349
-\def\Eifclear{\Eifclear450,14480
-\def\ifclearfail{\ifclearfail451,14496
-\long\def\ifclearfailxxx #1\end ifclear{\ifclearfailxxx452,14556
-\def\set{\set456,14707
-\def\setxxx #1{\setxxx457,14734
-\def\clear{\clear460,14796
-\def\clearxxx #1{\clearxxx461,14827
-\def\iftex{\iftex466,14944
-\def\Eiftex{\Eiftex467,14957
-\def\ifinfo{\ifinfo468,14971
-\long\def\ifinfoxxx #1\end ifinfo{\ifinfoxxx469,15021
-\long\def\menu #1\end menu{\menu471,15080
-\def\asis#1{\asis472,15109
-\def\math#1{\math485,15652
-\def\node{\node487,15696
-\def\nodezzz#1{\nodezzz488,15734
-\def\nodexxx[#1,#2]{\nodexxx[489,15765
-\def\donoderef{\donoderef492,15827
-\def\unnumbnoderef{\unnumbnoderef496,15948
-\def\appendixnoderef{\appendixnoderef500,16079
-\expandafter\expandafter\expandafter\appendixsetref{setref501,16125
-\let\refill=\relaxill=\relax504,16214
-\def\setfilename{\setfilename509,16428
-\outer\def\bye{\bye518,16674
-\def\inforef #1{\inforef520,16730
-\def\inforefzzz #1,#2,#3,#4**{\inforefzzz521,16768
-\def\losespace #1{\losespace523,16865
-\def\sf{\sf532,17069
-\font\defbf=cmbx10 scaled \magstep1 %was 1314bf=cmbx10558,17864
-\font\deftt=cmtt10 scaled \magstep1tt=cmtt10559,17910
-\def\df{\df560,17946
-\def\resetmathfonts{\resetmathfonts635,20540
-\def\textfonts{\textfonts648,21129
-\def\chapfonts{\chapfonts653,21344
-\def\secfonts{\secfonts658,21560
-\def\subsecfonts{\subsecfonts663,21765
-\def\indexfonts{\indexfonts668,21982
-\def\smartitalicx{\smartitalicx691,22714
-\def\smartitalic#1{\smartitalic692,22790
-\let\cite=\smartitalic=\smartitalic698,22935
-\def\b#1{\b700,22959
-\def\t#1{\t703,22994
-\def\samp #1{\samp706,23146
-\def\key #1{\key707,23179
-\def\ctrl #1{\ctrl708,23240
-\def\tclose#1{\tclose716,23442
-\def\ {\720,23608
-\def\xkey{\xkey728,23877
-\def\kbdfoo#1#2#3\par{\kbdfoo729,23893
-\def\dmn#1{\dmn738,24194
-\def\kbd#1{\kbd740,24221
-\def\l#1{\l742,24278
-\def\r#1{\r744,24307
-\def\sc#1{\sc746,24375
-\def\ii#1{\ii747,24418
-\def\titlefont#1{\titlefont755,24651
-\def\titlepage{\titlepage761,24754
- \def\subtitlefont{\subtitlefont766,24981
- \def\authorfont{\authorfont768,25065
- \def\title{\title774,25275
- \def\titlezzz##1{\titlezzz775,25310
- \def\subtitle{\subtitle783,25625
- \def\subtitlezzz##1{\subtitlezzz784,25666
- \def\author{\author787,25784
- \def\authorzzz##1{\authorzzz788,25821
- \def\page{\page794,26112
-\def\Etitlepage{\Etitlepage804,26281
-\def\finishtitlepage{\finishtitlepage817,26669
-\def\evenheading{\evenheading846,27677
-\def\oddheading{\oddheading847,27720
-\def\everyheading{\everyheading848,27761
-\def\evenfooting{\evenfooting850,27807
-\def\oddfooting{\oddfooting851,27850
-\def\everyfooting{\everyfooting852,27891
-\def\headings #1 {\headings893,29583
-\def\HEADINGSoff{\HEADINGSoff895,29632
-\def\HEADINGSdouble{\HEADINGSdouble904,30059
-\def\HEADINGSsingle{\HEADINGSsingle914,30379
-\def\HEADINGSon{\HEADINGSon922,30600
-\def\HEADINGSafter{\HEADINGSafter924,30634
-\def\HEADINGSdoublex{\HEADINGSdoublex926,30729
-\def\HEADINGSsingleafter{\HEADINGSsingleafter933,30917
-\def\HEADINGSsinglex{\HEADINGSsinglex934,30978
-\def\today{\today943,31253
-\def\thistitle{\thistitle958,31798
-\def\settitle{\settitle959,31823
-\def\settitlezzz #1{\settitlezzz960,31860
-\def\internalBitem{\internalBitem992,32790
-\def\internalBitemx{\internalBitemx993,32840
-\def\internalBxitem "#1"{\internalBxitem995,32885
-\def\internalBxitemx "#1"{\internalBxitemx996,32965
-\def\internalBkitem{\internalBkitem998,33040
-\def\internalBkitemx{\internalBkitemx999,33092
-\def\kitemzzz #1{\kitemzzz1001,33139
-\def\xitemzzz #1{\xitemzzz1004,33241
-\def\itemzzz #1{\itemzzz1007,33344
-\def\item{\item1037,34415
-\def\itemx{\itemx1038,34466
-\def\kitem{\kitem1039,34519
-\def\kitemx{\kitemx1040,34572
-\def\xitem{\xitem1041,34627
-\def\xitemx{\xitemx1042,34680
-\def\description{\description1045,34790
-\def\table{\table1047,34840
-\def\ftable{\ftable1052,34984
-\def\Eftable{\Eftable1056,35130
-\def\vtable{\vtable1059,35199
-\def\Evtable{\Evtable1063,35345
-\def\dontindex #1{\dontindex1066,35414
-\def\fnitemindex #1{\fnitemindex1067,35434
-\def\vritemindex #1{\vritemindex1068,35479
-\def\tablez #1#2#3#4#5#6{\tablez1074,35628
-\def\Edescription{\Edescription1077,35686
-\def\itemfont{\itemfont1082,35888
-\def\Etable{\Etable1090,36114
-\def\itemize{\itemize1103,36438
-\def\itemizezzz #1{\itemizezzz1105,36474
-\def\itemizey #1#2{\itemizey1110,36569
-\def#2{1119,36815
-\def\itemcontents{\itemcontents1120,36856
-\def\bullet{\bullet1123,36904
-\def\minus{\minus1124,36931
-\def\frenchspacing{\frenchspacing1128,37039
-\def\splitoff#1#2\endmark{\splitoff1134,37264
-\def\enumerate{\enumerate1140,37494
-\def\enumeratezzz #1{\enumeratezzz1141,37533
-\def\enumeratey #1 #2\endenumeratey{\enumeratey1142,37586
- \def\thearg{\thearg1146,37733
- \ifx\thearg\empty \def\thearg{\thearg1147,37752
-\def\numericenumerate{\numericenumerate1184,39086
-\def\lowercaseenumerate{\lowercaseenumerate1190,39216
-\def\uppercaseenumerate{\uppercaseenumerate1203,39563
-\def\startenumeration#1{\startenumeration1219,40053
-\def\alphaenumerate{\alphaenumerate1227,40235
-\def\capsenumerate{\capsenumerate1228,40270
-\def\Ealphaenumerate{\Ealphaenumerate1229,40304
-\def\Ecapsenumerate{\Ecapsenumerate1230,40338
-\def\itemizeitem{\itemizeitem1234,40418
-\def\newindex #1{\newindex1259,41275
-\def\defindex{\defindex1268,41564
-\def\newcodeindex #1{\newcodeindex1272,41672
-\def\defcodeindex{\defcodeindex1279,41932
-\def\synindex #1 #2 {\synindex1283,42112
-\def\syncodeindex #1 #2 {\syncodeindex1292,42452
-\def\doindex#1{\doindex1309,43131
-\def\singleindexer #1{\singleindexer1310,43190
-\def\docodeindex#1{\docodeindex1313,43302
-\def\singlecodeindexer #1{\singlecodeindexer1314,43369
-\def\indexdummies{\indexdummies1316,43427
-\def\_{\_1317,43447
-\def\w{\w1318,43475
-\def\bf{\bf1319,43502
-\def\rm{\rm1320,43531
-\def\sl{\sl1321,43560
-\def\sf{\sf1322,43589
-\def\tt{\tt1323,43617
-\def\gtr{\gtr1324,43645
-\def\less{\less1325,43675
-\def\hat{\hat1326,43707
-\def\char{\char1327,43737
-\def\TeX{\TeX1328,43769
-\def\dots{\dots1329,43799
-\def\copyright{\copyright1330,43832
-\def\tclose##1{\tclose1331,43875
-\def\code##1{\code1332,43920
-\def\samp##1{\samp1333,43961
-\def\t##1{\t1334,44002
-\def\r##1{\r1335,44037
-\def\i##1{\i1336,44072
-\def\b##1{\b1337,44107
-\def\cite##1{\cite1338,44142
-\def\key##1{\key1339,44183
-\def\file##1{\file1340,44222
-\def\var##1{\var1341,44263
-\def\kbd##1{\kbd1342,44302
-\def\indexdummyfont#1{\indexdummyfont1347,44458
-\def\indexdummytex{\indexdummytex1348,44484
-\def\indexdummydots{\indexdummydots1349,44508
-\def\indexnofonts{\indexnofonts1351,44534
-\let\w=\indexdummyfontdummyfont1352,44554
-\let\t=\indexdummyfontdummyfont1353,44577
-\let\r=\indexdummyfontdummyfont1354,44600
-\let\i=\indexdummyfontdummyfont1355,44623
-\let\b=\indexdummyfontdummyfont1356,44646
-\let\emph=\indexdummyfontdummyfont1357,44669
-\let\strong=\indexdummyfontdummyfont1358,44695
-\let\cite=\indexdummyfont=\indexdummyfont1359,44723
-\let\sc=\indexdummyfontdummyfont1360,44749
-\let\tclose=\indexdummyfontdummyfont1364,44921
-\let\code=\indexdummyfontdummyfont1365,44949
-\let\file=\indexdummyfontdummyfont1366,44975
-\let\samp=\indexdummyfontdummyfont1367,45001
-\let\kbd=\indexdummyfontdummyfont1368,45027
-\let\key=\indexdummyfontdummyfont1369,45052
-\let\var=\indexdummyfontdummyfont1370,45077
-\let\TeX=\indexdummytexdummytex1371,45102
-\let\dots=\indexdummydotsdummydots1372,45126
-\let\indexbackslash=0 %overridden during \printindex.backslash=01382,45378
-\def\doind #1#2{\doind1384,45434
-{\indexdummies % Must do this here, since \bf, etc expand at this stagedummies1386,45477
-\def\rawbackslashxx{\rawbackslashxx1389,45617
-{\indexnofontsnofonts1394,45879
-\def\dosubind #1#2#3{\dosubind1405,46190
-{\indexdummies % Must do this here, since \bf, etc expand at this stagedummies1407,46238
-\def\rawbackslashxx{\rawbackslashxx1410,46342
-{\indexnofontsnofonts1414,46496
-\def\findex {\findex1443,47427
-\def\kindex {\kindex1444,47450
-\def\cindex {\cindex1445,47473
-\def\vindex {\vindex1446,47496
-\def\tindex {\tindex1447,47519
-\def\pindex {\pindex1448,47542
-\def\cindexsub {\cindexsub1450,47566
-\def\printindex{\printindex1462,47893
-\def\doprintindex#1{\doprintindex1464,47934
- \def\indexbackslash{\indexbackslash1481,48419
- \indexfonts\rm \tolerance=9500 \advance\baselineskip -1ptfonts\rm1482,48458
-\def\initial #1{\initial1517,49530
-\def\entry #1#2{\entry1523,49737
- \null\nobreak\indexdotfill % Have leaders before the page number.dotfill1540,50384
-\def\indexdotfill{\indexdotfill1549,50712
-\def\primary #1{\primary1552,50818
-\def\secondary #1#2{\secondary1556,50900
-\noindent\hskip\secondaryindent\hbox{#1}\indexdotfill #2\pardotfill1559,50982
-\newbox\partialpageialpage1566,51155
-\def\begindoublecolumns{\begindoublecolumns1572,51313
- \output={\global\setbox\partialpage=ialpage=1573,51349
-\def\enddoublecolumns{\enddoublecolumns1577,51537
-\def\doublecolumnout{\doublecolumnout1580,51622
- \dimen@=\pageheight \advance\dimen@ by-\ht\partialpageialpage1581,51691
-\def\pagesofar{\pagesofar1584,51869
-\def\balancecolumns{\balancecolumns1588,52106
- \availdimen@=\pageheight \advance\availdimen@ by-\ht\partialpageialpage1594,52277
- \dimen@=\pageheight \advance\dimen@ by-\ht\partialpageialpage1600,52538
-\newcount \appendixno \appendixno = `\@no1627,53443
-\def\appendixletter{\appendixletter1628,53484
-\def\opencontents{\opencontents1632,53587
-\def\thischapter{\thischapter1637,53768
-\def\seccheck#1{\seccheck1638,53806
-\def\chapternofonts{\chapternofonts1643,53910
-\def\result{\result1646,53985
-\def\equiv{\equiv1647,54020
-\def\expansion{\expansion1648,54053
-\def\print{\print1649,54094
-\def\TeX{\TeX1650,54127
-\def\dots{\dots1651,54156
-\def\copyright{\copyright1652,54187
-\def\tt{\tt1653,54228
-\def\bf{\bf1654,54255
-\def\w{\w1655,54283
-\def\less{\less1656,54308
-\def\gtr{\gtr1657,54339
-\def\hat{\hat1658,54368
-\def\char{\char1659,54397
-\def\tclose##1{\tclose1660,54428
-\def\code##1{\code1661,54472
-\def\samp##1{\samp1662,54512
-\def\r##1{\r1663,54552
-\def\b##1{\b1664,54586
-\def\key##1{\key1665,54620
-\def\file##1{\file1666,54658
-\def\kbd##1{\kbd1667,54698
-\def\i##1{\i1669,54806
-\def\cite##1{\cite1670,54840
-\def\var##1{\var1671,54880
-\def\emph##1{\emph1672,54918
-\def\dfn##1{\dfn1673,54958
-\def\thischaptername{\thischaptername1676,54999
-\outer\def\chapter{\chapter1677,55038
-\def\chapterzzz #1{\chapterzzz1678,55079
-{\chapternofonts%nofonts%1687,55475
-\global\let\section = \numberedsec=1692,55628
-\global\let\subsection = \numberedsubsec=1693,55663
-\global\let\subsubsection = \numberedsubsubsec=1694,55704
-\outer\def\appendix{\appendix1697,55755
-\def\appendixzzz #1{\appendixzzz1698,55798
-\global\advance \appendixno by 1 \message{no1700,55875
-\chapmacro {#1}{Appendix \appendixletter}letter1701,55944
-\xdef\thischapter{Appendix \appendixletter: \noexpand\thischaptername}letter:1704,56037
-{\chapternofonts%nofonts%1705,56109
- {#1}{Appendix \appendixletter}letter1707,56165
-\appendixnoderef %noderef1710,56265
-\global\let\section = \appendixsec=1711,56284
-\global\let\subsection = \appendixsubsec=1712,56319
-\global\let\subsubsection = \appendixsubsubsec=1713,56360
-\outer\def\top{\top1716,56411
-\outer\def\unnumbered{\unnumbered1717,56451
-\def\unnumberedzzz #1{\unnumberedzzz1718,56498
-{\chapternofonts%nofonts%1722,56661
-\global\let\section = \unnumberedsec=1727,56811
-\global\let\subsection = \unnumberedsubsec=1728,56848
-\global\let\subsubsection = \unnumberedsubsubsec=1729,56891
-\outer\def\numberedsec{\numberedsec1732,56944
-\def\seczzz #1{\seczzz1733,56985
-{\chapternofonts%nofonts%1736,57141
-\outer\def\appendixsection{\appendixsection1745,57327
-\outer\def\appendixsec{\appendixsec1746,57384
-\def\appendixsectionzzz #1{\appendixsectionzzz1747,57437
-\gdef\thissection{#1}\secheading {#1}{\appendixletter}letter1749,57549
-{\chapternofonts%nofonts%1750,57617
-{#1}{\appendixletter}letter1752,57673
-\appendixnoderef %noderef1755,57773
-\outer\def\unnumberedsec{\unnumberedsec1759,57813
-\def\unnumberedseczzz #1{\unnumberedseczzz1760,57866
-{\chapternofonts%nofonts%1762,57961
-\outer\def\numberedsubsec{\numberedsubsec1770,58129
-\def\numberedsubseczzz #1{\numberedsubseczzz1771,58184
-{\chapternofonts%nofonts%1774,58363
-\outer\def\appendixsubsec{\appendixsubsec1783,58567
-\def\appendixsubseczzz #1{\appendixsubseczzz1784,58622
-\subsecheading {#1}{\appendixletter}letter1786,58744
-{\chapternofonts%nofonts%1787,58809
-{#1}{\appendixletter}letter1789,58868
-\appendixnoderef %noderef1792,58983
-\outer\def\unnumberedsubsec{\unnumberedsubsec1796,59023
-\def\unnumberedsubseczzz #1{\unnumberedsubseczzz1797,59082
-{\chapternofonts%nofonts%1799,59183
-\outer\def\numberedsubsubsec{\numberedsubsubsec1807,59354
-\def\numberedsubsubseczzz #1{\numberedsubsubseczzz1808,59415
-{\chapternofonts%nofonts%1812,59612
-\outer\def\appendixsubsubsec{\appendixsubsubsec1823,59845
-\def\appendixsubsubseczzz #1{\appendixsubsubseczzz1824,59906
- {\appendixletter}letter1827,60045
-{\chapternofonts%nofonts%1828,60111
- {\appendixletter}letter1830,60176
-\appendixnoderef %noderef1834,60310
-\outer\def\unnumberedsubsubsec{\unnumberedsubsubsec1838,60350
-\def\unnumberedsubsubseczzz #1{\unnumberedsubsubseczzz1839,60415
-{\chapternofonts%nofonts%1841,60522
-\def\infotop{\infotop1851,60851
-\def\infounnumbered{\infounnumbered1852,60889
-\def\infounnumberedsec{\infounnumberedsec1853,60934
-\def\infounnumberedsubsec{\infounnumberedsubsec1854,60985
-\def\infounnumberedsubsubsec{\infounnumberedsubsubsec1855,61042
-\def\infoappendix{\infoappendix1857,61106
-\def\infoappendixsec{\infoappendixsec1858,61147
-\def\infoappendixsubsec{\infoappendixsubsec1859,61194
-\def\infoappendixsubsubsec{\infoappendixsubsubsec1860,61247
-\def\infochapter{\infochapter1862,61307
-\def\infosection{\infosection1863,61346
-\def\infosubsection{\infosubsection1864,61385
-\def\infosubsubsection{\infosubsubsection1865,61430
-\global\let\section = \numberedsec=1870,61667
-\global\let\subsection = \numberedsubsec=1871,61702
-\global\let\subsubsection = \numberedsubsubsec=1872,61743
-\def\majorheading{\majorheading1886,62250
-\def\majorheadingzzz #1{\majorheadingzzz1887,62295
-\def\chapheading{\chapheading1893,62528
-\def\chapheadingzzz #1{\chapheadingzzz1894,62571
-\def\heading{\heading1899,62766
-\def\subheading{\subheading1901,62803
-\def\subsubheading{\subsubheading1903,62846
-\def\dobreak#1#2{\dobreak1910,63123
-\def\setchapterstyle #1 {\setchapterstyle1912,63201
-\def\chapbreak{\chapbreak1919,63456
-\def\chappager{\chappager1920,63506
-\def\chapoddpage{\chapoddpage1921,63544
-\def\setchapternewpage #1 {\setchapternewpage1923,63623
-\def\CHAPPAGoff{\CHAPPAGoff1925,63680
-\def\CHAPPAGon{\CHAPPAGon1929,63774
-\global\def\HEADINGSon{\HEADINGSon1932,63865
-\def\CHAPPAGodd{\CHAPPAGodd1934,63907
-\global\def\HEADINGSon{\HEADINGSon1937,64003
-\def\CHAPFplain{\CHAPFplain1941,64057
-\def\chfplain #1#2{\chfplain1945,64149
-\def\unnchfplain #1{\unnchfplain1956,64372
-\def\unnchfopen #1{\unnchfopen1964,64601
-\def\chfopen #1#2{\chfopen1970,64809
-\def\CHAPFopen{\CHAPFopen1975,64953
-\def\subsecheadingbreak{\subsecheadingbreak1982,65171
-\def\secheadingbreak{\secheadingbreak1985,65300
-\def\secheading #1#2#3{\secheading1993,65582
-\def\plainsecheading #1{\plainsecheading1994,65638
-\def\secheadingi #1{\secheadingi1995,65681
-\def\subsecheading #1#2#3#4{\subsecheading2006,66049
-\def\subsecheadingi #1{\subsecheadingi2007,66116
-\def\subsubsecfonts{\subsubsecfonts2014,66413
-\def\subsubsecheading #1#2#3#4#5{\subsubsecheading2017,66536
-\def\subsubsecheadingi #1{\subsubsecheadingi2018,66614
-\def\startcontents#1{\startcontents2032,67086
- \unnumbchapmacro{#1}\def\thischapter{\thischapter2040,67359
-\outer\def\contents{\contents2049,67718
-\outer\def\summarycontents{\summarycontents2057,67862
- \def\secentry ##1##2##3##4{\secentry2067,68233
- \def\unnumbsecentry ##1##2{\unnumbsecentry2068,68268
- \def\subsecentry ##1##2##3##4##5{\subsecentry2069,68303
- \def\unnumbsubsecentry ##1##2{\unnumbsubsecentry2070,68344
- \def\subsubsecentry ##1##2##3##4##5##6{\subsubsecentry2071,68382
- \def\unnumbsubsubsecentry ##1##2{\unnumbsubsubsecentry2072,68429
-\def\chapentry#1#2#3{\chapentry2085,68863
-\def\shortchapentry#1#2#3{\shortchapentry2088,68980
- {#2\labelspace #1}space2091,69090
-\def\unnumbchapentry#1#2{\unnumbchapentry2094,69144
-\def\shortunnumberedentry#1#2{\shortunnumberedentry2095,69191
-\def\secentry#1#2#3#4{\secentry2102,69355
-\def\unnumbsecentry#1#2{\unnumbsecentry2103,69414
-\def\subsecentry#1#2#3#4#5{\subsecentry2106,69475
-\def\unnumbsubsecentry#1#2{\unnumbsubsecentry2107,69545
-\def\subsubsecentry#1#2#3#4#5#6{\subsubsecentry2110,69619
- \dosubsubsecentry{#2.#3.#4.#5\labelspace#1}space2111,69653
-\def\unnumbsubsubsecentry#1#2{\unnumbsubsubsecentry2112,69704
-\def\dochapentry#1#2{\dochapentry2123,70078
-\def\dosecentry#1#2{\dosecentry2138,70683
-\def\dosubsecentry#1#2{\dosubsecentry2145,70861
-\def\dosubsubsecentry#1#2{\dosubsubsecentry2152,71046
-\def\labelspace{\labelspace2160,71297
-\def\dopageno#1{\dopageno2162,71332
-\def\doshortpageno#1{\doshortpageno2163,71358
-\def\chapentryfonts{\chapentryfonts2165,71390
-\def\secentryfonts{\secentryfonts2166,71425
-\def\point{\point2192,72384
-\def\result{\result2194,72405
-\def\expansion{\expansion2195,72478
-\def\print{\print2196,72549
-\def\equiv{\equiv2198,72616
-\def\error{\error2218,73389
-\def\tex{\tex2224,73618
-\def\@{\@2242,74001
-\gdef\sepspaces{\def {\ }}}\2265,74733
-\def\aboveenvbreak{\aboveenvbreak2268,74815
-\def\afterenvbreak{\afterenvbreak2272,74981
-\def\ctl{\ctl2286,75492
-\def\ctr{\ctr2287,75564
-\def\cbl{\cbl2288,75603
-\def\cbr{\cbr2289,75643
-\def\carttop{\carttop2290,75682
-\def\cartbot{\cartbot2293,75790
-\long\def\cartouche{\cartouche2299,75930
-\def\Ecartouche{\Ecartouche2326,76718
-\def\lisp{\lisp2338,76853
-\def\Elisp{\Elisp2348,77200
-\def\next##1{\next2360,77526
-\def\Eexample{\Eexample2364,77568
-\def\Esmallexample{\Esmallexample2367,77615
-\def\smalllispx{\smalllispx2373,77793
-\def\Esmalllisp{\Esmalllisp2383,78147
-\obeyspaces \obeylines \ninett \indexfonts \rawbackslashfonts2396,78503
-\def\next##1{\next2397,78560
-\def\display{\display2401,78640
-\def\Edisplay{\Edisplay2410,78959
-\def\next##1{\next2422,79270
-\def\format{\format2426,79373
-\def\Eformat{\Eformat2434,79669
-\def\next##1{\next2437,79758
-\def\flushleft{\flushleft2441,79810
-\def\Eflushleft{\Eflushleft2451,80181
-\def\next##1{\next2454,80274
-\def\flushright{\flushright2456,80296
-\def\Eflushright{\Eflushright2466,80668
-\def\next##1{\next2470,80799
-\def\quotation{\quotation2474,80857
-\def\Equotation{\Equotation2480,81049
-\def\setdeffont #1 {\setdeffont2493,81447
-\newskip\defbodyindent \defbodyindent=.4inbodyindent2495,81493
-\newskip\defargsindent \defargsindent=50ptargsindent2496,81536
-\newskip\deftypemargin \deftypemargin=12pttypemargin2497,81579
-\newskip\deflastargmargin \deflastargmargin=18ptlastargmargin2498,81622
-\def\activeparens{\activeparens2503,81820
-\def\opnr{\opnr2529,83032
-\def\lbrb{\lbrb2530,83097
-\def\defname #1#2{\defname2536,83298
-\advance\dimen2 by -\defbodyindentbodyindent2540,83416
-\advance\dimen3 by -\defbodyindentbodyindent2542,83470
-\setbox0=\hbox{\hskip \deflastargmargin{lastargmargin2544,83524
-\dimen1=\hsize \advance \dimen1 by -\defargsindent %size for continuationsargsindent2546,83666
-\parshape 2 0in \dimen0 \defargsindent \dimen1 %argsindent2547,83741
-\rlap{\rightline{{\rm #2}\hskip \deftypemargin}typemargin2554,84110
-\advance\leftskip by -\defbodyindentbodyindent2557,84244
-\exdentamount=\defbodyindentbodyindent2558,84281
-\def\defparsebody #1#2#3{\defparsebody2568,84640
-\def#1{2572,84824
-\def#2{2573,84860
-\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2575,84932
-\exdentamount=\defbodyindentbodyindent2576,85006
-\def\defmethparsebody #1#2#3#4 {\defmethparsebody2581,85110
-\def#1{2585,85271
-\def#2##1 {2586,85307
-\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2588,85390
-\exdentamount=\defbodyindentbodyindent2589,85464
-\def\defopparsebody #1#2#3#4#5 {\defopparsebody2592,85549
-\def#1{2596,85710
-\def#2##1 ##2 {2597,85746
-\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2600,85846
-\exdentamount=\defbodyindentbodyindent2601,85920
-\def\defvarparsebody #1#2#3{\defvarparsebody2608,86191
-\def#1{2612,86378
-\def#2{2613,86414
-\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2615,86473
-\exdentamount=\defbodyindentbodyindent2616,86547
-\def\defvrparsebody #1#2#3#4 {\defvrparsebody2621,86638
-\def#1{2625,86797
-\def#2##1 {2626,86833
-\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2628,86903
-\exdentamount=\defbodyindentbodyindent2629,86977
-\def\defopvarparsebody #1#2#3#4#5 {\defopvarparsebody2632,87049
-\def#1{2636,87213
-\def#2##1 ##2 {2637,87249
-\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2640,87336
-\exdentamount=\defbodyindentbodyindent2641,87410
-\def\defunargs #1{\defunargs2664,88170
-\def\deftypefunargs #1{\deftypefunargs2676,88552
-\def\deffn{\deffn2690,88934
-\def\deffnheader #1#2#3{\deffnheader2692,88991
-\begingroup\defname {name2693,89039
-\def\defun{\defun2699,89184
-\def\defunheader #1#2{\defunheader2701,89237
-\begingroup\defname {name2702,89312
-\defunargs {unargs2703,89348
-\def\deftypefun{\deftypefun2709,89496
-\def\deftypefunheader #1#2{\deftypefunheader2712,89618
-\def\deftypefunheaderx #1#2 #3\relax{\deftypefunheaderx2714,89727
-\begingroup\defname {name2716,89819
-\deftypefunargs {typefunargs2717,89865
-\def\deftypefn{\deftypefn2723,90036
-\def\deftypefnheader #1#2#3{\deftypefnheader2726,90185
-\def\deftypefnheaderx #1#2#3 #4\relax{\deftypefnheaderx2728,90321
-\begingroup\defname {name2730,90414
-\deftypefunargs {typefunargs2731,90454
-\def\defmac{\defmac2737,90575
-\def\defmacheader #1#2{\defmacheader2739,90632
-\begingroup\defname {name2740,90708
-\defunargs {unargs2741,90741
-\def\defspec{\defspec2747,90865
-\def\defspecheader #1#2{\defspecheader2749,90926
-\begingroup\defname {name2750,91003
-\defunargs {unargs2751,91043
-\def\deffnx #1 {\deffnx2758,91238
-\def\defunx #1 {\defunx2759,91295
-\def\defmacx #1 {\defmacx2760,91352
-\def\defspecx #1 {\defspecx2761,91411
-\def\deftypefnx #1 {\deftypefnx2762,91472
-\def\deftypeunx #1 {\deftypeunx2763,91537
-\def\defop #1 {\defop2769,91683
-\defopparsebody\Edefop\defopx\defopheader\defoptype}opparsebody\Edefop\defopx\defopheader\defoptype2770,91718
-\def\defopheader #1#2#3{\defopheader2772,91772
-\begingroup\defname {name2774,91861
-\defunargs {unargs2775,91907
-\def\defmethod{\defmethod2780,91968
-\def\defmethodheader #1#2#3{\defmethodheader2782,92041
-\begingroup\defname {name2784,92129
-\defunargs {unargs2785,92169
-\def\defcv #1 {\defcv2790,92243
-\defopvarparsebody\Edefcv\defcvx\defcvarheader\defcvtype}opvarparsebody\Edefcv\defcvx\defcvarheader\defcvtype2791,92278
-\def\defcvarheader #1#2#3{\defcvarheader2793,92337
-\begingroup\defname {name2795,92423
-\defvarargs {varargs2796,92469
-\def\defivar{\defivar2801,92542
-\def\defivarheader #1#2#3{\defivarheader2803,92605
-\begingroup\defname {name2805,92691
-\defvarargs {varargs2806,92742
-\def\defopx #1 {\defopx2812,92891
-\def\defmethodx #1 {\defmethodx2813,92948
-\def\defcvx #1 {\defcvx2814,93013
-\def\defivarx #1 {\defivarx2815,93070
-\def\defvarargs #1{\defvarargs2822,93341
-\def\defvr{\defvr2828,93485
-\def\defvrheader #1#2#3{\defvrheader2830,93540
-\begingroup\defname {name2831,93588
-\def\defvar{\defvar2835,93673
-\def\defvarheader #1#2{\defvarheader2837,93733
-\begingroup\defname {name2838,93804
-\defvarargs {varargs2839,93840
-\def\defopt{\defopt2844,93906
-\def\defoptheader #1#2{\defoptheader2846,93966
-\begingroup\defname {name2847,94037
-\defvarargs {varargs2848,94076
-\def\deftypevar{\deftypevar2853,94133
-\def\deftypevarheader #1#2{\deftypevarheader2856,94249
-\begingroup\defname {name2858,94332
-\def\deftypevr{\deftypevr2865,94506
-\def\deftypevrheader #1#2#3{\deftypevrheader2867,94577
-\begingroup\defname {name2868,94629
-\def\defvrx #1 {\defvrx2876,94866
-\def\defvarx #1 {\defvarx2877,94923
-\def\defoptx #1 {\defoptx2878,94982
-\def\deftypevarx #1 {\deftypevarx2879,95041
-\def\deftypevrx #1 {\deftypevrx2880,95108
-\def\deftpargs #1{\deftpargs2885,95257
-\def\deftp{\deftp2889,95337
-\def\deftpheader #1#2#3{\deftpheader2891,95392
-\begingroup\defname {name2892,95440
-\def\deftpx #1 {\deftpx2897,95599
-\def\setref#1{\setref2908,95920
-\def\unnumbsetref#1{\unnumbsetref2913,96034
-\def\appendixsetref#1{\appendixsetref2918,96141
-\def\pxref#1{\pxref2929,96552
-\def\xref#1{\xref2930,96588
-\def\ref#1{\ref2931,96623
-\def\xrefX[#1,#2,#3,#4,#5,#6]{\xrefX[2932,96653
-\def\printedmanual{\printedmanual2933,96696
-\def\printednodename{\printednodename2934,96734
-\def\printednodename{\printednodename2939,96859
-section ``\printednodename'' in \cite{\printedmanual}\printedmanual2954,97492
-\refx{x2957,97570
-\def\dosetq #1#2{\dosetq2965,97790
-\def\internalsetq #1#2{\internalsetq2973,98048
-\def\Ypagenumber{\Ypagenumber2977,98149
-\def\Ytitle{\Ytitle2979,98175
-\def\Ynothing{\Ynothing2981,98202
-\def\Ysectionnumberandtype{\Ysectionnumberandtype2983,98219
-\def\Yappendixletterandtype{\Yappendixletterandtype2992,98535
-\ifnum\secno=0 Appendix\xreftie'char\the\appendixno{no2993,98565
-\else \ifnum \subsecno=0 Section\xreftie'char\the\appendixno.\the\secno %no.\the\secno2994,98620
-Section\xreftie'char\the\appendixno.\the\secno.\the\subsecno %no.\the\secno.\the\subsecno2996,98724
-Section\xreftie'char\the\appendixno.\the\secno.\the\subsecno.\the\subsubsecno %no.\the\secno.\the\subsecno.\the\subsubsecno2998,98795
- \def\linenumber{\linenumber3009,99134
-\def\refx#1#2{\refx3015,99318
-\def\xrdef #1#2{\xrdef3037,99944
-\def\readauxfile{\readauxfile3040,100029
-\def\supereject{\supereject3110,101810
-\footstrut\parindent=\defaultparindent\hang\textindent{aultparindent\hang\textindent3131,102495
-\def\openindices{\openindices3139,102681
-\newdimen\defaultparindent \defaultparindent = 15ptaultparindent3151,102906
-\parindent = \defaultparindentaultparindent3152,102958
-\def\smallbook{\smallbook3175,103682
-\global\def\Esmallexample{\Esmallexample3192,104109
-\def\afourpaper{\afourpaper3196,104200
-\def\finalout{\finalout3224,105008
-\def\normaldoublequote{\normaldoublequote3235,105269
-\def\normaltilde{\normaltilde3236,105295
-\def\normalcaret{\normalcaret3237,105315
-\def\normalunderscore{\normalunderscore3238,105335
-\def\normalverticalbar{\normalverticalbar3239,105360
-\def\normalless{\normalless3240,105386
-\def\normalgreater{\normalgreater3241,105405
-\def\normalplus{\normalplus3242,105427
-\def\ifusingtt#1#2{\ifusingtt3253,105919
-\def\activedoublequote{\activedoublequote3261,106247
-\def~{~3264,106333
-\def^{^3267,106394
-\def_{_3270,106433
-\def\_{\_3272,106507
-\def\lvvmode{\lvvmode3279,106844
-\def|{|3282,106894
-\def<{<3285,106957
-\def>{>3288,107014
-\def+{+3290,107052
-\def\turnoffactive{\turnoffactive3296,107213
-\global\def={=3307,107499
-\def\normalbackslash{\normalbackslash3321,107881
+\def\texinfoversion{\texinfoversion26,1035
+\def\tie{\tie49,1526
+\def\gloggingall{\gloggingall72,2276
+\def\loggingall{\loggingall73,2345
+\def\onepageout#1{\onepageout99,3282
+\def\croppageout#1{\croppageout115,4032
+\def\cropmarks{\cropmarks142,5092
+\def\pagebody#1{\pagebody144,5139
+\def\ewtop{\ewtop157,5594
+\def\nstop{\nstop158,5658
+\def\ewbot{\ewbot160,5741
+\def\nsbot{\nsbot161,5805
+\def\parsearg #1{\parsearg170,6104
+\def\parseargx{\parseargx172,6182
+\def\parseargline{\parseargline182,6422
+\def\flushcr{\flushcr186,6543
+\newif\ifENV \ENVfalse \def\inENV{\inENV190,6742
+\def\ENVcheck{\ENVcheck191,6806
+\outer\def\begin{\begin198,7053
+\def\beginxxx #1{\beginxxx200,7091
+\def\end{\end208,7346
+\def\endxxx #1{\endxxx210,7374
+\def\errorE#1{\errorE216,7563
+\def\singlespace{\singlespace222,7757
+\def\@{\@232,7980
+\def\`{\`236,8080
+\def\'{\'237,8092
+\def\mylbrace {\mylbrace241,8140
+\def\myrbrace {\myrbrace242,8173
+\def\:{\:247,8287
+\def\*{\*250,8341
+\def\.{\.253,8417
+\def\w#1{\w258,8648
+\def\group{\group268,9131
+ \def\Egroup{\Egroup273,9295
+\def\need{\need289,9737
+\def\needx#1{\needx300,10014
+\def\dots{\dots339,11400
+\def\page{\page343,11464
+\def\exdent{\exdent353,11791
+\def\exdentyyy #1{\exdentyyy354,11824
+\def\nofillexdent{\nofillexdent357,11968
+\def\nofillexdentyyy #1{\nofillexdentyyy358,12013
+\def\include{\include365,12197
+\def\includezzz #1{\includezzz366,12232
+\def\thisfile{\thisfile369,12283
+\def\center{\center373,12346
+\def\centerzzz #1{\centerzzz374,12379
+\def\sp{\sp380,12521
+\def\spxxx #1{\spxxx381,12546
+\def\comment{\comment387,12720
+\def\commentxxx #1{\commentxxx390,12817
+\def\ignoresections{\ignoresections396,12986
+\let\chapter=\relax=\relax397,13008
+\let\section=\relax=\relax406,13253
+\let\subsection=\relax=\relax409,13314
+\let\subsubsection=\relax=\relax410,13337
+\let\appendix=\relax=\relax411,13363
+\let\appendixsec=\relaxsec=\relax412,13384
+\let\appendixsection=\relaxsection=\relax413,13408
+\let\appendixsubsec=\relaxsubsec=\relax414,13436
+\let\appendixsubsection=\relaxsubsection=\relax415,13463
+\let\appendixsubsubsec=\relaxsubsubsec=\relax416,13494
+\let\appendixsubsubsection=\relaxsubsubsection=\relax417,13524
+\def\ignore{\ignore423,13626
+\long\def\ignorexxx #1\end ignore{\ignorexxx427,13766
+\def\direntry{\direntry429,13825
+\long\def\direntryxxx #1\end direntry{\direntryxxx430,13864
+\def\ifset{\ifset434,13974
+\def\ifsetxxx #1{\ifsetxxx436,14032
+\def\Eifset{\Eifset440,14159
+\def\ifsetfail{\ifsetfail441,14173
+\long\def\ifsetfailxxx #1\end ifset{\ifsetfailxxx442,14229
+\def\ifclear{\ifclear444,14290
+\def\ifclearxxx #1{\ifclearxxx446,14352
+\def\Eifclear{\Eifclear450,14483
+\def\ifclearfail{\ifclearfail451,14499
+\long\def\ifclearfailxxx #1\end ifclear{\ifclearfailxxx452,14559
+\def\set{\set456,14710
+\def\setxxx #1{\setxxx457,14737
+\def\clear{\clear460,14799
+\def\clearxxx #1{\clearxxx461,14830
+\def\iftex{\iftex466,14947
+\def\Eiftex{\Eiftex467,14960
+\def\ifinfo{\ifinfo468,14974
+\long\def\ifinfoxxx #1\end ifinfo{\ifinfoxxx469,15024
+\long\def\menu #1\end menu{\menu471,15083
+\def\asis#1{\asis472,15112
+\def\math#1{\math485,15655
+\def\node{\node487,15699
+\def\nodezzz#1{\nodezzz488,15737
+\def\nodexxx[#1,#2]{\nodexxx[489,15768
+\def\donoderef{\donoderef492,15830
+\def\unnumbnoderef{\unnumbnoderef496,15951
+\def\appendixnoderef{\appendixnoderef500,16082
+\expandafter\expandafter\expandafter\appendixsetref{setref501,16128
+\let\refill=\relaxill=\relax504,16217
+\def\setfilename{\setfilename509,16431
+\outer\def\bye{\bye518,16677
+\def\inforef #1{\inforef520,16733
+\def\inforefzzz #1,#2,#3,#4**{\inforefzzz521,16771
+\def\losespace #1{\losespace523,16868
+\def\sf{\sf532,17072
+\font\defbf=cmbx10 scaled \magstep1 %was 1314bf=cmbx10558,17867
+\font\deftt=cmtt10 scaled \magstep1tt=cmtt10559,17913
+\def\df{\df560,17949
+\def\resetmathfonts{\resetmathfonts635,20543
+\def\textfonts{\textfonts648,21132
+\def\chapfonts{\chapfonts653,21347
+\def\secfonts{\secfonts658,21563
+\def\subsecfonts{\subsecfonts663,21768
+\def\indexfonts{\indexfonts668,21985
+\def\smartitalicx{\smartitalicx691,22717
+\def\smartitalic#1{\smartitalic692,22793
+\let\cite=\smartitalic=\smartitalic698,22938
+\def\b#1{\b700,22962
+\def\t#1{\t703,22997
+\def\samp #1{\samp706,23149
+\def\key #1{\key707,23182
+\def\ctrl #1{\ctrl708,23243
+\def\tclose#1{\tclose716,23445
+\def\ {\720,23611
+\def\xkey{\xkey728,23880
+\def\kbdfoo#1#2#3\par{\kbdfoo729,23896
+\def\dmn#1{\dmn738,24197
+\def\kbd#1{\kbd740,24224
+\def\l#1{\l742,24281
+\def\r#1{\r744,24310
+\def\sc#1{\sc746,24378
+\def\ii#1{\ii747,24421
+\def\titlefont#1{\titlefont755,24654
+\def\titlepage{\titlepage761,24757
+ \def\subtitlefont{\subtitlefont766,24984
+ \def\authorfont{\authorfont768,25068
+ \def\title{\title774,25278
+ \def\titlezzz##1{\titlezzz775,25313
+ \def\subtitle{\subtitle783,25628
+ \def\subtitlezzz##1{\subtitlezzz784,25669
+ \def\author{\author787,25787
+ \def\authorzzz##1{\authorzzz788,25824
+ \def\page{\page794,26115
+\def\Etitlepage{\Etitlepage804,26284
+\def\finishtitlepage{\finishtitlepage817,26672
+\def\evenheading{\evenheading846,27680
+\def\oddheading{\oddheading847,27723
+\def\everyheading{\everyheading848,27764
+\def\evenfooting{\evenfooting850,27810
+\def\oddfooting{\oddfooting851,27853
+\def\everyfooting{\everyfooting852,27894
+\def\headings #1 {\headings893,29586
+\def\HEADINGSoff{\HEADINGSoff895,29635
+\def\HEADINGSdouble{\HEADINGSdouble904,30062
+\def\HEADINGSsingle{\HEADINGSsingle914,30382
+\def\HEADINGSon{\HEADINGSon922,30603
+\def\HEADINGSafter{\HEADINGSafter924,30637
+\def\HEADINGSdoublex{\HEADINGSdoublex926,30732
+\def\HEADINGSsingleafter{\HEADINGSsingleafter933,30920
+\def\HEADINGSsinglex{\HEADINGSsinglex934,30981
+\def\today{\today943,31256
+\def\thistitle{\thistitle958,31801
+\def\settitle{\settitle959,31826
+\def\settitlezzz #1{\settitlezzz960,31863
+\def\internalBitem{\internalBitem992,32793
+\def\internalBitemx{\internalBitemx993,32843
+\def\internalBxitem "#1"{\internalBxitem995,32888
+\def\internalBxitemx "#1"{\internalBxitemx996,32968
+\def\internalBkitem{\internalBkitem998,33043
+\def\internalBkitemx{\internalBkitemx999,33095
+\def\kitemzzz #1{\kitemzzz1001,33142
+\def\xitemzzz #1{\xitemzzz1004,33244
+\def\itemzzz #1{\itemzzz1007,33347
+\def\item{\item1037,34418
+\def\itemx{\itemx1038,34469
+\def\kitem{\kitem1039,34522
+\def\kitemx{\kitemx1040,34575
+\def\xitem{\xitem1041,34630
+\def\xitemx{\xitemx1042,34683
+\def\description{\description1045,34793
+\def\table{\table1047,34843
+\def\ftable{\ftable1052,34987
+\def\Eftable{\Eftable1056,35133
+\def\vtable{\vtable1059,35202
+\def\Evtable{\Evtable1063,35348
+\def\dontindex #1{\dontindex1066,35417
+\def\fnitemindex #1{\fnitemindex1067,35437
+\def\vritemindex #1{\vritemindex1068,35482
+\def\tablez #1#2#3#4#5#6{\tablez1074,35631
+\def\Edescription{\Edescription1077,35689
+\def\itemfont{\itemfont1082,35890
+\def\Etable{\Etable1090,36116
+\def\itemize{\itemize1103,36440
+\def\itemizezzz #1{\itemizezzz1105,36476
+\def\itemizey #1#2{\itemizey1110,36571
+\def#2{1119,36817
+\def\itemcontents{\itemcontents1120,36858
+\def\bullet{\bullet1123,36906
+\def\minus{\minus1124,36933
+\def\frenchspacing{\frenchspacing1128,37041
+\def\splitoff#1#2\endmark{\splitoff1134,37266
+\def\enumerate{\enumerate1140,37496
+\def\enumeratezzz #1{\enumeratezzz1141,37535
+\def\enumeratey #1 #2\endenumeratey{\enumeratey1142,37588
+ \def\thearg{\thearg1146,37735
+ \ifx\thearg\empty \def\thearg{\thearg1147,37754
+\def\numericenumerate{\numericenumerate1184,39088
+\def\lowercaseenumerate{\lowercaseenumerate1190,39218
+\def\uppercaseenumerate{\uppercaseenumerate1203,39565
+\def\startenumeration#1{\startenumeration1219,40055
+\def\alphaenumerate{\alphaenumerate1227,40237
+\def\capsenumerate{\capsenumerate1228,40272
+\def\Ealphaenumerate{\Ealphaenumerate1229,40306
+\def\Ecapsenumerate{\Ecapsenumerate1230,40340
+\def\itemizeitem{\itemizeitem1234,40420
+\def\newindex #1{\newindex1259,41277
+\def\defindex{\defindex1268,41566
+\def\newcodeindex #1{\newcodeindex1272,41674
+\def\defcodeindex{\defcodeindex1279,41934
+\def\synindex #1 #2 {\synindex1283,42114
+\def\syncodeindex #1 #2 {\syncodeindex1292,42454
+\def\doindex#1{\doindex1309,43133
+\def\singleindexer #1{\singleindexer1310,43192
+\def\docodeindex#1{\docodeindex1313,43304
+\def\singlecodeindexer #1{\singlecodeindexer1314,43371
+\def\indexdummies{\indexdummies1316,43429
+\def\_{\_1317,43449
+\def\w{\w1318,43477
+\def\bf{\bf1319,43504
+\def\rm{\rm1320,43533
+\def\sl{\sl1321,43562
+\def\sf{\sf1322,43591
+\def\tt{\tt1323,43619
+\def\gtr{\gtr1324,43647
+\def\less{\less1325,43677
+\def\hat{\hat1326,43709
+\def\char{\char1327,43739
+\def\TeX{\TeX1328,43771
+\def\dots{\dots1329,43801
+\def\copyright{\copyright1330,43834
+\def\tclose##1{\tclose1331,43877
+\def\code##1{\code1332,43922
+\def\samp##1{\samp1333,43963
+\def\t##1{\t1334,44004
+\def\r##1{\r1335,44039
+\def\i##1{\i1336,44074
+\def\b##1{\b1337,44109
+\def\cite##1{\cite1338,44144
+\def\key##1{\key1339,44185
+\def\file##1{\file1340,44224
+\def\var##1{\var1341,44265
+\def\kbd##1{\kbd1342,44304
+\def\indexdummyfont#1{\indexdummyfont1347,44460
+\def\indexdummytex{\indexdummytex1348,44486
+\def\indexdummydots{\indexdummydots1349,44510
+\def\indexnofonts{\indexnofonts1351,44536
+\let\w=\indexdummyfontdummyfont1352,44556
+\let\t=\indexdummyfontdummyfont1353,44579
+\let\r=\indexdummyfontdummyfont1354,44602
+\let\i=\indexdummyfontdummyfont1355,44625
+\let\b=\indexdummyfontdummyfont1356,44648
+\let\emph=\indexdummyfontdummyfont1357,44671
+\let\strong=\indexdummyfontdummyfont1358,44697
+\let\cite=\indexdummyfont=\indexdummyfont1359,44725
+\let\sc=\indexdummyfontdummyfont1360,44751
+\let\tclose=\indexdummyfontdummyfont1364,44923
+\let\code=\indexdummyfontdummyfont1365,44951
+\let\file=\indexdummyfontdummyfont1366,44977
+\let\samp=\indexdummyfontdummyfont1367,45003
+\let\kbd=\indexdummyfontdummyfont1368,45029
+\let\key=\indexdummyfontdummyfont1369,45054
+\let\var=\indexdummyfontdummyfont1370,45079
+\let\TeX=\indexdummytexdummytex1371,45104
+\let\dots=\indexdummydotsdummydots1372,45128
+\let\indexbackslash=0 %overridden during \printindex.backslash=01382,45380
+\def\doind #1#2{\doind1384,45436
+{\indexdummies % Must do this here, since \bf, etc expand at this stagedummies1386,45479
+\def\rawbackslashxx{\rawbackslashxx1389,45619
+{\indexnofontsnofonts1394,45881
+\def\dosubind #1#2#3{\dosubind1405,46192
+{\indexdummies % Must do this here, since \bf, etc expand at this stagedummies1407,46240
+\def\rawbackslashxx{\rawbackslashxx1410,46344
+{\indexnofontsnofonts1414,46498
+\def\findex {\findex1443,47429
+\def\kindex {\kindex1444,47452
+\def\cindex {\cindex1445,47475
+\def\vindex {\vindex1446,47498
+\def\tindex {\tindex1447,47521
+\def\pindex {\pindex1448,47544
+\def\cindexsub {\cindexsub1450,47568
+\def\printindex{\printindex1462,47895
+\def\doprintindex#1{\doprintindex1464,47936
+ \def\indexbackslash{\indexbackslash1481,48421
+ \indexfonts\rm \tolerance=9500 \advance\baselineskip -1ptfonts\rm1482,48460
+\def\initial #1{\initial1517,49532
+\def\entry #1#2{\entry1523,49739
+ \null\nobreak\indexdotfill % Have leaders before the page number.dotfill1540,50386
+\def\indexdotfill{\indexdotfill1549,50714
+\def\primary #1{\primary1552,50820
+\def\secondary #1#2{\secondary1556,50902
+\noindent\hskip\secondaryindent\hbox{#1}\indexdotfill #2\pardotfill1559,50984
+\newbox\partialpageialpage1566,51157
+\def\begindoublecolumns{\begindoublecolumns1572,51315
+ \output={\global\setbox\partialpage=ialpage=1573,51351
+\def\enddoublecolumns{\enddoublecolumns1577,51539
+\def\doublecolumnout{\doublecolumnout1580,51624
+ \dimen@=\pageheight \advance\dimen@ by-\ht\partialpageialpage1581,51693
+\def\pagesofar{\pagesofar1584,51871
+\def\balancecolumns{\balancecolumns1588,52108
+ \availdimen@=\pageheight \advance\availdimen@ by-\ht\partialpageialpage1594,52279
+ \dimen@=\pageheight \advance\dimen@ by-\ht\partialpageialpage1600,52540
+\newcount \appendixno \appendixno = `\@no1627,53445
+\def\appendixletter{\appendixletter1628,53486
+\def\opencontents{\opencontents1632,53589
+\def\thischapter{\thischapter1637,53770
+\def\seccheck#1{\seccheck1638,53808
+\def\chapternofonts{\chapternofonts1643,53912
+\def\result{\result1646,53987
+\def\equiv{\equiv1647,54022
+\def\expansion{\expansion1648,54055
+\def\print{\print1649,54096
+\def\TeX{\TeX1650,54129
+\def\dots{\dots1651,54158
+\def\copyright{\copyright1652,54189
+\def\tt{\tt1653,54230
+\def\bf{\bf1654,54257
+\def\w{\w1655,54285
+\def\less{\less1656,54310
+\def\gtr{\gtr1657,54341
+\def\hat{\hat1658,54370
+\def\char{\char1659,54399
+\def\tclose##1{\tclose1660,54430
+\def\code##1{\code1661,54474
+\def\samp##1{\samp1662,54514
+\def\r##1{\r1663,54554
+\def\b##1{\b1664,54588
+\def\key##1{\key1665,54622
+\def\file##1{\file1666,54660
+\def\kbd##1{\kbd1667,54700
+\def\i##1{\i1669,54808
+\def\cite##1{\cite1670,54842
+\def\var##1{\var1671,54882
+\def\emph##1{\emph1672,54920
+\def\dfn##1{\dfn1673,54960
+\def\thischaptername{\thischaptername1676,55001
+\outer\def\chapter{\chapter1677,55040
+\def\chapterzzz #1{\chapterzzz1678,55081
+{\chapternofonts%nofonts%1687,55477
+\global\let\section = \numberedsec=1692,55630
+\global\let\subsection = \numberedsubsec=1693,55665
+\global\let\subsubsection = \numberedsubsubsec=1694,55706
+\outer\def\appendix{\appendix1697,55757
+\def\appendixzzz #1{\appendixzzz1698,55800
+\global\advance \appendixno by 1 \message{no1700,55877
+\chapmacro {#1}{Appendix \appendixletter}letter1701,55946
+\xdef\thischapter{Appendix \appendixletter: \noexpand\thischaptername}letter:1704,56039
+{\chapternofonts%nofonts%1705,56111
+ {#1}{Appendix \appendixletter}letter1707,56167
+\appendixnoderef %noderef1710,56267
+\global\let\section = \appendixsec=1711,56286
+\global\let\subsection = \appendixsubsec=1712,56321
+\global\let\subsubsection = \appendixsubsubsec=1713,56362
+\outer\def\top{\top1716,56413
+\outer\def\unnumbered{\unnumbered1717,56453
+\def\unnumberedzzz #1{\unnumberedzzz1718,56500
+{\chapternofonts%nofonts%1722,56663
+\global\let\section = \unnumberedsec=1727,56813
+\global\let\subsection = \unnumberedsubsec=1728,56850
+\global\let\subsubsection = \unnumberedsubsubsec=1729,56893
+\outer\def\numberedsec{\numberedsec1732,56946
+\def\seczzz #1{\seczzz1733,56987
+{\chapternofonts%nofonts%1736,57143
+\outer\def\appendixsection{\appendixsection1745,57329
+\outer\def\appendixsec{\appendixsec1746,57386
+\def\appendixsectionzzz #1{\appendixsectionzzz1747,57439
+\gdef\thissection{#1}\secheading {#1}{\appendixletter}letter1749,57551
+{\chapternofonts%nofonts%1750,57619
+{#1}{\appendixletter}letter1752,57675
+\appendixnoderef %noderef1755,57775
+\outer\def\unnumberedsec{\unnumberedsec1759,57815
+\def\unnumberedseczzz #1{\unnumberedseczzz1760,57868
+{\chapternofonts%nofonts%1762,57963
+\outer\def\numberedsubsec{\numberedsubsec1770,58131
+\def\numberedsubseczzz #1{\numberedsubseczzz1771,58186
+{\chapternofonts%nofonts%1774,58365
+\outer\def\appendixsubsec{\appendixsubsec1783,58569
+\def\appendixsubseczzz #1{\appendixsubseczzz1784,58624
+\subsecheading {#1}{\appendixletter}letter1786,58746
+{\chapternofonts%nofonts%1787,58811
+{#1}{\appendixletter}letter1789,58870
+\appendixnoderef %noderef1792,58985
+\outer\def\unnumberedsubsec{\unnumberedsubsec1796,59025
+\def\unnumberedsubseczzz #1{\unnumberedsubseczzz1797,59084
+{\chapternofonts%nofonts%1799,59185
+\outer\def\numberedsubsubsec{\numberedsubsubsec1807,59356
+\def\numberedsubsubseczzz #1{\numberedsubsubseczzz1808,59417
+{\chapternofonts%nofonts%1812,59614
+\outer\def\appendixsubsubsec{\appendixsubsubsec1823,59847
+\def\appendixsubsubseczzz #1{\appendixsubsubseczzz1824,59908
+ {\appendixletter}letter1827,60047
+{\chapternofonts%nofonts%1828,60113
+ {\appendixletter}letter1830,60178
+\appendixnoderef %noderef1834,60312
+\outer\def\unnumberedsubsubsec{\unnumberedsubsubsec1838,60352
+\def\unnumberedsubsubseczzz #1{\unnumberedsubsubseczzz1839,60417
+{\chapternofonts%nofonts%1841,60524
+\def\infotop{\infotop1851,60853
+\def\infounnumbered{\infounnumbered1852,60891
+\def\infounnumberedsec{\infounnumberedsec1853,60936
+\def\infounnumberedsubsec{\infounnumberedsubsec1854,60987
+\def\infounnumberedsubsubsec{\infounnumberedsubsubsec1855,61044
+\def\infoappendix{\infoappendix1857,61108
+\def\infoappendixsec{\infoappendixsec1858,61149
+\def\infoappendixsubsec{\infoappendixsubsec1859,61196
+\def\infoappendixsubsubsec{\infoappendixsubsubsec1860,61249
+\def\infochapter{\infochapter1862,61309
+\def\infosection{\infosection1863,61348
+\def\infosubsection{\infosubsection1864,61387
+\def\infosubsubsection{\infosubsubsection1865,61432
+\global\let\section = \numberedsec=1870,61669
+\global\let\subsection = \numberedsubsec=1871,61704
+\global\let\subsubsection = \numberedsubsubsec=1872,61745
+\def\majorheading{\majorheading1886,62252
+\def\majorheadingzzz #1{\majorheadingzzz1887,62297
+\def\chapheading{\chapheading1893,62530
+\def\chapheadingzzz #1{\chapheadingzzz1894,62573
+\def\heading{\heading1899,62768
+\def\subheading{\subheading1901,62805
+\def\subsubheading{\subsubheading1903,62848
+\def\dobreak#1#2{\dobreak1910,63125
+\def\setchapterstyle #1 {\setchapterstyle1912,63203
+\def\chapbreak{\chapbreak1919,63458
+\def\chappager{\chappager1920,63508
+\def\chapoddpage{\chapoddpage1921,63546
+\def\setchapternewpage #1 {\setchapternewpage1923,63625
+\def\CHAPPAGoff{\CHAPPAGoff1925,63682
+\def\CHAPPAGon{\CHAPPAGon1929,63776
+\global\def\HEADINGSon{\HEADINGSon1932,63867
+\def\CHAPPAGodd{\CHAPPAGodd1934,63909
+\global\def\HEADINGSon{\HEADINGSon1937,64005
+\def\CHAPFplain{\CHAPFplain1941,64059
+\def\chfplain #1#2{\chfplain1945,64151
+\def\unnchfplain #1{\unnchfplain1956,64374
+\def\unnchfopen #1{\unnchfopen1964,64603
+\def\chfopen #1#2{\chfopen1970,64811
+\def\CHAPFopen{\CHAPFopen1975,64955
+\def\subsecheadingbreak{\subsecheadingbreak1982,65173
+\def\secheadingbreak{\secheadingbreak1985,65302
+\def\secheading #1#2#3{\secheading1993,65584
+\def\plainsecheading #1{\plainsecheading1994,65640
+\def\secheadingi #1{\secheadingi1995,65683
+\def\subsecheading #1#2#3#4{\subsecheading2006,66051
+\def\subsecheadingi #1{\subsecheadingi2007,66118
+\def\subsubsecfonts{\subsubsecfonts2014,66415
+\def\subsubsecheading #1#2#3#4#5{\subsubsecheading2017,66538
+\def\subsubsecheadingi #1{\subsubsecheadingi2018,66616
+\def\startcontents#1{\startcontents2032,67088
+ \unnumbchapmacro{#1}\def\thischapter{\thischapter2040,67361
+\outer\def\contents{\contents2049,67720
+\outer\def\summarycontents{\summarycontents2057,67864
+ \def\secentry ##1##2##3##4{\secentry2067,68235
+ \def\unnumbsecentry ##1##2{\unnumbsecentry2068,68270
+ \def\subsecentry ##1##2##3##4##5{\subsecentry2069,68305
+ \def\unnumbsubsecentry ##1##2{\unnumbsubsecentry2070,68346
+ \def\subsubsecentry ##1##2##3##4##5##6{\subsubsecentry2071,68384
+ \def\unnumbsubsubsecentry ##1##2{\unnumbsubsubsecentry2072,68431
+\def\chapentry#1#2#3{\chapentry2085,68865
+\def\shortchapentry#1#2#3{\shortchapentry2088,68982
+ {#2\labelspace #1}space2091,69092
+\def\unnumbchapentry#1#2{\unnumbchapentry2094,69146
+\def\shortunnumberedentry#1#2{\shortunnumberedentry2095,69193
+\def\secentry#1#2#3#4{\secentry2102,69357
+\def\unnumbsecentry#1#2{\unnumbsecentry2103,69416
+\def\subsecentry#1#2#3#4#5{\subsecentry2106,69477
+\def\unnumbsubsecentry#1#2{\unnumbsubsecentry2107,69547
+\def\subsubsecentry#1#2#3#4#5#6{\subsubsecentry2110,69621
+ \dosubsubsecentry{#2.#3.#4.#5\labelspace#1}space2111,69655
+\def\unnumbsubsubsecentry#1#2{\unnumbsubsubsecentry2112,69706
+\def\dochapentry#1#2{\dochapentry2123,70080
+\def\dosecentry#1#2{\dosecentry2138,70685
+\def\dosubsecentry#1#2{\dosubsecentry2145,70863
+\def\dosubsubsecentry#1#2{\dosubsubsecentry2152,71048
+\def\labelspace{\labelspace2160,71299
+\def\dopageno#1{\dopageno2162,71334
+\def\doshortpageno#1{\doshortpageno2163,71360
+\def\chapentryfonts{\chapentryfonts2165,71392
+\def\secentryfonts{\secentryfonts2166,71427
+\def\point{\point2192,72386
+\def\result{\result2194,72407
+\def\expansion{\expansion2195,72480
+\def\print{\print2196,72551
+\def\equiv{\equiv2198,72618
+\def\error{\error2218,73391
+\def\tex{\tex2224,73620
+\def\@{\@2242,74003
+\gdef\sepspaces{\def {\ }}}\2265,74735
+\def\aboveenvbreak{\aboveenvbreak2268,74817
+\def\afterenvbreak{\afterenvbreak2272,74983
+\def\ctl{\ctl2286,75494
+\def\ctr{\ctr2287,75566
+\def\cbl{\cbl2288,75605
+\def\cbr{\cbr2289,75645
+\def\carttop{\carttop2290,75684
+\def\cartbot{\cartbot2293,75792
+\long\def\cartouche{\cartouche2299,75932
+\def\Ecartouche{\Ecartouche2326,76720
+\def\lisp{\lisp2338,76855
+\def\Elisp{\Elisp2348,77202
+\def\next##1{\next2360,77528
+\def\Eexample{\Eexample2364,77570
+\def\Esmallexample{\Esmallexample2367,77617
+\def\smalllispx{\smalllispx2373,77795
+\def\Esmalllisp{\Esmalllisp2383,78149
+\obeyspaces \obeylines \ninett \indexfonts \rawbackslashfonts2396,78505
+\def\next##1{\next2397,78562
+\def\display{\display2401,78642
+\def\Edisplay{\Edisplay2410,78961
+\def\next##1{\next2422,79272
+\def\format{\format2426,79375
+\def\Eformat{\Eformat2434,79671
+\def\next##1{\next2437,79760
+\def\flushleft{\flushleft2441,79812
+\def\Eflushleft{\Eflushleft2451,80183
+\def\next##1{\next2454,80276
+\def\flushright{\flushright2456,80298
+\def\Eflushright{\Eflushright2466,80670
+\def\next##1{\next2470,80801
+\def\quotation{\quotation2474,80859
+\def\Equotation{\Equotation2480,81051
+\def\setdeffont #1 {\setdeffont2493,81449
+\newskip\defbodyindent \defbodyindent=.4inbodyindent2495,81495
+\newskip\defargsindent \defargsindent=50ptargsindent2496,81538
+\newskip\deftypemargin \deftypemargin=12pttypemargin2497,81581
+\newskip\deflastargmargin \deflastargmargin=18ptlastargmargin2498,81624
+\def\activeparens{\activeparens2503,81822
+\def\opnr{\opnr2529,83034
+\def\lbrb{\lbrb2530,83099
+\def\defname #1#2{\defname2536,83300
+\advance\dimen2 by -\defbodyindentbodyindent2540,83418
+\advance\dimen3 by -\defbodyindentbodyindent2542,83472
+\setbox0=\hbox{\hskip \deflastargmargin{lastargmargin2544,83526
+\dimen1=\hsize \advance \dimen1 by -\defargsindent %size for continuationsargsindent2546,83668
+\parshape 2 0in \dimen0 \defargsindent \dimen1 %argsindent2547,83743
+\rlap{\rightline{{\rm #2}\hskip \deftypemargin}typemargin2554,84112
+\advance\leftskip by -\defbodyindentbodyindent2557,84246
+\exdentamount=\defbodyindentbodyindent2558,84283
+\def\defparsebody #1#2#3{\defparsebody2568,84642
+\def#1{2572,84826
+\def#2{2573,84862
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2575,84934
+\exdentamount=\defbodyindentbodyindent2576,85008
+\def\defmethparsebody #1#2#3#4 {\defmethparsebody2581,85112
+\def#1{2585,85273
+\def#2##1 {2586,85309
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2588,85392
+\exdentamount=\defbodyindentbodyindent2589,85466
+\def\defopparsebody #1#2#3#4#5 {\defopparsebody2592,85551
+\def#1{2596,85712
+\def#2##1 ##2 {2597,85748
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2600,85848
+\exdentamount=\defbodyindentbodyindent2601,85922
+\def\defvarparsebody #1#2#3{\defvarparsebody2608,86193
+\def#1{2612,86380
+\def#2{2613,86416
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2615,86475
+\exdentamount=\defbodyindentbodyindent2616,86549
+\def\defvrparsebody #1#2#3#4 {\defvrparsebody2621,86640
+\def#1{2625,86799
+\def#2##1 {2626,86835
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2628,86905
+\exdentamount=\defbodyindentbodyindent2629,86979
+\def\defopvarparsebody #1#2#3#4#5 {\defopvarparsebody2632,87051
+\def#1{2636,87215
+\def#2##1 ##2 {2637,87251
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2640,87338
+\exdentamount=\defbodyindentbodyindent2641,87412
+\def\defunargs #1{\defunargs2664,88172
+\def\deftypefunargs #1{\deftypefunargs2676,88554
+\def\deffn{\deffn2690,88936
+\def\deffnheader #1#2#3{\deffnheader2692,88993
+\begingroup\defname {name2693,89041
+\def\defun{\defun2699,89186
+\def\defunheader #1#2{\defunheader2701,89239
+\begingroup\defname {name2702,89314
+\defunargs {unargs2703,89350
+\def\deftypefun{\deftypefun2709,89498
+\def\deftypefunheader #1#2{\deftypefunheader2712,89620
+\def\deftypefunheaderx #1#2 #3\relax{\deftypefunheaderx2714,89729
+\begingroup\defname {name2716,89821
+\deftypefunargs {typefunargs2717,89867
+\def\deftypefn{\deftypefn2723,90038
+\def\deftypefnheader #1#2#3{\deftypefnheader2726,90187
+\def\deftypefnheaderx #1#2#3 #4\relax{\deftypefnheaderx2728,90323
+\begingroup\defname {name2730,90416
+\deftypefunargs {typefunargs2731,90456
+\def\defmac{\defmac2737,90577
+\def\defmacheader #1#2{\defmacheader2739,90634
+\begingroup\defname {name2740,90710
+\defunargs {unargs2741,90743
+\def\defspec{\defspec2747,90867
+\def\defspecheader #1#2{\defspecheader2749,90928
+\begingroup\defname {name2750,91005
+\defunargs {unargs2751,91045
+\def\deffnx #1 {\deffnx2758,91240
+\def\defunx #1 {\defunx2759,91297
+\def\defmacx #1 {\defmacx2760,91354
+\def\defspecx #1 {\defspecx2761,91413
+\def\deftypefnx #1 {\deftypefnx2762,91474
+\def\deftypeunx #1 {\deftypeunx2763,91539
+\def\defop #1 {\defop2769,91685
+\defopparsebody\Edefop\defopx\defopheader\defoptype}opparsebody\Edefop\defopx\defopheader\defoptype2770,91720
+\def\defopheader #1#2#3{\defopheader2772,91774
+\begingroup\defname {name2774,91863
+\defunargs {unargs2775,91909
+\def\defmethod{\defmethod2780,91970
+\def\defmethodheader #1#2#3{\defmethodheader2782,92043
+\begingroup\defname {name2784,92131
+\defunargs {unargs2785,92171
+\def\defcv #1 {\defcv2790,92245
+\defopvarparsebody\Edefcv\defcvx\defcvarheader\defcvtype}opvarparsebody\Edefcv\defcvx\defcvarheader\defcvtype2791,92280
+\def\defcvarheader #1#2#3{\defcvarheader2793,92339
+\begingroup\defname {name2795,92425
+\defvarargs {varargs2796,92471
+\def\defivar{\defivar2801,92544
+\def\defivarheader #1#2#3{\defivarheader2803,92607
+\begingroup\defname {name2805,92693
+\defvarargs {varargs2806,92744
+\def\defopx #1 {\defopx2812,92893
+\def\defmethodx #1 {\defmethodx2813,92950
+\def\defcvx #1 {\defcvx2814,93015
+\def\defivarx #1 {\defivarx2815,93072
+\def\defvarargs #1{\defvarargs2822,93343
+\def\defvr{\defvr2828,93487
+\def\defvrheader #1#2#3{\defvrheader2830,93542
+\begingroup\defname {name2831,93590
+\def\defvar{\defvar2835,93675
+\def\defvarheader #1#2{\defvarheader2837,93735
+\begingroup\defname {name2838,93806
+\defvarargs {varargs2839,93842
+\def\defopt{\defopt2844,93908
+\def\defoptheader #1#2{\defoptheader2846,93968
+\begingroup\defname {name2847,94039
+\defvarargs {varargs2848,94078
+\def\deftypevar{\deftypevar2853,94135
+\def\deftypevarheader #1#2{\deftypevarheader2856,94251
+\begingroup\defname {name2858,94334
+\def\deftypevr{\deftypevr2865,94508
+\def\deftypevrheader #1#2#3{\deftypevrheader2867,94579
+\begingroup\defname {name2868,94631
+\def\defvrx #1 {\defvrx2876,94868
+\def\defvarx #1 {\defvarx2877,94925
+\def\defoptx #1 {\defoptx2878,94984
+\def\deftypevarx #1 {\deftypevarx2879,95043
+\def\deftypevrx #1 {\deftypevrx2880,95110
+\def\deftpargs #1{\deftpargs2885,95259
+\def\deftp{\deftp2889,95339
+\def\deftpheader #1#2#3{\deftpheader2891,95394
+\begingroup\defname {name2892,95442
+\def\deftpx #1 {\deftpx2897,95601
+\def\setref#1{\setref2908,95922
+\def\unnumbsetref#1{\unnumbsetref2913,96036
+\def\appendixsetref#1{\appendixsetref2918,96143
+\def\pxref#1{\pxref2929,96554
+\def\xref#1{\xref2930,96590
+\def\ref#1{\ref2931,96625
+\def\xrefX[#1,#2,#3,#4,#5,#6]{\xrefX[2932,96655
+\def\printedmanual{\printedmanual2933,96698
+\def\printednodename{\printednodename2934,96736
+\def\printednodename{\printednodename2939,96861
+section ``\printednodename'' in \cite{\printedmanual}\printedmanual2954,97493
+\refx{x2957,97571
+\def\dosetq #1#2{\dosetq2965,97791
+\def\internalsetq #1#2{\internalsetq2973,98049
+\def\Ypagenumber{\Ypagenumber2977,98150
+\def\Ytitle{\Ytitle2979,98176
+\def\Ynothing{\Ynothing2981,98203
+\def\Ysectionnumberandtype{\Ysectionnumberandtype2983,98220
+\def\Yappendixletterandtype{\Yappendixletterandtype2992,98536
+\ifnum\secno=0 Appendix\xreftie'char\the\appendixno{no2993,98566
+\else \ifnum \subsecno=0 Section\xreftie'char\the\appendixno.\the\secno %no.\the\secno2994,98621
+Section\xreftie'char\the\appendixno.\the\secno.\the\subsecno %no.\the\secno.\the\subsecno2996,98725
+Section\xreftie'char\the\appendixno.\the\secno.\the\subsecno.\the\subsubsecno %no.\the\secno.\the\subsecno.\the\subsubsecno2998,98796
+ \def\linenumber{\linenumber3009,99135
+\def\refx#1#2{\refx3015,99319
+\def\xrdef #1#2{\xrdef3037,99945
+\def\readauxfile{\readauxfile3040,100030
+\def\supereject{\supereject3110,101811
+\footstrut\parindent=\defaultparindent\hang\textindent{aultparindent\hang\textindent3131,102496
+\def\openindices{\openindices3139,102682
+\newdimen\defaultparindent \defaultparindent = 15ptaultparindent3151,102907
+\parindent = \defaultparindentaultparindent3152,102959
+\def\smallbook{\smallbook3175,103683
+\global\def\Esmallexample{\Esmallexample3192,104110
+\def\afourpaper{\afourpaper3196,104201
+\def\finalout{\finalout3224,105009
+\def\normaldoublequote{\normaldoublequote3235,105270
+\def\normaltilde{\normaltilde3236,105296
+\def\normalcaret{\normalcaret3237,105316
+\def\normalunderscore{\normalunderscore3238,105336
+\def\normalverticalbar{\normalverticalbar3239,105361
+\def\normalless{\normalless3240,105387
+\def\normalgreater{\normalgreater3241,105406
+\def\normalplus{\normalplus3242,105428
+\def\ifusingtt#1#2{\ifusingtt3253,105920
+\def\activedoublequote{\activedoublequote3261,106248
+\def~{~3264,106334
+\def^{^3267,106395
+\def_{_3270,106434
+\def\_{\_3272,106508
+\def\lvvmode{\lvvmode3279,106845
+\def|{|3282,106895
+\def<{<3285,106958
+\def>{>3288,107015
+\def+{+3290,107053
+\def\turnoffactive{\turnoffactive3296,107214
+\global\def={=3307,107500
+\def\normalbackslash{\normalbackslash3321,107882
+
+merc-src/accumulator.m,4915
+:- interface146,5371
+:- import_module hlds148,5386
+:- import_module univ152,5478
+:- pred accu_transform_proc159,5793
+:- implementation166,6115
+:- import_module libs180,6552
+:- import_module mdbcomp184,6681
+:- import_module parse_tree186,6742
+:- import_module assoc_list194,7013
+:- import_module bool195,7042
+:- import_module int196,7065
+:- import_module io197,7087
+:- import_module list198,7108
+:- import_module map199,7131
+:- import_module maybe200,7153
+:- import_module pair201,7177
+:- import_module require202,7200
+:- import_module set203,7226
+:- import_module solutions204,7248
+:- import_module string205,7276
+:- import_module term206,7301
+:- import_module varset207,7324
+:- type top_level213,7499
+:- type accu_goal_id225,7900
+:- type accu_case228,7964
+:- type accu_goal_store234,8091
+:- type accu_subst238,8216
+:- type accu_warning240,8264
+accu_transform_proc247,8578
+:- pred generate_warnings334,12550
+generate_warnings337,12669
+:- pred generate_warning342,12895
+generate_warning345,13001
+:- pred should_attempt_accu_transform365,13886
+should_attempt_accu_transform370,14123
+:- pred should_attempt_accu_transform_2398,15406
+should_attempt_accu_transform_2405,15763
+:- pred accu_standardize440,17390
+accu_standardize442,17455
+:- pred identify_goal_type465,18169
+identify_goal_type469,18359
+:- pred is_recursive_case549,21175
+is_recursive_case551,21253
+:- type store_info560,21713
+:- func initialize_goal_store570,22060
+initialize_goal_store573,22166
+:- pred accu_store580,22421
+accu_store584,22576
+:- pred identify_recursive_calls601,23288
+identify_recursive_calls604,23406
+:- pred identify_out_and_out_prime626,24397
+identify_out_and_out_prime631,24632
+:- type accu_sets676,26426
+:- pred accu_stage1689,26978
+accu_stage1693,27156
+:- pred accu_stage1_2727,28348
+accu_stage1_2731,28516
+:- pred accu_sets_init781,30558
+accu_sets_init783,30606
+:- func set_upto796,30985
+set_upto798,31040
+:- pred accu_before812,31499
+accu_before815,31640
+:- pred accu_assoc835,32478
+accu_assoc838,32618
+:- pred accu_construct862,33713
+accu_construct865,33857
+:- pred accu_construct_assoc896,35308
+accu_construct_assoc899,35458
+:- pred accu_update938,37070
+accu_update941,37211
+:- pred member_lessthan_goalid964,38220
+member_lessthan_goalid967,38343
+:- type accu_assoc975,38653
+:- pred accu_is_associative986,39139
+accu_is_associative989,39251
+:- pred associativity_assertion1014,40264
+associativity_assertion1017,40405
+:- pred commutativity_assertion1037,41243
+commutativity_assertion1040,41370
+:- pred accu_is_update1057,41953
+accu_is_update1060,42067
+:- pred is_associative_construction1078,42803
+is_associative_construction1081,42899
+:- type accu_substs1095,43481
+:- type accu_base1103,43745
+:- pred accu_stage21124,44606
+accu_stage21131,44947
+:- pred accu_substs_init1179,46958
+accu_substs_init1182,47098
+:- pred acc_var_subst_init1194,47574
+acc_var_subst_init1198,47719
+:- pred create_new_var1207,48148
+create_new_var1210,48289
+:- pred accu_process_assoc_set1223,48863
+accu_process_assoc_set1229,49151
+:- pred accu_has_heuristic1297,52082
+accu_has_heuristic1299,52162
+:- pred accu_heuristic1304,52337
+accu_heuristic1307,52458
+:- pred accu_process_update_set1318,52907
+accu_process_update_set1325,53222
+:- pred accu_divide_base_case1380,55845
+accu_divide_base_case1385,56060
+:- pred accu_related1412,57147
+accu_related1415,57271
+:- inst stored_goal_plain_call1444,58416
+:- pred lookup_call1449,58602
+lookup_call1452,58716
+:- pred accu_stage31470,59433
+accu_stage31477,59827
+:- pred acc_proc_info1508,61327
+acc_proc_info1512,61486
+:- pred acc_pred_info1556,63450
+acc_pred_info1559,63598
+:- pred accu_create_goal1600,65286
+accu_create_goal1607,65629
+:- func create_acc_call1621,66401
+create_acc_call1625,66570
+:- pred create_orig_goal1634,66988
+create_orig_goal1638,67177
+:- pred create_acc_goal1662,68158
+create_acc_goal1667,68381
+:- func create_new_orig_recursive_goals1709,70226
+create_new_orig_recursive_goals1712,70369
+:- func create_new_recursive_goals1723,70919
+create_new_recursive_goals1727,71109
+:- func create_new_base_goals1738,71718
+create_new_base_goals1741,71832
+:- pred acc_unification1749,72157
+acc_unification1751,72226
+:- pred accu_top_level1766,72897
+accu_top_level1770,73059
+:- pred update_accumulator_pred1856,76291
+update_accumulator_pred1859,76412
+:- func accu_rename1876,77254
+accu_rename1879,77364
+:- func base_case_ids1889,77785
+base_case_ids1891,77847
+:- func base_case_ids_set1898,78049
+base_case_ids_set1900,78114
+:- func accu_goal_list1905,78270
+accu_goal_list1907,78350
+:- pred calculate_goal_info1916,78681
+calculate_goal_info1918,78754
+:- func chain_subst1932,79320
+chain_subst1934,79379
+:- pred chain_subst_21938,79483
+chain_subst_21941,79577
+:- some [T] pred unravel_univ1956,80061
+:- pragma foreign_export1957,80117
+unravel_univ1961,80341
c-src/c.c,76
T f(1,0
@@ -4574,13 +4731,13 @@ extern struct node *yylval;yylval306,6246
unsigned char parse_cell_or_range 309,6291
unsigned char parse_cell_or_range 311,6355
yylex FUN0(315,6405
-parse_cell_or_range FUN2(587,11771
-#define CK_ABS_R(671,13213
-#define CK_REL_R(675,13292
-#define CK_ABS_C(680,13421
-#define CK_REL_C(684,13500
-#define MAYBEREL(689,13629
-str_to_col FUN1(847,16830
+parse_cell_or_range FUN2(587,11772
+#define CK_ABS_R(671,13214
+#define CK_REL_R(675,13293
+#define CK_ABS_C(680,13422
+#define CK_REL_C(684,13501
+#define MAYBEREL(689,13630
+str_to_col FUN1(847,16831
y-src/parse.c,520
#define YYBISON 4,64
diff --git a/test/manual/etags/ETAGS.good_3 b/test/manual/etags/ETAGS.good_3
index 508427c501c..15ed7855b30 100644
--- a/test/manual/etags/ETAGS.good_3
+++ b/test/manual/etags/ETAGS.good_3
@@ -175,7 +175,7 @@ package body Truc.Bidule Truc.Bidule/b138,2153
protected body Bidule Bidule/b139,2181
protected body Machin_T Machin_T/b146,2281
-c-src/abbrev.c,2072
+c-src/abbrev.c,1957
Lisp_Object Vabbrev_table_name_list;43,1429
Lisp_Object Vglobal_abbrev_table;48,1574
Lisp_Object Vfundamental_mode_abbrev_table;52,1685
@@ -186,33 +186,31 @@ Lisp_Object Vabbrev_start_location_buffer;66,2046
Lisp_Object Vlast_abbrev;70,2155
Lisp_Object Vlast_abbrev_text;75,2324
int last_abbrev_point;79,2414
-Lisp_Object Vpre_abbrev_expand_hook,83,2487
-Lisp_Object Vpre_abbrev_expand_hook, Qpre_abbrev_expand_hook;83,2487
-DEFUN ("make-abbrev-table", Fmake_abbrev_table,85,2551
-DEFUN ("make-abbrev-table", Fmake_abbrev_table,make-abbrev-table85,2551
-DEFUN ("clear-abbrev-table", Fclear_abbrev_table,92,2743
-DEFUN ("clear-abbrev-table", Fclear_abbrev_table,clear-abbrev-table92,2743
-DEFUN ("define-abbrev", Fdefine_abbrev,107,3124
-DEFUN ("define-abbrev", Fdefine_abbrev,define-abbrev107,3124
-DEFUN ("define-global-abbrev", Fdefine_global_abbrev,149,4443
-DEFUN ("define-global-abbrev", Fdefine_global_abbrev,define-global-abbrev149,4443
-DEFUN ("define-mode-abbrev", Fdefine_mode_abbrev,160,4814
-DEFUN ("define-mode-abbrev", Fdefine_mode_abbrev,define-mode-abbrev160,4814
-DEFUN ("abbrev-symbol", Fabbrev_symbol,174,5282
-DEFUN ("abbrev-symbol", Fabbrev_symbol,abbrev-symbol174,5282
-DEFUN ("abbrev-expansion", Fabbrev_expansion,202,6246
-DEFUN ("abbrev-expansion", Fabbrev_expansion,abbrev-expansion202,6246
-DEFUN ("expand-abbrev", Fexpand_abbrev,218,6761
-DEFUN ("expand-abbrev", Fexpand_abbrev,expand-abbrev218,6761
-DEFUN ("unexpand-abbrev", Funexpand_abbrev,389,11682
-DEFUN ("unexpand-abbrev", Funexpand_abbrev,unexpand-abbrev389,11682
-write_abbrev 426,12889
-describe_abbrev 445,13324
-DEFUN ("insert-abbrev-table-description", Finsert_abbrev_table_description,466,13839
-DEFUN ("insert-abbrev-table-description", Finsert_abbrev_table_description,insert-abbrev-table-description466,13839
-DEFUN ("define-abbrev-table", Fdefine_abbrev_table,506,14995
-DEFUN ("define-abbrev-table", Fdefine_abbrev_table,define-abbrev-table506,14995
-syms_of_abbrev 540,16072
+DEFUN ("make-abbrev-table", Fmake_abbrev_table,82,2440
+DEFUN ("make-abbrev-table", Fmake_abbrev_table,make-abbrev-table82,2440
+DEFUN ("clear-abbrev-table", Fclear_abbrev_table,89,2632
+DEFUN ("clear-abbrev-table", Fclear_abbrev_table,clear-abbrev-table89,2632
+DEFUN ("define-abbrev", Fdefine_abbrev,104,3013
+DEFUN ("define-abbrev", Fdefine_abbrev,define-abbrev104,3013
+DEFUN ("define-global-abbrev", Fdefine_global_abbrev,146,4332
+DEFUN ("define-global-abbrev", Fdefine_global_abbrev,define-global-abbrev146,4332
+DEFUN ("define-mode-abbrev", Fdefine_mode_abbrev,157,4703
+DEFUN ("define-mode-abbrev", Fdefine_mode_abbrev,define-mode-abbrev157,4703
+DEFUN ("abbrev-symbol", Fabbrev_symbol,171,5171
+DEFUN ("abbrev-symbol", Fabbrev_symbol,abbrev-symbol171,5171
+DEFUN ("abbrev-expansion", Fabbrev_expansion,199,6135
+DEFUN ("abbrev-expansion", Fabbrev_expansion,abbrev-expansion199,6135
+DEFUN ("expand-abbrev", Fexpand_abbrev,215,6650
+DEFUN ("expand-abbrev", Fexpand_abbrev,expand-abbrev215,6650
+DEFUN ("unexpand-abbrev", Funexpand_abbrev,383,11495
+DEFUN ("unexpand-abbrev", Funexpand_abbrev,unexpand-abbrev383,11495
+write_abbrev 420,12702
+describe_abbrev 439,13137
+DEFUN ("insert-abbrev-table-description", Finsert_abbrev_table_description,460,13652
+DEFUN ("insert-abbrev-table-description", Finsert_abbrev_table_description,insert-abbrev-table-description460,13652
+DEFUN ("define-abbrev-table", Fdefine_abbrev_table,500,14808
+DEFUN ("define-abbrev-table", Fdefine_abbrev_table,define-abbrev-table500,14808
+syms_of_abbrev 534,15885
c-src/torture.c,197
(*tag1 tag118,452
@@ -240,384 +238,384 @@ struct option73,2795
#define optional_argument 91,3173
c-src/etags.c,12045
-char pot_etags_version[pot_etags_version81,3470
-# undef DEBUG84,3552
-# define DEBUG 85,3567
-# define DEBUG 87,3594
-# define NDEBUG 88,3617
-# define _GNU_SOURCE 94,3705
-# undef MSDOS100,3876
-# undef WINDOWSNT101,3890
-# define WINDOWSNT102,3909
-# undef MSDOS106,3968
-# define MSDOS 107,3982
-# define MSDOS 110,4032
-# define MAXPATHLEN 115,4111
-# undef HAVE_NTGUI116,4141
-# undef DOS_NT117,4160
-# define DOS_NT118,4176
-# undef assert 135,4482
-# define assert(136,4541
-# undef CTAGS146,4857
-# define CTAGS 147,4872
-# define CTAGS 149,4898
-#define streq(152,4927
-#define strcaseeq(153,4996
-#define strneq(154,5075
-#define strncaseeq(155,5151
-#define CHARS 157,5238
-#define CHAR(158,5278
-#define iswhite(159,5329
-#define notinname(160,5394
-#define begtoken(161,5469
-#define intoken(162,5542
-#define endtoken(163,5614
-#define ISALNUM(165,5684
-#define ISALPHA(166,5722
-#define ISDIGIT(167,5760
-#define ISLOWER(168,5798
-#define lowcase(170,5837
-#define xnew(179,6015
-#define xrnew(180,6083
-typedef void Lang_function 182,6164
- const char *suffix;suffix186,6219
- const char *command;command187,6294
-} compressor;188,6365
- const char *name;name192,6397
- const char *help;help193,6449
- Lang_function *function;function194,6508
- const char **suffixes;suffixes195,6556
- const char **filenames;filenames196,6633
- const char **interpreters;interpreters197,6702
- bool metasource;198,6771
-} language;199,6835
-typedef struct fdesc201,6848
- struct fdesc *next;next203,6871
- char *infname;infname204,6920
- char *infabsname;infabsname205,6973
- char *infabsdir;infabsdir206,7038
- char *taggedfname;taggedfname207,7091
- language *lang;lang208,7149
- char *prop;prop209,7191
- bool usecharno;210,7249
- bool written;211,7311
-} fdesc;212,7366
-typedef struct node_st214,7376
- struct node_st *left,left216,7428
- struct node_st *left, *right;right216,7428
- fdesc *fdp;fdp217,7486
- char *name;name218,7548
- char *regex;regex219,7580
- bool valid;220,7617
- bool is_func;221,7670
- bool been_warned;222,7733
- int lno;223,7801
- long cno;224,7842
-} node;225,7894
- long size;236,8208
- int len;237,8221
- char *buffer;buffer238,8232
-} linebuffer;239,8248
- at_language,245,8344
- at_regexp,246,8393
- at_filename,247,8437
- at_stdin,248,8473
- at_end 249,8516
- } arg_type;250,8557
- language *lang;lang251,8593
- char *what;what252,8656
-} argument;253,8698
-typedef struct regexp256,8758
- struct regexp *p_next;p_next258,8782
- language *lang;lang259,8837
- char *pattern;pattern260,8897
- char *name;name261,8940
- struct re_pattern_buffer *pat;pat262,8971
- struct re_registers regs;263,9031
- bool error_signaled;264,9078
- bool force_explicit_name;265,9141
- bool ignore_case;266,9206
- bool multi_line;267,9259
-} regexp;268,9325
-static void error 311,10780
-# undef STDIN408,15073
-#define STDIN 411,15095
-static compressor compressors[compressors457,17664
-static const char *Ada_suffixes Ada_suffixes473,17907
-static const char Ada_help 475,17977
-static const char *Asm_suffixes Asm_suffixes493,18580
-static const char Asm_help 504,18976
-static const char *default_C_suffixes default_C_suffixes512,19312
-static const char default_C_help 515,19413
-static const char default_C_help 523,19850
-static const char *Cplusplus_suffixes Cplusplus_suffixes535,20460
-static const char Cplusplus_help 540,20658
-static const char *Cjava_suffixes Cjava_suffixes549,21113
-static char Cjava_help 551,21172
-static const char *Cobol_suffixes Cobol_suffixes556,21337
-static char Cobol_help 558,21402
-static const char *Cstar_suffixes Cstar_suffixes562,21543
-static const char *Erlang_suffixes Erlang_suffixes565,21607
-static const char Erlang_help 567,21673
-const char *Forth_suffixes Forth_suffixes571,21799
-static const char Forth_help 573,21857
-static const char *Fortran_suffixes Fortran_suffixes577,22008
-static const char Fortran_help 579,22085
-static const char *HTML_suffixes HTML_suffixes582,22190
-static const char HTML_help 584,22264
-static const char *Lisp_suffixes Lisp_suffixes589,22452
-static const char Lisp_help 591,22556
-static const char *Lua_suffixes Lua_suffixes598,22871
-static const char Lua_help 600,22934
-static const char *Makefile_filenames Makefile_filenames603,23010
-static const char Makefile_help 605,23133
-static const char *Objc_suffixes Objc_suffixes609,23277
-static const char Objc_help 613,23399
-static const char *Pascal_suffixes Pascal_suffixes619,23714
-static const char Pascal_help 621,23778
-static const char *Perl_suffixes Perl_suffixes626,23966
-static const char *Perl_interpreters Perl_interpreters628,24028
-static const char Perl_help 630,24100
-static const char *PHP_suffixes PHP_suffixes637,24451
-static const char PHP_help 639,24523
-static const char *plain_C_suffixes plain_C_suffixes643,24678
-static const char *PS_suffixes PS_suffixes647,24762
-static const char PS_help 649,24848
-static const char *Prolog_suffixes Prolog_suffixes652,24931
-static const char Prolog_help 654,24993
-static const char *Python_suffixes Python_suffixes658,25107
-static const char Python_help 660,25165
-static const char *Scheme_suffixes Scheme_suffixes665,25347
-static const char Scheme_help 667,25460
-static const char *TeX_suffixes TeX_suffixes672,25683
-static const char TeX_help 674,25781
-static const char *Texinfo_suffixes Texinfo_suffixes686,26316
-static const char Texinfo_help 688,26395
-static const char *Yacc_suffixes Yacc_suffixes691,26492
-static const char Yacc_help 693,26606
-static const char auto_help 699,26856
-static const char none_help 703,27020
-static const char no_lang_help 707,27143
-static language lang_names 718,27355
-print_language_names 753,29532
-# define EMACS_NAME 786,30755
-# define VERSION 789,30811
-print_version 792,30869
-# define PRINT_UNDOCUMENTED_OPTIONS_HELP 804,31173
-print_help 808,31250
-main 981,37438
-get_compressor_from_suffix 1319,46217
-get_language_from_langname 1355,47158
-get_language_from_interpreter 1377,47545
-get_language_from_filename 1399,47976
-process_file_name 1433,48834
-process_file 1555,51665
-init 1632,54150
-find_entries 1656,54901
-make_tag 1814,59707
-pfnote 1856,60942
-free_tree 1917,62744
-free_fdesc 1935,63029
-add_node 1955,63472
-invalidate_nodes 2035,65537
-static int number_len 2068,66193
-total_size_of_entries 2087,66694
-put_entries 2107,67154
-#define C_EXT 2193,68995
-#define C_PLAIN 2194,69037
-#define C_PLPL 2195,69070
-#define C_STAR 2196,69104
-#define C_JAVA 2197,69137
-#define C_AUTO 2198,69172
-#define YACC 2199,69242
-enum sym_type2204,69312
- st_none,2206,69328
- st_C_objprot,2207,69339
- st_C_objprot, st_C_objimpl,2207,69339
- st_C_objprot, st_C_objimpl, st_C_objend,2207,69339
- st_C_gnumacro,2208,69382
- st_C_ignore,2209,69399
- st_C_ignore, st_C_attribute,2209,69399
- st_C_javastruct,2210,69430
- st_C_operator,2211,69449
- st_C_class,2212,69466
- st_C_class, st_C_template,2212,69466
- st_C_struct,2213,69495
- st_C_struct, st_C_extern,2213,69495
- st_C_struct, st_C_extern, st_C_enum,2213,69495
- st_C_struct, st_C_extern, st_C_enum, st_C_define,2213,69495
- st_C_struct, st_C_extern, st_C_enum, st_C_define, st_C_typedef2213,69495
-struct C_stab_entry 2271,71278
-struct C_stab_entry { const char *name;name2271,71278
-struct C_stab_entry { const char *name; int c_ext;2271,71278
-struct C_stab_entry { const char *name; int c_ext; enum sym_type type;2271,71278
-hash 2275,71409
-in_word_set 2321,72937
- TOTAL_KEYWORDS 2325,73018
- MIN_WORD_LENGTH 2326,73045
- MAX_WORD_LENGTH 2327,73072
- MIN_HASH_VALUE 2328,73100
- MAX_HASH_VALUE 2329,73126
-C_symtype 2387,74985
-static bool inattribute;2400,75234
- fvnone,2408,75435
- fdefunkey,2409,75466
- fdefunname,2410,75512
- foperator,2411,75556
- fvnameseen,2412,75613
- fstartlist,2413,75666
- finlist,2414,75722
- flistseen,2415,75765
- fignore,2416,75813
- vignore 2417,75856
-} fvdef;2418,75901
-static bool fvextern;2420,75911
- tnone,2428,76089
- tkeyseen,2429,76119
- ttypeseen,2430,76160
- tinbody,2431,76199
- tend,2432,76238
- tignore 2433,76279
-} typdef;2434,76320
- snone,2443,76499
- skeyseen,2445,76575
- stagseen,2446,76620
- scolonseen 2447,76661
-} structdef;2448,76715
-static const char *objtag objtag2453,76809
- dnone,2460,76942
- dsharpseen,2461,76972
- ddefineseen,2462,77025
- dignorerest 2463,77070
-} definedef;2464,77112
- onone,2472,77267
- oprotocol,2473,77297
- oimplementation,2474,77347
- otagseen,2475,77395
- oparenseen,2476,77431
- ocatseen,2477,77486
- oinbody,2478,77525
- omethodsign,2479,77568
- omethodtag,2480,77626
- omethodcolon,2481,77666
- omethodparm,2482,77709
- oignore 2483,77755
-} objdef;2484,77787
-static struct tok2491,77944
- char *line;line2493,77964
- int offset;2494,78014
- int length;2495,78067
- bool valid;2502,78352
- bool named;2505,78487
- int lineno;2506,78528
- long linepos;2507,78576
-} token;2508,78626
- char **cname;cname2519,78950
- int *bracelev;bracelev2520,78993
- int nl;2521,79042
- int size;2522,79096
-} cstack;2523,79136
-#define nestlev 2525,79264
-#define instruct 2527,79369
-pushclass_above 2531,79489
-popclass_above 2550,79948
-write_classname 2564,80162
-consider_token 2613,81341
- long linepos;2922,88499
- linebuffer lb;2923,88515
-} lbs[lbs2924,88532
-#define current_lb_is_new 2926,88543
-#define switch_line_buffers(2927,88588
-#define curlb 2929,88641
-#define newlb 2930,88672
-#define curlinepos 2931,88703
-#define newlinepos 2932,88744
-#define plainc 2934,88786
-#define cplpl 2935,88830
-#define cjava 2936,88861
-#define CNL_SAVE_DEFINEDEF(2938,88905
-#define CNL(2947,89117
-make_C_tag 2960,89375
-C_entries 2986,90194
-default_C_entries 3833,110156
-plain_C_entries 3840,110276
-Cplusplus_entries 3847,110364
-Cjava_entries 3854,110460
-Cstar_entries 3861,110550
-Yacc_entries 3868,110642
-#define LOOP_ON_INPUT_LINES(3875,110720
-#define LOOKING_AT(3884,111056
-#define LOOKING_AT_NOCASE(3891,111461
-just_read_file 3901,111861
-F_takeprec 3914,112039
-F_getit 3937,112366
-Fortran_functions 3961,112840
-Ada_getit 4052,114669
-Ada_funcs 4115,116044
-Asm_labels 4228,118582
-Perl_functions 4261,119549
-Python_functions 4357,122057
-PHP_functions 4387,122684
-Cobol_paragraphs 4466,124471
-Makefile_targets 4494,125029
-Pascal_functions 4529,125950
-L_getit 4709,130318
-Lisp_functions 4725,130664
-Lua_functions 4785,131850
-PS_functions 4811,132385
-Forth_words 4841,133053
-Scheme_functions 4877,134092
-static linebuffer *TEX_toktab TEX_toktab4908,134781
-static const char *TEX_defenv TEX_defenv4912,134974
-static char TEX_esc 4920,135261
-static char TEX_opgrp 4921,135289
-static char TEX_clgrp 4922,135318
-TeX_commands 4928,135395
-#define TEX_LESC 4986,136652
-#define TEX_SESC 4987,136674
-TEX_mode 4992,136804
-TEX_decode_env 5026,137509
-Texinfo_nodes 5071,138554
-HTML_labels 5094,139013
-Prolog_functions 5219,142347
-prolog_skip_comment 5255,143128
-prolog_pr 5281,143736
-prolog_atom 5319,144628
-Erlang_functions 5379,145666
-erlang_func 5438,146965
-erlang_attribute 5476,147642
-erlang_atom 5496,148061
-scan_separators 5534,149080
-analyze_regex 5586,150460
-add_regex 5654,152050
-substitute 5767,154797
-free_regexps 5814,155837
-regex_tag_multiline 5836,156291
-nocase_tail 5913,158263
-get_tag 5928,158519
-readline_internal 5959,159455
-readline 6037,161296
-savestr 6230,167243
-savenstr 6240,167473
-skip_spaces 6249,167679
-skip_non_spaces 6258,167833
-skip_name 6267,167983
-fatal 6277,168156
-pfatal 6284,168253
-suggest_asking_for_help 6291,168332
-error 6300,168554
-concat 6313,168846
-etags_getcwd 6329,169259
-relative_filename 6350,169725
-absolute_filename 6389,170751
-absolute_dirname 6453,172416
-filename_is_absolute 6472,172845
-canonicalize_filename 6484,173096
-# define ISUPPER(6491,173235
-linebuffer_init 6514,173656
-linebuffer_setlen 6524,173887
-xmalloc 6536,174148
-xrealloc 6545,174314
+char pot_etags_version[pot_etags_version81,3471
+# undef DEBUG84,3553
+# define DEBUG 85,3568
+# define DEBUG 87,3595
+# define NDEBUG 88,3618
+# define _GNU_SOURCE 94,3706
+# undef MSDOS100,3877
+# undef WINDOWSNT101,3891
+# define WINDOWSNT102,3910
+# undef MSDOS106,3969
+# define MSDOS 107,3983
+# define MSDOS 110,4033
+# define MAXPATHLEN 115,4112
+# undef HAVE_NTGUI116,4142
+# undef DOS_NT117,4161
+# define DOS_NT118,4177
+# undef assert 135,4483
+# define assert(136,4542
+# undef CTAGS146,4858
+# define CTAGS 147,4873
+# define CTAGS 149,4899
+#define streq(152,4928
+#define strcaseeq(153,4997
+#define strneq(154,5076
+#define strncaseeq(155,5152
+#define CHARS 157,5239
+#define CHAR(158,5279
+#define iswhite(159,5330
+#define notinname(160,5395
+#define begtoken(161,5470
+#define intoken(162,5543
+#define endtoken(163,5615
+#define ISALNUM(165,5685
+#define ISALPHA(166,5723
+#define ISDIGIT(167,5761
+#define ISLOWER(168,5799
+#define lowcase(170,5838
+#define xnew(179,6016
+#define xrnew(180,6084
+typedef void Lang_function 182,6165
+ const char *suffix;suffix186,6220
+ const char *command;command187,6295
+} compressor;188,6366
+ const char *name;name192,6398
+ const char *help;help193,6450
+ Lang_function *function;function194,6509
+ const char **suffixes;suffixes195,6557
+ const char **filenames;filenames196,6634
+ const char **interpreters;interpreters197,6703
+ bool metasource;198,6772
+} language;199,6836
+typedef struct fdesc201,6849
+ struct fdesc *next;next203,6872
+ char *infname;infname204,6921
+ char *infabsname;infabsname205,6974
+ char *infabsdir;infabsdir206,7039
+ char *taggedfname;taggedfname207,7092
+ language *lang;lang208,7150
+ char *prop;prop209,7192
+ bool usecharno;210,7250
+ bool written;211,7312
+} fdesc;212,7367
+typedef struct node_st214,7377
+ struct node_st *left,left216,7429
+ struct node_st *left, *right;right216,7429
+ fdesc *fdp;fdp217,7487
+ char *name;name218,7549
+ char *regex;regex219,7581
+ bool valid;220,7618
+ bool is_func;221,7671
+ bool been_warned;222,7734
+ int lno;223,7802
+ long cno;224,7843
+} node;225,7895
+ long size;236,8209
+ int len;237,8222
+ char *buffer;buffer238,8233
+} linebuffer;239,8249
+ at_language,245,8345
+ at_regexp,246,8394
+ at_filename,247,8438
+ at_stdin,248,8474
+ at_end 249,8517
+ } arg_type;250,8558
+ language *lang;lang251,8594
+ char *what;what252,8657
+} argument;253,8699
+typedef struct regexp256,8759
+ struct regexp *p_next;p_next258,8783
+ language *lang;lang259,8838
+ char *pattern;pattern260,8898
+ char *name;name261,8941
+ struct re_pattern_buffer *pat;pat262,8972
+ struct re_registers regs;263,9032
+ bool error_signaled;264,9079
+ bool force_explicit_name;265,9142
+ bool ignore_case;266,9207
+ bool multi_line;267,9260
+} regexp;268,9326
+static void error 311,10781
+# undef STDIN408,15074
+#define STDIN 411,15096
+static compressor compressors[compressors457,17665
+static const char *Ada_suffixes Ada_suffixes473,17908
+static const char Ada_help 475,17978
+static const char *Asm_suffixes Asm_suffixes493,18581
+static const char Asm_help 504,18977
+static const char *default_C_suffixes default_C_suffixes512,19313
+static const char default_C_help 515,19414
+static const char default_C_help 523,19851
+static const char *Cplusplus_suffixes Cplusplus_suffixes535,20461
+static const char Cplusplus_help 540,20659
+static const char *Cjava_suffixes Cjava_suffixes549,21114
+static char Cjava_help 551,21173
+static const char *Cobol_suffixes Cobol_suffixes556,21338
+static char Cobol_help 558,21403
+static const char *Cstar_suffixes Cstar_suffixes562,21544
+static const char *Erlang_suffixes Erlang_suffixes565,21608
+static const char Erlang_help 567,21674
+const char *Forth_suffixes Forth_suffixes571,21800
+static const char Forth_help 573,21858
+static const char *Fortran_suffixes Fortran_suffixes577,22009
+static const char Fortran_help 579,22086
+static const char *HTML_suffixes HTML_suffixes582,22191
+static const char HTML_help 584,22265
+static const char *Lisp_suffixes Lisp_suffixes589,22453
+static const char Lisp_help 591,22557
+static const char *Lua_suffixes Lua_suffixes598,22872
+static const char Lua_help 600,22935
+static const char *Makefile_filenames Makefile_filenames603,23011
+static const char Makefile_help 605,23134
+static const char *Objc_suffixes Objc_suffixes609,23278
+static const char Objc_help 613,23400
+static const char *Pascal_suffixes Pascal_suffixes619,23715
+static const char Pascal_help 621,23779
+static const char *Perl_suffixes Perl_suffixes626,23967
+static const char *Perl_interpreters Perl_interpreters628,24029
+static const char Perl_help 630,24101
+static const char *PHP_suffixes PHP_suffixes637,24452
+static const char PHP_help 639,24524
+static const char *plain_C_suffixes plain_C_suffixes643,24679
+static const char *PS_suffixes PS_suffixes647,24763
+static const char PS_help 649,24849
+static const char *Prolog_suffixes Prolog_suffixes652,24932
+static const char Prolog_help 654,24994
+static const char *Python_suffixes Python_suffixes658,25108
+static const char Python_help 660,25166
+static const char *Scheme_suffixes Scheme_suffixes665,25348
+static const char Scheme_help 667,25461
+static const char *TeX_suffixes TeX_suffixes672,25684
+static const char TeX_help 674,25782
+static const char *Texinfo_suffixes Texinfo_suffixes686,26317
+static const char Texinfo_help 688,26396
+static const char *Yacc_suffixes Yacc_suffixes691,26493
+static const char Yacc_help 693,26607
+static const char auto_help 699,26857
+static const char none_help 703,27021
+static const char no_lang_help 707,27144
+static language lang_names 718,27356
+print_language_names 753,29533
+# define EMACS_NAME 786,30756
+# define VERSION 789,30812
+print_version 792,30870
+# define PRINT_UNDOCUMENTED_OPTIONS_HELP 804,31174
+print_help 808,31251
+main 981,37439
+get_compressor_from_suffix 1319,46218
+get_language_from_langname 1355,47159
+get_language_from_interpreter 1377,47546
+get_language_from_filename 1399,47977
+process_file_name 1433,48835
+process_file 1555,51666
+init 1632,54151
+find_entries 1656,54902
+make_tag 1814,59708
+pfnote 1856,60943
+free_tree 1917,62745
+free_fdesc 1935,63030
+add_node 1955,63473
+invalidate_nodes 2035,65538
+static int number_len 2068,66194
+total_size_of_entries 2087,66695
+put_entries 2107,67155
+#define C_EXT 2193,68996
+#define C_PLAIN 2194,69038
+#define C_PLPL 2195,69071
+#define C_STAR 2196,69105
+#define C_JAVA 2197,69138
+#define C_AUTO 2198,69173
+#define YACC 2199,69243
+enum sym_type2204,69313
+ st_none,2206,69329
+ st_C_objprot,2207,69340
+ st_C_objprot, st_C_objimpl,2207,69340
+ st_C_objprot, st_C_objimpl, st_C_objend,2207,69340
+ st_C_gnumacro,2208,69383
+ st_C_ignore,2209,69400
+ st_C_ignore, st_C_attribute,2209,69400
+ st_C_javastruct,2210,69431
+ st_C_operator,2211,69450
+ st_C_class,2212,69467
+ st_C_class, st_C_template,2212,69467
+ st_C_struct,2213,69496
+ st_C_struct, st_C_extern,2213,69496
+ st_C_struct, st_C_extern, st_C_enum,2213,69496
+ st_C_struct, st_C_extern, st_C_enum, st_C_define,2213,69496
+ st_C_struct, st_C_extern, st_C_enum, st_C_define, st_C_typedef2213,69496
+struct C_stab_entry 2271,71279
+struct C_stab_entry { const char *name;name2271,71279
+struct C_stab_entry { const char *name; int c_ext;2271,71279
+struct C_stab_entry { const char *name; int c_ext; enum sym_type type;2271,71279
+hash 2275,71410
+in_word_set 2321,72938
+ TOTAL_KEYWORDS 2325,73019
+ MIN_WORD_LENGTH 2326,73046
+ MAX_WORD_LENGTH 2327,73073
+ MIN_HASH_VALUE 2328,73101
+ MAX_HASH_VALUE 2329,73127
+C_symtype 2387,74986
+static bool inattribute;2400,75235
+ fvnone,2408,75436
+ fdefunkey,2409,75467
+ fdefunname,2410,75513
+ foperator,2411,75557
+ fvnameseen,2412,75614
+ fstartlist,2413,75667
+ finlist,2414,75723
+ flistseen,2415,75766
+ fignore,2416,75814
+ vignore 2417,75857
+} fvdef;2418,75902
+static bool fvextern;2420,75912
+ tnone,2428,76090
+ tkeyseen,2429,76120
+ ttypeseen,2430,76161
+ tinbody,2431,76200
+ tend,2432,76239
+ tignore 2433,76280
+} typdef;2434,76321
+ snone,2443,76500
+ skeyseen,2445,76576
+ stagseen,2446,76621
+ scolonseen 2447,76662
+} structdef;2448,76716
+static const char *objtag objtag2453,76810
+ dnone,2460,76943
+ dsharpseen,2461,76973
+ ddefineseen,2462,77026
+ dignorerest 2463,77071
+} definedef;2464,77113
+ onone,2472,77268
+ oprotocol,2473,77298
+ oimplementation,2474,77348
+ otagseen,2475,77396
+ oparenseen,2476,77432
+ ocatseen,2477,77487
+ oinbody,2478,77526
+ omethodsign,2479,77569
+ omethodtag,2480,77627
+ omethodcolon,2481,77667
+ omethodparm,2482,77710
+ oignore 2483,77756
+} objdef;2484,77788
+static struct tok2491,77945
+ char *line;line2493,77965
+ int offset;2494,78015
+ int length;2495,78068
+ bool valid;2502,78353
+ bool named;2505,78488
+ int lineno;2506,78529
+ long linepos;2507,78577
+} token;2508,78627
+ char **cname;cname2519,78951
+ int *bracelev;bracelev2520,78994
+ int nl;2521,79043
+ int size;2522,79097
+} cstack;2523,79137
+#define nestlev 2525,79265
+#define instruct 2527,79370
+pushclass_above 2531,79490
+popclass_above 2550,79949
+write_classname 2564,80163
+consider_token 2613,81342
+ long linepos;2922,88500
+ linebuffer lb;2923,88516
+} lbs[lbs2924,88533
+#define current_lb_is_new 2926,88544
+#define switch_line_buffers(2927,88589
+#define curlb 2929,88642
+#define newlb 2930,88673
+#define curlinepos 2931,88704
+#define newlinepos 2932,88745
+#define plainc 2934,88787
+#define cplpl 2935,88831
+#define cjava 2936,88862
+#define CNL_SAVE_DEFINEDEF(2938,88906
+#define CNL(2947,89118
+make_C_tag 2960,89376
+C_entries 2986,90195
+default_C_entries 3833,110157
+plain_C_entries 3840,110277
+Cplusplus_entries 3847,110365
+Cjava_entries 3854,110461
+Cstar_entries 3861,110551
+Yacc_entries 3868,110643
+#define LOOP_ON_INPUT_LINES(3875,110721
+#define LOOKING_AT(3884,111057
+#define LOOKING_AT_NOCASE(3891,111462
+just_read_file 3901,111862
+F_takeprec 3914,112040
+F_getit 3937,112367
+Fortran_functions 3961,112841
+Ada_getit 4052,114670
+Ada_funcs 4115,116045
+Asm_labels 4228,118583
+Perl_functions 4261,119550
+Python_functions 4357,122058
+PHP_functions 4387,122685
+Cobol_paragraphs 4466,124472
+Makefile_targets 4494,125030
+Pascal_functions 4529,125951
+L_getit 4709,130319
+Lisp_functions 4725,130665
+Lua_functions 4785,131851
+PS_functions 4811,132386
+Forth_words 4841,133054
+Scheme_functions 4877,134093
+static linebuffer *TEX_toktab TEX_toktab4908,134782
+static const char *TEX_defenv TEX_defenv4912,134975
+static char TEX_esc 4920,135262
+static char TEX_opgrp 4921,135290
+static char TEX_clgrp 4922,135319
+TeX_commands 4928,135396
+#define TEX_LESC 4986,136653
+#define TEX_SESC 4987,136675
+TEX_mode 4992,136805
+TEX_decode_env 5026,137510
+Texinfo_nodes 5071,138555
+HTML_labels 5094,139014
+Prolog_functions 5219,142348
+prolog_skip_comment 5255,143129
+prolog_pr 5281,143737
+prolog_atom 5319,144629
+Erlang_functions 5379,145667
+erlang_func 5438,146966
+erlang_attribute 5476,147643
+erlang_atom 5496,148062
+scan_separators 5534,149081
+analyze_regex 5586,150461
+add_regex 5654,152051
+substitute 5767,154798
+free_regexps 5814,155838
+regex_tag_multiline 5836,156292
+nocase_tail 5913,158264
+get_tag 5928,158520
+readline_internal 5959,159456
+readline 6037,161297
+savestr 6230,167244
+savenstr 6240,167474
+skip_spaces 6249,167680
+skip_non_spaces 6258,167834
+skip_name 6267,167984
+fatal 6277,168157
+pfatal 6284,168254
+suggest_asking_for_help 6291,168333
+error 6300,168555
+concat 6313,168847
+etags_getcwd 6329,169260
+relative_filename 6350,169726
+absolute_filename 6389,170752
+absolute_dirname 6453,172417
+filename_is_absolute 6472,172846
+canonicalize_filename 6484,173097
+# define ISUPPER(6491,173236
+linebuffer_init 6514,173657
+linebuffer_setlen 6524,173888
+xmalloc 6536,174149
+xrealloc 6545,174315
c-src/exit.c,99
size_t n;28,972
@@ -673,1488 +671,1488 @@ pp287,1504
pp3(100,1616
c-src/emacs/src/gmalloc.c,4207
-#define USE_PTHREAD25,1002
-#undef get_current_dir_name33,1126
-#undef malloc64,2110
-#undef realloc65,2124
-#undef calloc66,2139
-#undef free67,2153
-#define malloc 68,2165
-#define realloc 69,2188
-#define calloc 70,2213
-#define aligned_alloc 71,2236
-#define free 72,2273
-#define DUMPED 80,2472
-#define ALLOCATED_BEFORE_DUMPING(81,2507
-extern void *malloc malloc94,2718
-#define INT_BIT 124,3934
-#define BLOCKLOG 125,3977
-#define BLOCKSIZE 126,4018
-#define BLOCKIFY(127,4052
-#define HEAP 131,4215
-#define FINAL_FREE_BLOCKS 135,4391
- int type;145,4676
- size_t nfree;150,4720
- size_t first;151,4777
- } frag;152,4834
- ptrdiff_t size;156,5055
- } info;157,5076
- } busy;158,5087
- size_t size;163,5215
- size_t next;164,5272
- size_t prev;165,5321
- } free;166,5374
- } malloc_info;167,5388
-#define BLOCK(176,5620
-#define ADDRESS(177,5682
-struct list186,5939
- struct list *next;next188,5955
- struct list *prev;prev189,5978
-struct alignlist196,6153
- struct alignlist *next;next198,6174
- void *aligned;aligned199,6202
- void *exact;exact200,6270
-#define LOCK(223,7064
-#define UNLOCK(228,7195
-#define LOCK_ALIGNED_BLOCKS(233,7329
-#define UNLOCK_ALIGNED_BLOCKS(238,7484
-#define LOCK(244,7649
-#define UNLOCK(245,7664
-#define LOCK_ALIGNED_BLOCKS(246,7681
-#define UNLOCK_ALIGNED_BLOCKS(247,7711
-enum mcheck_status283,9092
- MCHECK_DISABLED 285,9115
- MCHECK_OK,286,9187
- MCHECK_FREE,287,9226
- MCHECK_HEAD,288,9270
- MCHECK_TAIL 289,9334
-struct mstats308,10153
- size_t bytes_total;310,10171
- size_t chunks_used;311,10225
- size_t bytes_used;312,10285
- size_t chunks_free;313,10351
- size_t bytes_free;314,10406
-char *_heapbase;_heapbase355,11829
-malloc_info *_heapinfo;_heapinfo358,11927
-static size_t heapsize;361,11983
-size_t _heapindex;364,12047
-size_t _heaplimit;367,12109
-struct list _fraghead[_fraghead370,12171
-size_t _chunks_used;373,12229
-size_t _bytes_used;374,12250
-size_t _chunks_free;375,12270
-size_t _bytes_free;376,12291
-int __malloc_initialized;379,12340
-size_t __malloc_extra_blocks;381,12367
-static int state_protected_p;400,12912
-static size_t last_state_size;401,12942
-static malloc_info *last_heapinfo;last_heapinfo402,12973
-protect_malloc_state 405,13014
-#define PROTECT_MALLOC_STATE(426,13627
-#define PROTECT_MALLOC_STATE(429,13697
-align 435,13794
-get_contiguous_space 466,14616
-register_heapinfo 497,15325
-pthread_mutex_t _malloc_mutex 517,15879
-pthread_mutex_t _aligned_blocks_mutex 518,15938
-int _malloc_thread_enabled_p;519,16005
-malloc_atfork_handler_prepare 522,16048
-malloc_atfork_handler_parent 529,16139
-malloc_atfork_handler_child 536,16233
-malloc_enable_thread 544,16375
-malloc_initialize_1 563,16961
-__malloc_initialize 594,17793
-static int morecore_recursing;604,17926
-morecore_nolock 609,18066
-_malloc_internal_nolock 722,21584
-_malloc_internal 920,28102
-malloc 932,28247
-_malloc 961,29140
-_free 967,29196
-_realloc 973,29240
-struct alignlist *_aligned_blocks _aligned_blocks1004,30345
-_free_internal_nolock 1009,30474
-_free_internal 1255,38476
-free 1265,38603
-weak_alias 1277,38799
-#define min(1306,39813
-_realloc_internal_nolock 1319,40309
-_realloc_internal 1435,43563
-realloc 1447,43726
-calloc 1478,44894
-#define __sbrk 1513,46042
-__default_morecore 1525,46511
-aligned_alloc 1557,47522
-memalign 1647,49704
-posix_memalign 1656,49909
-static size_t pagesize;1703,51317
-valloc 1706,51349
-#undef malloc1715,51490
-#undef realloc1716,51504
-#undef calloc1717,51519
-#undef aligned_alloc1718,51533
-#undef free1719,51554
-hybrid_malloc 1736,52083
-hybrid_calloc 1744,52188
-hybrid_free 1752,52319
-hybrid_aligned_alloc 1765,52626
-hybrid_realloc 1780,52984
-hybrid_get_current_dir_name 1811,53797
-#define MAGICWORD 1854,55206
-#define MAGICFREE 1855,55261
-#define MAGICBYTE 1856,55316
-#define MALLOCFLOOD 1857,55348
-#define FREEFLOOD 1858,55382
-struct hdr1860,55415
- size_t size;1862,55430
- size_t magic;1863,55484
-checkhdr 1867,55581
-freehook 1891,56022
-mallochook 1927,56804
-reallochook 1944,57143
-mabort 1978,57901
-static int mcheck_used 2012,58586
-mcheck 2015,58619
-mprobe 2035,59138
+#define USE_PTHREAD25,1003
+#undef get_current_dir_name33,1127
+#undef malloc64,2111
+#undef realloc65,2125
+#undef calloc66,2140
+#undef free67,2154
+#define malloc 68,2166
+#define realloc 69,2189
+#define calloc 70,2214
+#define aligned_alloc 71,2237
+#define free 72,2274
+#define DUMPED 80,2473
+#define ALLOCATED_BEFORE_DUMPING(81,2508
+extern void *malloc malloc94,2719
+#define INT_BIT 124,3935
+#define BLOCKLOG 125,3978
+#define BLOCKSIZE 126,4019
+#define BLOCKIFY(127,4053
+#define HEAP 131,4216
+#define FINAL_FREE_BLOCKS 135,4392
+ int type;145,4677
+ size_t nfree;150,4721
+ size_t first;151,4778
+ } frag;152,4835
+ ptrdiff_t size;156,5056
+ } info;157,5077
+ } busy;158,5088
+ size_t size;163,5216
+ size_t next;164,5273
+ size_t prev;165,5322
+ } free;166,5375
+ } malloc_info;167,5389
+#define BLOCK(176,5621
+#define ADDRESS(177,5683
+struct list186,5940
+ struct list *next;next188,5956
+ struct list *prev;prev189,5979
+struct alignlist196,6154
+ struct alignlist *next;next198,6175
+ void *aligned;aligned199,6203
+ void *exact;exact200,6271
+#define LOCK(223,7065
+#define UNLOCK(228,7196
+#define LOCK_ALIGNED_BLOCKS(233,7330
+#define UNLOCK_ALIGNED_BLOCKS(238,7485
+#define LOCK(244,7650
+#define UNLOCK(245,7665
+#define LOCK_ALIGNED_BLOCKS(246,7682
+#define UNLOCK_ALIGNED_BLOCKS(247,7712
+enum mcheck_status283,9093
+ MCHECK_DISABLED 285,9116
+ MCHECK_OK,286,9188
+ MCHECK_FREE,287,9227
+ MCHECK_HEAD,288,9271
+ MCHECK_TAIL 289,9335
+struct mstats308,10154
+ size_t bytes_total;310,10172
+ size_t chunks_used;311,10226
+ size_t bytes_used;312,10286
+ size_t chunks_free;313,10352
+ size_t bytes_free;314,10407
+char *_heapbase;_heapbase355,11831
+malloc_info *_heapinfo;_heapinfo358,11929
+static size_t heapsize;361,11985
+size_t _heapindex;364,12049
+size_t _heaplimit;367,12111
+struct list _fraghead[_fraghead370,12173
+size_t _chunks_used;373,12231
+size_t _bytes_used;374,12252
+size_t _chunks_free;375,12272
+size_t _bytes_free;376,12293
+int __malloc_initialized;379,12342
+size_t __malloc_extra_blocks;381,12369
+static int state_protected_p;400,12914
+static size_t last_state_size;401,12944
+static malloc_info *last_heapinfo;last_heapinfo402,12975
+protect_malloc_state 405,13016
+#define PROTECT_MALLOC_STATE(426,13629
+#define PROTECT_MALLOC_STATE(429,13699
+align 435,13796
+get_contiguous_space 466,14618
+register_heapinfo 497,15327
+pthread_mutex_t _malloc_mutex 517,15881
+pthread_mutex_t _aligned_blocks_mutex 518,15940
+int _malloc_thread_enabled_p;519,16007
+malloc_atfork_handler_prepare 522,16050
+malloc_atfork_handler_parent 529,16141
+malloc_atfork_handler_child 536,16235
+malloc_enable_thread 544,16377
+malloc_initialize_1 563,16963
+__malloc_initialize 594,17795
+static int morecore_recursing;604,17928
+morecore_nolock 609,18068
+_malloc_internal_nolock 722,21586
+_malloc_internal 920,28104
+malloc 932,28249
+_malloc 961,29142
+_free 967,29198
+_realloc 973,29242
+struct alignlist *_aligned_blocks _aligned_blocks1004,30348
+_free_internal_nolock 1009,30477
+_free_internal 1255,38479
+free 1265,38606
+weak_alias 1277,38802
+#define min(1306,39817
+_realloc_internal_nolock 1319,40313
+_realloc_internal 1435,43567
+realloc 1447,43730
+calloc 1478,44899
+#define __sbrk 1513,46048
+__default_morecore 1525,46517
+aligned_alloc 1557,47529
+memalign 1647,49711
+posix_memalign 1656,49916
+static size_t pagesize;1703,51325
+valloc 1706,51357
+#undef malloc1715,51498
+#undef realloc1716,51512
+#undef calloc1717,51527
+#undef aligned_alloc1718,51541
+#undef free1719,51562
+hybrid_malloc 1736,52091
+hybrid_calloc 1744,52196
+hybrid_free 1752,52327
+hybrid_aligned_alloc 1765,52634
+hybrid_realloc 1780,52990
+hybrid_get_current_dir_name 1811,53803
+#define MAGICWORD 1854,55213
+#define MAGICFREE 1855,55268
+#define MAGICBYTE 1856,55323
+#define MALLOCFLOOD 1857,55355
+#define FREEFLOOD 1858,55389
+struct hdr1860,55422
+ size_t size;1862,55437
+ size_t magic;1863,55491
+checkhdr 1867,55588
+freehook 1891,56029
+mallochook 1927,56811
+reallochook 1944,57150
+mabort 1978,57908
+static int mcheck_used 2012,58593
+mcheck 2015,58626
+mprobe 2035,59145
c-src/emacs/src/regex.h,4485
-#define _REGEX_H 21,836
-typedef unsigned long reg_syntax_t;43,1577
-#define RE_BACKSLASH_ESCAPE_IN_LISTS 47,1749
-#define RE_BK_PLUS_QM 52,1969
-#define RE_CHAR_CLASSES 58,2298
-#define RE_CONTEXT_INDEP_ANCHORS 72,3032
-#define RE_CONTEXT_INDEP_OPS 80,3458
-#define RE_CONTEXT_INVALID_OPS 84,3658
-#define RE_DOT_NEWLINE 88,3801
-#define RE_DOT_NOT_NULL 92,3937
-#define RE_HAT_LISTS_NOT_NEWLINE 96,4082
-#define RE_INTERVALS 101,4292
-#define RE_LIMITED_OPS 105,4441
-#define RE_NEWLINE_ALT 109,4583
-#define RE_NO_BK_BRACES 114,4773
-#define RE_NO_BK_PARENS 118,4964
-#define RE_NO_BK_REFS 122,5120
-#define RE_NO_BK_VBAR 126,5316
-#define RE_NO_EMPTY_RANGES 132,5610
-#define RE_UNMATCHED_RIGHT_PAREN_ORD 136,5766
-#define RE_NO_POSIX_BACKTRACKING 140,5937
-#define RE_NO_GNU_OPS 144,6133
-#define RE_FRUGAL 147,6253
-#define RE_SHY_GROUPS 150,6360
-#define RE_NO_NEWLINE_ANCHOR 153,6468
-#define RE_DEBUG 161,6884
-#define RE_SYNTAX_EMACS 183,7684
-#define RE_SYNTAX_AWK 186,7780
-#define RE_SYNTAX_GNU_AWK 193,8084
-#define RE_SYNTAX_POSIX_AWK 197,8255
-#define RE_SYNTAX_GREP 201,8393
-#define RE_SYNTAX_EGREP 206,8549
-#define RE_SYNTAX_POSIX_EGREP 212,8765
-#define RE_SYNTAX_ED 216,8910
-#define RE_SYNTAX_SED 218,8954
-#define _RE_SYNTAX_POSIX_COMMON 221,9072
-#define RE_SYNTAX_POSIX_BASIC 225,9215
-#define RE_SYNTAX_POSIX_MINIMAL_BASIC 231,9508
-#define RE_SYNTAX_POSIX_EXTENDED 234,9598
-#define RE_SYNTAX_POSIX_MINIMAL_EXTENDED 242,9967
-# undef RE_DUP_MAX253,10454
-#define RE_DUP_MAX 256,10540
-#define REG_EXTENDED 263,10762
-#define REG_ICASE 267,10886
-#define REG_NEWLINE 272,11070
-#define REG_NOSUB 276,11248
-#define REG_NOTBOL 286,11614
-#define REG_NOTEOL 289,11688
- REG_ENOSYS 297,11859
- REG_NOERROR 300,11941
- REG_NOMATCH,301,11976
- REG_BADPAT,305,12123
- REG_ECOLLATE,306,12162
- REG_ECTYPE,307,12203
- REG_EESCAPE,308,12255
- REG_ESUBREG,309,12298
- REG_EBRACK,310,12345
- REG_EPAREN,311,12391
- REG_EBRACE,312,12436
- REG_BADBR,313,12472
- REG_ERANGE,314,12519
- REG_ESPACE,315,12560
- REG_BADRPT,316,12601
- REG_EEND,319,12693
- REG_ESIZE,320,12728
- REG_ERPAREN,321,12790
- REG_ERANGEX 322,12859
-} reg_errcode_t;323,12911
-# define RE_TRANSLATE_TYPE 332,13273
-struct re_pattern_buffer335,13315
- unsigned char *buffer;buffer341,13538
- size_t allocated;344,13614
- size_t used;347,13686
- reg_syntax_t syntax;350,13769
- char *fastmap;fastmap355,13975
- RE_TRANSLATE_TYPE translate;361,14241
- size_t re_nsub;364,14329
- unsigned can_be_null 370,14624
-#define REGS_UNALLOCATED 376,14889
-#define REGS_REALLOCATE 377,14916
-#define REGS_FIXED 378,14942
- unsigned regs_allocated 379,14963
- unsigned fastmap_accurate 383,15136
- unsigned no_sub 387,15267
- unsigned not_bol 391,15398
- unsigned not_eol 394,15475
- unsigned used_syntax 398,15655
- unsigned multibyte 403,15805
- unsigned target_multibyte 407,15941
- int charset_unibyte;410,16032
-typedef struct re_pattern_buffer regex_t;416,16098
-typedef ssize_t regoff_t;423,16492
-struct re_registers428,16652
- unsigned num_regs;430,16674
- regoff_t *start;start431,16695
- regoff_t *end;end432,16714
-# define RE_NREGS 440,16942
- regoff_t rm_so;449,17159
- regoff_t rm_eo;450,17239
-} regmatch_t;451,17317
-# define _Restrict_ 540,20886
-# define _Restrict_ 542,20979
-# define _Restrict_544,21018
-# define _Restrict_arr_ 555,21418
-# define _Restrict_arr_557,21461
-# define CHAR_CLASS_MAX_LENGTH 593,22470
-# define CHAR_CLASS_MAX_LENGTH 597,22648
-typedef wctype_t re_wctype_t;599,22692
-typedef wchar_t re_wchar_t;600,22722
-# define re_wctype 601,22750
-# define re_iswctype 602,22776
-# define re_wctype_to_bit(603,22806
-# define CHAR_CLASS_MAX_LENGTH 605,22844
-# define btowc(606,22906
-typedef enum { RECC_ERROR 609,22953
- RECC_ALNUM,610,22984
- RECC_ALNUM, RECC_ALPHA,610,22984
- RECC_ALNUM, RECC_ALPHA, RECC_WORD,610,22984
- RECC_GRAPH,611,23027
- RECC_GRAPH, RECC_PRINT,611,23027
- RECC_LOWER,612,23059
- RECC_LOWER, RECC_UPPER,612,23059
- RECC_PUNCT,613,23091
- RECC_PUNCT, RECC_CNTRL,613,23091
- RECC_DIGIT,614,23123
- RECC_DIGIT, RECC_XDIGIT,614,23123
- RECC_BLANK,615,23156
- RECC_BLANK, RECC_SPACE,615,23156
- RECC_MULTIBYTE,616,23188
- RECC_MULTIBYTE, RECC_NONASCII,616,23188
- RECC_ASCII,617,23227
- RECC_ASCII, RECC_UNIBYTE617,23227
-} re_wctype_t;618,23260
-typedef int re_wchar_t;623,23387
+#define _REGEX_H 21,837
+typedef unsigned long reg_syntax_t;43,1578
+#define RE_BACKSLASH_ESCAPE_IN_LISTS 47,1750
+#define RE_BK_PLUS_QM 52,1970
+#define RE_CHAR_CLASSES 58,2299
+#define RE_CONTEXT_INDEP_ANCHORS 72,3033
+#define RE_CONTEXT_INDEP_OPS 80,3459
+#define RE_CONTEXT_INVALID_OPS 84,3659
+#define RE_DOT_NEWLINE 88,3802
+#define RE_DOT_NOT_NULL 92,3938
+#define RE_HAT_LISTS_NOT_NEWLINE 96,4083
+#define RE_INTERVALS 101,4293
+#define RE_LIMITED_OPS 105,4442
+#define RE_NEWLINE_ALT 109,4584
+#define RE_NO_BK_BRACES 114,4774
+#define RE_NO_BK_PARENS 118,4965
+#define RE_NO_BK_REFS 122,5121
+#define RE_NO_BK_VBAR 126,5317
+#define RE_NO_EMPTY_RANGES 132,5611
+#define RE_UNMATCHED_RIGHT_PAREN_ORD 136,5767
+#define RE_NO_POSIX_BACKTRACKING 140,5938
+#define RE_NO_GNU_OPS 144,6134
+#define RE_FRUGAL 147,6254
+#define RE_SHY_GROUPS 150,6361
+#define RE_NO_NEWLINE_ANCHOR 153,6469
+#define RE_DEBUG 161,6885
+#define RE_SYNTAX_EMACS 183,7685
+#define RE_SYNTAX_AWK 186,7781
+#define RE_SYNTAX_GNU_AWK 193,8085
+#define RE_SYNTAX_POSIX_AWK 197,8256
+#define RE_SYNTAX_GREP 201,8394
+#define RE_SYNTAX_EGREP 206,8550
+#define RE_SYNTAX_POSIX_EGREP 212,8766
+#define RE_SYNTAX_ED 216,8911
+#define RE_SYNTAX_SED 218,8955
+#define _RE_SYNTAX_POSIX_COMMON 221,9073
+#define RE_SYNTAX_POSIX_BASIC 225,9216
+#define RE_SYNTAX_POSIX_MINIMAL_BASIC 231,9509
+#define RE_SYNTAX_POSIX_EXTENDED 234,9599
+#define RE_SYNTAX_POSIX_MINIMAL_EXTENDED 242,9968
+# undef RE_DUP_MAX253,10455
+#define RE_DUP_MAX 256,10541
+#define REG_EXTENDED 263,10763
+#define REG_ICASE 267,10887
+#define REG_NEWLINE 272,11071
+#define REG_NOSUB 276,11249
+#define REG_NOTBOL 286,11615
+#define REG_NOTEOL 289,11689
+ REG_ENOSYS 297,11860
+ REG_NOERROR 300,11942
+ REG_NOMATCH,301,11977
+ REG_BADPAT,305,12124
+ REG_ECOLLATE,306,12163
+ REG_ECTYPE,307,12204
+ REG_EESCAPE,308,12256
+ REG_ESUBREG,309,12299
+ REG_EBRACK,310,12346
+ REG_EPAREN,311,12392
+ REG_EBRACE,312,12437
+ REG_BADBR,313,12473
+ REG_ERANGE,314,12520
+ REG_ESPACE,315,12561
+ REG_BADRPT,316,12602
+ REG_EEND,319,12694
+ REG_ESIZE,320,12729
+ REG_ERPAREN,321,12791
+ REG_ERANGEX 322,12860
+} reg_errcode_t;323,12912
+# define RE_TRANSLATE_TYPE 332,13274
+struct re_pattern_buffer335,13316
+ unsigned char *buffer;buffer341,13539
+ size_t allocated;344,13615
+ size_t used;347,13687
+ reg_syntax_t syntax;350,13770
+ char *fastmap;fastmap355,13976
+ RE_TRANSLATE_TYPE translate;361,14242
+ size_t re_nsub;364,14330
+ unsigned can_be_null 370,14625
+#define REGS_UNALLOCATED 376,14890
+#define REGS_REALLOCATE 377,14917
+#define REGS_FIXED 378,14943
+ unsigned regs_allocated 379,14964
+ unsigned fastmap_accurate 383,15137
+ unsigned no_sub 387,15268
+ unsigned not_bol 391,15399
+ unsigned not_eol 394,15476
+ unsigned used_syntax 398,15656
+ unsigned multibyte 403,15806
+ unsigned target_multibyte 407,15942
+ int charset_unibyte;410,16033
+typedef struct re_pattern_buffer regex_t;416,16099
+typedef ssize_t regoff_t;423,16493
+struct re_registers428,16653
+ unsigned num_regs;430,16675
+ regoff_t *start;start431,16696
+ regoff_t *end;end432,16715
+# define RE_NREGS 440,16943
+ regoff_t rm_so;449,17160
+ regoff_t rm_eo;450,17240
+} regmatch_t;451,17318
+# define _Restrict_ 540,20887
+# define _Restrict_ 542,20980
+# define _Restrict_544,21019
+# define _Restrict_arr_ 555,21419
+# define _Restrict_arr_557,21462
+# define CHAR_CLASS_MAX_LENGTH 593,22471
+# define CHAR_CLASS_MAX_LENGTH 597,22649
+typedef wctype_t re_wctype_t;599,22693
+typedef wchar_t re_wchar_t;600,22723
+# define re_wctype 601,22751
+# define re_iswctype 602,22777
+# define re_wctype_to_bit(603,22807
+# define CHAR_CLASS_MAX_LENGTH 605,22845
+# define btowc(606,22907
+typedef enum { RECC_ERROR 609,22954
+ RECC_ALNUM,610,22985
+ RECC_ALNUM, RECC_ALPHA,610,22985
+ RECC_ALNUM, RECC_ALPHA, RECC_WORD,610,22985
+ RECC_GRAPH,611,23028
+ RECC_GRAPH, RECC_PRINT,611,23028
+ RECC_LOWER,612,23060
+ RECC_LOWER, RECC_UPPER,612,23060
+ RECC_PUNCT,613,23092
+ RECC_PUNCT, RECC_CNTRL,613,23092
+ RECC_DIGIT,614,23124
+ RECC_DIGIT, RECC_XDIGIT,614,23124
+ RECC_BLANK,615,23157
+ RECC_BLANK, RECC_SPACE,615,23157
+ RECC_MULTIBYTE,616,23189
+ RECC_MULTIBYTE, RECC_NONASCII,616,23189
+ RECC_ASCII,617,23228
+ RECC_ASCII, RECC_UNIBYTE617,23228
+} re_wctype_t;618,23261
+typedef int re_wchar_t;623,23388
c-src/emacs/src/keyboard.c,15923
-volatile int interrupt_input_blocked;76,1808
-volatile bool pending_signals;80,1944
-#define KBD_BUFFER_SIZE 82,1976
-KBOARD *initial_kboard;initial_kboard84,2006
-KBOARD *current_kboard;current_kboard85,2030
-static KBOARD *all_kboards;all_kboards86,2054
-static bool single_kboard;89,2154
-#define NUM_RECENT_KEYS 91,2182
-static int recent_keys_index;94,2269
-static int total_keys;97,2357
-static Lisp_Object recent_keys;100,2443
-Lisp_Object this_command_keys;107,2777
-ptrdiff_t this_command_key_count;108,2808
-static bool this_command_key_count_reset;112,2922
-static Lisp_Object raw_keybuf;116,3074
-static int raw_keybuf_count;117,3105
-#define GROW_RAW_KEYBUF 119,3135
-static ptrdiff_t this_single_command_key_start;125,3350
-static ptrdiff_t before_command_key_count;129,3498
-static ptrdiff_t before_command_echo_length;130,3541
-sigjmp_buf return_to_command_loop;135,3677
-static Lisp_Object recover_top_level_message;138,3791
-static Lisp_Object regular_top_level_message;143,3930
-static sys_jmp_buf getcjmp;147,4031
-bool waiting_for_input;150,4095
-static bool echoing;154,4186
-static struct kboard *ok_to_echo_at_next_pause;ok_to_echo_at_next_pause159,4328
-struct kboard *echo_kboard;echo_kboard166,4632
-Lisp_Object echo_message_buffer;171,4744
-bool immediate_quit;174,4837
-int quit_char;192,5623
-EMACS_INT command_loop_level;195,5680
-Lisp_Object unread_switch_frame;204,6108
-static ptrdiff_t last_non_minibuf_size;207,6216
-uintmax_t num_input_events;210,6334
-static EMACS_INT last_auto_save;214,6428
-static ptrdiff_t last_point_position;217,6523
-Lisp_Object internal_last_event_frame;228,7028
-static Lisp_Object read_key_sequence_cmd;232,7168
-static Lisp_Object read_key_sequence_remapped;233,7210
-static FILE *dribble;dribble236,7310
-bool input_pending;239,7368
-static bool input_was_pending;287,10022
-static struct input_event kbd_buffer[kbd_buffer291,10107
-static struct input_event *kbd_fetch_ptr;kbd_fetch_ptr297,10386
-static struct input_event * volatile kbd_store_ptr;302,10601
-unsigned timers_run;320,11296
-struct timespec *input_available_clear_time;input_available_clear_time324,11408
-bool interrupt_input;328,11573
-bool interrupts_deferred;331,11671
-static struct timespec timer_idleness_start_time;335,11746
-static struct timespec timer_last_idleness_start_time;340,11916
-#define READABLE_EVENTS_DO_TIMERS_NOW 346,12046
-#define READABLE_EVENTS_FILTER_EVENTS 347,12094
-#define READABLE_EVENTS_IGNORE_SQUEEZABLES 348,12142
-kset_echo_string 392,14088
-kset_kbd_queue 397,14184
-kset_keyboard_translate_table 402,14276
-kset_last_prefix_arg 407,14399
-kset_last_repeatable_command 412,14504
-kset_local_function_key_map 417,14625
-kset_overriding_terminal_local_map 422,14744
-kset_real_last_command 427,14877
-kset_system_key_syms 432,14986
-echo_add_key 443,15249
-echo_char 527,17527
-echo_dash 541,17813
-echo_now 586,19140
-cancel_echoing 635,20614
-echo_length 648,20922
-echo_truncate 660,21253
-add_command_key 672,21582
-recursive_edit_1 697,22406
-record_auto_save 742,23848
-force_auto_save_soon 751,24016
-DEFUN ("recursive-edit", Frecursive_edit,759,24137
-DEFUN ("recursive-edit", Frecursive_edit,recursive-edit759,24137
-recursive_edit_unwind 804,25747
-any_kboard_state 817,26013
-single_kboard_state 838,26665
-not_single_kboard_state 848,26803
-struct kboard_stack858,27065
- KBOARD *kboard;kboard860,27087
- struct kboard_stack *next;next861,27105
-static struct kboard_stack *kboard_stack;kboard_stack864,27138
-push_kboard 867,27186
-pop_kboard 879,27375
-temporarily_switch_to_single_kboard 914,28263
-record_single_kboard_state 943,29437
-restore_kboard_configuration 952,29621
-cmd_error 970,30077
-cmd_error_internal 1024,31510
-DEFUN ("command-error-default-function", Fcommand_error_default_function,1043,32030
-DEFUN ("command-error-default-function", Fcommand_error_default_function,command-error-default-function1043,32030
-command_loop 1094,33916
-command_loop_2 1134,35135
-top_level_2 1146,35339
-top_level_1 1152,35417
-DEFUN ("top-level", Ftop_level,1164,35787
-DEFUN ("top-level", Ftop_level,top-level1164,35787
-user_error 1183,36288
-DEFUN ("exit-recursive-edit", Fexit_recursive_edit,1189,36429
-DEFUN ("exit-recursive-edit", Fexit_recursive_edit,exit-recursive-edit1189,36429
-DEFUN ("abort-recursive-edit", Fabort_recursive_edit,1201,36819
-DEFUN ("abort-recursive-edit", Fabort_recursive_edit,abort-recursive-edit1201,36819
-tracking_off 1216,37281
-DEFUN ("internal--track-mouse", Ftrack_mouse,1234,37816
-DEFUN ("internal--track-mouse", Ftrack_mouse,track-mouse1234,37816
-bool ignore_mouse_drag_p;1256,38392
-some_mouse_moved 1259,38441
-Lisp_Object last_undo_boundary;1287,39032
-command_loop_1 1294,39273
-read_menu_command 1649,50889
-adjust_point_for_property 1678,51617
-safe_run_hooks_1 1831,57339
-safe_run_hooks_error 1841,57569
-safe_run_hook_funcall 1878,58576
-safe_run_hooks 1893,59058
-int poll_suppress_count;1908,59397
-static struct atimer *poll_timer;poll_timer1915,59487
-poll_for_input_1 1919,59589
-poll_for_input 1930,59789
-start_polling 1942,60053
-input_polling_used 1979,61091
-stop_polling 1994,61390
-set_poll_suppress_count 2009,61759
-bind_polling_period 2029,62141
-make_ctrl_char 2048,62492
-show_help_echo 2113,64455
-static Lisp_Object help_form_saved_window_configs;2156,65638
-read_char_help_form_unwind 2158,65701
-#define STOP_POLLING 2166,65959
-#define RESUME_POLLING 2170,66084
-read_event_from_main_queue 2175,66229
-read_decoded_event_from_main_queue 2249,68417
-#define MAX_ENCODED_BYTES 2254,68664
-echo_keystrokes_p 2342,71556
-read_char 2376,72848
-record_menu_key 3225,98949
-help_char_p 3258,99674
-record_char 3273,99953
-save_getcjmp 3412,104235
-restore_getcjmp 3418,104326
-readable_events 3430,104697
-int stop_character EXTERNALLY_VISIBLE;3497,106437
-event_to_kboard 3500,106493
-kbd_buffer_nr_stored 3522,107142
-kbd_buffer_store_event 3534,107483
-kbd_buffer_store_event_hold 3550,108025
-kbd_buffer_unget_event 3684,111617
-#define INPUT_EVENT_POS_MAX 3698,112018
-#define INPUT_EVENT_POS_MIN 3701,112147
-position_to_Time 3706,112287
-Time_to_position 3716,112514
-gen_help_event 3738,113171
-kbd_buffer_store_help_event 3756,113611
-discard_mouse_events 3773,113976
-kbd_buffer_events_waiting 3803,114711
-clear_event 3823,115068
-kbd_buffer_get_event 3836,115408
-process_special_events 4258,127881
-swallow_events 4322,129705
-timer_start_idle 4339,130098
-timer_stop_idle 4355,130576
-timer_resume_idle 4363,130720
-struct input_event last_timer_event EXTERNALLY_VISIBLE;4372,130912
-Lisp_Object pending_funcalls;4377,131172
-decode_timer 4381,131293
-timer_check_2 4414,132246
-timer_check 4572,136817
-DEFUN ("current-idle-time", Fcurrent_idle_time,4607,137662
-DEFUN ("current-idle-time", Fcurrent_idle_time,current-idle-time4607,137662
-static Lisp_Object accent_key_syms;4625,138239
-static Lisp_Object func_key_syms;4626,138275
-static Lisp_Object mouse_syms;4627,138309
-static Lisp_Object wheel_syms;4628,138340
-static Lisp_Object drag_n_drop_syms;4629,138371
-static const int lispy_accent_codes[lispy_accent_codes4634,138516
-static const char *const lispy_accent_keys[lispy_accent_keys4741,139878
-#define FUNCTION_KEY_OFFSET 4766,140314
-const char *const lispy_function_keys[lispy_function_keys4768,140347
-static const char *const lispy_multimedia_keys[lispy_multimedia_keys4962,148901
-static const char *const lispy_kana_keys[lispy_kana_keys5026,150135
-#define FUNCTION_KEY_OFFSET 5061,151751
-static const char *const lispy_function_keys[lispy_function_keys5065,151894
-#define ISO_FUNCTION_KEY_OFFSET 5149,154429
-static const char *const iso_lispy_function_keys[iso_lispy_function_keys5151,154469
-static Lisp_Object Vlispy_mouse_stem;5172,155328
-static const char *const lispy_wheel_names[lispy_wheel_names5174,155367
-static const char *const lispy_drag_n_drop_names[lispy_drag_n_drop_names5181,155619
-static short const scroll_bar_parts[scroll_bar_parts5189,155885
-static Lisp_Object button_down_location;5210,156910
-static int last_mouse_button;5215,157065
-static int last_mouse_x;5216,157095
-static int last_mouse_y;5217,157120
-static Time button_down_time;5218,157145
-static int double_click_count;5222,157229
-make_lispy_position 5228,157390
-toolkit_menubar_in_use 5456,163953
-make_scroll_bar_position 5469,164321
-make_lispy_event 5485,164967
-make_lispy_movement 6104,183531
-make_lispy_switch_frame 6131,184262
-make_lispy_focus_in 6137,184369
-make_lispy_focus_out 6145,184495
-parse_modifiers_uncached 6163,184945
-#define SINGLE_LETTER_MOD(6185,185465
-#undef SINGLE_LETTER_MOD6212,185906
-#define MULTI_LETTER_MOD(6214,185932
-#undef MULTI_LETTER_MOD6231,186400
-apply_modifiers_uncached 6273,187574
-static const char *const modifier_names[modifier_names6319,189193
-#define NUM_MOD_NAMES 6325,189399
-static Lisp_Object modifier_symbols;6327,189449
-lispy_modifier_list 6331,189586
-#define KEY_TO_CHAR(6353,190252
-parse_modifiers 6356,190328
-DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,6399,191517
-DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,event-symbol-parse-modifiers6399,191517
-apply_modifiers 6422,192391
-reorder_modifiers 6491,194720
-modify_event_symbol 6536,196528
-DEFUN ("event-convert-list", Fevent_convert_list,6628,199244
-DEFUN ("event-convert-list", Fevent_convert_list,event-convert-list6628,199244
-parse_solitary_modifier 6695,201135
-#define SINGLE_LETTER_MOD(6701,201258
-#define MULTI_LETTER_MOD(6705,201343
-#undef SINGLE_LETTER_MOD6763,202641
-#undef MULTI_LETTER_MOD6764,202666
-lucid_event_type_list_p 6775,202889
-get_input_pending 6814,203960
-record_asynch_buffer_change 6834,204579
-gobble_input 6872,205702
-tty_read_avail_input 6967,208310
-handle_async_input 7149,214039
-process_pending_signals 7165,214359
-unblock_input_to 7177,214645
-unblock_input 7200,215277
-totally_unblock_input 7209,215445
-handle_input_available_signal 7217,215529
-deliver_input_available_signal 7226,215700
-struct user_signal_info7235,215865
- int sig;7238,215915
- char *name;name7241,215956
- int npending;7244,216007
- struct user_signal_info *next;next7246,216024
-static struct user_signal_info *user_signals user_signals7250,216090
-add_user_signal 7253,216149
-handle_user_signal 7275,216598
-deliver_user_signal 7316,217558
-find_user_signal_name 7322,217659
-store_user_signal_events 7334,217841
-static Lisp_Object menu_bar_one_keymap_changed_items;7363,218416
-static Lisp_Object menu_bar_items_vector;7368,218630
-static int menu_bar_items_index;7369,218672
-static const char *separator_names[separator_names7372,218707
-menu_separator_name_p 7393,219148
-menu_bar_items 7426,219852
-Lisp_Object item_properties;7568,224603
-menu_bar_item 7571,224645
-menu_item_eval_property_1 7647,227175
-eval_dyn 7658,227465
-menu_item_eval_property 7666,227675
-parse_menu_item 7686,228341
-static Lisp_Object tool_bar_items_vector;7965,236336
-static Lisp_Object tool_bar_item_properties;7970,236510
-static int ntool_bar_items;7974,236606
-tool_bar_items 7990,237083
-process_tool_bar_item 8075,239892
-#define PROP(8112,240969
-set_prop 8114,241038
-parse_tool_bar_item 8167,242453
-#undef PROP8379,248844
-init_tool_bar_items 8387,248969
-append_tool_bar_item 8401,249261
-read_char_x_menu_prompt 8443,250771
-read_char_minibuf_menu_prompt 8503,252445
-#define PUSH_C_STR(8527,253014
-follow_key 8726,258553
-active_maps 8733,258695
-typedef struct keyremap8742,259021
- Lisp_Object parent;8745,259107
- Lisp_Object map;8748,259224
- int start,8753,259446
- int start, end;8753,259446
-} keyremap;8754,259464
-access_keymap_keyremap 8764,259808
-keyremap_step 8811,261450
-test_undefined 8867,262934
-read_key_sequence 8916,264861
-read_key_sequence_vs 9826,295821
-DEFUN ("read-key-sequence", Fread_key_sequence,9885,297294
-DEFUN ("read-key-sequence", Fread_key_sequence,read-key-sequence9885,297294
-DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,9938,299982
-DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,read-key-sequence-vector9938,299982
-detect_input_pending 9950,300488
-detect_input_pending_ignore_squeezables 9959,300654
-detect_input_pending_run_timers 9967,300870
-clear_input_pending 9985,301362
-requeued_events_pending_p 9997,301732
-DEFUN ("input-pending-p", Finput_pending_p,10002,301813
-DEFUN ("input-pending-p", Finput_pending_p,input-pending-p10002,301813
-DEFUN ("recent-keys", Frecent_keys,10024,302596
-DEFUN ("recent-keys", Frecent_keys,recent-keys10024,302596
-DEFUN ("this-command-keys", Fthis_command_keys,10055,303517
-DEFUN ("this-command-keys", Fthis_command_keys,this-command-keys10055,303517
-DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,10068,303958
-DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,this-command-keys-vector10068,303958
-DEFUN ("this-single-command-keys", Fthis_single_command_keys,10080,304380
-DEFUN ("this-single-command-keys", Fthis_single_command_keys,this-single-command-keys10080,304380
-DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,10096,304955
-DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,this-single-command-raw-keys10096,304955
-DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,10109,305495
-DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,reset-this-command-lengths10109,305495
-DEFUN ("clear-this-command-keys", Fclear_this_command_keys,10136,306510
-DEFUN ("clear-this-command-keys", Fclear_this_command_keys,clear-this-command-keys10136,306510
-DEFUN ("recursion-depth", Frecursion_depth,10158,307069
-DEFUN ("recursion-depth", Frecursion_depth,recursion-depth10158,307069
-DEFUN ("open-dribble-file", Fopen_dribble_file,10169,307406
-DEFUN ("open-dribble-file", Fopen_dribble_file,open-dribble-file10169,307406
-DEFUN ("discard-input", Fdiscard_input,10203,308447
-DEFUN ("discard-input", Fdiscard_input,discard-input10203,308447
-DEFUN ("suspend-emacs", Fsuspend_emacs,10225,308949
-DEFUN ("suspend-emacs", Fsuspend_emacs,suspend-emacs10225,308949
-stuff_buffered_input 10285,311045
-set_waiting_for_input 10323,312016
-clear_waiting_for_input 10337,312390
-handle_interrupt_signal 10351,312754
-deliver_interrupt_signal 10378,313642
-static int volatile force_quit_count;10387,313932
-handle_interrupt 10401,314414
-quit_throw_to_read_char 10541,318711
-DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,10562,319288
-DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,set-input-interrupt-mode10562,319288
-DEFUN ("set-output-flow-control", Fset_output_flow_control,10609,320516
-DEFUN ("set-output-flow-control", Fset_output_flow_control,set-output-flow-control10609,320516
-DEFUN ("set-input-meta-mode", Fset_input_meta_mode,10643,321432
-DEFUN ("set-input-meta-mode", Fset_input_meta_mode,set-input-meta-mode10643,321432
-DEFUN ("set-quit-char", Fset_quit_char,10694,322706
-DEFUN ("set-quit-char", Fset_quit_char,set-quit-char10694,322706
-DEFUN ("set-input-mode", Fset_input_mode,10729,323570
-DEFUN ("set-input-mode", Fset_input_mode,set-input-mode10729,323570
-DEFUN ("current-input-mode", Fcurrent_input_mode,10750,324459
-DEFUN ("current-input-mode", Fcurrent_input_mode,current-input-mode10750,324459
-DEFUN ("posn-at-x-y", Fposn_at_x_y,10787,325837
-DEFUN ("posn-at-x-y", Fposn_at_x_y,posn-at-x-y10787,325837
-DEFUN ("posn-at-point", Fposn_at_point,10824,327060
-DEFUN ("posn-at-point", Fposn_at_point,posn-at-point10824,327060
-init_kboard 10861,328214
-allocate_kboard 10893,329284
-wipe_kboard 10909,329637
-delete_kboard 10917,329751
-init_keyboard 10942,330281
-struct event_head11021,332696
- short var;11023,332716
- short kind;11024,332729
-static const struct event_head head_table[head_table11027,332747
-syms_of_keyboard 11045,333577
-keys_of_keyboard 11841,367115
-mark_kboards 11916,370434
+volatile int interrupt_input_blocked;76,1809
+volatile bool pending_signals;80,1945
+#define KBD_BUFFER_SIZE 82,1977
+KBOARD *initial_kboard;initial_kboard84,2007
+KBOARD *current_kboard;current_kboard85,2031
+static KBOARD *all_kboards;all_kboards86,2055
+static bool single_kboard;89,2155
+#define NUM_RECENT_KEYS 91,2183
+static int recent_keys_index;94,2270
+static int total_keys;97,2358
+static Lisp_Object recent_keys;100,2444
+Lisp_Object this_command_keys;107,2778
+ptrdiff_t this_command_key_count;108,2809
+static bool this_command_key_count_reset;112,2923
+static Lisp_Object raw_keybuf;116,3075
+static int raw_keybuf_count;117,3106
+#define GROW_RAW_KEYBUF 119,3136
+static ptrdiff_t this_single_command_key_start;125,3351
+static ptrdiff_t before_command_key_count;129,3499
+static ptrdiff_t before_command_echo_length;130,3542
+sigjmp_buf return_to_command_loop;135,3678
+static Lisp_Object recover_top_level_message;138,3792
+static Lisp_Object regular_top_level_message;143,3931
+static sys_jmp_buf getcjmp;147,4032
+bool waiting_for_input;150,4096
+static bool echoing;154,4187
+static struct kboard *ok_to_echo_at_next_pause;ok_to_echo_at_next_pause159,4329
+struct kboard *echo_kboard;echo_kboard166,4633
+Lisp_Object echo_message_buffer;171,4745
+bool immediate_quit;174,4838
+int quit_char;192,5624
+EMACS_INT command_loop_level;195,5681
+Lisp_Object unread_switch_frame;204,6109
+static ptrdiff_t last_non_minibuf_size;207,6217
+uintmax_t num_input_events;210,6335
+static EMACS_INT last_auto_save;214,6429
+static ptrdiff_t last_point_position;217,6524
+Lisp_Object internal_last_event_frame;228,7029
+static Lisp_Object read_key_sequence_cmd;232,7169
+static Lisp_Object read_key_sequence_remapped;233,7211
+static FILE *dribble;dribble236,7311
+bool input_pending;239,7369
+static bool input_was_pending;287,10023
+static struct input_event kbd_buffer[kbd_buffer291,10108
+static struct input_event *kbd_fetch_ptr;kbd_fetch_ptr297,10387
+static struct input_event * volatile kbd_store_ptr;302,10602
+unsigned timers_run;320,11297
+struct timespec *input_available_clear_time;input_available_clear_time324,11409
+bool interrupt_input;328,11574
+bool interrupts_deferred;331,11672
+static struct timespec timer_idleness_start_time;335,11747
+static struct timespec timer_last_idleness_start_time;340,11917
+#define READABLE_EVENTS_DO_TIMERS_NOW 346,12047
+#define READABLE_EVENTS_FILTER_EVENTS 347,12095
+#define READABLE_EVENTS_IGNORE_SQUEEZABLES 348,12143
+kset_echo_string 392,14089
+kset_kbd_queue 397,14185
+kset_keyboard_translate_table 402,14277
+kset_last_prefix_arg 407,14400
+kset_last_repeatable_command 412,14505
+kset_local_function_key_map 417,14626
+kset_overriding_terminal_local_map 422,14745
+kset_real_last_command 427,14878
+kset_system_key_syms 432,14987
+echo_add_key 443,15250
+echo_char 527,17528
+echo_dash 541,17814
+echo_now 586,19141
+cancel_echoing 635,20615
+echo_length 648,20923
+echo_truncate 660,21254
+add_command_key 672,21583
+recursive_edit_1 697,22407
+record_auto_save 742,23849
+force_auto_save_soon 751,24017
+DEFUN ("recursive-edit", Frecursive_edit,759,24138
+DEFUN ("recursive-edit", Frecursive_edit,recursive-edit759,24138
+recursive_edit_unwind 804,25751
+any_kboard_state 817,26017
+single_kboard_state 838,26669
+not_single_kboard_state 848,26807
+struct kboard_stack858,27069
+ KBOARD *kboard;kboard860,27091
+ struct kboard_stack *next;next861,27109
+static struct kboard_stack *kboard_stack;kboard_stack864,27142
+push_kboard 867,27190
+pop_kboard 879,27379
+temporarily_switch_to_single_kboard 914,28267
+record_single_kboard_state 943,29441
+restore_kboard_configuration 952,29625
+cmd_error 970,30081
+cmd_error_internal 1024,31514
+DEFUN ("command-error-default-function", Fcommand_error_default_function,1043,32034
+DEFUN ("command-error-default-function", Fcommand_error_default_function,command-error-default-function1043,32034
+command_loop 1094,33920
+command_loop_2 1134,35139
+top_level_2 1146,35343
+top_level_1 1152,35421
+DEFUN ("top-level", Ftop_level,1164,35791
+DEFUN ("top-level", Ftop_level,top-level1164,35791
+user_error 1183,36292
+DEFUN ("exit-recursive-edit", Fexit_recursive_edit,1189,36433
+DEFUN ("exit-recursive-edit", Fexit_recursive_edit,exit-recursive-edit1189,36433
+DEFUN ("abort-recursive-edit", Fabort_recursive_edit,1201,36823
+DEFUN ("abort-recursive-edit", Fabort_recursive_edit,abort-recursive-edit1201,36823
+tracking_off 1216,37285
+DEFUN ("internal--track-mouse", Ftrack_mouse,1234,37820
+DEFUN ("internal--track-mouse", Ftrack_mouse,track-mouse1234,37820
+bool ignore_mouse_drag_p;1256,38396
+some_mouse_moved 1259,38445
+Lisp_Object last_undo_boundary;1287,39036
+command_loop_1 1294,39277
+read_menu_command 1649,50893
+adjust_point_for_property 1678,51621
+safe_run_hooks_1 1831,57343
+safe_run_hooks_error 1841,57573
+safe_run_hook_funcall 1878,58580
+safe_run_hooks 1893,59062
+int poll_suppress_count;1908,59401
+static struct atimer *poll_timer;poll_timer1915,59491
+poll_for_input_1 1919,59593
+poll_for_input 1930,59793
+start_polling 1942,60057
+input_polling_used 1979,61095
+stop_polling 1994,61394
+set_poll_suppress_count 2009,61763
+bind_polling_period 2029,62145
+make_ctrl_char 2048,62496
+show_help_echo 2113,64459
+static Lisp_Object help_form_saved_window_configs;2156,65642
+read_char_help_form_unwind 2158,65705
+#define STOP_POLLING 2166,65963
+#define RESUME_POLLING 2170,66088
+read_event_from_main_queue 2175,66233
+read_decoded_event_from_main_queue 2249,68421
+#define MAX_ENCODED_BYTES 2254,68668
+echo_keystrokes_p 2342,71560
+read_char 2376,72852
+record_menu_key 3225,98953
+help_char_p 3258,99678
+record_char 3273,99957
+save_getcjmp 3412,104239
+restore_getcjmp 3418,104330
+readable_events 3430,104701
+int stop_character EXTERNALLY_VISIBLE;3497,106441
+event_to_kboard 3500,106497
+kbd_buffer_nr_stored 3522,107146
+kbd_buffer_store_event 3534,107487
+kbd_buffer_store_event_hold 3550,108029
+kbd_buffer_unget_event 3684,111621
+#define INPUT_EVENT_POS_MAX 3698,112022
+#define INPUT_EVENT_POS_MIN 3701,112151
+position_to_Time 3706,112291
+Time_to_position 3716,112518
+gen_help_event 3738,113175
+kbd_buffer_store_help_event 3756,113615
+discard_mouse_events 3773,113980
+kbd_buffer_events_waiting 3803,114715
+clear_event 3823,115072
+kbd_buffer_get_event 3836,115412
+process_special_events 4258,127885
+swallow_events 4322,129709
+timer_start_idle 4339,130102
+timer_stop_idle 4355,130580
+timer_resume_idle 4363,130724
+struct input_event last_timer_event EXTERNALLY_VISIBLE;4372,130916
+Lisp_Object pending_funcalls;4377,131176
+decode_timer 4381,131297
+timer_check_2 4414,132250
+timer_check 4572,136821
+DEFUN ("current-idle-time", Fcurrent_idle_time,4607,137666
+DEFUN ("current-idle-time", Fcurrent_idle_time,current-idle-time4607,137666
+static Lisp_Object accent_key_syms;4625,138243
+static Lisp_Object func_key_syms;4626,138279
+static Lisp_Object mouse_syms;4627,138313
+static Lisp_Object wheel_syms;4628,138344
+static Lisp_Object drag_n_drop_syms;4629,138375
+static const int lispy_accent_codes[lispy_accent_codes4634,138520
+static const char *const lispy_accent_keys[lispy_accent_keys4741,139882
+#define FUNCTION_KEY_OFFSET 4766,140318
+const char *const lispy_function_keys[lispy_function_keys4768,140351
+static const char *const lispy_multimedia_keys[lispy_multimedia_keys4962,148905
+static const char *const lispy_kana_keys[lispy_kana_keys5026,150139
+#define FUNCTION_KEY_OFFSET 5061,151755
+static const char *const lispy_function_keys[lispy_function_keys5065,151898
+#define ISO_FUNCTION_KEY_OFFSET 5149,154433
+static const char *const iso_lispy_function_keys[iso_lispy_function_keys5151,154473
+static Lisp_Object Vlispy_mouse_stem;5172,155332
+static const char *const lispy_wheel_names[lispy_wheel_names5174,155371
+static const char *const lispy_drag_n_drop_names[lispy_drag_n_drop_names5181,155623
+static short const scroll_bar_parts[scroll_bar_parts5189,155889
+static Lisp_Object button_down_location;5210,156914
+static int last_mouse_button;5215,157069
+static int last_mouse_x;5216,157099
+static int last_mouse_y;5217,157124
+static Time button_down_time;5218,157149
+static int double_click_count;5222,157233
+make_lispy_position 5228,157394
+toolkit_menubar_in_use 5456,163957
+make_scroll_bar_position 5469,164325
+make_lispy_event 5485,164971
+make_lispy_movement 6104,183534
+make_lispy_switch_frame 6131,184265
+make_lispy_focus_in 6137,184372
+make_lispy_focus_out 6145,184498
+parse_modifiers_uncached 6163,184948
+#define SINGLE_LETTER_MOD(6185,185468
+#undef SINGLE_LETTER_MOD6212,185909
+#define MULTI_LETTER_MOD(6214,185935
+#undef MULTI_LETTER_MOD6231,186403
+apply_modifiers_uncached 6273,187577
+static const char *const modifier_names[modifier_names6319,189196
+#define NUM_MOD_NAMES 6325,189402
+static Lisp_Object modifier_symbols;6327,189452
+lispy_modifier_list 6331,189589
+#define KEY_TO_CHAR(6353,190255
+parse_modifiers 6356,190331
+DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,6399,191520
+DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,event-symbol-parse-modifiers6399,191520
+apply_modifiers 6422,192394
+reorder_modifiers 6491,194723
+modify_event_symbol 6536,196531
+DEFUN ("event-convert-list", Fevent_convert_list,6628,199247
+DEFUN ("event-convert-list", Fevent_convert_list,event-convert-list6628,199247
+parse_solitary_modifier 6695,201138
+#define SINGLE_LETTER_MOD(6701,201261
+#define MULTI_LETTER_MOD(6705,201346
+#undef SINGLE_LETTER_MOD6763,202644
+#undef MULTI_LETTER_MOD6764,202669
+lucid_event_type_list_p 6775,202892
+get_input_pending 6814,203963
+record_asynch_buffer_change 6834,204582
+gobble_input 6872,205705
+tty_read_avail_input 6967,208313
+handle_async_input 7149,214042
+process_pending_signals 7165,214362
+unblock_input_to 7177,214648
+unblock_input 7200,215280
+totally_unblock_input 7209,215448
+handle_input_available_signal 7217,215532
+deliver_input_available_signal 7226,215703
+struct user_signal_info7235,215868
+ int sig;7238,215918
+ char *name;name7241,215959
+ int npending;7244,216010
+ struct user_signal_info *next;next7246,216027
+static struct user_signal_info *user_signals user_signals7250,216093
+add_user_signal 7253,216152
+handle_user_signal 7275,216601
+deliver_user_signal 7316,217561
+find_user_signal_name 7322,217662
+store_user_signal_events 7334,217844
+static Lisp_Object menu_bar_one_keymap_changed_items;7363,218419
+static Lisp_Object menu_bar_items_vector;7368,218633
+static int menu_bar_items_index;7369,218675
+static const char *separator_names[separator_names7372,218710
+menu_separator_name_p 7393,219151
+menu_bar_items 7426,219855
+Lisp_Object item_properties;7568,224606
+menu_bar_item 7571,224648
+menu_item_eval_property_1 7647,227178
+eval_dyn 7658,227468
+menu_item_eval_property 7666,227678
+parse_menu_item 7686,228344
+static Lisp_Object tool_bar_items_vector;7965,236339
+static Lisp_Object tool_bar_item_properties;7970,236513
+static int ntool_bar_items;7974,236609
+tool_bar_items 7990,237086
+process_tool_bar_item 8075,239895
+#define PROP(8112,240972
+set_prop 8114,241041
+parse_tool_bar_item 8167,242456
+#undef PROP8379,248847
+init_tool_bar_items 8387,248972
+append_tool_bar_item 8401,249264
+read_char_x_menu_prompt 8443,250774
+read_char_minibuf_menu_prompt 8503,252448
+#define PUSH_C_STR(8527,253017
+follow_key 8726,258556
+active_maps 8733,258698
+typedef struct keyremap8742,259024
+ Lisp_Object parent;8745,259110
+ Lisp_Object map;8748,259227
+ int start,8753,259449
+ int start, end;8753,259449
+} keyremap;8754,259467
+access_keymap_keyremap 8764,259811
+keyremap_step 8811,261453
+test_undefined 8867,262937
+read_key_sequence 8916,264864
+read_key_sequence_vs 9826,295824
+DEFUN ("read-key-sequence", Fread_key_sequence,9885,297297
+DEFUN ("read-key-sequence", Fread_key_sequence,read-key-sequence9885,297297
+DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,9938,299985
+DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,read-key-sequence-vector9938,299985
+detect_input_pending 9950,300491
+detect_input_pending_ignore_squeezables 9959,300657
+detect_input_pending_run_timers 9967,300873
+clear_input_pending 9985,301365
+requeued_events_pending_p 9997,301735
+DEFUN ("input-pending-p", Finput_pending_p,10002,301816
+DEFUN ("input-pending-p", Finput_pending_p,input-pending-p10002,301816
+DEFUN ("recent-keys", Frecent_keys,10024,302599
+DEFUN ("recent-keys", Frecent_keys,recent-keys10024,302599
+DEFUN ("this-command-keys", Fthis_command_keys,10055,303520
+DEFUN ("this-command-keys", Fthis_command_keys,this-command-keys10055,303520
+DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,10068,303961
+DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,this-command-keys-vector10068,303961
+DEFUN ("this-single-command-keys", Fthis_single_command_keys,10080,304383
+DEFUN ("this-single-command-keys", Fthis_single_command_keys,this-single-command-keys10080,304383
+DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,10096,304958
+DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,this-single-command-raw-keys10096,304958
+DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,10109,305498
+DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,reset-this-command-lengths10109,305498
+DEFUN ("clear-this-command-keys", Fclear_this_command_keys,10136,306513
+DEFUN ("clear-this-command-keys", Fclear_this_command_keys,clear-this-command-keys10136,306513
+DEFUN ("recursion-depth", Frecursion_depth,10158,307072
+DEFUN ("recursion-depth", Frecursion_depth,recursion-depth10158,307072
+DEFUN ("open-dribble-file", Fopen_dribble_file,10169,307409
+DEFUN ("open-dribble-file", Fopen_dribble_file,open-dribble-file10169,307409
+DEFUN ("discard-input", Fdiscard_input,10203,308450
+DEFUN ("discard-input", Fdiscard_input,discard-input10203,308450
+DEFUN ("suspend-emacs", Fsuspend_emacs,10225,308952
+DEFUN ("suspend-emacs", Fsuspend_emacs,suspend-emacs10225,308952
+stuff_buffered_input 10285,311048
+set_waiting_for_input 10323,312019
+clear_waiting_for_input 10337,312393
+handle_interrupt_signal 10351,312757
+deliver_interrupt_signal 10378,313645
+static int volatile force_quit_count;10387,313935
+handle_interrupt 10401,314417
+quit_throw_to_read_char 10541,318714
+DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,10562,319291
+DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,set-input-interrupt-mode10562,319291
+DEFUN ("set-output-flow-control", Fset_output_flow_control,10609,320519
+DEFUN ("set-output-flow-control", Fset_output_flow_control,set-output-flow-control10609,320519
+DEFUN ("set-input-meta-mode", Fset_input_meta_mode,10643,321435
+DEFUN ("set-input-meta-mode", Fset_input_meta_mode,set-input-meta-mode10643,321435
+DEFUN ("set-quit-char", Fset_quit_char,10694,322709
+DEFUN ("set-quit-char", Fset_quit_char,set-quit-char10694,322709
+DEFUN ("set-input-mode", Fset_input_mode,10729,323573
+DEFUN ("set-input-mode", Fset_input_mode,set-input-mode10729,323573
+DEFUN ("current-input-mode", Fcurrent_input_mode,10750,324462
+DEFUN ("current-input-mode", Fcurrent_input_mode,current-input-mode10750,324462
+DEFUN ("posn-at-x-y", Fposn_at_x_y,10787,325840
+DEFUN ("posn-at-x-y", Fposn_at_x_y,posn-at-x-y10787,325840
+DEFUN ("posn-at-point", Fposn_at_point,10824,327063
+DEFUN ("posn-at-point", Fposn_at_point,posn-at-point10824,327063
+init_kboard 10861,328217
+allocate_kboard 10893,329287
+wipe_kboard 10909,329640
+delete_kboard 10917,329754
+init_keyboard 10942,330284
+struct event_head11021,332699
+ short var;11023,332719
+ short kind;11024,332732
+static const struct event_head head_table[head_table11027,332750
+syms_of_keyboard 11045,333580
+keys_of_keyboard 11841,367118
+mark_kboards 11916,370437
c-src/emacs/src/lisp.h,27827
-#define EMACS_LISP_H22,800
-#define DECLARE_GDB_SYM(47,1421
-# define DEFINE_GDB_SYMBOL_BEGIN(49,1508
-# define DEFINE_GDB_SYMBOL_END(50,1578
-# define DEFINE_GDB_SYMBOL_BEGIN(52,1625
-# define DEFINE_GDB_SYMBOL_END(53,1702
-#undef min57,1790
-#undef max58,1801
-#define max(59,1812
-#define min(60,1854
-#define ARRAYELTS(63,1936
-#define GCTYPEBITS 67,2079
-DEFINE_GDB_SYMBOL_BEGIN GCTYPEBITS66,2037
-# define NONPOINTER_BITS 78,2567
-# define NONPOINTER_BITS 80,2600
-typedef int EMACS_INT;91,3023
-typedef unsigned int EMACS_UINT;92,3046
-# define EMACS_INT_MAX 93,3079
-# define pI 94,3111
-typedef long int EMACS_INT;96,3203
-typedef unsigned long EMACS_UINT;97,3231
-# define EMACS_INT_MAX 98,3265
-# define pI 99,3298
-typedef long long int EMACS_INT;103,3477
-typedef unsigned long long int EMACS_UINT;104,3510
-# define EMACS_INT_MAX 105,3553
-# define pI 106,3587
-enum { BOOL_VECTOR_BITS_PER_CHAR 114,3804
-#define BOOL_VECTOR_BITS_PER_CHAR 115,3840
-typedef size_t bits_word;123,4165
-# define BITS_WORD_MAX 124,4191
-enum { BITS_PER_BITS_WORD 125,4223
-typedef unsigned char bits_word;127,4290
-# define BITS_WORD_MAX 128,4323
-enum { BITS_PER_BITS_WORD 129,4386
- BITS_PER_CHAR 136,4570
- BITS_PER_SHORT 137,4605
- BITS_PER_LONG 138,4657
- BITS_PER_EMACS_INT 139,4712
-typedef intmax_t printmax_t;148,5089
-typedef uintmax_t uprintmax_t;149,5118
-# define pMd 150,5149
-# define pMu 151,5170
-typedef EMACS_INT printmax_t;153,5197
-typedef EMACS_UINT uprintmax_t;154,5227
-# define pMd 155,5259
-# define pMu 156,5278
-# define pD 165,5664
-# define pD 167,5709
-# define pD 169,5756
-# define pD 171,5779
-# define eassert(200,7062
-# define eassume(201,7140
-# define eassert(208,7319
-# define eassume(212,7450
-enum Lisp_Bits239,8519
-#define GCALIGNMENT 243,8647
- VALBITS 246,8742
- INTTYPEBITS 249,8838
- FIXNUM_BITS 252,8945
-#define VAL_MAX 263,9327
-#define USE_LSB_TAG 271,9777
-DEFINE_GDB_SYMBOL_BEGIN USE_LSB_TAG270,9733
-# define alignas(281,10077
-# define GCALIGNED 288,10227
-# define GCALIGNED 290,10292
-# define lisp_h_XLI(327,11642
-# define lisp_h_XIL(328,11673
-# define lisp_h_XLI(330,11724
-# define lisp_h_XIL(331,11751
-#define lisp_h_CHECK_LIST_CONS(333,11785
-#define lisp_h_CHECK_NUMBER(334,11856
-#define lisp_h_CHECK_SYMBOL(335,11927
-#define lisp_h_CHECK_TYPE(336,11996
-#define lisp_h_CONSP(338,12107
-#define lisp_h_EQ(339,12156
-#define lisp_h_FLOATP(340,12201
-#define lisp_h_INTEGERP(341,12252
-#define lisp_h_MARKERP(342,12333
-#define lisp_h_MISCP(343,12408
-#define lisp_h_NILP(344,12457
-#define lisp_h_SET_SYMBOL_VAL(345,12493
-#define lisp_h_SYMBOL_CONSTANT_P(347,12607
-#define lisp_h_SYMBOL_VAL(348,12671
-#define lisp_h_SYMBOLP(350,12772
-#define lisp_h_VECTORLIKEP(351,12825
-#define lisp_h_XCAR(352,12886
-#define lisp_h_XCDR(353,12924
-#define lisp_h_XCONS(354,12964
-#define lisp_h_XHASH(356,13059
-#define lisp_h_XPNTR(357,13093
-# define lisp_h_check_cons_list(360,13221
-# define lisp_h_make_number(363,13289
-# define lisp_h_XFASTINT(365,13392
-# define lisp_h_XINT(366,13429
-# define lisp_h_XSYMBOL(367,13478
-# define lisp_h_XTYPE(371,13631
-# define lisp_h_XUNTAG(372,13696
-# define XLI(381,14086
-# define XIL(382,14117
-# define CHECK_LIST_CONS(383,14148
-# define CHECK_NUMBER(384,14209
-# define CHECK_SYMBOL(385,14258
-# define CHECK_TYPE(386,14307
-# define CONSP(387,14382
-# define EQ(388,14417
-# define FLOATP(389,14452
-# define INTEGERP(390,14489
-# define MARKERP(391,14530
-# define MISCP(392,14569
-# define NILP(393,14604
-# define SET_SYMBOL_VAL(394,14637
-# define SYMBOL_CONSTANT_P(395,14700
-# define SYMBOL_VAL(396,14763
-# define SYMBOLP(397,14812
-# define VECTORLIKEP(398,14851
-# define XCAR(399,14898
-# define XCDR(400,14931
-# define XCONS(401,14964
-# define XHASH(402,14999
-# define XPNTR(403,15034
-# define check_cons_list(405,15097
-# define make_number(408,15176
-# define XFASTINT(409,15224
-# define XINT(410,15266
-# define XSYMBOL(411,15300
-# define XTYPE(412,15340
-# define XUNTAG(413,15376
-#define LISP_MACRO_DEFUN(421,15672
-#define LISP_MACRO_DEFUN_VOID(425,15845
-#define INTMASK 437,16289
-#define case_Lisp_Int 438,16342
-#define ENUM_BF(445,16681
-#define ENUM_BF(447,16722
-enum Lisp_Type451,16763
- Lisp_Symbol 454,16851
- Lisp_Misc 458,16993
- Lisp_Int0 461,17067
- Lisp_Int1 462,17086
- Lisp_String 466,17264
- Lisp_Vectorlike 472,17543
- Lisp_Cons 475,17632
- Lisp_Float 477,17670
-enum Lisp_Misc_Type485,18016
- Lisp_Misc_Free 487,18040
- Lisp_Misc_Marker,488,18069
- Lisp_Misc_Overlay,489,18091
- Lisp_Misc_Save_Value,490,18114
- Lisp_Misc_Finalizer,491,18140
- Lisp_Misc_Float,494,18275
- Lisp_Misc_Limit496,18359
-enum Lisp_Fwd_Type502,18543
- Lisp_Fwd_Int,504,18566
- Lisp_Fwd_Bool,505,18619
- Lisp_Fwd_Obj,506,18670
- Lisp_Fwd_Buffer_Obj,507,18729
- Lisp_Fwd_Kboard_Obj 508,18800
-typedef struct { EMACS_INT i;567,21781
-typedef struct { EMACS_INT i; } Lisp_Object;567,21781
-#define LISP_INITIALLY(569,21827
-#undef CHECK_LISP_OBJECT_TYPE571,21858
-enum CHECK_LISP_OBJECT_TYPE 572,21888
-enum CHECK_LISP_OBJECT_TYPE { CHECK_LISP_OBJECT_TYPE 572,21888
-typedef EMACS_INT Lisp_Object;577,22064
-#define LISP_INITIALLY(578,22095
-enum CHECK_LISP_OBJECT_TYPE 579,22125
-enum CHECK_LISP_OBJECT_TYPE { CHECK_LISP_OBJECT_TYPE 579,22125
-#define LISP_INITIALLY_ZERO 582,22226
-enum symbol_interned639,24199
- SYMBOL_UNINTERNED 641,24222
- SYMBOL_INTERNED 642,24247
- SYMBOL_INTERNED_IN_INITIAL_OBARRAY 643,24270
-enum symbol_redirect646,24315
- SYMBOL_PLAINVAL 648,24338
- SYMBOL_VARALIAS 649,24362
- SYMBOL_LOCALIZED 650,24386
- SYMBOL_FORWARDED 651,24410
-struct Lisp_Symbol654,24437
- bool_bf gcmarkbit 656,24458
- ENUM_BF (symbol_redirect) redirect 663,24793
- unsigned constant 668,25011
- unsigned interned 672,25131
- bool_bf declared_special 676,25293
- bool_bf pinned 679,25394
- Lisp_Object name;682,25463
- Lisp_Object value;687,25631
- struct Lisp_Symbol *alias;alias688,25654
- struct Lisp_Buffer_Local_Value *blv;blv689,25685
- union Lisp_Fwd *fwd;fwd690,25726
- } val;691,25751
- Lisp_Object function;694,25823
- Lisp_Object plist;697,25885
- struct Lisp_Symbol *next;next700,25974
-#define EXFUN(707,26252
-#define DEFUN_ARGS_MANY 712,26446
-#define DEFUN_ARGS_UNEVALLED 713,26498
-#define DEFUN_ARGS_0 714,26541
-#define DEFUN_ARGS_1 715,26569
-#define DEFUN_ARGS_2 716,26604
-#define DEFUN_ARGS_3 717,26652
-#define DEFUN_ARGS_4 718,26713
-#define DEFUN_ARGS_5 719,26787
-#define DEFUN_ARGS_6 721,26880
-#define DEFUN_ARGS_7 723,26986
-#define DEFUN_ARGS_8 725,27105
-#define TAG_PTR(729,27296
-#define TAG_SYMOFFSET(734,27543
-#define XLI_BUILTIN_LISPSYM(741,27842
-#define DEFINE_LISP_SYMBOL(746,28101
-# define DEFINE_NON_NIL_Q_SYMBOL_MACROS 755,28572
-LISP_MACRO_DEFUN 762,28777
-# define ARRAY_MARK_FLAG 768,29024
-# define PSEUDOVECTOR_FLAG 774,29267
-enum pvec_type780,29568
- PVEC_NORMAL_VECTOR,782,29585
- PVEC_FREE,783,29607
- PVEC_PROCESS,784,29620
- PVEC_FRAME,785,29636
- PVEC_WINDOW,786,29650
- PVEC_BOOL_VECTOR,787,29665
- PVEC_BUFFER,788,29685
- PVEC_HASH_TABLE,789,29700
- PVEC_TERMINAL,790,29719
- PVEC_WINDOW_CONFIGURATION,791,29736
- PVEC_SUBR,792,29765
- PVEC_OTHER,793,29778
- PVEC_COMPILED,795,29856
- PVEC_CHAR_TABLE,796,29873
- PVEC_SUB_CHAR_TABLE,797,29892
- PVEC_FONT 798,29915
-enum More_Lisp_Bits801,29991
- PSEUDOVECTOR_SIZE_BITS 808,30382
- PSEUDOVECTOR_SIZE_MASK 809,30415
- PSEUDOVECTOR_REST_BITS 813,30625
- PSEUDOVECTOR_REST_MASK 814,30658
- PSEUDOVECTOR_AREA_BITS 818,30823
- PVEC_TYPE_MASK 819,30901
-# define VALMASK 829,31302
-DEFINE_GDB_SYMBOL_BEGIN VALMASK828,31257
-#define MOST_POSITIVE_FIXNUM 834,31532
-#define MOST_NEGATIVE_FIXNUM 835,31592
-XINT 874,32684
-XFASTINT 889,33035
-XSYMBOL 899,33263
-XTYPE 910,33481
-XUNTAG 918,33661
-LISP_MACRO_DEFUN 927,33857
-LISP_MACRO_DEFUN 940,34242
-#define FIXNUM_OVERFLOW_P(958,34855
-LISP_MACRO_DEFUN FIXNUM_OVERFLOW_P952,34632
-LISP_MACRO_DEFUN 970,35171
-XSTRING 980,35391
-#define SYMBOL_INDEX(988,35575
-XFLOAT 991,35636
-XPROCESS 1000,35778
-XWINDOW 1007,35895
-XTERMINAL 1014,36012
-XSUBR 1021,36134
-XBUFFER 1028,36245
-XCHAR_TABLE 1035,36369
-XSUB_CHAR_TABLE 1042,36506
-XBOOL_VECTOR 1049,36648
-make_lisp_ptr 1058,36827
-make_lisp_symbol 1066,37013
-builtin_lisp_symbol 1074,37197
-#define XSETINT(1079,37279
-#define XSETFASTINT(1080,37325
-#define XSETCONS(1081,37375
-#define XSETVECTOR(1082,37435
-#define XSETSTRING(1083,37503
-#define XSETSYMBOL(1084,37567
-#define XSETFLOAT(1085,37621
-#define XSETMISC(1086,37683
-#define XSETPVECTYPE(1090,37772
-#define XSETPVECTYPESIZE(1092,37888
-#define XSETPSEUDOVECTOR(1099,38185
-#define XSETTYPED_PSEUDOVECTOR(1105,38369
-#define XSETWINDOW_CONFIGURATION(1110,38579
-#define XSETPROCESS(1112,38675
-#define XSETWINDOW(1113,38741
-#define XSETTERMINAL(1114,38805
-#define XSETSUBR(1115,38873
-#define XSETCOMPILED(1116,38933
-#define XSETBUFFER(1117,39001
-#define XSETCHAR_TABLE(1118,39065
-#define XSETBOOL_VECTOR(1119,39137
-#define XSETSUB_CHAR_TABLE(1120,39211
-XINTPTR 1128,39581
-make_pointer_integer 1134,39661
-LISP_MACRO_DEFUN_VOID 1143,39826
-typedef struct interval *INTERVAL;INTERVAL1149,39987
- Lisp_Object cdr;1159,40162
- struct Lisp_Cons *chain;chain1162,40236
-xcar_addr 1174,40760
-xcdr_addr 1179,40837
-LISP_MACRO_DEFUN 1185,40931
-XSETCDR 1198,41307
-CAR 1205,41457
-CDR 1212,41591
-CAR_SAFE 1221,41791
-CDR_SAFE 1226,41877
-STRING_MULTIBYTE 1243,42250
-#define STRING_BYTES_BOUND 1261,43057
-#define STRING_SET_UNIBYTE(1265,43201
-#define STRING_SET_MULTIBYTE(1275,43516
-SDATA 1286,43830
-SSDATA 1291,43908
-SREF 1297,44037
-SSET 1302,44128
-SCHARS 1307,44242
-STRING_BYTES 1316,44415
-SBYTES 1326,44595
-STRING_SET_CHARS 1331,44681
-struct vectorlike_header1343,45232
- ptrdiff_t size;1364,46383
-struct Lisp_Vector1369,46482
- struct vectorlike_header header;1371,46505
- Lisp_Object contents[contents1372,46542
- ALIGNOF_STRUCT_LISP_VECTOR1378,46681
-struct Lisp_Bool_Vector1384,46864
- struct vectorlike_header header;1388,47012
- EMACS_INT size;1390,47086
- bits_word data[data1395,47319
-bool_vector_size 1399,47385
-bool_vector_data 1407,47523
-bool_vector_uchar_data 1413,47617
-bool_vector_words 1421,47803
-bool_vector_bytes 1428,47998
-bool_vector_bitref 1437,48238
-bool_vector_ref 1445,48478
-bool_vector_set 1453,48618
- header_size 1471,49047
- bool_header_size 1472,49106
- word_size 1473,49171
-AREF 1479,49284
-aref_addr 1485,49391
-ASIZE 1491,49501
-ASET 1497,49583
-gc_aset 1504,49742
-enum { NIL_IS_ZERO 1515,50269
-memclear 1520,50464
-#define VECSIZE(1531,50762
-#define PSEUDOVECSIZE(1538,51047
-#define UNSIGNED_CMP(1546,51480
-#define ASCII_CHAR_P(1552,51734
-enum CHARTAB_SIZE_BITS1565,52489
- CHARTAB_SIZE_BITS_0 1567,52516
- CHARTAB_SIZE_BITS_1 1568,52545
- CHARTAB_SIZE_BITS_2 1569,52574
- CHARTAB_SIZE_BITS_3 1570,52603
-struct Lisp_Char_Table1575,52672
- struct vectorlike_header header;1581,52928
- Lisp_Object defalt;1585,53078
- Lisp_Object parent;1590,53280
- Lisp_Object purpose;1594,53398
- Lisp_Object ascii;1598,53564
- Lisp_Object contents[contents1600,53588
- Lisp_Object extras[extras1603,53699
-struct Lisp_Sub_Char_Table1606,53752
- struct vectorlike_header header;1610,53918
- int depth;1618,54341
- int min_char;1621,54417
- Lisp_Object contents[contents1624,54492
-CHAR_TABLE_REF_ASCII 1628,54566
-CHAR_TABLE_REF 1648,55113
-CHAR_TABLE_SET 1658,55402
-struct Lisp_Subr1670,55786
- struct vectorlike_header header;1672,55807
- Lisp_Object (*a0)a01674,55856
- Lisp_Object (*a1)a11675,55888
- Lisp_Object (*a2)a21676,55927
- Lisp_Object (*a3)a31677,55979
- Lisp_Object (*a4)a41678,56044
- Lisp_Object (*a5)a51679,56122
- Lisp_Object (*a6)a61680,56213
- Lisp_Object (*a7)a71681,56317
- Lisp_Object (*a8)a81682,56434
- Lisp_Object (*aUNEVALLED)aUNEVALLED1683,56564
- Lisp_Object (*aMANY)aMANY1684,56616
- } function;1685,56671
- short min_args,1686,56687
- short min_args, max_args;1686,56687
- const char *symbol_name;symbol_name1687,56717
- const char *intspec;intspec1688,56746
- const char *doc;doc1689,56771
-enum char_table_specials1692,56798
- CHAR_TABLE_STANDARD_SLOTS 1697,56993
- SUB_CHAR_TABLE_OFFSET 1701,57214
-CHAR_TABLE_EXTRA_SLOTS 1707,57377
-LISP_MACRO_DEFUN 1723,57921
-SYMBOL_BLV 1732,58181
-SYMBOL_FWD 1738,58316
-LISP_MACRO_DEFUN_VOID 1744,58428
-SET_SYMBOL_BLV 1754,58691
-SET_SYMBOL_FWD 1760,58850
-SYMBOL_NAME 1767,59001
-SYMBOL_INTERNED_P 1775,59130
-SYMBOL_INTERNED_IN_INITIAL_OBARRAY_P 1783,59299
-#define DEFSYM(1796,59809
-LISP_MACRO_DEFUN DEFSYM1792,59630
-struct hash_table_test1805,60062
- Lisp_Object name;1808,60139
- Lisp_Object user_hash_function;1811,60206
- Lisp_Object user_cmp_function;1814,60297
- bool (*cmpfn)cmpfn1817,60372
- EMACS_UINT (*hashfn)hashfn1820,60486
-struct Lisp_Hash_Table1823,60555
- struct vectorlike_header header;1826,60649
- Lisp_Object weak;1830,60783
- Lisp_Object rehash_size;1835,61007
- Lisp_Object rehash_threshold;1839,61129
- Lisp_Object hash;1843,61260
- Lisp_Object next;1848,61490
- Lisp_Object next_free;1851,61560
- Lisp_Object index;1856,61771
- ptrdiff_t count;1863,62041
- Lisp_Object key_and_value;1868,62240
- struct hash_table_test test;1871,62314
- struct Lisp_Hash_Table *next_weak;next_weak1875,62457
-XHASH_TABLE 1880,62531
-#define XSET_HASH_TABLE(1885,62602
-HASH_TABLE_P 1889,62703
-HASH_KEY 1896,62860
-HASH_VALUE 1903,63040
-HASH_NEXT 1911,63254
-HASH_HASH 1918,63431
-HASH_INDEX 1926,63677
-HASH_TABLE_SIZE 1933,63826
-enum DEFAULT_HASH_SIZE 1940,63956
-enum DEFAULT_HASH_SIZE { DEFAULT_HASH_SIZE 1940,63956
-static double const DEFAULT_REHASH_THRESHOLD 1946,64176
-static double const DEFAULT_REHASH_SIZE 1950,64299
-sxhash_combine 1956,64465
-SXHASH_REDUCE 1964,64648
-struct Lisp_Misc_Any 1971,64806
- ENUM_BF (Lisp_Misc_Type) type 1973,64866
- bool_bf gcmarkbit 1974,64927
- unsigned spacer 1975,64952
-struct Lisp_Marker1978,64980
- ENUM_BF (Lisp_Misc_Type) type 1980,65001
- bool_bf gcmarkbit 1981,65065
- unsigned spacer 1982,65090
- bool_bf need_adjustment 1986,65282
- bool_bf insertion_type 1989,65423
- struct buffer *buffer;buffer2000,66016
- struct Lisp_Marker *next;next2009,66367
- ptrdiff_t charpos;2011,66455
- ptrdiff_t bytepos;2016,66713
-struct Lisp_Overlay2021,66841
- ENUM_BF (Lisp_Misc_Type) type 2034,67349
- bool_bf gcmarkbit 2035,67415
- unsigned spacer 2036,67442
- struct Lisp_Overlay *next;next2037,67468
- Lisp_Object start;2038,67499
- Lisp_Object end;2039,67522
- Lisp_Object plist;2040,67543
- SAVE_UNUSED,2047,67644
- SAVE_INTEGER,2048,67661
- SAVE_FUNCPOINTER,2049,67679
- SAVE_POINTER,2050,67701
- SAVE_OBJECT2051,67719
-enum { SAVE_SLOT_BITS 2055,67804
-enum { SAVE_VALUE_SLOTS 2058,67901
-enum { SAVE_TYPE_BITS 2062,68009
-enum Lisp_Save_Type2064,68075
- SAVE_TYPE_INT_INT 2066,68099
- SAVE_TYPE_INT_INT_INT2067,68172
- SAVE_TYPE_OBJ_OBJ 2069,68262
- SAVE_TYPE_OBJ_OBJ_OBJ 2070,68333
- SAVE_TYPE_OBJ_OBJ_OBJ_OBJ2071,68414
- SAVE_TYPE_PTR_INT 2073,68509
- SAVE_TYPE_PTR_OBJ 2074,68582
- SAVE_TYPE_PTR_PTR 2075,68654
- SAVE_TYPE_FUNCPTR_PTR_OBJ2076,68727
- SAVE_TYPE_MEMORY 2080,68885
-typedef void (*voidfuncptr)voidfuncptr2108,69839
-struct Lisp_Save_Value2110,69876
- ENUM_BF (Lisp_Misc_Type) type 2112,69903
- bool_bf gcmarkbit 2113,69972
- unsigned spacer : 32 - (16 + 1 + SAVE_TYPE_BITS)2114,69999
- ENUM_BF (Lisp_Save_Type) save_type : SAVE_TYPE_BITS;2123,70489
- void *pointer;pointer2125,70558
- voidfuncptr funcpointer;2126,70579
- ptrdiff_t integer;2127,70610
- Lisp_Object object;2128,70635
- } data[data2129,70661
-save_type 2134,70755
-XSAVE_POINTER 2143,70985
-set_save_pointer 2149,71147
-XSAVE_FUNCPOINTER 2155,71329
-XSAVE_INTEGER 2164,71549
-set_save_integer 2170,71711
-XSAVE_OBJECT 2179,71932
-struct Lisp_Finalizer2186,72109
- struct Lisp_Misc_Any base;2188,72135
- struct Lisp_Finalizer *prev;prev2191,72223
- struct Lisp_Finalizer *next;next2192,72256
- Lisp_Object function;2197,72493
-struct Lisp_Free2201,72584
- ENUM_BF (Lisp_Misc_Type) type 2203,72605
- bool_bf gcmarkbit 2204,72668
- unsigned spacer 2205,72695
- union Lisp_Misc *chain;chain2206,72721
-union Lisp_Misc2212,72885
- struct Lisp_Misc_Any u_any;2214,72905
- struct Lisp_Free u_free;2215,72976
- struct Lisp_Marker u_marker;2216,73005
- struct Lisp_Overlay u_overlay;2217,73038
- struct Lisp_Save_Value u_save_value;2218,73073
- struct Lisp_Finalizer u_finalizer;2219,73114
-XMISC 2223,73184
-XMISCANY 2229,73273
-XMISCTYPE 2236,73382
-XMARKER 2242,73470
-XOVERLAY 2249,73585
-XSAVE_VALUE 2256,73706
-XFINALIZER 2263,73835
-struct Lisp_Intfwd2274,74120
- enum Lisp_Fwd_Type type;2276,74143
- EMACS_INT *intvar;intvar2277,74193
-struct Lisp_Boolfwd2284,74414
- enum Lisp_Fwd_Type type;2286,74438
- bool *boolvar;boolvar2287,74489
-struct Lisp_Objfwd2294,74705
- enum Lisp_Fwd_Type type;2296,74728
- Lisp_Object *objvar;objvar2297,74778
-struct Lisp_Buffer_Objfwd2302,74937
- enum Lisp_Fwd_Type type;2304,74967
- int offset;2305,75024
- Lisp_Object predicate;2307,75116
-struct Lisp_Buffer_Local_Value2334,76473
- bool_bf local_if_set 2338,76618
- bool_bf frame_local 2341,76800
- bool_bf found 2344,76942
- union Lisp_Fwd *fwd;fwd2346,77044
- Lisp_Object where;2348,77187
- Lisp_Object defcell;2351,77313
- Lisp_Object valcell;2357,77617
-struct Lisp_Kboard_Objfwd2362,77732
- enum Lisp_Fwd_Type type;2364,77762
- int offset;2365,77819
-union Lisp_Fwd2368,77841
- struct Lisp_Intfwd u_intfwd;2370,77860
- struct Lisp_Boolfwd u_boolfwd;2371,77893
- struct Lisp_Objfwd u_objfwd;2372,77928
- struct Lisp_Buffer_Objfwd u_buffer_objfwd;2373,77961
- struct Lisp_Kboard_Objfwd u_kboard_objfwd;2374,78008
-XFWDTYPE 2378,78087
-XBUFFER_OBJFWD 2384,78183
-struct Lisp_Float2391,78319
- double data;2395,78357
- struct Lisp_Float *chain;chain2396,78376
- } u;2397,78408
-XFLOAT_DATA 2401,78437
- IEEE_FLOATING_POINT2415,78946
-#define _UCHAR_T2423,79269
-typedef unsigned char UCHAR;2424,79286
-enum Lisp_Compiled2429,79369
- COMPILED_ARGLIST 2431,79392
- COMPILED_BYTECODE 2432,79418
- COMPILED_CONSTANTS 2433,79445
- COMPILED_STACK_DEPTH 2434,79473
- COMPILED_DOC_STRING 2435,79503
- COMPILED_INTERACTIVE 2436,79532
-enum char_bits2443,79834
- CHAR_ALT 2445,79853
- CHAR_SUPER 2446,79879
- CHAR_HYPER 2447,79907
- CHAR_SHIFT 2448,79935
- CHAR_CTL 2449,79963
- CHAR_META 2450,79989
- CHAR_MODIFIER_MASK 2452,80017
- CHARACTERBITS 2457,80212
-LISP_MACRO_DEFUN 2462,80270
-NATNUMP 2470,80412
-RANGED_INTEGERP 2476,80493
-#define TYPE_RANGED_INTEGERP(2481,80615
-LISP_MACRO_DEFUN 2486,80800
-VECTORP 2500,81273
-OVERLAYP 2505,81376
-SAVE_VALUEP 2510,81475
-FINALIZERP 2516,81581
-AUTOLOADP 2522,81685
-BUFFER_OBJFWDP 2528,81776
-PSEUDOVECTOR_TYPEP 2534,81874
-PSEUDOVECTORP 2542,82127
-WINDOW_CONFIGURATIONP 2558,82479
-PROCESSP 2564,82589
-WINDOWP 2570,82673
-TERMINALP 2576,82755
-SUBRP 2582,82841
-COMPILEDP 2588,82919
-BUFFERP 2594,83005
-CHAR_TABLE_P 2600,83087
-SUB_CHAR_TABLE_P 2606,83178
-BOOL_VECTOR_P 2612,83277
-FRAMEP 2618,83370
-IMAGEP 2625,83487
-ARRAYP 2632,83592
-CHECK_LIST 2638,83711
-LISP_MACRO_DEFUN_VOID 2643,83792
-CHECK_STRING_CAR 2653,84089
-CHECK_CONS 2658,84193
-CHECK_VECTOR 2663,84273
-CHECK_BOOL_VECTOR 2668,84359
-CHECK_VECTOR_OR_STRING 2674,84536
-CHECK_ARRAY 2683,84710
-CHECK_BUFFER 2688,84818
-CHECK_WINDOW 2693,84904
-CHECK_PROCESS 2699,85010
-CHECK_NATNUM 2705,85106
-#define CHECK_RANGED_INTEGER(2710,85183
-#define CHECK_TYPE_RANGED_INTEGER(2721,85566
-#define CHECK_NUMBER_COERCE_MARKER(2729,85836
-XFLOATINT 2738,86089
-CHECK_NUMBER_OR_FLOAT 2744,86160
-#define CHECK_NUMBER_OR_FLOAT_COERCE_MARKER(2749,86259
-CHECK_NUMBER_CAR 2760,86669
-CHECK_NUMBER_CDR 2768,86791
-#define DEFUN(2803,88386
-#define DEFUN(2812,88854
-FUNCTIONP 2822,89209
-enum maxargs2831,89404
- MANY 2833,89421
- UNEVALLED 2834,89436
-#define CALLMANY(2838,89539
-#define CALLN(2844,89892
-#define DEFVAR_LISP(2869,91097
-#define DEFVAR_LISP_NOPRO(2874,91269
-#define DEFVAR_BOOL(2879,91451
-#define DEFVAR_INT(2884,91624
-#define DEFVAR_BUFFER_DEFAULTS(2890,91795
-#define DEFVAR_KBOARD(2896,91999
-typedef jmp_buf sys_jmp_buf;2906,92323
-# define sys_setjmp(2907,92352
-# define sys_longjmp(2908,92387
-typedef sigjmp_buf sys_jmp_buf;2910,92459
-# define sys_setjmp(2911,92491
-# define sys_longjmp(2912,92531
-typedef jmp_buf sys_jmp_buf;2916,92690
-# define sys_setjmp(2917,92719
-# define sys_longjmp(2918,92753
-enum specbind_tag 2943,93805
- SPECPDL_UNWIND,2944,93825
- SPECPDL_UNWIND_PTR,2945,93894
- SPECPDL_UNWIND_INT,2946,93945
- SPECPDL_UNWIND_VOID,2947,93993
- SPECPDL_BACKTRACE,2948,94047
- SPECPDL_LET,2949,94105
- SPECPDL_LET_LOCAL,2951,94235
- SPECPDL_LET_DEFAULT 2952,94292
-union specbinding2955,94364
- ENUM_BF (specbind_tag) kind : CHAR_BIT;2957,94386
- ENUM_BF (specbind_tag) kind : CHAR_BIT;2959,94443
- void (*func)func2960,94489
- Lisp_Object arg;2961,94523
- } unwind;2962,94546
- ENUM_BF (specbind_tag) kind : CHAR_BIT;2964,94573
- void (*func)func2965,94619
- void *arg;arg2966,94648
- } unwind_ptr;2967,94665
- ENUM_BF (specbind_tag) kind : CHAR_BIT;2969,94696
- void (*func)func2970,94742
- int arg;2971,94768
- } unwind_int;2972,94783
- ENUM_BF (specbind_tag) kind : CHAR_BIT;2974,94814
- void (*func)func2975,94860
- } unwind_void;2976,94887
- ENUM_BF (specbind_tag) kind : CHAR_BIT;2978,94919
- Lisp_Object symbol,2980,95026
- Lisp_Object symbol, old_value,2980,95026
- Lisp_Object symbol, old_value, where;2980,95026
- } let;2981,95070
- ENUM_BF (specbind_tag) kind : CHAR_BIT;2983,95094
- bool_bf debug_on_exit 2984,95140
- Lisp_Object function;2985,95173
- Lisp_Object *args;args2986,95201
- ptrdiff_t nargs;2987,95226
- } bt;2988,95249
-SPECPDL_INDEX 2996,95388
-enum handlertype 3021,96410
-enum handlertype { CATCHER,3021,96410
-enum handlertype { CATCHER, CONDITION_CASE 3021,96410
-struct handler3023,96457
- enum handlertype type;3025,96474
- Lisp_Object tag_or_ch;3026,96499
- Lisp_Object val;3027,96524
- struct handler *next;next3028,96543
- struct handler *nextfree;nextfree3029,96567
- Lisp_Object *bytecode_top;bytecode_top3036,96925
- int bytecode_dest;3037,96954
- struct gcpro *gcpro;gcpro3042,97191
- sys_jmp_buf jmp;3044,97221
- EMACS_INT lisp_eval_depth;3045,97240
- ptrdiff_t pdlcount;3046,97269
- int poll_suppress_count;3047,97291
- int interrupt_input_blocked;3048,97318
- struct byte_stack *byte_stack;byte_stack3049,97349
-#define PUSH_HANDLER(3053,97446
-#define QUIT 3101,99223
-#define QUITP 3112,99473
-struct gcpro3132,100316
- struct gcpro *next;next3134,100331
- volatile Lisp_Object *var;var3137,100400
- ptrdiff_t nvars;3140,100482
- const char *name;name3144,100567
- int lineno;3147,100623
- int idx;3150,100684
- int level;3153,100720
-#define GC_USE_GCPROS_AS_BEFORE 3171,101297
-#define GC_MAKE_GCPROS_NOOPS 3172,101332
-#define GC_MARK_STACK_CHECK_GCPROS 3173,101364
-#define GC_USE_GCPROS_CHECK_ZOMBIES 3174,101401
-#define GC_MARK_STACK 3177,101462
-#define BYTE_MARK_STACK 3181,101562
-#define GCPRO1(3190,101833
-#define GCPRO2(3191,101873
-#define GCPRO3(3192,101939
-#define GCPRO4(3194,102034
-#define GCPRO5(3196,102154
-#define GCPRO6(3198,102299
-#define GCPRO7(3201,102474
-#define UNGCPRO 3202,102553
-#define GCPRO1(3208,102653
-#define GCPRO2(3212,102775
-#define GCPRO3(3217,102967
-#define GCPRO4(3223,103229
-#define GCPRO5(3230,103560
-#define GCPRO6(3238,103961
-#define GCPRO7(3247,104431
-#define UNGCPRO 3257,104971
-#define GCPRO1(3263,105065
-#define GCPRO2(3269,105299
-#define GCPRO3(3278,105717
-#define GCPRO4(3289,106274
-#define GCPRO5(3302,106972
-#define GCPRO6(3317,107812
-#define GCPRO7(3334,108793
-#define UNGCPRO 3353,109916
-#define RETURN_UNGCPRO(3363,110183
-vcopy 3384,110657
-set_hash_key_slot 3393,110932
-set_hash_value_slot 3399,111071
-set_symbol_function 3408,111306
-set_symbol_plist 3414,111421
-set_symbol_next 3420,111524
-blv_found 3428,111697
-set_overlay_plist 3437,111880
-string_intervals 3445,112031
-set_string_intervals 3453,112153
-set_char_table_defalt 3462,112355
-set_char_table_purpose 3467,112467
-set_char_table_extras 3475,112636
-set_char_table_contents 3482,112845
-set_sub_char_table_contents 3489,113040
-enum Arith_Comparison 3497,113303
- ARITH_EQUAL,3498,113327
- ARITH_NOTEQUAL,3499,113342
- ARITH_LESS,3500,113360
- ARITH_GRTR,3501,113374
- ARITH_LESS_OR_EQUAL,3502,113388
- ARITH_GRTR_OR_EQUAL3503,113411
-#define INTEGER_TO_CONS(3511,113762
-#define CONS_TO_INTEGER(3529,114625
-enum { NEXT_ALMOST_PRIME_LIMIT 3573,116329
-extern EMACS_INT next_almost_prime 3574,116368
-enum constype 3739,123820
-enum constype {CONSTYPE_HEAP,CONSTYPE_HEAP3739,123820
-enum constype {CONSTYPE_HEAP, CONSTYPE_PURE}CONSTYPE_PURE3739,123820
-list2i 3745,124010
-list3i 3751,124119
-list4i 3757,124258
-extern Lisp_Object make_formatted_string 3767,124634
-build_pure_c_string 3792,125662
-build_string 3801,125867
-make_uninit_vector 3820,126438
-make_uninit_sub_char_table 3833,126657
-#define ALLOCATE_PSEUDOVECTOR(3850,127201
-#define ALLOCATE_ZEROED_PSEUDOVECTOR(3858,127537
-INLINE void 3890,128943
-extern void *r_alloc r_alloc3895,129064
-#define FLOAT_TO_STRING_BUFSIZE 3927,130527
-intern 3968,132134
-intern_c_string 3974,132222
-extern _Noreturn void error 4034,135601
-fast_string_match_ignore_case 4136,140089
-INLINE void fixup_locale 4241,143854
-INLINE void synchronize_system_messages_locale 4242,143889
-INLINE void synchronize_system_time_locale 4243,143946
-#define IS_DAEMON 4257,144419
-#define DAEMON_RUNNING 4258,144459
-#define IS_DAEMON 4261,144558
-#define DAEMON_RUNNING 4262,144603
-# define WAIT_READING_MAX 4281,145422
-# define WAIT_READING_MAX 4283,145494
-extern _Noreturn void emacs_abort 4374,148386
-egetenv 4532,152809
-#define eabs(4545,153305
-#define make_fixnum_or_float(4550,153438
-enum MAX_ALLOCA 4556,153689
-enum MAX_ALLOCA { MAX_ALLOCA 4556,153689
-extern void *record_xmalloc record_xmalloc4558,153734
-#define USE_SAFE_ALLOCA 4560,153800
-#define AVAIL_ALLOCA(4564,153933
-#define SAFE_ALLOCA(4568,154044
-#define SAFE_NALLOCA(4576,154385
-#define SAFE_ALLOCA_STRING(4590,154861
-#define SAFE_FREE(4598,155113
-#define SAFE_ALLOCA_LISP(4625,155691
-# define USE_STACK_LISP_OBJECTS 4652,156813
-# undef USE_STACK_LISP_OBJECTS4658,156979
-# define USE_STACK_LISP_OBJECTS 4659,157010
-enum { defined_GC_CHECK_STRING_BYTES 4663,157085
-enum { defined_GC_CHECK_STRING_BYTES 4665,157138
-union Aligned_Cons4670,157272
- struct Lisp_Cons s;4672,157293
- double d;4673,157315
- double d; intmax_t i;4673,157315
- double d; intmax_t i; void *p;p4673,157315
-union Aligned_String4676,157352
- struct Lisp_String s;4678,157375
- double d;4679,157399
- double d; intmax_t i;4679,157399
- double d; intmax_t i; void *p;p4679,157399
- USE_STACK_CONS 4689,157707
- USE_STACK_STRING 4691,157813
-#define STACK_CONS(4699,158150
-#define AUTO_CONS_EXPR(4701,158247
-#define AUTO_CONS(4709,158610
-#define AUTO_LIST1(4710,158681
-#define AUTO_LIST2(4712,158789
-#define AUTO_LIST3(4716,158944
-#define AUTO_LIST4(4720,159119
-# define verify_ascii(4732,159510
-#define AUTO_STRING(4740,159818
-#define FOR_EACH_TAIL(4752,160282
-#define FOR_EACH_ALIST_VALUE(4766,160773
-maybe_gc 4774,161060
-functionp 4784,161299
+#define EMACS_LISP_H22,801
+#define DECLARE_GDB_SYM(47,1422
+# define DEFINE_GDB_SYMBOL_BEGIN(49,1509
+# define DEFINE_GDB_SYMBOL_END(50,1579
+# define DEFINE_GDB_SYMBOL_BEGIN(52,1626
+# define DEFINE_GDB_SYMBOL_END(53,1703
+#undef min57,1791
+#undef max58,1802
+#define max(59,1813
+#define min(60,1855
+#define ARRAYELTS(63,1937
+#define GCTYPEBITS 67,2080
+DEFINE_GDB_SYMBOL_BEGIN GCTYPEBITS66,2038
+# define NONPOINTER_BITS 78,2568
+# define NONPOINTER_BITS 80,2601
+typedef int EMACS_INT;91,3024
+typedef unsigned int EMACS_UINT;92,3047
+# define EMACS_INT_MAX 93,3080
+# define pI 94,3112
+typedef long int EMACS_INT;96,3204
+typedef unsigned long EMACS_UINT;97,3232
+# define EMACS_INT_MAX 98,3266
+# define pI 99,3299
+typedef long long int EMACS_INT;103,3478
+typedef unsigned long long int EMACS_UINT;104,3511
+# define EMACS_INT_MAX 105,3554
+# define pI 106,3588
+enum { BOOL_VECTOR_BITS_PER_CHAR 114,3805
+#define BOOL_VECTOR_BITS_PER_CHAR 115,3841
+typedef size_t bits_word;123,4166
+# define BITS_WORD_MAX 124,4192
+enum { BITS_PER_BITS_WORD 125,4224
+typedef unsigned char bits_word;127,4291
+# define BITS_WORD_MAX 128,4324
+enum { BITS_PER_BITS_WORD 129,4387
+ BITS_PER_CHAR 136,4571
+ BITS_PER_SHORT 137,4606
+ BITS_PER_LONG 138,4658
+ BITS_PER_EMACS_INT 139,4713
+typedef intmax_t printmax_t;148,5090
+typedef uintmax_t uprintmax_t;149,5119
+# define pMd 150,5150
+# define pMu 151,5171
+typedef EMACS_INT printmax_t;153,5198
+typedef EMACS_UINT uprintmax_t;154,5228
+# define pMd 155,5260
+# define pMu 156,5279
+# define pD 165,5665
+# define pD 167,5710
+# define pD 169,5757
+# define pD 171,5780
+# define eassert(200,7063
+# define eassume(201,7141
+# define eassert(208,7320
+# define eassume(212,7451
+enum Lisp_Bits239,8520
+#define GCALIGNMENT 243,8648
+ VALBITS 246,8743
+ INTTYPEBITS 249,8839
+ FIXNUM_BITS 252,8946
+#define VAL_MAX 263,9328
+#define USE_LSB_TAG 271,9778
+DEFINE_GDB_SYMBOL_BEGIN USE_LSB_TAG270,9734
+# define alignas(281,10078
+# define GCALIGNED 288,10228
+# define GCALIGNED 290,10293
+# define lisp_h_XLI(327,11643
+# define lisp_h_XIL(328,11674
+# define lisp_h_XLI(330,11725
+# define lisp_h_XIL(331,11752
+#define lisp_h_CHECK_LIST_CONS(333,11786
+#define lisp_h_CHECK_NUMBER(334,11857
+#define lisp_h_CHECK_SYMBOL(335,11928
+#define lisp_h_CHECK_TYPE(336,11997
+#define lisp_h_CONSP(338,12108
+#define lisp_h_EQ(339,12157
+#define lisp_h_FLOATP(340,12202
+#define lisp_h_INTEGERP(341,12253
+#define lisp_h_MARKERP(342,12334
+#define lisp_h_MISCP(343,12409
+#define lisp_h_NILP(344,12458
+#define lisp_h_SET_SYMBOL_VAL(345,12494
+#define lisp_h_SYMBOL_CONSTANT_P(347,12608
+#define lisp_h_SYMBOL_VAL(348,12672
+#define lisp_h_SYMBOLP(350,12773
+#define lisp_h_VECTORLIKEP(351,12826
+#define lisp_h_XCAR(352,12887
+#define lisp_h_XCDR(353,12925
+#define lisp_h_XCONS(354,12965
+#define lisp_h_XHASH(356,13060
+#define lisp_h_XPNTR(357,13094
+# define lisp_h_check_cons_list(360,13222
+# define lisp_h_make_number(363,13290
+# define lisp_h_XFASTINT(365,13393
+# define lisp_h_XINT(366,13430
+# define lisp_h_XSYMBOL(367,13479
+# define lisp_h_XTYPE(371,13632
+# define lisp_h_XUNTAG(372,13697
+# define XLI(381,14087
+# define XIL(382,14118
+# define CHECK_LIST_CONS(383,14149
+# define CHECK_NUMBER(384,14210
+# define CHECK_SYMBOL(385,14259
+# define CHECK_TYPE(386,14308
+# define CONSP(387,14383
+# define EQ(388,14418
+# define FLOATP(389,14453
+# define INTEGERP(390,14490
+# define MARKERP(391,14531
+# define MISCP(392,14570
+# define NILP(393,14605
+# define SET_SYMBOL_VAL(394,14638
+# define SYMBOL_CONSTANT_P(395,14701
+# define SYMBOL_VAL(396,14764
+# define SYMBOLP(397,14813
+# define VECTORLIKEP(398,14852
+# define XCAR(399,14899
+# define XCDR(400,14932
+# define XCONS(401,14965
+# define XHASH(402,15000
+# define XPNTR(403,15035
+# define check_cons_list(405,15098
+# define make_number(408,15177
+# define XFASTINT(409,15225
+# define XINT(410,15267
+# define XSYMBOL(411,15301
+# define XTYPE(412,15341
+# define XUNTAG(413,15377
+#define LISP_MACRO_DEFUN(421,15673
+#define LISP_MACRO_DEFUN_VOID(425,15846
+#define INTMASK 437,16290
+#define case_Lisp_Int 438,16343
+#define ENUM_BF(445,16682
+#define ENUM_BF(447,16723
+enum Lisp_Type451,16764
+ Lisp_Symbol 454,16852
+ Lisp_Misc 458,16994
+ Lisp_Int0 461,17068
+ Lisp_Int1 462,17087
+ Lisp_String 466,17265
+ Lisp_Vectorlike 472,17544
+ Lisp_Cons 475,17633
+ Lisp_Float 477,17671
+enum Lisp_Misc_Type485,18017
+ Lisp_Misc_Free 487,18041
+ Lisp_Misc_Marker,488,18070
+ Lisp_Misc_Overlay,489,18092
+ Lisp_Misc_Save_Value,490,18115
+ Lisp_Misc_Finalizer,491,18141
+ Lisp_Misc_Float,494,18276
+ Lisp_Misc_Limit496,18360
+enum Lisp_Fwd_Type502,18544
+ Lisp_Fwd_Int,504,18567
+ Lisp_Fwd_Bool,505,18620
+ Lisp_Fwd_Obj,506,18671
+ Lisp_Fwd_Buffer_Obj,507,18730
+ Lisp_Fwd_Kboard_Obj 508,18801
+typedef struct { EMACS_INT i;567,21772
+typedef struct { EMACS_INT i; } Lisp_Object;567,21772
+#define LISP_INITIALLY(569,21818
+#undef CHECK_LISP_OBJECT_TYPE571,21849
+enum CHECK_LISP_OBJECT_TYPE 572,21879
+enum CHECK_LISP_OBJECT_TYPE { CHECK_LISP_OBJECT_TYPE 572,21879
+typedef EMACS_INT Lisp_Object;577,22055
+#define LISP_INITIALLY(578,22086
+enum CHECK_LISP_OBJECT_TYPE 579,22116
+enum CHECK_LISP_OBJECT_TYPE { CHECK_LISP_OBJECT_TYPE 579,22116
+#define LISP_INITIALLY_ZERO 582,22217
+enum symbol_interned639,24190
+ SYMBOL_UNINTERNED 641,24213
+ SYMBOL_INTERNED 642,24238
+ SYMBOL_INTERNED_IN_INITIAL_OBARRAY 643,24261
+enum symbol_redirect646,24306
+ SYMBOL_PLAINVAL 648,24329
+ SYMBOL_VARALIAS 649,24353
+ SYMBOL_LOCALIZED 650,24377
+ SYMBOL_FORWARDED 651,24401
+struct Lisp_Symbol654,24428
+ bool_bf gcmarkbit 656,24449
+ ENUM_BF (symbol_redirect) redirect 663,24784
+ unsigned constant 668,25002
+ unsigned interned 672,25122
+ bool_bf declared_special 676,25284
+ bool_bf pinned 679,25385
+ Lisp_Object name;682,25454
+ Lisp_Object value;687,25622
+ struct Lisp_Symbol *alias;alias688,25645
+ struct Lisp_Buffer_Local_Value *blv;blv689,25676
+ union Lisp_Fwd *fwd;fwd690,25717
+ } val;691,25742
+ Lisp_Object function;694,25814
+ Lisp_Object plist;697,25876
+ struct Lisp_Symbol *next;next700,25965
+#define EXFUN(707,26243
+#define DEFUN_ARGS_MANY 712,26437
+#define DEFUN_ARGS_UNEVALLED 713,26489
+#define DEFUN_ARGS_0 714,26532
+#define DEFUN_ARGS_1 715,26560
+#define DEFUN_ARGS_2 716,26595
+#define DEFUN_ARGS_3 717,26643
+#define DEFUN_ARGS_4 718,26704
+#define DEFUN_ARGS_5 719,26778
+#define DEFUN_ARGS_6 721,26871
+#define DEFUN_ARGS_7 723,26977
+#define DEFUN_ARGS_8 725,27096
+#define TAG_PTR(729,27287
+#define TAG_SYMOFFSET(734,27534
+#define XLI_BUILTIN_LISPSYM(741,27833
+#define DEFINE_LISP_SYMBOL(746,28092
+# define DEFINE_NON_NIL_Q_SYMBOL_MACROS 755,28563
+LISP_MACRO_DEFUN 762,28768
+# define ARRAY_MARK_FLAG 768,29015
+# define PSEUDOVECTOR_FLAG 774,29258
+enum pvec_type780,29559
+ PVEC_NORMAL_VECTOR,782,29576
+ PVEC_FREE,783,29598
+ PVEC_PROCESS,784,29611
+ PVEC_FRAME,785,29627
+ PVEC_WINDOW,786,29641
+ PVEC_BOOL_VECTOR,787,29656
+ PVEC_BUFFER,788,29676
+ PVEC_HASH_TABLE,789,29691
+ PVEC_TERMINAL,790,29710
+ PVEC_WINDOW_CONFIGURATION,791,29727
+ PVEC_SUBR,792,29756
+ PVEC_OTHER,793,29769
+ PVEC_COMPILED,795,29847
+ PVEC_CHAR_TABLE,796,29864
+ PVEC_SUB_CHAR_TABLE,797,29883
+ PVEC_FONT 798,29906
+enum More_Lisp_Bits801,29982
+ PSEUDOVECTOR_SIZE_BITS 808,30373
+ PSEUDOVECTOR_SIZE_MASK 809,30406
+ PSEUDOVECTOR_REST_BITS 813,30616
+ PSEUDOVECTOR_REST_MASK 814,30649
+ PSEUDOVECTOR_AREA_BITS 818,30814
+ PVEC_TYPE_MASK 819,30892
+# define VALMASK 829,31293
+DEFINE_GDB_SYMBOL_BEGIN VALMASK828,31248
+#define MOST_POSITIVE_FIXNUM 834,31523
+#define MOST_NEGATIVE_FIXNUM 835,31583
+XINT 874,32675
+XFASTINT 889,33026
+XSYMBOL 899,33254
+XTYPE 910,33472
+XUNTAG 918,33652
+LISP_MACRO_DEFUN 927,33848
+LISP_MACRO_DEFUN 940,34233
+#define FIXNUM_OVERFLOW_P(958,34846
+LISP_MACRO_DEFUN FIXNUM_OVERFLOW_P952,34623
+LISP_MACRO_DEFUN 970,35162
+XSTRING 980,35382
+#define SYMBOL_INDEX(988,35566
+XFLOAT 991,35627
+XPROCESS 1000,35769
+XWINDOW 1007,35886
+XTERMINAL 1014,36003
+XSUBR 1021,36125
+XBUFFER 1028,36236
+XCHAR_TABLE 1035,36360
+XSUB_CHAR_TABLE 1042,36497
+XBOOL_VECTOR 1049,36639
+make_lisp_ptr 1058,36818
+make_lisp_symbol 1066,37004
+builtin_lisp_symbol 1074,37188
+#define XSETINT(1079,37270
+#define XSETFASTINT(1080,37316
+#define XSETCONS(1081,37366
+#define XSETVECTOR(1082,37426
+#define XSETSTRING(1083,37494
+#define XSETSYMBOL(1084,37558
+#define XSETFLOAT(1085,37612
+#define XSETMISC(1086,37674
+#define XSETPVECTYPE(1090,37763
+#define XSETPVECTYPESIZE(1092,37879
+#define XSETPSEUDOVECTOR(1099,38176
+#define XSETTYPED_PSEUDOVECTOR(1105,38360
+#define XSETWINDOW_CONFIGURATION(1110,38570
+#define XSETPROCESS(1112,38666
+#define XSETWINDOW(1113,38732
+#define XSETTERMINAL(1114,38796
+#define XSETSUBR(1115,38864
+#define XSETCOMPILED(1116,38924
+#define XSETBUFFER(1117,38992
+#define XSETCHAR_TABLE(1118,39056
+#define XSETBOOL_VECTOR(1119,39128
+#define XSETSUB_CHAR_TABLE(1120,39202
+XINTPTR 1128,39572
+make_pointer_integer 1134,39652
+LISP_MACRO_DEFUN_VOID 1143,39817
+typedef struct interval *INTERVAL;INTERVAL1149,39978
+ Lisp_Object cdr;1159,40153
+ struct Lisp_Cons *chain;chain1162,40227
+xcar_addr 1174,40751
+xcdr_addr 1179,40828
+LISP_MACRO_DEFUN 1185,40922
+XSETCDR 1198,41298
+CAR 1205,41448
+CDR 1212,41582
+CAR_SAFE 1221,41782
+CDR_SAFE 1226,41868
+STRING_MULTIBYTE 1243,42241
+#define STRING_BYTES_BOUND 1261,43048
+#define STRING_SET_UNIBYTE(1265,43192
+#define STRING_SET_MULTIBYTE(1275,43507
+SDATA 1286,43821
+SSDATA 1291,43899
+SREF 1297,44028
+SSET 1302,44119
+SCHARS 1307,44233
+STRING_BYTES 1316,44406
+SBYTES 1326,44586
+STRING_SET_CHARS 1331,44672
+struct vectorlike_header1343,45223
+ ptrdiff_t size;1364,46374
+struct Lisp_Vector1369,46473
+ struct vectorlike_header header;1371,46496
+ Lisp_Object contents[contents1372,46533
+ ALIGNOF_STRUCT_LISP_VECTOR1378,46672
+struct Lisp_Bool_Vector1384,46855
+ struct vectorlike_header header;1388,47003
+ EMACS_INT size;1390,47077
+ bits_word data[data1395,47310
+bool_vector_size 1399,47376
+bool_vector_data 1407,47514
+bool_vector_uchar_data 1413,47608
+bool_vector_words 1421,47794
+bool_vector_bytes 1428,47989
+bool_vector_bitref 1437,48229
+bool_vector_ref 1445,48469
+bool_vector_set 1453,48609
+ header_size 1471,49038
+ bool_header_size 1472,49097
+ word_size 1473,49162
+AREF 1479,49275
+aref_addr 1485,49382
+ASIZE 1491,49492
+ASET 1497,49574
+gc_aset 1504,49733
+enum { NIL_IS_ZERO 1515,50260
+memclear 1520,50455
+#define VECSIZE(1531,50753
+#define PSEUDOVECSIZE(1538,51038
+#define UNSIGNED_CMP(1546,51471
+#define ASCII_CHAR_P(1552,51725
+enum CHARTAB_SIZE_BITS1565,52480
+ CHARTAB_SIZE_BITS_0 1567,52507
+ CHARTAB_SIZE_BITS_1 1568,52536
+ CHARTAB_SIZE_BITS_2 1569,52565
+ CHARTAB_SIZE_BITS_3 1570,52594
+struct Lisp_Char_Table1575,52663
+ struct vectorlike_header header;1581,52919
+ Lisp_Object defalt;1585,53069
+ Lisp_Object parent;1590,53271
+ Lisp_Object purpose;1594,53389
+ Lisp_Object ascii;1598,53555
+ Lisp_Object contents[contents1600,53579
+ Lisp_Object extras[extras1603,53690
+struct Lisp_Sub_Char_Table1606,53743
+ struct vectorlike_header header;1610,53909
+ int depth;1618,54332
+ int min_char;1621,54408
+ Lisp_Object contents[contents1624,54483
+CHAR_TABLE_REF_ASCII 1628,54557
+CHAR_TABLE_REF 1648,55104
+CHAR_TABLE_SET 1658,55393
+struct Lisp_Subr1670,55777
+ struct vectorlike_header header;1672,55798
+ Lisp_Object (*a0)a01674,55847
+ Lisp_Object (*a1)a11675,55879
+ Lisp_Object (*a2)a21676,55918
+ Lisp_Object (*a3)a31677,55970
+ Lisp_Object (*a4)a41678,56035
+ Lisp_Object (*a5)a51679,56113
+ Lisp_Object (*a6)a61680,56204
+ Lisp_Object (*a7)a71681,56308
+ Lisp_Object (*a8)a81682,56425
+ Lisp_Object (*aUNEVALLED)aUNEVALLED1683,56555
+ Lisp_Object (*aMANY)aMANY1684,56607
+ } function;1685,56662
+ short min_args,1686,56678
+ short min_args, max_args;1686,56678
+ const char *symbol_name;symbol_name1687,56708
+ const char *intspec;intspec1688,56737
+ const char *doc;doc1689,56762
+enum char_table_specials1692,56789
+ CHAR_TABLE_STANDARD_SLOTS 1697,56984
+ SUB_CHAR_TABLE_OFFSET 1701,57205
+CHAR_TABLE_EXTRA_SLOTS 1707,57368
+LISP_MACRO_DEFUN 1723,57912
+SYMBOL_BLV 1732,58172
+SYMBOL_FWD 1738,58307
+LISP_MACRO_DEFUN_VOID 1744,58419
+SET_SYMBOL_BLV 1754,58682
+SET_SYMBOL_FWD 1760,58841
+SYMBOL_NAME 1767,58992
+SYMBOL_INTERNED_P 1775,59121
+SYMBOL_INTERNED_IN_INITIAL_OBARRAY_P 1783,59290
+#define DEFSYM(1796,59800
+LISP_MACRO_DEFUN DEFSYM1792,59621
+struct hash_table_test1805,60053
+ Lisp_Object name;1808,60130
+ Lisp_Object user_hash_function;1811,60197
+ Lisp_Object user_cmp_function;1814,60288
+ bool (*cmpfn)cmpfn1817,60363
+ EMACS_UINT (*hashfn)hashfn1820,60477
+struct Lisp_Hash_Table1823,60546
+ struct vectorlike_header header;1826,60640
+ Lisp_Object weak;1830,60774
+ Lisp_Object rehash_size;1835,60998
+ Lisp_Object rehash_threshold;1839,61120
+ Lisp_Object hash;1843,61251
+ Lisp_Object next;1848,61481
+ Lisp_Object next_free;1851,61551
+ Lisp_Object index;1856,61762
+ ptrdiff_t count;1863,62032
+ Lisp_Object key_and_value;1868,62231
+ struct hash_table_test test;1871,62305
+ struct Lisp_Hash_Table *next_weak;next_weak1875,62448
+XHASH_TABLE 1880,62522
+#define XSET_HASH_TABLE(1885,62593
+HASH_TABLE_P 1889,62694
+HASH_KEY 1896,62851
+HASH_VALUE 1903,63031
+HASH_NEXT 1911,63245
+HASH_HASH 1918,63422
+HASH_INDEX 1926,63668
+HASH_TABLE_SIZE 1933,63817
+enum DEFAULT_HASH_SIZE 1940,63947
+enum DEFAULT_HASH_SIZE { DEFAULT_HASH_SIZE 1940,63947
+static double const DEFAULT_REHASH_THRESHOLD 1946,64167
+static double const DEFAULT_REHASH_SIZE 1950,64290
+sxhash_combine 1956,64456
+SXHASH_REDUCE 1964,64639
+struct Lisp_Misc_Any 1971,64797
+ ENUM_BF (Lisp_Misc_Type) type 1973,64857
+ bool_bf gcmarkbit 1974,64918
+ unsigned spacer 1975,64943
+struct Lisp_Marker1978,64971
+ ENUM_BF (Lisp_Misc_Type) type 1980,64992
+ bool_bf gcmarkbit 1981,65056
+ unsigned spacer 1982,65081
+ bool_bf need_adjustment 1986,65273
+ bool_bf insertion_type 1989,65414
+ struct buffer *buffer;buffer2000,66007
+ struct Lisp_Marker *next;next2009,66358
+ ptrdiff_t charpos;2011,66446
+ ptrdiff_t bytepos;2016,66704
+struct Lisp_Overlay2021,66832
+ ENUM_BF (Lisp_Misc_Type) type 2034,67340
+ bool_bf gcmarkbit 2035,67406
+ unsigned spacer 2036,67433
+ struct Lisp_Overlay *next;next2037,67459
+ Lisp_Object start;2038,67490
+ Lisp_Object end;2039,67513
+ Lisp_Object plist;2040,67534
+ SAVE_UNUSED,2047,67635
+ SAVE_INTEGER,2048,67652
+ SAVE_FUNCPOINTER,2049,67670
+ SAVE_POINTER,2050,67692
+ SAVE_OBJECT2051,67710
+enum { SAVE_SLOT_BITS 2055,67795
+enum { SAVE_VALUE_SLOTS 2058,67892
+enum { SAVE_TYPE_BITS 2062,68000
+enum Lisp_Save_Type2064,68066
+ SAVE_TYPE_INT_INT 2066,68090
+ SAVE_TYPE_INT_INT_INT2067,68163
+ SAVE_TYPE_OBJ_OBJ 2069,68253
+ SAVE_TYPE_OBJ_OBJ_OBJ 2070,68324
+ SAVE_TYPE_OBJ_OBJ_OBJ_OBJ2071,68405
+ SAVE_TYPE_PTR_INT 2073,68500
+ SAVE_TYPE_PTR_OBJ 2074,68573
+ SAVE_TYPE_PTR_PTR 2075,68645
+ SAVE_TYPE_FUNCPTR_PTR_OBJ2076,68718
+ SAVE_TYPE_MEMORY 2080,68876
+typedef void (*voidfuncptr)voidfuncptr2108,69830
+struct Lisp_Save_Value2110,69867
+ ENUM_BF (Lisp_Misc_Type) type 2112,69894
+ bool_bf gcmarkbit 2113,69963
+ unsigned spacer : 32 - (16 + 1 + SAVE_TYPE_BITS)2114,69990
+ ENUM_BF (Lisp_Save_Type) save_type : SAVE_TYPE_BITS;2123,70480
+ void *pointer;pointer2125,70549
+ voidfuncptr funcpointer;2126,70570
+ ptrdiff_t integer;2127,70601
+ Lisp_Object object;2128,70626
+ } data[data2129,70652
+save_type 2134,70746
+XSAVE_POINTER 2143,70976
+set_save_pointer 2149,71138
+XSAVE_FUNCPOINTER 2155,71320
+XSAVE_INTEGER 2164,71540
+set_save_integer 2170,71702
+XSAVE_OBJECT 2179,71923
+struct Lisp_Finalizer2186,72100
+ struct Lisp_Misc_Any base;2188,72126
+ struct Lisp_Finalizer *prev;prev2191,72214
+ struct Lisp_Finalizer *next;next2192,72247
+ Lisp_Object function;2197,72484
+struct Lisp_Free2201,72575
+ ENUM_BF (Lisp_Misc_Type) type 2203,72596
+ bool_bf gcmarkbit 2204,72659
+ unsigned spacer 2205,72686
+ union Lisp_Misc *chain;chain2206,72712
+union Lisp_Misc2212,72876
+ struct Lisp_Misc_Any u_any;2214,72896
+ struct Lisp_Free u_free;2215,72967
+ struct Lisp_Marker u_marker;2216,72996
+ struct Lisp_Overlay u_overlay;2217,73029
+ struct Lisp_Save_Value u_save_value;2218,73064
+ struct Lisp_Finalizer u_finalizer;2219,73105
+XMISC 2223,73175
+XMISCANY 2229,73264
+XMISCTYPE 2236,73373
+XMARKER 2242,73461
+XOVERLAY 2249,73576
+XSAVE_VALUE 2256,73697
+XFINALIZER 2263,73826
+struct Lisp_Intfwd2274,74111
+ enum Lisp_Fwd_Type type;2276,74134
+ EMACS_INT *intvar;intvar2277,74184
+struct Lisp_Boolfwd2284,74405
+ enum Lisp_Fwd_Type type;2286,74429
+ bool *boolvar;boolvar2287,74480
+struct Lisp_Objfwd2294,74696
+ enum Lisp_Fwd_Type type;2296,74719
+ Lisp_Object *objvar;objvar2297,74769
+struct Lisp_Buffer_Objfwd2302,74928
+ enum Lisp_Fwd_Type type;2304,74958
+ int offset;2305,75015
+ Lisp_Object predicate;2307,75107
+struct Lisp_Buffer_Local_Value2334,76464
+ bool_bf local_if_set 2338,76609
+ bool_bf frame_local 2341,76791
+ bool_bf found 2344,76933
+ union Lisp_Fwd *fwd;fwd2346,77035
+ Lisp_Object where;2348,77178
+ Lisp_Object defcell;2351,77304
+ Lisp_Object valcell;2357,77608
+struct Lisp_Kboard_Objfwd2362,77723
+ enum Lisp_Fwd_Type type;2364,77753
+ int offset;2365,77810
+union Lisp_Fwd2368,77832
+ struct Lisp_Intfwd u_intfwd;2370,77851
+ struct Lisp_Boolfwd u_boolfwd;2371,77884
+ struct Lisp_Objfwd u_objfwd;2372,77919
+ struct Lisp_Buffer_Objfwd u_buffer_objfwd;2373,77952
+ struct Lisp_Kboard_Objfwd u_kboard_objfwd;2374,77999
+XFWDTYPE 2378,78078
+XBUFFER_OBJFWD 2384,78174
+struct Lisp_Float2391,78310
+ double data;2395,78348
+ struct Lisp_Float *chain;chain2396,78367
+ } u;2397,78399
+XFLOAT_DATA 2401,78428
+ IEEE_FLOATING_POINT2415,78937
+#define _UCHAR_T2423,79260
+typedef unsigned char UCHAR;2424,79277
+enum Lisp_Compiled2429,79360
+ COMPILED_ARGLIST 2431,79383
+ COMPILED_BYTECODE 2432,79409
+ COMPILED_CONSTANTS 2433,79436
+ COMPILED_STACK_DEPTH 2434,79464
+ COMPILED_DOC_STRING 2435,79494
+ COMPILED_INTERACTIVE 2436,79523
+enum char_bits2443,79825
+ CHAR_ALT 2445,79844
+ CHAR_SUPER 2446,79870
+ CHAR_HYPER 2447,79898
+ CHAR_SHIFT 2448,79926
+ CHAR_CTL 2449,79954
+ CHAR_META 2450,79980
+ CHAR_MODIFIER_MASK 2452,80008
+ CHARACTERBITS 2457,80203
+LISP_MACRO_DEFUN 2462,80261
+NATNUMP 2470,80403
+RANGED_INTEGERP 2476,80484
+#define TYPE_RANGED_INTEGERP(2481,80606
+LISP_MACRO_DEFUN 2486,80791
+VECTORP 2500,81264
+OVERLAYP 2505,81367
+SAVE_VALUEP 2510,81466
+FINALIZERP 2516,81572
+AUTOLOADP 2522,81676
+BUFFER_OBJFWDP 2528,81767
+PSEUDOVECTOR_TYPEP 2534,81865
+PSEUDOVECTORP 2542,82118
+WINDOW_CONFIGURATIONP 2558,82470
+PROCESSP 2564,82580
+WINDOWP 2570,82664
+TERMINALP 2576,82746
+SUBRP 2582,82832
+COMPILEDP 2588,82910
+BUFFERP 2594,82996
+CHAR_TABLE_P 2600,83078
+SUB_CHAR_TABLE_P 2606,83169
+BOOL_VECTOR_P 2612,83268
+FRAMEP 2618,83361
+IMAGEP 2625,83478
+ARRAYP 2632,83583
+CHECK_LIST 2638,83702
+LISP_MACRO_DEFUN_VOID 2643,83783
+CHECK_STRING_CAR 2653,84080
+CHECK_CONS 2658,84184
+CHECK_VECTOR 2663,84264
+CHECK_BOOL_VECTOR 2668,84350
+CHECK_VECTOR_OR_STRING 2674,84527
+CHECK_ARRAY 2683,84701
+CHECK_BUFFER 2688,84809
+CHECK_WINDOW 2693,84895
+CHECK_PROCESS 2699,85001
+CHECK_NATNUM 2705,85097
+#define CHECK_RANGED_INTEGER(2710,85174
+#define CHECK_TYPE_RANGED_INTEGER(2721,85557
+#define CHECK_NUMBER_COERCE_MARKER(2729,85827
+XFLOATINT 2738,86080
+CHECK_NUMBER_OR_FLOAT 2744,86151
+#define CHECK_NUMBER_OR_FLOAT_COERCE_MARKER(2749,86250
+CHECK_NUMBER_CAR 2760,86660
+CHECK_NUMBER_CDR 2768,86782
+#define DEFUN(2803,88377
+#define DEFUN(2812,88845
+FUNCTIONP 2822,89200
+enum maxargs2831,89395
+ MANY 2833,89412
+ UNEVALLED 2834,89427
+#define CALLMANY(2838,89530
+#define CALLN(2844,89883
+#define DEFVAR_LISP(2869,91088
+#define DEFVAR_LISP_NOPRO(2874,91260
+#define DEFVAR_BOOL(2879,91442
+#define DEFVAR_INT(2884,91615
+#define DEFVAR_BUFFER_DEFAULTS(2890,91786
+#define DEFVAR_KBOARD(2896,91990
+typedef jmp_buf sys_jmp_buf;2906,92314
+# define sys_setjmp(2907,92343
+# define sys_longjmp(2908,92378
+typedef sigjmp_buf sys_jmp_buf;2910,92450
+# define sys_setjmp(2911,92482
+# define sys_longjmp(2912,92522
+typedef jmp_buf sys_jmp_buf;2916,92681
+# define sys_setjmp(2917,92710
+# define sys_longjmp(2918,92744
+enum specbind_tag 2943,93796
+ SPECPDL_UNWIND,2944,93816
+ SPECPDL_UNWIND_PTR,2945,93885
+ SPECPDL_UNWIND_INT,2946,93936
+ SPECPDL_UNWIND_VOID,2947,93984
+ SPECPDL_BACKTRACE,2948,94038
+ SPECPDL_LET,2949,94096
+ SPECPDL_LET_LOCAL,2951,94226
+ SPECPDL_LET_DEFAULT 2952,94283
+union specbinding2955,94355
+ ENUM_BF (specbind_tag) kind : CHAR_BIT;2957,94377
+ ENUM_BF (specbind_tag) kind : CHAR_BIT;2959,94434
+ void (*func)func2960,94480
+ Lisp_Object arg;2961,94514
+ } unwind;2962,94537
+ ENUM_BF (specbind_tag) kind : CHAR_BIT;2964,94564
+ void (*func)func2965,94610
+ void *arg;arg2966,94639
+ } unwind_ptr;2967,94656
+ ENUM_BF (specbind_tag) kind : CHAR_BIT;2969,94687
+ void (*func)func2970,94733
+ int arg;2971,94759
+ } unwind_int;2972,94774
+ ENUM_BF (specbind_tag) kind : CHAR_BIT;2974,94805
+ void (*func)func2975,94851
+ } unwind_void;2976,94878
+ ENUM_BF (specbind_tag) kind : CHAR_BIT;2978,94910
+ Lisp_Object symbol,2980,95017
+ Lisp_Object symbol, old_value,2980,95017
+ Lisp_Object symbol, old_value, where;2980,95017
+ } let;2981,95061
+ ENUM_BF (specbind_tag) kind : CHAR_BIT;2983,95085
+ bool_bf debug_on_exit 2984,95131
+ Lisp_Object function;2985,95164
+ Lisp_Object *args;args2986,95192
+ ptrdiff_t nargs;2987,95217
+ } bt;2988,95240
+SPECPDL_INDEX 2996,95379
+enum handlertype 3021,96401
+enum handlertype { CATCHER,3021,96401
+enum handlertype { CATCHER, CONDITION_CASE 3021,96401
+struct handler3023,96448
+ enum handlertype type;3025,96465
+ Lisp_Object tag_or_ch;3026,96490
+ Lisp_Object val;3027,96515
+ struct handler *next;next3028,96534
+ struct handler *nextfree;nextfree3029,96558
+ Lisp_Object *bytecode_top;bytecode_top3036,96916
+ int bytecode_dest;3037,96945
+ struct gcpro *gcpro;gcpro3042,97182
+ sys_jmp_buf jmp;3044,97212
+ EMACS_INT lisp_eval_depth;3045,97231
+ ptrdiff_t pdlcount;3046,97260
+ int poll_suppress_count;3047,97282
+ int interrupt_input_blocked;3048,97309
+ struct byte_stack *byte_stack;byte_stack3049,97340
+#define PUSH_HANDLER(3053,97437
+#define QUIT 3101,99214
+#define QUITP 3112,99464
+struct gcpro3132,100307
+ struct gcpro *next;next3134,100322
+ volatile Lisp_Object *var;var3137,100391
+ ptrdiff_t nvars;3140,100473
+ const char *name;name3144,100558
+ int lineno;3147,100614
+ int idx;3150,100675
+ int level;3153,100711
+#define GC_USE_GCPROS_AS_BEFORE 3171,101288
+#define GC_MAKE_GCPROS_NOOPS 3172,101323
+#define GC_MARK_STACK_CHECK_GCPROS 3173,101355
+#define GC_USE_GCPROS_CHECK_ZOMBIES 3174,101392
+#define GC_MARK_STACK 3177,101453
+#define BYTE_MARK_STACK 3181,101553
+#define GCPRO1(3190,101824
+#define GCPRO2(3191,101864
+#define GCPRO3(3192,101930
+#define GCPRO4(3194,102025
+#define GCPRO5(3196,102145
+#define GCPRO6(3198,102290
+#define GCPRO7(3201,102465
+#define UNGCPRO 3202,102544
+#define GCPRO1(3208,102644
+#define GCPRO2(3212,102766
+#define GCPRO3(3217,102958
+#define GCPRO4(3223,103220
+#define GCPRO5(3230,103551
+#define GCPRO6(3238,103952
+#define GCPRO7(3247,104422
+#define UNGCPRO 3257,104962
+#define GCPRO1(3263,105056
+#define GCPRO2(3269,105290
+#define GCPRO3(3278,105708
+#define GCPRO4(3289,106265
+#define GCPRO5(3302,106963
+#define GCPRO6(3317,107803
+#define GCPRO7(3334,108784
+#define UNGCPRO 3353,109907
+#define RETURN_UNGCPRO(3363,110174
+vcopy 3384,110648
+set_hash_key_slot 3393,110923
+set_hash_value_slot 3399,111062
+set_symbol_function 3408,111297
+set_symbol_plist 3414,111412
+set_symbol_next 3420,111515
+blv_found 3428,111688
+set_overlay_plist 3437,111871
+string_intervals 3445,112022
+set_string_intervals 3453,112144
+set_char_table_defalt 3462,112346
+set_char_table_purpose 3467,112458
+set_char_table_extras 3475,112627
+set_char_table_contents 3482,112836
+set_sub_char_table_contents 3489,113031
+enum Arith_Comparison 3497,113294
+ ARITH_EQUAL,3498,113318
+ ARITH_NOTEQUAL,3499,113333
+ ARITH_LESS,3500,113351
+ ARITH_GRTR,3501,113365
+ ARITH_LESS_OR_EQUAL,3502,113379
+ ARITH_GRTR_OR_EQUAL3503,113402
+#define INTEGER_TO_CONS(3511,113753
+#define CONS_TO_INTEGER(3529,114616
+enum { NEXT_ALMOST_PRIME_LIMIT 3573,116320
+extern EMACS_INT next_almost_prime 3574,116359
+enum constype 3739,123811
+enum constype {CONSTYPE_HEAP,CONSTYPE_HEAP3739,123811
+enum constype {CONSTYPE_HEAP, CONSTYPE_PURE}CONSTYPE_PURE3739,123811
+list2i 3745,124001
+list3i 3751,124110
+list4i 3757,124249
+extern Lisp_Object make_formatted_string 3767,124625
+build_pure_c_string 3792,125653
+build_string 3801,125858
+make_uninit_vector 3820,126429
+make_uninit_sub_char_table 3833,126648
+#define ALLOCATE_PSEUDOVECTOR(3850,127192
+#define ALLOCATE_ZEROED_PSEUDOVECTOR(3858,127528
+INLINE void 3890,128934
+extern void *r_alloc r_alloc3895,129055
+#define FLOAT_TO_STRING_BUFSIZE 3927,130518
+intern 3968,132125
+intern_c_string 3974,132213
+extern _Noreturn void error 4034,135592
+fast_string_match_ignore_case 4136,140080
+INLINE void fixup_locale 4241,143845
+INLINE void synchronize_system_messages_locale 4242,143880
+INLINE void synchronize_system_time_locale 4243,143937
+#define IS_DAEMON 4257,144410
+#define DAEMON_RUNNING 4258,144450
+#define IS_DAEMON 4261,144549
+#define DAEMON_RUNNING 4262,144594
+# define WAIT_READING_MAX 4281,145413
+# define WAIT_READING_MAX 4283,145485
+extern _Noreturn void emacs_abort 4374,148377
+egetenv 4532,152800
+#define eabs(4545,153296
+#define make_fixnum_or_float(4550,153429
+enum MAX_ALLOCA 4556,153680
+enum MAX_ALLOCA { MAX_ALLOCA 4556,153680
+extern void *record_xmalloc record_xmalloc4558,153725
+#define USE_SAFE_ALLOCA 4560,153791
+#define AVAIL_ALLOCA(4564,153924
+#define SAFE_ALLOCA(4568,154035
+#define SAFE_NALLOCA(4576,154376
+#define SAFE_ALLOCA_STRING(4590,154852
+#define SAFE_FREE(4598,155104
+#define SAFE_ALLOCA_LISP(4625,155682
+# define USE_STACK_LISP_OBJECTS 4652,156804
+# undef USE_STACK_LISP_OBJECTS4658,156970
+# define USE_STACK_LISP_OBJECTS 4659,157001
+enum { defined_GC_CHECK_STRING_BYTES 4663,157076
+enum { defined_GC_CHECK_STRING_BYTES 4665,157129
+union Aligned_Cons4670,157263
+ struct Lisp_Cons s;4672,157284
+ double d;4673,157306
+ double d; intmax_t i;4673,157306
+ double d; intmax_t i; void *p;p4673,157306
+union Aligned_String4676,157343
+ struct Lisp_String s;4678,157366
+ double d;4679,157390
+ double d; intmax_t i;4679,157390
+ double d; intmax_t i; void *p;p4679,157390
+ USE_STACK_CONS 4689,157698
+ USE_STACK_STRING 4691,157804
+#define STACK_CONS(4699,158141
+#define AUTO_CONS_EXPR(4701,158238
+#define AUTO_CONS(4709,158601
+#define AUTO_LIST1(4710,158672
+#define AUTO_LIST2(4712,158780
+#define AUTO_LIST3(4716,158935
+#define AUTO_LIST4(4720,159110
+# define verify_ascii(4732,159501
+#define AUTO_STRING(4740,159809
+#define FOR_EACH_TAIL(4752,160273
+#define FOR_EACH_ALIST_VALUE(4766,160764
+maybe_gc 4774,161051
+functionp 4784,161290
c-src/machsyscalls.c,23
#define SYSCALL(6,113
@@ -2351,27 +2349,27 @@ cp-src/burton.cpp,124
cp-src/functions.cpp,778
void Date::setDate setDate5,148
-void Date::plus plus32,939
-void Date::minus minus42,1229
-void Date::shift shift52,1407
-Date & Date::operator = operator =62,1628
-Date & Date::operator += operator +=69,1789
-Date & Date::operator -= operator -=78,1939
-Date & Date::operator ++ operator ++87,2080
-Date & Date::operator -- operator --96,2216
-int Date::operator - operator -104,2331
-int Date::operator < operator <112,2483
-int Date::operator > operator >116,2557
-int Date::operator == operator ==120,2631
-ostream& operator << operator <<124,2707
-istream& operator >> operator >>133,2943
-bool isLeap 159,3543
-bool isHoliday 163,3629
-void asort(173,3865
-void ReadVacation 186,4064
-void Debug 201,4523
-int WorkingDays(211,4867
-Date StartDay(226,5129
+void Date::plus plus32,938
+void Date::minus minus42,1226
+void Date::shift shift52,1404
+Date & Date::operator = operator =62,1625
+Date & Date::operator += operator +=69,1786
+Date & Date::operator -= operator -=78,1935
+Date & Date::operator ++ operator ++87,2076
+Date & Date::operator -- operator --96,2212
+int Date::operator - operator -104,2327
+int Date::operator < operator <112,2479
+int Date::operator > operator >116,2553
+int Date::operator == operator ==120,2627
+ostream& operator << operator <<124,2703
+istream& operator >> operator >>133,2939
+bool isLeap 159,3539
+bool isHoliday 163,3625
+void asort(173,3861
+void ReadVacation 186,4060
+void Debug 201,4519
+int WorkingDays(211,4863
+Date StartDay(226,5125
cp-src/MDiagArray2.h,482
#define octave_MDiagArray2_h 29,870
@@ -2520,134 +2518,134 @@ main(37,571
D(43,659
int x;44,694
-el-src/TAGTEST.EL,179
-(foo::defmumble bletch 1,0
-(defun foo==bar foo==bar2,33
-(defalias 'pending-delete-mode pending-delete-mode6,149
-(defalias (quote explicitly-quoted-pending-delete-mode)9,222
+el-src/TAGTEST.EL,181
+(foo::defmumble bletch 3,33
+(defun foo==bar foo==bar4,66
+(defalias 'pending-delete-mode pending-delete-mode8,182
+(defalias (quote explicitly-quoted-pending-delete-mode)11,255
el-src/emacs/lisp/progmodes/etags.el,5069
-(defvar tags-file-name 34,1034
-(defgroup etags 43,1498
-(defcustom tags-case-fold-search 47,1566
-(defcustom tags-table-list 59,2051
-(defcustom tags-compression-info-list69,2449
-(defcustom tags-add-tables 88,3231
-(defcustom tags-revert-without-query 98,3627
-(defvar tags-table-computed-list 103,3778
-(defvar tags-table-computed-list-for 112,4262
-(defvar tags-table-list-pointer 117,4510
-(defvar tags-table-list-started-at 121,4701
-(defvar tags-table-set-list 124,4821
-(defcustom find-tag-hook 129,5000
-(defcustom find-tag-default-function 137,5263
-(define-obsolete-variable-alias 'find-tag-marker-ring-lengthfind-tag-marker-ring-length145,5602
-(defcustom tags-tag-face 148,5699
-(defcustom tags-apropos-verbose 154,5834
-(defcustom tags-apropos-additional-actions 160,5998
-(defvaralias 'find-tag-marker-ring find-tag-marker-ring183,6917
-(defvar default-tags-table-function 189,7097
-(defvar tags-location-ring 194,7323
-(defvar tags-table-files 201,7599
-(defvar tags-completion-table 206,7766
-(defvar tags-included-tables 209,7858
-(defvar next-file-list 212,7953
-(defvar tags-table-format-functions 217,8059
-(defvar file-of-tag-function 224,8440
-(defvar tags-table-files-function 228,8634
-(defvar tags-completion-table-function 230,8745
-(defvar snarf-tag-function 232,8840
-(defvar goto-tag-location-function 236,9049
-(defvar find-tag-regexp-search-function 239,9222
-(defvar find-tag-regexp-tag-order 241,9343
-(defvar find-tag-regexp-next-line-after-failure-p 243,9452
-(defvar find-tag-search-function 245,9572
-(defvar find-tag-tag-order 247,9679
-(defvar find-tag-next-line-after-failure-p 249,9774
-(defvar list-tags-function 251,9880
-(defvar tags-apropos-function 253,9968
-(defvar tags-included-tables-function 255,10062
-(defvar verify-tags-table-function 257,10181
-(defun initialize-new-tags-table 260,10292
-(defun tags-table-mode 276,10980
-(defun visit-tags-table 285,11245
-(defun tags-table-check-computed-list 321,12783
-(defun tags-table-extend-computed-list 360,14654
-(defun tags-expand-table-name 400,16367
-(defun tags-table-list-member 409,16710
-(defun tags-verify-table 421,17182
-(defun tags-table-including 470,19302
-(defun tags-next-table 522,21346
-(defun visit-tags-table-buffer 543,22203
-(defun tags-reset-tags-tables 712,28513
-(defun file-of-tag 731,29170
-(defun tags-table-files 740,29519
-(defun tags-included-tables 749,29869
-(defun tags-completion-table 755,30115
-(defun tags-lazy-completion-table 783,31309
-(defun tags-completion-at-point-function 799,31944
-(defun find-tag-tag 818,32694
-(defvar last-tag 837,33367
-(defun find-tag-interactive 840,33426
-(defvar find-tag-history 852,33841
-(defun find-tag-noselect 860,34011
-(defun find-tag 932,37125
-(defun find-tag-other-window 959,38341
-(defun find-tag-other-frame 1000,40269
-(defun find-tag-regexp 1025,41443
-(defalias 'pop-tag-mark pop-tag-mark1049,42605
-(defvar tag-lines-already-matched 1052,42656
-(defun find-tag-in-order 1055,42763
-(defun tag-find-file-of-tag-noselect 1167,47109
-(defun tag-find-file-of-tag 1200,48955
-(defun etags-recognize-tags-table 1208,49181
-(defun etags-verify-tags-table 1241,50812
-(defun etags-file-of-tag 1246,51010
-(defun etags-tags-completion-table 1256,51345
-(defun etags-snarf-tag 1286,52551
-(defun etags-goto-tag-location 1324,54120
-(defun etags-list-tags 1388,56563
-(defmacro tags-with-face 1423,57838
-(defun etags-tags-apropos-additional 1431,58171
-(defun etags-tags-apropos 1465,59408
-(defun etags-tags-table-files 1527,61617
-(defun etags-tags-included-tables 1542,62053
-(defun tags-recognize-empty-tags-table 1559,62593
-(defun tag-exact-file-name-match-p 1587,63739
-(defun tag-file-name-match-p 1596,64132
-(defun tag-exact-match-p 1609,64688
-(defun tag-implicit-name-match-p 1620,65256
-(defun tag-symbol-match-p 1633,65856
-(defun tag-word-match-p 1643,66292
-(defun tag-partial-file-name-match-p 1652,66690
-(defun tag-any-match-p 1662,67134
-(defun tag-re-match-p 1667,67318
-(defcustom tags-loop-revert-buffers 1675,67567
-(defun next-file 1685,67976
-(defvar tags-loop-operate 1760,70890
-(defvar tags-loop-scan1763,70984
-(defun tags-loop-eval 1771,71313
-(defun tags-loop-continue 1782,71642
-(defun tags-search 1850,73948
-(defun tags-query-replace 1871,74774
-(defun tags-complete-tags-table-file 1896,75998
-(defun list-tags 1906,76377
-(defun tags-apropos 1934,77330
-(define-button-type 'tags-select-tags-tabletags-select-tags-table1957,78156
-(defun select-tags-table 1964,78395
-(defvar select-tags-table-mode-map 2019,80522
-(define-derived-mode select-tags-table-mode 2030,80905
-(defun select-tags-table-select 2034,81089
-(defun select-tags-table-quit 2043,81455
-(defun complete-tag 2049,81610
-(defconst etags--xref-limit 2074,82551
-(defvar etags-xref-find-definitions-tag-order 2076,82586
-(defun etags-xref-find 2082,82876
-(defun etags--xref-find-definitions 2096,83405
-(defclass xref-etags-location 2129,85119
-(defun xref-make-etags-location 2135,85342
-(cl-defmethod xref-location-marker 2139,85497
-(cl-defmethod xref-location-line 2146,85741
+(defvar tags-file-name 34,1035
+(defgroup etags 43,1499
+(defcustom tags-case-fold-search 47,1567
+(defcustom tags-table-list 59,2052
+(defcustom tags-compression-info-list69,2450
+(defcustom tags-add-tables 88,3232
+(defcustom tags-revert-without-query 98,3628
+(defvar tags-table-computed-list 103,3779
+(defvar tags-table-computed-list-for 112,4263
+(defvar tags-table-list-pointer 117,4511
+(defvar tags-table-list-started-at 121,4702
+(defvar tags-table-set-list 124,4822
+(defcustom find-tag-hook 129,5001
+(defcustom find-tag-default-function 137,5264
+(define-obsolete-variable-alias 'find-tag-marker-ring-lengthfind-tag-marker-ring-length145,5603
+(defcustom tags-tag-face 148,5700
+(defcustom tags-apropos-verbose 154,5835
+(defcustom tags-apropos-additional-actions 160,5999
+(defvaralias 'find-tag-marker-ring find-tag-marker-ring183,6921
+(defvar default-tags-table-function 189,7101
+(defvar tags-location-ring 194,7327
+(defvar tags-table-files 201,7603
+(defvar tags-completion-table 206,7770
+(defvar tags-included-tables 209,7862
+(defvar next-file-list 212,7957
+(defvar tags-table-format-functions 217,8063
+(defvar file-of-tag-function 224,8444
+(defvar tags-table-files-function 228,8638
+(defvar tags-completion-table-function 230,8749
+(defvar snarf-tag-function 232,8844
+(defvar goto-tag-location-function 236,9053
+(defvar find-tag-regexp-search-function 239,9226
+(defvar find-tag-regexp-tag-order 241,9347
+(defvar find-tag-regexp-next-line-after-failure-p 243,9456
+(defvar find-tag-search-function 245,9576
+(defvar find-tag-tag-order 247,9683
+(defvar find-tag-next-line-after-failure-p 249,9778
+(defvar list-tags-function 251,9884
+(defvar tags-apropos-function 253,9972
+(defvar tags-included-tables-function 255,10066
+(defvar verify-tags-table-function 257,10185
+(defun initialize-new-tags-table 260,10296
+(defun tags-table-mode 276,10984
+(defun visit-tags-table 285,11249
+(defun tags-table-check-computed-list 321,12787
+(defun tags-table-extend-computed-list 360,14658
+(defun tags-expand-table-name 400,16371
+(defun tags-table-list-member 409,16714
+(defun tags-verify-table 421,17186
+(defun tags-table-including 470,19306
+(defun tags-next-table 522,21350
+(defun visit-tags-table-buffer 543,22207
+(defun tags-reset-tags-tables 712,28517
+(defun file-of-tag 731,29174
+(defun tags-table-files 740,29524
+(defun tags-included-tables 749,29874
+(defun tags-completion-table 755,30120
+(defun tags-lazy-completion-table 783,31314
+(defun tags-completion-at-point-function 799,31949
+(defun find-tag-tag 818,32699
+(defvar last-tag 837,33372
+(defun find-tag-interactive 840,33431
+(defvar find-tag-history 852,33846
+(defun find-tag-noselect 860,34016
+(defun find-tag 932,37130
+(defun find-tag-other-window 959,38346
+(defun find-tag-other-frame 1000,40274
+(defun find-tag-regexp 1025,41448
+(defalias 'pop-tag-mark pop-tag-mark1049,42610
+(defvar tag-lines-already-matched 1052,42661
+(defun find-tag-in-order 1055,42768
+(defun tag-find-file-of-tag-noselect 1167,47114
+(defun tag-find-file-of-tag 1200,48960
+(defun etags-recognize-tags-table 1208,49186
+(defun etags-verify-tags-table 1241,50817
+(defun etags-file-of-tag 1246,51015
+(defun etags-tags-completion-table 1256,51350
+(defun etags-snarf-tag 1286,52556
+(defun etags-goto-tag-location 1324,54125
+(defun etags-list-tags 1388,56568
+(defmacro tags-with-face 1423,57843
+(defun etags-tags-apropos-additional 1431,58176
+(defun etags-tags-apropos 1465,59413
+(defun etags-tags-table-files 1527,61622
+(defun etags-tags-included-tables 1542,62058
+(defun tags-recognize-empty-tags-table 1559,62598
+(defun tag-exact-file-name-match-p 1587,63744
+(defun tag-file-name-match-p 1596,64137
+(defun tag-exact-match-p 1609,64693
+(defun tag-implicit-name-match-p 1620,65261
+(defun tag-symbol-match-p 1633,65861
+(defun tag-word-match-p 1643,66297
+(defun tag-partial-file-name-match-p 1652,66695
+(defun tag-any-match-p 1662,67139
+(defun tag-re-match-p 1667,67323
+(defcustom tags-loop-revert-buffers 1675,67572
+(defun next-file 1685,67981
+(defvar tags-loop-operate 1760,70895
+(defvar tags-loop-scan1763,70989
+(defun tags-loop-eval 1771,71318
+(defun tags-loop-continue 1782,71647
+(defun tags-search 1850,73953
+(defun tags-query-replace 1871,74779
+(defun tags-complete-tags-table-file 1896,76003
+(defun list-tags 1906,76382
+(defun tags-apropos 1934,77335
+(define-button-type 'tags-select-tags-tabletags-select-tags-table1957,78161
+(defun select-tags-table 1964,78400
+(defvar select-tags-table-mode-map 2019,80527
+(define-derived-mode select-tags-table-mode 2030,80910
+(defun select-tags-table-select 2034,81094
+(defun select-tags-table-quit 2043,81460
+(defun complete-tag 2049,81615
+(defconst etags--xref-limit 2074,82556
+(defvar etags-xref-find-definitions-tag-order 2076,82591
+(defun etags-xref-find 2082,82881
+(defun etags--xref-find-definitions 2096,83410
+(defclass xref-etags-location 2129,85124
+(defun xref-make-etags-location 2135,85347
+(cl-defmethod xref-location-marker 2139,85502
+(cl-defmethod xref-location-line 2146,85746
erl-src/gs_dialog.erl,98
-define(VERSION2,32
@@ -2721,10 +2719,10 @@ func main(29,285
html-src/softwarelibero.html,200
Cos'è il software libero?4,38
-Licenze d'uso di un programmalicenze65,2500
-Sfatiamo alcuni miti138,6118
-Il movimento open sourceoss191,8037
-Impatto pratico del software liberoimpatto231,10066
+Licenze d'uso di un programmalicenze65,2502
+Sfatiamo alcuni miti138,6122
+Il movimento open sourceoss191,8041
+Impatto pratico del software liberoimpatto231,10070
html-src/index.shtml,104
&nbsp;8,281
@@ -2750,13 +2748,13 @@ MTGmtg41,1482
Fracasfracas65,2624
GaliLEOgalileo101,4232
Leasqrleasqr114,4677
-Free software that I wrote for the GNU project or for my personal or workgnu142,6065
-Etagsetags148,6180
-checkiso161,6729
-cgrep178,7547
-debian-bug.eldebian-bug190,7979
-tcpdump205,8564
-Links to interesting softwarelinks216,8891
+Free software that I wrote for the GNU project or for my personal or workgnu142,6066
+Etagsetags148,6181
+checkiso161,6731
+cgrep178,7549
+debian-bug.eldebian-bug190,7981
+tcpdump205,8566
+Links to interesting softwarelinks216,8893
lua-src/allegro.lua,400
local function get_layer_by_name 7,175
@@ -3313,22 +3311,22 @@ ord_add_element(71,1867
ord_del_element(85,2344
ord_disjoint(100,2783
ord_intersect(108,2953
-ord_intersection(126,3552
-ord_intersection3(130,3691
-ord_intersection(150,4531
-ord_intersection4(154,4703
-ord_intersection(176,5664
-ord_intersection2(181,5812
-ord_member(200,6318
-ord_seteq(216,6683
-ord_setproduct(225,6971
-ord_subset(240,7377
-ord_subtract(257,7861
-ord_symdiff(265,8054
-ord_union(288,8887
-ord_union4(303,9352
-ord_union(324,10171
-ord_union_all(329,10313
+ord_intersection(126,3553
+ord_intersection3(130,3692
+ord_intersection(150,4533
+ord_intersection4(154,4705
+ord_intersection(176,5666
+ord_intersection2(181,5814
+ord_member(200,6320
+ord_seteq(216,6685
+ord_setproduct(225,6973
+ord_subset(240,7379
+ord_subtract(257,7863
+ord_symdiff(265,8056
+ord_union(288,8889
+ord_union4(303,9354
+ord_union(324,10173
+ord_union_all(329,10315
prol-src/natded.prolog,2319
expandmng(100,2879
@@ -3350,92 +3348,92 @@ complete(328,10055
add_active(340,10527
parse(353,10949
derived_analyses(364,11341
-build(378,11965
-buildact(392,12521
-mapsyn(412,13542
-add_edge(434,14278
-findcats(447,14758
-normalize_tree(465,15478
-normalize_trees(475,15856
-expandmng_tree(486,16248
-expandmng_trees(496,16614
-cat(511,17013
-subtree(644,21266
-hypothetical_mem(653,21565
-make_coor(667,22130
-start_up:-start_up688,23013
-tokenizeatom(710,23921
-tokenize(720,24348
-isoperator(752,25377
-isoptab(756,25431
-specialsymbol(765,25756
-sstab(771,25861
-parse_cgi(787,26347
-keyvalseq(792,26510
-andkeyvalseq(796,26609
-keyval(799,26688
-valseq(807,26920
-plusvalseq(810,27007
-val(816,27109
-argvals(824,27426
-commaargvals(828,27503
-atomval(833,27578
-atom(836,27640
-action(846,28004
-keyvalcgi(864,28649
-keyvalscgi(865,28670
-outsyn(868,28726
-act(876,29060
-actout(901,29906
-texttreelist(912,30089
-htmltreelist(918,30190
-fitchtreelist(924,30304
-pp_html_table_tree(938,30759
-pp_html_tree(949,31113
-pp_html_trees(988,32381
-pp_html_table_fitch_tree(999,32769
-pp_html_fitch_tree(1017,33672
-removeexp(1129,39002
-splitexp(1142,39490
-pp_exp(1155,39990
-map_word(1168,40249
-pp_exps(1180,40474
-pp_tree(1188,40777
-pp_trees(1216,41807
-pp_word_list(1225,42128
-pp_word(1231,42262
-pp_word_list_rest(1238,42569
-pp_cat(1248,42929
-pp_syn(1255,43196
-pp_syn_paren(1276,43899
-pp_paren(1293,44377
-pp_syn_back(1300,44661
-pp_bas_cat(1311,45001
-writecat(1322,45409
-writesubs(1351,46455
-writesups(1361,46757
-writelistsubs(1371,47090
-pp_lam(1380,47408
-pp_lam_bracket(1398,48022
-pp_lam_paren(1407,48338
-pp_rule(1429,49238
-member(1447,49866
-append_list(1451,49919
-append(1456,50010
-at_least_one_member(1460,50076
-numbervars(1464,50171
-reverse(1467,50209
-select(1471,50290
-select_last(1475,50357
-cat_atoms(1479,50436
-writelist(1485,50524
-write_lex_cat(1492,50676
-writebreaklex(1500,50988
-write_lex(1513,51265
-writebreak(1521,51541
-tt:-tt1531,51713
-mt:-mt1534,51784
-cmt:-cmt1537,51878
+build(378,11967
+buildact(392,12523
+mapsyn(412,13544
+add_edge(434,14280
+findcats(447,14760
+normalize_tree(465,15480
+normalize_trees(475,15858
+expandmng_tree(486,16250
+expandmng_trees(496,16616
+cat(511,17015
+subtree(644,21268
+hypothetical_mem(653,21567
+make_coor(667,22132
+start_up:-start_up688,23015
+tokenizeatom(710,23923
+tokenize(720,24350
+isoperator(752,25379
+isoptab(756,25433
+specialsymbol(765,25758
+sstab(771,25863
+parse_cgi(787,26349
+keyvalseq(792,26512
+andkeyvalseq(796,26611
+keyval(799,26690
+valseq(807,26922
+plusvalseq(810,27009
+val(816,27111
+argvals(824,27428
+commaargvals(828,27505
+atomval(833,27580
+atom(836,27642
+action(846,28006
+keyvalcgi(864,28651
+keyvalscgi(865,28672
+outsyn(868,28728
+act(876,29062
+actout(901,29908
+texttreelist(912,30091
+htmltreelist(918,30192
+fitchtreelist(924,30306
+pp_html_table_tree(938,30761
+pp_html_tree(949,31115
+pp_html_trees(988,32383
+pp_html_table_fitch_tree(999,32771
+pp_html_fitch_tree(1017,33674
+removeexp(1129,39004
+splitexp(1142,39492
+pp_exp(1155,39992
+map_word(1168,40251
+pp_exps(1180,40476
+pp_tree(1188,40779
+pp_trees(1216,41809
+pp_word_list(1225,42130
+pp_word(1231,42264
+pp_word_list_rest(1238,42571
+pp_cat(1248,42931
+pp_syn(1255,43198
+pp_syn_paren(1276,43901
+pp_paren(1293,44379
+pp_syn_back(1300,44663
+pp_bas_cat(1311,45003
+writecat(1322,45411
+writesubs(1351,46457
+writesups(1361,46759
+writelistsubs(1371,47092
+pp_lam(1380,47410
+pp_lam_bracket(1398,48024
+pp_lam_paren(1407,48340
+pp_rule(1429,49240
+member(1447,49868
+append_list(1451,49921
+append(1456,50012
+at_least_one_member(1460,50078
+numbervars(1464,50173
+reverse(1467,50211
+select(1471,50292
+select_last(1475,50359
+cat_atoms(1479,50438
+writelist(1485,50526
+write_lex_cat(1492,50678
+writebreaklex(1500,50990
+write_lex(1513,51267
+writebreak(1521,51543
+tt:-tt1531,51715
+mt:-mt1534,51786
+cmt:-cmt1537,51880
pyt-src/server.py,1438
class Controls:Controls17,358
@@ -3543,6 +3541,11 @@ module A9,57
alias_method ( :foo2,foo237,586
A::Constant Constant42,655
+rs-src/test.rs,52
+enum IpAddrKind 3,11
+fn test1(8,48
+fn main(12,88
+
scm-src/test.scm,260
(define hello 1,0
(set! hello 3,32
@@ -3560,730 +3563,825 @@ tex-src/gzip.texi,303
@node Top,62,2139
@node Copying,80,2652
@node Overview,83,2705
-@node Sample,166,7272
-@node Invoking gzip,Invoking gzip210,8828
-@node Advanced usage,Advanced usage357,13496
-@node Environment,420,15208
-@node Tapes,437,15769
-@node Problems,460,16768
-@node Concept Index,Concept Index473,17288
+@node Sample,166,7273
+@node Invoking gzip,Invoking gzip210,8829
+@node Advanced usage,Advanced usage357,13497
+@node Environment,420,15209
+@node Tapes,437,15770
+@node Problems,460,16769
+@node Concept Index,Concept Index473,17289
tex-src/texinfo.tex,30627
-\def\texinfoversion{\texinfoversion26,1032
-\def\tie{\tie49,1523
-\def\gloggingall{\gloggingall72,2273
-\def\loggingall{\loggingall73,2342
-\def\onepageout#1{\onepageout99,3279
-\def\croppageout#1{\croppageout115,4029
-\def\cropmarks{\cropmarks142,5089
-\def\pagebody#1{\pagebody144,5136
-\def\ewtop{\ewtop157,5591
-\def\nstop{\nstop158,5655
-\def\ewbot{\ewbot160,5738
-\def\nsbot{\nsbot161,5802
-\def\parsearg #1{\parsearg170,6101
-\def\parseargx{\parseargx172,6179
-\def\parseargline{\parseargline182,6419
-\def\flushcr{\flushcr186,6540
-\newif\ifENV \ENVfalse \def\inENV{\inENV190,6739
-\def\ENVcheck{\ENVcheck191,6803
-\outer\def\begin{\begin198,7050
-\def\beginxxx #1{\beginxxx200,7088
-\def\end{\end208,7343
-\def\endxxx #1{\endxxx210,7371
-\def\errorE#1{\errorE216,7560
-\def\singlespace{\singlespace222,7754
-\def\@{\@232,7977
-\def\`{\`236,8077
-\def\'{\'237,8089
-\def\mylbrace {\mylbrace241,8137
-\def\myrbrace {\myrbrace242,8170
-\def\:{\:247,8284
-\def\*{\*250,8338
-\def\.{\.253,8414
-\def\w#1{\w258,8645
-\def\group{\group268,9128
- \def\Egroup{\Egroup273,9292
-\def\need{\need289,9734
-\def\needx#1{\needx300,10011
-\def\dots{\dots339,11397
-\def\page{\page343,11461
-\def\exdent{\exdent353,11788
-\def\exdentyyy #1{\exdentyyy354,11821
-\def\nofillexdent{\nofillexdent357,11965
-\def\nofillexdentyyy #1{\nofillexdentyyy358,12010
-\def\include{\include365,12194
-\def\includezzz #1{\includezzz366,12229
-\def\thisfile{\thisfile369,12280
-\def\center{\center373,12343
-\def\centerzzz #1{\centerzzz374,12376
-\def\sp{\sp380,12518
-\def\spxxx #1{\spxxx381,12543
-\def\comment{\comment387,12717
-\def\commentxxx #1{\commentxxx390,12814
-\def\ignoresections{\ignoresections396,12983
-\let\chapter=\relax=\relax397,13005
-\let\section=\relax=\relax406,13250
-\let\subsection=\relax=\relax409,13311
-\let\subsubsection=\relax=\relax410,13334
-\let\appendix=\relax=\relax411,13360
-\let\appendixsec=\relaxsec=\relax412,13381
-\let\appendixsection=\relaxsection=\relax413,13405
-\let\appendixsubsec=\relaxsubsec=\relax414,13433
-\let\appendixsubsection=\relaxsubsection=\relax415,13460
-\let\appendixsubsubsec=\relaxsubsubsec=\relax416,13491
-\let\appendixsubsubsection=\relaxsubsubsection=\relax417,13521
-\def\ignore{\ignore423,13623
-\long\def\ignorexxx #1\end ignore{\ignorexxx427,13763
-\def\direntry{\direntry429,13822
-\long\def\direntryxxx #1\end direntry{\direntryxxx430,13861
-\def\ifset{\ifset434,13971
-\def\ifsetxxx #1{\ifsetxxx436,14029
-\def\Eifset{\Eifset440,14156
-\def\ifsetfail{\ifsetfail441,14170
-\long\def\ifsetfailxxx #1\end ifset{\ifsetfailxxx442,14226
-\def\ifclear{\ifclear444,14287
-\def\ifclearxxx #1{\ifclearxxx446,14349
-\def\Eifclear{\Eifclear450,14480
-\def\ifclearfail{\ifclearfail451,14496
-\long\def\ifclearfailxxx #1\end ifclear{\ifclearfailxxx452,14556
-\def\set{\set456,14707
-\def\setxxx #1{\setxxx457,14734
-\def\clear{\clear460,14796
-\def\clearxxx #1{\clearxxx461,14827
-\def\iftex{\iftex466,14944
-\def\Eiftex{\Eiftex467,14957
-\def\ifinfo{\ifinfo468,14971
-\long\def\ifinfoxxx #1\end ifinfo{\ifinfoxxx469,15021
-\long\def\menu #1\end menu{\menu471,15080
-\def\asis#1{\asis472,15109
-\def\math#1{\math485,15652
-\def\node{\node487,15696
-\def\nodezzz#1{\nodezzz488,15734
-\def\nodexxx[#1,#2]{\nodexxx[489,15765
-\def\donoderef{\donoderef492,15827
-\def\unnumbnoderef{\unnumbnoderef496,15948
-\def\appendixnoderef{\appendixnoderef500,16079
-\expandafter\expandafter\expandafter\appendixsetref{setref501,16125
-\let\refill=\relaxill=\relax504,16214
-\def\setfilename{\setfilename509,16428
-\outer\def\bye{\bye518,16674
-\def\inforef #1{\inforef520,16730
-\def\inforefzzz #1,#2,#3,#4**{\inforefzzz521,16768
-\def\losespace #1{\losespace523,16865
-\def\sf{\sf532,17069
-\font\defbf=cmbx10 scaled \magstep1 %was 1314bf=cmbx10558,17864
-\font\deftt=cmtt10 scaled \magstep1tt=cmtt10559,17910
-\def\df{\df560,17946
-\def\resetmathfonts{\resetmathfonts635,20540
-\def\textfonts{\textfonts648,21129
-\def\chapfonts{\chapfonts653,21344
-\def\secfonts{\secfonts658,21560
-\def\subsecfonts{\subsecfonts663,21765
-\def\indexfonts{\indexfonts668,21982
-\def\smartitalicx{\smartitalicx691,22714
-\def\smartitalic#1{\smartitalic692,22790
-\let\cite=\smartitalic=\smartitalic698,22935
-\def\b#1{\b700,22959
-\def\t#1{\t703,22994
-\def\samp #1{\samp706,23146
-\def\key #1{\key707,23179
-\def\ctrl #1{\ctrl708,23240
-\def\tclose#1{\tclose716,23442
-\def\ {\720,23608
-\def\xkey{\xkey728,23877
-\def\kbdfoo#1#2#3\par{\kbdfoo729,23893
-\def\dmn#1{\dmn738,24194
-\def\kbd#1{\kbd740,24221
-\def\l#1{\l742,24278
-\def\r#1{\r744,24307
-\def\sc#1{\sc746,24375
-\def\ii#1{\ii747,24418
-\def\titlefont#1{\titlefont755,24651
-\def\titlepage{\titlepage761,24754
- \def\subtitlefont{\subtitlefont766,24981
- \def\authorfont{\authorfont768,25065
- \def\title{\title774,25275
- \def\titlezzz##1{\titlezzz775,25310
- \def\subtitle{\subtitle783,25625
- \def\subtitlezzz##1{\subtitlezzz784,25666
- \def\author{\author787,25784
- \def\authorzzz##1{\authorzzz788,25821
- \def\page{\page794,26112
-\def\Etitlepage{\Etitlepage804,26281
-\def\finishtitlepage{\finishtitlepage817,26669
-\def\evenheading{\evenheading846,27677
-\def\oddheading{\oddheading847,27720
-\def\everyheading{\everyheading848,27761
-\def\evenfooting{\evenfooting850,27807
-\def\oddfooting{\oddfooting851,27850
-\def\everyfooting{\everyfooting852,27891
-\def\headings #1 {\headings893,29583
-\def\HEADINGSoff{\HEADINGSoff895,29632
-\def\HEADINGSdouble{\HEADINGSdouble904,30059
-\def\HEADINGSsingle{\HEADINGSsingle914,30379
-\def\HEADINGSon{\HEADINGSon922,30600
-\def\HEADINGSafter{\HEADINGSafter924,30634
-\def\HEADINGSdoublex{\HEADINGSdoublex926,30729
-\def\HEADINGSsingleafter{\HEADINGSsingleafter933,30917
-\def\HEADINGSsinglex{\HEADINGSsinglex934,30978
-\def\today{\today943,31253
-\def\thistitle{\thistitle958,31798
-\def\settitle{\settitle959,31823
-\def\settitlezzz #1{\settitlezzz960,31860
-\def\internalBitem{\internalBitem992,32790
-\def\internalBitemx{\internalBitemx993,32840
-\def\internalBxitem "#1"{\internalBxitem995,32885
-\def\internalBxitemx "#1"{\internalBxitemx996,32965
-\def\internalBkitem{\internalBkitem998,33040
-\def\internalBkitemx{\internalBkitemx999,33092
-\def\kitemzzz #1{\kitemzzz1001,33139
-\def\xitemzzz #1{\xitemzzz1004,33241
-\def\itemzzz #1{\itemzzz1007,33344
-\def\item{\item1037,34415
-\def\itemx{\itemx1038,34466
-\def\kitem{\kitem1039,34519
-\def\kitemx{\kitemx1040,34572
-\def\xitem{\xitem1041,34627
-\def\xitemx{\xitemx1042,34680
-\def\description{\description1045,34790
-\def\table{\table1047,34840
-\def\ftable{\ftable1052,34984
-\def\Eftable{\Eftable1056,35130
-\def\vtable{\vtable1059,35199
-\def\Evtable{\Evtable1063,35345
-\def\dontindex #1{\dontindex1066,35414
-\def\fnitemindex #1{\fnitemindex1067,35434
-\def\vritemindex #1{\vritemindex1068,35479
-\def\tablez #1#2#3#4#5#6{\tablez1074,35628
-\def\Edescription{\Edescription1077,35686
-\def\itemfont{\itemfont1082,35888
-\def\Etable{\Etable1090,36114
-\def\itemize{\itemize1103,36438
-\def\itemizezzz #1{\itemizezzz1105,36474
-\def\itemizey #1#2{\itemizey1110,36569
-\def#2{1119,36815
-\def\itemcontents{\itemcontents1120,36856
-\def\bullet{\bullet1123,36904
-\def\minus{\minus1124,36931
-\def\frenchspacing{\frenchspacing1128,37039
-\def\splitoff#1#2\endmark{\splitoff1134,37264
-\def\enumerate{\enumerate1140,37494
-\def\enumeratezzz #1{\enumeratezzz1141,37533
-\def\enumeratey #1 #2\endenumeratey{\enumeratey1142,37586
- \def\thearg{\thearg1146,37733
- \ifx\thearg\empty \def\thearg{\thearg1147,37752
-\def\numericenumerate{\numericenumerate1184,39086
-\def\lowercaseenumerate{\lowercaseenumerate1190,39216
-\def\uppercaseenumerate{\uppercaseenumerate1203,39563
-\def\startenumeration#1{\startenumeration1219,40053
-\def\alphaenumerate{\alphaenumerate1227,40235
-\def\capsenumerate{\capsenumerate1228,40270
-\def\Ealphaenumerate{\Ealphaenumerate1229,40304
-\def\Ecapsenumerate{\Ecapsenumerate1230,40338
-\def\itemizeitem{\itemizeitem1234,40418
-\def\newindex #1{\newindex1259,41275
-\def\defindex{\defindex1268,41564
-\def\newcodeindex #1{\newcodeindex1272,41672
-\def\defcodeindex{\defcodeindex1279,41932
-\def\synindex #1 #2 {\synindex1283,42112
-\def\syncodeindex #1 #2 {\syncodeindex1292,42452
-\def\doindex#1{\doindex1309,43131
-\def\singleindexer #1{\singleindexer1310,43190
-\def\docodeindex#1{\docodeindex1313,43302
-\def\singlecodeindexer #1{\singlecodeindexer1314,43369
-\def\indexdummies{\indexdummies1316,43427
-\def\_{\_1317,43447
-\def\w{\w1318,43475
-\def\bf{\bf1319,43502
-\def\rm{\rm1320,43531
-\def\sl{\sl1321,43560
-\def\sf{\sf1322,43589
-\def\tt{\tt1323,43617
-\def\gtr{\gtr1324,43645
-\def\less{\less1325,43675
-\def\hat{\hat1326,43707
-\def\char{\char1327,43737
-\def\TeX{\TeX1328,43769
-\def\dots{\dots1329,43799
-\def\copyright{\copyright1330,43832
-\def\tclose##1{\tclose1331,43875
-\def\code##1{\code1332,43920
-\def\samp##1{\samp1333,43961
-\def\t##1{\t1334,44002
-\def\r##1{\r1335,44037
-\def\i##1{\i1336,44072
-\def\b##1{\b1337,44107
-\def\cite##1{\cite1338,44142
-\def\key##1{\key1339,44183
-\def\file##1{\file1340,44222
-\def\var##1{\var1341,44263
-\def\kbd##1{\kbd1342,44302
-\def\indexdummyfont#1{\indexdummyfont1347,44458
-\def\indexdummytex{\indexdummytex1348,44484
-\def\indexdummydots{\indexdummydots1349,44508
-\def\indexnofonts{\indexnofonts1351,44534
-\let\w=\indexdummyfontdummyfont1352,44554
-\let\t=\indexdummyfontdummyfont1353,44577
-\let\r=\indexdummyfontdummyfont1354,44600
-\let\i=\indexdummyfontdummyfont1355,44623
-\let\b=\indexdummyfontdummyfont1356,44646
-\let\emph=\indexdummyfontdummyfont1357,44669
-\let\strong=\indexdummyfontdummyfont1358,44695
-\let\cite=\indexdummyfont=\indexdummyfont1359,44723
-\let\sc=\indexdummyfontdummyfont1360,44749
-\let\tclose=\indexdummyfontdummyfont1364,44921
-\let\code=\indexdummyfontdummyfont1365,44949
-\let\file=\indexdummyfontdummyfont1366,44975
-\let\samp=\indexdummyfontdummyfont1367,45001
-\let\kbd=\indexdummyfontdummyfont1368,45027
-\let\key=\indexdummyfontdummyfont1369,45052
-\let\var=\indexdummyfontdummyfont1370,45077
-\let\TeX=\indexdummytexdummytex1371,45102
-\let\dots=\indexdummydotsdummydots1372,45126
-\let\indexbackslash=0 %overridden during \printindex.backslash=01382,45378
-\def\doind #1#2{\doind1384,45434
-{\indexdummies % Must do this here, since \bf, etc expand at this stagedummies1386,45477
-\def\rawbackslashxx{\rawbackslashxx1389,45617
-{\indexnofontsnofonts1394,45879
-\def\dosubind #1#2#3{\dosubind1405,46190
-{\indexdummies % Must do this here, since \bf, etc expand at this stagedummies1407,46238
-\def\rawbackslashxx{\rawbackslashxx1410,46342
-{\indexnofontsnofonts1414,46496
-\def\findex {\findex1443,47427
-\def\kindex {\kindex1444,47450
-\def\cindex {\cindex1445,47473
-\def\vindex {\vindex1446,47496
-\def\tindex {\tindex1447,47519
-\def\pindex {\pindex1448,47542
-\def\cindexsub {\cindexsub1450,47566
-\def\printindex{\printindex1462,47893
-\def\doprintindex#1{\doprintindex1464,47934
- \def\indexbackslash{\indexbackslash1481,48419
- \indexfonts\rm \tolerance=9500 \advance\baselineskip -1ptfonts\rm1482,48458
-\def\initial #1{\initial1517,49530
-\def\entry #1#2{\entry1523,49737
- \null\nobreak\indexdotfill % Have leaders before the page number.dotfill1540,50384
-\def\indexdotfill{\indexdotfill1549,50712
-\def\primary #1{\primary1552,50818
-\def\secondary #1#2{\secondary1556,50900
-\noindent\hskip\secondaryindent\hbox{#1}\indexdotfill #2\pardotfill1559,50982
-\newbox\partialpageialpage1566,51155
-\def\begindoublecolumns{\begindoublecolumns1572,51313
- \output={\global\setbox\partialpage=ialpage=1573,51349
-\def\enddoublecolumns{\enddoublecolumns1577,51537
-\def\doublecolumnout{\doublecolumnout1580,51622
- \dimen@=\pageheight \advance\dimen@ by-\ht\partialpageialpage1581,51691
-\def\pagesofar{\pagesofar1584,51869
-\def\balancecolumns{\balancecolumns1588,52106
- \availdimen@=\pageheight \advance\availdimen@ by-\ht\partialpageialpage1594,52277
- \dimen@=\pageheight \advance\dimen@ by-\ht\partialpageialpage1600,52538
-\newcount \appendixno \appendixno = `\@no1627,53443
-\def\appendixletter{\appendixletter1628,53484
-\def\opencontents{\opencontents1632,53587
-\def\thischapter{\thischapter1637,53768
-\def\seccheck#1{\seccheck1638,53806
-\def\chapternofonts{\chapternofonts1643,53910
-\def\result{\result1646,53985
-\def\equiv{\equiv1647,54020
-\def\expansion{\expansion1648,54053
-\def\print{\print1649,54094
-\def\TeX{\TeX1650,54127
-\def\dots{\dots1651,54156
-\def\copyright{\copyright1652,54187
-\def\tt{\tt1653,54228
-\def\bf{\bf1654,54255
-\def\w{\w1655,54283
-\def\less{\less1656,54308
-\def\gtr{\gtr1657,54339
-\def\hat{\hat1658,54368
-\def\char{\char1659,54397
-\def\tclose##1{\tclose1660,54428
-\def\code##1{\code1661,54472
-\def\samp##1{\samp1662,54512
-\def\r##1{\r1663,54552
-\def\b##1{\b1664,54586
-\def\key##1{\key1665,54620
-\def\file##1{\file1666,54658
-\def\kbd##1{\kbd1667,54698
-\def\i##1{\i1669,54806
-\def\cite##1{\cite1670,54840
-\def\var##1{\var1671,54880
-\def\emph##1{\emph1672,54918
-\def\dfn##1{\dfn1673,54958
-\def\thischaptername{\thischaptername1676,54999
-\outer\def\chapter{\chapter1677,55038
-\def\chapterzzz #1{\chapterzzz1678,55079
-{\chapternofonts%nofonts%1687,55475
-\global\let\section = \numberedsec=1692,55628
-\global\let\subsection = \numberedsubsec=1693,55663
-\global\let\subsubsection = \numberedsubsubsec=1694,55704
-\outer\def\appendix{\appendix1697,55755
-\def\appendixzzz #1{\appendixzzz1698,55798
-\global\advance \appendixno by 1 \message{no1700,55875
-\chapmacro {#1}{Appendix \appendixletter}letter1701,55944
-\xdef\thischapter{Appendix \appendixletter: \noexpand\thischaptername}letter:1704,56037
-{\chapternofonts%nofonts%1705,56109
- {#1}{Appendix \appendixletter}letter1707,56165
-\appendixnoderef %noderef1710,56265
-\global\let\section = \appendixsec=1711,56284
-\global\let\subsection = \appendixsubsec=1712,56319
-\global\let\subsubsection = \appendixsubsubsec=1713,56360
-\outer\def\top{\top1716,56411
-\outer\def\unnumbered{\unnumbered1717,56451
-\def\unnumberedzzz #1{\unnumberedzzz1718,56498
-{\chapternofonts%nofonts%1722,56661
-\global\let\section = \unnumberedsec=1727,56811
-\global\let\subsection = \unnumberedsubsec=1728,56848
-\global\let\subsubsection = \unnumberedsubsubsec=1729,56891
-\outer\def\numberedsec{\numberedsec1732,56944
-\def\seczzz #1{\seczzz1733,56985
-{\chapternofonts%nofonts%1736,57141
-\outer\def\appendixsection{\appendixsection1745,57327
-\outer\def\appendixsec{\appendixsec1746,57384
-\def\appendixsectionzzz #1{\appendixsectionzzz1747,57437
-\gdef\thissection{#1}\secheading {#1}{\appendixletter}letter1749,57549
-{\chapternofonts%nofonts%1750,57617
-{#1}{\appendixletter}letter1752,57673
-\appendixnoderef %noderef1755,57773
-\outer\def\unnumberedsec{\unnumberedsec1759,57813
-\def\unnumberedseczzz #1{\unnumberedseczzz1760,57866
-{\chapternofonts%nofonts%1762,57961
-\outer\def\numberedsubsec{\numberedsubsec1770,58129
-\def\numberedsubseczzz #1{\numberedsubseczzz1771,58184
-{\chapternofonts%nofonts%1774,58363
-\outer\def\appendixsubsec{\appendixsubsec1783,58567
-\def\appendixsubseczzz #1{\appendixsubseczzz1784,58622
-\subsecheading {#1}{\appendixletter}letter1786,58744
-{\chapternofonts%nofonts%1787,58809
-{#1}{\appendixletter}letter1789,58868
-\appendixnoderef %noderef1792,58983
-\outer\def\unnumberedsubsec{\unnumberedsubsec1796,59023
-\def\unnumberedsubseczzz #1{\unnumberedsubseczzz1797,59082
-{\chapternofonts%nofonts%1799,59183
-\outer\def\numberedsubsubsec{\numberedsubsubsec1807,59354
-\def\numberedsubsubseczzz #1{\numberedsubsubseczzz1808,59415
-{\chapternofonts%nofonts%1812,59612
-\outer\def\appendixsubsubsec{\appendixsubsubsec1823,59845
-\def\appendixsubsubseczzz #1{\appendixsubsubseczzz1824,59906
- {\appendixletter}letter1827,60045
-{\chapternofonts%nofonts%1828,60111
- {\appendixletter}letter1830,60176
-\appendixnoderef %noderef1834,60310
-\outer\def\unnumberedsubsubsec{\unnumberedsubsubsec1838,60350
-\def\unnumberedsubsubseczzz #1{\unnumberedsubsubseczzz1839,60415
-{\chapternofonts%nofonts%1841,60522
-\def\infotop{\infotop1851,60851
-\def\infounnumbered{\infounnumbered1852,60889
-\def\infounnumberedsec{\infounnumberedsec1853,60934
-\def\infounnumberedsubsec{\infounnumberedsubsec1854,60985
-\def\infounnumberedsubsubsec{\infounnumberedsubsubsec1855,61042
-\def\infoappendix{\infoappendix1857,61106
-\def\infoappendixsec{\infoappendixsec1858,61147
-\def\infoappendixsubsec{\infoappendixsubsec1859,61194
-\def\infoappendixsubsubsec{\infoappendixsubsubsec1860,61247
-\def\infochapter{\infochapter1862,61307
-\def\infosection{\infosection1863,61346
-\def\infosubsection{\infosubsection1864,61385
-\def\infosubsubsection{\infosubsubsection1865,61430
-\global\let\section = \numberedsec=1870,61667
-\global\let\subsection = \numberedsubsec=1871,61702
-\global\let\subsubsection = \numberedsubsubsec=1872,61743
-\def\majorheading{\majorheading1886,62250
-\def\majorheadingzzz #1{\majorheadingzzz1887,62295
-\def\chapheading{\chapheading1893,62528
-\def\chapheadingzzz #1{\chapheadingzzz1894,62571
-\def\heading{\heading1899,62766
-\def\subheading{\subheading1901,62803
-\def\subsubheading{\subsubheading1903,62846
-\def\dobreak#1#2{\dobreak1910,63123
-\def\setchapterstyle #1 {\setchapterstyle1912,63201
-\def\chapbreak{\chapbreak1919,63456
-\def\chappager{\chappager1920,63506
-\def\chapoddpage{\chapoddpage1921,63544
-\def\setchapternewpage #1 {\setchapternewpage1923,63623
-\def\CHAPPAGoff{\CHAPPAGoff1925,63680
-\def\CHAPPAGon{\CHAPPAGon1929,63774
-\global\def\HEADINGSon{\HEADINGSon1932,63865
-\def\CHAPPAGodd{\CHAPPAGodd1934,63907
-\global\def\HEADINGSon{\HEADINGSon1937,64003
-\def\CHAPFplain{\CHAPFplain1941,64057
-\def\chfplain #1#2{\chfplain1945,64149
-\def\unnchfplain #1{\unnchfplain1956,64372
-\def\unnchfopen #1{\unnchfopen1964,64601
-\def\chfopen #1#2{\chfopen1970,64809
-\def\CHAPFopen{\CHAPFopen1975,64953
-\def\subsecheadingbreak{\subsecheadingbreak1982,65171
-\def\secheadingbreak{\secheadingbreak1985,65300
-\def\secheading #1#2#3{\secheading1993,65582
-\def\plainsecheading #1{\plainsecheading1994,65638
-\def\secheadingi #1{\secheadingi1995,65681
-\def\subsecheading #1#2#3#4{\subsecheading2006,66049
-\def\subsecheadingi #1{\subsecheadingi2007,66116
-\def\subsubsecfonts{\subsubsecfonts2014,66413
-\def\subsubsecheading #1#2#3#4#5{\subsubsecheading2017,66536
-\def\subsubsecheadingi #1{\subsubsecheadingi2018,66614
-\def\startcontents#1{\startcontents2032,67086
- \unnumbchapmacro{#1}\def\thischapter{\thischapter2040,67359
-\outer\def\contents{\contents2049,67718
-\outer\def\summarycontents{\summarycontents2057,67862
- \def\secentry ##1##2##3##4{\secentry2067,68233
- \def\unnumbsecentry ##1##2{\unnumbsecentry2068,68268
- \def\subsecentry ##1##2##3##4##5{\subsecentry2069,68303
- \def\unnumbsubsecentry ##1##2{\unnumbsubsecentry2070,68344
- \def\subsubsecentry ##1##2##3##4##5##6{\subsubsecentry2071,68382
- \def\unnumbsubsubsecentry ##1##2{\unnumbsubsubsecentry2072,68429
-\def\chapentry#1#2#3{\chapentry2085,68863
-\def\shortchapentry#1#2#3{\shortchapentry2088,68980
- {#2\labelspace #1}space2091,69090
-\def\unnumbchapentry#1#2{\unnumbchapentry2094,69144
-\def\shortunnumberedentry#1#2{\shortunnumberedentry2095,69191
-\def\secentry#1#2#3#4{\secentry2102,69355
-\def\unnumbsecentry#1#2{\unnumbsecentry2103,69414
-\def\subsecentry#1#2#3#4#5{\subsecentry2106,69475
-\def\unnumbsubsecentry#1#2{\unnumbsubsecentry2107,69545
-\def\subsubsecentry#1#2#3#4#5#6{\subsubsecentry2110,69619
- \dosubsubsecentry{#2.#3.#4.#5\labelspace#1}space2111,69653
-\def\unnumbsubsubsecentry#1#2{\unnumbsubsubsecentry2112,69704
-\def\dochapentry#1#2{\dochapentry2123,70078
-\def\dosecentry#1#2{\dosecentry2138,70683
-\def\dosubsecentry#1#2{\dosubsecentry2145,70861
-\def\dosubsubsecentry#1#2{\dosubsubsecentry2152,71046
-\def\labelspace{\labelspace2160,71297
-\def\dopageno#1{\dopageno2162,71332
-\def\doshortpageno#1{\doshortpageno2163,71358
-\def\chapentryfonts{\chapentryfonts2165,71390
-\def\secentryfonts{\secentryfonts2166,71425
-\def\point{\point2192,72384
-\def\result{\result2194,72405
-\def\expansion{\expansion2195,72478
-\def\print{\print2196,72549
-\def\equiv{\equiv2198,72616
-\def\error{\error2218,73389
-\def\tex{\tex2224,73618
-\def\@{\@2242,74001
-\gdef\sepspaces{\def {\ }}}\2265,74733
-\def\aboveenvbreak{\aboveenvbreak2268,74815
-\def\afterenvbreak{\afterenvbreak2272,74981
-\def\ctl{\ctl2286,75492
-\def\ctr{\ctr2287,75564
-\def\cbl{\cbl2288,75603
-\def\cbr{\cbr2289,75643
-\def\carttop{\carttop2290,75682
-\def\cartbot{\cartbot2293,75790
-\long\def\cartouche{\cartouche2299,75930
-\def\Ecartouche{\Ecartouche2326,76718
-\def\lisp{\lisp2338,76853
-\def\Elisp{\Elisp2348,77200
-\def\next##1{\next2360,77526
-\def\Eexample{\Eexample2364,77568
-\def\Esmallexample{\Esmallexample2367,77615
-\def\smalllispx{\smalllispx2373,77793
-\def\Esmalllisp{\Esmalllisp2383,78147
-\obeyspaces \obeylines \ninett \indexfonts \rawbackslashfonts2396,78503
-\def\next##1{\next2397,78560
-\def\display{\display2401,78640
-\def\Edisplay{\Edisplay2410,78959
-\def\next##1{\next2422,79270
-\def\format{\format2426,79373
-\def\Eformat{\Eformat2434,79669
-\def\next##1{\next2437,79758
-\def\flushleft{\flushleft2441,79810
-\def\Eflushleft{\Eflushleft2451,80181
-\def\next##1{\next2454,80274
-\def\flushright{\flushright2456,80296
-\def\Eflushright{\Eflushright2466,80668
-\def\next##1{\next2470,80799
-\def\quotation{\quotation2474,80857
-\def\Equotation{\Equotation2480,81049
-\def\setdeffont #1 {\setdeffont2493,81447
-\newskip\defbodyindent \defbodyindent=.4inbodyindent2495,81493
-\newskip\defargsindent \defargsindent=50ptargsindent2496,81536
-\newskip\deftypemargin \deftypemargin=12pttypemargin2497,81579
-\newskip\deflastargmargin \deflastargmargin=18ptlastargmargin2498,81622
-\def\activeparens{\activeparens2503,81820
-\def\opnr{\opnr2529,83032
-\def\lbrb{\lbrb2530,83097
-\def\defname #1#2{\defname2536,83298
-\advance\dimen2 by -\defbodyindentbodyindent2540,83416
-\advance\dimen3 by -\defbodyindentbodyindent2542,83470
-\setbox0=\hbox{\hskip \deflastargmargin{lastargmargin2544,83524
-\dimen1=\hsize \advance \dimen1 by -\defargsindent %size for continuationsargsindent2546,83666
-\parshape 2 0in \dimen0 \defargsindent \dimen1 %argsindent2547,83741
-\rlap{\rightline{{\rm #2}\hskip \deftypemargin}typemargin2554,84110
-\advance\leftskip by -\defbodyindentbodyindent2557,84244
-\exdentamount=\defbodyindentbodyindent2558,84281
-\def\defparsebody #1#2#3{\defparsebody2568,84640
-\def#1{2572,84824
-\def#2{2573,84860
-\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2575,84932
-\exdentamount=\defbodyindentbodyindent2576,85006
-\def\defmethparsebody #1#2#3#4 {\defmethparsebody2581,85110
-\def#1{2585,85271
-\def#2##1 {2586,85307
-\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2588,85390
-\exdentamount=\defbodyindentbodyindent2589,85464
-\def\defopparsebody #1#2#3#4#5 {\defopparsebody2592,85549
-\def#1{2596,85710
-\def#2##1 ##2 {2597,85746
-\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2600,85846
-\exdentamount=\defbodyindentbodyindent2601,85920
-\def\defvarparsebody #1#2#3{\defvarparsebody2608,86191
-\def#1{2612,86378
-\def#2{2613,86414
-\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2615,86473
-\exdentamount=\defbodyindentbodyindent2616,86547
-\def\defvrparsebody #1#2#3#4 {\defvrparsebody2621,86638
-\def#1{2625,86797
-\def#2##1 {2626,86833
-\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2628,86903
-\exdentamount=\defbodyindentbodyindent2629,86977
-\def\defopvarparsebody #1#2#3#4#5 {\defopvarparsebody2632,87049
-\def#1{2636,87213
-\def#2##1 ##2 {2637,87249
-\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2640,87336
-\exdentamount=\defbodyindentbodyindent2641,87410
-\def\defunargs #1{\defunargs2664,88170
-\def\deftypefunargs #1{\deftypefunargs2676,88552
-\def\deffn{\deffn2690,88934
-\def\deffnheader #1#2#3{\deffnheader2692,88991
-\begingroup\defname {name2693,89039
-\def\defun{\defun2699,89184
-\def\defunheader #1#2{\defunheader2701,89237
-\begingroup\defname {name2702,89312
-\defunargs {unargs2703,89348
-\def\deftypefun{\deftypefun2709,89496
-\def\deftypefunheader #1#2{\deftypefunheader2712,89618
-\def\deftypefunheaderx #1#2 #3\relax{\deftypefunheaderx2714,89727
-\begingroup\defname {name2716,89819
-\deftypefunargs {typefunargs2717,89865
-\def\deftypefn{\deftypefn2723,90036
-\def\deftypefnheader #1#2#3{\deftypefnheader2726,90185
-\def\deftypefnheaderx #1#2#3 #4\relax{\deftypefnheaderx2728,90321
-\begingroup\defname {name2730,90414
-\deftypefunargs {typefunargs2731,90454
-\def\defmac{\defmac2737,90575
-\def\defmacheader #1#2{\defmacheader2739,90632
-\begingroup\defname {name2740,90708
-\defunargs {unargs2741,90741
-\def\defspec{\defspec2747,90865
-\def\defspecheader #1#2{\defspecheader2749,90926
-\begingroup\defname {name2750,91003
-\defunargs {unargs2751,91043
-\def\deffnx #1 {\deffnx2758,91238
-\def\defunx #1 {\defunx2759,91295
-\def\defmacx #1 {\defmacx2760,91352
-\def\defspecx #1 {\defspecx2761,91411
-\def\deftypefnx #1 {\deftypefnx2762,91472
-\def\deftypeunx #1 {\deftypeunx2763,91537
-\def\defop #1 {\defop2769,91683
-\defopparsebody\Edefop\defopx\defopheader\defoptype}opparsebody\Edefop\defopx\defopheader\defoptype2770,91718
-\def\defopheader #1#2#3{\defopheader2772,91772
-\begingroup\defname {name2774,91861
-\defunargs {unargs2775,91907
-\def\defmethod{\defmethod2780,91968
-\def\defmethodheader #1#2#3{\defmethodheader2782,92041
-\begingroup\defname {name2784,92129
-\defunargs {unargs2785,92169
-\def\defcv #1 {\defcv2790,92243
-\defopvarparsebody\Edefcv\defcvx\defcvarheader\defcvtype}opvarparsebody\Edefcv\defcvx\defcvarheader\defcvtype2791,92278
-\def\defcvarheader #1#2#3{\defcvarheader2793,92337
-\begingroup\defname {name2795,92423
-\defvarargs {varargs2796,92469
-\def\defivar{\defivar2801,92542
-\def\defivarheader #1#2#3{\defivarheader2803,92605
-\begingroup\defname {name2805,92691
-\defvarargs {varargs2806,92742
-\def\defopx #1 {\defopx2812,92891
-\def\defmethodx #1 {\defmethodx2813,92948
-\def\defcvx #1 {\defcvx2814,93013
-\def\defivarx #1 {\defivarx2815,93070
-\def\defvarargs #1{\defvarargs2822,93341
-\def\defvr{\defvr2828,93485
-\def\defvrheader #1#2#3{\defvrheader2830,93540
-\begingroup\defname {name2831,93588
-\def\defvar{\defvar2835,93673
-\def\defvarheader #1#2{\defvarheader2837,93733
-\begingroup\defname {name2838,93804
-\defvarargs {varargs2839,93840
-\def\defopt{\defopt2844,93906
-\def\defoptheader #1#2{\defoptheader2846,93966
-\begingroup\defname {name2847,94037
-\defvarargs {varargs2848,94076
-\def\deftypevar{\deftypevar2853,94133
-\def\deftypevarheader #1#2{\deftypevarheader2856,94249
-\begingroup\defname {name2858,94332
-\def\deftypevr{\deftypevr2865,94506
-\def\deftypevrheader #1#2#3{\deftypevrheader2867,94577
-\begingroup\defname {name2868,94629
-\def\defvrx #1 {\defvrx2876,94866
-\def\defvarx #1 {\defvarx2877,94923
-\def\defoptx #1 {\defoptx2878,94982
-\def\deftypevarx #1 {\deftypevarx2879,95041
-\def\deftypevrx #1 {\deftypevrx2880,95108
-\def\deftpargs #1{\deftpargs2885,95257
-\def\deftp{\deftp2889,95337
-\def\deftpheader #1#2#3{\deftpheader2891,95392
-\begingroup\defname {name2892,95440
-\def\deftpx #1 {\deftpx2897,95599
-\def\setref#1{\setref2908,95920
-\def\unnumbsetref#1{\unnumbsetref2913,96034
-\def\appendixsetref#1{\appendixsetref2918,96141
-\def\pxref#1{\pxref2929,96552
-\def\xref#1{\xref2930,96588
-\def\ref#1{\ref2931,96623
-\def\xrefX[#1,#2,#3,#4,#5,#6]{\xrefX[2932,96653
-\def\printedmanual{\printedmanual2933,96696
-\def\printednodename{\printednodename2934,96734
-\def\printednodename{\printednodename2939,96859
-section ``\printednodename'' in \cite{\printedmanual}\printedmanual2954,97492
-\refx{x2957,97570
-\def\dosetq #1#2{\dosetq2965,97790
-\def\internalsetq #1#2{\internalsetq2973,98048
-\def\Ypagenumber{\Ypagenumber2977,98149
-\def\Ytitle{\Ytitle2979,98175
-\def\Ynothing{\Ynothing2981,98202
-\def\Ysectionnumberandtype{\Ysectionnumberandtype2983,98219
-\def\Yappendixletterandtype{\Yappendixletterandtype2992,98535
-\ifnum\secno=0 Appendix\xreftie'char\the\appendixno{no2993,98565
-\else \ifnum \subsecno=0 Section\xreftie'char\the\appendixno.\the\secno %no.\the\secno2994,98620
-Section\xreftie'char\the\appendixno.\the\secno.\the\subsecno %no.\the\secno.\the\subsecno2996,98724
-Section\xreftie'char\the\appendixno.\the\secno.\the\subsecno.\the\subsubsecno %no.\the\secno.\the\subsecno.\the\subsubsecno2998,98795
- \def\linenumber{\linenumber3009,99134
-\def\refx#1#2{\refx3015,99318
-\def\xrdef #1#2{\xrdef3037,99944
-\def\readauxfile{\readauxfile3040,100029
-\def\supereject{\supereject3110,101810
-\footstrut\parindent=\defaultparindent\hang\textindent{aultparindent\hang\textindent3131,102495
-\def\openindices{\openindices3139,102681
-\newdimen\defaultparindent \defaultparindent = 15ptaultparindent3151,102906
-\parindent = \defaultparindentaultparindent3152,102958
-\def\smallbook{\smallbook3175,103682
-\global\def\Esmallexample{\Esmallexample3192,104109
-\def\afourpaper{\afourpaper3196,104200
-\def\finalout{\finalout3224,105008
-\def\normaldoublequote{\normaldoublequote3235,105269
-\def\normaltilde{\normaltilde3236,105295
-\def\normalcaret{\normalcaret3237,105315
-\def\normalunderscore{\normalunderscore3238,105335
-\def\normalverticalbar{\normalverticalbar3239,105360
-\def\normalless{\normalless3240,105386
-\def\normalgreater{\normalgreater3241,105405
-\def\normalplus{\normalplus3242,105427
-\def\ifusingtt#1#2{\ifusingtt3253,105919
-\def\activedoublequote{\activedoublequote3261,106247
-\def~{~3264,106333
-\def^{^3267,106394
-\def_{_3270,106433
-\def\_{\_3272,106507
-\def\lvvmode{\lvvmode3279,106844
-\def|{|3282,106894
-\def<{<3285,106957
-\def>{>3288,107014
-\def+{+3290,107052
-\def\turnoffactive{\turnoffactive3296,107213
-\global\def={=3307,107499
-\def\normalbackslash{\normalbackslash3321,107881
+\def\texinfoversion{\texinfoversion26,1035
+\def\tie{\tie49,1526
+\def\gloggingall{\gloggingall72,2276
+\def\loggingall{\loggingall73,2345
+\def\onepageout#1{\onepageout99,3282
+\def\croppageout#1{\croppageout115,4032
+\def\cropmarks{\cropmarks142,5092
+\def\pagebody#1{\pagebody144,5139
+\def\ewtop{\ewtop157,5594
+\def\nstop{\nstop158,5658
+\def\ewbot{\ewbot160,5741
+\def\nsbot{\nsbot161,5805
+\def\parsearg #1{\parsearg170,6104
+\def\parseargx{\parseargx172,6182
+\def\parseargline{\parseargline182,6422
+\def\flushcr{\flushcr186,6543
+\newif\ifENV \ENVfalse \def\inENV{\inENV190,6742
+\def\ENVcheck{\ENVcheck191,6806
+\outer\def\begin{\begin198,7053
+\def\beginxxx #1{\beginxxx200,7091
+\def\end{\end208,7346
+\def\endxxx #1{\endxxx210,7374
+\def\errorE#1{\errorE216,7563
+\def\singlespace{\singlespace222,7757
+\def\@{\@232,7980
+\def\`{\`236,8080
+\def\'{\'237,8092
+\def\mylbrace {\mylbrace241,8140
+\def\myrbrace {\myrbrace242,8173
+\def\:{\:247,8287
+\def\*{\*250,8341
+\def\.{\.253,8417
+\def\w#1{\w258,8648
+\def\group{\group268,9131
+ \def\Egroup{\Egroup273,9295
+\def\need{\need289,9737
+\def\needx#1{\needx300,10014
+\def\dots{\dots339,11400
+\def\page{\page343,11464
+\def\exdent{\exdent353,11791
+\def\exdentyyy #1{\exdentyyy354,11824
+\def\nofillexdent{\nofillexdent357,11968
+\def\nofillexdentyyy #1{\nofillexdentyyy358,12013
+\def\include{\include365,12197
+\def\includezzz #1{\includezzz366,12232
+\def\thisfile{\thisfile369,12283
+\def\center{\center373,12346
+\def\centerzzz #1{\centerzzz374,12379
+\def\sp{\sp380,12521
+\def\spxxx #1{\spxxx381,12546
+\def\comment{\comment387,12720
+\def\commentxxx #1{\commentxxx390,12817
+\def\ignoresections{\ignoresections396,12986
+\let\chapter=\relax=\relax397,13008
+\let\section=\relax=\relax406,13253
+\let\subsection=\relax=\relax409,13314
+\let\subsubsection=\relax=\relax410,13337
+\let\appendix=\relax=\relax411,13363
+\let\appendixsec=\relaxsec=\relax412,13384
+\let\appendixsection=\relaxsection=\relax413,13408
+\let\appendixsubsec=\relaxsubsec=\relax414,13436
+\let\appendixsubsection=\relaxsubsection=\relax415,13463
+\let\appendixsubsubsec=\relaxsubsubsec=\relax416,13494
+\let\appendixsubsubsection=\relaxsubsubsection=\relax417,13524
+\def\ignore{\ignore423,13626
+\long\def\ignorexxx #1\end ignore{\ignorexxx427,13766
+\def\direntry{\direntry429,13825
+\long\def\direntryxxx #1\end direntry{\direntryxxx430,13864
+\def\ifset{\ifset434,13974
+\def\ifsetxxx #1{\ifsetxxx436,14032
+\def\Eifset{\Eifset440,14159
+\def\ifsetfail{\ifsetfail441,14173
+\long\def\ifsetfailxxx #1\end ifset{\ifsetfailxxx442,14229
+\def\ifclear{\ifclear444,14290
+\def\ifclearxxx #1{\ifclearxxx446,14352
+\def\Eifclear{\Eifclear450,14483
+\def\ifclearfail{\ifclearfail451,14499
+\long\def\ifclearfailxxx #1\end ifclear{\ifclearfailxxx452,14559
+\def\set{\set456,14710
+\def\setxxx #1{\setxxx457,14737
+\def\clear{\clear460,14799
+\def\clearxxx #1{\clearxxx461,14830
+\def\iftex{\iftex466,14947
+\def\Eiftex{\Eiftex467,14960
+\def\ifinfo{\ifinfo468,14974
+\long\def\ifinfoxxx #1\end ifinfo{\ifinfoxxx469,15024
+\long\def\menu #1\end menu{\menu471,15083
+\def\asis#1{\asis472,15112
+\def\math#1{\math485,15655
+\def\node{\node487,15699
+\def\nodezzz#1{\nodezzz488,15737
+\def\nodexxx[#1,#2]{\nodexxx[489,15768
+\def\donoderef{\donoderef492,15830
+\def\unnumbnoderef{\unnumbnoderef496,15951
+\def\appendixnoderef{\appendixnoderef500,16082
+\expandafter\expandafter\expandafter\appendixsetref{setref501,16128
+\let\refill=\relaxill=\relax504,16217
+\def\setfilename{\setfilename509,16431
+\outer\def\bye{\bye518,16677
+\def\inforef #1{\inforef520,16733
+\def\inforefzzz #1,#2,#3,#4**{\inforefzzz521,16771
+\def\losespace #1{\losespace523,16868
+\def\sf{\sf532,17072
+\font\defbf=cmbx10 scaled \magstep1 %was 1314bf=cmbx10558,17867
+\font\deftt=cmtt10 scaled \magstep1tt=cmtt10559,17913
+\def\df{\df560,17949
+\def\resetmathfonts{\resetmathfonts635,20543
+\def\textfonts{\textfonts648,21132
+\def\chapfonts{\chapfonts653,21347
+\def\secfonts{\secfonts658,21563
+\def\subsecfonts{\subsecfonts663,21768
+\def\indexfonts{\indexfonts668,21985
+\def\smartitalicx{\smartitalicx691,22717
+\def\smartitalic#1{\smartitalic692,22793
+\let\cite=\smartitalic=\smartitalic698,22938
+\def\b#1{\b700,22962
+\def\t#1{\t703,22997
+\def\samp #1{\samp706,23149
+\def\key #1{\key707,23182
+\def\ctrl #1{\ctrl708,23243
+\def\tclose#1{\tclose716,23445
+\def\ {\720,23611
+\def\xkey{\xkey728,23880
+\def\kbdfoo#1#2#3\par{\kbdfoo729,23896
+\def\dmn#1{\dmn738,24197
+\def\kbd#1{\kbd740,24224
+\def\l#1{\l742,24281
+\def\r#1{\r744,24310
+\def\sc#1{\sc746,24378
+\def\ii#1{\ii747,24421
+\def\titlefont#1{\titlefont755,24654
+\def\titlepage{\titlepage761,24757
+ \def\subtitlefont{\subtitlefont766,24984
+ \def\authorfont{\authorfont768,25068
+ \def\title{\title774,25278
+ \def\titlezzz##1{\titlezzz775,25313
+ \def\subtitle{\subtitle783,25628
+ \def\subtitlezzz##1{\subtitlezzz784,25669
+ \def\author{\author787,25787
+ \def\authorzzz##1{\authorzzz788,25824
+ \def\page{\page794,26115
+\def\Etitlepage{\Etitlepage804,26284
+\def\finishtitlepage{\finishtitlepage817,26672
+\def\evenheading{\evenheading846,27680
+\def\oddheading{\oddheading847,27723
+\def\everyheading{\everyheading848,27764
+\def\evenfooting{\evenfooting850,27810
+\def\oddfooting{\oddfooting851,27853
+\def\everyfooting{\everyfooting852,27894
+\def\headings #1 {\headings893,29586
+\def\HEADINGSoff{\HEADINGSoff895,29635
+\def\HEADINGSdouble{\HEADINGSdouble904,30062
+\def\HEADINGSsingle{\HEADINGSsingle914,30382
+\def\HEADINGSon{\HEADINGSon922,30603
+\def\HEADINGSafter{\HEADINGSafter924,30637
+\def\HEADINGSdoublex{\HEADINGSdoublex926,30732
+\def\HEADINGSsingleafter{\HEADINGSsingleafter933,30920
+\def\HEADINGSsinglex{\HEADINGSsinglex934,30981
+\def\today{\today943,31256
+\def\thistitle{\thistitle958,31801
+\def\settitle{\settitle959,31826
+\def\settitlezzz #1{\settitlezzz960,31863
+\def\internalBitem{\internalBitem992,32793
+\def\internalBitemx{\internalBitemx993,32843
+\def\internalBxitem "#1"{\internalBxitem995,32888
+\def\internalBxitemx "#1"{\internalBxitemx996,32968
+\def\internalBkitem{\internalBkitem998,33043
+\def\internalBkitemx{\internalBkitemx999,33095
+\def\kitemzzz #1{\kitemzzz1001,33142
+\def\xitemzzz #1{\xitemzzz1004,33244
+\def\itemzzz #1{\itemzzz1007,33347
+\def\item{\item1037,34418
+\def\itemx{\itemx1038,34469
+\def\kitem{\kitem1039,34522
+\def\kitemx{\kitemx1040,34575
+\def\xitem{\xitem1041,34630
+\def\xitemx{\xitemx1042,34683
+\def\description{\description1045,34793
+\def\table{\table1047,34843
+\def\ftable{\ftable1052,34987
+\def\Eftable{\Eftable1056,35133
+\def\vtable{\vtable1059,35202
+\def\Evtable{\Evtable1063,35348
+\def\dontindex #1{\dontindex1066,35417
+\def\fnitemindex #1{\fnitemindex1067,35437
+\def\vritemindex #1{\vritemindex1068,35482
+\def\tablez #1#2#3#4#5#6{\tablez1074,35631
+\def\Edescription{\Edescription1077,35689
+\def\itemfont{\itemfont1082,35890
+\def\Etable{\Etable1090,36116
+\def\itemize{\itemize1103,36440
+\def\itemizezzz #1{\itemizezzz1105,36476
+\def\itemizey #1#2{\itemizey1110,36571
+\def#2{1119,36817
+\def\itemcontents{\itemcontents1120,36858
+\def\bullet{\bullet1123,36906
+\def\minus{\minus1124,36933
+\def\frenchspacing{\frenchspacing1128,37041
+\def\splitoff#1#2\endmark{\splitoff1134,37266
+\def\enumerate{\enumerate1140,37496
+\def\enumeratezzz #1{\enumeratezzz1141,37535
+\def\enumeratey #1 #2\endenumeratey{\enumeratey1142,37588
+ \def\thearg{\thearg1146,37735
+ \ifx\thearg\empty \def\thearg{\thearg1147,37754
+\def\numericenumerate{\numericenumerate1184,39088
+\def\lowercaseenumerate{\lowercaseenumerate1190,39218
+\def\uppercaseenumerate{\uppercaseenumerate1203,39565
+\def\startenumeration#1{\startenumeration1219,40055
+\def\alphaenumerate{\alphaenumerate1227,40237
+\def\capsenumerate{\capsenumerate1228,40272
+\def\Ealphaenumerate{\Ealphaenumerate1229,40306
+\def\Ecapsenumerate{\Ecapsenumerate1230,40340
+\def\itemizeitem{\itemizeitem1234,40420
+\def\newindex #1{\newindex1259,41277
+\def\defindex{\defindex1268,41566
+\def\newcodeindex #1{\newcodeindex1272,41674
+\def\defcodeindex{\defcodeindex1279,41934
+\def\synindex #1 #2 {\synindex1283,42114
+\def\syncodeindex #1 #2 {\syncodeindex1292,42454
+\def\doindex#1{\doindex1309,43133
+\def\singleindexer #1{\singleindexer1310,43192
+\def\docodeindex#1{\docodeindex1313,43304
+\def\singlecodeindexer #1{\singlecodeindexer1314,43371
+\def\indexdummies{\indexdummies1316,43429
+\def\_{\_1317,43449
+\def\w{\w1318,43477
+\def\bf{\bf1319,43504
+\def\rm{\rm1320,43533
+\def\sl{\sl1321,43562
+\def\sf{\sf1322,43591
+\def\tt{\tt1323,43619
+\def\gtr{\gtr1324,43647
+\def\less{\less1325,43677
+\def\hat{\hat1326,43709
+\def\char{\char1327,43739
+\def\TeX{\TeX1328,43771
+\def\dots{\dots1329,43801
+\def\copyright{\copyright1330,43834
+\def\tclose##1{\tclose1331,43877
+\def\code##1{\code1332,43922
+\def\samp##1{\samp1333,43963
+\def\t##1{\t1334,44004
+\def\r##1{\r1335,44039
+\def\i##1{\i1336,44074
+\def\b##1{\b1337,44109
+\def\cite##1{\cite1338,44144
+\def\key##1{\key1339,44185
+\def\file##1{\file1340,44224
+\def\var##1{\var1341,44265
+\def\kbd##1{\kbd1342,44304
+\def\indexdummyfont#1{\indexdummyfont1347,44460
+\def\indexdummytex{\indexdummytex1348,44486
+\def\indexdummydots{\indexdummydots1349,44510
+\def\indexnofonts{\indexnofonts1351,44536
+\let\w=\indexdummyfontdummyfont1352,44556
+\let\t=\indexdummyfontdummyfont1353,44579
+\let\r=\indexdummyfontdummyfont1354,44602
+\let\i=\indexdummyfontdummyfont1355,44625
+\let\b=\indexdummyfontdummyfont1356,44648
+\let\emph=\indexdummyfontdummyfont1357,44671
+\let\strong=\indexdummyfontdummyfont1358,44697
+\let\cite=\indexdummyfont=\indexdummyfont1359,44725
+\let\sc=\indexdummyfontdummyfont1360,44751
+\let\tclose=\indexdummyfontdummyfont1364,44923
+\let\code=\indexdummyfontdummyfont1365,44951
+\let\file=\indexdummyfontdummyfont1366,44977
+\let\samp=\indexdummyfontdummyfont1367,45003
+\let\kbd=\indexdummyfontdummyfont1368,45029
+\let\key=\indexdummyfontdummyfont1369,45054
+\let\var=\indexdummyfontdummyfont1370,45079
+\let\TeX=\indexdummytexdummytex1371,45104
+\let\dots=\indexdummydotsdummydots1372,45128
+\let\indexbackslash=0 %overridden during \printindex.backslash=01382,45380
+\def\doind #1#2{\doind1384,45436
+{\indexdummies % Must do this here, since \bf, etc expand at this stagedummies1386,45479
+\def\rawbackslashxx{\rawbackslashxx1389,45619
+{\indexnofontsnofonts1394,45881
+\def\dosubind #1#2#3{\dosubind1405,46192
+{\indexdummies % Must do this here, since \bf, etc expand at this stagedummies1407,46240
+\def\rawbackslashxx{\rawbackslashxx1410,46344
+{\indexnofontsnofonts1414,46498
+\def\findex {\findex1443,47429
+\def\kindex {\kindex1444,47452
+\def\cindex {\cindex1445,47475
+\def\vindex {\vindex1446,47498
+\def\tindex {\tindex1447,47521
+\def\pindex {\pindex1448,47544
+\def\cindexsub {\cindexsub1450,47568
+\def\printindex{\printindex1462,47895
+\def\doprintindex#1{\doprintindex1464,47936
+ \def\indexbackslash{\indexbackslash1481,48421
+ \indexfonts\rm \tolerance=9500 \advance\baselineskip -1ptfonts\rm1482,48460
+\def\initial #1{\initial1517,49532
+\def\entry #1#2{\entry1523,49739
+ \null\nobreak\indexdotfill % Have leaders before the page number.dotfill1540,50386
+\def\indexdotfill{\indexdotfill1549,50714
+\def\primary #1{\primary1552,50820
+\def\secondary #1#2{\secondary1556,50902
+\noindent\hskip\secondaryindent\hbox{#1}\indexdotfill #2\pardotfill1559,50984
+\newbox\partialpageialpage1566,51157
+\def\begindoublecolumns{\begindoublecolumns1572,51315
+ \output={\global\setbox\partialpage=ialpage=1573,51351
+\def\enddoublecolumns{\enddoublecolumns1577,51539
+\def\doublecolumnout{\doublecolumnout1580,51624
+ \dimen@=\pageheight \advance\dimen@ by-\ht\partialpageialpage1581,51693
+\def\pagesofar{\pagesofar1584,51871
+\def\balancecolumns{\balancecolumns1588,52108
+ \availdimen@=\pageheight \advance\availdimen@ by-\ht\partialpageialpage1594,52279
+ \dimen@=\pageheight \advance\dimen@ by-\ht\partialpageialpage1600,52540
+\newcount \appendixno \appendixno = `\@no1627,53445
+\def\appendixletter{\appendixletter1628,53486
+\def\opencontents{\opencontents1632,53589
+\def\thischapter{\thischapter1637,53770
+\def\seccheck#1{\seccheck1638,53808
+\def\chapternofonts{\chapternofonts1643,53912
+\def\result{\result1646,53987
+\def\equiv{\equiv1647,54022
+\def\expansion{\expansion1648,54055
+\def\print{\print1649,54096
+\def\TeX{\TeX1650,54129
+\def\dots{\dots1651,54158
+\def\copyright{\copyright1652,54189
+\def\tt{\tt1653,54230
+\def\bf{\bf1654,54257
+\def\w{\w1655,54285
+\def\less{\less1656,54310
+\def\gtr{\gtr1657,54341
+\def\hat{\hat1658,54370
+\def\char{\char1659,54399
+\def\tclose##1{\tclose1660,54430
+\def\code##1{\code1661,54474
+\def\samp##1{\samp1662,54514
+\def\r##1{\r1663,54554
+\def\b##1{\b1664,54588
+\def\key##1{\key1665,54622
+\def\file##1{\file1666,54660
+\def\kbd##1{\kbd1667,54700
+\def\i##1{\i1669,54808
+\def\cite##1{\cite1670,54842
+\def\var##1{\var1671,54882
+\def\emph##1{\emph1672,54920
+\def\dfn##1{\dfn1673,54960
+\def\thischaptername{\thischaptername1676,55001
+\outer\def\chapter{\chapter1677,55040
+\def\chapterzzz #1{\chapterzzz1678,55081
+{\chapternofonts%nofonts%1687,55477
+\global\let\section = \numberedsec=1692,55630
+\global\let\subsection = \numberedsubsec=1693,55665
+\global\let\subsubsection = \numberedsubsubsec=1694,55706
+\outer\def\appendix{\appendix1697,55757
+\def\appendixzzz #1{\appendixzzz1698,55800
+\global\advance \appendixno by 1 \message{no1700,55877
+\chapmacro {#1}{Appendix \appendixletter}letter1701,55946
+\xdef\thischapter{Appendix \appendixletter: \noexpand\thischaptername}letter:1704,56039
+{\chapternofonts%nofonts%1705,56111
+ {#1}{Appendix \appendixletter}letter1707,56167
+\appendixnoderef %noderef1710,56267
+\global\let\section = \appendixsec=1711,56286
+\global\let\subsection = \appendixsubsec=1712,56321
+\global\let\subsubsection = \appendixsubsubsec=1713,56362
+\outer\def\top{\top1716,56413
+\outer\def\unnumbered{\unnumbered1717,56453
+\def\unnumberedzzz #1{\unnumberedzzz1718,56500
+{\chapternofonts%nofonts%1722,56663
+\global\let\section = \unnumberedsec=1727,56813
+\global\let\subsection = \unnumberedsubsec=1728,56850
+\global\let\subsubsection = \unnumberedsubsubsec=1729,56893
+\outer\def\numberedsec{\numberedsec1732,56946
+\def\seczzz #1{\seczzz1733,56987
+{\chapternofonts%nofonts%1736,57143
+\outer\def\appendixsection{\appendixsection1745,57329
+\outer\def\appendixsec{\appendixsec1746,57386
+\def\appendixsectionzzz #1{\appendixsectionzzz1747,57439
+\gdef\thissection{#1}\secheading {#1}{\appendixletter}letter1749,57551
+{\chapternofonts%nofonts%1750,57619
+{#1}{\appendixletter}letter1752,57675
+\appendixnoderef %noderef1755,57775
+\outer\def\unnumberedsec{\unnumberedsec1759,57815
+\def\unnumberedseczzz #1{\unnumberedseczzz1760,57868
+{\chapternofonts%nofonts%1762,57963
+\outer\def\numberedsubsec{\numberedsubsec1770,58131
+\def\numberedsubseczzz #1{\numberedsubseczzz1771,58186
+{\chapternofonts%nofonts%1774,58365
+\outer\def\appendixsubsec{\appendixsubsec1783,58569
+\def\appendixsubseczzz #1{\appendixsubseczzz1784,58624
+\subsecheading {#1}{\appendixletter}letter1786,58746
+{\chapternofonts%nofonts%1787,58811
+{#1}{\appendixletter}letter1789,58870
+\appendixnoderef %noderef1792,58985
+\outer\def\unnumberedsubsec{\unnumberedsubsec1796,59025
+\def\unnumberedsubseczzz #1{\unnumberedsubseczzz1797,59084
+{\chapternofonts%nofonts%1799,59185
+\outer\def\numberedsubsubsec{\numberedsubsubsec1807,59356
+\def\numberedsubsubseczzz #1{\numberedsubsubseczzz1808,59417
+{\chapternofonts%nofonts%1812,59614
+\outer\def\appendixsubsubsec{\appendixsubsubsec1823,59847
+\def\appendixsubsubseczzz #1{\appendixsubsubseczzz1824,59908
+ {\appendixletter}letter1827,60047
+{\chapternofonts%nofonts%1828,60113
+ {\appendixletter}letter1830,60178
+\appendixnoderef %noderef1834,60312
+\outer\def\unnumberedsubsubsec{\unnumberedsubsubsec1838,60352
+\def\unnumberedsubsubseczzz #1{\unnumberedsubsubseczzz1839,60417
+{\chapternofonts%nofonts%1841,60524
+\def\infotop{\infotop1851,60853
+\def\infounnumbered{\infounnumbered1852,60891
+\def\infounnumberedsec{\infounnumberedsec1853,60936
+\def\infounnumberedsubsec{\infounnumberedsubsec1854,60987
+\def\infounnumberedsubsubsec{\infounnumberedsubsubsec1855,61044
+\def\infoappendix{\infoappendix1857,61108
+\def\infoappendixsec{\infoappendixsec1858,61149
+\def\infoappendixsubsec{\infoappendixsubsec1859,61196
+\def\infoappendixsubsubsec{\infoappendixsubsubsec1860,61249
+\def\infochapter{\infochapter1862,61309
+\def\infosection{\infosection1863,61348
+\def\infosubsection{\infosubsection1864,61387
+\def\infosubsubsection{\infosubsubsection1865,61432
+\global\let\section = \numberedsec=1870,61669
+\global\let\subsection = \numberedsubsec=1871,61704
+\global\let\subsubsection = \numberedsubsubsec=1872,61745
+\def\majorheading{\majorheading1886,62252
+\def\majorheadingzzz #1{\majorheadingzzz1887,62297
+\def\chapheading{\chapheading1893,62530
+\def\chapheadingzzz #1{\chapheadingzzz1894,62573
+\def\heading{\heading1899,62768
+\def\subheading{\subheading1901,62805
+\def\subsubheading{\subsubheading1903,62848
+\def\dobreak#1#2{\dobreak1910,63125
+\def\setchapterstyle #1 {\setchapterstyle1912,63203
+\def\chapbreak{\chapbreak1919,63458
+\def\chappager{\chappager1920,63508
+\def\chapoddpage{\chapoddpage1921,63546
+\def\setchapternewpage #1 {\setchapternewpage1923,63625
+\def\CHAPPAGoff{\CHAPPAGoff1925,63682
+\def\CHAPPAGon{\CHAPPAGon1929,63776
+\global\def\HEADINGSon{\HEADINGSon1932,63867
+\def\CHAPPAGodd{\CHAPPAGodd1934,63909
+\global\def\HEADINGSon{\HEADINGSon1937,64005
+\def\CHAPFplain{\CHAPFplain1941,64059
+\def\chfplain #1#2{\chfplain1945,64151
+\def\unnchfplain #1{\unnchfplain1956,64374
+\def\unnchfopen #1{\unnchfopen1964,64603
+\def\chfopen #1#2{\chfopen1970,64811
+\def\CHAPFopen{\CHAPFopen1975,64955
+\def\subsecheadingbreak{\subsecheadingbreak1982,65173
+\def\secheadingbreak{\secheadingbreak1985,65302
+\def\secheading #1#2#3{\secheading1993,65584
+\def\plainsecheading #1{\plainsecheading1994,65640
+\def\secheadingi #1{\secheadingi1995,65683
+\def\subsecheading #1#2#3#4{\subsecheading2006,66051
+\def\subsecheadingi #1{\subsecheadingi2007,66118
+\def\subsubsecfonts{\subsubsecfonts2014,66415
+\def\subsubsecheading #1#2#3#4#5{\subsubsecheading2017,66538
+\def\subsubsecheadingi #1{\subsubsecheadingi2018,66616
+\def\startcontents#1{\startcontents2032,67088
+ \unnumbchapmacro{#1}\def\thischapter{\thischapter2040,67361
+\outer\def\contents{\contents2049,67720
+\outer\def\summarycontents{\summarycontents2057,67864
+ \def\secentry ##1##2##3##4{\secentry2067,68235
+ \def\unnumbsecentry ##1##2{\unnumbsecentry2068,68270
+ \def\subsecentry ##1##2##3##4##5{\subsecentry2069,68305
+ \def\unnumbsubsecentry ##1##2{\unnumbsubsecentry2070,68346
+ \def\subsubsecentry ##1##2##3##4##5##6{\subsubsecentry2071,68384
+ \def\unnumbsubsubsecentry ##1##2{\unnumbsubsubsecentry2072,68431
+\def\chapentry#1#2#3{\chapentry2085,68865
+\def\shortchapentry#1#2#3{\shortchapentry2088,68982
+ {#2\labelspace #1}space2091,69092
+\def\unnumbchapentry#1#2{\unnumbchapentry2094,69146
+\def\shortunnumberedentry#1#2{\shortunnumberedentry2095,69193
+\def\secentry#1#2#3#4{\secentry2102,69357
+\def\unnumbsecentry#1#2{\unnumbsecentry2103,69416
+\def\subsecentry#1#2#3#4#5{\subsecentry2106,69477
+\def\unnumbsubsecentry#1#2{\unnumbsubsecentry2107,69547
+\def\subsubsecentry#1#2#3#4#5#6{\subsubsecentry2110,69621
+ \dosubsubsecentry{#2.#3.#4.#5\labelspace#1}space2111,69655
+\def\unnumbsubsubsecentry#1#2{\unnumbsubsubsecentry2112,69706
+\def\dochapentry#1#2{\dochapentry2123,70080
+\def\dosecentry#1#2{\dosecentry2138,70685
+\def\dosubsecentry#1#2{\dosubsecentry2145,70863
+\def\dosubsubsecentry#1#2{\dosubsubsecentry2152,71048
+\def\labelspace{\labelspace2160,71299
+\def\dopageno#1{\dopageno2162,71334
+\def\doshortpageno#1{\doshortpageno2163,71360
+\def\chapentryfonts{\chapentryfonts2165,71392
+\def\secentryfonts{\secentryfonts2166,71427
+\def\point{\point2192,72386
+\def\result{\result2194,72407
+\def\expansion{\expansion2195,72480
+\def\print{\print2196,72551
+\def\equiv{\equiv2198,72618
+\def\error{\error2218,73391
+\def\tex{\tex2224,73620
+\def\@{\@2242,74003
+\gdef\sepspaces{\def {\ }}}\2265,74735
+\def\aboveenvbreak{\aboveenvbreak2268,74817
+\def\afterenvbreak{\afterenvbreak2272,74983
+\def\ctl{\ctl2286,75494
+\def\ctr{\ctr2287,75566
+\def\cbl{\cbl2288,75605
+\def\cbr{\cbr2289,75645
+\def\carttop{\carttop2290,75684
+\def\cartbot{\cartbot2293,75792
+\long\def\cartouche{\cartouche2299,75932
+\def\Ecartouche{\Ecartouche2326,76720
+\def\lisp{\lisp2338,76855
+\def\Elisp{\Elisp2348,77202
+\def\next##1{\next2360,77528
+\def\Eexample{\Eexample2364,77570
+\def\Esmallexample{\Esmallexample2367,77617
+\def\smalllispx{\smalllispx2373,77795
+\def\Esmalllisp{\Esmalllisp2383,78149
+\obeyspaces \obeylines \ninett \indexfonts \rawbackslashfonts2396,78505
+\def\next##1{\next2397,78562
+\def\display{\display2401,78642
+\def\Edisplay{\Edisplay2410,78961
+\def\next##1{\next2422,79272
+\def\format{\format2426,79375
+\def\Eformat{\Eformat2434,79671
+\def\next##1{\next2437,79760
+\def\flushleft{\flushleft2441,79812
+\def\Eflushleft{\Eflushleft2451,80183
+\def\next##1{\next2454,80276
+\def\flushright{\flushright2456,80298
+\def\Eflushright{\Eflushright2466,80670
+\def\next##1{\next2470,80801
+\def\quotation{\quotation2474,80859
+\def\Equotation{\Equotation2480,81051
+\def\setdeffont #1 {\setdeffont2493,81449
+\newskip\defbodyindent \defbodyindent=.4inbodyindent2495,81495
+\newskip\defargsindent \defargsindent=50ptargsindent2496,81538
+\newskip\deftypemargin \deftypemargin=12pttypemargin2497,81581
+\newskip\deflastargmargin \deflastargmargin=18ptlastargmargin2498,81624
+\def\activeparens{\activeparens2503,81822
+\def\opnr{\opnr2529,83034
+\def\lbrb{\lbrb2530,83099
+\def\defname #1#2{\defname2536,83300
+\advance\dimen2 by -\defbodyindentbodyindent2540,83418
+\advance\dimen3 by -\defbodyindentbodyindent2542,83472
+\setbox0=\hbox{\hskip \deflastargmargin{lastargmargin2544,83526
+\dimen1=\hsize \advance \dimen1 by -\defargsindent %size for continuationsargsindent2546,83668
+\parshape 2 0in \dimen0 \defargsindent \dimen1 %argsindent2547,83743
+\rlap{\rightline{{\rm #2}\hskip \deftypemargin}typemargin2554,84112
+\advance\leftskip by -\defbodyindentbodyindent2557,84246
+\exdentamount=\defbodyindentbodyindent2558,84283
+\def\defparsebody #1#2#3{\defparsebody2568,84642
+\def#1{2572,84826
+\def#2{2573,84862
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2575,84934
+\exdentamount=\defbodyindentbodyindent2576,85008
+\def\defmethparsebody #1#2#3#4 {\defmethparsebody2581,85112
+\def#1{2585,85273
+\def#2##1 {2586,85309
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2588,85392
+\exdentamount=\defbodyindentbodyindent2589,85466
+\def\defopparsebody #1#2#3#4#5 {\defopparsebody2592,85551
+\def#1{2596,85712
+\def#2##1 ##2 {2597,85748
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2600,85848
+\exdentamount=\defbodyindentbodyindent2601,85922
+\def\defvarparsebody #1#2#3{\defvarparsebody2608,86193
+\def#1{2612,86380
+\def#2{2613,86416
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2615,86475
+\exdentamount=\defbodyindentbodyindent2616,86549
+\def\defvrparsebody #1#2#3#4 {\defvrparsebody2621,86640
+\def#1{2625,86799
+\def#2##1 {2626,86835
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2628,86905
+\exdentamount=\defbodyindentbodyindent2629,86979
+\def\defopvarparsebody #1#2#3#4#5 {\defopvarparsebody2632,87051
+\def#1{2636,87215
+\def#2##1 ##2 {2637,87251
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2640,87338
+\exdentamount=\defbodyindentbodyindent2641,87412
+\def\defunargs #1{\defunargs2664,88172
+\def\deftypefunargs #1{\deftypefunargs2676,88554
+\def\deffn{\deffn2690,88936
+\def\deffnheader #1#2#3{\deffnheader2692,88993
+\begingroup\defname {name2693,89041
+\def\defun{\defun2699,89186
+\def\defunheader #1#2{\defunheader2701,89239
+\begingroup\defname {name2702,89314
+\defunargs {unargs2703,89350
+\def\deftypefun{\deftypefun2709,89498
+\def\deftypefunheader #1#2{\deftypefunheader2712,89620
+\def\deftypefunheaderx #1#2 #3\relax{\deftypefunheaderx2714,89729
+\begingroup\defname {name2716,89821
+\deftypefunargs {typefunargs2717,89867
+\def\deftypefn{\deftypefn2723,90038
+\def\deftypefnheader #1#2#3{\deftypefnheader2726,90187
+\def\deftypefnheaderx #1#2#3 #4\relax{\deftypefnheaderx2728,90323
+\begingroup\defname {name2730,90416
+\deftypefunargs {typefunargs2731,90456
+\def\defmac{\defmac2737,90577
+\def\defmacheader #1#2{\defmacheader2739,90634
+\begingroup\defname {name2740,90710
+\defunargs {unargs2741,90743
+\def\defspec{\defspec2747,90867
+\def\defspecheader #1#2{\defspecheader2749,90928
+\begingroup\defname {name2750,91005
+\defunargs {unargs2751,91045
+\def\deffnx #1 {\deffnx2758,91240
+\def\defunx #1 {\defunx2759,91297
+\def\defmacx #1 {\defmacx2760,91354
+\def\defspecx #1 {\defspecx2761,91413
+\def\deftypefnx #1 {\deftypefnx2762,91474
+\def\deftypeunx #1 {\deftypeunx2763,91539
+\def\defop #1 {\defop2769,91685
+\defopparsebody\Edefop\defopx\defopheader\defoptype}opparsebody\Edefop\defopx\defopheader\defoptype2770,91720
+\def\defopheader #1#2#3{\defopheader2772,91774
+\begingroup\defname {name2774,91863
+\defunargs {unargs2775,91909
+\def\defmethod{\defmethod2780,91970
+\def\defmethodheader #1#2#3{\defmethodheader2782,92043
+\begingroup\defname {name2784,92131
+\defunargs {unargs2785,92171
+\def\defcv #1 {\defcv2790,92245
+\defopvarparsebody\Edefcv\defcvx\defcvarheader\defcvtype}opvarparsebody\Edefcv\defcvx\defcvarheader\defcvtype2791,92280
+\def\defcvarheader #1#2#3{\defcvarheader2793,92339
+\begingroup\defname {name2795,92425
+\defvarargs {varargs2796,92471
+\def\defivar{\defivar2801,92544
+\def\defivarheader #1#2#3{\defivarheader2803,92607
+\begingroup\defname {name2805,92693
+\defvarargs {varargs2806,92744
+\def\defopx #1 {\defopx2812,92893
+\def\defmethodx #1 {\defmethodx2813,92950
+\def\defcvx #1 {\defcvx2814,93015
+\def\defivarx #1 {\defivarx2815,93072
+\def\defvarargs #1{\defvarargs2822,93343
+\def\defvr{\defvr2828,93487
+\def\defvrheader #1#2#3{\defvrheader2830,93542
+\begingroup\defname {name2831,93590
+\def\defvar{\defvar2835,93675
+\def\defvarheader #1#2{\defvarheader2837,93735
+\begingroup\defname {name2838,93806
+\defvarargs {varargs2839,93842
+\def\defopt{\defopt2844,93908
+\def\defoptheader #1#2{\defoptheader2846,93968
+\begingroup\defname {name2847,94039
+\defvarargs {varargs2848,94078
+\def\deftypevar{\deftypevar2853,94135
+\def\deftypevarheader #1#2{\deftypevarheader2856,94251
+\begingroup\defname {name2858,94334
+\def\deftypevr{\deftypevr2865,94508
+\def\deftypevrheader #1#2#3{\deftypevrheader2867,94579
+\begingroup\defname {name2868,94631
+\def\defvrx #1 {\defvrx2876,94868
+\def\defvarx #1 {\defvarx2877,94925
+\def\defoptx #1 {\defoptx2878,94984
+\def\deftypevarx #1 {\deftypevarx2879,95043
+\def\deftypevrx #1 {\deftypevrx2880,95110
+\def\deftpargs #1{\deftpargs2885,95259
+\def\deftp{\deftp2889,95339
+\def\deftpheader #1#2#3{\deftpheader2891,95394
+\begingroup\defname {name2892,95442
+\def\deftpx #1 {\deftpx2897,95601
+\def\setref#1{\setref2908,95922
+\def\unnumbsetref#1{\unnumbsetref2913,96036
+\def\appendixsetref#1{\appendixsetref2918,96143
+\def\pxref#1{\pxref2929,96554
+\def\xref#1{\xref2930,96590
+\def\ref#1{\ref2931,96625
+\def\xrefX[#1,#2,#3,#4,#5,#6]{\xrefX[2932,96655
+\def\printedmanual{\printedmanual2933,96698
+\def\printednodename{\printednodename2934,96736
+\def\printednodename{\printednodename2939,96861
+section ``\printednodename'' in \cite{\printedmanual}\printedmanual2954,97493
+\refx{x2957,97571
+\def\dosetq #1#2{\dosetq2965,97791
+\def\internalsetq #1#2{\internalsetq2973,98049
+\def\Ypagenumber{\Ypagenumber2977,98150
+\def\Ytitle{\Ytitle2979,98176
+\def\Ynothing{\Ynothing2981,98203
+\def\Ysectionnumberandtype{\Ysectionnumberandtype2983,98220
+\def\Yappendixletterandtype{\Yappendixletterandtype2992,98536
+\ifnum\secno=0 Appendix\xreftie'char\the\appendixno{no2993,98566
+\else \ifnum \subsecno=0 Section\xreftie'char\the\appendixno.\the\secno %no.\the\secno2994,98621
+Section\xreftie'char\the\appendixno.\the\secno.\the\subsecno %no.\the\secno.\the\subsecno2996,98725
+Section\xreftie'char\the\appendixno.\the\secno.\the\subsecno.\the\subsubsecno %no.\the\secno.\the\subsecno.\the\subsubsecno2998,98796
+ \def\linenumber{\linenumber3009,99135
+\def\refx#1#2{\refx3015,99319
+\def\xrdef #1#2{\xrdef3037,99945
+\def\readauxfile{\readauxfile3040,100030
+\def\supereject{\supereject3110,101811
+\footstrut\parindent=\defaultparindent\hang\textindent{aultparindent\hang\textindent3131,102496
+\def\openindices{\openindices3139,102682
+\newdimen\defaultparindent \defaultparindent = 15ptaultparindent3151,102907
+\parindent = \defaultparindentaultparindent3152,102959
+\def\smallbook{\smallbook3175,103683
+\global\def\Esmallexample{\Esmallexample3192,104110
+\def\afourpaper{\afourpaper3196,104201
+\def\finalout{\finalout3224,105009
+\def\normaldoublequote{\normaldoublequote3235,105270
+\def\normaltilde{\normaltilde3236,105296
+\def\normalcaret{\normalcaret3237,105316
+\def\normalunderscore{\normalunderscore3238,105336
+\def\normalverticalbar{\normalverticalbar3239,105361
+\def\normalless{\normalless3240,105387
+\def\normalgreater{\normalgreater3241,105406
+\def\normalplus{\normalplus3242,105428
+\def\ifusingtt#1#2{\ifusingtt3253,105920
+\def\activedoublequote{\activedoublequote3261,106248
+\def~{~3264,106334
+\def^{^3267,106395
+\def_{_3270,106434
+\def\_{\_3272,106508
+\def\lvvmode{\lvvmode3279,106845
+\def|{|3282,106895
+\def<{<3285,106958
+\def>{>3288,107015
+\def+{+3290,107053
+\def\turnoffactive{\turnoffactive3296,107214
+\global\def={=3307,107500
+\def\normalbackslash{\normalbackslash3321,107882
+
+merc-src/accumulator.m,3228
+:- interface146,5371
+:- import_module hlds148,5386
+:- import_module univ152,5478
+:- pred accu_transform_proc159,5793
+:- implementation166,6115
+:- import_module libs180,6552
+:- import_module mdbcomp184,6681
+:- import_module parse_tree186,6742
+:- import_module assoc_list194,7013
+:- import_module bool195,7042
+:- import_module int196,7065
+:- import_module io197,7087
+:- import_module list198,7108
+:- import_module map199,7131
+:- import_module maybe200,7153
+:- import_module pair201,7177
+:- import_module require202,7200
+:- import_module set203,7226
+:- import_module solutions204,7248
+:- import_module string205,7276
+:- import_module term206,7301
+:- import_module varset207,7324
+:- type top_level213,7499
+:- type accu_goal_id225,7900
+:- type accu_case228,7964
+:- type accu_goal_store234,8091
+:- type accu_subst238,8216
+:- type accu_warning240,8264
+:- pred generate_warnings334,12550
+:- pred generate_warning342,12895
+:- pred should_attempt_accu_transform365,13886
+:- pred should_attempt_accu_transform_2398,15406
+:- pred accu_standardize440,17390
+:- pred identify_goal_type465,18169
+:- pred is_recursive_case549,21175
+:- type store_info560,21713
+:- func initialize_goal_store570,22060
+:- pred accu_store580,22421
+:- pred identify_recursive_calls601,23288
+:- pred identify_out_and_out_prime626,24397
+:- type accu_sets676,26426
+:- pred accu_stage1689,26978
+:- pred accu_stage1_2727,28348
+:- pred accu_sets_init781,30558
+:- func set_upto796,30985
+:- pred accu_before812,31499
+:- pred accu_assoc835,32478
+:- pred accu_construct862,33713
+:- pred accu_construct_assoc896,35308
+:- pred accu_update938,37070
+:- pred member_lessthan_goalid964,38220
+:- type accu_assoc975,38653
+:- pred accu_is_associative986,39139
+:- pred associativity_assertion1014,40264
+:- pred commutativity_assertion1037,41243
+:- pred accu_is_update1057,41953
+:- pred is_associative_construction1078,42803
+:- type accu_substs1095,43481
+:- type accu_base1103,43745
+:- pred accu_stage21124,44606
+:- pred accu_substs_init1179,46958
+:- pred acc_var_subst_init1194,47574
+:- pred create_new_var1207,48148
+:- pred accu_process_assoc_set1223,48863
+:- pred accu_has_heuristic1297,52082
+:- pred accu_heuristic1304,52337
+:- pred accu_process_update_set1318,52907
+:- pred accu_divide_base_case1380,55845
+:- pred accu_related1412,57147
+:- inst stored_goal_plain_call1444,58416
+:- pred lookup_call1449,58602
+:- pred accu_stage31470,59433
+:- pred acc_proc_info1508,61327
+:- pred acc_pred_info1556,63450
+:- pred accu_create_goal1600,65286
+:- func create_acc_call1621,66401
+:- pred create_orig_goal1634,66988
+:- pred create_acc_goal1662,68158
+:- func create_new_orig_recursive_goals1709,70226
+:- func create_new_recursive_goals1723,70919
+:- func create_new_base_goals1738,71718
+:- pred acc_unification1749,72157
+:- pred accu_top_level1766,72897
+:- pred update_accumulator_pred1856,76291
+:- func accu_rename1876,77254
+:- func base_case_ids1889,77785
+:- func base_case_ids_set1898,78049
+:- func accu_goal_list1905,78270
+:- pred calculate_goal_info1916,78681
+:- func chain_subst1932,79320
+:- pred chain_subst_21938,79483
+:- some [T] pred unravel_univ1956,80061
+:- pragma foreign_export1957,80117
c-src/c.c,76
T f(1,0
@@ -4406,13 +4504,13 @@ yyerror FUN1(286,5948
make_list FUN2(293,6028
#define ERROR 304,6228
yylex FUN0(315,6405
-parse_cell_or_range FUN2(587,11771
-#define CK_ABS_R(671,13213
-#define CK_REL_R(675,13292
-#define CK_ABS_C(680,13421
-#define CK_REL_C(684,13500
-#define MAYBEREL(689,13629
-str_to_col FUN1(847,16830
+parse_cell_or_range FUN2(587,11772
+#define CK_ABS_R(671,13214
+#define CK_REL_R(675,13293
+#define CK_ABS_C(680,13422
+#define CK_REL_C(684,13501
+#define MAYBEREL(689,13630
+str_to_col FUN1(847,16831
y-src/parse.c,520
#define YYBISON 4,64
diff --git a/test/manual/etags/ETAGS.good_4 b/test/manual/etags/ETAGS.good_4
index 460e31b5d96..dc65a09fdc2 100644
--- a/test/manual/etags/ETAGS.good_4
+++ b/test/manual/etags/ETAGS.good_4
@@ -175,7 +175,7 @@ package body Truc.Bidule Truc.Bidule/b138,2153
protected body Bidule Bidule/b139,2181
protected body Machin_T Machin_T/b146,2281
-c-src/abbrev.c,3274
+c-src/abbrev.c,3055
Lisp_Object Vabbrev_table_name_list;43,1429
Lisp_Object Vglobal_abbrev_table;48,1574
Lisp_Object Vfundamental_mode_abbrev_table;52,1685
@@ -186,57 +186,53 @@ Lisp_Object Vabbrev_start_location_buffer;66,2046
Lisp_Object Vlast_abbrev;70,2155
Lisp_Object Vlast_abbrev_text;75,2324
int last_abbrev_point;79,2414
-Lisp_Object Vpre_abbrev_expand_hook,83,2487
-Lisp_Object Vpre_abbrev_expand_hook, Qpre_abbrev_expand_hook;83,2487
-DEFUN ("make-abbrev-table", Fmake_abbrev_table,85,2551
-DEFUN ("make-abbrev-table", Fmake_abbrev_table,make-abbrev-table85,2551
-DEFUN ("clear-abbrev-table", Fclear_abbrev_table,92,2743
-DEFUN ("clear-abbrev-table", Fclear_abbrev_table,clear-abbrev-table92,2743
-DEFUN ("define-abbrev", Fdefine_abbrev,107,3124
-DEFUN ("define-abbrev", Fdefine_abbrev,define-abbrev107,3124
-DEFUN ("define-global-abbrev", Fdefine_global_abbrev,149,4443
-DEFUN ("define-global-abbrev", Fdefine_global_abbrev,define-global-abbrev149,4443
-DEFUN ("define-mode-abbrev", Fdefine_mode_abbrev,160,4814
-DEFUN ("define-mode-abbrev", Fdefine_mode_abbrev,define-mode-abbrev160,4814
-DEFUN ("abbrev-symbol", Fabbrev_symbol,174,5282
-DEFUN ("abbrev-symbol", Fabbrev_symbol,abbrev-symbol174,5282
-DEFUN ("abbrev-expansion", Fabbrev_expansion,202,6246
-DEFUN ("abbrev-expansion", Fabbrev_expansion,abbrev-expansion202,6246
-DEFUN ("expand-abbrev", Fexpand_abbrev,218,6761
-DEFUN ("expand-abbrev", Fexpand_abbrev,expand-abbrev218,6761
-DEFUN ("unexpand-abbrev", Funexpand_abbrev,389,11682
-DEFUN ("unexpand-abbrev", Funexpand_abbrev,unexpand-abbrev389,11682
-write_abbrev 426,12889
-describe_abbrev 445,13324
-DEFUN ("insert-abbrev-table-description", Finsert_abbrev_table_description,466,13839
-DEFUN ("insert-abbrev-table-description", Finsert_abbrev_table_description,insert-abbrev-table-description466,13839
-DEFUN ("define-abbrev-table", Fdefine_abbrev_table,506,14995
-DEFUN ("define-abbrev-table", Fdefine_abbrev_table,define-abbrev-table506,14995
-syms_of_abbrev 540,16072
- DEFVAR_LISP ("abbrev-table-name-list"542,16092
- DEFVAR_LISP ("global-abbrev-table"548,16354
- DEFVAR_LISP ("fundamental-mode-abbrev-table"555,16676
- DEFVAR_LISP ("last-abbrev"561,17018
- DEFVAR_LISP ("last-abbrev-text"564,17141
- DEFVAR_INT ("last-abbrev-location"568,17299
- DEFVAR_LISP ("abbrev-start-location"575,17498
- DEFVAR_LISP ("abbrev-start-location-buffer"581,17775
- DEFVAR_PER_BUFFER ("local-abbrev-table"586,18039
- DEFVAR_BOOL ("abbrevs-changed"589,18182
- DEFVAR_BOOL ("abbrev-all-caps"594,18385
- DEFVAR_LISP ("pre-abbrev-expand-hook"598,18541
- DEFVAR_LISP ("abbrev-table-name-list",\1542,16092
- DEFVAR_LISP ("global-abbrev-table",\1548,16354
- DEFVAR_LISP ("fundamental-mode-abbrev-table",\1555,16676
- DEFVAR_LISP ("last-abbrev",\1561,17018
- DEFVAR_LISP ("last-abbrev-text",\1564,17141
- DEFVAR_INT ("last-abbrev-location",\1568,17299
- DEFVAR_LISP ("abbrev-start-location",\1575,17498
- DEFVAR_LISP ("abbrev-start-location-buffer",\1581,17775
- DEFVAR_PER_BUFFER ("local-abbrev-table",\1586,18039
- DEFVAR_BOOL ("abbrevs-changed",\1589,18182
- DEFVAR_BOOL ("abbrev-all-caps",\1594,18385
- DEFVAR_LISP ("pre-abbrev-expand-hook",\1598,18541
+DEFUN ("make-abbrev-table", Fmake_abbrev_table,82,2440
+DEFUN ("make-abbrev-table", Fmake_abbrev_table,make-abbrev-table82,2440
+DEFUN ("clear-abbrev-table", Fclear_abbrev_table,89,2632
+DEFUN ("clear-abbrev-table", Fclear_abbrev_table,clear-abbrev-table89,2632
+DEFUN ("define-abbrev", Fdefine_abbrev,104,3013
+DEFUN ("define-abbrev", Fdefine_abbrev,define-abbrev104,3013
+DEFUN ("define-global-abbrev", Fdefine_global_abbrev,146,4332
+DEFUN ("define-global-abbrev", Fdefine_global_abbrev,define-global-abbrev146,4332
+DEFUN ("define-mode-abbrev", Fdefine_mode_abbrev,157,4703
+DEFUN ("define-mode-abbrev", Fdefine_mode_abbrev,define-mode-abbrev157,4703
+DEFUN ("abbrev-symbol", Fabbrev_symbol,171,5171
+DEFUN ("abbrev-symbol", Fabbrev_symbol,abbrev-symbol171,5171
+DEFUN ("abbrev-expansion", Fabbrev_expansion,199,6135
+DEFUN ("abbrev-expansion", Fabbrev_expansion,abbrev-expansion199,6135
+DEFUN ("expand-abbrev", Fexpand_abbrev,215,6650
+DEFUN ("expand-abbrev", Fexpand_abbrev,expand-abbrev215,6650
+DEFUN ("unexpand-abbrev", Funexpand_abbrev,383,11495
+DEFUN ("unexpand-abbrev", Funexpand_abbrev,unexpand-abbrev383,11495
+write_abbrev 420,12702
+describe_abbrev 439,13137
+DEFUN ("insert-abbrev-table-description", Finsert_abbrev_table_description,460,13652
+DEFUN ("insert-abbrev-table-description", Finsert_abbrev_table_description,insert-abbrev-table-description460,13652
+DEFUN ("define-abbrev-table", Fdefine_abbrev_table,500,14808
+DEFUN ("define-abbrev-table", Fdefine_abbrev_table,define-abbrev-table500,14808
+syms_of_abbrev 534,15885
+ DEFVAR_LISP ("abbrev-table-name-list"536,15905
+ DEFVAR_LISP ("global-abbrev-table"542,16167
+ DEFVAR_LISP ("fundamental-mode-abbrev-table"549,16489
+ DEFVAR_LISP ("last-abbrev"555,16831
+ DEFVAR_LISP ("last-abbrev-text"558,16954
+ DEFVAR_INT ("last-abbrev-location"562,17112
+ DEFVAR_LISP ("abbrev-start-location"569,17311
+ DEFVAR_LISP ("abbrev-start-location-buffer"575,17588
+ DEFVAR_PER_BUFFER ("local-abbrev-table"580,17852
+ DEFVAR_BOOL ("abbrevs-changed"583,17995
+ DEFVAR_BOOL ("abbrev-all-caps"588,18198
+ DEFVAR_LISP ("abbrev-table-name-list",\1536,15905
+ DEFVAR_LISP ("global-abbrev-table",\1542,16167
+ DEFVAR_LISP ("fundamental-mode-abbrev-table",\1549,16489
+ DEFVAR_LISP ("last-abbrev",\1555,16831
+ DEFVAR_LISP ("last-abbrev-text",\1558,16954
+ DEFVAR_INT ("last-abbrev-location",\1562,17112
+ DEFVAR_LISP ("abbrev-start-location",\1569,17311
+ DEFVAR_LISP ("abbrev-start-location-buffer",\1575,17588
+ DEFVAR_PER_BUFFER ("local-abbrev-table",\1580,17852
+ DEFVAR_BOOL ("abbrevs-changed",\1583,17995
+ DEFVAR_BOOL ("abbrev-all-caps",\1588,18198
c-src/torture.c,197
(*tag1 tag118,452
@@ -259,324 +255,324 @@ struct option73,2795
#define optional_argument 91,3173
c-src/etags.c,10045
-char pot_etags_version[pot_etags_version81,3470
-# undef DEBUG84,3552
-# define DEBUG 85,3567
-# define DEBUG 87,3594
-# define NDEBUG 88,3617
-# define _GNU_SOURCE 94,3705
-# undef MSDOS100,3876
-# undef WINDOWSNT101,3890
-# define WINDOWSNT102,3909
-# undef MSDOS106,3968
-# define MSDOS 107,3982
-# define MSDOS 110,4032
-# define MAXPATHLEN 115,4111
-# undef HAVE_NTGUI116,4141
-# undef DOS_NT117,4160
-# define DOS_NT118,4176
-# undef assert 135,4482
-# define assert(136,4541
-# undef CTAGS146,4857
-# define CTAGS 147,4872
-# define CTAGS 149,4898
-#define streq(152,4927
-#define strcaseeq(153,4996
-#define strneq(154,5075
-#define strncaseeq(155,5151
-#define CHARS 157,5238
-#define CHAR(158,5278
-#define iswhite(159,5329
-#define notinname(160,5394
-#define begtoken(161,5469
-#define intoken(162,5542
-#define endtoken(163,5614
-#define ISALNUM(165,5684
-#define ISALPHA(166,5722
-#define ISDIGIT(167,5760
-#define ISLOWER(168,5798
-#define lowcase(170,5837
-#define xnew(179,6015
-#define xrnew(180,6083
-typedef void Lang_function 182,6164
-} compressor;188,6365
-} language;199,6835
-typedef struct fdesc201,6848
-} fdesc;212,7366
-typedef struct node_st214,7376
-} node;225,7894
-} linebuffer;239,8248
- at_language,245,8344
- at_regexp,246,8393
- at_filename,247,8437
- at_stdin,248,8473
- at_end 249,8516
-} argument;253,8698
-typedef struct regexp256,8758
-} regexp;268,9325
-static void error 311,10780
-# undef STDIN408,15073
-#define STDIN 411,15095
-static compressor compressors[compressors457,17664
-static const char *Ada_suffixes Ada_suffixes473,17907
-static const char Ada_help 475,17977
-static const char *Asm_suffixes Asm_suffixes493,18580
-static const char Asm_help 504,18976
-static const char *default_C_suffixes default_C_suffixes512,19312
-static const char default_C_help 515,19413
-static const char default_C_help 523,19850
-static const char *Cplusplus_suffixes Cplusplus_suffixes535,20460
-static const char Cplusplus_help 540,20658
-static const char *Cjava_suffixes Cjava_suffixes549,21113
-static char Cjava_help 551,21172
-static const char *Cobol_suffixes Cobol_suffixes556,21337
-static char Cobol_help 558,21402
-static const char *Cstar_suffixes Cstar_suffixes562,21543
-static const char *Erlang_suffixes Erlang_suffixes565,21607
-static const char Erlang_help 567,21673
-const char *Forth_suffixes Forth_suffixes571,21799
-static const char Forth_help 573,21857
-static const char *Fortran_suffixes Fortran_suffixes577,22008
-static const char Fortran_help 579,22085
-static const char *HTML_suffixes HTML_suffixes582,22190
-static const char HTML_help 584,22264
-static const char *Lisp_suffixes Lisp_suffixes589,22452
-static const char Lisp_help 591,22556
-static const char *Lua_suffixes Lua_suffixes598,22871
-static const char Lua_help 600,22934
-static const char *Makefile_filenames Makefile_filenames603,23010
-static const char Makefile_help 605,23133
-static const char *Objc_suffixes Objc_suffixes609,23277
-static const char Objc_help 613,23399
-static const char *Pascal_suffixes Pascal_suffixes619,23714
-static const char Pascal_help 621,23778
-static const char *Perl_suffixes Perl_suffixes626,23966
-static const char *Perl_interpreters Perl_interpreters628,24028
-static const char Perl_help 630,24100
-static const char *PHP_suffixes PHP_suffixes637,24451
-static const char PHP_help 639,24523
-static const char *plain_C_suffixes plain_C_suffixes643,24678
-static const char *PS_suffixes PS_suffixes647,24762
-static const char PS_help 649,24848
-static const char *Prolog_suffixes Prolog_suffixes652,24931
-static const char Prolog_help 654,24993
-static const char *Python_suffixes Python_suffixes658,25107
-static const char Python_help 660,25165
-static const char *Scheme_suffixes Scheme_suffixes665,25347
-static const char Scheme_help 667,25460
-static const char *TeX_suffixes TeX_suffixes672,25683
-static const char TeX_help 674,25781
-static const char *Texinfo_suffixes Texinfo_suffixes686,26316
-static const char Texinfo_help 688,26395
-static const char *Yacc_suffixes Yacc_suffixes691,26492
-static const char Yacc_help 693,26606
-static const char auto_help 699,26856
-static const char none_help 703,27020
-static const char no_lang_help 707,27143
-static language lang_names 718,27355
-print_language_names 753,29532
-# define EMACS_NAME 786,30755
-# define VERSION 789,30811
-print_version 792,30869
-# define PRINT_UNDOCUMENTED_OPTIONS_HELP 804,31173
-print_help 808,31250
-main 981,37438
-get_compressor_from_suffix 1319,46217
-get_language_from_langname 1355,47158
-get_language_from_interpreter 1377,47545
-get_language_from_filename 1399,47976
-process_file_name 1433,48834
-process_file 1555,51665
-init 1632,54150
-find_entries 1656,54901
-make_tag 1814,59707
-pfnote 1856,60942
-free_tree 1917,62744
-free_fdesc 1935,63029
-add_node 1955,63472
-invalidate_nodes 2035,65537
-static int number_len 2068,66193
-total_size_of_entries 2087,66694
-put_entries 2107,67154
-#define C_EXT 2193,68995
-#define C_PLAIN 2194,69037
-#define C_PLPL 2195,69070
-#define C_STAR 2196,69104
-#define C_JAVA 2197,69137
-#define C_AUTO 2198,69172
-#define YACC 2199,69242
-enum sym_type2204,69312
- st_none,2206,69328
- st_C_objprot,2207,69339
- st_C_objprot, st_C_objimpl,2207,69339
- st_C_objprot, st_C_objimpl, st_C_objend,2207,69339
- st_C_gnumacro,2208,69382
- st_C_ignore,2209,69399
- st_C_ignore, st_C_attribute,2209,69399
- st_C_javastruct,2210,69430
- st_C_operator,2211,69449
- st_C_class,2212,69466
- st_C_class, st_C_template,2212,69466
- st_C_struct,2213,69495
- st_C_struct, st_C_extern,2213,69495
- st_C_struct, st_C_extern, st_C_enum,2213,69495
- st_C_struct, st_C_extern, st_C_enum, st_C_define,2213,69495
- st_C_struct, st_C_extern, st_C_enum, st_C_define, st_C_typedef2213,69495
-struct C_stab_entry 2271,71278
-hash 2275,71409
-in_word_set 2321,72937
- TOTAL_KEYWORDS 2325,73018
- MIN_WORD_LENGTH 2326,73045
- MAX_WORD_LENGTH 2327,73072
- MIN_HASH_VALUE 2328,73100
- MAX_HASH_VALUE 2329,73126
-C_symtype 2387,74985
-static bool inattribute;2400,75234
- fvnone,2408,75435
- fdefunkey,2409,75466
- fdefunname,2410,75512
- foperator,2411,75556
- fvnameseen,2412,75613
- fstartlist,2413,75666
- finlist,2414,75722
- flistseen,2415,75765
- fignore,2416,75813
- vignore 2417,75856
-} fvdef;2418,75901
-static bool fvextern;2420,75911
- tnone,2428,76089
- tkeyseen,2429,76119
- ttypeseen,2430,76160
- tinbody,2431,76199
- tend,2432,76238
- tignore 2433,76279
-} typdef;2434,76320
- snone,2443,76499
- skeyseen,2445,76575
- stagseen,2446,76620
- scolonseen 2447,76661
-} structdef;2448,76715
-static const char *objtag objtag2453,76809
- dnone,2460,76942
- dsharpseen,2461,76972
- ddefineseen,2462,77025
- dignorerest 2463,77070
-} definedef;2464,77112
- onone,2472,77267
- oprotocol,2473,77297
- oimplementation,2474,77347
- otagseen,2475,77395
- oparenseen,2476,77431
- ocatseen,2477,77486
- oinbody,2478,77525
- omethodsign,2479,77568
- omethodtag,2480,77626
- omethodcolon,2481,77666
- omethodparm,2482,77709
- oignore 2483,77755
-} objdef;2484,77787
-static struct tok2491,77944
-} token;2508,78626
-} cstack;2523,79136
-#define nestlev 2525,79264
-#define instruct 2527,79369
-pushclass_above 2531,79489
-popclass_above 2550,79948
-write_classname 2564,80162
-consider_token 2613,81341
-} lbs[lbs2924,88532
-#define current_lb_is_new 2926,88543
-#define switch_line_buffers(2927,88588
-#define curlb 2929,88641
-#define newlb 2930,88672
-#define curlinepos 2931,88703
-#define newlinepos 2932,88744
-#define plainc 2934,88786
-#define cplpl 2935,88830
-#define cjava 2936,88861
-#define CNL_SAVE_DEFINEDEF(2938,88905
-#define CNL(2947,89117
-make_C_tag 2960,89375
-C_entries 2986,90194
-default_C_entries 3833,110156
-plain_C_entries 3840,110276
-Cplusplus_entries 3847,110364
-Cjava_entries 3854,110460
-Cstar_entries 3861,110550
-Yacc_entries 3868,110642
-#define LOOP_ON_INPUT_LINES(3875,110720
-#define LOOKING_AT(3884,111056
-#define LOOKING_AT_NOCASE(3891,111461
-just_read_file 3901,111861
-F_takeprec 3914,112039
-F_getit 3937,112366
-Fortran_functions 3961,112840
-Ada_getit 4052,114669
-Ada_funcs 4115,116044
-Asm_labels 4228,118582
-Perl_functions 4261,119549
-Python_functions 4357,122057
-PHP_functions 4387,122684
-Cobol_paragraphs 4466,124471
-Makefile_targets 4494,125029
-Pascal_functions 4529,125950
-L_getit 4709,130318
-Lisp_functions 4725,130664
-Lua_functions 4785,131850
-PS_functions 4811,132385
-Forth_words 4841,133053
-Scheme_functions 4877,134092
-static linebuffer *TEX_toktab TEX_toktab4908,134781
-static const char *TEX_defenv TEX_defenv4912,134974
-static char TEX_esc 4920,135261
-static char TEX_opgrp 4921,135289
-static char TEX_clgrp 4922,135318
-TeX_commands 4928,135395
-#define TEX_LESC 4986,136652
-#define TEX_SESC 4987,136674
-TEX_mode 4992,136804
-TEX_decode_env 5026,137509
-Texinfo_nodes 5071,138554
-HTML_labels 5094,139013
-Prolog_functions 5219,142347
-prolog_skip_comment 5255,143128
-prolog_pr 5281,143736
-prolog_atom 5319,144628
-Erlang_functions 5379,145666
-erlang_func 5438,146965
-erlang_attribute 5476,147642
-erlang_atom 5496,148061
-scan_separators 5534,149080
-analyze_regex 5586,150460
-add_regex 5654,152050
-substitute 5767,154797
-free_regexps 5814,155837
-regex_tag_multiline 5836,156291
-nocase_tail 5913,158263
-get_tag 5928,158519
-readline_internal 5959,159455
-readline 6037,161296
-savestr 6230,167243
-savenstr 6240,167473
-skip_spaces 6249,167679
-skip_non_spaces 6258,167833
-skip_name 6267,167983
-fatal 6277,168156
-pfatal 6284,168253
-suggest_asking_for_help 6291,168332
-error 6300,168554
-concat 6313,168846
-etags_getcwd 6329,169259
-relative_filename 6350,169725
-absolute_filename 6389,170751
-absolute_dirname 6453,172416
-filename_is_absolute 6472,172845
-canonicalize_filename 6484,173096
-# define ISUPPER(6491,173235
-linebuffer_init 6514,173656
-linebuffer_setlen 6524,173887
-xmalloc 6536,174148
-xrealloc 6545,174314
+char pot_etags_version[pot_etags_version81,3471
+# undef DEBUG84,3553
+# define DEBUG 85,3568
+# define DEBUG 87,3595
+# define NDEBUG 88,3618
+# define _GNU_SOURCE 94,3706
+# undef MSDOS100,3877
+# undef WINDOWSNT101,3891
+# define WINDOWSNT102,3910
+# undef MSDOS106,3969
+# define MSDOS 107,3983
+# define MSDOS 110,4033
+# define MAXPATHLEN 115,4112
+# undef HAVE_NTGUI116,4142
+# undef DOS_NT117,4161
+# define DOS_NT118,4177
+# undef assert 135,4483
+# define assert(136,4542
+# undef CTAGS146,4858
+# define CTAGS 147,4873
+# define CTAGS 149,4899
+#define streq(152,4928
+#define strcaseeq(153,4997
+#define strneq(154,5076
+#define strncaseeq(155,5152
+#define CHARS 157,5239
+#define CHAR(158,5279
+#define iswhite(159,5330
+#define notinname(160,5395
+#define begtoken(161,5470
+#define intoken(162,5543
+#define endtoken(163,5615
+#define ISALNUM(165,5685
+#define ISALPHA(166,5723
+#define ISDIGIT(167,5761
+#define ISLOWER(168,5799
+#define lowcase(170,5838
+#define xnew(179,6016
+#define xrnew(180,6084
+typedef void Lang_function 182,6165
+} compressor;188,6366
+} language;199,6836
+typedef struct fdesc201,6849
+} fdesc;212,7367
+typedef struct node_st214,7377
+} node;225,7895
+} linebuffer;239,8249
+ at_language,245,8345
+ at_regexp,246,8394
+ at_filename,247,8438
+ at_stdin,248,8474
+ at_end 249,8517
+} argument;253,8699
+typedef struct regexp256,8759
+} regexp;268,9326
+static void error 311,10781
+# undef STDIN408,15074
+#define STDIN 411,15096
+static compressor compressors[compressors457,17665
+static const char *Ada_suffixes Ada_suffixes473,17908
+static const char Ada_help 475,17978
+static const char *Asm_suffixes Asm_suffixes493,18581
+static const char Asm_help 504,18977
+static const char *default_C_suffixes default_C_suffixes512,19313
+static const char default_C_help 515,19414
+static const char default_C_help 523,19851
+static const char *Cplusplus_suffixes Cplusplus_suffixes535,20461
+static const char Cplusplus_help 540,20659
+static const char *Cjava_suffixes Cjava_suffixes549,21114
+static char Cjava_help 551,21173
+static const char *Cobol_suffixes Cobol_suffixes556,21338
+static char Cobol_help 558,21403
+static const char *Cstar_suffixes Cstar_suffixes562,21544
+static const char *Erlang_suffixes Erlang_suffixes565,21608
+static const char Erlang_help 567,21674
+const char *Forth_suffixes Forth_suffixes571,21800
+static const char Forth_help 573,21858
+static const char *Fortran_suffixes Fortran_suffixes577,22009
+static const char Fortran_help 579,22086
+static const char *HTML_suffixes HTML_suffixes582,22191
+static const char HTML_help 584,22265
+static const char *Lisp_suffixes Lisp_suffixes589,22453
+static const char Lisp_help 591,22557
+static const char *Lua_suffixes Lua_suffixes598,22872
+static const char Lua_help 600,22935
+static const char *Makefile_filenames Makefile_filenames603,23011
+static const char Makefile_help 605,23134
+static const char *Objc_suffixes Objc_suffixes609,23278
+static const char Objc_help 613,23400
+static const char *Pascal_suffixes Pascal_suffixes619,23715
+static const char Pascal_help 621,23779
+static const char *Perl_suffixes Perl_suffixes626,23967
+static const char *Perl_interpreters Perl_interpreters628,24029
+static const char Perl_help 630,24101
+static const char *PHP_suffixes PHP_suffixes637,24452
+static const char PHP_help 639,24524
+static const char *plain_C_suffixes plain_C_suffixes643,24679
+static const char *PS_suffixes PS_suffixes647,24763
+static const char PS_help 649,24849
+static const char *Prolog_suffixes Prolog_suffixes652,24932
+static const char Prolog_help 654,24994
+static const char *Python_suffixes Python_suffixes658,25108
+static const char Python_help 660,25166
+static const char *Scheme_suffixes Scheme_suffixes665,25348
+static const char Scheme_help 667,25461
+static const char *TeX_suffixes TeX_suffixes672,25684
+static const char TeX_help 674,25782
+static const char *Texinfo_suffixes Texinfo_suffixes686,26317
+static const char Texinfo_help 688,26396
+static const char *Yacc_suffixes Yacc_suffixes691,26493
+static const char Yacc_help 693,26607
+static const char auto_help 699,26857
+static const char none_help 703,27021
+static const char no_lang_help 707,27144
+static language lang_names 718,27356
+print_language_names 753,29533
+# define EMACS_NAME 786,30756
+# define VERSION 789,30812
+print_version 792,30870
+# define PRINT_UNDOCUMENTED_OPTIONS_HELP 804,31174
+print_help 808,31251
+main 981,37439
+get_compressor_from_suffix 1319,46218
+get_language_from_langname 1355,47159
+get_language_from_interpreter 1377,47546
+get_language_from_filename 1399,47977
+process_file_name 1433,48835
+process_file 1555,51666
+init 1632,54151
+find_entries 1656,54902
+make_tag 1814,59708
+pfnote 1856,60943
+free_tree 1917,62745
+free_fdesc 1935,63030
+add_node 1955,63473
+invalidate_nodes 2035,65538
+static int number_len 2068,66194
+total_size_of_entries 2087,66695
+put_entries 2107,67155
+#define C_EXT 2193,68996
+#define C_PLAIN 2194,69038
+#define C_PLPL 2195,69071
+#define C_STAR 2196,69105
+#define C_JAVA 2197,69138
+#define C_AUTO 2198,69173
+#define YACC 2199,69243
+enum sym_type2204,69313
+ st_none,2206,69329
+ st_C_objprot,2207,69340
+ st_C_objprot, st_C_objimpl,2207,69340
+ st_C_objprot, st_C_objimpl, st_C_objend,2207,69340
+ st_C_gnumacro,2208,69383
+ st_C_ignore,2209,69400
+ st_C_ignore, st_C_attribute,2209,69400
+ st_C_javastruct,2210,69431
+ st_C_operator,2211,69450
+ st_C_class,2212,69467
+ st_C_class, st_C_template,2212,69467
+ st_C_struct,2213,69496
+ st_C_struct, st_C_extern,2213,69496
+ st_C_struct, st_C_extern, st_C_enum,2213,69496
+ st_C_struct, st_C_extern, st_C_enum, st_C_define,2213,69496
+ st_C_struct, st_C_extern, st_C_enum, st_C_define, st_C_typedef2213,69496
+struct C_stab_entry 2271,71279
+hash 2275,71410
+in_word_set 2321,72938
+ TOTAL_KEYWORDS 2325,73019
+ MIN_WORD_LENGTH 2326,73046
+ MAX_WORD_LENGTH 2327,73073
+ MIN_HASH_VALUE 2328,73101
+ MAX_HASH_VALUE 2329,73127
+C_symtype 2387,74986
+static bool inattribute;2400,75235
+ fvnone,2408,75436
+ fdefunkey,2409,75467
+ fdefunname,2410,75513
+ foperator,2411,75557
+ fvnameseen,2412,75614
+ fstartlist,2413,75667
+ finlist,2414,75723
+ flistseen,2415,75766
+ fignore,2416,75814
+ vignore 2417,75857
+} fvdef;2418,75902
+static bool fvextern;2420,75912
+ tnone,2428,76090
+ tkeyseen,2429,76120
+ ttypeseen,2430,76161
+ tinbody,2431,76200
+ tend,2432,76239
+ tignore 2433,76280
+} typdef;2434,76321
+ snone,2443,76500
+ skeyseen,2445,76576
+ stagseen,2446,76621
+ scolonseen 2447,76662
+} structdef;2448,76716
+static const char *objtag objtag2453,76810
+ dnone,2460,76943
+ dsharpseen,2461,76973
+ ddefineseen,2462,77026
+ dignorerest 2463,77071
+} definedef;2464,77113
+ onone,2472,77268
+ oprotocol,2473,77298
+ oimplementation,2474,77348
+ otagseen,2475,77396
+ oparenseen,2476,77432
+ ocatseen,2477,77487
+ oinbody,2478,77526
+ omethodsign,2479,77569
+ omethodtag,2480,77627
+ omethodcolon,2481,77667
+ omethodparm,2482,77710
+ oignore 2483,77756
+} objdef;2484,77788
+static struct tok2491,77945
+} token;2508,78627
+} cstack;2523,79137
+#define nestlev 2525,79265
+#define instruct 2527,79370
+pushclass_above 2531,79490
+popclass_above 2550,79949
+write_classname 2564,80163
+consider_token 2613,81342
+} lbs[lbs2924,88533
+#define current_lb_is_new 2926,88544
+#define switch_line_buffers(2927,88589
+#define curlb 2929,88642
+#define newlb 2930,88673
+#define curlinepos 2931,88704
+#define newlinepos 2932,88745
+#define plainc 2934,88787
+#define cplpl 2935,88831
+#define cjava 2936,88862
+#define CNL_SAVE_DEFINEDEF(2938,88906
+#define CNL(2947,89118
+make_C_tag 2960,89376
+C_entries 2986,90195
+default_C_entries 3833,110157
+plain_C_entries 3840,110277
+Cplusplus_entries 3847,110365
+Cjava_entries 3854,110461
+Cstar_entries 3861,110551
+Yacc_entries 3868,110643
+#define LOOP_ON_INPUT_LINES(3875,110721
+#define LOOKING_AT(3884,111057
+#define LOOKING_AT_NOCASE(3891,111462
+just_read_file 3901,111862
+F_takeprec 3914,112040
+F_getit 3937,112367
+Fortran_functions 3961,112841
+Ada_getit 4052,114670
+Ada_funcs 4115,116045
+Asm_labels 4228,118583
+Perl_functions 4261,119550
+Python_functions 4357,122058
+PHP_functions 4387,122685
+Cobol_paragraphs 4466,124472
+Makefile_targets 4494,125030
+Pascal_functions 4529,125951
+L_getit 4709,130319
+Lisp_functions 4725,130665
+Lua_functions 4785,131851
+PS_functions 4811,132386
+Forth_words 4841,133054
+Scheme_functions 4877,134093
+static linebuffer *TEX_toktab TEX_toktab4908,134782
+static const char *TEX_defenv TEX_defenv4912,134975
+static char TEX_esc 4920,135262
+static char TEX_opgrp 4921,135290
+static char TEX_clgrp 4922,135319
+TeX_commands 4928,135396
+#define TEX_LESC 4986,136653
+#define TEX_SESC 4987,136675
+TEX_mode 4992,136805
+TEX_decode_env 5026,137510
+Texinfo_nodes 5071,138555
+HTML_labels 5094,139014
+Prolog_functions 5219,142348
+prolog_skip_comment 5255,143129
+prolog_pr 5281,143737
+prolog_atom 5319,144629
+Erlang_functions 5379,145667
+erlang_func 5438,146966
+erlang_attribute 5476,147643
+erlang_atom 5496,148062
+scan_separators 5534,149081
+analyze_regex 5586,150461
+add_regex 5654,152051
+substitute 5767,154798
+free_regexps 5814,155838
+regex_tag_multiline 5836,156292
+nocase_tail 5913,158264
+get_tag 5928,158520
+readline_internal 5959,159456
+readline 6037,161297
+savestr 6230,167244
+savenstr 6240,167474
+skip_spaces 6249,167680
+skip_non_spaces 6258,167834
+skip_name 6267,167984
+fatal 6277,168157
+pfatal 6284,168254
+suggest_asking_for_help 6291,168333
+error 6300,168555
+concat 6313,168847
+etags_getcwd 6329,169260
+relative_filename 6350,169726
+absolute_filename 6389,170752
+absolute_dirname 6453,172417
+filename_is_absolute 6472,172846
+canonicalize_filename 6484,173097
+# define ISUPPER(6491,173236
+linebuffer_init 6514,173657
+linebuffer_setlen 6524,173888
+xmalloc 6536,174149
+xrealloc 6545,174315
c-src/exit.c,47
} __libc_atexit;30,1022
@@ -628,1377 +624,1377 @@ pp287,1504
pp3(100,1616
c-src/emacs/src/gmalloc.c,3539
-#define USE_PTHREAD25,1002
-#undef get_current_dir_name33,1126
-#undef malloc64,2110
-#undef realloc65,2124
-#undef calloc66,2139
-#undef free67,2153
-#define malloc 68,2165
-#define realloc 69,2188
-#define calloc 70,2213
-#define aligned_alloc 71,2236
-#define free 72,2273
-#define DUMPED 80,2472
-#define ALLOCATED_BEFORE_DUMPING(81,2507
-extern void *malloc malloc94,2718
-#define INT_BIT 124,3934
-#define BLOCKLOG 125,3977
-#define BLOCKSIZE 126,4018
-#define BLOCKIFY(127,4052
-#define HEAP 131,4215
-#define FINAL_FREE_BLOCKS 135,4391
- } malloc_info;167,5388
-#define BLOCK(176,5620
-#define ADDRESS(177,5682
-struct list186,5939
-struct alignlist196,6153
-#define LOCK(223,7064
-#define UNLOCK(228,7195
-#define LOCK_ALIGNED_BLOCKS(233,7329
-#define UNLOCK_ALIGNED_BLOCKS(238,7484
-#define LOCK(244,7649
-#define UNLOCK(245,7664
-#define LOCK_ALIGNED_BLOCKS(246,7681
-#define UNLOCK_ALIGNED_BLOCKS(247,7711
-enum mcheck_status283,9092
- MCHECK_DISABLED 285,9115
- MCHECK_OK,286,9187
- MCHECK_FREE,287,9226
- MCHECK_HEAD,288,9270
- MCHECK_TAIL 289,9334
-struct mstats308,10153
-char *_heapbase;_heapbase355,11829
-malloc_info *_heapinfo;_heapinfo358,11927
-static size_t heapsize;361,11983
-size_t _heapindex;364,12047
-size_t _heaplimit;367,12109
-struct list _fraghead[_fraghead370,12171
-size_t _chunks_used;373,12229
-size_t _bytes_used;374,12250
-size_t _chunks_free;375,12270
-size_t _bytes_free;376,12291
-int __malloc_initialized;379,12340
-size_t __malloc_extra_blocks;381,12367
-static int state_protected_p;400,12912
-static size_t last_state_size;401,12942
-static malloc_info *last_heapinfo;last_heapinfo402,12973
-protect_malloc_state 405,13014
-#define PROTECT_MALLOC_STATE(426,13627
-#define PROTECT_MALLOC_STATE(429,13697
-align 435,13794
-get_contiguous_space 466,14616
-register_heapinfo 497,15325
-pthread_mutex_t _malloc_mutex 517,15879
-pthread_mutex_t _aligned_blocks_mutex 518,15938
-int _malloc_thread_enabled_p;519,16005
-malloc_atfork_handler_prepare 522,16048
-malloc_atfork_handler_parent 529,16139
-malloc_atfork_handler_child 536,16233
-malloc_enable_thread 544,16375
-malloc_initialize_1 563,16961
-__malloc_initialize 594,17793
-static int morecore_recursing;604,17926
-morecore_nolock 609,18066
-_malloc_internal_nolock 722,21584
-_malloc_internal 920,28102
-malloc 932,28247
-_malloc 961,29140
-_free 967,29196
-_realloc 973,29240
-struct alignlist *_aligned_blocks _aligned_blocks1004,30345
-_free_internal_nolock 1009,30474
-_free_internal 1255,38476
-free 1265,38603
-weak_alias 1277,38799
-#define min(1306,39813
-_realloc_internal_nolock 1319,40309
-_realloc_internal 1435,43563
-realloc 1447,43726
-calloc 1478,44894
-#define __sbrk 1513,46042
-__default_morecore 1525,46511
-aligned_alloc 1557,47522
-memalign 1647,49704
-posix_memalign 1656,49909
-static size_t pagesize;1703,51317
-valloc 1706,51349
-#undef malloc1715,51490
-#undef realloc1716,51504
-#undef calloc1717,51519
-#undef aligned_alloc1718,51533
-#undef free1719,51554
-hybrid_malloc 1736,52083
-hybrid_calloc 1744,52188
-hybrid_free 1752,52319
-hybrid_aligned_alloc 1765,52626
-hybrid_realloc 1780,52984
-hybrid_get_current_dir_name 1811,53797
-#define MAGICWORD 1854,55206
-#define MAGICFREE 1855,55261
-#define MAGICBYTE 1856,55316
-#define MALLOCFLOOD 1857,55348
-#define FREEFLOOD 1858,55382
-struct hdr1860,55415
-checkhdr 1867,55581
-freehook 1891,56022
-mallochook 1927,56804
-reallochook 1944,57143
-mabort 1978,57901
-static int mcheck_used 2012,58586
-mcheck 2015,58619
-mprobe 2035,59138
+#define USE_PTHREAD25,1003
+#undef get_current_dir_name33,1127
+#undef malloc64,2111
+#undef realloc65,2125
+#undef calloc66,2140
+#undef free67,2154
+#define malloc 68,2166
+#define realloc 69,2189
+#define calloc 70,2214
+#define aligned_alloc 71,2237
+#define free 72,2274
+#define DUMPED 80,2473
+#define ALLOCATED_BEFORE_DUMPING(81,2508
+extern void *malloc malloc94,2719
+#define INT_BIT 124,3935
+#define BLOCKLOG 125,3978
+#define BLOCKSIZE 126,4019
+#define BLOCKIFY(127,4053
+#define HEAP 131,4216
+#define FINAL_FREE_BLOCKS 135,4392
+ } malloc_info;167,5389
+#define BLOCK(176,5621
+#define ADDRESS(177,5683
+struct list186,5940
+struct alignlist196,6154
+#define LOCK(223,7065
+#define UNLOCK(228,7196
+#define LOCK_ALIGNED_BLOCKS(233,7330
+#define UNLOCK_ALIGNED_BLOCKS(238,7485
+#define LOCK(244,7650
+#define UNLOCK(245,7665
+#define LOCK_ALIGNED_BLOCKS(246,7682
+#define UNLOCK_ALIGNED_BLOCKS(247,7712
+enum mcheck_status283,9093
+ MCHECK_DISABLED 285,9116
+ MCHECK_OK,286,9188
+ MCHECK_FREE,287,9227
+ MCHECK_HEAD,288,9271
+ MCHECK_TAIL 289,9335
+struct mstats308,10154
+char *_heapbase;_heapbase355,11831
+malloc_info *_heapinfo;_heapinfo358,11929
+static size_t heapsize;361,11985
+size_t _heapindex;364,12049
+size_t _heaplimit;367,12111
+struct list _fraghead[_fraghead370,12173
+size_t _chunks_used;373,12231
+size_t _bytes_used;374,12252
+size_t _chunks_free;375,12272
+size_t _bytes_free;376,12293
+int __malloc_initialized;379,12342
+size_t __malloc_extra_blocks;381,12369
+static int state_protected_p;400,12914
+static size_t last_state_size;401,12944
+static malloc_info *last_heapinfo;last_heapinfo402,12975
+protect_malloc_state 405,13016
+#define PROTECT_MALLOC_STATE(426,13629
+#define PROTECT_MALLOC_STATE(429,13699
+align 435,13796
+get_contiguous_space 466,14618
+register_heapinfo 497,15327
+pthread_mutex_t _malloc_mutex 517,15881
+pthread_mutex_t _aligned_blocks_mutex 518,15940
+int _malloc_thread_enabled_p;519,16007
+malloc_atfork_handler_prepare 522,16050
+malloc_atfork_handler_parent 529,16141
+malloc_atfork_handler_child 536,16235
+malloc_enable_thread 544,16377
+malloc_initialize_1 563,16963
+__malloc_initialize 594,17795
+static int morecore_recursing;604,17928
+morecore_nolock 609,18068
+_malloc_internal_nolock 722,21586
+_malloc_internal 920,28104
+malloc 932,28249
+_malloc 961,29142
+_free 967,29198
+_realloc 973,29242
+struct alignlist *_aligned_blocks _aligned_blocks1004,30348
+_free_internal_nolock 1009,30477
+_free_internal 1255,38479
+free 1265,38606
+weak_alias 1277,38802
+#define min(1306,39817
+_realloc_internal_nolock 1319,40313
+_realloc_internal 1435,43567
+realloc 1447,43730
+calloc 1478,44899
+#define __sbrk 1513,46048
+__default_morecore 1525,46517
+aligned_alloc 1557,47529
+memalign 1647,49711
+posix_memalign 1656,49916
+static size_t pagesize;1703,51325
+valloc 1706,51357
+#undef malloc1715,51498
+#undef realloc1716,51512
+#undef calloc1717,51527
+#undef aligned_alloc1718,51541
+#undef free1719,51562
+hybrid_malloc 1736,52091
+hybrid_calloc 1744,52196
+hybrid_free 1752,52327
+hybrid_aligned_alloc 1765,52634
+hybrid_realloc 1780,52990
+hybrid_get_current_dir_name 1811,53803
+#define MAGICWORD 1854,55213
+#define MAGICFREE 1855,55268
+#define MAGICBYTE 1856,55323
+#define MALLOCFLOOD 1857,55355
+#define FREEFLOOD 1858,55389
+struct hdr1860,55422
+checkhdr 1867,55588
+freehook 1891,56029
+mallochook 1927,56811
+reallochook 1944,57150
+mabort 1978,57908
+static int mcheck_used 2012,58593
+mcheck 2015,58626
+mprobe 2035,59145
c-src/emacs/src/regex.h,3761
-#define _REGEX_H 21,836
-typedef unsigned long reg_syntax_t;43,1577
-#define RE_BACKSLASH_ESCAPE_IN_LISTS 47,1749
-#define RE_BK_PLUS_QM 52,1969
-#define RE_CHAR_CLASSES 58,2298
-#define RE_CONTEXT_INDEP_ANCHORS 72,3032
-#define RE_CONTEXT_INDEP_OPS 80,3458
-#define RE_CONTEXT_INVALID_OPS 84,3658
-#define RE_DOT_NEWLINE 88,3801
-#define RE_DOT_NOT_NULL 92,3937
-#define RE_HAT_LISTS_NOT_NEWLINE 96,4082
-#define RE_INTERVALS 101,4292
-#define RE_LIMITED_OPS 105,4441
-#define RE_NEWLINE_ALT 109,4583
-#define RE_NO_BK_BRACES 114,4773
-#define RE_NO_BK_PARENS 118,4964
-#define RE_NO_BK_REFS 122,5120
-#define RE_NO_BK_VBAR 126,5316
-#define RE_NO_EMPTY_RANGES 132,5610
-#define RE_UNMATCHED_RIGHT_PAREN_ORD 136,5766
-#define RE_NO_POSIX_BACKTRACKING 140,5937
-#define RE_NO_GNU_OPS 144,6133
-#define RE_FRUGAL 147,6253
-#define RE_SHY_GROUPS 150,6360
-#define RE_NO_NEWLINE_ANCHOR 153,6468
-#define RE_DEBUG 161,6884
-#define RE_SYNTAX_EMACS 183,7684
-#define RE_SYNTAX_AWK 186,7780
-#define RE_SYNTAX_GNU_AWK 193,8084
-#define RE_SYNTAX_POSIX_AWK 197,8255
-#define RE_SYNTAX_GREP 201,8393
-#define RE_SYNTAX_EGREP 206,8549
-#define RE_SYNTAX_POSIX_EGREP 212,8765
-#define RE_SYNTAX_ED 216,8910
-#define RE_SYNTAX_SED 218,8954
-#define _RE_SYNTAX_POSIX_COMMON 221,9072
-#define RE_SYNTAX_POSIX_BASIC 225,9215
-#define RE_SYNTAX_POSIX_MINIMAL_BASIC 231,9508
-#define RE_SYNTAX_POSIX_EXTENDED 234,9598
-#define RE_SYNTAX_POSIX_MINIMAL_EXTENDED 242,9967
-# undef RE_DUP_MAX253,10454
-#define RE_DUP_MAX 256,10540
-#define REG_EXTENDED 263,10762
-#define REG_ICASE 267,10886
-#define REG_NEWLINE 272,11070
-#define REG_NOSUB 276,11248
-#define REG_NOTBOL 286,11614
-#define REG_NOTEOL 289,11688
- REG_ENOSYS 297,11859
- REG_NOERROR 300,11941
- REG_NOMATCH,301,11976
- REG_BADPAT,305,12123
- REG_ECOLLATE,306,12162
- REG_ECTYPE,307,12203
- REG_EESCAPE,308,12255
- REG_ESUBREG,309,12298
- REG_EBRACK,310,12345
- REG_EPAREN,311,12391
- REG_EBRACE,312,12436
- REG_BADBR,313,12472
- REG_ERANGE,314,12519
- REG_ESPACE,315,12560
- REG_BADRPT,316,12601
- REG_EEND,319,12693
- REG_ESIZE,320,12728
- REG_ERPAREN,321,12790
- REG_ERANGEX 322,12859
-} reg_errcode_t;323,12911
-# define RE_TRANSLATE_TYPE 332,13273
-struct re_pattern_buffer335,13315
-#define REGS_UNALLOCATED 376,14889
-#define REGS_REALLOCATE 377,14916
-#define REGS_FIXED 378,14942
-typedef struct re_pattern_buffer regex_t;416,16098
-typedef ssize_t regoff_t;423,16492
-struct re_registers428,16652
-# define RE_NREGS 440,16942
-} regmatch_t;451,17317
-# define _Restrict_ 540,20886
-# define _Restrict_ 542,20979
-# define _Restrict_544,21018
-# define _Restrict_arr_ 555,21418
-# define _Restrict_arr_557,21461
-# define CHAR_CLASS_MAX_LENGTH 593,22470
-# define CHAR_CLASS_MAX_LENGTH 597,22648
-typedef wctype_t re_wctype_t;599,22692
-typedef wchar_t re_wchar_t;600,22722
-# define re_wctype 601,22750
-# define re_iswctype 602,22776
-# define re_wctype_to_bit(603,22806
-# define CHAR_CLASS_MAX_LENGTH 605,22844
-# define btowc(606,22906
-typedef enum { RECC_ERROR 609,22953
- RECC_ALNUM,610,22984
- RECC_ALNUM, RECC_ALPHA,610,22984
- RECC_ALNUM, RECC_ALPHA, RECC_WORD,610,22984
- RECC_GRAPH,611,23027
- RECC_GRAPH, RECC_PRINT,611,23027
- RECC_LOWER,612,23059
- RECC_LOWER, RECC_UPPER,612,23059
- RECC_PUNCT,613,23091
- RECC_PUNCT, RECC_CNTRL,613,23091
- RECC_DIGIT,614,23123
- RECC_DIGIT, RECC_XDIGIT,614,23123
- RECC_BLANK,615,23156
- RECC_BLANK, RECC_SPACE,615,23156
- RECC_MULTIBYTE,616,23188
- RECC_MULTIBYTE, RECC_NONASCII,616,23188
- RECC_ASCII,617,23227
- RECC_ASCII, RECC_UNIBYTE617,23227
-} re_wctype_t;618,23260
-typedef int re_wchar_t;623,23387
+#define _REGEX_H 21,837
+typedef unsigned long reg_syntax_t;43,1578
+#define RE_BACKSLASH_ESCAPE_IN_LISTS 47,1750
+#define RE_BK_PLUS_QM 52,1970
+#define RE_CHAR_CLASSES 58,2299
+#define RE_CONTEXT_INDEP_ANCHORS 72,3033
+#define RE_CONTEXT_INDEP_OPS 80,3459
+#define RE_CONTEXT_INVALID_OPS 84,3659
+#define RE_DOT_NEWLINE 88,3802
+#define RE_DOT_NOT_NULL 92,3938
+#define RE_HAT_LISTS_NOT_NEWLINE 96,4083
+#define RE_INTERVALS 101,4293
+#define RE_LIMITED_OPS 105,4442
+#define RE_NEWLINE_ALT 109,4584
+#define RE_NO_BK_BRACES 114,4774
+#define RE_NO_BK_PARENS 118,4965
+#define RE_NO_BK_REFS 122,5121
+#define RE_NO_BK_VBAR 126,5317
+#define RE_NO_EMPTY_RANGES 132,5611
+#define RE_UNMATCHED_RIGHT_PAREN_ORD 136,5767
+#define RE_NO_POSIX_BACKTRACKING 140,5938
+#define RE_NO_GNU_OPS 144,6134
+#define RE_FRUGAL 147,6254
+#define RE_SHY_GROUPS 150,6361
+#define RE_NO_NEWLINE_ANCHOR 153,6469
+#define RE_DEBUG 161,6885
+#define RE_SYNTAX_EMACS 183,7685
+#define RE_SYNTAX_AWK 186,7781
+#define RE_SYNTAX_GNU_AWK 193,8085
+#define RE_SYNTAX_POSIX_AWK 197,8256
+#define RE_SYNTAX_GREP 201,8394
+#define RE_SYNTAX_EGREP 206,8550
+#define RE_SYNTAX_POSIX_EGREP 212,8766
+#define RE_SYNTAX_ED 216,8911
+#define RE_SYNTAX_SED 218,8955
+#define _RE_SYNTAX_POSIX_COMMON 221,9073
+#define RE_SYNTAX_POSIX_BASIC 225,9216
+#define RE_SYNTAX_POSIX_MINIMAL_BASIC 231,9509
+#define RE_SYNTAX_POSIX_EXTENDED 234,9599
+#define RE_SYNTAX_POSIX_MINIMAL_EXTENDED 242,9968
+# undef RE_DUP_MAX253,10455
+#define RE_DUP_MAX 256,10541
+#define REG_EXTENDED 263,10763
+#define REG_ICASE 267,10887
+#define REG_NEWLINE 272,11071
+#define REG_NOSUB 276,11249
+#define REG_NOTBOL 286,11615
+#define REG_NOTEOL 289,11689
+ REG_ENOSYS 297,11860
+ REG_NOERROR 300,11942
+ REG_NOMATCH,301,11977
+ REG_BADPAT,305,12124
+ REG_ECOLLATE,306,12163
+ REG_ECTYPE,307,12204
+ REG_EESCAPE,308,12256
+ REG_ESUBREG,309,12299
+ REG_EBRACK,310,12346
+ REG_EPAREN,311,12392
+ REG_EBRACE,312,12437
+ REG_BADBR,313,12473
+ REG_ERANGE,314,12520
+ REG_ESPACE,315,12561
+ REG_BADRPT,316,12602
+ REG_EEND,319,12694
+ REG_ESIZE,320,12729
+ REG_ERPAREN,321,12791
+ REG_ERANGEX 322,12860
+} reg_errcode_t;323,12912
+# define RE_TRANSLATE_TYPE 332,13274
+struct re_pattern_buffer335,13316
+#define REGS_UNALLOCATED 376,14890
+#define REGS_REALLOCATE 377,14917
+#define REGS_FIXED 378,14943
+typedef struct re_pattern_buffer regex_t;416,16099
+typedef ssize_t regoff_t;423,16493
+struct re_registers428,16653
+# define RE_NREGS 440,16943
+} regmatch_t;451,17318
+# define _Restrict_ 540,20887
+# define _Restrict_ 542,20980
+# define _Restrict_544,21019
+# define _Restrict_arr_ 555,21419
+# define _Restrict_arr_557,21462
+# define CHAR_CLASS_MAX_LENGTH 593,22471
+# define CHAR_CLASS_MAX_LENGTH 597,22649
+typedef wctype_t re_wctype_t;599,22693
+typedef wchar_t re_wchar_t;600,22723
+# define re_wctype 601,22751
+# define re_iswctype 602,22777
+# define re_wctype_to_bit(603,22807
+# define CHAR_CLASS_MAX_LENGTH 605,22845
+# define btowc(606,22907
+typedef enum { RECC_ERROR 609,22954
+ RECC_ALNUM,610,22985
+ RECC_ALNUM, RECC_ALPHA,610,22985
+ RECC_ALNUM, RECC_ALPHA, RECC_WORD,610,22985
+ RECC_GRAPH,611,23028
+ RECC_GRAPH, RECC_PRINT,611,23028
+ RECC_LOWER,612,23060
+ RECC_LOWER, RECC_UPPER,612,23060
+ RECC_PUNCT,613,23092
+ RECC_PUNCT, RECC_CNTRL,613,23092
+ RECC_DIGIT,614,23124
+ RECC_DIGIT, RECC_XDIGIT,614,23124
+ RECC_BLANK,615,23157
+ RECC_BLANK, RECC_SPACE,615,23157
+ RECC_MULTIBYTE,616,23189
+ RECC_MULTIBYTE, RECC_NONASCII,616,23189
+ RECC_ASCII,617,23228
+ RECC_ASCII, RECC_UNIBYTE617,23228
+} re_wctype_t;618,23261
+typedef int re_wchar_t;623,23388
c-src/emacs/src/keyboard.c,22931
-volatile int interrupt_input_blocked;76,1808
-volatile bool pending_signals;80,1944
-#define KBD_BUFFER_SIZE 82,1976
-KBOARD *initial_kboard;initial_kboard84,2006
-KBOARD *current_kboard;current_kboard85,2030
-static KBOARD *all_kboards;all_kboards86,2054
-static bool single_kboard;89,2154
-#define NUM_RECENT_KEYS 91,2182
-static int recent_keys_index;94,2269
-static int total_keys;97,2357
-static Lisp_Object recent_keys;100,2443
-Lisp_Object this_command_keys;107,2777
-ptrdiff_t this_command_key_count;108,2808
-static bool this_command_key_count_reset;112,2922
-static Lisp_Object raw_keybuf;116,3074
-static int raw_keybuf_count;117,3105
-#define GROW_RAW_KEYBUF 119,3135
-static ptrdiff_t this_single_command_key_start;125,3350
-static ptrdiff_t before_command_key_count;129,3498
-static ptrdiff_t before_command_echo_length;130,3541
-sigjmp_buf return_to_command_loop;135,3677
-static Lisp_Object recover_top_level_message;138,3791
-static Lisp_Object regular_top_level_message;143,3930
-static sys_jmp_buf getcjmp;147,4031
-bool waiting_for_input;150,4095
-static bool echoing;154,4186
-static struct kboard *ok_to_echo_at_next_pause;ok_to_echo_at_next_pause159,4328
-struct kboard *echo_kboard;echo_kboard166,4632
-Lisp_Object echo_message_buffer;171,4744
-bool immediate_quit;174,4837
-int quit_char;192,5623
-EMACS_INT command_loop_level;195,5680
-Lisp_Object unread_switch_frame;204,6108
-static ptrdiff_t last_non_minibuf_size;207,6216
-uintmax_t num_input_events;210,6334
-static EMACS_INT last_auto_save;214,6428
-static ptrdiff_t last_point_position;217,6523
-Lisp_Object internal_last_event_frame;228,7028
-static Lisp_Object read_key_sequence_cmd;232,7168
-static Lisp_Object read_key_sequence_remapped;233,7210
-static FILE *dribble;dribble236,7310
-bool input_pending;239,7368
-static bool input_was_pending;287,10022
-static struct input_event kbd_buffer[kbd_buffer291,10107
-static struct input_event *kbd_fetch_ptr;kbd_fetch_ptr297,10386
-static struct input_event * volatile kbd_store_ptr;302,10601
-unsigned timers_run;320,11296
-struct timespec *input_available_clear_time;input_available_clear_time324,11408
-bool interrupt_input;328,11573
-bool interrupts_deferred;331,11671
-static struct timespec timer_idleness_start_time;335,11746
-static struct timespec timer_last_idleness_start_time;340,11916
-#define READABLE_EVENTS_DO_TIMERS_NOW 346,12046
-#define READABLE_EVENTS_FILTER_EVENTS 347,12094
-#define READABLE_EVENTS_IGNORE_SQUEEZABLES 348,12142
-kset_echo_string 392,14088
-kset_kbd_queue 397,14184
-kset_keyboard_translate_table 402,14276
-kset_last_prefix_arg 407,14399
-kset_last_repeatable_command 412,14504
-kset_local_function_key_map 417,14625
-kset_overriding_terminal_local_map 422,14744
-kset_real_last_command 427,14877
-kset_system_key_syms 432,14986
-echo_add_key 443,15249
-echo_char 527,17527
-echo_dash 541,17813
-echo_now 586,19140
-cancel_echoing 635,20614
-echo_length 648,20922
-echo_truncate 660,21253
-add_command_key 672,21582
-recursive_edit_1 697,22406
-record_auto_save 742,23848
-force_auto_save_soon 751,24016
-DEFUN ("recursive-edit", Frecursive_edit,759,24137
-DEFUN ("recursive-edit", Frecursive_edit,recursive-edit759,24137
-recursive_edit_unwind 804,25747
-any_kboard_state 817,26013
-single_kboard_state 838,26665
-not_single_kboard_state 848,26803
-struct kboard_stack858,27065
-static struct kboard_stack *kboard_stack;kboard_stack864,27138
-push_kboard 867,27186
-pop_kboard 879,27375
-temporarily_switch_to_single_kboard 914,28263
-record_single_kboard_state 943,29437
-restore_kboard_configuration 952,29621
-cmd_error 970,30077
-cmd_error_internal 1024,31510
-DEFUN ("command-error-default-function", Fcommand_error_default_function,1043,32030
-DEFUN ("command-error-default-function", Fcommand_error_default_function,command-error-default-function1043,32030
-command_loop 1094,33916
-command_loop_2 1134,35135
-top_level_2 1146,35339
-top_level_1 1152,35417
-DEFUN ("top-level", Ftop_level,1164,35787
-DEFUN ("top-level", Ftop_level,top-level1164,35787
-user_error 1183,36288
-DEFUN ("exit-recursive-edit", Fexit_recursive_edit,1189,36429
-DEFUN ("exit-recursive-edit", Fexit_recursive_edit,exit-recursive-edit1189,36429
-DEFUN ("abort-recursive-edit", Fabort_recursive_edit,1201,36819
-DEFUN ("abort-recursive-edit", Fabort_recursive_edit,abort-recursive-edit1201,36819
-tracking_off 1216,37281
-DEFUN ("internal--track-mouse", Ftrack_mouse,1234,37816
-DEFUN ("internal--track-mouse", Ftrack_mouse,track-mouse1234,37816
-bool ignore_mouse_drag_p;1256,38392
-some_mouse_moved 1259,38441
-Lisp_Object last_undo_boundary;1287,39032
-command_loop_1 1294,39273
-read_menu_command 1649,50889
-adjust_point_for_property 1678,51617
-safe_run_hooks_1 1831,57339
-safe_run_hooks_error 1841,57569
-safe_run_hook_funcall 1878,58576
-safe_run_hooks 1893,59058
-int poll_suppress_count;1908,59397
-static struct atimer *poll_timer;poll_timer1915,59487
-poll_for_input_1 1919,59589
-poll_for_input 1930,59789
-start_polling 1942,60053
-input_polling_used 1979,61091
-stop_polling 1994,61390
-set_poll_suppress_count 2009,61759
-bind_polling_period 2029,62141
-make_ctrl_char 2048,62492
-show_help_echo 2113,64455
-static Lisp_Object help_form_saved_window_configs;2156,65638
-read_char_help_form_unwind 2158,65701
-#define STOP_POLLING 2166,65959
-#define RESUME_POLLING 2170,66084
-read_event_from_main_queue 2175,66229
-read_decoded_event_from_main_queue 2249,68417
-#define MAX_ENCODED_BYTES 2254,68664
-echo_keystrokes_p 2342,71556
-read_char 2376,72848
-record_menu_key 3225,98949
-help_char_p 3258,99674
-record_char 3273,99953
-save_getcjmp 3412,104235
-restore_getcjmp 3418,104326
-readable_events 3430,104697
-int stop_character EXTERNALLY_VISIBLE;3497,106437
-event_to_kboard 3500,106493
-kbd_buffer_nr_stored 3522,107142
-kbd_buffer_store_event 3534,107483
-kbd_buffer_store_event_hold 3550,108025
-kbd_buffer_unget_event 3684,111617
-#define INPUT_EVENT_POS_MAX 3698,112018
-#define INPUT_EVENT_POS_MIN 3701,112147
-position_to_Time 3706,112287
-Time_to_position 3716,112514
-gen_help_event 3738,113171
-kbd_buffer_store_help_event 3756,113611
-discard_mouse_events 3773,113976
-kbd_buffer_events_waiting 3803,114711
-clear_event 3823,115068
-kbd_buffer_get_event 3836,115408
-process_special_events 4258,127881
-swallow_events 4322,129705
-timer_start_idle 4339,130098
-timer_stop_idle 4355,130576
-timer_resume_idle 4363,130720
-struct input_event last_timer_event EXTERNALLY_VISIBLE;4372,130912
-Lisp_Object pending_funcalls;4377,131172
-decode_timer 4381,131293
-timer_check_2 4414,132246
-timer_check 4572,136817
-DEFUN ("current-idle-time", Fcurrent_idle_time,4607,137662
-DEFUN ("current-idle-time", Fcurrent_idle_time,current-idle-time4607,137662
-static Lisp_Object accent_key_syms;4625,138239
-static Lisp_Object func_key_syms;4626,138275
-static Lisp_Object mouse_syms;4627,138309
-static Lisp_Object wheel_syms;4628,138340
-static Lisp_Object drag_n_drop_syms;4629,138371
-static const int lispy_accent_codes[lispy_accent_codes4634,138516
-static const char *const lispy_accent_keys[lispy_accent_keys4741,139878
-#define FUNCTION_KEY_OFFSET 4766,140314
-const char *const lispy_function_keys[lispy_function_keys4768,140347
-static const char *const lispy_multimedia_keys[lispy_multimedia_keys4962,148901
-static const char *const lispy_kana_keys[lispy_kana_keys5026,150135
-#define FUNCTION_KEY_OFFSET 5061,151751
-static const char *const lispy_function_keys[lispy_function_keys5065,151894
-#define ISO_FUNCTION_KEY_OFFSET 5149,154429
-static const char *const iso_lispy_function_keys[iso_lispy_function_keys5151,154469
-static Lisp_Object Vlispy_mouse_stem;5172,155328
-static const char *const lispy_wheel_names[lispy_wheel_names5174,155367
-static const char *const lispy_drag_n_drop_names[lispy_drag_n_drop_names5181,155619
-static short const scroll_bar_parts[scroll_bar_parts5189,155885
-static Lisp_Object button_down_location;5210,156910
-static int last_mouse_button;5215,157065
-static int last_mouse_x;5216,157095
-static int last_mouse_y;5217,157120
-static Time button_down_time;5218,157145
-static int double_click_count;5222,157229
-make_lispy_position 5228,157390
-toolkit_menubar_in_use 5456,163953
-make_scroll_bar_position 5469,164321
-make_lispy_event 5485,164967
-make_lispy_movement 6104,183531
-make_lispy_switch_frame 6131,184262
-make_lispy_focus_in 6137,184369
-make_lispy_focus_out 6145,184495
-parse_modifiers_uncached 6163,184945
-#define SINGLE_LETTER_MOD(6185,185465
-#undef SINGLE_LETTER_MOD6212,185906
-#define MULTI_LETTER_MOD(6214,185932
-#undef MULTI_LETTER_MOD6231,186400
-apply_modifiers_uncached 6273,187574
-static const char *const modifier_names[modifier_names6319,189193
-#define NUM_MOD_NAMES 6325,189399
-static Lisp_Object modifier_symbols;6327,189449
-lispy_modifier_list 6331,189586
-#define KEY_TO_CHAR(6353,190252
-parse_modifiers 6356,190328
-DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,6399,191517
-DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,event-symbol-parse-modifiers6399,191517
-apply_modifiers 6422,192391
-reorder_modifiers 6491,194720
-modify_event_symbol 6536,196528
-DEFUN ("event-convert-list", Fevent_convert_list,6628,199244
-DEFUN ("event-convert-list", Fevent_convert_list,event-convert-list6628,199244
-parse_solitary_modifier 6695,201135
-#define SINGLE_LETTER_MOD(6701,201258
-#define MULTI_LETTER_MOD(6705,201343
-#undef SINGLE_LETTER_MOD6763,202641
-#undef MULTI_LETTER_MOD6764,202666
-lucid_event_type_list_p 6775,202889
-get_input_pending 6814,203960
-record_asynch_buffer_change 6834,204579
-gobble_input 6872,205702
-tty_read_avail_input 6967,208310
-handle_async_input 7149,214039
-process_pending_signals 7165,214359
-unblock_input_to 7177,214645
-unblock_input 7200,215277
-totally_unblock_input 7209,215445
-handle_input_available_signal 7217,215529
-deliver_input_available_signal 7226,215700
-struct user_signal_info7235,215865
-static struct user_signal_info *user_signals user_signals7250,216090
-add_user_signal 7253,216149
-handle_user_signal 7275,216598
-deliver_user_signal 7316,217558
-find_user_signal_name 7322,217659
-store_user_signal_events 7334,217841
-static Lisp_Object menu_bar_one_keymap_changed_items;7363,218416
-static Lisp_Object menu_bar_items_vector;7368,218630
-static int menu_bar_items_index;7369,218672
-static const char *separator_names[separator_names7372,218707
-menu_separator_name_p 7393,219148
-menu_bar_items 7426,219852
-Lisp_Object item_properties;7568,224603
-menu_bar_item 7571,224645
-menu_item_eval_property_1 7647,227175
-eval_dyn 7658,227465
-menu_item_eval_property 7666,227675
-parse_menu_item 7686,228341
-static Lisp_Object tool_bar_items_vector;7965,236336
-static Lisp_Object tool_bar_item_properties;7970,236510
-static int ntool_bar_items;7974,236606
-tool_bar_items 7990,237083
-process_tool_bar_item 8075,239892
-#define PROP(8112,240969
-set_prop 8114,241038
-parse_tool_bar_item 8167,242453
-#undef PROP8379,248844
-init_tool_bar_items 8387,248969
-append_tool_bar_item 8401,249261
-read_char_x_menu_prompt 8443,250771
-read_char_minibuf_menu_prompt 8503,252445
-#define PUSH_C_STR(8527,253014
-follow_key 8726,258553
-active_maps 8733,258695
-typedef struct keyremap8742,259021
-} keyremap;8754,259464
-access_keymap_keyremap 8764,259808
-keyremap_step 8811,261450
-test_undefined 8867,262934
-read_key_sequence 8916,264861
-read_key_sequence_vs 9826,295821
-DEFUN ("read-key-sequence", Fread_key_sequence,9885,297294
-DEFUN ("read-key-sequence", Fread_key_sequence,read-key-sequence9885,297294
-DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,9938,299982
-DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,read-key-sequence-vector9938,299982
-detect_input_pending 9950,300488
-detect_input_pending_ignore_squeezables 9959,300654
-detect_input_pending_run_timers 9967,300870
-clear_input_pending 9985,301362
-requeued_events_pending_p 9997,301732
-DEFUN ("input-pending-p", Finput_pending_p,10002,301813
-DEFUN ("input-pending-p", Finput_pending_p,input-pending-p10002,301813
-DEFUN ("recent-keys", Frecent_keys,10024,302596
-DEFUN ("recent-keys", Frecent_keys,recent-keys10024,302596
-DEFUN ("this-command-keys", Fthis_command_keys,10055,303517
-DEFUN ("this-command-keys", Fthis_command_keys,this-command-keys10055,303517
-DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,10068,303958
-DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,this-command-keys-vector10068,303958
-DEFUN ("this-single-command-keys", Fthis_single_command_keys,10080,304380
-DEFUN ("this-single-command-keys", Fthis_single_command_keys,this-single-command-keys10080,304380
-DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,10096,304955
-DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,this-single-command-raw-keys10096,304955
-DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,10109,305495
-DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,reset-this-command-lengths10109,305495
-DEFUN ("clear-this-command-keys", Fclear_this_command_keys,10136,306510
-DEFUN ("clear-this-command-keys", Fclear_this_command_keys,clear-this-command-keys10136,306510
-DEFUN ("recursion-depth", Frecursion_depth,10158,307069
-DEFUN ("recursion-depth", Frecursion_depth,recursion-depth10158,307069
-DEFUN ("open-dribble-file", Fopen_dribble_file,10169,307406
-DEFUN ("open-dribble-file", Fopen_dribble_file,open-dribble-file10169,307406
-DEFUN ("discard-input", Fdiscard_input,10203,308447
-DEFUN ("discard-input", Fdiscard_input,discard-input10203,308447
-DEFUN ("suspend-emacs", Fsuspend_emacs,10225,308949
-DEFUN ("suspend-emacs", Fsuspend_emacs,suspend-emacs10225,308949
-stuff_buffered_input 10285,311045
-set_waiting_for_input 10323,312016
-clear_waiting_for_input 10337,312390
-handle_interrupt_signal 10351,312754
-deliver_interrupt_signal 10378,313642
-static int volatile force_quit_count;10387,313932
-handle_interrupt 10401,314414
-quit_throw_to_read_char 10541,318711
-DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,10562,319288
-DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,set-input-interrupt-mode10562,319288
-DEFUN ("set-output-flow-control", Fset_output_flow_control,10609,320516
-DEFUN ("set-output-flow-control", Fset_output_flow_control,set-output-flow-control10609,320516
-DEFUN ("set-input-meta-mode", Fset_input_meta_mode,10643,321432
-DEFUN ("set-input-meta-mode", Fset_input_meta_mode,set-input-meta-mode10643,321432
-DEFUN ("set-quit-char", Fset_quit_char,10694,322706
-DEFUN ("set-quit-char", Fset_quit_char,set-quit-char10694,322706
-DEFUN ("set-input-mode", Fset_input_mode,10729,323570
-DEFUN ("set-input-mode", Fset_input_mode,set-input-mode10729,323570
-DEFUN ("current-input-mode", Fcurrent_input_mode,10750,324459
-DEFUN ("current-input-mode", Fcurrent_input_mode,current-input-mode10750,324459
-DEFUN ("posn-at-x-y", Fposn_at_x_y,10787,325837
-DEFUN ("posn-at-x-y", Fposn_at_x_y,posn-at-x-y10787,325837
-DEFUN ("posn-at-point", Fposn_at_point,10824,327060
-DEFUN ("posn-at-point", Fposn_at_point,posn-at-point10824,327060
-init_kboard 10861,328214
-allocate_kboard 10893,329284
-wipe_kboard 10909,329637
-delete_kboard 10917,329751
-init_keyboard 10942,330281
-struct event_head11021,332696
-static const struct event_head head_table[head_table11027,332747
-syms_of_keyboard 11045,333577
- DEFVAR_LISP ("internal--top-level-message"11058,333972
- DEFVAR_LISP ("last-command-event"11312,342173
- DEFVAR_LISP ("last-nonmenu-event"11315,342297
- DEFVAR_LISP ("last-input-event"11321,342636
- DEFVAR_LISP ("unread-command-events"11324,342730
- DEFVAR_LISP ("unread-post-input-method-events"11332,343190
- DEFVAR_LISP ("unread-input-method-events"11338,343529
- DEFVAR_LISP ("meta-prefix-char"11346,343898
- DEFVAR_KBOARD ("last-command"11351,344106
- DEFVAR_KBOARD ("real-last-command"11368,344787
- DEFVAR_KBOARD ("last-repeatable-command"11372,344973
- DEFVAR_LISP ("this-command"11378,345261
- DEFVAR_LISP ("real-this-command"11384,345498
- DEFVAR_LISP ("this-command-keys-shift-translated"11388,345680
- DEFVAR_LISP ("this-original-command"11396,346123
- DEFVAR_INT ("auto-save-interval"11403,346520
- DEFVAR_LISP ("auto-save-timeout"11408,346734
- DEFVAR_LISP ("echo-keystrokes"11415,347079
- DEFVAR_INT ("polling-period"11421,347350
- DEFVAR_LISP ("double-click-time"11428,347693
- DEFVAR_INT ("double-click-fuzz"11435,348029
- DEFVAR_INT ("num-input-keys"11446,348519
- DEFVAR_INT ("num-nonmacro-input-events"11452,348794
- DEFVAR_LISP ("last-event-frame"11457,349032
- DEFVAR_LISP ("tty-erase-char"11463,349311
- DEFVAR_LISP ("help-char"11466,349434
- DEFVAR_LISP ("help-event-list"11472,349717
- DEFVAR_LISP ("help-form"11477,349928
- DEFVAR_LISP ("prefix-help-command"11483,350176
- DEFVAR_LISP ("top-level"11489,350454
- DEFVAR_KBOARD ("keyboard-translate-table"11495,350675
- DEFVAR_BOOL ("cannot-suspend"11511,351488
- DEFVAR_BOOL ("menu-prompting"11516,351715
- DEFVAR_LISP ("menu-prompt-more-char"11526,352145
- DEFVAR_INT ("extra-keyboard-modifiers"11531,352391
- DEFVAR_LISP ("deactivate-mark"11545,353117
- DEFVAR_LISP ("pre-command-hook"11553,353486
- DEFVAR_LISP ("post-command-hook"11560,353841
- DEFVAR_LISP ("echo-area-clear-hook"11568,354204
- DEFVAR_LISP ("lucid-menu-bar-dirty-flag"11574,354419
- DEFVAR_LISP ("menu-bar-final-items"11578,354622
- DEFVAR_LISP ("tool-bar-separator-image-expression"11583,354872
- DEFVAR_KBOARD ("overriding-terminal-local-map"11589,355230
- DEFVAR_LISP ("overriding-local-map"11598,355652
- DEFVAR_LISP ("overriding-local-map-menu-flag"11607,356103
- DEFVAR_LISP ("special-event-map"11613,356442
- DEFVAR_LISP ("track-mouse"11617,356630
- DEFVAR_KBOARD ("system-key-alist"11620,356757
- DEFVAR_KBOARD ("local-function-key-map"11629,357138
- DEFVAR_KBOARD ("input-decode-map"11658,358597
- DEFVAR_LISP ("function-key-map"11675,359385
- DEFVAR_LISP ("key-translation-map"11683,359801
- DEFVAR_LISP ("deferred-action-list"11689,360145
- DEFVAR_LISP ("deferred-action-function"11694,360393
- DEFVAR_LISP ("delayed-warnings-list"11700,360692
- DEFVAR_LISP ("timer-list"11708,361100
- DEFVAR_LISP ("timer-idle-list"11712,361252
- DEFVAR_LISP ("input-method-function"11716,361415
- DEFVAR_LISP ("input-method-previous-message"11737,362384
- DEFVAR_LISP ("show-help-function"11744,362745
- DEFVAR_LISP ("disable-point-adjustment"11749,362977
- DEFVAR_LISP ("global-disable-point-adjustment"11761,363527
- DEFVAR_LISP ("minibuffer-message-timeout"11770,363893
- DEFVAR_LISP ("throw-on-input"11775,364171
- DEFVAR_LISP ("command-error-function"11781,364422
- DEFVAR_LISP ("enable-disabled-menus-and-buttons"11790,364909
- DEFVAR_LISP ("select-active-regions"11798,365236
- DEFVAR_LISP ("saved-region-selection"11807,365628
- DEFVAR_LISP ("selection-inhibit-update-commands"11815,366013
- DEFVAR_LISP ("debug-on-event"11825,366554
-keys_of_keyboard 11841,367115
-mark_kboards 11916,370434
- DEFVAR_LISP ("internal--top-level-message",\111058,333972
- DEFVAR_LISP ("last-command-event",\111312,342173
- DEFVAR_LISP ("last-nonmenu-event",\111315,342297
- DEFVAR_LISP ("last-input-event",\111321,342636
- DEFVAR_LISP ("unread-command-events",\111324,342730
- DEFVAR_LISP ("unread-post-input-method-events",\111332,343190
- DEFVAR_LISP ("unread-input-method-events",\111338,343529
- DEFVAR_LISP ("meta-prefix-char",\111346,343898
- DEFVAR_KBOARD ("last-command",\111351,344106
- DEFVAR_KBOARD ("real-last-command",\111368,344787
- DEFVAR_KBOARD ("last-repeatable-command",\111372,344973
- DEFVAR_LISP ("this-command",\111378,345261
- DEFVAR_LISP ("real-this-command",\111384,345498
- DEFVAR_LISP ("this-command-keys-shift-translated",\111388,345680
- DEFVAR_LISP ("this-original-command",\111396,346123
- DEFVAR_INT ("auto-save-interval",\111403,346520
- DEFVAR_LISP ("auto-save-timeout",\111408,346734
- DEFVAR_LISP ("echo-keystrokes",\111415,347079
- DEFVAR_INT ("polling-period",\111421,347350
- DEFVAR_LISP ("double-click-time",\111428,347693
- DEFVAR_INT ("double-click-fuzz",\111435,348029
- DEFVAR_INT ("num-input-keys",\111446,348519
- DEFVAR_INT ("num-nonmacro-input-events",\111452,348794
- DEFVAR_LISP ("last-event-frame",\111457,349032
- DEFVAR_LISP ("tty-erase-char",\111463,349311
- DEFVAR_LISP ("help-char",\111466,349434
- DEFVAR_LISP ("help-event-list",\111472,349717
- DEFVAR_LISP ("help-form",\111477,349928
- DEFVAR_LISP ("prefix-help-command",\111483,350176
- DEFVAR_LISP ("top-level",\111489,350454
- DEFVAR_KBOARD ("keyboard-translate-table",\111495,350675
- DEFVAR_BOOL ("cannot-suspend",\111511,351488
- DEFVAR_BOOL ("menu-prompting",\111516,351715
- DEFVAR_LISP ("menu-prompt-more-char",\111526,352145
- DEFVAR_INT ("extra-keyboard-modifiers",\111531,352391
- DEFVAR_LISP ("deactivate-mark",\111545,353117
- DEFVAR_LISP ("pre-command-hook",\111553,353486
- DEFVAR_LISP ("post-command-hook",\111560,353841
- DEFVAR_LISP ("echo-area-clear-hook",\111568,354204
- DEFVAR_LISP ("lucid-menu-bar-dirty-flag",\111574,354419
- DEFVAR_LISP ("menu-bar-final-items",\111578,354622
- DEFVAR_LISP ("tool-bar-separator-image-expression",\111583,354872
- DEFVAR_KBOARD ("overriding-terminal-local-map",\111589,355230
- DEFVAR_LISP ("overriding-local-map",\111598,355652
- DEFVAR_LISP ("overriding-local-map-menu-flag",\111607,356103
- DEFVAR_LISP ("special-event-map",\111613,356442
- DEFVAR_LISP ("track-mouse",\111617,356630
- DEFVAR_KBOARD ("system-key-alist",\111620,356757
- DEFVAR_KBOARD ("local-function-key-map",\111629,357138
- DEFVAR_KBOARD ("input-decode-map",\111658,358597
- DEFVAR_LISP ("function-key-map",\111675,359385
- DEFVAR_LISP ("key-translation-map",\111683,359801
- DEFVAR_LISP ("deferred-action-list",\111689,360145
- DEFVAR_LISP ("deferred-action-function",\111694,360393
- DEFVAR_LISP ("delayed-warnings-list",\111700,360692
- DEFVAR_LISP ("timer-list",\111708,361100
- DEFVAR_LISP ("timer-idle-list",\111712,361252
- DEFVAR_LISP ("input-method-function",\111716,361415
- DEFVAR_LISP ("input-method-previous-message",\111737,362384
- DEFVAR_LISP ("show-help-function",\111744,362745
- DEFVAR_LISP ("disable-point-adjustment",\111749,362977
- DEFVAR_LISP ("global-disable-point-adjustment",\111761,363527
- DEFVAR_LISP ("minibuffer-message-timeout",\111770,363893
- DEFVAR_LISP ("throw-on-input",\111775,364171
- DEFVAR_LISP ("command-error-function",\111781,364422
- DEFVAR_LISP ("enable-disabled-menus-and-buttons",\111790,364909
- DEFVAR_LISP ("select-active-regions",\111798,365236
- DEFVAR_LISP ("saved-region-selection",\111807,365628
- DEFVAR_LISP ("selection-inhibit-update-commands",\111815,366013
- DEFVAR_LISP ("debug-on-event",\111825,366554
+volatile int interrupt_input_blocked;76,1809
+volatile bool pending_signals;80,1945
+#define KBD_BUFFER_SIZE 82,1977
+KBOARD *initial_kboard;initial_kboard84,2007
+KBOARD *current_kboard;current_kboard85,2031
+static KBOARD *all_kboards;all_kboards86,2055
+static bool single_kboard;89,2155
+#define NUM_RECENT_KEYS 91,2183
+static int recent_keys_index;94,2270
+static int total_keys;97,2358
+static Lisp_Object recent_keys;100,2444
+Lisp_Object this_command_keys;107,2778
+ptrdiff_t this_command_key_count;108,2809
+static bool this_command_key_count_reset;112,2923
+static Lisp_Object raw_keybuf;116,3075
+static int raw_keybuf_count;117,3106
+#define GROW_RAW_KEYBUF 119,3136
+static ptrdiff_t this_single_command_key_start;125,3351
+static ptrdiff_t before_command_key_count;129,3499
+static ptrdiff_t before_command_echo_length;130,3542
+sigjmp_buf return_to_command_loop;135,3678
+static Lisp_Object recover_top_level_message;138,3792
+static Lisp_Object regular_top_level_message;143,3931
+static sys_jmp_buf getcjmp;147,4032
+bool waiting_for_input;150,4096
+static bool echoing;154,4187
+static struct kboard *ok_to_echo_at_next_pause;ok_to_echo_at_next_pause159,4329
+struct kboard *echo_kboard;echo_kboard166,4633
+Lisp_Object echo_message_buffer;171,4745
+bool immediate_quit;174,4838
+int quit_char;192,5624
+EMACS_INT command_loop_level;195,5681
+Lisp_Object unread_switch_frame;204,6109
+static ptrdiff_t last_non_minibuf_size;207,6217
+uintmax_t num_input_events;210,6335
+static EMACS_INT last_auto_save;214,6429
+static ptrdiff_t last_point_position;217,6524
+Lisp_Object internal_last_event_frame;228,7029
+static Lisp_Object read_key_sequence_cmd;232,7169
+static Lisp_Object read_key_sequence_remapped;233,7211
+static FILE *dribble;dribble236,7311
+bool input_pending;239,7369
+static bool input_was_pending;287,10023
+static struct input_event kbd_buffer[kbd_buffer291,10108
+static struct input_event *kbd_fetch_ptr;kbd_fetch_ptr297,10387
+static struct input_event * volatile kbd_store_ptr;302,10602
+unsigned timers_run;320,11297
+struct timespec *input_available_clear_time;input_available_clear_time324,11409
+bool interrupt_input;328,11574
+bool interrupts_deferred;331,11672
+static struct timespec timer_idleness_start_time;335,11747
+static struct timespec timer_last_idleness_start_time;340,11917
+#define READABLE_EVENTS_DO_TIMERS_NOW 346,12047
+#define READABLE_EVENTS_FILTER_EVENTS 347,12095
+#define READABLE_EVENTS_IGNORE_SQUEEZABLES 348,12143
+kset_echo_string 392,14089
+kset_kbd_queue 397,14185
+kset_keyboard_translate_table 402,14277
+kset_last_prefix_arg 407,14400
+kset_last_repeatable_command 412,14505
+kset_local_function_key_map 417,14626
+kset_overriding_terminal_local_map 422,14745
+kset_real_last_command 427,14878
+kset_system_key_syms 432,14987
+echo_add_key 443,15250
+echo_char 527,17528
+echo_dash 541,17814
+echo_now 586,19141
+cancel_echoing 635,20615
+echo_length 648,20923
+echo_truncate 660,21254
+add_command_key 672,21583
+recursive_edit_1 697,22407
+record_auto_save 742,23849
+force_auto_save_soon 751,24017
+DEFUN ("recursive-edit", Frecursive_edit,759,24138
+DEFUN ("recursive-edit", Frecursive_edit,recursive-edit759,24138
+recursive_edit_unwind 804,25751
+any_kboard_state 817,26017
+single_kboard_state 838,26669
+not_single_kboard_state 848,26807
+struct kboard_stack858,27069
+static struct kboard_stack *kboard_stack;kboard_stack864,27142
+push_kboard 867,27190
+pop_kboard 879,27379
+temporarily_switch_to_single_kboard 914,28267
+record_single_kboard_state 943,29441
+restore_kboard_configuration 952,29625
+cmd_error 970,30081
+cmd_error_internal 1024,31514
+DEFUN ("command-error-default-function", Fcommand_error_default_function,1043,32034
+DEFUN ("command-error-default-function", Fcommand_error_default_function,command-error-default-function1043,32034
+command_loop 1094,33920
+command_loop_2 1134,35139
+top_level_2 1146,35343
+top_level_1 1152,35421
+DEFUN ("top-level", Ftop_level,1164,35791
+DEFUN ("top-level", Ftop_level,top-level1164,35791
+user_error 1183,36292
+DEFUN ("exit-recursive-edit", Fexit_recursive_edit,1189,36433
+DEFUN ("exit-recursive-edit", Fexit_recursive_edit,exit-recursive-edit1189,36433
+DEFUN ("abort-recursive-edit", Fabort_recursive_edit,1201,36823
+DEFUN ("abort-recursive-edit", Fabort_recursive_edit,abort-recursive-edit1201,36823
+tracking_off 1216,37285
+DEFUN ("internal--track-mouse", Ftrack_mouse,1234,37820
+DEFUN ("internal--track-mouse", Ftrack_mouse,track-mouse1234,37820
+bool ignore_mouse_drag_p;1256,38396
+some_mouse_moved 1259,38445
+Lisp_Object last_undo_boundary;1287,39036
+command_loop_1 1294,39277
+read_menu_command 1649,50893
+adjust_point_for_property 1678,51621
+safe_run_hooks_1 1831,57343
+safe_run_hooks_error 1841,57573
+safe_run_hook_funcall 1878,58580
+safe_run_hooks 1893,59062
+int poll_suppress_count;1908,59401
+static struct atimer *poll_timer;poll_timer1915,59491
+poll_for_input_1 1919,59593
+poll_for_input 1930,59793
+start_polling 1942,60057
+input_polling_used 1979,61095
+stop_polling 1994,61394
+set_poll_suppress_count 2009,61763
+bind_polling_period 2029,62145
+make_ctrl_char 2048,62496
+show_help_echo 2113,64459
+static Lisp_Object help_form_saved_window_configs;2156,65642
+read_char_help_form_unwind 2158,65705
+#define STOP_POLLING 2166,65963
+#define RESUME_POLLING 2170,66088
+read_event_from_main_queue 2175,66233
+read_decoded_event_from_main_queue 2249,68421
+#define MAX_ENCODED_BYTES 2254,68668
+echo_keystrokes_p 2342,71560
+read_char 2376,72852
+record_menu_key 3225,98953
+help_char_p 3258,99678
+record_char 3273,99957
+save_getcjmp 3412,104239
+restore_getcjmp 3418,104330
+readable_events 3430,104701
+int stop_character EXTERNALLY_VISIBLE;3497,106441
+event_to_kboard 3500,106497
+kbd_buffer_nr_stored 3522,107146
+kbd_buffer_store_event 3534,107487
+kbd_buffer_store_event_hold 3550,108029
+kbd_buffer_unget_event 3684,111621
+#define INPUT_EVENT_POS_MAX 3698,112022
+#define INPUT_EVENT_POS_MIN 3701,112151
+position_to_Time 3706,112291
+Time_to_position 3716,112518
+gen_help_event 3738,113175
+kbd_buffer_store_help_event 3756,113615
+discard_mouse_events 3773,113980
+kbd_buffer_events_waiting 3803,114715
+clear_event 3823,115072
+kbd_buffer_get_event 3836,115412
+process_special_events 4258,127885
+swallow_events 4322,129709
+timer_start_idle 4339,130102
+timer_stop_idle 4355,130580
+timer_resume_idle 4363,130724
+struct input_event last_timer_event EXTERNALLY_VISIBLE;4372,130916
+Lisp_Object pending_funcalls;4377,131176
+decode_timer 4381,131297
+timer_check_2 4414,132250
+timer_check 4572,136821
+DEFUN ("current-idle-time", Fcurrent_idle_time,4607,137666
+DEFUN ("current-idle-time", Fcurrent_idle_time,current-idle-time4607,137666
+static Lisp_Object accent_key_syms;4625,138243
+static Lisp_Object func_key_syms;4626,138279
+static Lisp_Object mouse_syms;4627,138313
+static Lisp_Object wheel_syms;4628,138344
+static Lisp_Object drag_n_drop_syms;4629,138375
+static const int lispy_accent_codes[lispy_accent_codes4634,138520
+static const char *const lispy_accent_keys[lispy_accent_keys4741,139882
+#define FUNCTION_KEY_OFFSET 4766,140318
+const char *const lispy_function_keys[lispy_function_keys4768,140351
+static const char *const lispy_multimedia_keys[lispy_multimedia_keys4962,148905
+static const char *const lispy_kana_keys[lispy_kana_keys5026,150139
+#define FUNCTION_KEY_OFFSET 5061,151755
+static const char *const lispy_function_keys[lispy_function_keys5065,151898
+#define ISO_FUNCTION_KEY_OFFSET 5149,154433
+static const char *const iso_lispy_function_keys[iso_lispy_function_keys5151,154473
+static Lisp_Object Vlispy_mouse_stem;5172,155332
+static const char *const lispy_wheel_names[lispy_wheel_names5174,155371
+static const char *const lispy_drag_n_drop_names[lispy_drag_n_drop_names5181,155623
+static short const scroll_bar_parts[scroll_bar_parts5189,155889
+static Lisp_Object button_down_location;5210,156914
+static int last_mouse_button;5215,157069
+static int last_mouse_x;5216,157099
+static int last_mouse_y;5217,157124
+static Time button_down_time;5218,157149
+static int double_click_count;5222,157233
+make_lispy_position 5228,157394
+toolkit_menubar_in_use 5456,163957
+make_scroll_bar_position 5469,164325
+make_lispy_event 5485,164971
+make_lispy_movement 6104,183534
+make_lispy_switch_frame 6131,184265
+make_lispy_focus_in 6137,184372
+make_lispy_focus_out 6145,184498
+parse_modifiers_uncached 6163,184948
+#define SINGLE_LETTER_MOD(6185,185468
+#undef SINGLE_LETTER_MOD6212,185909
+#define MULTI_LETTER_MOD(6214,185935
+#undef MULTI_LETTER_MOD6231,186403
+apply_modifiers_uncached 6273,187577
+static const char *const modifier_names[modifier_names6319,189196
+#define NUM_MOD_NAMES 6325,189402
+static Lisp_Object modifier_symbols;6327,189452
+lispy_modifier_list 6331,189589
+#define KEY_TO_CHAR(6353,190255
+parse_modifiers 6356,190331
+DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,6399,191520
+DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,event-symbol-parse-modifiers6399,191520
+apply_modifiers 6422,192394
+reorder_modifiers 6491,194723
+modify_event_symbol 6536,196531
+DEFUN ("event-convert-list", Fevent_convert_list,6628,199247
+DEFUN ("event-convert-list", Fevent_convert_list,event-convert-list6628,199247
+parse_solitary_modifier 6695,201138
+#define SINGLE_LETTER_MOD(6701,201261
+#define MULTI_LETTER_MOD(6705,201346
+#undef SINGLE_LETTER_MOD6763,202644
+#undef MULTI_LETTER_MOD6764,202669
+lucid_event_type_list_p 6775,202892
+get_input_pending 6814,203963
+record_asynch_buffer_change 6834,204582
+gobble_input 6872,205705
+tty_read_avail_input 6967,208313
+handle_async_input 7149,214042
+process_pending_signals 7165,214362
+unblock_input_to 7177,214648
+unblock_input 7200,215280
+totally_unblock_input 7209,215448
+handle_input_available_signal 7217,215532
+deliver_input_available_signal 7226,215703
+struct user_signal_info7235,215868
+static struct user_signal_info *user_signals user_signals7250,216093
+add_user_signal 7253,216152
+handle_user_signal 7275,216601
+deliver_user_signal 7316,217561
+find_user_signal_name 7322,217662
+store_user_signal_events 7334,217844
+static Lisp_Object menu_bar_one_keymap_changed_items;7363,218419
+static Lisp_Object menu_bar_items_vector;7368,218633
+static int menu_bar_items_index;7369,218675
+static const char *separator_names[separator_names7372,218710
+menu_separator_name_p 7393,219151
+menu_bar_items 7426,219855
+Lisp_Object item_properties;7568,224606
+menu_bar_item 7571,224648
+menu_item_eval_property_1 7647,227178
+eval_dyn 7658,227468
+menu_item_eval_property 7666,227678
+parse_menu_item 7686,228344
+static Lisp_Object tool_bar_items_vector;7965,236339
+static Lisp_Object tool_bar_item_properties;7970,236513
+static int ntool_bar_items;7974,236609
+tool_bar_items 7990,237086
+process_tool_bar_item 8075,239895
+#define PROP(8112,240972
+set_prop 8114,241041
+parse_tool_bar_item 8167,242456
+#undef PROP8379,248847
+init_tool_bar_items 8387,248972
+append_tool_bar_item 8401,249264
+read_char_x_menu_prompt 8443,250774
+read_char_minibuf_menu_prompt 8503,252448
+#define PUSH_C_STR(8527,253017
+follow_key 8726,258556
+active_maps 8733,258698
+typedef struct keyremap8742,259024
+} keyremap;8754,259467
+access_keymap_keyremap 8764,259811
+keyremap_step 8811,261453
+test_undefined 8867,262937
+read_key_sequence 8916,264864
+read_key_sequence_vs 9826,295824
+DEFUN ("read-key-sequence", Fread_key_sequence,9885,297297
+DEFUN ("read-key-sequence", Fread_key_sequence,read-key-sequence9885,297297
+DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,9938,299985
+DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,read-key-sequence-vector9938,299985
+detect_input_pending 9950,300491
+detect_input_pending_ignore_squeezables 9959,300657
+detect_input_pending_run_timers 9967,300873
+clear_input_pending 9985,301365
+requeued_events_pending_p 9997,301735
+DEFUN ("input-pending-p", Finput_pending_p,10002,301816
+DEFUN ("input-pending-p", Finput_pending_p,input-pending-p10002,301816
+DEFUN ("recent-keys", Frecent_keys,10024,302599
+DEFUN ("recent-keys", Frecent_keys,recent-keys10024,302599
+DEFUN ("this-command-keys", Fthis_command_keys,10055,303520
+DEFUN ("this-command-keys", Fthis_command_keys,this-command-keys10055,303520
+DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,10068,303961
+DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,this-command-keys-vector10068,303961
+DEFUN ("this-single-command-keys", Fthis_single_command_keys,10080,304383
+DEFUN ("this-single-command-keys", Fthis_single_command_keys,this-single-command-keys10080,304383
+DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,10096,304958
+DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,this-single-command-raw-keys10096,304958
+DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,10109,305498
+DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,reset-this-command-lengths10109,305498
+DEFUN ("clear-this-command-keys", Fclear_this_command_keys,10136,306513
+DEFUN ("clear-this-command-keys", Fclear_this_command_keys,clear-this-command-keys10136,306513
+DEFUN ("recursion-depth", Frecursion_depth,10158,307072
+DEFUN ("recursion-depth", Frecursion_depth,recursion-depth10158,307072
+DEFUN ("open-dribble-file", Fopen_dribble_file,10169,307409
+DEFUN ("open-dribble-file", Fopen_dribble_file,open-dribble-file10169,307409
+DEFUN ("discard-input", Fdiscard_input,10203,308450
+DEFUN ("discard-input", Fdiscard_input,discard-input10203,308450
+DEFUN ("suspend-emacs", Fsuspend_emacs,10225,308952
+DEFUN ("suspend-emacs", Fsuspend_emacs,suspend-emacs10225,308952
+stuff_buffered_input 10285,311048
+set_waiting_for_input 10323,312019
+clear_waiting_for_input 10337,312393
+handle_interrupt_signal 10351,312757
+deliver_interrupt_signal 10378,313645
+static int volatile force_quit_count;10387,313935
+handle_interrupt 10401,314417
+quit_throw_to_read_char 10541,318714
+DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,10562,319291
+DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,set-input-interrupt-mode10562,319291
+DEFUN ("set-output-flow-control", Fset_output_flow_control,10609,320519
+DEFUN ("set-output-flow-control", Fset_output_flow_control,set-output-flow-control10609,320519
+DEFUN ("set-input-meta-mode", Fset_input_meta_mode,10643,321435
+DEFUN ("set-input-meta-mode", Fset_input_meta_mode,set-input-meta-mode10643,321435
+DEFUN ("set-quit-char", Fset_quit_char,10694,322709
+DEFUN ("set-quit-char", Fset_quit_char,set-quit-char10694,322709
+DEFUN ("set-input-mode", Fset_input_mode,10729,323573
+DEFUN ("set-input-mode", Fset_input_mode,set-input-mode10729,323573
+DEFUN ("current-input-mode", Fcurrent_input_mode,10750,324462
+DEFUN ("current-input-mode", Fcurrent_input_mode,current-input-mode10750,324462
+DEFUN ("posn-at-x-y", Fposn_at_x_y,10787,325840
+DEFUN ("posn-at-x-y", Fposn_at_x_y,posn-at-x-y10787,325840
+DEFUN ("posn-at-point", Fposn_at_point,10824,327063
+DEFUN ("posn-at-point", Fposn_at_point,posn-at-point10824,327063
+init_kboard 10861,328217
+allocate_kboard 10893,329287
+wipe_kboard 10909,329640
+delete_kboard 10917,329754
+init_keyboard 10942,330284
+struct event_head11021,332699
+static const struct event_head head_table[head_table11027,332750
+syms_of_keyboard 11045,333580
+ DEFVAR_LISP ("internal--top-level-message"11058,333975
+ DEFVAR_LISP ("last-command-event"11312,342176
+ DEFVAR_LISP ("last-nonmenu-event"11315,342300
+ DEFVAR_LISP ("last-input-event"11321,342639
+ DEFVAR_LISP ("unread-command-events"11324,342733
+ DEFVAR_LISP ("unread-post-input-method-events"11332,343193
+ DEFVAR_LISP ("unread-input-method-events"11338,343532
+ DEFVAR_LISP ("meta-prefix-char"11346,343901
+ DEFVAR_KBOARD ("last-command"11351,344109
+ DEFVAR_KBOARD ("real-last-command"11368,344790
+ DEFVAR_KBOARD ("last-repeatable-command"11372,344976
+ DEFVAR_LISP ("this-command"11378,345264
+ DEFVAR_LISP ("real-this-command"11384,345501
+ DEFVAR_LISP ("this-command-keys-shift-translated"11388,345683
+ DEFVAR_LISP ("this-original-command"11396,346126
+ DEFVAR_INT ("auto-save-interval"11403,346523
+ DEFVAR_LISP ("auto-save-timeout"11408,346737
+ DEFVAR_LISP ("echo-keystrokes"11415,347082
+ DEFVAR_INT ("polling-period"11421,347353
+ DEFVAR_LISP ("double-click-time"11428,347696
+ DEFVAR_INT ("double-click-fuzz"11435,348032
+ DEFVAR_INT ("num-input-keys"11446,348522
+ DEFVAR_INT ("num-nonmacro-input-events"11452,348797
+ DEFVAR_LISP ("last-event-frame"11457,349035
+ DEFVAR_LISP ("tty-erase-char"11463,349314
+ DEFVAR_LISP ("help-char"11466,349437
+ DEFVAR_LISP ("help-event-list"11472,349720
+ DEFVAR_LISP ("help-form"11477,349931
+ DEFVAR_LISP ("prefix-help-command"11483,350179
+ DEFVAR_LISP ("top-level"11489,350457
+ DEFVAR_KBOARD ("keyboard-translate-table"11495,350678
+ DEFVAR_BOOL ("cannot-suspend"11511,351491
+ DEFVAR_BOOL ("menu-prompting"11516,351718
+ DEFVAR_LISP ("menu-prompt-more-char"11526,352148
+ DEFVAR_INT ("extra-keyboard-modifiers"11531,352394
+ DEFVAR_LISP ("deactivate-mark"11545,353120
+ DEFVAR_LISP ("pre-command-hook"11553,353489
+ DEFVAR_LISP ("post-command-hook"11560,353844
+ DEFVAR_LISP ("echo-area-clear-hook"11568,354207
+ DEFVAR_LISP ("lucid-menu-bar-dirty-flag"11574,354422
+ DEFVAR_LISP ("menu-bar-final-items"11578,354625
+ DEFVAR_LISP ("tool-bar-separator-image-expression"11583,354875
+ DEFVAR_KBOARD ("overriding-terminal-local-map"11589,355233
+ DEFVAR_LISP ("overriding-local-map"11598,355655
+ DEFVAR_LISP ("overriding-local-map-menu-flag"11607,356106
+ DEFVAR_LISP ("special-event-map"11613,356445
+ DEFVAR_LISP ("track-mouse"11617,356633
+ DEFVAR_KBOARD ("system-key-alist"11620,356760
+ DEFVAR_KBOARD ("local-function-key-map"11629,357141
+ DEFVAR_KBOARD ("input-decode-map"11658,358600
+ DEFVAR_LISP ("function-key-map"11675,359388
+ DEFVAR_LISP ("key-translation-map"11683,359804
+ DEFVAR_LISP ("deferred-action-list"11689,360148
+ DEFVAR_LISP ("deferred-action-function"11694,360396
+ DEFVAR_LISP ("delayed-warnings-list"11700,360695
+ DEFVAR_LISP ("timer-list"11708,361103
+ DEFVAR_LISP ("timer-idle-list"11712,361255
+ DEFVAR_LISP ("input-method-function"11716,361418
+ DEFVAR_LISP ("input-method-previous-message"11737,362387
+ DEFVAR_LISP ("show-help-function"11744,362748
+ DEFVAR_LISP ("disable-point-adjustment"11749,362980
+ DEFVAR_LISP ("global-disable-point-adjustment"11761,363530
+ DEFVAR_LISP ("minibuffer-message-timeout"11770,363896
+ DEFVAR_LISP ("throw-on-input"11775,364174
+ DEFVAR_LISP ("command-error-function"11781,364425
+ DEFVAR_LISP ("enable-disabled-menus-and-buttons"11790,364912
+ DEFVAR_LISP ("select-active-regions"11798,365239
+ DEFVAR_LISP ("saved-region-selection"11807,365631
+ DEFVAR_LISP ("selection-inhibit-update-commands"11815,366016
+ DEFVAR_LISP ("debug-on-event"11825,366557
+keys_of_keyboard 11841,367118
+mark_kboards 11916,370437
+ DEFVAR_LISP ("internal--top-level-message",\111058,333975
+ DEFVAR_LISP ("last-command-event",\111312,342176
+ DEFVAR_LISP ("last-nonmenu-event",\111315,342300
+ DEFVAR_LISP ("last-input-event",\111321,342639
+ DEFVAR_LISP ("unread-command-events",\111324,342733
+ DEFVAR_LISP ("unread-post-input-method-events",\111332,343193
+ DEFVAR_LISP ("unread-input-method-events",\111338,343532
+ DEFVAR_LISP ("meta-prefix-char",\111346,343901
+ DEFVAR_KBOARD ("last-command",\111351,344109
+ DEFVAR_KBOARD ("real-last-command",\111368,344790
+ DEFVAR_KBOARD ("last-repeatable-command",\111372,344976
+ DEFVAR_LISP ("this-command",\111378,345264
+ DEFVAR_LISP ("real-this-command",\111384,345501
+ DEFVAR_LISP ("this-command-keys-shift-translated",\111388,345683
+ DEFVAR_LISP ("this-original-command",\111396,346126
+ DEFVAR_INT ("auto-save-interval",\111403,346523
+ DEFVAR_LISP ("auto-save-timeout",\111408,346737
+ DEFVAR_LISP ("echo-keystrokes",\111415,347082
+ DEFVAR_INT ("polling-period",\111421,347353
+ DEFVAR_LISP ("double-click-time",\111428,347696
+ DEFVAR_INT ("double-click-fuzz",\111435,348032
+ DEFVAR_INT ("num-input-keys",\111446,348522
+ DEFVAR_INT ("num-nonmacro-input-events",\111452,348797
+ DEFVAR_LISP ("last-event-frame",\111457,349035
+ DEFVAR_LISP ("tty-erase-char",\111463,349314
+ DEFVAR_LISP ("help-char",\111466,349437
+ DEFVAR_LISP ("help-event-list",\111472,349720
+ DEFVAR_LISP ("help-form",\111477,349931
+ DEFVAR_LISP ("prefix-help-command",\111483,350179
+ DEFVAR_LISP ("top-level",\111489,350457
+ DEFVAR_KBOARD ("keyboard-translate-table",\111495,350678
+ DEFVAR_BOOL ("cannot-suspend",\111511,351491
+ DEFVAR_BOOL ("menu-prompting",\111516,351718
+ DEFVAR_LISP ("menu-prompt-more-char",\111526,352148
+ DEFVAR_INT ("extra-keyboard-modifiers",\111531,352394
+ DEFVAR_LISP ("deactivate-mark",\111545,353120
+ DEFVAR_LISP ("pre-command-hook",\111553,353489
+ DEFVAR_LISP ("post-command-hook",\111560,353844
+ DEFVAR_LISP ("echo-area-clear-hook",\111568,354207
+ DEFVAR_LISP ("lucid-menu-bar-dirty-flag",\111574,354422
+ DEFVAR_LISP ("menu-bar-final-items",\111578,354625
+ DEFVAR_LISP ("tool-bar-separator-image-expression",\111583,354875
+ DEFVAR_KBOARD ("overriding-terminal-local-map",\111589,355233
+ DEFVAR_LISP ("overriding-local-map",\111598,355655
+ DEFVAR_LISP ("overriding-local-map-menu-flag",\111607,356106
+ DEFVAR_LISP ("special-event-map",\111613,356445
+ DEFVAR_LISP ("track-mouse",\111617,356633
+ DEFVAR_KBOARD ("system-key-alist",\111620,356760
+ DEFVAR_KBOARD ("local-function-key-map",\111629,357141
+ DEFVAR_KBOARD ("input-decode-map",\111658,358600
+ DEFVAR_LISP ("function-key-map",\111675,359388
+ DEFVAR_LISP ("key-translation-map",\111683,359804
+ DEFVAR_LISP ("deferred-action-list",\111689,360148
+ DEFVAR_LISP ("deferred-action-function",\111694,360396
+ DEFVAR_LISP ("delayed-warnings-list",\111700,360695
+ DEFVAR_LISP ("timer-list",\111708,361103
+ DEFVAR_LISP ("timer-idle-list",\111712,361255
+ DEFVAR_LISP ("input-method-function",\111716,361418
+ DEFVAR_LISP ("input-method-previous-message",\111737,362387
+ DEFVAR_LISP ("show-help-function",\111744,362748
+ DEFVAR_LISP ("disable-point-adjustment",\111749,362980
+ DEFVAR_LISP ("global-disable-point-adjustment",\111761,363530
+ DEFVAR_LISP ("minibuffer-message-timeout",\111770,363896
+ DEFVAR_LISP ("throw-on-input",\111775,364174
+ DEFVAR_LISP ("command-error-function",\111781,364425
+ DEFVAR_LISP ("enable-disabled-menus-and-buttons",\111790,364912
+ DEFVAR_LISP ("select-active-regions",\111798,365239
+ DEFVAR_LISP ("saved-region-selection",\111807,365631
+ DEFVAR_LISP ("selection-inhibit-update-commands",\111815,366016
+ DEFVAR_LISP ("debug-on-event",\111825,366557
c-src/emacs/src/lisp.h,20276
-#define EMACS_LISP_H22,800
-#define DECLARE_GDB_SYM(47,1421
-# define DEFINE_GDB_SYMBOL_BEGIN(49,1508
-# define DEFINE_GDB_SYMBOL_END(50,1578
-# define DEFINE_GDB_SYMBOL_BEGIN(52,1625
-# define DEFINE_GDB_SYMBOL_END(53,1702
-#undef min57,1790
-#undef max58,1801
-#define max(59,1812
-#define min(60,1854
-#define ARRAYELTS(63,1936
-#define GCTYPEBITS 67,2079
-DEFINE_GDB_SYMBOL_BEGIN GCTYPEBITS66,2037
-# define NONPOINTER_BITS 78,2567
-# define NONPOINTER_BITS 80,2600
-typedef int EMACS_INT;91,3023
-typedef unsigned int EMACS_UINT;92,3046
-# define EMACS_INT_MAX 93,3079
-# define pI 94,3111
-typedef long int EMACS_INT;96,3203
-typedef unsigned long EMACS_UINT;97,3231
-# define EMACS_INT_MAX 98,3265
-# define pI 99,3298
-typedef long long int EMACS_INT;103,3477
-typedef unsigned long long int EMACS_UINT;104,3510
-# define EMACS_INT_MAX 105,3553
-# define pI 106,3587
-enum { BOOL_VECTOR_BITS_PER_CHAR 114,3804
-#define BOOL_VECTOR_BITS_PER_CHAR 115,3840
-typedef size_t bits_word;123,4165
-# define BITS_WORD_MAX 124,4191
-enum { BITS_PER_BITS_WORD 125,4223
-typedef unsigned char bits_word;127,4290
-# define BITS_WORD_MAX 128,4323
-enum { BITS_PER_BITS_WORD 129,4386
- BITS_PER_CHAR 136,4570
- BITS_PER_SHORT 137,4605
- BITS_PER_LONG 138,4657
- BITS_PER_EMACS_INT 139,4712
-typedef intmax_t printmax_t;148,5089
-typedef uintmax_t uprintmax_t;149,5118
-# define pMd 150,5149
-# define pMu 151,5170
-typedef EMACS_INT printmax_t;153,5197
-typedef EMACS_UINT uprintmax_t;154,5227
-# define pMd 155,5259
-# define pMu 156,5278
-# define pD 165,5664
-# define pD 167,5709
-# define pD 169,5756
-# define pD 171,5779
-# define eassert(200,7062
-# define eassume(201,7140
-# define eassert(208,7319
-# define eassume(212,7450
-enum Lisp_Bits239,8519
-#define GCALIGNMENT 243,8647
- VALBITS 246,8742
- INTTYPEBITS 249,8838
- FIXNUM_BITS 252,8945
-#define VAL_MAX 263,9327
-#define USE_LSB_TAG 271,9777
-DEFINE_GDB_SYMBOL_BEGIN USE_LSB_TAG270,9733
-# define alignas(281,10077
-# define GCALIGNED 288,10227
-# define GCALIGNED 290,10292
-# define lisp_h_XLI(327,11642
-# define lisp_h_XIL(328,11673
-# define lisp_h_XLI(330,11724
-# define lisp_h_XIL(331,11751
-#define lisp_h_CHECK_LIST_CONS(333,11785
-#define lisp_h_CHECK_NUMBER(334,11856
-#define lisp_h_CHECK_SYMBOL(335,11927
-#define lisp_h_CHECK_TYPE(336,11996
-#define lisp_h_CONSP(338,12107
-#define lisp_h_EQ(339,12156
-#define lisp_h_FLOATP(340,12201
-#define lisp_h_INTEGERP(341,12252
-#define lisp_h_MARKERP(342,12333
-#define lisp_h_MISCP(343,12408
-#define lisp_h_NILP(344,12457
-#define lisp_h_SET_SYMBOL_VAL(345,12493
-#define lisp_h_SYMBOL_CONSTANT_P(347,12607
-#define lisp_h_SYMBOL_VAL(348,12671
-#define lisp_h_SYMBOLP(350,12772
-#define lisp_h_VECTORLIKEP(351,12825
-#define lisp_h_XCAR(352,12886
-#define lisp_h_XCDR(353,12924
-#define lisp_h_XCONS(354,12964
-#define lisp_h_XHASH(356,13059
-#define lisp_h_XPNTR(357,13093
-# define lisp_h_check_cons_list(360,13221
-# define lisp_h_make_number(363,13289
-# define lisp_h_XFASTINT(365,13392
-# define lisp_h_XINT(366,13429
-# define lisp_h_XSYMBOL(367,13478
-# define lisp_h_XTYPE(371,13631
-# define lisp_h_XUNTAG(372,13696
-# define XLI(381,14086
-# define XIL(382,14117
-# define CHECK_LIST_CONS(383,14148
-# define CHECK_NUMBER(384,14209
-# define CHECK_SYMBOL(385,14258
-# define CHECK_TYPE(386,14307
-# define CONSP(387,14382
-# define EQ(388,14417
-# define FLOATP(389,14452
-# define INTEGERP(390,14489
-# define MARKERP(391,14530
-# define MISCP(392,14569
-# define NILP(393,14604
-# define SET_SYMBOL_VAL(394,14637
-# define SYMBOL_CONSTANT_P(395,14700
-# define SYMBOL_VAL(396,14763
-# define SYMBOLP(397,14812
-# define VECTORLIKEP(398,14851
-# define XCAR(399,14898
-# define XCDR(400,14931
-# define XCONS(401,14964
-# define XHASH(402,14999
-# define XPNTR(403,15034
-# define check_cons_list(405,15097
-# define make_number(408,15176
-# define XFASTINT(409,15224
-# define XINT(410,15266
-# define XSYMBOL(411,15300
-# define XTYPE(412,15340
-# define XUNTAG(413,15376
-#define LISP_MACRO_DEFUN(421,15672
-#define LISP_MACRO_DEFUN_VOID(425,15845
-#define INTMASK 437,16289
-#define case_Lisp_Int 438,16342
-#define ENUM_BF(445,16681
-#define ENUM_BF(447,16722
-enum Lisp_Type451,16763
- Lisp_Symbol 454,16851
- Lisp_Misc 458,16993
- Lisp_Int0 461,17067
- Lisp_Int1 462,17086
- Lisp_String 466,17264
- Lisp_Vectorlike 472,17543
- Lisp_Cons 475,17632
- Lisp_Float 477,17670
-enum Lisp_Misc_Type485,18016
- Lisp_Misc_Free 487,18040
- Lisp_Misc_Marker,488,18069
- Lisp_Misc_Overlay,489,18091
- Lisp_Misc_Save_Value,490,18114
- Lisp_Misc_Finalizer,491,18140
- Lisp_Misc_Float,494,18275
- Lisp_Misc_Limit496,18359
-enum Lisp_Fwd_Type502,18543
- Lisp_Fwd_Int,504,18566
- Lisp_Fwd_Bool,505,18619
- Lisp_Fwd_Obj,506,18670
- Lisp_Fwd_Buffer_Obj,507,18729
- Lisp_Fwd_Kboard_Obj 508,18800
-typedef struct { EMACS_INT i; } Lisp_Object;567,21781
-#define LISP_INITIALLY(569,21827
-#undef CHECK_LISP_OBJECT_TYPE571,21858
-enum CHECK_LISP_OBJECT_TYPE 572,21888
-enum CHECK_LISP_OBJECT_TYPE { CHECK_LISP_OBJECT_TYPE 572,21888
-typedef EMACS_INT Lisp_Object;577,22064
-#define LISP_INITIALLY(578,22095
-enum CHECK_LISP_OBJECT_TYPE 579,22125
-enum CHECK_LISP_OBJECT_TYPE { CHECK_LISP_OBJECT_TYPE 579,22125
-#define LISP_INITIALLY_ZERO 582,22226
-enum symbol_interned639,24199
- SYMBOL_UNINTERNED 641,24222
- SYMBOL_INTERNED 642,24247
- SYMBOL_INTERNED_IN_INITIAL_OBARRAY 643,24270
-enum symbol_redirect646,24315
- SYMBOL_PLAINVAL 648,24338
- SYMBOL_VARALIAS 649,24362
- SYMBOL_LOCALIZED 650,24386
- SYMBOL_FORWARDED 651,24410
-struct Lisp_Symbol654,24437
-#define EXFUN(707,26252
-#define DEFUN_ARGS_MANY 712,26446
-#define DEFUN_ARGS_UNEVALLED 713,26498
-#define DEFUN_ARGS_0 714,26541
-#define DEFUN_ARGS_1 715,26569
-#define DEFUN_ARGS_2 716,26604
-#define DEFUN_ARGS_3 717,26652
-#define DEFUN_ARGS_4 718,26713
-#define DEFUN_ARGS_5 719,26787
-#define DEFUN_ARGS_6 721,26880
-#define DEFUN_ARGS_7 723,26986
-#define DEFUN_ARGS_8 725,27105
-#define TAG_PTR(729,27296
-#define TAG_SYMOFFSET(734,27543
-#define XLI_BUILTIN_LISPSYM(741,27842
-#define DEFINE_LISP_SYMBOL(746,28101
-# define DEFINE_NON_NIL_Q_SYMBOL_MACROS 755,28572
-LISP_MACRO_DEFUN 762,28777
-# define ARRAY_MARK_FLAG 768,29024
-# define PSEUDOVECTOR_FLAG 774,29267
-enum pvec_type780,29568
- PVEC_NORMAL_VECTOR,782,29585
- PVEC_FREE,783,29607
- PVEC_PROCESS,784,29620
- PVEC_FRAME,785,29636
- PVEC_WINDOW,786,29650
- PVEC_BOOL_VECTOR,787,29665
- PVEC_BUFFER,788,29685
- PVEC_HASH_TABLE,789,29700
- PVEC_TERMINAL,790,29719
- PVEC_WINDOW_CONFIGURATION,791,29736
- PVEC_SUBR,792,29765
- PVEC_OTHER,793,29778
- PVEC_COMPILED,795,29856
- PVEC_CHAR_TABLE,796,29873
- PVEC_SUB_CHAR_TABLE,797,29892
- PVEC_FONT 798,29915
-enum More_Lisp_Bits801,29991
- PSEUDOVECTOR_SIZE_BITS 808,30382
- PSEUDOVECTOR_SIZE_MASK 809,30415
- PSEUDOVECTOR_REST_BITS 813,30625
- PSEUDOVECTOR_REST_MASK 814,30658
- PSEUDOVECTOR_AREA_BITS 818,30823
- PVEC_TYPE_MASK 819,30901
-# define VALMASK 829,31302
-DEFINE_GDB_SYMBOL_BEGIN VALMASK828,31257
-#define MOST_POSITIVE_FIXNUM 834,31532
-#define MOST_NEGATIVE_FIXNUM 835,31592
-XINT 874,32684
-XFASTINT 889,33035
-XSYMBOL 899,33263
-XTYPE 910,33481
-XUNTAG 918,33661
-LISP_MACRO_DEFUN 927,33857
-LISP_MACRO_DEFUN 940,34242
-#define FIXNUM_OVERFLOW_P(958,34855
-LISP_MACRO_DEFUN FIXNUM_OVERFLOW_P952,34632
-LISP_MACRO_DEFUN 970,35171
-XSTRING 980,35391
-#define SYMBOL_INDEX(988,35575
-XFLOAT 991,35636
-XPROCESS 1000,35778
-XWINDOW 1007,35895
-XTERMINAL 1014,36012
-XSUBR 1021,36134
-XBUFFER 1028,36245
-XCHAR_TABLE 1035,36369
-XSUB_CHAR_TABLE 1042,36506
-XBOOL_VECTOR 1049,36648
-make_lisp_ptr 1058,36827
-make_lisp_symbol 1066,37013
-builtin_lisp_symbol 1074,37197
-#define XSETINT(1079,37279
-#define XSETFASTINT(1080,37325
-#define XSETCONS(1081,37375
-#define XSETVECTOR(1082,37435
-#define XSETSTRING(1083,37503
-#define XSETSYMBOL(1084,37567
-#define XSETFLOAT(1085,37621
-#define XSETMISC(1086,37683
-#define XSETPVECTYPE(1090,37772
-#define XSETPVECTYPESIZE(1092,37888
-#define XSETPSEUDOVECTOR(1099,38185
-#define XSETTYPED_PSEUDOVECTOR(1105,38369
-#define XSETWINDOW_CONFIGURATION(1110,38579
-#define XSETPROCESS(1112,38675
-#define XSETWINDOW(1113,38741
-#define XSETTERMINAL(1114,38805
-#define XSETSUBR(1115,38873
-#define XSETCOMPILED(1116,38933
-#define XSETBUFFER(1117,39001
-#define XSETCHAR_TABLE(1118,39065
-#define XSETBOOL_VECTOR(1119,39137
-#define XSETSUB_CHAR_TABLE(1120,39211
-XINTPTR 1128,39581
-make_pointer_integer 1134,39661
-LISP_MACRO_DEFUN_VOID 1143,39826
-typedef struct interval *INTERVAL;INTERVAL1149,39987
-xcar_addr 1174,40760
-xcdr_addr 1179,40837
-LISP_MACRO_DEFUN 1185,40931
-XSETCDR 1198,41307
-CAR 1205,41457
-CDR 1212,41591
-CAR_SAFE 1221,41791
-CDR_SAFE 1226,41877
-STRING_MULTIBYTE 1243,42250
-#define STRING_BYTES_BOUND 1261,43057
-#define STRING_SET_UNIBYTE(1265,43201
-#define STRING_SET_MULTIBYTE(1275,43516
-SDATA 1286,43830
-SSDATA 1291,43908
-SREF 1297,44037
-SSET 1302,44128
-SCHARS 1307,44242
-STRING_BYTES 1316,44415
-SBYTES 1326,44595
-STRING_SET_CHARS 1331,44681
-struct vectorlike_header1343,45232
-struct Lisp_Vector1369,46482
- ALIGNOF_STRUCT_LISP_VECTOR1378,46681
-struct Lisp_Bool_Vector1384,46864
-bool_vector_size 1399,47385
-bool_vector_data 1407,47523
-bool_vector_uchar_data 1413,47617
-bool_vector_words 1421,47803
-bool_vector_bytes 1428,47998
-bool_vector_bitref 1437,48238
-bool_vector_ref 1445,48478
-bool_vector_set 1453,48618
- header_size 1471,49047
- bool_header_size 1472,49106
- word_size 1473,49171
-AREF 1479,49284
-aref_addr 1485,49391
-ASIZE 1491,49501
-ASET 1497,49583
-gc_aset 1504,49742
-enum { NIL_IS_ZERO 1515,50269
-memclear 1520,50464
-#define VECSIZE(1531,50762
-#define PSEUDOVECSIZE(1538,51047
-#define UNSIGNED_CMP(1546,51480
-#define ASCII_CHAR_P(1552,51734
-enum CHARTAB_SIZE_BITS1565,52489
- CHARTAB_SIZE_BITS_0 1567,52516
- CHARTAB_SIZE_BITS_1 1568,52545
- CHARTAB_SIZE_BITS_2 1569,52574
- CHARTAB_SIZE_BITS_3 1570,52603
-struct Lisp_Char_Table1575,52672
-struct Lisp_Sub_Char_Table1606,53752
-CHAR_TABLE_REF_ASCII 1628,54566
-CHAR_TABLE_REF 1648,55113
-CHAR_TABLE_SET 1658,55402
-struct Lisp_Subr1670,55786
-enum char_table_specials1692,56798
- CHAR_TABLE_STANDARD_SLOTS 1697,56993
- SUB_CHAR_TABLE_OFFSET 1701,57214
-CHAR_TABLE_EXTRA_SLOTS 1707,57377
-LISP_MACRO_DEFUN 1723,57921
-SYMBOL_BLV 1732,58181
-SYMBOL_FWD 1738,58316
-LISP_MACRO_DEFUN_VOID 1744,58428
-SET_SYMBOL_BLV 1754,58691
-SET_SYMBOL_FWD 1760,58850
-SYMBOL_NAME 1767,59001
-SYMBOL_INTERNED_P 1775,59130
-SYMBOL_INTERNED_IN_INITIAL_OBARRAY_P 1783,59299
-#define DEFSYM(1796,59809
-LISP_MACRO_DEFUN DEFSYM1792,59630
-struct hash_table_test1805,60062
-struct Lisp_Hash_Table1823,60555
-XHASH_TABLE 1880,62531
-#define XSET_HASH_TABLE(1885,62602
-HASH_TABLE_P 1889,62703
-HASH_KEY 1896,62860
-HASH_VALUE 1903,63040
-HASH_NEXT 1911,63254
-HASH_HASH 1918,63431
-HASH_INDEX 1926,63677
-HASH_TABLE_SIZE 1933,63826
-enum DEFAULT_HASH_SIZE 1940,63956
-enum DEFAULT_HASH_SIZE { DEFAULT_HASH_SIZE 1940,63956
-static double const DEFAULT_REHASH_THRESHOLD 1946,64176
-static double const DEFAULT_REHASH_SIZE 1950,64299
-sxhash_combine 1956,64465
-SXHASH_REDUCE 1964,64648
-struct Lisp_Misc_Any 1971,64806
-struct Lisp_Marker1978,64980
-struct Lisp_Overlay2021,66841
- SAVE_UNUSED,2047,67644
- SAVE_INTEGER,2048,67661
- SAVE_FUNCPOINTER,2049,67679
- SAVE_POINTER,2050,67701
- SAVE_OBJECT2051,67719
-enum { SAVE_SLOT_BITS 2055,67804
-enum { SAVE_VALUE_SLOTS 2058,67901
-enum { SAVE_TYPE_BITS 2062,68009
-enum Lisp_Save_Type2064,68075
- SAVE_TYPE_INT_INT 2066,68099
- SAVE_TYPE_INT_INT_INT2067,68172
- SAVE_TYPE_OBJ_OBJ 2069,68262
- SAVE_TYPE_OBJ_OBJ_OBJ 2070,68333
- SAVE_TYPE_OBJ_OBJ_OBJ_OBJ2071,68414
- SAVE_TYPE_PTR_INT 2073,68509
- SAVE_TYPE_PTR_OBJ 2074,68582
- SAVE_TYPE_PTR_PTR 2075,68654
- SAVE_TYPE_FUNCPTR_PTR_OBJ2076,68727
- SAVE_TYPE_MEMORY 2080,68885
-typedef void (*voidfuncptr)voidfuncptr2108,69839
-struct Lisp_Save_Value2110,69876
-save_type 2134,70755
-XSAVE_POINTER 2143,70985
-set_save_pointer 2149,71147
-XSAVE_FUNCPOINTER 2155,71329
-XSAVE_INTEGER 2164,71549
-set_save_integer 2170,71711
-XSAVE_OBJECT 2179,71932
-struct Lisp_Finalizer2186,72109
-struct Lisp_Free2201,72584
-union Lisp_Misc2212,72885
-XMISC 2223,73184
-XMISCANY 2229,73273
-XMISCTYPE 2236,73382
-XMARKER 2242,73470
-XOVERLAY 2249,73585
-XSAVE_VALUE 2256,73706
-XFINALIZER 2263,73835
-struct Lisp_Intfwd2274,74120
-struct Lisp_Boolfwd2284,74414
-struct Lisp_Objfwd2294,74705
-struct Lisp_Buffer_Objfwd2302,74937
-struct Lisp_Buffer_Local_Value2334,76473
-struct Lisp_Kboard_Objfwd2362,77732
-union Lisp_Fwd2368,77841
-XFWDTYPE 2378,78087
-XBUFFER_OBJFWD 2384,78183
-struct Lisp_Float2391,78319
-XFLOAT_DATA 2401,78437
- IEEE_FLOATING_POINT2415,78946
-#define _UCHAR_T2423,79269
-typedef unsigned char UCHAR;2424,79286
-enum Lisp_Compiled2429,79369
- COMPILED_ARGLIST 2431,79392
- COMPILED_BYTECODE 2432,79418
- COMPILED_CONSTANTS 2433,79445
- COMPILED_STACK_DEPTH 2434,79473
- COMPILED_DOC_STRING 2435,79503
- COMPILED_INTERACTIVE 2436,79532
-enum char_bits2443,79834
- CHAR_ALT 2445,79853
- CHAR_SUPER 2446,79879
- CHAR_HYPER 2447,79907
- CHAR_SHIFT 2448,79935
- CHAR_CTL 2449,79963
- CHAR_META 2450,79989
- CHAR_MODIFIER_MASK 2452,80017
- CHARACTERBITS 2457,80212
-LISP_MACRO_DEFUN 2462,80270
-NATNUMP 2470,80412
-RANGED_INTEGERP 2476,80493
-#define TYPE_RANGED_INTEGERP(2481,80615
-LISP_MACRO_DEFUN 2486,80800
-VECTORP 2500,81273
-OVERLAYP 2505,81376
-SAVE_VALUEP 2510,81475
-FINALIZERP 2516,81581
-AUTOLOADP 2522,81685
-BUFFER_OBJFWDP 2528,81776
-PSEUDOVECTOR_TYPEP 2534,81874
-PSEUDOVECTORP 2542,82127
-WINDOW_CONFIGURATIONP 2558,82479
-PROCESSP 2564,82589
-WINDOWP 2570,82673
-TERMINALP 2576,82755
-SUBRP 2582,82841
-COMPILEDP 2588,82919
-BUFFERP 2594,83005
-CHAR_TABLE_P 2600,83087
-SUB_CHAR_TABLE_P 2606,83178
-BOOL_VECTOR_P 2612,83277
-FRAMEP 2618,83370
-IMAGEP 2625,83487
-ARRAYP 2632,83592
-CHECK_LIST 2638,83711
-LISP_MACRO_DEFUN_VOID 2643,83792
-CHECK_STRING_CAR 2653,84089
-CHECK_CONS 2658,84193
-CHECK_VECTOR 2663,84273
-CHECK_BOOL_VECTOR 2668,84359
-CHECK_VECTOR_OR_STRING 2674,84536
-CHECK_ARRAY 2683,84710
-CHECK_BUFFER 2688,84818
-CHECK_WINDOW 2693,84904
-CHECK_PROCESS 2699,85010
-CHECK_NATNUM 2705,85106
-#define CHECK_RANGED_INTEGER(2710,85183
-#define CHECK_TYPE_RANGED_INTEGER(2721,85566
-#define CHECK_NUMBER_COERCE_MARKER(2729,85836
-XFLOATINT 2738,86089
-CHECK_NUMBER_OR_FLOAT 2744,86160
-#define CHECK_NUMBER_OR_FLOAT_COERCE_MARKER(2749,86259
-CHECK_NUMBER_CAR 2760,86669
-CHECK_NUMBER_CDR 2768,86791
-#define DEFUN(2803,88386
-#define DEFUN(2812,88854
-FUNCTIONP 2822,89209
-enum maxargs2831,89404
- MANY 2833,89421
- UNEVALLED 2834,89436
-#define CALLMANY(2838,89539
-#define CALLN(2844,89892
-#define DEFVAR_LISP(2869,91097
-#define DEFVAR_LISP_NOPRO(2874,91269
-#define DEFVAR_BOOL(2879,91451
-#define DEFVAR_INT(2884,91624
-#define DEFVAR_BUFFER_DEFAULTS(2890,91795
-#define DEFVAR_KBOARD(2896,91999
-typedef jmp_buf sys_jmp_buf;2906,92323
-# define sys_setjmp(2907,92352
-# define sys_longjmp(2908,92387
-typedef sigjmp_buf sys_jmp_buf;2910,92459
-# define sys_setjmp(2911,92491
-# define sys_longjmp(2912,92531
-typedef jmp_buf sys_jmp_buf;2916,92690
-# define sys_setjmp(2917,92719
-# define sys_longjmp(2918,92753
-enum specbind_tag 2943,93805
- SPECPDL_UNWIND,2944,93825
- SPECPDL_UNWIND_PTR,2945,93894
- SPECPDL_UNWIND_INT,2946,93945
- SPECPDL_UNWIND_VOID,2947,93993
- SPECPDL_BACKTRACE,2948,94047
- SPECPDL_LET,2949,94105
- SPECPDL_LET_LOCAL,2951,94235
- SPECPDL_LET_DEFAULT 2952,94292
-union specbinding2955,94364
-SPECPDL_INDEX 2996,95388
-enum handlertype 3021,96410
-enum handlertype { CATCHER,3021,96410
-enum handlertype { CATCHER, CONDITION_CASE 3021,96410
-struct handler3023,96457
-#define PUSH_HANDLER(3053,97446
-#define QUIT 3101,99223
-#define QUITP 3112,99473
-struct gcpro3132,100316
-#define GC_USE_GCPROS_AS_BEFORE 3171,101297
-#define GC_MAKE_GCPROS_NOOPS 3172,101332
-#define GC_MARK_STACK_CHECK_GCPROS 3173,101364
-#define GC_USE_GCPROS_CHECK_ZOMBIES 3174,101401
-#define GC_MARK_STACK 3177,101462
-#define BYTE_MARK_STACK 3181,101562
-#define GCPRO1(3190,101833
-#define GCPRO2(3191,101873
-#define GCPRO3(3192,101939
-#define GCPRO4(3194,102034
-#define GCPRO5(3196,102154
-#define GCPRO6(3198,102299
-#define GCPRO7(3201,102474
-#define UNGCPRO 3202,102553
-#define GCPRO1(3208,102653
-#define GCPRO2(3212,102775
-#define GCPRO3(3217,102967
-#define GCPRO4(3223,103229
-#define GCPRO5(3230,103560
-#define GCPRO6(3238,103961
-#define GCPRO7(3247,104431
-#define UNGCPRO 3257,104971
-#define GCPRO1(3263,105065
-#define GCPRO2(3269,105299
-#define GCPRO3(3278,105717
-#define GCPRO4(3289,106274
-#define GCPRO5(3302,106972
-#define GCPRO6(3317,107812
-#define GCPRO7(3334,108793
-#define UNGCPRO 3353,109916
-#define RETURN_UNGCPRO(3363,110183
-vcopy 3384,110657
-set_hash_key_slot 3393,110932
-set_hash_value_slot 3399,111071
-set_symbol_function 3408,111306
-set_symbol_plist 3414,111421
-set_symbol_next 3420,111524
-blv_found 3428,111697
-set_overlay_plist 3437,111880
-string_intervals 3445,112031
-set_string_intervals 3453,112153
-set_char_table_defalt 3462,112355
-set_char_table_purpose 3467,112467
-set_char_table_extras 3475,112636
-set_char_table_contents 3482,112845
-set_sub_char_table_contents 3489,113040
-enum Arith_Comparison 3497,113303
- ARITH_EQUAL,3498,113327
- ARITH_NOTEQUAL,3499,113342
- ARITH_LESS,3500,113360
- ARITH_GRTR,3501,113374
- ARITH_LESS_OR_EQUAL,3502,113388
- ARITH_GRTR_OR_EQUAL3503,113411
-#define INTEGER_TO_CONS(3511,113762
-#define CONS_TO_INTEGER(3529,114625
-enum { NEXT_ALMOST_PRIME_LIMIT 3573,116329
-extern EMACS_INT next_almost_prime 3574,116368
-enum constype 3739,123820
-enum constype {CONSTYPE_HEAP,CONSTYPE_HEAP3739,123820
-enum constype {CONSTYPE_HEAP, CONSTYPE_PURE}CONSTYPE_PURE3739,123820
-list2i 3745,124010
-list3i 3751,124119
-list4i 3757,124258
-extern Lisp_Object make_formatted_string 3767,124634
-build_pure_c_string 3792,125662
-build_string 3801,125867
-make_uninit_vector 3820,126438
-make_uninit_sub_char_table 3833,126657
-#define ALLOCATE_PSEUDOVECTOR(3850,127201
-#define ALLOCATE_ZEROED_PSEUDOVECTOR(3858,127537
-INLINE void 3890,128943
-extern void *r_alloc r_alloc3895,129064
-#define FLOAT_TO_STRING_BUFSIZE 3927,130527
-intern 3968,132134
-intern_c_string 3974,132222
-extern _Noreturn void error 4034,135601
-fast_string_match_ignore_case 4136,140089
-INLINE void fixup_locale 4241,143854
-INLINE void synchronize_system_messages_locale 4242,143889
-INLINE void synchronize_system_time_locale 4243,143946
-#define IS_DAEMON 4257,144419
-#define DAEMON_RUNNING 4258,144459
-#define IS_DAEMON 4261,144558
-#define DAEMON_RUNNING 4262,144603
-# define WAIT_READING_MAX 4281,145422
-# define WAIT_READING_MAX 4283,145494
-extern _Noreturn void emacs_abort 4374,148386
-egetenv 4532,152809
-#define eabs(4545,153305
-#define make_fixnum_or_float(4550,153438
-enum MAX_ALLOCA 4556,153689
-enum MAX_ALLOCA { MAX_ALLOCA 4556,153689
-extern void *record_xmalloc record_xmalloc4558,153734
-#define USE_SAFE_ALLOCA 4560,153800
-#define AVAIL_ALLOCA(4564,153933
-#define SAFE_ALLOCA(4568,154044
-#define SAFE_NALLOCA(4576,154385
-#define SAFE_ALLOCA_STRING(4590,154861
-#define SAFE_FREE(4598,155113
-#define SAFE_ALLOCA_LISP(4625,155691
-# define USE_STACK_LISP_OBJECTS 4652,156813
-# undef USE_STACK_LISP_OBJECTS4658,156979
-# define USE_STACK_LISP_OBJECTS 4659,157010
-enum { defined_GC_CHECK_STRING_BYTES 4663,157085
-enum { defined_GC_CHECK_STRING_BYTES 4665,157138
-union Aligned_Cons4670,157272
-union Aligned_String4676,157352
- USE_STACK_CONS 4689,157707
- USE_STACK_STRING 4691,157813
-#define STACK_CONS(4699,158150
-#define AUTO_CONS_EXPR(4701,158247
-#define AUTO_CONS(4709,158610
-#define AUTO_LIST1(4710,158681
-#define AUTO_LIST2(4712,158789
-#define AUTO_LIST3(4716,158944
-#define AUTO_LIST4(4720,159119
-# define verify_ascii(4732,159510
-#define AUTO_STRING(4740,159818
-#define FOR_EACH_TAIL(4752,160282
-#define FOR_EACH_ALIST_VALUE(4766,160773
-maybe_gc 4774,161060
-functionp 4784,161299
+#define EMACS_LISP_H22,801
+#define DECLARE_GDB_SYM(47,1422
+# define DEFINE_GDB_SYMBOL_BEGIN(49,1509
+# define DEFINE_GDB_SYMBOL_END(50,1579
+# define DEFINE_GDB_SYMBOL_BEGIN(52,1626
+# define DEFINE_GDB_SYMBOL_END(53,1703
+#undef min57,1791
+#undef max58,1802
+#define max(59,1813
+#define min(60,1855
+#define ARRAYELTS(63,1937
+#define GCTYPEBITS 67,2080
+DEFINE_GDB_SYMBOL_BEGIN GCTYPEBITS66,2038
+# define NONPOINTER_BITS 78,2568
+# define NONPOINTER_BITS 80,2601
+typedef int EMACS_INT;91,3024
+typedef unsigned int EMACS_UINT;92,3047
+# define EMACS_INT_MAX 93,3080
+# define pI 94,3112
+typedef long int EMACS_INT;96,3204
+typedef unsigned long EMACS_UINT;97,3232
+# define EMACS_INT_MAX 98,3266
+# define pI 99,3299
+typedef long long int EMACS_INT;103,3478
+typedef unsigned long long int EMACS_UINT;104,3511
+# define EMACS_INT_MAX 105,3554
+# define pI 106,3588
+enum { BOOL_VECTOR_BITS_PER_CHAR 114,3805
+#define BOOL_VECTOR_BITS_PER_CHAR 115,3841
+typedef size_t bits_word;123,4166
+# define BITS_WORD_MAX 124,4192
+enum { BITS_PER_BITS_WORD 125,4224
+typedef unsigned char bits_word;127,4291
+# define BITS_WORD_MAX 128,4324
+enum { BITS_PER_BITS_WORD 129,4387
+ BITS_PER_CHAR 136,4571
+ BITS_PER_SHORT 137,4606
+ BITS_PER_LONG 138,4658
+ BITS_PER_EMACS_INT 139,4713
+typedef intmax_t printmax_t;148,5090
+typedef uintmax_t uprintmax_t;149,5119
+# define pMd 150,5150
+# define pMu 151,5171
+typedef EMACS_INT printmax_t;153,5198
+typedef EMACS_UINT uprintmax_t;154,5228
+# define pMd 155,5260
+# define pMu 156,5279
+# define pD 165,5665
+# define pD 167,5710
+# define pD 169,5757
+# define pD 171,5780
+# define eassert(200,7063
+# define eassume(201,7141
+# define eassert(208,7320
+# define eassume(212,7451
+enum Lisp_Bits239,8520
+#define GCALIGNMENT 243,8648
+ VALBITS 246,8743
+ INTTYPEBITS 249,8839
+ FIXNUM_BITS 252,8946
+#define VAL_MAX 263,9328
+#define USE_LSB_TAG 271,9778
+DEFINE_GDB_SYMBOL_BEGIN USE_LSB_TAG270,9734
+# define alignas(281,10078
+# define GCALIGNED 288,10228
+# define GCALIGNED 290,10293
+# define lisp_h_XLI(327,11643
+# define lisp_h_XIL(328,11674
+# define lisp_h_XLI(330,11725
+# define lisp_h_XIL(331,11752
+#define lisp_h_CHECK_LIST_CONS(333,11786
+#define lisp_h_CHECK_NUMBER(334,11857
+#define lisp_h_CHECK_SYMBOL(335,11928
+#define lisp_h_CHECK_TYPE(336,11997
+#define lisp_h_CONSP(338,12108
+#define lisp_h_EQ(339,12157
+#define lisp_h_FLOATP(340,12202
+#define lisp_h_INTEGERP(341,12253
+#define lisp_h_MARKERP(342,12334
+#define lisp_h_MISCP(343,12409
+#define lisp_h_NILP(344,12458
+#define lisp_h_SET_SYMBOL_VAL(345,12494
+#define lisp_h_SYMBOL_CONSTANT_P(347,12608
+#define lisp_h_SYMBOL_VAL(348,12672
+#define lisp_h_SYMBOLP(350,12773
+#define lisp_h_VECTORLIKEP(351,12826
+#define lisp_h_XCAR(352,12887
+#define lisp_h_XCDR(353,12925
+#define lisp_h_XCONS(354,12965
+#define lisp_h_XHASH(356,13060
+#define lisp_h_XPNTR(357,13094
+# define lisp_h_check_cons_list(360,13222
+# define lisp_h_make_number(363,13290
+# define lisp_h_XFASTINT(365,13393
+# define lisp_h_XINT(366,13430
+# define lisp_h_XSYMBOL(367,13479
+# define lisp_h_XTYPE(371,13632
+# define lisp_h_XUNTAG(372,13697
+# define XLI(381,14087
+# define XIL(382,14118
+# define CHECK_LIST_CONS(383,14149
+# define CHECK_NUMBER(384,14210
+# define CHECK_SYMBOL(385,14259
+# define CHECK_TYPE(386,14308
+# define CONSP(387,14383
+# define EQ(388,14418
+# define FLOATP(389,14453
+# define INTEGERP(390,14490
+# define MARKERP(391,14531
+# define MISCP(392,14570
+# define NILP(393,14605
+# define SET_SYMBOL_VAL(394,14638
+# define SYMBOL_CONSTANT_P(395,14701
+# define SYMBOL_VAL(396,14764
+# define SYMBOLP(397,14813
+# define VECTORLIKEP(398,14852
+# define XCAR(399,14899
+# define XCDR(400,14932
+# define XCONS(401,14965
+# define XHASH(402,15000
+# define XPNTR(403,15035
+# define check_cons_list(405,15098
+# define make_number(408,15177
+# define XFASTINT(409,15225
+# define XINT(410,15267
+# define XSYMBOL(411,15301
+# define XTYPE(412,15341
+# define XUNTAG(413,15377
+#define LISP_MACRO_DEFUN(421,15673
+#define LISP_MACRO_DEFUN_VOID(425,15846
+#define INTMASK 437,16290
+#define case_Lisp_Int 438,16343
+#define ENUM_BF(445,16682
+#define ENUM_BF(447,16723
+enum Lisp_Type451,16764
+ Lisp_Symbol 454,16852
+ Lisp_Misc 458,16994
+ Lisp_Int0 461,17068
+ Lisp_Int1 462,17087
+ Lisp_String 466,17265
+ Lisp_Vectorlike 472,17544
+ Lisp_Cons 475,17633
+ Lisp_Float 477,17671
+enum Lisp_Misc_Type485,18017
+ Lisp_Misc_Free 487,18041
+ Lisp_Misc_Marker,488,18070
+ Lisp_Misc_Overlay,489,18092
+ Lisp_Misc_Save_Value,490,18115
+ Lisp_Misc_Finalizer,491,18141
+ Lisp_Misc_Float,494,18276
+ Lisp_Misc_Limit496,18360
+enum Lisp_Fwd_Type502,18544
+ Lisp_Fwd_Int,504,18567
+ Lisp_Fwd_Bool,505,18620
+ Lisp_Fwd_Obj,506,18671
+ Lisp_Fwd_Buffer_Obj,507,18730
+ Lisp_Fwd_Kboard_Obj 508,18801
+typedef struct { EMACS_INT i; } Lisp_Object;567,21772
+#define LISP_INITIALLY(569,21818
+#undef CHECK_LISP_OBJECT_TYPE571,21849
+enum CHECK_LISP_OBJECT_TYPE 572,21879
+enum CHECK_LISP_OBJECT_TYPE { CHECK_LISP_OBJECT_TYPE 572,21879
+typedef EMACS_INT Lisp_Object;577,22055
+#define LISP_INITIALLY(578,22086
+enum CHECK_LISP_OBJECT_TYPE 579,22116
+enum CHECK_LISP_OBJECT_TYPE { CHECK_LISP_OBJECT_TYPE 579,22116
+#define LISP_INITIALLY_ZERO 582,22217
+enum symbol_interned639,24190
+ SYMBOL_UNINTERNED 641,24213
+ SYMBOL_INTERNED 642,24238
+ SYMBOL_INTERNED_IN_INITIAL_OBARRAY 643,24261
+enum symbol_redirect646,24306
+ SYMBOL_PLAINVAL 648,24329
+ SYMBOL_VARALIAS 649,24353
+ SYMBOL_LOCALIZED 650,24377
+ SYMBOL_FORWARDED 651,24401
+struct Lisp_Symbol654,24428
+#define EXFUN(707,26243
+#define DEFUN_ARGS_MANY 712,26437
+#define DEFUN_ARGS_UNEVALLED 713,26489
+#define DEFUN_ARGS_0 714,26532
+#define DEFUN_ARGS_1 715,26560
+#define DEFUN_ARGS_2 716,26595
+#define DEFUN_ARGS_3 717,26643
+#define DEFUN_ARGS_4 718,26704
+#define DEFUN_ARGS_5 719,26778
+#define DEFUN_ARGS_6 721,26871
+#define DEFUN_ARGS_7 723,26977
+#define DEFUN_ARGS_8 725,27096
+#define TAG_PTR(729,27287
+#define TAG_SYMOFFSET(734,27534
+#define XLI_BUILTIN_LISPSYM(741,27833
+#define DEFINE_LISP_SYMBOL(746,28092
+# define DEFINE_NON_NIL_Q_SYMBOL_MACROS 755,28563
+LISP_MACRO_DEFUN 762,28768
+# define ARRAY_MARK_FLAG 768,29015
+# define PSEUDOVECTOR_FLAG 774,29258
+enum pvec_type780,29559
+ PVEC_NORMAL_VECTOR,782,29576
+ PVEC_FREE,783,29598
+ PVEC_PROCESS,784,29611
+ PVEC_FRAME,785,29627
+ PVEC_WINDOW,786,29641
+ PVEC_BOOL_VECTOR,787,29656
+ PVEC_BUFFER,788,29676
+ PVEC_HASH_TABLE,789,29691
+ PVEC_TERMINAL,790,29710
+ PVEC_WINDOW_CONFIGURATION,791,29727
+ PVEC_SUBR,792,29756
+ PVEC_OTHER,793,29769
+ PVEC_COMPILED,795,29847
+ PVEC_CHAR_TABLE,796,29864
+ PVEC_SUB_CHAR_TABLE,797,29883
+ PVEC_FONT 798,29906
+enum More_Lisp_Bits801,29982
+ PSEUDOVECTOR_SIZE_BITS 808,30373
+ PSEUDOVECTOR_SIZE_MASK 809,30406
+ PSEUDOVECTOR_REST_BITS 813,30616
+ PSEUDOVECTOR_REST_MASK 814,30649
+ PSEUDOVECTOR_AREA_BITS 818,30814
+ PVEC_TYPE_MASK 819,30892
+# define VALMASK 829,31293
+DEFINE_GDB_SYMBOL_BEGIN VALMASK828,31248
+#define MOST_POSITIVE_FIXNUM 834,31523
+#define MOST_NEGATIVE_FIXNUM 835,31583
+XINT 874,32675
+XFASTINT 889,33026
+XSYMBOL 899,33254
+XTYPE 910,33472
+XUNTAG 918,33652
+LISP_MACRO_DEFUN 927,33848
+LISP_MACRO_DEFUN 940,34233
+#define FIXNUM_OVERFLOW_P(958,34846
+LISP_MACRO_DEFUN FIXNUM_OVERFLOW_P952,34623
+LISP_MACRO_DEFUN 970,35162
+XSTRING 980,35382
+#define SYMBOL_INDEX(988,35566
+XFLOAT 991,35627
+XPROCESS 1000,35769
+XWINDOW 1007,35886
+XTERMINAL 1014,36003
+XSUBR 1021,36125
+XBUFFER 1028,36236
+XCHAR_TABLE 1035,36360
+XSUB_CHAR_TABLE 1042,36497
+XBOOL_VECTOR 1049,36639
+make_lisp_ptr 1058,36818
+make_lisp_symbol 1066,37004
+builtin_lisp_symbol 1074,37188
+#define XSETINT(1079,37270
+#define XSETFASTINT(1080,37316
+#define XSETCONS(1081,37366
+#define XSETVECTOR(1082,37426
+#define XSETSTRING(1083,37494
+#define XSETSYMBOL(1084,37558
+#define XSETFLOAT(1085,37612
+#define XSETMISC(1086,37674
+#define XSETPVECTYPE(1090,37763
+#define XSETPVECTYPESIZE(1092,37879
+#define XSETPSEUDOVECTOR(1099,38176
+#define XSETTYPED_PSEUDOVECTOR(1105,38360
+#define XSETWINDOW_CONFIGURATION(1110,38570
+#define XSETPROCESS(1112,38666
+#define XSETWINDOW(1113,38732
+#define XSETTERMINAL(1114,38796
+#define XSETSUBR(1115,38864
+#define XSETCOMPILED(1116,38924
+#define XSETBUFFER(1117,38992
+#define XSETCHAR_TABLE(1118,39056
+#define XSETBOOL_VECTOR(1119,39128
+#define XSETSUB_CHAR_TABLE(1120,39202
+XINTPTR 1128,39572
+make_pointer_integer 1134,39652
+LISP_MACRO_DEFUN_VOID 1143,39817
+typedef struct interval *INTERVAL;INTERVAL1149,39978
+xcar_addr 1174,40751
+xcdr_addr 1179,40828
+LISP_MACRO_DEFUN 1185,40922
+XSETCDR 1198,41298
+CAR 1205,41448
+CDR 1212,41582
+CAR_SAFE 1221,41782
+CDR_SAFE 1226,41868
+STRING_MULTIBYTE 1243,42241
+#define STRING_BYTES_BOUND 1261,43048
+#define STRING_SET_UNIBYTE(1265,43192
+#define STRING_SET_MULTIBYTE(1275,43507
+SDATA 1286,43821
+SSDATA 1291,43899
+SREF 1297,44028
+SSET 1302,44119
+SCHARS 1307,44233
+STRING_BYTES 1316,44406
+SBYTES 1326,44586
+STRING_SET_CHARS 1331,44672
+struct vectorlike_header1343,45223
+struct Lisp_Vector1369,46473
+ ALIGNOF_STRUCT_LISP_VECTOR1378,46672
+struct Lisp_Bool_Vector1384,46855
+bool_vector_size 1399,47376
+bool_vector_data 1407,47514
+bool_vector_uchar_data 1413,47608
+bool_vector_words 1421,47794
+bool_vector_bytes 1428,47989
+bool_vector_bitref 1437,48229
+bool_vector_ref 1445,48469
+bool_vector_set 1453,48609
+ header_size 1471,49038
+ bool_header_size 1472,49097
+ word_size 1473,49162
+AREF 1479,49275
+aref_addr 1485,49382
+ASIZE 1491,49492
+ASET 1497,49574
+gc_aset 1504,49733
+enum { NIL_IS_ZERO 1515,50260
+memclear 1520,50455
+#define VECSIZE(1531,50753
+#define PSEUDOVECSIZE(1538,51038
+#define UNSIGNED_CMP(1546,51471
+#define ASCII_CHAR_P(1552,51725
+enum CHARTAB_SIZE_BITS1565,52480
+ CHARTAB_SIZE_BITS_0 1567,52507
+ CHARTAB_SIZE_BITS_1 1568,52536
+ CHARTAB_SIZE_BITS_2 1569,52565
+ CHARTAB_SIZE_BITS_3 1570,52594
+struct Lisp_Char_Table1575,52663
+struct Lisp_Sub_Char_Table1606,53743
+CHAR_TABLE_REF_ASCII 1628,54557
+CHAR_TABLE_REF 1648,55104
+CHAR_TABLE_SET 1658,55393
+struct Lisp_Subr1670,55777
+enum char_table_specials1692,56789
+ CHAR_TABLE_STANDARD_SLOTS 1697,56984
+ SUB_CHAR_TABLE_OFFSET 1701,57205
+CHAR_TABLE_EXTRA_SLOTS 1707,57368
+LISP_MACRO_DEFUN 1723,57912
+SYMBOL_BLV 1732,58172
+SYMBOL_FWD 1738,58307
+LISP_MACRO_DEFUN_VOID 1744,58419
+SET_SYMBOL_BLV 1754,58682
+SET_SYMBOL_FWD 1760,58841
+SYMBOL_NAME 1767,58992
+SYMBOL_INTERNED_P 1775,59121
+SYMBOL_INTERNED_IN_INITIAL_OBARRAY_P 1783,59290
+#define DEFSYM(1796,59800
+LISP_MACRO_DEFUN DEFSYM1792,59621
+struct hash_table_test1805,60053
+struct Lisp_Hash_Table1823,60546
+XHASH_TABLE 1880,62522
+#define XSET_HASH_TABLE(1885,62593
+HASH_TABLE_P 1889,62694
+HASH_KEY 1896,62851
+HASH_VALUE 1903,63031
+HASH_NEXT 1911,63245
+HASH_HASH 1918,63422
+HASH_INDEX 1926,63668
+HASH_TABLE_SIZE 1933,63817
+enum DEFAULT_HASH_SIZE 1940,63947
+enum DEFAULT_HASH_SIZE { DEFAULT_HASH_SIZE 1940,63947
+static double const DEFAULT_REHASH_THRESHOLD 1946,64167
+static double const DEFAULT_REHASH_SIZE 1950,64290
+sxhash_combine 1956,64456
+SXHASH_REDUCE 1964,64639
+struct Lisp_Misc_Any 1971,64797
+struct Lisp_Marker1978,64971
+struct Lisp_Overlay2021,66832
+ SAVE_UNUSED,2047,67635
+ SAVE_INTEGER,2048,67652
+ SAVE_FUNCPOINTER,2049,67670
+ SAVE_POINTER,2050,67692
+ SAVE_OBJECT2051,67710
+enum { SAVE_SLOT_BITS 2055,67795
+enum { SAVE_VALUE_SLOTS 2058,67892
+enum { SAVE_TYPE_BITS 2062,68000
+enum Lisp_Save_Type2064,68066
+ SAVE_TYPE_INT_INT 2066,68090
+ SAVE_TYPE_INT_INT_INT2067,68163
+ SAVE_TYPE_OBJ_OBJ 2069,68253
+ SAVE_TYPE_OBJ_OBJ_OBJ 2070,68324
+ SAVE_TYPE_OBJ_OBJ_OBJ_OBJ2071,68405
+ SAVE_TYPE_PTR_INT 2073,68500
+ SAVE_TYPE_PTR_OBJ 2074,68573
+ SAVE_TYPE_PTR_PTR 2075,68645
+ SAVE_TYPE_FUNCPTR_PTR_OBJ2076,68718
+ SAVE_TYPE_MEMORY 2080,68876
+typedef void (*voidfuncptr)voidfuncptr2108,69830
+struct Lisp_Save_Value2110,69867
+save_type 2134,70746
+XSAVE_POINTER 2143,70976
+set_save_pointer 2149,71138
+XSAVE_FUNCPOINTER 2155,71320
+XSAVE_INTEGER 2164,71540
+set_save_integer 2170,71702
+XSAVE_OBJECT 2179,71923
+struct Lisp_Finalizer2186,72100
+struct Lisp_Free2201,72575
+union Lisp_Misc2212,72876
+XMISC 2223,73175
+XMISCANY 2229,73264
+XMISCTYPE 2236,73373
+XMARKER 2242,73461
+XOVERLAY 2249,73576
+XSAVE_VALUE 2256,73697
+XFINALIZER 2263,73826
+struct Lisp_Intfwd2274,74111
+struct Lisp_Boolfwd2284,74405
+struct Lisp_Objfwd2294,74696
+struct Lisp_Buffer_Objfwd2302,74928
+struct Lisp_Buffer_Local_Value2334,76464
+struct Lisp_Kboard_Objfwd2362,77723
+union Lisp_Fwd2368,77832
+XFWDTYPE 2378,78078
+XBUFFER_OBJFWD 2384,78174
+struct Lisp_Float2391,78310
+XFLOAT_DATA 2401,78428
+ IEEE_FLOATING_POINT2415,78937
+#define _UCHAR_T2423,79260
+typedef unsigned char UCHAR;2424,79277
+enum Lisp_Compiled2429,79360
+ COMPILED_ARGLIST 2431,79383
+ COMPILED_BYTECODE 2432,79409
+ COMPILED_CONSTANTS 2433,79436
+ COMPILED_STACK_DEPTH 2434,79464
+ COMPILED_DOC_STRING 2435,79494
+ COMPILED_INTERACTIVE 2436,79523
+enum char_bits2443,79825
+ CHAR_ALT 2445,79844
+ CHAR_SUPER 2446,79870
+ CHAR_HYPER 2447,79898
+ CHAR_SHIFT 2448,79926
+ CHAR_CTL 2449,79954
+ CHAR_META 2450,79980
+ CHAR_MODIFIER_MASK 2452,80008
+ CHARACTERBITS 2457,80203
+LISP_MACRO_DEFUN 2462,80261
+NATNUMP 2470,80403
+RANGED_INTEGERP 2476,80484
+#define TYPE_RANGED_INTEGERP(2481,80606
+LISP_MACRO_DEFUN 2486,80791
+VECTORP 2500,81264
+OVERLAYP 2505,81367
+SAVE_VALUEP 2510,81466
+FINALIZERP 2516,81572
+AUTOLOADP 2522,81676
+BUFFER_OBJFWDP 2528,81767
+PSEUDOVECTOR_TYPEP 2534,81865
+PSEUDOVECTORP 2542,82118
+WINDOW_CONFIGURATIONP 2558,82470
+PROCESSP 2564,82580
+WINDOWP 2570,82664
+TERMINALP 2576,82746
+SUBRP 2582,82832
+COMPILEDP 2588,82910
+BUFFERP 2594,82996
+CHAR_TABLE_P 2600,83078
+SUB_CHAR_TABLE_P 2606,83169
+BOOL_VECTOR_P 2612,83268
+FRAMEP 2618,83361
+IMAGEP 2625,83478
+ARRAYP 2632,83583
+CHECK_LIST 2638,83702
+LISP_MACRO_DEFUN_VOID 2643,83783
+CHECK_STRING_CAR 2653,84080
+CHECK_CONS 2658,84184
+CHECK_VECTOR 2663,84264
+CHECK_BOOL_VECTOR 2668,84350
+CHECK_VECTOR_OR_STRING 2674,84527
+CHECK_ARRAY 2683,84701
+CHECK_BUFFER 2688,84809
+CHECK_WINDOW 2693,84895
+CHECK_PROCESS 2699,85001
+CHECK_NATNUM 2705,85097
+#define CHECK_RANGED_INTEGER(2710,85174
+#define CHECK_TYPE_RANGED_INTEGER(2721,85557
+#define CHECK_NUMBER_COERCE_MARKER(2729,85827
+XFLOATINT 2738,86080
+CHECK_NUMBER_OR_FLOAT 2744,86151
+#define CHECK_NUMBER_OR_FLOAT_COERCE_MARKER(2749,86250
+CHECK_NUMBER_CAR 2760,86660
+CHECK_NUMBER_CDR 2768,86782
+#define DEFUN(2803,88377
+#define DEFUN(2812,88845
+FUNCTIONP 2822,89200
+enum maxargs2831,89395
+ MANY 2833,89412
+ UNEVALLED 2834,89427
+#define CALLMANY(2838,89530
+#define CALLN(2844,89883
+#define DEFVAR_LISP(2869,91088
+#define DEFVAR_LISP_NOPRO(2874,91260
+#define DEFVAR_BOOL(2879,91442
+#define DEFVAR_INT(2884,91615
+#define DEFVAR_BUFFER_DEFAULTS(2890,91786
+#define DEFVAR_KBOARD(2896,91990
+typedef jmp_buf sys_jmp_buf;2906,92314
+# define sys_setjmp(2907,92343
+# define sys_longjmp(2908,92378
+typedef sigjmp_buf sys_jmp_buf;2910,92450
+# define sys_setjmp(2911,92482
+# define sys_longjmp(2912,92522
+typedef jmp_buf sys_jmp_buf;2916,92681
+# define sys_setjmp(2917,92710
+# define sys_longjmp(2918,92744
+enum specbind_tag 2943,93796
+ SPECPDL_UNWIND,2944,93816
+ SPECPDL_UNWIND_PTR,2945,93885
+ SPECPDL_UNWIND_INT,2946,93936
+ SPECPDL_UNWIND_VOID,2947,93984
+ SPECPDL_BACKTRACE,2948,94038
+ SPECPDL_LET,2949,94096
+ SPECPDL_LET_LOCAL,2951,94226
+ SPECPDL_LET_DEFAULT 2952,94283
+union specbinding2955,94355
+SPECPDL_INDEX 2996,95379
+enum handlertype 3021,96401
+enum handlertype { CATCHER,3021,96401
+enum handlertype { CATCHER, CONDITION_CASE 3021,96401
+struct handler3023,96448
+#define PUSH_HANDLER(3053,97437
+#define QUIT 3101,99214
+#define QUITP 3112,99464
+struct gcpro3132,100307
+#define GC_USE_GCPROS_AS_BEFORE 3171,101288
+#define GC_MAKE_GCPROS_NOOPS 3172,101323
+#define GC_MARK_STACK_CHECK_GCPROS 3173,101355
+#define GC_USE_GCPROS_CHECK_ZOMBIES 3174,101392
+#define GC_MARK_STACK 3177,101453
+#define BYTE_MARK_STACK 3181,101553
+#define GCPRO1(3190,101824
+#define GCPRO2(3191,101864
+#define GCPRO3(3192,101930
+#define GCPRO4(3194,102025
+#define GCPRO5(3196,102145
+#define GCPRO6(3198,102290
+#define GCPRO7(3201,102465
+#define UNGCPRO 3202,102544
+#define GCPRO1(3208,102644
+#define GCPRO2(3212,102766
+#define GCPRO3(3217,102958
+#define GCPRO4(3223,103220
+#define GCPRO5(3230,103551
+#define GCPRO6(3238,103952
+#define GCPRO7(3247,104422
+#define UNGCPRO 3257,104962
+#define GCPRO1(3263,105056
+#define GCPRO2(3269,105290
+#define GCPRO3(3278,105708
+#define GCPRO4(3289,106265
+#define GCPRO5(3302,106963
+#define GCPRO6(3317,107803
+#define GCPRO7(3334,108784
+#define UNGCPRO 3353,109907
+#define RETURN_UNGCPRO(3363,110174
+vcopy 3384,110648
+set_hash_key_slot 3393,110923
+set_hash_value_slot 3399,111062
+set_symbol_function 3408,111297
+set_symbol_plist 3414,111412
+set_symbol_next 3420,111515
+blv_found 3428,111688
+set_overlay_plist 3437,111871
+string_intervals 3445,112022
+set_string_intervals 3453,112144
+set_char_table_defalt 3462,112346
+set_char_table_purpose 3467,112458
+set_char_table_extras 3475,112627
+set_char_table_contents 3482,112836
+set_sub_char_table_contents 3489,113031
+enum Arith_Comparison 3497,113294
+ ARITH_EQUAL,3498,113318
+ ARITH_NOTEQUAL,3499,113333
+ ARITH_LESS,3500,113351
+ ARITH_GRTR,3501,113365
+ ARITH_LESS_OR_EQUAL,3502,113379
+ ARITH_GRTR_OR_EQUAL3503,113402
+#define INTEGER_TO_CONS(3511,113753
+#define CONS_TO_INTEGER(3529,114616
+enum { NEXT_ALMOST_PRIME_LIMIT 3573,116320
+extern EMACS_INT next_almost_prime 3574,116359
+enum constype 3739,123811
+enum constype {CONSTYPE_HEAP,CONSTYPE_HEAP3739,123811
+enum constype {CONSTYPE_HEAP, CONSTYPE_PURE}CONSTYPE_PURE3739,123811
+list2i 3745,124001
+list3i 3751,124110
+list4i 3757,124249
+extern Lisp_Object make_formatted_string 3767,124625
+build_pure_c_string 3792,125653
+build_string 3801,125858
+make_uninit_vector 3820,126429
+make_uninit_sub_char_table 3833,126648
+#define ALLOCATE_PSEUDOVECTOR(3850,127192
+#define ALLOCATE_ZEROED_PSEUDOVECTOR(3858,127528
+INLINE void 3890,128934
+extern void *r_alloc r_alloc3895,129055
+#define FLOAT_TO_STRING_BUFSIZE 3927,130518
+intern 3968,132125
+intern_c_string 3974,132213
+extern _Noreturn void error 4034,135592
+fast_string_match_ignore_case 4136,140080
+INLINE void fixup_locale 4241,143845
+INLINE void synchronize_system_messages_locale 4242,143880
+INLINE void synchronize_system_time_locale 4243,143937
+#define IS_DAEMON 4257,144410
+#define DAEMON_RUNNING 4258,144450
+#define IS_DAEMON 4261,144549
+#define DAEMON_RUNNING 4262,144594
+# define WAIT_READING_MAX 4281,145413
+# define WAIT_READING_MAX 4283,145485
+extern _Noreturn void emacs_abort 4374,148377
+egetenv 4532,152800
+#define eabs(4545,153296
+#define make_fixnum_or_float(4550,153429
+enum MAX_ALLOCA 4556,153680
+enum MAX_ALLOCA { MAX_ALLOCA 4556,153680
+extern void *record_xmalloc record_xmalloc4558,153725
+#define USE_SAFE_ALLOCA 4560,153791
+#define AVAIL_ALLOCA(4564,153924
+#define SAFE_ALLOCA(4568,154035
+#define SAFE_NALLOCA(4576,154376
+#define SAFE_ALLOCA_STRING(4590,154852
+#define SAFE_FREE(4598,155104
+#define SAFE_ALLOCA_LISP(4625,155682
+# define USE_STACK_LISP_OBJECTS 4652,156804
+# undef USE_STACK_LISP_OBJECTS4658,156970
+# define USE_STACK_LISP_OBJECTS 4659,157001
+enum { defined_GC_CHECK_STRING_BYTES 4663,157076
+enum { defined_GC_CHECK_STRING_BYTES 4665,157129
+union Aligned_Cons4670,157263
+union Aligned_String4676,157343
+ USE_STACK_CONS 4689,157698
+ USE_STACK_STRING 4691,157804
+#define STACK_CONS(4699,158141
+#define AUTO_CONS_EXPR(4701,158238
+#define AUTO_CONS(4709,158601
+#define AUTO_LIST1(4710,158672
+#define AUTO_LIST2(4712,158780
+#define AUTO_LIST3(4716,158935
+#define AUTO_LIST4(4720,159110
+# define verify_ascii(4732,159501
+#define AUTO_STRING(4740,159809
+#define FOR_EACH_TAIL(4752,160273
+#define FOR_EACH_ALIST_VALUE(4766,160764
+maybe_gc 4774,161051
+functionp 4784,161290
c-src/machsyscalls.c,23
#define SYSCALL(6,113
@@ -2157,27 +2153,27 @@ cp-src/burton.cpp,124
cp-src/functions.cpp,778
void Date::setDate setDate5,148
-void Date::plus plus32,939
-void Date::minus minus42,1229
-void Date::shift shift52,1407
-Date & Date::operator = operator =62,1628
-Date & Date::operator += operator +=69,1789
-Date & Date::operator -= operator -=78,1939
-Date & Date::operator ++ operator ++87,2080
-Date & Date::operator -- operator --96,2216
-int Date::operator - operator -104,2331
-int Date::operator < operator <112,2483
-int Date::operator > operator >116,2557
-int Date::operator == operator ==120,2631
-ostream& operator << operator <<124,2707
-istream& operator >> operator >>133,2943
-bool isLeap 159,3543
-bool isHoliday 163,3629
-void asort(173,3865
-void ReadVacation 186,4064
-void Debug 201,4523
-int WorkingDays(211,4867
-Date StartDay(226,5129
+void Date::plus plus32,938
+void Date::minus minus42,1226
+void Date::shift shift52,1404
+Date & Date::operator = operator =62,1625
+Date & Date::operator += operator +=69,1786
+Date & Date::operator -= operator -=78,1935
+Date & Date::operator ++ operator ++87,2076
+Date & Date::operator -- operator --96,2212
+int Date::operator - operator -104,2327
+int Date::operator < operator <112,2479
+int Date::operator > operator >116,2553
+int Date::operator == operator ==120,2627
+ostream& operator << operator <<124,2703
+istream& operator >> operator >>133,2939
+bool isLeap 159,3539
+bool isHoliday 163,3625
+void asort(173,3861
+void ReadVacation 186,4060
+void Debug 201,4519
+int WorkingDays(211,4863
+Date StartDay(226,5125
cp-src/MDiagArray2.h,482
#define octave_MDiagArray2_h 29,870
@@ -2307,134 +2303,134 @@ main(37,571
class D 41,622
D(43,659
-el-src/TAGTEST.EL,179
-(foo::defmumble bletch 1,0
-(defun foo==bar foo==bar2,33
-(defalias 'pending-delete-mode pending-delete-mode6,149
-(defalias (quote explicitly-quoted-pending-delete-mode)9,222
+el-src/TAGTEST.EL,181
+(foo::defmumble bletch 3,33
+(defun foo==bar foo==bar4,66
+(defalias 'pending-delete-mode pending-delete-mode8,182
+(defalias (quote explicitly-quoted-pending-delete-mode)11,255
el-src/emacs/lisp/progmodes/etags.el,5069
-(defvar tags-file-name 34,1034
-(defgroup etags 43,1498
-(defcustom tags-case-fold-search 47,1566
-(defcustom tags-table-list 59,2051
-(defcustom tags-compression-info-list69,2449
-(defcustom tags-add-tables 88,3231
-(defcustom tags-revert-without-query 98,3627
-(defvar tags-table-computed-list 103,3778
-(defvar tags-table-computed-list-for 112,4262
-(defvar tags-table-list-pointer 117,4510
-(defvar tags-table-list-started-at 121,4701
-(defvar tags-table-set-list 124,4821
-(defcustom find-tag-hook 129,5000
-(defcustom find-tag-default-function 137,5263
-(define-obsolete-variable-alias 'find-tag-marker-ring-lengthfind-tag-marker-ring-length145,5602
-(defcustom tags-tag-face 148,5699
-(defcustom tags-apropos-verbose 154,5834
-(defcustom tags-apropos-additional-actions 160,5998
-(defvaralias 'find-tag-marker-ring find-tag-marker-ring183,6917
-(defvar default-tags-table-function 189,7097
-(defvar tags-location-ring 194,7323
-(defvar tags-table-files 201,7599
-(defvar tags-completion-table 206,7766
-(defvar tags-included-tables 209,7858
-(defvar next-file-list 212,7953
-(defvar tags-table-format-functions 217,8059
-(defvar file-of-tag-function 224,8440
-(defvar tags-table-files-function 228,8634
-(defvar tags-completion-table-function 230,8745
-(defvar snarf-tag-function 232,8840
-(defvar goto-tag-location-function 236,9049
-(defvar find-tag-regexp-search-function 239,9222
-(defvar find-tag-regexp-tag-order 241,9343
-(defvar find-tag-regexp-next-line-after-failure-p 243,9452
-(defvar find-tag-search-function 245,9572
-(defvar find-tag-tag-order 247,9679
-(defvar find-tag-next-line-after-failure-p 249,9774
-(defvar list-tags-function 251,9880
-(defvar tags-apropos-function 253,9968
-(defvar tags-included-tables-function 255,10062
-(defvar verify-tags-table-function 257,10181
-(defun initialize-new-tags-table 260,10292
-(defun tags-table-mode 276,10980
-(defun visit-tags-table 285,11245
-(defun tags-table-check-computed-list 321,12783
-(defun tags-table-extend-computed-list 360,14654
-(defun tags-expand-table-name 400,16367
-(defun tags-table-list-member 409,16710
-(defun tags-verify-table 421,17182
-(defun tags-table-including 470,19302
-(defun tags-next-table 522,21346
-(defun visit-tags-table-buffer 543,22203
-(defun tags-reset-tags-tables 712,28513
-(defun file-of-tag 731,29170
-(defun tags-table-files 740,29519
-(defun tags-included-tables 749,29869
-(defun tags-completion-table 755,30115
-(defun tags-lazy-completion-table 783,31309
-(defun tags-completion-at-point-function 799,31944
-(defun find-tag-tag 818,32694
-(defvar last-tag 837,33367
-(defun find-tag-interactive 840,33426
-(defvar find-tag-history 852,33841
-(defun find-tag-noselect 860,34011
-(defun find-tag 932,37125
-(defun find-tag-other-window 959,38341
-(defun find-tag-other-frame 1000,40269
-(defun find-tag-regexp 1025,41443
-(defalias 'pop-tag-mark pop-tag-mark1049,42605
-(defvar tag-lines-already-matched 1052,42656
-(defun find-tag-in-order 1055,42763
-(defun tag-find-file-of-tag-noselect 1167,47109
-(defun tag-find-file-of-tag 1200,48955
-(defun etags-recognize-tags-table 1208,49181
-(defun etags-verify-tags-table 1241,50812
-(defun etags-file-of-tag 1246,51010
-(defun etags-tags-completion-table 1256,51345
-(defun etags-snarf-tag 1286,52551
-(defun etags-goto-tag-location 1324,54120
-(defun etags-list-tags 1388,56563
-(defmacro tags-with-face 1423,57838
-(defun etags-tags-apropos-additional 1431,58171
-(defun etags-tags-apropos 1465,59408
-(defun etags-tags-table-files 1527,61617
-(defun etags-tags-included-tables 1542,62053
-(defun tags-recognize-empty-tags-table 1559,62593
-(defun tag-exact-file-name-match-p 1587,63739
-(defun tag-file-name-match-p 1596,64132
-(defun tag-exact-match-p 1609,64688
-(defun tag-implicit-name-match-p 1620,65256
-(defun tag-symbol-match-p 1633,65856
-(defun tag-word-match-p 1643,66292
-(defun tag-partial-file-name-match-p 1652,66690
-(defun tag-any-match-p 1662,67134
-(defun tag-re-match-p 1667,67318
-(defcustom tags-loop-revert-buffers 1675,67567
-(defun next-file 1685,67976
-(defvar tags-loop-operate 1760,70890
-(defvar tags-loop-scan1763,70984
-(defun tags-loop-eval 1771,71313
-(defun tags-loop-continue 1782,71642
-(defun tags-search 1850,73948
-(defun tags-query-replace 1871,74774
-(defun tags-complete-tags-table-file 1896,75998
-(defun list-tags 1906,76377
-(defun tags-apropos 1934,77330
-(define-button-type 'tags-select-tags-tabletags-select-tags-table1957,78156
-(defun select-tags-table 1964,78395
-(defvar select-tags-table-mode-map 2019,80522
-(define-derived-mode select-tags-table-mode 2030,80905
-(defun select-tags-table-select 2034,81089
-(defun select-tags-table-quit 2043,81455
-(defun complete-tag 2049,81610
-(defconst etags--xref-limit 2074,82551
-(defvar etags-xref-find-definitions-tag-order 2076,82586
-(defun etags-xref-find 2082,82876
-(defun etags--xref-find-definitions 2096,83405
-(defclass xref-etags-location 2129,85119
-(defun xref-make-etags-location 2135,85342
-(cl-defmethod xref-location-marker 2139,85497
-(cl-defmethod xref-location-line 2146,85741
+(defvar tags-file-name 34,1035
+(defgroup etags 43,1499
+(defcustom tags-case-fold-search 47,1567
+(defcustom tags-table-list 59,2052
+(defcustom tags-compression-info-list69,2450
+(defcustom tags-add-tables 88,3232
+(defcustom tags-revert-without-query 98,3628
+(defvar tags-table-computed-list 103,3779
+(defvar tags-table-computed-list-for 112,4263
+(defvar tags-table-list-pointer 117,4511
+(defvar tags-table-list-started-at 121,4702
+(defvar tags-table-set-list 124,4822
+(defcustom find-tag-hook 129,5001
+(defcustom find-tag-default-function 137,5264
+(define-obsolete-variable-alias 'find-tag-marker-ring-lengthfind-tag-marker-ring-length145,5603
+(defcustom tags-tag-face 148,5700
+(defcustom tags-apropos-verbose 154,5835
+(defcustom tags-apropos-additional-actions 160,5999
+(defvaralias 'find-tag-marker-ring find-tag-marker-ring183,6921
+(defvar default-tags-table-function 189,7101
+(defvar tags-location-ring 194,7327
+(defvar tags-table-files 201,7603
+(defvar tags-completion-table 206,7770
+(defvar tags-included-tables 209,7862
+(defvar next-file-list 212,7957
+(defvar tags-table-format-functions 217,8063
+(defvar file-of-tag-function 224,8444
+(defvar tags-table-files-function 228,8638
+(defvar tags-completion-table-function 230,8749
+(defvar snarf-tag-function 232,8844
+(defvar goto-tag-location-function 236,9053
+(defvar find-tag-regexp-search-function 239,9226
+(defvar find-tag-regexp-tag-order 241,9347
+(defvar find-tag-regexp-next-line-after-failure-p 243,9456
+(defvar find-tag-search-function 245,9576
+(defvar find-tag-tag-order 247,9683
+(defvar find-tag-next-line-after-failure-p 249,9778
+(defvar list-tags-function 251,9884
+(defvar tags-apropos-function 253,9972
+(defvar tags-included-tables-function 255,10066
+(defvar verify-tags-table-function 257,10185
+(defun initialize-new-tags-table 260,10296
+(defun tags-table-mode 276,10984
+(defun visit-tags-table 285,11249
+(defun tags-table-check-computed-list 321,12787
+(defun tags-table-extend-computed-list 360,14658
+(defun tags-expand-table-name 400,16371
+(defun tags-table-list-member 409,16714
+(defun tags-verify-table 421,17186
+(defun tags-table-including 470,19306
+(defun tags-next-table 522,21350
+(defun visit-tags-table-buffer 543,22207
+(defun tags-reset-tags-tables 712,28517
+(defun file-of-tag 731,29174
+(defun tags-table-files 740,29524
+(defun tags-included-tables 749,29874
+(defun tags-completion-table 755,30120
+(defun tags-lazy-completion-table 783,31314
+(defun tags-completion-at-point-function 799,31949
+(defun find-tag-tag 818,32699
+(defvar last-tag 837,33372
+(defun find-tag-interactive 840,33431
+(defvar find-tag-history 852,33846
+(defun find-tag-noselect 860,34016
+(defun find-tag 932,37130
+(defun find-tag-other-window 959,38346
+(defun find-tag-other-frame 1000,40274
+(defun find-tag-regexp 1025,41448
+(defalias 'pop-tag-mark pop-tag-mark1049,42610
+(defvar tag-lines-already-matched 1052,42661
+(defun find-tag-in-order 1055,42768
+(defun tag-find-file-of-tag-noselect 1167,47114
+(defun tag-find-file-of-tag 1200,48960
+(defun etags-recognize-tags-table 1208,49186
+(defun etags-verify-tags-table 1241,50817
+(defun etags-file-of-tag 1246,51015
+(defun etags-tags-completion-table 1256,51350
+(defun etags-snarf-tag 1286,52556
+(defun etags-goto-tag-location 1324,54125
+(defun etags-list-tags 1388,56568
+(defmacro tags-with-face 1423,57843
+(defun etags-tags-apropos-additional 1431,58176
+(defun etags-tags-apropos 1465,59413
+(defun etags-tags-table-files 1527,61622
+(defun etags-tags-included-tables 1542,62058
+(defun tags-recognize-empty-tags-table 1559,62598
+(defun tag-exact-file-name-match-p 1587,63744
+(defun tag-file-name-match-p 1596,64137
+(defun tag-exact-match-p 1609,64693
+(defun tag-implicit-name-match-p 1620,65261
+(defun tag-symbol-match-p 1633,65861
+(defun tag-word-match-p 1643,66297
+(defun tag-partial-file-name-match-p 1652,66695
+(defun tag-any-match-p 1662,67139
+(defun tag-re-match-p 1667,67323
+(defcustom tags-loop-revert-buffers 1675,67572
+(defun next-file 1685,67981
+(defvar tags-loop-operate 1760,70895
+(defvar tags-loop-scan1763,70989
+(defun tags-loop-eval 1771,71318
+(defun tags-loop-continue 1782,71647
+(defun tags-search 1850,73953
+(defun tags-query-replace 1871,74779
+(defun tags-complete-tags-table-file 1896,76003
+(defun list-tags 1906,76382
+(defun tags-apropos 1934,77335
+(define-button-type 'tags-select-tags-tabletags-select-tags-table1957,78161
+(defun select-tags-table 1964,78400
+(defvar select-tags-table-mode-map 2019,80527
+(define-derived-mode select-tags-table-mode 2030,80910
+(defun select-tags-table-select 2034,81094
+(defun select-tags-table-quit 2043,81460
+(defun complete-tag 2049,81615
+(defconst etags--xref-limit 2074,82556
+(defvar etags-xref-find-definitions-tag-order 2076,82591
+(defun etags-xref-find 2082,82881
+(defun etags--xref-find-definitions 2096,83410
+(defclass xref-etags-location 2129,85124
+(defun xref-make-etags-location 2135,85347
+(cl-defmethod xref-location-marker 2139,85502
+(cl-defmethod xref-location-line 2146,85746
erl-src/gs_dialog.erl,98
-define(VERSION2,32
@@ -2505,10 +2501,10 @@ func main(29,285
html-src/softwarelibero.html,200
Cos'è il software libero?4,38
-Licenze d'uso di un programmalicenze65,2500
-Sfatiamo alcuni miti138,6118
-Il movimento open sourceoss191,8037
-Impatto pratico del software liberoimpatto231,10066
+Licenze d'uso di un programmalicenze65,2502
+Sfatiamo alcuni miti138,6122
+Il movimento open sourceoss191,8041
+Impatto pratico del software liberoimpatto231,10070
html-src/index.shtml,104
&nbsp;8,281
@@ -2534,13 +2530,13 @@ MTGmtg41,1482
Fracasfracas65,2624
GaliLEOgalileo101,4232
Leasqrleasqr114,4677
-Free software that I wrote for the GNU project or for my personal or workgnu142,6065
-Etagsetags148,6180
-checkiso161,6729
-cgrep178,7547
-debian-bug.eldebian-bug190,7979
-tcpdump205,8564
-Links to interesting softwarelinks216,8891
+Free software that I wrote for the GNU project or for my personal or workgnu142,6066
+Etagsetags148,6181
+checkiso161,6731
+cgrep178,7549
+debian-bug.eldebian-bug190,7981
+tcpdump205,8566
+Links to interesting softwarelinks216,8893
lua-src/allegro.lua,400
local function get_layer_by_name 7,175
@@ -3070,22 +3066,22 @@ ord_add_element(71,1867
ord_del_element(85,2344
ord_disjoint(100,2783
ord_intersect(108,2953
-ord_intersection(126,3552
-ord_intersection3(130,3691
-ord_intersection(150,4531
-ord_intersection4(154,4703
-ord_intersection(176,5664
-ord_intersection2(181,5812
-ord_member(200,6318
-ord_seteq(216,6683
-ord_setproduct(225,6971
-ord_subset(240,7377
-ord_subtract(257,7861
-ord_symdiff(265,8054
-ord_union(288,8887
-ord_union4(303,9352
-ord_union(324,10171
-ord_union_all(329,10313
+ord_intersection(126,3553
+ord_intersection3(130,3692
+ord_intersection(150,4533
+ord_intersection4(154,4705
+ord_intersection(176,5666
+ord_intersection2(181,5814
+ord_member(200,6320
+ord_seteq(216,6685
+ord_setproduct(225,6973
+ord_subset(240,7379
+ord_subtract(257,7863
+ord_symdiff(265,8056
+ord_union(288,8889
+ord_union4(303,9354
+ord_union(324,10173
+ord_union_all(329,10315
prol-src/natded.prolog,2319
expandmng(100,2879
@@ -3107,92 +3103,92 @@ complete(328,10055
add_active(340,10527
parse(353,10949
derived_analyses(364,11341
-build(378,11965
-buildact(392,12521
-mapsyn(412,13542
-add_edge(434,14278
-findcats(447,14758
-normalize_tree(465,15478
-normalize_trees(475,15856
-expandmng_tree(486,16248
-expandmng_trees(496,16614
-cat(511,17013
-subtree(644,21266
-hypothetical_mem(653,21565
-make_coor(667,22130
-start_up:-start_up688,23013
-tokenizeatom(710,23921
-tokenize(720,24348
-isoperator(752,25377
-isoptab(756,25431
-specialsymbol(765,25756
-sstab(771,25861
-parse_cgi(787,26347
-keyvalseq(792,26510
-andkeyvalseq(796,26609
-keyval(799,26688
-valseq(807,26920
-plusvalseq(810,27007
-val(816,27109
-argvals(824,27426
-commaargvals(828,27503
-atomval(833,27578
-atom(836,27640
-action(846,28004
-keyvalcgi(864,28649
-keyvalscgi(865,28670
-outsyn(868,28726
-act(876,29060
-actout(901,29906
-texttreelist(912,30089
-htmltreelist(918,30190
-fitchtreelist(924,30304
-pp_html_table_tree(938,30759
-pp_html_tree(949,31113
-pp_html_trees(988,32381
-pp_html_table_fitch_tree(999,32769
-pp_html_fitch_tree(1017,33672
-removeexp(1129,39002
-splitexp(1142,39490
-pp_exp(1155,39990
-map_word(1168,40249
-pp_exps(1180,40474
-pp_tree(1188,40777
-pp_trees(1216,41807
-pp_word_list(1225,42128
-pp_word(1231,42262
-pp_word_list_rest(1238,42569
-pp_cat(1248,42929
-pp_syn(1255,43196
-pp_syn_paren(1276,43899
-pp_paren(1293,44377
-pp_syn_back(1300,44661
-pp_bas_cat(1311,45001
-writecat(1322,45409
-writesubs(1351,46455
-writesups(1361,46757
-writelistsubs(1371,47090
-pp_lam(1380,47408
-pp_lam_bracket(1398,48022
-pp_lam_paren(1407,48338
-pp_rule(1429,49238
-member(1447,49866
-append_list(1451,49919
-append(1456,50010
-at_least_one_member(1460,50076
-numbervars(1464,50171
-reverse(1467,50209
-select(1471,50290
-select_last(1475,50357
-cat_atoms(1479,50436
-writelist(1485,50524
-write_lex_cat(1492,50676
-writebreaklex(1500,50988
-write_lex(1513,51265
-writebreak(1521,51541
-tt:-tt1531,51713
-mt:-mt1534,51784
-cmt:-cmt1537,51878
+build(378,11967
+buildact(392,12523
+mapsyn(412,13544
+add_edge(434,14280
+findcats(447,14760
+normalize_tree(465,15480
+normalize_trees(475,15858
+expandmng_tree(486,16250
+expandmng_trees(496,16616
+cat(511,17015
+subtree(644,21268
+hypothetical_mem(653,21567
+make_coor(667,22132
+start_up:-start_up688,23015
+tokenizeatom(710,23923
+tokenize(720,24350
+isoperator(752,25379
+isoptab(756,25433
+specialsymbol(765,25758
+sstab(771,25863
+parse_cgi(787,26349
+keyvalseq(792,26512
+andkeyvalseq(796,26611
+keyval(799,26690
+valseq(807,26922
+plusvalseq(810,27009
+val(816,27111
+argvals(824,27428
+commaargvals(828,27505
+atomval(833,27580
+atom(836,27642
+action(846,28006
+keyvalcgi(864,28651
+keyvalscgi(865,28672
+outsyn(868,28728
+act(876,29062
+actout(901,29908
+texttreelist(912,30091
+htmltreelist(918,30192
+fitchtreelist(924,30306
+pp_html_table_tree(938,30761
+pp_html_tree(949,31115
+pp_html_trees(988,32383
+pp_html_table_fitch_tree(999,32771
+pp_html_fitch_tree(1017,33674
+removeexp(1129,39004
+splitexp(1142,39492
+pp_exp(1155,39992
+map_word(1168,40251
+pp_exps(1180,40476
+pp_tree(1188,40779
+pp_trees(1216,41809
+pp_word_list(1225,42130
+pp_word(1231,42264
+pp_word_list_rest(1238,42571
+pp_cat(1248,42931
+pp_syn(1255,43198
+pp_syn_paren(1276,43901
+pp_paren(1293,44379
+pp_syn_back(1300,44663
+pp_bas_cat(1311,45003
+writecat(1322,45411
+writesubs(1351,46457
+writesups(1361,46759
+writelistsubs(1371,47092
+pp_lam(1380,47410
+pp_lam_bracket(1398,48024
+pp_lam_paren(1407,48340
+pp_rule(1429,49240
+member(1447,49868
+append_list(1451,49921
+append(1456,50012
+at_least_one_member(1460,50078
+numbervars(1464,50173
+reverse(1467,50211
+select(1471,50292
+select_last(1475,50359
+cat_atoms(1479,50438
+writelist(1485,50526
+write_lex_cat(1492,50678
+writebreaklex(1500,50990
+write_lex(1513,51267
+writebreak(1521,51543
+tt:-tt1531,51715
+mt:-mt1534,51786
+cmt:-cmt1537,51880
pyt-src/server.py,1438
class Controls:Controls17,358
@@ -3300,6 +3296,11 @@ module A9,57
alias_method ( :foo2,foo237,586
A::Constant Constant42,655
+rs-src/test.rs,52
+enum IpAddrKind 3,11
+fn test1(8,48
+fn main(12,88
+
scm-src/test.scm,260
(define hello 1,0
(set! hello 3,32
@@ -3317,730 +3318,825 @@ tex-src/gzip.texi,303
@node Top,62,2139
@node Copying,80,2652
@node Overview,83,2705
-@node Sample,166,7272
-@node Invoking gzip,Invoking gzip210,8828
-@node Advanced usage,Advanced usage357,13496
-@node Environment,420,15208
-@node Tapes,437,15769
-@node Problems,460,16768
-@node Concept Index,Concept Index473,17288
+@node Sample,166,7273
+@node Invoking gzip,Invoking gzip210,8829
+@node Advanced usage,Advanced usage357,13497
+@node Environment,420,15209
+@node Tapes,437,15770
+@node Problems,460,16769
+@node Concept Index,Concept Index473,17289
tex-src/texinfo.tex,30627
-\def\texinfoversion{\texinfoversion26,1032
-\def\tie{\tie49,1523
-\def\gloggingall{\gloggingall72,2273
-\def\loggingall{\loggingall73,2342
-\def\onepageout#1{\onepageout99,3279
-\def\croppageout#1{\croppageout115,4029
-\def\cropmarks{\cropmarks142,5089
-\def\pagebody#1{\pagebody144,5136
-\def\ewtop{\ewtop157,5591
-\def\nstop{\nstop158,5655
-\def\ewbot{\ewbot160,5738
-\def\nsbot{\nsbot161,5802
-\def\parsearg #1{\parsearg170,6101
-\def\parseargx{\parseargx172,6179
-\def\parseargline{\parseargline182,6419
-\def\flushcr{\flushcr186,6540
-\newif\ifENV \ENVfalse \def\inENV{\inENV190,6739
-\def\ENVcheck{\ENVcheck191,6803
-\outer\def\begin{\begin198,7050
-\def\beginxxx #1{\beginxxx200,7088
-\def\end{\end208,7343
-\def\endxxx #1{\endxxx210,7371
-\def\errorE#1{\errorE216,7560
-\def\singlespace{\singlespace222,7754
-\def\@{\@232,7977
-\def\`{\`236,8077
-\def\'{\'237,8089
-\def\mylbrace {\mylbrace241,8137
-\def\myrbrace {\myrbrace242,8170
-\def\:{\:247,8284
-\def\*{\*250,8338
-\def\.{\.253,8414
-\def\w#1{\w258,8645
-\def\group{\group268,9128
- \def\Egroup{\Egroup273,9292
-\def\need{\need289,9734
-\def\needx#1{\needx300,10011
-\def\dots{\dots339,11397
-\def\page{\page343,11461
-\def\exdent{\exdent353,11788
-\def\exdentyyy #1{\exdentyyy354,11821
-\def\nofillexdent{\nofillexdent357,11965
-\def\nofillexdentyyy #1{\nofillexdentyyy358,12010
-\def\include{\include365,12194
-\def\includezzz #1{\includezzz366,12229
-\def\thisfile{\thisfile369,12280
-\def\center{\center373,12343
-\def\centerzzz #1{\centerzzz374,12376
-\def\sp{\sp380,12518
-\def\spxxx #1{\spxxx381,12543
-\def\comment{\comment387,12717
-\def\commentxxx #1{\commentxxx390,12814
-\def\ignoresections{\ignoresections396,12983
-\let\chapter=\relax=\relax397,13005
-\let\section=\relax=\relax406,13250
-\let\subsection=\relax=\relax409,13311
-\let\subsubsection=\relax=\relax410,13334
-\let\appendix=\relax=\relax411,13360
-\let\appendixsec=\relaxsec=\relax412,13381
-\let\appendixsection=\relaxsection=\relax413,13405
-\let\appendixsubsec=\relaxsubsec=\relax414,13433
-\let\appendixsubsection=\relaxsubsection=\relax415,13460
-\let\appendixsubsubsec=\relaxsubsubsec=\relax416,13491
-\let\appendixsubsubsection=\relaxsubsubsection=\relax417,13521
-\def\ignore{\ignore423,13623
-\long\def\ignorexxx #1\end ignore{\ignorexxx427,13763
-\def\direntry{\direntry429,13822
-\long\def\direntryxxx #1\end direntry{\direntryxxx430,13861
-\def\ifset{\ifset434,13971
-\def\ifsetxxx #1{\ifsetxxx436,14029
-\def\Eifset{\Eifset440,14156
-\def\ifsetfail{\ifsetfail441,14170
-\long\def\ifsetfailxxx #1\end ifset{\ifsetfailxxx442,14226
-\def\ifclear{\ifclear444,14287
-\def\ifclearxxx #1{\ifclearxxx446,14349
-\def\Eifclear{\Eifclear450,14480
-\def\ifclearfail{\ifclearfail451,14496
-\long\def\ifclearfailxxx #1\end ifclear{\ifclearfailxxx452,14556
-\def\set{\set456,14707
-\def\setxxx #1{\setxxx457,14734
-\def\clear{\clear460,14796
-\def\clearxxx #1{\clearxxx461,14827
-\def\iftex{\iftex466,14944
-\def\Eiftex{\Eiftex467,14957
-\def\ifinfo{\ifinfo468,14971
-\long\def\ifinfoxxx #1\end ifinfo{\ifinfoxxx469,15021
-\long\def\menu #1\end menu{\menu471,15080
-\def\asis#1{\asis472,15109
-\def\math#1{\math485,15652
-\def\node{\node487,15696
-\def\nodezzz#1{\nodezzz488,15734
-\def\nodexxx[#1,#2]{\nodexxx[489,15765
-\def\donoderef{\donoderef492,15827
-\def\unnumbnoderef{\unnumbnoderef496,15948
-\def\appendixnoderef{\appendixnoderef500,16079
-\expandafter\expandafter\expandafter\appendixsetref{setref501,16125
-\let\refill=\relaxill=\relax504,16214
-\def\setfilename{\setfilename509,16428
-\outer\def\bye{\bye518,16674
-\def\inforef #1{\inforef520,16730
-\def\inforefzzz #1,#2,#3,#4**{\inforefzzz521,16768
-\def\losespace #1{\losespace523,16865
-\def\sf{\sf532,17069
-\font\defbf=cmbx10 scaled \magstep1 %was 1314bf=cmbx10558,17864
-\font\deftt=cmtt10 scaled \magstep1tt=cmtt10559,17910
-\def\df{\df560,17946
-\def\resetmathfonts{\resetmathfonts635,20540
-\def\textfonts{\textfonts648,21129
-\def\chapfonts{\chapfonts653,21344
-\def\secfonts{\secfonts658,21560
-\def\subsecfonts{\subsecfonts663,21765
-\def\indexfonts{\indexfonts668,21982
-\def\smartitalicx{\smartitalicx691,22714
-\def\smartitalic#1{\smartitalic692,22790
-\let\cite=\smartitalic=\smartitalic698,22935
-\def\b#1{\b700,22959
-\def\t#1{\t703,22994
-\def\samp #1{\samp706,23146
-\def\key #1{\key707,23179
-\def\ctrl #1{\ctrl708,23240
-\def\tclose#1{\tclose716,23442
-\def\ {\720,23608
-\def\xkey{\xkey728,23877
-\def\kbdfoo#1#2#3\par{\kbdfoo729,23893
-\def\dmn#1{\dmn738,24194
-\def\kbd#1{\kbd740,24221
-\def\l#1{\l742,24278
-\def\r#1{\r744,24307
-\def\sc#1{\sc746,24375
-\def\ii#1{\ii747,24418
-\def\titlefont#1{\titlefont755,24651
-\def\titlepage{\titlepage761,24754
- \def\subtitlefont{\subtitlefont766,24981
- \def\authorfont{\authorfont768,25065
- \def\title{\title774,25275
- \def\titlezzz##1{\titlezzz775,25310
- \def\subtitle{\subtitle783,25625
- \def\subtitlezzz##1{\subtitlezzz784,25666
- \def\author{\author787,25784
- \def\authorzzz##1{\authorzzz788,25821
- \def\page{\page794,26112
-\def\Etitlepage{\Etitlepage804,26281
-\def\finishtitlepage{\finishtitlepage817,26669
-\def\evenheading{\evenheading846,27677
-\def\oddheading{\oddheading847,27720
-\def\everyheading{\everyheading848,27761
-\def\evenfooting{\evenfooting850,27807
-\def\oddfooting{\oddfooting851,27850
-\def\everyfooting{\everyfooting852,27891
-\def\headings #1 {\headings893,29583
-\def\HEADINGSoff{\HEADINGSoff895,29632
-\def\HEADINGSdouble{\HEADINGSdouble904,30059
-\def\HEADINGSsingle{\HEADINGSsingle914,30379
-\def\HEADINGSon{\HEADINGSon922,30600
-\def\HEADINGSafter{\HEADINGSafter924,30634
-\def\HEADINGSdoublex{\HEADINGSdoublex926,30729
-\def\HEADINGSsingleafter{\HEADINGSsingleafter933,30917
-\def\HEADINGSsinglex{\HEADINGSsinglex934,30978
-\def\today{\today943,31253
-\def\thistitle{\thistitle958,31798
-\def\settitle{\settitle959,31823
-\def\settitlezzz #1{\settitlezzz960,31860
-\def\internalBitem{\internalBitem992,32790
-\def\internalBitemx{\internalBitemx993,32840
-\def\internalBxitem "#1"{\internalBxitem995,32885
-\def\internalBxitemx "#1"{\internalBxitemx996,32965
-\def\internalBkitem{\internalBkitem998,33040
-\def\internalBkitemx{\internalBkitemx999,33092
-\def\kitemzzz #1{\kitemzzz1001,33139
-\def\xitemzzz #1{\xitemzzz1004,33241
-\def\itemzzz #1{\itemzzz1007,33344
-\def\item{\item1037,34415
-\def\itemx{\itemx1038,34466
-\def\kitem{\kitem1039,34519
-\def\kitemx{\kitemx1040,34572
-\def\xitem{\xitem1041,34627
-\def\xitemx{\xitemx1042,34680
-\def\description{\description1045,34790
-\def\table{\table1047,34840
-\def\ftable{\ftable1052,34984
-\def\Eftable{\Eftable1056,35130
-\def\vtable{\vtable1059,35199
-\def\Evtable{\Evtable1063,35345
-\def\dontindex #1{\dontindex1066,35414
-\def\fnitemindex #1{\fnitemindex1067,35434
-\def\vritemindex #1{\vritemindex1068,35479
-\def\tablez #1#2#3#4#5#6{\tablez1074,35628
-\def\Edescription{\Edescription1077,35686
-\def\itemfont{\itemfont1082,35888
-\def\Etable{\Etable1090,36114
-\def\itemize{\itemize1103,36438
-\def\itemizezzz #1{\itemizezzz1105,36474
-\def\itemizey #1#2{\itemizey1110,36569
-\def#2{1119,36815
-\def\itemcontents{\itemcontents1120,36856
-\def\bullet{\bullet1123,36904
-\def\minus{\minus1124,36931
-\def\frenchspacing{\frenchspacing1128,37039
-\def\splitoff#1#2\endmark{\splitoff1134,37264
-\def\enumerate{\enumerate1140,37494
-\def\enumeratezzz #1{\enumeratezzz1141,37533
-\def\enumeratey #1 #2\endenumeratey{\enumeratey1142,37586
- \def\thearg{\thearg1146,37733
- \ifx\thearg\empty \def\thearg{\thearg1147,37752
-\def\numericenumerate{\numericenumerate1184,39086
-\def\lowercaseenumerate{\lowercaseenumerate1190,39216
-\def\uppercaseenumerate{\uppercaseenumerate1203,39563
-\def\startenumeration#1{\startenumeration1219,40053
-\def\alphaenumerate{\alphaenumerate1227,40235
-\def\capsenumerate{\capsenumerate1228,40270
-\def\Ealphaenumerate{\Ealphaenumerate1229,40304
-\def\Ecapsenumerate{\Ecapsenumerate1230,40338
-\def\itemizeitem{\itemizeitem1234,40418
-\def\newindex #1{\newindex1259,41275
-\def\defindex{\defindex1268,41564
-\def\newcodeindex #1{\newcodeindex1272,41672
-\def\defcodeindex{\defcodeindex1279,41932
-\def\synindex #1 #2 {\synindex1283,42112
-\def\syncodeindex #1 #2 {\syncodeindex1292,42452
-\def\doindex#1{\doindex1309,43131
-\def\singleindexer #1{\singleindexer1310,43190
-\def\docodeindex#1{\docodeindex1313,43302
-\def\singlecodeindexer #1{\singlecodeindexer1314,43369
-\def\indexdummies{\indexdummies1316,43427
-\def\_{\_1317,43447
-\def\w{\w1318,43475
-\def\bf{\bf1319,43502
-\def\rm{\rm1320,43531
-\def\sl{\sl1321,43560
-\def\sf{\sf1322,43589
-\def\tt{\tt1323,43617
-\def\gtr{\gtr1324,43645
-\def\less{\less1325,43675
-\def\hat{\hat1326,43707
-\def\char{\char1327,43737
-\def\TeX{\TeX1328,43769
-\def\dots{\dots1329,43799
-\def\copyright{\copyright1330,43832
-\def\tclose##1{\tclose1331,43875
-\def\code##1{\code1332,43920
-\def\samp##1{\samp1333,43961
-\def\t##1{\t1334,44002
-\def\r##1{\r1335,44037
-\def\i##1{\i1336,44072
-\def\b##1{\b1337,44107
-\def\cite##1{\cite1338,44142
-\def\key##1{\key1339,44183
-\def\file##1{\file1340,44222
-\def\var##1{\var1341,44263
-\def\kbd##1{\kbd1342,44302
-\def\indexdummyfont#1{\indexdummyfont1347,44458
-\def\indexdummytex{\indexdummytex1348,44484
-\def\indexdummydots{\indexdummydots1349,44508
-\def\indexnofonts{\indexnofonts1351,44534
-\let\w=\indexdummyfontdummyfont1352,44554
-\let\t=\indexdummyfontdummyfont1353,44577
-\let\r=\indexdummyfontdummyfont1354,44600
-\let\i=\indexdummyfontdummyfont1355,44623
-\let\b=\indexdummyfontdummyfont1356,44646
-\let\emph=\indexdummyfontdummyfont1357,44669
-\let\strong=\indexdummyfontdummyfont1358,44695
-\let\cite=\indexdummyfont=\indexdummyfont1359,44723
-\let\sc=\indexdummyfontdummyfont1360,44749
-\let\tclose=\indexdummyfontdummyfont1364,44921
-\let\code=\indexdummyfontdummyfont1365,44949
-\let\file=\indexdummyfontdummyfont1366,44975
-\let\samp=\indexdummyfontdummyfont1367,45001
-\let\kbd=\indexdummyfontdummyfont1368,45027
-\let\key=\indexdummyfontdummyfont1369,45052
-\let\var=\indexdummyfontdummyfont1370,45077
-\let\TeX=\indexdummytexdummytex1371,45102
-\let\dots=\indexdummydotsdummydots1372,45126
-\let\indexbackslash=0 %overridden during \printindex.backslash=01382,45378
-\def\doind #1#2{\doind1384,45434
-{\indexdummies % Must do this here, since \bf, etc expand at this stagedummies1386,45477
-\def\rawbackslashxx{\rawbackslashxx1389,45617
-{\indexnofontsnofonts1394,45879
-\def\dosubind #1#2#3{\dosubind1405,46190
-{\indexdummies % Must do this here, since \bf, etc expand at this stagedummies1407,46238
-\def\rawbackslashxx{\rawbackslashxx1410,46342
-{\indexnofontsnofonts1414,46496
-\def\findex {\findex1443,47427
-\def\kindex {\kindex1444,47450
-\def\cindex {\cindex1445,47473
-\def\vindex {\vindex1446,47496
-\def\tindex {\tindex1447,47519
-\def\pindex {\pindex1448,47542
-\def\cindexsub {\cindexsub1450,47566
-\def\printindex{\printindex1462,47893
-\def\doprintindex#1{\doprintindex1464,47934
- \def\indexbackslash{\indexbackslash1481,48419
- \indexfonts\rm \tolerance=9500 \advance\baselineskip -1ptfonts\rm1482,48458
-\def\initial #1{\initial1517,49530
-\def\entry #1#2{\entry1523,49737
- \null\nobreak\indexdotfill % Have leaders before the page number.dotfill1540,50384
-\def\indexdotfill{\indexdotfill1549,50712
-\def\primary #1{\primary1552,50818
-\def\secondary #1#2{\secondary1556,50900
-\noindent\hskip\secondaryindent\hbox{#1}\indexdotfill #2\pardotfill1559,50982
-\newbox\partialpageialpage1566,51155
-\def\begindoublecolumns{\begindoublecolumns1572,51313
- \output={\global\setbox\partialpage=ialpage=1573,51349
-\def\enddoublecolumns{\enddoublecolumns1577,51537
-\def\doublecolumnout{\doublecolumnout1580,51622
- \dimen@=\pageheight \advance\dimen@ by-\ht\partialpageialpage1581,51691
-\def\pagesofar{\pagesofar1584,51869
-\def\balancecolumns{\balancecolumns1588,52106
- \availdimen@=\pageheight \advance\availdimen@ by-\ht\partialpageialpage1594,52277
- \dimen@=\pageheight \advance\dimen@ by-\ht\partialpageialpage1600,52538
-\newcount \appendixno \appendixno = `\@no1627,53443
-\def\appendixletter{\appendixletter1628,53484
-\def\opencontents{\opencontents1632,53587
-\def\thischapter{\thischapter1637,53768
-\def\seccheck#1{\seccheck1638,53806
-\def\chapternofonts{\chapternofonts1643,53910
-\def\result{\result1646,53985
-\def\equiv{\equiv1647,54020
-\def\expansion{\expansion1648,54053
-\def\print{\print1649,54094
-\def\TeX{\TeX1650,54127
-\def\dots{\dots1651,54156
-\def\copyright{\copyright1652,54187
-\def\tt{\tt1653,54228
-\def\bf{\bf1654,54255
-\def\w{\w1655,54283
-\def\less{\less1656,54308
-\def\gtr{\gtr1657,54339
-\def\hat{\hat1658,54368
-\def\char{\char1659,54397
-\def\tclose##1{\tclose1660,54428
-\def\code##1{\code1661,54472
-\def\samp##1{\samp1662,54512
-\def\r##1{\r1663,54552
-\def\b##1{\b1664,54586
-\def\key##1{\key1665,54620
-\def\file##1{\file1666,54658
-\def\kbd##1{\kbd1667,54698
-\def\i##1{\i1669,54806
-\def\cite##1{\cite1670,54840
-\def\var##1{\var1671,54880
-\def\emph##1{\emph1672,54918
-\def\dfn##1{\dfn1673,54958
-\def\thischaptername{\thischaptername1676,54999
-\outer\def\chapter{\chapter1677,55038
-\def\chapterzzz #1{\chapterzzz1678,55079
-{\chapternofonts%nofonts%1687,55475
-\global\let\section = \numberedsec=1692,55628
-\global\let\subsection = \numberedsubsec=1693,55663
-\global\let\subsubsection = \numberedsubsubsec=1694,55704
-\outer\def\appendix{\appendix1697,55755
-\def\appendixzzz #1{\appendixzzz1698,55798
-\global\advance \appendixno by 1 \message{no1700,55875
-\chapmacro {#1}{Appendix \appendixletter}letter1701,55944
-\xdef\thischapter{Appendix \appendixletter: \noexpand\thischaptername}letter:1704,56037
-{\chapternofonts%nofonts%1705,56109
- {#1}{Appendix \appendixletter}letter1707,56165
-\appendixnoderef %noderef1710,56265
-\global\let\section = \appendixsec=1711,56284
-\global\let\subsection = \appendixsubsec=1712,56319
-\global\let\subsubsection = \appendixsubsubsec=1713,56360
-\outer\def\top{\top1716,56411
-\outer\def\unnumbered{\unnumbered1717,56451
-\def\unnumberedzzz #1{\unnumberedzzz1718,56498
-{\chapternofonts%nofonts%1722,56661
-\global\let\section = \unnumberedsec=1727,56811
-\global\let\subsection = \unnumberedsubsec=1728,56848
-\global\let\subsubsection = \unnumberedsubsubsec=1729,56891
-\outer\def\numberedsec{\numberedsec1732,56944
-\def\seczzz #1{\seczzz1733,56985
-{\chapternofonts%nofonts%1736,57141
-\outer\def\appendixsection{\appendixsection1745,57327
-\outer\def\appendixsec{\appendixsec1746,57384
-\def\appendixsectionzzz #1{\appendixsectionzzz1747,57437
-\gdef\thissection{#1}\secheading {#1}{\appendixletter}letter1749,57549
-{\chapternofonts%nofonts%1750,57617
-{#1}{\appendixletter}letter1752,57673
-\appendixnoderef %noderef1755,57773
-\outer\def\unnumberedsec{\unnumberedsec1759,57813
-\def\unnumberedseczzz #1{\unnumberedseczzz1760,57866
-{\chapternofonts%nofonts%1762,57961
-\outer\def\numberedsubsec{\numberedsubsec1770,58129
-\def\numberedsubseczzz #1{\numberedsubseczzz1771,58184
-{\chapternofonts%nofonts%1774,58363
-\outer\def\appendixsubsec{\appendixsubsec1783,58567
-\def\appendixsubseczzz #1{\appendixsubseczzz1784,58622
-\subsecheading {#1}{\appendixletter}letter1786,58744
-{\chapternofonts%nofonts%1787,58809
-{#1}{\appendixletter}letter1789,58868
-\appendixnoderef %noderef1792,58983
-\outer\def\unnumberedsubsec{\unnumberedsubsec1796,59023
-\def\unnumberedsubseczzz #1{\unnumberedsubseczzz1797,59082
-{\chapternofonts%nofonts%1799,59183
-\outer\def\numberedsubsubsec{\numberedsubsubsec1807,59354
-\def\numberedsubsubseczzz #1{\numberedsubsubseczzz1808,59415
-{\chapternofonts%nofonts%1812,59612
-\outer\def\appendixsubsubsec{\appendixsubsubsec1823,59845
-\def\appendixsubsubseczzz #1{\appendixsubsubseczzz1824,59906
- {\appendixletter}letter1827,60045
-{\chapternofonts%nofonts%1828,60111
- {\appendixletter}letter1830,60176
-\appendixnoderef %noderef1834,60310
-\outer\def\unnumberedsubsubsec{\unnumberedsubsubsec1838,60350
-\def\unnumberedsubsubseczzz #1{\unnumberedsubsubseczzz1839,60415
-{\chapternofonts%nofonts%1841,60522
-\def\infotop{\infotop1851,60851
-\def\infounnumbered{\infounnumbered1852,60889
-\def\infounnumberedsec{\infounnumberedsec1853,60934
-\def\infounnumberedsubsec{\infounnumberedsubsec1854,60985
-\def\infounnumberedsubsubsec{\infounnumberedsubsubsec1855,61042
-\def\infoappendix{\infoappendix1857,61106
-\def\infoappendixsec{\infoappendixsec1858,61147
-\def\infoappendixsubsec{\infoappendixsubsec1859,61194
-\def\infoappendixsubsubsec{\infoappendixsubsubsec1860,61247
-\def\infochapter{\infochapter1862,61307
-\def\infosection{\infosection1863,61346
-\def\infosubsection{\infosubsection1864,61385
-\def\infosubsubsection{\infosubsubsection1865,61430
-\global\let\section = \numberedsec=1870,61667
-\global\let\subsection = \numberedsubsec=1871,61702
-\global\let\subsubsection = \numberedsubsubsec=1872,61743
-\def\majorheading{\majorheading1886,62250
-\def\majorheadingzzz #1{\majorheadingzzz1887,62295
-\def\chapheading{\chapheading1893,62528
-\def\chapheadingzzz #1{\chapheadingzzz1894,62571
-\def\heading{\heading1899,62766
-\def\subheading{\subheading1901,62803
-\def\subsubheading{\subsubheading1903,62846
-\def\dobreak#1#2{\dobreak1910,63123
-\def\setchapterstyle #1 {\setchapterstyle1912,63201
-\def\chapbreak{\chapbreak1919,63456
-\def\chappager{\chappager1920,63506
-\def\chapoddpage{\chapoddpage1921,63544
-\def\setchapternewpage #1 {\setchapternewpage1923,63623
-\def\CHAPPAGoff{\CHAPPAGoff1925,63680
-\def\CHAPPAGon{\CHAPPAGon1929,63774
-\global\def\HEADINGSon{\HEADINGSon1932,63865
-\def\CHAPPAGodd{\CHAPPAGodd1934,63907
-\global\def\HEADINGSon{\HEADINGSon1937,64003
-\def\CHAPFplain{\CHAPFplain1941,64057
-\def\chfplain #1#2{\chfplain1945,64149
-\def\unnchfplain #1{\unnchfplain1956,64372
-\def\unnchfopen #1{\unnchfopen1964,64601
-\def\chfopen #1#2{\chfopen1970,64809
-\def\CHAPFopen{\CHAPFopen1975,64953
-\def\subsecheadingbreak{\subsecheadingbreak1982,65171
-\def\secheadingbreak{\secheadingbreak1985,65300
-\def\secheading #1#2#3{\secheading1993,65582
-\def\plainsecheading #1{\plainsecheading1994,65638
-\def\secheadingi #1{\secheadingi1995,65681
-\def\subsecheading #1#2#3#4{\subsecheading2006,66049
-\def\subsecheadingi #1{\subsecheadingi2007,66116
-\def\subsubsecfonts{\subsubsecfonts2014,66413
-\def\subsubsecheading #1#2#3#4#5{\subsubsecheading2017,66536
-\def\subsubsecheadingi #1{\subsubsecheadingi2018,66614
-\def\startcontents#1{\startcontents2032,67086
- \unnumbchapmacro{#1}\def\thischapter{\thischapter2040,67359
-\outer\def\contents{\contents2049,67718
-\outer\def\summarycontents{\summarycontents2057,67862
- \def\secentry ##1##2##3##4{\secentry2067,68233
- \def\unnumbsecentry ##1##2{\unnumbsecentry2068,68268
- \def\subsecentry ##1##2##3##4##5{\subsecentry2069,68303
- \def\unnumbsubsecentry ##1##2{\unnumbsubsecentry2070,68344
- \def\subsubsecentry ##1##2##3##4##5##6{\subsubsecentry2071,68382
- \def\unnumbsubsubsecentry ##1##2{\unnumbsubsubsecentry2072,68429
-\def\chapentry#1#2#3{\chapentry2085,68863
-\def\shortchapentry#1#2#3{\shortchapentry2088,68980
- {#2\labelspace #1}space2091,69090
-\def\unnumbchapentry#1#2{\unnumbchapentry2094,69144
-\def\shortunnumberedentry#1#2{\shortunnumberedentry2095,69191
-\def\secentry#1#2#3#4{\secentry2102,69355
-\def\unnumbsecentry#1#2{\unnumbsecentry2103,69414
-\def\subsecentry#1#2#3#4#5{\subsecentry2106,69475
-\def\unnumbsubsecentry#1#2{\unnumbsubsecentry2107,69545
-\def\subsubsecentry#1#2#3#4#5#6{\subsubsecentry2110,69619
- \dosubsubsecentry{#2.#3.#4.#5\labelspace#1}space2111,69653
-\def\unnumbsubsubsecentry#1#2{\unnumbsubsubsecentry2112,69704
-\def\dochapentry#1#2{\dochapentry2123,70078
-\def\dosecentry#1#2{\dosecentry2138,70683
-\def\dosubsecentry#1#2{\dosubsecentry2145,70861
-\def\dosubsubsecentry#1#2{\dosubsubsecentry2152,71046
-\def\labelspace{\labelspace2160,71297
-\def\dopageno#1{\dopageno2162,71332
-\def\doshortpageno#1{\doshortpageno2163,71358
-\def\chapentryfonts{\chapentryfonts2165,71390
-\def\secentryfonts{\secentryfonts2166,71425
-\def\point{\point2192,72384
-\def\result{\result2194,72405
-\def\expansion{\expansion2195,72478
-\def\print{\print2196,72549
-\def\equiv{\equiv2198,72616
-\def\error{\error2218,73389
-\def\tex{\tex2224,73618
-\def\@{\@2242,74001
-\gdef\sepspaces{\def {\ }}}\2265,74733
-\def\aboveenvbreak{\aboveenvbreak2268,74815
-\def\afterenvbreak{\afterenvbreak2272,74981
-\def\ctl{\ctl2286,75492
-\def\ctr{\ctr2287,75564
-\def\cbl{\cbl2288,75603
-\def\cbr{\cbr2289,75643
-\def\carttop{\carttop2290,75682
-\def\cartbot{\cartbot2293,75790
-\long\def\cartouche{\cartouche2299,75930
-\def\Ecartouche{\Ecartouche2326,76718
-\def\lisp{\lisp2338,76853
-\def\Elisp{\Elisp2348,77200
-\def\next##1{\next2360,77526
-\def\Eexample{\Eexample2364,77568
-\def\Esmallexample{\Esmallexample2367,77615
-\def\smalllispx{\smalllispx2373,77793
-\def\Esmalllisp{\Esmalllisp2383,78147
-\obeyspaces \obeylines \ninett \indexfonts \rawbackslashfonts2396,78503
-\def\next##1{\next2397,78560
-\def\display{\display2401,78640
-\def\Edisplay{\Edisplay2410,78959
-\def\next##1{\next2422,79270
-\def\format{\format2426,79373
-\def\Eformat{\Eformat2434,79669
-\def\next##1{\next2437,79758
-\def\flushleft{\flushleft2441,79810
-\def\Eflushleft{\Eflushleft2451,80181
-\def\next##1{\next2454,80274
-\def\flushright{\flushright2456,80296
-\def\Eflushright{\Eflushright2466,80668
-\def\next##1{\next2470,80799
-\def\quotation{\quotation2474,80857
-\def\Equotation{\Equotation2480,81049
-\def\setdeffont #1 {\setdeffont2493,81447
-\newskip\defbodyindent \defbodyindent=.4inbodyindent2495,81493
-\newskip\defargsindent \defargsindent=50ptargsindent2496,81536
-\newskip\deftypemargin \deftypemargin=12pttypemargin2497,81579
-\newskip\deflastargmargin \deflastargmargin=18ptlastargmargin2498,81622
-\def\activeparens{\activeparens2503,81820
-\def\opnr{\opnr2529,83032
-\def\lbrb{\lbrb2530,83097
-\def\defname #1#2{\defname2536,83298
-\advance\dimen2 by -\defbodyindentbodyindent2540,83416
-\advance\dimen3 by -\defbodyindentbodyindent2542,83470
-\setbox0=\hbox{\hskip \deflastargmargin{lastargmargin2544,83524
-\dimen1=\hsize \advance \dimen1 by -\defargsindent %size for continuationsargsindent2546,83666
-\parshape 2 0in \dimen0 \defargsindent \dimen1 %argsindent2547,83741
-\rlap{\rightline{{\rm #2}\hskip \deftypemargin}typemargin2554,84110
-\advance\leftskip by -\defbodyindentbodyindent2557,84244
-\exdentamount=\defbodyindentbodyindent2558,84281
-\def\defparsebody #1#2#3{\defparsebody2568,84640
-\def#1{2572,84824
-\def#2{2573,84860
-\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2575,84932
-\exdentamount=\defbodyindentbodyindent2576,85006
-\def\defmethparsebody #1#2#3#4 {\defmethparsebody2581,85110
-\def#1{2585,85271
-\def#2##1 {2586,85307
-\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2588,85390
-\exdentamount=\defbodyindentbodyindent2589,85464
-\def\defopparsebody #1#2#3#4#5 {\defopparsebody2592,85549
-\def#1{2596,85710
-\def#2##1 ##2 {2597,85746
-\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2600,85846
-\exdentamount=\defbodyindentbodyindent2601,85920
-\def\defvarparsebody #1#2#3{\defvarparsebody2608,86191
-\def#1{2612,86378
-\def#2{2613,86414
-\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2615,86473
-\exdentamount=\defbodyindentbodyindent2616,86547
-\def\defvrparsebody #1#2#3#4 {\defvrparsebody2621,86638
-\def#1{2625,86797
-\def#2##1 {2626,86833
-\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2628,86903
-\exdentamount=\defbodyindentbodyindent2629,86977
-\def\defopvarparsebody #1#2#3#4#5 {\defopvarparsebody2632,87049
-\def#1{2636,87213
-\def#2##1 ##2 {2637,87249
-\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2640,87336
-\exdentamount=\defbodyindentbodyindent2641,87410
-\def\defunargs #1{\defunargs2664,88170
-\def\deftypefunargs #1{\deftypefunargs2676,88552
-\def\deffn{\deffn2690,88934
-\def\deffnheader #1#2#3{\deffnheader2692,88991
-\begingroup\defname {name2693,89039
-\def\defun{\defun2699,89184
-\def\defunheader #1#2{\defunheader2701,89237
-\begingroup\defname {name2702,89312
-\defunargs {unargs2703,89348
-\def\deftypefun{\deftypefun2709,89496
-\def\deftypefunheader #1#2{\deftypefunheader2712,89618
-\def\deftypefunheaderx #1#2 #3\relax{\deftypefunheaderx2714,89727
-\begingroup\defname {name2716,89819
-\deftypefunargs {typefunargs2717,89865
-\def\deftypefn{\deftypefn2723,90036
-\def\deftypefnheader #1#2#3{\deftypefnheader2726,90185
-\def\deftypefnheaderx #1#2#3 #4\relax{\deftypefnheaderx2728,90321
-\begingroup\defname {name2730,90414
-\deftypefunargs {typefunargs2731,90454
-\def\defmac{\defmac2737,90575
-\def\defmacheader #1#2{\defmacheader2739,90632
-\begingroup\defname {name2740,90708
-\defunargs {unargs2741,90741
-\def\defspec{\defspec2747,90865
-\def\defspecheader #1#2{\defspecheader2749,90926
-\begingroup\defname {name2750,91003
-\defunargs {unargs2751,91043
-\def\deffnx #1 {\deffnx2758,91238
-\def\defunx #1 {\defunx2759,91295
-\def\defmacx #1 {\defmacx2760,91352
-\def\defspecx #1 {\defspecx2761,91411
-\def\deftypefnx #1 {\deftypefnx2762,91472
-\def\deftypeunx #1 {\deftypeunx2763,91537
-\def\defop #1 {\defop2769,91683
-\defopparsebody\Edefop\defopx\defopheader\defoptype}opparsebody\Edefop\defopx\defopheader\defoptype2770,91718
-\def\defopheader #1#2#3{\defopheader2772,91772
-\begingroup\defname {name2774,91861
-\defunargs {unargs2775,91907
-\def\defmethod{\defmethod2780,91968
-\def\defmethodheader #1#2#3{\defmethodheader2782,92041
-\begingroup\defname {name2784,92129
-\defunargs {unargs2785,92169
-\def\defcv #1 {\defcv2790,92243
-\defopvarparsebody\Edefcv\defcvx\defcvarheader\defcvtype}opvarparsebody\Edefcv\defcvx\defcvarheader\defcvtype2791,92278
-\def\defcvarheader #1#2#3{\defcvarheader2793,92337
-\begingroup\defname {name2795,92423
-\defvarargs {varargs2796,92469
-\def\defivar{\defivar2801,92542
-\def\defivarheader #1#2#3{\defivarheader2803,92605
-\begingroup\defname {name2805,92691
-\defvarargs {varargs2806,92742
-\def\defopx #1 {\defopx2812,92891
-\def\defmethodx #1 {\defmethodx2813,92948
-\def\defcvx #1 {\defcvx2814,93013
-\def\defivarx #1 {\defivarx2815,93070
-\def\defvarargs #1{\defvarargs2822,93341
-\def\defvr{\defvr2828,93485
-\def\defvrheader #1#2#3{\defvrheader2830,93540
-\begingroup\defname {name2831,93588
-\def\defvar{\defvar2835,93673
-\def\defvarheader #1#2{\defvarheader2837,93733
-\begingroup\defname {name2838,93804
-\defvarargs {varargs2839,93840
-\def\defopt{\defopt2844,93906
-\def\defoptheader #1#2{\defoptheader2846,93966
-\begingroup\defname {name2847,94037
-\defvarargs {varargs2848,94076
-\def\deftypevar{\deftypevar2853,94133
-\def\deftypevarheader #1#2{\deftypevarheader2856,94249
-\begingroup\defname {name2858,94332
-\def\deftypevr{\deftypevr2865,94506
-\def\deftypevrheader #1#2#3{\deftypevrheader2867,94577
-\begingroup\defname {name2868,94629
-\def\defvrx #1 {\defvrx2876,94866
-\def\defvarx #1 {\defvarx2877,94923
-\def\defoptx #1 {\defoptx2878,94982
-\def\deftypevarx #1 {\deftypevarx2879,95041
-\def\deftypevrx #1 {\deftypevrx2880,95108
-\def\deftpargs #1{\deftpargs2885,95257
-\def\deftp{\deftp2889,95337
-\def\deftpheader #1#2#3{\deftpheader2891,95392
-\begingroup\defname {name2892,95440
-\def\deftpx #1 {\deftpx2897,95599
-\def\setref#1{\setref2908,95920
-\def\unnumbsetref#1{\unnumbsetref2913,96034
-\def\appendixsetref#1{\appendixsetref2918,96141
-\def\pxref#1{\pxref2929,96552
-\def\xref#1{\xref2930,96588
-\def\ref#1{\ref2931,96623
-\def\xrefX[#1,#2,#3,#4,#5,#6]{\xrefX[2932,96653
-\def\printedmanual{\printedmanual2933,96696
-\def\printednodename{\printednodename2934,96734
-\def\printednodename{\printednodename2939,96859
-section ``\printednodename'' in \cite{\printedmanual}\printedmanual2954,97492
-\refx{x2957,97570
-\def\dosetq #1#2{\dosetq2965,97790
-\def\internalsetq #1#2{\internalsetq2973,98048
-\def\Ypagenumber{\Ypagenumber2977,98149
-\def\Ytitle{\Ytitle2979,98175
-\def\Ynothing{\Ynothing2981,98202
-\def\Ysectionnumberandtype{\Ysectionnumberandtype2983,98219
-\def\Yappendixletterandtype{\Yappendixletterandtype2992,98535
-\ifnum\secno=0 Appendix\xreftie'char\the\appendixno{no2993,98565
-\else \ifnum \subsecno=0 Section\xreftie'char\the\appendixno.\the\secno %no.\the\secno2994,98620
-Section\xreftie'char\the\appendixno.\the\secno.\the\subsecno %no.\the\secno.\the\subsecno2996,98724
-Section\xreftie'char\the\appendixno.\the\secno.\the\subsecno.\the\subsubsecno %no.\the\secno.\the\subsecno.\the\subsubsecno2998,98795
- \def\linenumber{\linenumber3009,99134
-\def\refx#1#2{\refx3015,99318
-\def\xrdef #1#2{\xrdef3037,99944
-\def\readauxfile{\readauxfile3040,100029
-\def\supereject{\supereject3110,101810
-\footstrut\parindent=\defaultparindent\hang\textindent{aultparindent\hang\textindent3131,102495
-\def\openindices{\openindices3139,102681
-\newdimen\defaultparindent \defaultparindent = 15ptaultparindent3151,102906
-\parindent = \defaultparindentaultparindent3152,102958
-\def\smallbook{\smallbook3175,103682
-\global\def\Esmallexample{\Esmallexample3192,104109
-\def\afourpaper{\afourpaper3196,104200
-\def\finalout{\finalout3224,105008
-\def\normaldoublequote{\normaldoublequote3235,105269
-\def\normaltilde{\normaltilde3236,105295
-\def\normalcaret{\normalcaret3237,105315
-\def\normalunderscore{\normalunderscore3238,105335
-\def\normalverticalbar{\normalverticalbar3239,105360
-\def\normalless{\normalless3240,105386
-\def\normalgreater{\normalgreater3241,105405
-\def\normalplus{\normalplus3242,105427
-\def\ifusingtt#1#2{\ifusingtt3253,105919
-\def\activedoublequote{\activedoublequote3261,106247
-\def~{~3264,106333
-\def^{^3267,106394
-\def_{_3270,106433
-\def\_{\_3272,106507
-\def\lvvmode{\lvvmode3279,106844
-\def|{|3282,106894
-\def<{<3285,106957
-\def>{>3288,107014
-\def+{+3290,107052
-\def\turnoffactive{\turnoffactive3296,107213
-\global\def={=3307,107499
-\def\normalbackslash{\normalbackslash3321,107881
+\def\texinfoversion{\texinfoversion26,1035
+\def\tie{\tie49,1526
+\def\gloggingall{\gloggingall72,2276
+\def\loggingall{\loggingall73,2345
+\def\onepageout#1{\onepageout99,3282
+\def\croppageout#1{\croppageout115,4032
+\def\cropmarks{\cropmarks142,5092
+\def\pagebody#1{\pagebody144,5139
+\def\ewtop{\ewtop157,5594
+\def\nstop{\nstop158,5658
+\def\ewbot{\ewbot160,5741
+\def\nsbot{\nsbot161,5805
+\def\parsearg #1{\parsearg170,6104
+\def\parseargx{\parseargx172,6182
+\def\parseargline{\parseargline182,6422
+\def\flushcr{\flushcr186,6543
+\newif\ifENV \ENVfalse \def\inENV{\inENV190,6742
+\def\ENVcheck{\ENVcheck191,6806
+\outer\def\begin{\begin198,7053
+\def\beginxxx #1{\beginxxx200,7091
+\def\end{\end208,7346
+\def\endxxx #1{\endxxx210,7374
+\def\errorE#1{\errorE216,7563
+\def\singlespace{\singlespace222,7757
+\def\@{\@232,7980
+\def\`{\`236,8080
+\def\'{\'237,8092
+\def\mylbrace {\mylbrace241,8140
+\def\myrbrace {\myrbrace242,8173
+\def\:{\:247,8287
+\def\*{\*250,8341
+\def\.{\.253,8417
+\def\w#1{\w258,8648
+\def\group{\group268,9131
+ \def\Egroup{\Egroup273,9295
+\def\need{\need289,9737
+\def\needx#1{\needx300,10014
+\def\dots{\dots339,11400
+\def\page{\page343,11464
+\def\exdent{\exdent353,11791
+\def\exdentyyy #1{\exdentyyy354,11824
+\def\nofillexdent{\nofillexdent357,11968
+\def\nofillexdentyyy #1{\nofillexdentyyy358,12013
+\def\include{\include365,12197
+\def\includezzz #1{\includezzz366,12232
+\def\thisfile{\thisfile369,12283
+\def\center{\center373,12346
+\def\centerzzz #1{\centerzzz374,12379
+\def\sp{\sp380,12521
+\def\spxxx #1{\spxxx381,12546
+\def\comment{\comment387,12720
+\def\commentxxx #1{\commentxxx390,12817
+\def\ignoresections{\ignoresections396,12986
+\let\chapter=\relax=\relax397,13008
+\let\section=\relax=\relax406,13253
+\let\subsection=\relax=\relax409,13314
+\let\subsubsection=\relax=\relax410,13337
+\let\appendix=\relax=\relax411,13363
+\let\appendixsec=\relaxsec=\relax412,13384
+\let\appendixsection=\relaxsection=\relax413,13408
+\let\appendixsubsec=\relaxsubsec=\relax414,13436
+\let\appendixsubsection=\relaxsubsection=\relax415,13463
+\let\appendixsubsubsec=\relaxsubsubsec=\relax416,13494
+\let\appendixsubsubsection=\relaxsubsubsection=\relax417,13524
+\def\ignore{\ignore423,13626
+\long\def\ignorexxx #1\end ignore{\ignorexxx427,13766
+\def\direntry{\direntry429,13825
+\long\def\direntryxxx #1\end direntry{\direntryxxx430,13864
+\def\ifset{\ifset434,13974
+\def\ifsetxxx #1{\ifsetxxx436,14032
+\def\Eifset{\Eifset440,14159
+\def\ifsetfail{\ifsetfail441,14173
+\long\def\ifsetfailxxx #1\end ifset{\ifsetfailxxx442,14229
+\def\ifclear{\ifclear444,14290
+\def\ifclearxxx #1{\ifclearxxx446,14352
+\def\Eifclear{\Eifclear450,14483
+\def\ifclearfail{\ifclearfail451,14499
+\long\def\ifclearfailxxx #1\end ifclear{\ifclearfailxxx452,14559
+\def\set{\set456,14710
+\def\setxxx #1{\setxxx457,14737
+\def\clear{\clear460,14799
+\def\clearxxx #1{\clearxxx461,14830
+\def\iftex{\iftex466,14947
+\def\Eiftex{\Eiftex467,14960
+\def\ifinfo{\ifinfo468,14974
+\long\def\ifinfoxxx #1\end ifinfo{\ifinfoxxx469,15024
+\long\def\menu #1\end menu{\menu471,15083
+\def\asis#1{\asis472,15112
+\def\math#1{\math485,15655
+\def\node{\node487,15699
+\def\nodezzz#1{\nodezzz488,15737
+\def\nodexxx[#1,#2]{\nodexxx[489,15768
+\def\donoderef{\donoderef492,15830
+\def\unnumbnoderef{\unnumbnoderef496,15951
+\def\appendixnoderef{\appendixnoderef500,16082
+\expandafter\expandafter\expandafter\appendixsetref{setref501,16128
+\let\refill=\relaxill=\relax504,16217
+\def\setfilename{\setfilename509,16431
+\outer\def\bye{\bye518,16677
+\def\inforef #1{\inforef520,16733
+\def\inforefzzz #1,#2,#3,#4**{\inforefzzz521,16771
+\def\losespace #1{\losespace523,16868
+\def\sf{\sf532,17072
+\font\defbf=cmbx10 scaled \magstep1 %was 1314bf=cmbx10558,17867
+\font\deftt=cmtt10 scaled \magstep1tt=cmtt10559,17913
+\def\df{\df560,17949
+\def\resetmathfonts{\resetmathfonts635,20543
+\def\textfonts{\textfonts648,21132
+\def\chapfonts{\chapfonts653,21347
+\def\secfonts{\secfonts658,21563
+\def\subsecfonts{\subsecfonts663,21768
+\def\indexfonts{\indexfonts668,21985
+\def\smartitalicx{\smartitalicx691,22717
+\def\smartitalic#1{\smartitalic692,22793
+\let\cite=\smartitalic=\smartitalic698,22938
+\def\b#1{\b700,22962
+\def\t#1{\t703,22997
+\def\samp #1{\samp706,23149
+\def\key #1{\key707,23182
+\def\ctrl #1{\ctrl708,23243
+\def\tclose#1{\tclose716,23445
+\def\ {\720,23611
+\def\xkey{\xkey728,23880
+\def\kbdfoo#1#2#3\par{\kbdfoo729,23896
+\def\dmn#1{\dmn738,24197
+\def\kbd#1{\kbd740,24224
+\def\l#1{\l742,24281
+\def\r#1{\r744,24310
+\def\sc#1{\sc746,24378
+\def\ii#1{\ii747,24421
+\def\titlefont#1{\titlefont755,24654
+\def\titlepage{\titlepage761,24757
+ \def\subtitlefont{\subtitlefont766,24984
+ \def\authorfont{\authorfont768,25068
+ \def\title{\title774,25278
+ \def\titlezzz##1{\titlezzz775,25313
+ \def\subtitle{\subtitle783,25628
+ \def\subtitlezzz##1{\subtitlezzz784,25669
+ \def\author{\author787,25787
+ \def\authorzzz##1{\authorzzz788,25824
+ \def\page{\page794,26115
+\def\Etitlepage{\Etitlepage804,26284
+\def\finishtitlepage{\finishtitlepage817,26672
+\def\evenheading{\evenheading846,27680
+\def\oddheading{\oddheading847,27723
+\def\everyheading{\everyheading848,27764
+\def\evenfooting{\evenfooting850,27810
+\def\oddfooting{\oddfooting851,27853
+\def\everyfooting{\everyfooting852,27894
+\def\headings #1 {\headings893,29586
+\def\HEADINGSoff{\HEADINGSoff895,29635
+\def\HEADINGSdouble{\HEADINGSdouble904,30062
+\def\HEADINGSsingle{\HEADINGSsingle914,30382
+\def\HEADINGSon{\HEADINGSon922,30603
+\def\HEADINGSafter{\HEADINGSafter924,30637
+\def\HEADINGSdoublex{\HEADINGSdoublex926,30732
+\def\HEADINGSsingleafter{\HEADINGSsingleafter933,30920
+\def\HEADINGSsinglex{\HEADINGSsinglex934,30981
+\def\today{\today943,31256
+\def\thistitle{\thistitle958,31801
+\def\settitle{\settitle959,31826
+\def\settitlezzz #1{\settitlezzz960,31863
+\def\internalBitem{\internalBitem992,32793
+\def\internalBitemx{\internalBitemx993,32843
+\def\internalBxitem "#1"{\internalBxitem995,32888
+\def\internalBxitemx "#1"{\internalBxitemx996,32968
+\def\internalBkitem{\internalBkitem998,33043
+\def\internalBkitemx{\internalBkitemx999,33095
+\def\kitemzzz #1{\kitemzzz1001,33142
+\def\xitemzzz #1{\xitemzzz1004,33244
+\def\itemzzz #1{\itemzzz1007,33347
+\def\item{\item1037,34418
+\def\itemx{\itemx1038,34469
+\def\kitem{\kitem1039,34522
+\def\kitemx{\kitemx1040,34575
+\def\xitem{\xitem1041,34630
+\def\xitemx{\xitemx1042,34683
+\def\description{\description1045,34793
+\def\table{\table1047,34843
+\def\ftable{\ftable1052,34987
+\def\Eftable{\Eftable1056,35133
+\def\vtable{\vtable1059,35202
+\def\Evtable{\Evtable1063,35348
+\def\dontindex #1{\dontindex1066,35417
+\def\fnitemindex #1{\fnitemindex1067,35437
+\def\vritemindex #1{\vritemindex1068,35482
+\def\tablez #1#2#3#4#5#6{\tablez1074,35631
+\def\Edescription{\Edescription1077,35689
+\def\itemfont{\itemfont1082,35890
+\def\Etable{\Etable1090,36116
+\def\itemize{\itemize1103,36440
+\def\itemizezzz #1{\itemizezzz1105,36476
+\def\itemizey #1#2{\itemizey1110,36571
+\def#2{1119,36817
+\def\itemcontents{\itemcontents1120,36858
+\def\bullet{\bullet1123,36906
+\def\minus{\minus1124,36933
+\def\frenchspacing{\frenchspacing1128,37041
+\def\splitoff#1#2\endmark{\splitoff1134,37266
+\def\enumerate{\enumerate1140,37496
+\def\enumeratezzz #1{\enumeratezzz1141,37535
+\def\enumeratey #1 #2\endenumeratey{\enumeratey1142,37588
+ \def\thearg{\thearg1146,37735
+ \ifx\thearg\empty \def\thearg{\thearg1147,37754
+\def\numericenumerate{\numericenumerate1184,39088
+\def\lowercaseenumerate{\lowercaseenumerate1190,39218
+\def\uppercaseenumerate{\uppercaseenumerate1203,39565
+\def\startenumeration#1{\startenumeration1219,40055
+\def\alphaenumerate{\alphaenumerate1227,40237
+\def\capsenumerate{\capsenumerate1228,40272
+\def\Ealphaenumerate{\Ealphaenumerate1229,40306
+\def\Ecapsenumerate{\Ecapsenumerate1230,40340
+\def\itemizeitem{\itemizeitem1234,40420
+\def\newindex #1{\newindex1259,41277
+\def\defindex{\defindex1268,41566
+\def\newcodeindex #1{\newcodeindex1272,41674
+\def\defcodeindex{\defcodeindex1279,41934
+\def\synindex #1 #2 {\synindex1283,42114
+\def\syncodeindex #1 #2 {\syncodeindex1292,42454
+\def\doindex#1{\doindex1309,43133
+\def\singleindexer #1{\singleindexer1310,43192
+\def\docodeindex#1{\docodeindex1313,43304
+\def\singlecodeindexer #1{\singlecodeindexer1314,43371
+\def\indexdummies{\indexdummies1316,43429
+\def\_{\_1317,43449
+\def\w{\w1318,43477
+\def\bf{\bf1319,43504
+\def\rm{\rm1320,43533
+\def\sl{\sl1321,43562
+\def\sf{\sf1322,43591
+\def\tt{\tt1323,43619
+\def\gtr{\gtr1324,43647
+\def\less{\less1325,43677
+\def\hat{\hat1326,43709
+\def\char{\char1327,43739
+\def\TeX{\TeX1328,43771
+\def\dots{\dots1329,43801
+\def\copyright{\copyright1330,43834
+\def\tclose##1{\tclose1331,43877
+\def\code##1{\code1332,43922
+\def\samp##1{\samp1333,43963
+\def\t##1{\t1334,44004
+\def\r##1{\r1335,44039
+\def\i##1{\i1336,44074
+\def\b##1{\b1337,44109
+\def\cite##1{\cite1338,44144
+\def\key##1{\key1339,44185
+\def\file##1{\file1340,44224
+\def\var##1{\var1341,44265
+\def\kbd##1{\kbd1342,44304
+\def\indexdummyfont#1{\indexdummyfont1347,44460
+\def\indexdummytex{\indexdummytex1348,44486
+\def\indexdummydots{\indexdummydots1349,44510
+\def\indexnofonts{\indexnofonts1351,44536
+\let\w=\indexdummyfontdummyfont1352,44556
+\let\t=\indexdummyfontdummyfont1353,44579
+\let\r=\indexdummyfontdummyfont1354,44602
+\let\i=\indexdummyfontdummyfont1355,44625
+\let\b=\indexdummyfontdummyfont1356,44648
+\let\emph=\indexdummyfontdummyfont1357,44671
+\let\strong=\indexdummyfontdummyfont1358,44697
+\let\cite=\indexdummyfont=\indexdummyfont1359,44725
+\let\sc=\indexdummyfontdummyfont1360,44751
+\let\tclose=\indexdummyfontdummyfont1364,44923
+\let\code=\indexdummyfontdummyfont1365,44951
+\let\file=\indexdummyfontdummyfont1366,44977
+\let\samp=\indexdummyfontdummyfont1367,45003
+\let\kbd=\indexdummyfontdummyfont1368,45029
+\let\key=\indexdummyfontdummyfont1369,45054
+\let\var=\indexdummyfontdummyfont1370,45079
+\let\TeX=\indexdummytexdummytex1371,45104
+\let\dots=\indexdummydotsdummydots1372,45128
+\let\indexbackslash=0 %overridden during \printindex.backslash=01382,45380
+\def\doind #1#2{\doind1384,45436
+{\indexdummies % Must do this here, since \bf, etc expand at this stagedummies1386,45479
+\def\rawbackslashxx{\rawbackslashxx1389,45619
+{\indexnofontsnofonts1394,45881
+\def\dosubind #1#2#3{\dosubind1405,46192
+{\indexdummies % Must do this here, since \bf, etc expand at this stagedummies1407,46240
+\def\rawbackslashxx{\rawbackslashxx1410,46344
+{\indexnofontsnofonts1414,46498
+\def\findex {\findex1443,47429
+\def\kindex {\kindex1444,47452
+\def\cindex {\cindex1445,47475
+\def\vindex {\vindex1446,47498
+\def\tindex {\tindex1447,47521
+\def\pindex {\pindex1448,47544
+\def\cindexsub {\cindexsub1450,47568
+\def\printindex{\printindex1462,47895
+\def\doprintindex#1{\doprintindex1464,47936
+ \def\indexbackslash{\indexbackslash1481,48421
+ \indexfonts\rm \tolerance=9500 \advance\baselineskip -1ptfonts\rm1482,48460
+\def\initial #1{\initial1517,49532
+\def\entry #1#2{\entry1523,49739
+ \null\nobreak\indexdotfill % Have leaders before the page number.dotfill1540,50386
+\def\indexdotfill{\indexdotfill1549,50714
+\def\primary #1{\primary1552,50820
+\def\secondary #1#2{\secondary1556,50902
+\noindent\hskip\secondaryindent\hbox{#1}\indexdotfill #2\pardotfill1559,50984
+\newbox\partialpageialpage1566,51157
+\def\begindoublecolumns{\begindoublecolumns1572,51315
+ \output={\global\setbox\partialpage=ialpage=1573,51351
+\def\enddoublecolumns{\enddoublecolumns1577,51539
+\def\doublecolumnout{\doublecolumnout1580,51624
+ \dimen@=\pageheight \advance\dimen@ by-\ht\partialpageialpage1581,51693
+\def\pagesofar{\pagesofar1584,51871
+\def\balancecolumns{\balancecolumns1588,52108
+ \availdimen@=\pageheight \advance\availdimen@ by-\ht\partialpageialpage1594,52279
+ \dimen@=\pageheight \advance\dimen@ by-\ht\partialpageialpage1600,52540
+\newcount \appendixno \appendixno = `\@no1627,53445
+\def\appendixletter{\appendixletter1628,53486
+\def\opencontents{\opencontents1632,53589
+\def\thischapter{\thischapter1637,53770
+\def\seccheck#1{\seccheck1638,53808
+\def\chapternofonts{\chapternofonts1643,53912
+\def\result{\result1646,53987
+\def\equiv{\equiv1647,54022
+\def\expansion{\expansion1648,54055
+\def\print{\print1649,54096
+\def\TeX{\TeX1650,54129
+\def\dots{\dots1651,54158
+\def\copyright{\copyright1652,54189
+\def\tt{\tt1653,54230
+\def\bf{\bf1654,54257
+\def\w{\w1655,54285
+\def\less{\less1656,54310
+\def\gtr{\gtr1657,54341
+\def\hat{\hat1658,54370
+\def\char{\char1659,54399
+\def\tclose##1{\tclose1660,54430
+\def\code##1{\code1661,54474
+\def\samp##1{\samp1662,54514
+\def\r##1{\r1663,54554
+\def\b##1{\b1664,54588
+\def\key##1{\key1665,54622
+\def\file##1{\file1666,54660
+\def\kbd##1{\kbd1667,54700
+\def\i##1{\i1669,54808
+\def\cite##1{\cite1670,54842
+\def\var##1{\var1671,54882
+\def\emph##1{\emph1672,54920
+\def\dfn##1{\dfn1673,54960
+\def\thischaptername{\thischaptername1676,55001
+\outer\def\chapter{\chapter1677,55040
+\def\chapterzzz #1{\chapterzzz1678,55081
+{\chapternofonts%nofonts%1687,55477
+\global\let\section = \numberedsec=1692,55630
+\global\let\subsection = \numberedsubsec=1693,55665
+\global\let\subsubsection = \numberedsubsubsec=1694,55706
+\outer\def\appendix{\appendix1697,55757
+\def\appendixzzz #1{\appendixzzz1698,55800
+\global\advance \appendixno by 1 \message{no1700,55877
+\chapmacro {#1}{Appendix \appendixletter}letter1701,55946
+\xdef\thischapter{Appendix \appendixletter: \noexpand\thischaptername}letter:1704,56039
+{\chapternofonts%nofonts%1705,56111
+ {#1}{Appendix \appendixletter}letter1707,56167
+\appendixnoderef %noderef1710,56267
+\global\let\section = \appendixsec=1711,56286
+\global\let\subsection = \appendixsubsec=1712,56321
+\global\let\subsubsection = \appendixsubsubsec=1713,56362
+\outer\def\top{\top1716,56413
+\outer\def\unnumbered{\unnumbered1717,56453
+\def\unnumberedzzz #1{\unnumberedzzz1718,56500
+{\chapternofonts%nofonts%1722,56663
+\global\let\section = \unnumberedsec=1727,56813
+\global\let\subsection = \unnumberedsubsec=1728,56850
+\global\let\subsubsection = \unnumberedsubsubsec=1729,56893
+\outer\def\numberedsec{\numberedsec1732,56946
+\def\seczzz #1{\seczzz1733,56987
+{\chapternofonts%nofonts%1736,57143
+\outer\def\appendixsection{\appendixsection1745,57329
+\outer\def\appendixsec{\appendixsec1746,57386
+\def\appendixsectionzzz #1{\appendixsectionzzz1747,57439
+\gdef\thissection{#1}\secheading {#1}{\appendixletter}letter1749,57551
+{\chapternofonts%nofonts%1750,57619
+{#1}{\appendixletter}letter1752,57675
+\appendixnoderef %noderef1755,57775
+\outer\def\unnumberedsec{\unnumberedsec1759,57815
+\def\unnumberedseczzz #1{\unnumberedseczzz1760,57868
+{\chapternofonts%nofonts%1762,57963
+\outer\def\numberedsubsec{\numberedsubsec1770,58131
+\def\numberedsubseczzz #1{\numberedsubseczzz1771,58186
+{\chapternofonts%nofonts%1774,58365
+\outer\def\appendixsubsec{\appendixsubsec1783,58569
+\def\appendixsubseczzz #1{\appendixsubseczzz1784,58624
+\subsecheading {#1}{\appendixletter}letter1786,58746
+{\chapternofonts%nofonts%1787,58811
+{#1}{\appendixletter}letter1789,58870
+\appendixnoderef %noderef1792,58985
+\outer\def\unnumberedsubsec{\unnumberedsubsec1796,59025
+\def\unnumberedsubseczzz #1{\unnumberedsubseczzz1797,59084
+{\chapternofonts%nofonts%1799,59185
+\outer\def\numberedsubsubsec{\numberedsubsubsec1807,59356
+\def\numberedsubsubseczzz #1{\numberedsubsubseczzz1808,59417
+{\chapternofonts%nofonts%1812,59614
+\outer\def\appendixsubsubsec{\appendixsubsubsec1823,59847
+\def\appendixsubsubseczzz #1{\appendixsubsubseczzz1824,59908
+ {\appendixletter}letter1827,60047
+{\chapternofonts%nofonts%1828,60113
+ {\appendixletter}letter1830,60178
+\appendixnoderef %noderef1834,60312
+\outer\def\unnumberedsubsubsec{\unnumberedsubsubsec1838,60352
+\def\unnumberedsubsubseczzz #1{\unnumberedsubsubseczzz1839,60417
+{\chapternofonts%nofonts%1841,60524
+\def\infotop{\infotop1851,60853
+\def\infounnumbered{\infounnumbered1852,60891
+\def\infounnumberedsec{\infounnumberedsec1853,60936
+\def\infounnumberedsubsec{\infounnumberedsubsec1854,60987
+\def\infounnumberedsubsubsec{\infounnumberedsubsubsec1855,61044
+\def\infoappendix{\infoappendix1857,61108
+\def\infoappendixsec{\infoappendixsec1858,61149
+\def\infoappendixsubsec{\infoappendixsubsec1859,61196
+\def\infoappendixsubsubsec{\infoappendixsubsubsec1860,61249
+\def\infochapter{\infochapter1862,61309
+\def\infosection{\infosection1863,61348
+\def\infosubsection{\infosubsection1864,61387
+\def\infosubsubsection{\infosubsubsection1865,61432
+\global\let\section = \numberedsec=1870,61669
+\global\let\subsection = \numberedsubsec=1871,61704
+\global\let\subsubsection = \numberedsubsubsec=1872,61745
+\def\majorheading{\majorheading1886,62252
+\def\majorheadingzzz #1{\majorheadingzzz1887,62297
+\def\chapheading{\chapheading1893,62530
+\def\chapheadingzzz #1{\chapheadingzzz1894,62573
+\def\heading{\heading1899,62768
+\def\subheading{\subheading1901,62805
+\def\subsubheading{\subsubheading1903,62848
+\def\dobreak#1#2{\dobreak1910,63125
+\def\setchapterstyle #1 {\setchapterstyle1912,63203
+\def\chapbreak{\chapbreak1919,63458
+\def\chappager{\chappager1920,63508
+\def\chapoddpage{\chapoddpage1921,63546
+\def\setchapternewpage #1 {\setchapternewpage1923,63625
+\def\CHAPPAGoff{\CHAPPAGoff1925,63682
+\def\CHAPPAGon{\CHAPPAGon1929,63776
+\global\def\HEADINGSon{\HEADINGSon1932,63867
+\def\CHAPPAGodd{\CHAPPAGodd1934,63909
+\global\def\HEADINGSon{\HEADINGSon1937,64005
+\def\CHAPFplain{\CHAPFplain1941,64059
+\def\chfplain #1#2{\chfplain1945,64151
+\def\unnchfplain #1{\unnchfplain1956,64374
+\def\unnchfopen #1{\unnchfopen1964,64603
+\def\chfopen #1#2{\chfopen1970,64811
+\def\CHAPFopen{\CHAPFopen1975,64955
+\def\subsecheadingbreak{\subsecheadingbreak1982,65173
+\def\secheadingbreak{\secheadingbreak1985,65302
+\def\secheading #1#2#3{\secheading1993,65584
+\def\plainsecheading #1{\plainsecheading1994,65640
+\def\secheadingi #1{\secheadingi1995,65683
+\def\subsecheading #1#2#3#4{\subsecheading2006,66051
+\def\subsecheadingi #1{\subsecheadingi2007,66118
+\def\subsubsecfonts{\subsubsecfonts2014,66415
+\def\subsubsecheading #1#2#3#4#5{\subsubsecheading2017,66538
+\def\subsubsecheadingi #1{\subsubsecheadingi2018,66616
+\def\startcontents#1{\startcontents2032,67088
+ \unnumbchapmacro{#1}\def\thischapter{\thischapter2040,67361
+\outer\def\contents{\contents2049,67720
+\outer\def\summarycontents{\summarycontents2057,67864
+ \def\secentry ##1##2##3##4{\secentry2067,68235
+ \def\unnumbsecentry ##1##2{\unnumbsecentry2068,68270
+ \def\subsecentry ##1##2##3##4##5{\subsecentry2069,68305
+ \def\unnumbsubsecentry ##1##2{\unnumbsubsecentry2070,68346
+ \def\subsubsecentry ##1##2##3##4##5##6{\subsubsecentry2071,68384
+ \def\unnumbsubsubsecentry ##1##2{\unnumbsubsubsecentry2072,68431
+\def\chapentry#1#2#3{\chapentry2085,68865
+\def\shortchapentry#1#2#3{\shortchapentry2088,68982
+ {#2\labelspace #1}space2091,69092
+\def\unnumbchapentry#1#2{\unnumbchapentry2094,69146
+\def\shortunnumberedentry#1#2{\shortunnumberedentry2095,69193
+\def\secentry#1#2#3#4{\secentry2102,69357
+\def\unnumbsecentry#1#2{\unnumbsecentry2103,69416
+\def\subsecentry#1#2#3#4#5{\subsecentry2106,69477
+\def\unnumbsubsecentry#1#2{\unnumbsubsecentry2107,69547
+\def\subsubsecentry#1#2#3#4#5#6{\subsubsecentry2110,69621
+ \dosubsubsecentry{#2.#3.#4.#5\labelspace#1}space2111,69655
+\def\unnumbsubsubsecentry#1#2{\unnumbsubsubsecentry2112,69706
+\def\dochapentry#1#2{\dochapentry2123,70080
+\def\dosecentry#1#2{\dosecentry2138,70685
+\def\dosubsecentry#1#2{\dosubsecentry2145,70863
+\def\dosubsubsecentry#1#2{\dosubsubsecentry2152,71048
+\def\labelspace{\labelspace2160,71299
+\def\dopageno#1{\dopageno2162,71334
+\def\doshortpageno#1{\doshortpageno2163,71360
+\def\chapentryfonts{\chapentryfonts2165,71392
+\def\secentryfonts{\secentryfonts2166,71427
+\def\point{\point2192,72386
+\def\result{\result2194,72407
+\def\expansion{\expansion2195,72480
+\def\print{\print2196,72551
+\def\equiv{\equiv2198,72618
+\def\error{\error2218,73391
+\def\tex{\tex2224,73620
+\def\@{\@2242,74003
+\gdef\sepspaces{\def {\ }}}\2265,74735
+\def\aboveenvbreak{\aboveenvbreak2268,74817
+\def\afterenvbreak{\afterenvbreak2272,74983
+\def\ctl{\ctl2286,75494
+\def\ctr{\ctr2287,75566
+\def\cbl{\cbl2288,75605
+\def\cbr{\cbr2289,75645
+\def\carttop{\carttop2290,75684
+\def\cartbot{\cartbot2293,75792
+\long\def\cartouche{\cartouche2299,75932
+\def\Ecartouche{\Ecartouche2326,76720
+\def\lisp{\lisp2338,76855
+\def\Elisp{\Elisp2348,77202
+\def\next##1{\next2360,77528
+\def\Eexample{\Eexample2364,77570
+\def\Esmallexample{\Esmallexample2367,77617
+\def\smalllispx{\smalllispx2373,77795
+\def\Esmalllisp{\Esmalllisp2383,78149
+\obeyspaces \obeylines \ninett \indexfonts \rawbackslashfonts2396,78505
+\def\next##1{\next2397,78562
+\def\display{\display2401,78642
+\def\Edisplay{\Edisplay2410,78961
+\def\next##1{\next2422,79272
+\def\format{\format2426,79375
+\def\Eformat{\Eformat2434,79671
+\def\next##1{\next2437,79760
+\def\flushleft{\flushleft2441,79812
+\def\Eflushleft{\Eflushleft2451,80183
+\def\next##1{\next2454,80276
+\def\flushright{\flushright2456,80298
+\def\Eflushright{\Eflushright2466,80670
+\def\next##1{\next2470,80801
+\def\quotation{\quotation2474,80859
+\def\Equotation{\Equotation2480,81051
+\def\setdeffont #1 {\setdeffont2493,81449
+\newskip\defbodyindent \defbodyindent=.4inbodyindent2495,81495
+\newskip\defargsindent \defargsindent=50ptargsindent2496,81538
+\newskip\deftypemargin \deftypemargin=12pttypemargin2497,81581
+\newskip\deflastargmargin \deflastargmargin=18ptlastargmargin2498,81624
+\def\activeparens{\activeparens2503,81822
+\def\opnr{\opnr2529,83034
+\def\lbrb{\lbrb2530,83099
+\def\defname #1#2{\defname2536,83300
+\advance\dimen2 by -\defbodyindentbodyindent2540,83418
+\advance\dimen3 by -\defbodyindentbodyindent2542,83472
+\setbox0=\hbox{\hskip \deflastargmargin{lastargmargin2544,83526
+\dimen1=\hsize \advance \dimen1 by -\defargsindent %size for continuationsargsindent2546,83668
+\parshape 2 0in \dimen0 \defargsindent \dimen1 %argsindent2547,83743
+\rlap{\rightline{{\rm #2}\hskip \deftypemargin}typemargin2554,84112
+\advance\leftskip by -\defbodyindentbodyindent2557,84246
+\exdentamount=\defbodyindentbodyindent2558,84283
+\def\defparsebody #1#2#3{\defparsebody2568,84642
+\def#1{2572,84826
+\def#2{2573,84862
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2575,84934
+\exdentamount=\defbodyindentbodyindent2576,85008
+\def\defmethparsebody #1#2#3#4 {\defmethparsebody2581,85112
+\def#1{2585,85273
+\def#2##1 {2586,85309
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2588,85392
+\exdentamount=\defbodyindentbodyindent2589,85466
+\def\defopparsebody #1#2#3#4#5 {\defopparsebody2592,85551
+\def#1{2596,85712
+\def#2##1 ##2 {2597,85748
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2600,85848
+\exdentamount=\defbodyindentbodyindent2601,85922
+\def\defvarparsebody #1#2#3{\defvarparsebody2608,86193
+\def#1{2612,86380
+\def#2{2613,86416
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2615,86475
+\exdentamount=\defbodyindentbodyindent2616,86549
+\def\defvrparsebody #1#2#3#4 {\defvrparsebody2621,86640
+\def#1{2625,86799
+\def#2##1 {2626,86835
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2628,86905
+\exdentamount=\defbodyindentbodyindent2629,86979
+\def\defopvarparsebody #1#2#3#4#5 {\defopvarparsebody2632,87051
+\def#1{2636,87215
+\def#2##1 ##2 {2637,87251
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2640,87338
+\exdentamount=\defbodyindentbodyindent2641,87412
+\def\defunargs #1{\defunargs2664,88172
+\def\deftypefunargs #1{\deftypefunargs2676,88554
+\def\deffn{\deffn2690,88936
+\def\deffnheader #1#2#3{\deffnheader2692,88993
+\begingroup\defname {name2693,89041
+\def\defun{\defun2699,89186
+\def\defunheader #1#2{\defunheader2701,89239
+\begingroup\defname {name2702,89314
+\defunargs {unargs2703,89350
+\def\deftypefun{\deftypefun2709,89498
+\def\deftypefunheader #1#2{\deftypefunheader2712,89620
+\def\deftypefunheaderx #1#2 #3\relax{\deftypefunheaderx2714,89729
+\begingroup\defname {name2716,89821
+\deftypefunargs {typefunargs2717,89867
+\def\deftypefn{\deftypefn2723,90038
+\def\deftypefnheader #1#2#3{\deftypefnheader2726,90187
+\def\deftypefnheaderx #1#2#3 #4\relax{\deftypefnheaderx2728,90323
+\begingroup\defname {name2730,90416
+\deftypefunargs {typefunargs2731,90456
+\def\defmac{\defmac2737,90577
+\def\defmacheader #1#2{\defmacheader2739,90634
+\begingroup\defname {name2740,90710
+\defunargs {unargs2741,90743
+\def\defspec{\defspec2747,90867
+\def\defspecheader #1#2{\defspecheader2749,90928
+\begingroup\defname {name2750,91005
+\defunargs {unargs2751,91045
+\def\deffnx #1 {\deffnx2758,91240
+\def\defunx #1 {\defunx2759,91297
+\def\defmacx #1 {\defmacx2760,91354
+\def\defspecx #1 {\defspecx2761,91413
+\def\deftypefnx #1 {\deftypefnx2762,91474
+\def\deftypeunx #1 {\deftypeunx2763,91539
+\def\defop #1 {\defop2769,91685
+\defopparsebody\Edefop\defopx\defopheader\defoptype}opparsebody\Edefop\defopx\defopheader\defoptype2770,91720
+\def\defopheader #1#2#3{\defopheader2772,91774
+\begingroup\defname {name2774,91863
+\defunargs {unargs2775,91909
+\def\defmethod{\defmethod2780,91970
+\def\defmethodheader #1#2#3{\defmethodheader2782,92043
+\begingroup\defname {name2784,92131
+\defunargs {unargs2785,92171
+\def\defcv #1 {\defcv2790,92245
+\defopvarparsebody\Edefcv\defcvx\defcvarheader\defcvtype}opvarparsebody\Edefcv\defcvx\defcvarheader\defcvtype2791,92280
+\def\defcvarheader #1#2#3{\defcvarheader2793,92339
+\begingroup\defname {name2795,92425
+\defvarargs {varargs2796,92471
+\def\defivar{\defivar2801,92544
+\def\defivarheader #1#2#3{\defivarheader2803,92607
+\begingroup\defname {name2805,92693
+\defvarargs {varargs2806,92744
+\def\defopx #1 {\defopx2812,92893
+\def\defmethodx #1 {\defmethodx2813,92950
+\def\defcvx #1 {\defcvx2814,93015
+\def\defivarx #1 {\defivarx2815,93072
+\def\defvarargs #1{\defvarargs2822,93343
+\def\defvr{\defvr2828,93487
+\def\defvrheader #1#2#3{\defvrheader2830,93542
+\begingroup\defname {name2831,93590
+\def\defvar{\defvar2835,93675
+\def\defvarheader #1#2{\defvarheader2837,93735
+\begingroup\defname {name2838,93806
+\defvarargs {varargs2839,93842
+\def\defopt{\defopt2844,93908
+\def\defoptheader #1#2{\defoptheader2846,93968
+\begingroup\defname {name2847,94039
+\defvarargs {varargs2848,94078
+\def\deftypevar{\deftypevar2853,94135
+\def\deftypevarheader #1#2{\deftypevarheader2856,94251
+\begingroup\defname {name2858,94334
+\def\deftypevr{\deftypevr2865,94508
+\def\deftypevrheader #1#2#3{\deftypevrheader2867,94579
+\begingroup\defname {name2868,94631
+\def\defvrx #1 {\defvrx2876,94868
+\def\defvarx #1 {\defvarx2877,94925
+\def\defoptx #1 {\defoptx2878,94984
+\def\deftypevarx #1 {\deftypevarx2879,95043
+\def\deftypevrx #1 {\deftypevrx2880,95110
+\def\deftpargs #1{\deftpargs2885,95259
+\def\deftp{\deftp2889,95339
+\def\deftpheader #1#2#3{\deftpheader2891,95394
+\begingroup\defname {name2892,95442
+\def\deftpx #1 {\deftpx2897,95601
+\def\setref#1{\setref2908,95922
+\def\unnumbsetref#1{\unnumbsetref2913,96036
+\def\appendixsetref#1{\appendixsetref2918,96143
+\def\pxref#1{\pxref2929,96554
+\def\xref#1{\xref2930,96590
+\def\ref#1{\ref2931,96625
+\def\xrefX[#1,#2,#3,#4,#5,#6]{\xrefX[2932,96655
+\def\printedmanual{\printedmanual2933,96698
+\def\printednodename{\printednodename2934,96736
+\def\printednodename{\printednodename2939,96861
+section ``\printednodename'' in \cite{\printedmanual}\printedmanual2954,97493
+\refx{x2957,97571
+\def\dosetq #1#2{\dosetq2965,97791
+\def\internalsetq #1#2{\internalsetq2973,98049
+\def\Ypagenumber{\Ypagenumber2977,98150
+\def\Ytitle{\Ytitle2979,98176
+\def\Ynothing{\Ynothing2981,98203
+\def\Ysectionnumberandtype{\Ysectionnumberandtype2983,98220
+\def\Yappendixletterandtype{\Yappendixletterandtype2992,98536
+\ifnum\secno=0 Appendix\xreftie'char\the\appendixno{no2993,98566
+\else \ifnum \subsecno=0 Section\xreftie'char\the\appendixno.\the\secno %no.\the\secno2994,98621
+Section\xreftie'char\the\appendixno.\the\secno.\the\subsecno %no.\the\secno.\the\subsecno2996,98725
+Section\xreftie'char\the\appendixno.\the\secno.\the\subsecno.\the\subsubsecno %no.\the\secno.\the\subsecno.\the\subsubsecno2998,98796
+ \def\linenumber{\linenumber3009,99135
+\def\refx#1#2{\refx3015,99319
+\def\xrdef #1#2{\xrdef3037,99945
+\def\readauxfile{\readauxfile3040,100030
+\def\supereject{\supereject3110,101811
+\footstrut\parindent=\defaultparindent\hang\textindent{aultparindent\hang\textindent3131,102496
+\def\openindices{\openindices3139,102682
+\newdimen\defaultparindent \defaultparindent = 15ptaultparindent3151,102907
+\parindent = \defaultparindentaultparindent3152,102959
+\def\smallbook{\smallbook3175,103683
+\global\def\Esmallexample{\Esmallexample3192,104110
+\def\afourpaper{\afourpaper3196,104201
+\def\finalout{\finalout3224,105009
+\def\normaldoublequote{\normaldoublequote3235,105270
+\def\normaltilde{\normaltilde3236,105296
+\def\normalcaret{\normalcaret3237,105316
+\def\normalunderscore{\normalunderscore3238,105336
+\def\normalverticalbar{\normalverticalbar3239,105361
+\def\normalless{\normalless3240,105387
+\def\normalgreater{\normalgreater3241,105406
+\def\normalplus{\normalplus3242,105428
+\def\ifusingtt#1#2{\ifusingtt3253,105920
+\def\activedoublequote{\activedoublequote3261,106248
+\def~{~3264,106334
+\def^{^3267,106395
+\def_{_3270,106434
+\def\_{\_3272,106508
+\def\lvvmode{\lvvmode3279,106845
+\def|{|3282,106895
+\def<{<3285,106958
+\def>{>3288,107015
+\def+{+3290,107053
+\def\turnoffactive{\turnoffactive3296,107214
+\global\def={=3307,107500
+\def\normalbackslash{\normalbackslash3321,107882
+
+merc-src/accumulator.m,3228
+:- interface146,5371
+:- import_module hlds148,5386
+:- import_module univ152,5478
+:- pred accu_transform_proc159,5793
+:- implementation166,6115
+:- import_module libs180,6552
+:- import_module mdbcomp184,6681
+:- import_module parse_tree186,6742
+:- import_module assoc_list194,7013
+:- import_module bool195,7042
+:- import_module int196,7065
+:- import_module io197,7087
+:- import_module list198,7108
+:- import_module map199,7131
+:- import_module maybe200,7153
+:- import_module pair201,7177
+:- import_module require202,7200
+:- import_module set203,7226
+:- import_module solutions204,7248
+:- import_module string205,7276
+:- import_module term206,7301
+:- import_module varset207,7324
+:- type top_level213,7499
+:- type accu_goal_id225,7900
+:- type accu_case228,7964
+:- type accu_goal_store234,8091
+:- type accu_subst238,8216
+:- type accu_warning240,8264
+:- pred generate_warnings334,12550
+:- pred generate_warning342,12895
+:- pred should_attempt_accu_transform365,13886
+:- pred should_attempt_accu_transform_2398,15406
+:- pred accu_standardize440,17390
+:- pred identify_goal_type465,18169
+:- pred is_recursive_case549,21175
+:- type store_info560,21713
+:- func initialize_goal_store570,22060
+:- pred accu_store580,22421
+:- pred identify_recursive_calls601,23288
+:- pred identify_out_and_out_prime626,24397
+:- type accu_sets676,26426
+:- pred accu_stage1689,26978
+:- pred accu_stage1_2727,28348
+:- pred accu_sets_init781,30558
+:- func set_upto796,30985
+:- pred accu_before812,31499
+:- pred accu_assoc835,32478
+:- pred accu_construct862,33713
+:- pred accu_construct_assoc896,35308
+:- pred accu_update938,37070
+:- pred member_lessthan_goalid964,38220
+:- type accu_assoc975,38653
+:- pred accu_is_associative986,39139
+:- pred associativity_assertion1014,40264
+:- pred commutativity_assertion1037,41243
+:- pred accu_is_update1057,41953
+:- pred is_associative_construction1078,42803
+:- type accu_substs1095,43481
+:- type accu_base1103,43745
+:- pred accu_stage21124,44606
+:- pred accu_substs_init1179,46958
+:- pred acc_var_subst_init1194,47574
+:- pred create_new_var1207,48148
+:- pred accu_process_assoc_set1223,48863
+:- pred accu_has_heuristic1297,52082
+:- pred accu_heuristic1304,52337
+:- pred accu_process_update_set1318,52907
+:- pred accu_divide_base_case1380,55845
+:- pred accu_related1412,57147
+:- inst stored_goal_plain_call1444,58416
+:- pred lookup_call1449,58602
+:- pred accu_stage31470,59433
+:- pred acc_proc_info1508,61327
+:- pred acc_pred_info1556,63450
+:- pred accu_create_goal1600,65286
+:- func create_acc_call1621,66401
+:- pred create_orig_goal1634,66988
+:- pred create_acc_goal1662,68158
+:- func create_new_orig_recursive_goals1709,70226
+:- func create_new_recursive_goals1723,70919
+:- func create_new_base_goals1738,71718
+:- pred acc_unification1749,72157
+:- pred accu_top_level1766,72897
+:- pred update_accumulator_pred1856,76291
+:- func accu_rename1876,77254
+:- func base_case_ids1889,77785
+:- func base_case_ids_set1898,78049
+:- func accu_goal_list1905,78270
+:- pred calculate_goal_info1916,78681
+:- func chain_subst1932,79320
+:- pred chain_subst_21938,79483
+:- some [T] pred unravel_univ1956,80061
+:- pragma foreign_export1957,80117
c-src/c.c,76
T f(1,0
@@ -4148,13 +4244,13 @@ yyerror FUN1(286,5948
make_list FUN2(293,6028
#define ERROR 304,6228
yylex FUN0(315,6405
-parse_cell_or_range FUN2(587,11771
-#define CK_ABS_R(671,13213
-#define CK_REL_R(675,13292
-#define CK_ABS_C(680,13421
-#define CK_REL_C(684,13500
-#define MAYBEREL(689,13629
-str_to_col FUN1(847,16830
+parse_cell_or_range FUN2(587,11772
+#define CK_ABS_R(671,13214
+#define CK_REL_R(675,13293
+#define CK_ABS_C(680,13422
+#define CK_REL_C(684,13501
+#define MAYBEREL(689,13630
+str_to_col FUN1(847,16831
y-src/parse.c,520
#define YYBISON 4,64
diff --git a/test/manual/etags/ETAGS.good_5 b/test/manual/etags/ETAGS.good_5
index b7a31602f51..3e238a50f38 100644
--- a/test/manual/etags/ETAGS.good_5
+++ b/test/manual/etags/ETAGS.good_5
@@ -175,7 +175,7 @@ package body Truc.Bidule Truc.Bidule/b138,2153
protected body Bidule Bidule/b139,2181
protected body Machin_T Machin_T/b146,2281
-c-src/abbrev.c,3274
+c-src/abbrev.c,3055
Lisp_Object Vabbrev_table_name_list;43,1429
Lisp_Object Vglobal_abbrev_table;48,1574
Lisp_Object Vfundamental_mode_abbrev_table;52,1685
@@ -186,57 +186,53 @@ Lisp_Object Vabbrev_start_location_buffer;66,2046
Lisp_Object Vlast_abbrev;70,2155
Lisp_Object Vlast_abbrev_text;75,2324
int last_abbrev_point;79,2414
-Lisp_Object Vpre_abbrev_expand_hook,83,2487
-Lisp_Object Vpre_abbrev_expand_hook, Qpre_abbrev_expand_hook;83,2487
-DEFUN ("make-abbrev-table", Fmake_abbrev_table,85,2551
-DEFUN ("make-abbrev-table", Fmake_abbrev_table,make-abbrev-table85,2551
-DEFUN ("clear-abbrev-table", Fclear_abbrev_table,92,2743
-DEFUN ("clear-abbrev-table", Fclear_abbrev_table,clear-abbrev-table92,2743
-DEFUN ("define-abbrev", Fdefine_abbrev,107,3124
-DEFUN ("define-abbrev", Fdefine_abbrev,define-abbrev107,3124
-DEFUN ("define-global-abbrev", Fdefine_global_abbrev,149,4443
-DEFUN ("define-global-abbrev", Fdefine_global_abbrev,define-global-abbrev149,4443
-DEFUN ("define-mode-abbrev", Fdefine_mode_abbrev,160,4814
-DEFUN ("define-mode-abbrev", Fdefine_mode_abbrev,define-mode-abbrev160,4814
-DEFUN ("abbrev-symbol", Fabbrev_symbol,174,5282
-DEFUN ("abbrev-symbol", Fabbrev_symbol,abbrev-symbol174,5282
-DEFUN ("abbrev-expansion", Fabbrev_expansion,202,6246
-DEFUN ("abbrev-expansion", Fabbrev_expansion,abbrev-expansion202,6246
-DEFUN ("expand-abbrev", Fexpand_abbrev,218,6761
-DEFUN ("expand-abbrev", Fexpand_abbrev,expand-abbrev218,6761
-DEFUN ("unexpand-abbrev", Funexpand_abbrev,389,11682
-DEFUN ("unexpand-abbrev", Funexpand_abbrev,unexpand-abbrev389,11682
-write_abbrev 426,12889
-describe_abbrev 445,13324
-DEFUN ("insert-abbrev-table-description", Finsert_abbrev_table_description,466,13839
-DEFUN ("insert-abbrev-table-description", Finsert_abbrev_table_description,insert-abbrev-table-description466,13839
-DEFUN ("define-abbrev-table", Fdefine_abbrev_table,506,14995
-DEFUN ("define-abbrev-table", Fdefine_abbrev_table,define-abbrev-table506,14995
-syms_of_abbrev 540,16072
- DEFVAR_LISP ("abbrev-table-name-list"542,16092
- DEFVAR_LISP ("global-abbrev-table"548,16354
- DEFVAR_LISP ("fundamental-mode-abbrev-table"555,16676
- DEFVAR_LISP ("last-abbrev"561,17018
- DEFVAR_LISP ("last-abbrev-text"564,17141
- DEFVAR_INT ("last-abbrev-location"568,17299
- DEFVAR_LISP ("abbrev-start-location"575,17498
- DEFVAR_LISP ("abbrev-start-location-buffer"581,17775
- DEFVAR_PER_BUFFER ("local-abbrev-table"586,18039
- DEFVAR_BOOL ("abbrevs-changed"589,18182
- DEFVAR_BOOL ("abbrev-all-caps"594,18385
- DEFVAR_LISP ("pre-abbrev-expand-hook"598,18541
- DEFVAR_LISP ("abbrev-table-name-list",\1542,16092
- DEFVAR_LISP ("global-abbrev-table",\1548,16354
- DEFVAR_LISP ("fundamental-mode-abbrev-table",\1555,16676
- DEFVAR_LISP ("last-abbrev",\1561,17018
- DEFVAR_LISP ("last-abbrev-text",\1564,17141
- DEFVAR_INT ("last-abbrev-location",\1568,17299
- DEFVAR_LISP ("abbrev-start-location",\1575,17498
- DEFVAR_LISP ("abbrev-start-location-buffer",\1581,17775
- DEFVAR_PER_BUFFER ("local-abbrev-table",\1586,18039
- DEFVAR_BOOL ("abbrevs-changed",\1589,18182
- DEFVAR_BOOL ("abbrev-all-caps",\1594,18385
- DEFVAR_LISP ("pre-abbrev-expand-hook",\1598,18541
+DEFUN ("make-abbrev-table", Fmake_abbrev_table,82,2440
+DEFUN ("make-abbrev-table", Fmake_abbrev_table,make-abbrev-table82,2440
+DEFUN ("clear-abbrev-table", Fclear_abbrev_table,89,2632
+DEFUN ("clear-abbrev-table", Fclear_abbrev_table,clear-abbrev-table89,2632
+DEFUN ("define-abbrev", Fdefine_abbrev,104,3013
+DEFUN ("define-abbrev", Fdefine_abbrev,define-abbrev104,3013
+DEFUN ("define-global-abbrev", Fdefine_global_abbrev,146,4332
+DEFUN ("define-global-abbrev", Fdefine_global_abbrev,define-global-abbrev146,4332
+DEFUN ("define-mode-abbrev", Fdefine_mode_abbrev,157,4703
+DEFUN ("define-mode-abbrev", Fdefine_mode_abbrev,define-mode-abbrev157,4703
+DEFUN ("abbrev-symbol", Fabbrev_symbol,171,5171
+DEFUN ("abbrev-symbol", Fabbrev_symbol,abbrev-symbol171,5171
+DEFUN ("abbrev-expansion", Fabbrev_expansion,199,6135
+DEFUN ("abbrev-expansion", Fabbrev_expansion,abbrev-expansion199,6135
+DEFUN ("expand-abbrev", Fexpand_abbrev,215,6650
+DEFUN ("expand-abbrev", Fexpand_abbrev,expand-abbrev215,6650
+DEFUN ("unexpand-abbrev", Funexpand_abbrev,383,11495
+DEFUN ("unexpand-abbrev", Funexpand_abbrev,unexpand-abbrev383,11495
+write_abbrev 420,12702
+describe_abbrev 439,13137
+DEFUN ("insert-abbrev-table-description", Finsert_abbrev_table_description,460,13652
+DEFUN ("insert-abbrev-table-description", Finsert_abbrev_table_description,insert-abbrev-table-description460,13652
+DEFUN ("define-abbrev-table", Fdefine_abbrev_table,500,14808
+DEFUN ("define-abbrev-table", Fdefine_abbrev_table,define-abbrev-table500,14808
+syms_of_abbrev 534,15885
+ DEFVAR_LISP ("abbrev-table-name-list"536,15905
+ DEFVAR_LISP ("global-abbrev-table"542,16167
+ DEFVAR_LISP ("fundamental-mode-abbrev-table"549,16489
+ DEFVAR_LISP ("last-abbrev"555,16831
+ DEFVAR_LISP ("last-abbrev-text"558,16954
+ DEFVAR_INT ("last-abbrev-location"562,17112
+ DEFVAR_LISP ("abbrev-start-location"569,17311
+ DEFVAR_LISP ("abbrev-start-location-buffer"575,17588
+ DEFVAR_PER_BUFFER ("local-abbrev-table"580,17852
+ DEFVAR_BOOL ("abbrevs-changed"583,17995
+ DEFVAR_BOOL ("abbrev-all-caps"588,18198
+ DEFVAR_LISP ("abbrev-table-name-list",\1536,15905
+ DEFVAR_LISP ("global-abbrev-table",\1542,16167
+ DEFVAR_LISP ("fundamental-mode-abbrev-table",\1549,16489
+ DEFVAR_LISP ("last-abbrev",\1555,16831
+ DEFVAR_LISP ("last-abbrev-text",\1558,16954
+ DEFVAR_INT ("last-abbrev-location",\1562,17112
+ DEFVAR_LISP ("abbrev-start-location",\1569,17311
+ DEFVAR_LISP ("abbrev-start-location-buffer",\1575,17588
+ DEFVAR_PER_BUFFER ("local-abbrev-table",\1580,17852
+ DEFVAR_BOOL ("abbrevs-changed",\1583,17995
+ DEFVAR_BOOL ("abbrev-all-caps",\1588,18198
c-src/torture.c,197
(*tag1 tag118,452
@@ -276,439 +272,439 @@ extern int getopt_long_only 116,4187
extern int _getopt_internal 118,4220
c-src/etags.c,14175
-char pot_etags_version[pot_etags_version81,3470
-# undef DEBUG84,3552
-# define DEBUG 85,3567
-# define DEBUG 87,3594
-# define NDEBUG 88,3617
-# define _GNU_SOURCE 94,3705
-# undef MSDOS100,3876
-# undef WINDOWSNT101,3890
-# define WINDOWSNT102,3909
-# undef MSDOS106,3968
-# define MSDOS 107,3982
-# define MSDOS 110,4032
-# define MAXPATHLEN 115,4111
-# undef HAVE_NTGUI116,4141
-# undef DOS_NT117,4160
-# define DOS_NT118,4176
-# undef assert 135,4482
-# define assert(136,4541
-# undef CTAGS146,4857
-# define CTAGS 147,4872
-# define CTAGS 149,4898
-#define streq(152,4927
-#define strcaseeq(153,4996
-#define strneq(154,5075
-#define strncaseeq(155,5151
-#define CHARS 157,5238
-#define CHAR(158,5278
-#define iswhite(159,5329
-#define notinname(160,5394
-#define begtoken(161,5469
-#define intoken(162,5542
-#define endtoken(163,5614
-#define ISALNUM(165,5684
-#define ISALPHA(166,5722
-#define ISDIGIT(167,5760
-#define ISLOWER(168,5798
-#define lowcase(170,5837
-#define xnew(179,6015
-#define xrnew(180,6083
-typedef void Lang_function 182,6164
- const char *suffix;suffix186,6219
- const char *command;command187,6294
-} compressor;188,6365
- const char *name;name192,6397
- const char *help;help193,6449
- Lang_function *function;function194,6508
- const char **suffixes;suffixes195,6556
- const char **filenames;filenames196,6633
- const char **interpreters;interpreters197,6702
- bool metasource;198,6771
-} language;199,6835
-typedef struct fdesc201,6848
- struct fdesc *next;next203,6871
- char *infname;infname204,6920
- char *infabsname;infabsname205,6973
- char *infabsdir;infabsdir206,7038
- char *taggedfname;taggedfname207,7091
- language *lang;lang208,7149
- char *prop;prop209,7191
- bool usecharno;210,7249
- bool written;211,7311
-} fdesc;212,7366
-typedef struct node_st214,7376
- struct node_st *left,left216,7428
- struct node_st *left, *right;right216,7428
- fdesc *fdp;fdp217,7486
- char *name;name218,7548
- char *regex;regex219,7580
- bool valid;220,7617
- bool is_func;221,7670
- bool been_warned;222,7733
- int lno;223,7801
- long cno;224,7842
-} node;225,7894
- long size;236,8208
- int len;237,8221
- char *buffer;buffer238,8232
-} linebuffer;239,8248
- at_language,245,8344
- at_regexp,246,8393
- at_filename,247,8437
- at_stdin,248,8473
- at_end 249,8516
- } arg_type;250,8557
- language *lang;lang251,8593
- char *what;what252,8656
-} argument;253,8698
-typedef struct regexp256,8758
- struct regexp *p_next;p_next258,8782
- language *lang;lang259,8837
- char *pattern;pattern260,8897
- char *name;name261,8940
- struct re_pattern_buffer *pat;pat262,8971
- struct re_registers regs;263,9031
- bool error_signaled;264,9078
- bool force_explicit_name;265,9141
- bool ignore_case;266,9206
- bool multi_line;267,9259
-} regexp;268,9325
-static void Ada_funcs 274,9428
-static void Asm_labels 275,9460
-static void C_entries 276,9493
-static void default_C_entries 277,9536
-static void plain_C_entries 278,9576
-static void Cjava_entries 279,9614
-static void Cobol_paragraphs 280,9650
-static void Cplusplus_entries 281,9689
-static void Cstar_entries 282,9729
-static void Erlang_functions 283,9765
-static void Forth_words 284,9804
-static void Fortran_functions 285,9838
-static void HTML_labels 286,9878
-static void Lisp_functions 287,9912
-static void Lua_functions 288,9949
-static void Makefile_targets 289,9985
-static void Pascal_functions 290,10024
-static void Perl_functions 291,10063
-static void PHP_functions 292,10100
-static void PS_functions 293,10136
-static void Prolog_functions 294,10171
-static void Python_functions 295,10210
-static void Scheme_functions 296,10249
-static void TeX_commands 297,10288
-static void Texinfo_nodes 298,10323
-static void Yacc_entries 299,10359
-static void just_read_file 300,10394
-static language *get_language_from_langname get_language_from_langname302,10432
-static void readline 303,10492
-static long readline_internal 304,10537
-static bool nocase_tail 305,10591
-static void get_tag 306,10631
-static void analyze_regex 308,10671
-static void free_regexps 309,10707
-static void regex_tag_multiline 310,10740
-static void error 311,10780
-# undef STDIN408,15073
-#define STDIN 411,15095
-static compressor compressors[compressors457,17664
-static const char *Ada_suffixes Ada_suffixes473,17907
-static const char Ada_help 475,17977
-static const char *Asm_suffixes Asm_suffixes493,18580
-static const char Asm_help 504,18976
-static const char *default_C_suffixes default_C_suffixes512,19312
-static const char default_C_help 515,19413
-static const char default_C_help 523,19850
-static const char *Cplusplus_suffixes Cplusplus_suffixes535,20460
-static const char Cplusplus_help 540,20658
-static const char *Cjava_suffixes Cjava_suffixes549,21113
-static char Cjava_help 551,21172
-static const char *Cobol_suffixes Cobol_suffixes556,21337
-static char Cobol_help 558,21402
-static const char *Cstar_suffixes Cstar_suffixes562,21543
-static const char *Erlang_suffixes Erlang_suffixes565,21607
-static const char Erlang_help 567,21673
-const char *Forth_suffixes Forth_suffixes571,21799
-static const char Forth_help 573,21857
-static const char *Fortran_suffixes Fortran_suffixes577,22008
-static const char Fortran_help 579,22085
-static const char *HTML_suffixes HTML_suffixes582,22190
-static const char HTML_help 584,22264
-static const char *Lisp_suffixes Lisp_suffixes589,22452
-static const char Lisp_help 591,22556
-static const char *Lua_suffixes Lua_suffixes598,22871
-static const char Lua_help 600,22934
-static const char *Makefile_filenames Makefile_filenames603,23010
-static const char Makefile_help 605,23133
-static const char *Objc_suffixes Objc_suffixes609,23277
-static const char Objc_help 613,23399
-static const char *Pascal_suffixes Pascal_suffixes619,23714
-static const char Pascal_help 621,23778
-static const char *Perl_suffixes Perl_suffixes626,23966
-static const char *Perl_interpreters Perl_interpreters628,24028
-static const char Perl_help 630,24100
-static const char *PHP_suffixes PHP_suffixes637,24451
-static const char PHP_help 639,24523
-static const char *plain_C_suffixes plain_C_suffixes643,24678
-static const char *PS_suffixes PS_suffixes647,24762
-static const char PS_help 649,24848
-static const char *Prolog_suffixes Prolog_suffixes652,24931
-static const char Prolog_help 654,24993
-static const char *Python_suffixes Python_suffixes658,25107
-static const char Python_help 660,25165
-static const char *Scheme_suffixes Scheme_suffixes665,25347
-static const char Scheme_help 667,25460
-static const char *TeX_suffixes TeX_suffixes672,25683
-static const char TeX_help 674,25781
-static const char *Texinfo_suffixes Texinfo_suffixes686,26316
-static const char Texinfo_help 688,26395
-static const char *Yacc_suffixes Yacc_suffixes691,26492
-static const char Yacc_help 693,26606
-static const char auto_help 699,26856
-static const char none_help 703,27020
-static const char no_lang_help 707,27143
-static language lang_names 718,27355
-print_language_names 753,29532
-# define EMACS_NAME 786,30755
-# define VERSION 789,30811
-print_version 792,30869
-# define PRINT_UNDOCUMENTED_OPTIONS_HELP 804,31173
-print_help 808,31250
-main 981,37438
-get_compressor_from_suffix 1319,46217
-get_language_from_langname 1355,47158
-get_language_from_interpreter 1377,47545
-get_language_from_filename 1399,47976
-process_file_name 1433,48834
-process_file 1555,51665
-init 1632,54150
-find_entries 1656,54901
-make_tag 1814,59707
-pfnote 1856,60942
-free_tree 1917,62744
-free_fdesc 1935,63029
-add_node 1955,63472
-invalidate_nodes 2035,65537
-static int total_size_of_entries 2067,66150
-static int number_len 2068,66193
-total_size_of_entries 2087,66694
-put_entries 2107,67154
-#define C_EXT 2193,68995
-#define C_PLAIN 2194,69037
-#define C_PLPL 2195,69070
-#define C_STAR 2196,69104
-#define C_JAVA 2197,69137
-#define C_AUTO 2198,69172
-#define YACC 2199,69242
-enum sym_type2204,69312
- st_none,2206,69328
- st_C_objprot,2207,69339
- st_C_objprot, st_C_objimpl,2207,69339
- st_C_objprot, st_C_objimpl, st_C_objend,2207,69339
- st_C_gnumacro,2208,69382
- st_C_ignore,2209,69399
- st_C_ignore, st_C_attribute,2209,69399
- st_C_javastruct,2210,69430
- st_C_operator,2211,69449
- st_C_class,2212,69466
- st_C_class, st_C_template,2212,69466
- st_C_struct,2213,69495
- st_C_struct, st_C_extern,2213,69495
- st_C_struct, st_C_extern, st_C_enum,2213,69495
- st_C_struct, st_C_extern, st_C_enum, st_C_define,2213,69495
- st_C_struct, st_C_extern, st_C_enum, st_C_define, st_C_typedef2213,69495
-struct C_stab_entry 2271,71278
-struct C_stab_entry { const char *name;name2271,71278
-struct C_stab_entry { const char *name; int c_ext;2271,71278
-struct C_stab_entry { const char *name; int c_ext; enum sym_type type;2271,71278
-hash 2275,71409
-in_word_set 2321,72937
- TOTAL_KEYWORDS 2325,73018
- MIN_WORD_LENGTH 2326,73045
- MAX_WORD_LENGTH 2327,73072
- MIN_HASH_VALUE 2328,73100
- MAX_HASH_VALUE 2329,73126
-C_symtype 2387,74985
-static bool inattribute;2400,75234
- fvnone,2408,75435
- fdefunkey,2409,75466
- fdefunname,2410,75512
- foperator,2411,75556
- fvnameseen,2412,75613
- fstartlist,2413,75666
- finlist,2414,75722
- flistseen,2415,75765
- fignore,2416,75813
- vignore 2417,75856
-} fvdef;2418,75901
-static bool fvextern;2420,75911
- tnone,2428,76089
- tkeyseen,2429,76119
- ttypeseen,2430,76160
- tinbody,2431,76199
- tend,2432,76238
- tignore 2433,76279
-} typdef;2434,76320
- snone,2443,76499
- skeyseen,2445,76575
- stagseen,2446,76620
- scolonseen 2447,76661
-} structdef;2448,76715
-static const char *objtag objtag2453,76809
- dnone,2460,76942
- dsharpseen,2461,76972
- ddefineseen,2462,77025
- dignorerest 2463,77070
-} definedef;2464,77112
- onone,2472,77267
- oprotocol,2473,77297
- oimplementation,2474,77347
- otagseen,2475,77395
- oparenseen,2476,77431
- ocatseen,2477,77486
- oinbody,2478,77525
- omethodsign,2479,77568
- omethodtag,2480,77626
- omethodcolon,2481,77666
- omethodparm,2482,77709
- oignore 2483,77755
-} objdef;2484,77787
-static struct tok2491,77944
- char *line;line2493,77964
- int offset;2494,78014
- int length;2495,78067
- bool valid;2502,78352
- bool named;2505,78487
- int lineno;2506,78528
- long linepos;2507,78576
-} token;2508,78626
-static void pushclass_above 2514,78784
-static void popclass_above 2515,78832
-static void write_classname 2516,78866
- char **cname;cname2519,78950
- int *bracelev;bracelev2520,78993
- int nl;2521,79042
- int size;2522,79096
-} cstack;2523,79136
-#define nestlev 2525,79264
-#define instruct 2527,79369
-pushclass_above 2531,79489
-popclass_above 2550,79948
-write_classname 2564,80162
-static bool consider_token 2592,80761
-static void make_C_tag 2593,80833
-consider_token 2613,81341
- long linepos;2922,88499
- linebuffer lb;2923,88515
-} lbs[lbs2924,88532
-#define current_lb_is_new 2926,88543
-#define switch_line_buffers(2927,88588
-#define curlb 2929,88641
-#define newlb 2930,88672
-#define curlinepos 2931,88703
-#define newlinepos 2932,88744
-#define plainc 2934,88786
-#define cplpl 2935,88830
-#define cjava 2936,88861
-#define CNL_SAVE_DEFINEDEF(2938,88905
-#define CNL(2947,89117
-make_C_tag 2960,89375
-C_entries 2986,90194
-default_C_entries 3833,110156
-plain_C_entries 3840,110276
-Cplusplus_entries 3847,110364
-Cjava_entries 3854,110460
-Cstar_entries 3861,110550
-Yacc_entries 3868,110642
-#define LOOP_ON_INPUT_LINES(3875,110720
-#define LOOKING_AT(3884,111056
-#define LOOKING_AT_NOCASE(3891,111461
-just_read_file 3901,111861
-static void F_takeprec 3910,111965
-static void F_getit 3911,111996
-F_takeprec 3914,112039
-F_getit 3937,112366
-Fortran_functions 3961,112840
-Ada_getit 4052,114669
-Ada_funcs 4115,116044
-Asm_labels 4228,118582
-Perl_functions 4261,119549
-Python_functions 4357,122057
-PHP_functions 4387,122684
-Cobol_paragraphs 4466,124471
-Makefile_targets 4494,125029
-Pascal_functions 4529,125950
-static void L_getit 4706,130277
-L_getit 4709,130318
-Lisp_functions 4725,130664
-Lua_functions 4785,131850
-PS_functions 4811,132385
-Forth_words 4841,133053
-Scheme_functions 4877,134092
-static linebuffer *TEX_toktab TEX_toktab4908,134781
-static const char *TEX_defenv TEX_defenv4912,134974
-static void TEX_mode 4917,135172
-static void TEX_decode_env 4918,135203
-static char TEX_esc 4920,135261
-static char TEX_opgrp 4921,135289
-static char TEX_clgrp 4922,135318
-TeX_commands 4928,135395
-#define TEX_LESC 4986,136652
-#define TEX_SESC 4987,136674
-TEX_mode 4992,136804
-TEX_decode_env 5026,137509
-Texinfo_nodes 5071,138554
-HTML_labels 5094,139013
-static size_t prolog_pr 5214,142192
-static void prolog_skip_comment 5215,142234
-static size_t prolog_atom 5216,142290
-Prolog_functions 5219,142347
-prolog_skip_comment 5255,143128
-prolog_pr 5281,143736
-prolog_atom 5319,144628
-static int erlang_func 5374,145540
-static void erlang_attribute 5375,145581
-static int erlang_atom 5376,145620
-Erlang_functions 5379,145666
-erlang_func 5438,146965
-erlang_attribute 5476,147642
-erlang_atom 5496,148061
-static char *scan_separators scan_separators5520,148487
-static void add_regex 5521,148526
-static char *substitute substitute5522,148570
-scan_separators 5534,149080
-analyze_regex 5586,150460
-add_regex 5654,152050
-substitute 5767,154797
-free_regexps 5814,155837
-regex_tag_multiline 5836,156291
-nocase_tail 5913,158263
-get_tag 5928,158519
-readline_internal 5959,159455
-readline 6037,161296
-savestr 6230,167243
-savenstr 6240,167473
-skip_spaces 6249,167679
-skip_non_spaces 6258,167833
-skip_name 6267,167983
-fatal 6277,168156
-pfatal 6284,168253
-suggest_asking_for_help 6291,168332
-error 6300,168554
-concat 6313,168846
-etags_getcwd 6329,169259
-relative_filename 6350,169725
-absolute_filename 6389,170751
-absolute_dirname 6453,172416
-filename_is_absolute 6472,172845
-canonicalize_filename 6484,173096
-# define ISUPPER(6491,173235
-linebuffer_init 6514,173656
-linebuffer_setlen 6524,173887
-xmalloc 6536,174148
-xrealloc 6545,174314
+char pot_etags_version[pot_etags_version81,3471
+# undef DEBUG84,3553
+# define DEBUG 85,3568
+# define DEBUG 87,3595
+# define NDEBUG 88,3618
+# define _GNU_SOURCE 94,3706
+# undef MSDOS100,3877
+# undef WINDOWSNT101,3891
+# define WINDOWSNT102,3910
+# undef MSDOS106,3969
+# define MSDOS 107,3983
+# define MSDOS 110,4033
+# define MAXPATHLEN 115,4112
+# undef HAVE_NTGUI116,4142
+# undef DOS_NT117,4161
+# define DOS_NT118,4177
+# undef assert 135,4483
+# define assert(136,4542
+# undef CTAGS146,4858
+# define CTAGS 147,4873
+# define CTAGS 149,4899
+#define streq(152,4928
+#define strcaseeq(153,4997
+#define strneq(154,5076
+#define strncaseeq(155,5152
+#define CHARS 157,5239
+#define CHAR(158,5279
+#define iswhite(159,5330
+#define notinname(160,5395
+#define begtoken(161,5470
+#define intoken(162,5543
+#define endtoken(163,5615
+#define ISALNUM(165,5685
+#define ISALPHA(166,5723
+#define ISDIGIT(167,5761
+#define ISLOWER(168,5799
+#define lowcase(170,5838
+#define xnew(179,6016
+#define xrnew(180,6084
+typedef void Lang_function 182,6165
+ const char *suffix;suffix186,6220
+ const char *command;command187,6295
+} compressor;188,6366
+ const char *name;name192,6398
+ const char *help;help193,6450
+ Lang_function *function;function194,6509
+ const char **suffixes;suffixes195,6557
+ const char **filenames;filenames196,6634
+ const char **interpreters;interpreters197,6703
+ bool metasource;198,6772
+} language;199,6836
+typedef struct fdesc201,6849
+ struct fdesc *next;next203,6872
+ char *infname;infname204,6921
+ char *infabsname;infabsname205,6974
+ char *infabsdir;infabsdir206,7039
+ char *taggedfname;taggedfname207,7092
+ language *lang;lang208,7150
+ char *prop;prop209,7192
+ bool usecharno;210,7250
+ bool written;211,7312
+} fdesc;212,7367
+typedef struct node_st214,7377
+ struct node_st *left,left216,7429
+ struct node_st *left, *right;right216,7429
+ fdesc *fdp;fdp217,7487
+ char *name;name218,7549
+ char *regex;regex219,7581
+ bool valid;220,7618
+ bool is_func;221,7671
+ bool been_warned;222,7734
+ int lno;223,7802
+ long cno;224,7843
+} node;225,7895
+ long size;236,8209
+ int len;237,8222
+ char *buffer;buffer238,8233
+} linebuffer;239,8249
+ at_language,245,8345
+ at_regexp,246,8394
+ at_filename,247,8438
+ at_stdin,248,8474
+ at_end 249,8517
+ } arg_type;250,8558
+ language *lang;lang251,8594
+ char *what;what252,8657
+} argument;253,8699
+typedef struct regexp256,8759
+ struct regexp *p_next;p_next258,8783
+ language *lang;lang259,8838
+ char *pattern;pattern260,8898
+ char *name;name261,8941
+ struct re_pattern_buffer *pat;pat262,8972
+ struct re_registers regs;263,9032
+ bool error_signaled;264,9079
+ bool force_explicit_name;265,9142
+ bool ignore_case;266,9207
+ bool multi_line;267,9260
+} regexp;268,9326
+static void Ada_funcs 274,9429
+static void Asm_labels 275,9461
+static void C_entries 276,9494
+static void default_C_entries 277,9537
+static void plain_C_entries 278,9577
+static void Cjava_entries 279,9615
+static void Cobol_paragraphs 280,9651
+static void Cplusplus_entries 281,9690
+static void Cstar_entries 282,9730
+static void Erlang_functions 283,9766
+static void Forth_words 284,9805
+static void Fortran_functions 285,9839
+static void HTML_labels 286,9879
+static void Lisp_functions 287,9913
+static void Lua_functions 288,9950
+static void Makefile_targets 289,9986
+static void Pascal_functions 290,10025
+static void Perl_functions 291,10064
+static void PHP_functions 292,10101
+static void PS_functions 293,10137
+static void Prolog_functions 294,10172
+static void Python_functions 295,10211
+static void Scheme_functions 296,10250
+static void TeX_commands 297,10289
+static void Texinfo_nodes 298,10324
+static void Yacc_entries 299,10360
+static void just_read_file 300,10395
+static language *get_language_from_langname get_language_from_langname302,10433
+static void readline 303,10493
+static long readline_internal 304,10538
+static bool nocase_tail 305,10592
+static void get_tag 306,10632
+static void analyze_regex 308,10672
+static void free_regexps 309,10708
+static void regex_tag_multiline 310,10741
+static void error 311,10781
+# undef STDIN408,15074
+#define STDIN 411,15096
+static compressor compressors[compressors457,17665
+static const char *Ada_suffixes Ada_suffixes473,17908
+static const char Ada_help 475,17978
+static const char *Asm_suffixes Asm_suffixes493,18581
+static const char Asm_help 504,18977
+static const char *default_C_suffixes default_C_suffixes512,19313
+static const char default_C_help 515,19414
+static const char default_C_help 523,19851
+static const char *Cplusplus_suffixes Cplusplus_suffixes535,20461
+static const char Cplusplus_help 540,20659
+static const char *Cjava_suffixes Cjava_suffixes549,21114
+static char Cjava_help 551,21173
+static const char *Cobol_suffixes Cobol_suffixes556,21338
+static char Cobol_help 558,21403
+static const char *Cstar_suffixes Cstar_suffixes562,21544
+static const char *Erlang_suffixes Erlang_suffixes565,21608
+static const char Erlang_help 567,21674
+const char *Forth_suffixes Forth_suffixes571,21800
+static const char Forth_help 573,21858
+static const char *Fortran_suffixes Fortran_suffixes577,22009
+static const char Fortran_help 579,22086
+static const char *HTML_suffixes HTML_suffixes582,22191
+static const char HTML_help 584,22265
+static const char *Lisp_suffixes Lisp_suffixes589,22453
+static const char Lisp_help 591,22557
+static const char *Lua_suffixes Lua_suffixes598,22872
+static const char Lua_help 600,22935
+static const char *Makefile_filenames Makefile_filenames603,23011
+static const char Makefile_help 605,23134
+static const char *Objc_suffixes Objc_suffixes609,23278
+static const char Objc_help 613,23400
+static const char *Pascal_suffixes Pascal_suffixes619,23715
+static const char Pascal_help 621,23779
+static const char *Perl_suffixes Perl_suffixes626,23967
+static const char *Perl_interpreters Perl_interpreters628,24029
+static const char Perl_help 630,24101
+static const char *PHP_suffixes PHP_suffixes637,24452
+static const char PHP_help 639,24524
+static const char *plain_C_suffixes plain_C_suffixes643,24679
+static const char *PS_suffixes PS_suffixes647,24763
+static const char PS_help 649,24849
+static const char *Prolog_suffixes Prolog_suffixes652,24932
+static const char Prolog_help 654,24994
+static const char *Python_suffixes Python_suffixes658,25108
+static const char Python_help 660,25166
+static const char *Scheme_suffixes Scheme_suffixes665,25348
+static const char Scheme_help 667,25461
+static const char *TeX_suffixes TeX_suffixes672,25684
+static const char TeX_help 674,25782
+static const char *Texinfo_suffixes Texinfo_suffixes686,26317
+static const char Texinfo_help 688,26396
+static const char *Yacc_suffixes Yacc_suffixes691,26493
+static const char Yacc_help 693,26607
+static const char auto_help 699,26857
+static const char none_help 703,27021
+static const char no_lang_help 707,27144
+static language lang_names 718,27356
+print_language_names 753,29533
+# define EMACS_NAME 786,30756
+# define VERSION 789,30812
+print_version 792,30870
+# define PRINT_UNDOCUMENTED_OPTIONS_HELP 804,31174
+print_help 808,31251
+main 981,37439
+get_compressor_from_suffix 1319,46218
+get_language_from_langname 1355,47159
+get_language_from_interpreter 1377,47546
+get_language_from_filename 1399,47977
+process_file_name 1433,48835
+process_file 1555,51666
+init 1632,54151
+find_entries 1656,54902
+make_tag 1814,59708
+pfnote 1856,60943
+free_tree 1917,62745
+free_fdesc 1935,63030
+add_node 1955,63473
+invalidate_nodes 2035,65538
+static int total_size_of_entries 2067,66151
+static int number_len 2068,66194
+total_size_of_entries 2087,66695
+put_entries 2107,67155
+#define C_EXT 2193,68996
+#define C_PLAIN 2194,69038
+#define C_PLPL 2195,69071
+#define C_STAR 2196,69105
+#define C_JAVA 2197,69138
+#define C_AUTO 2198,69173
+#define YACC 2199,69243
+enum sym_type2204,69313
+ st_none,2206,69329
+ st_C_objprot,2207,69340
+ st_C_objprot, st_C_objimpl,2207,69340
+ st_C_objprot, st_C_objimpl, st_C_objend,2207,69340
+ st_C_gnumacro,2208,69383
+ st_C_ignore,2209,69400
+ st_C_ignore, st_C_attribute,2209,69400
+ st_C_javastruct,2210,69431
+ st_C_operator,2211,69450
+ st_C_class,2212,69467
+ st_C_class, st_C_template,2212,69467
+ st_C_struct,2213,69496
+ st_C_struct, st_C_extern,2213,69496
+ st_C_struct, st_C_extern, st_C_enum,2213,69496
+ st_C_struct, st_C_extern, st_C_enum, st_C_define,2213,69496
+ st_C_struct, st_C_extern, st_C_enum, st_C_define, st_C_typedef2213,69496
+struct C_stab_entry 2271,71279
+struct C_stab_entry { const char *name;name2271,71279
+struct C_stab_entry { const char *name; int c_ext;2271,71279
+struct C_stab_entry { const char *name; int c_ext; enum sym_type type;2271,71279
+hash 2275,71410
+in_word_set 2321,72938
+ TOTAL_KEYWORDS 2325,73019
+ MIN_WORD_LENGTH 2326,73046
+ MAX_WORD_LENGTH 2327,73073
+ MIN_HASH_VALUE 2328,73101
+ MAX_HASH_VALUE 2329,73127
+C_symtype 2387,74986
+static bool inattribute;2400,75235
+ fvnone,2408,75436
+ fdefunkey,2409,75467
+ fdefunname,2410,75513
+ foperator,2411,75557
+ fvnameseen,2412,75614
+ fstartlist,2413,75667
+ finlist,2414,75723
+ flistseen,2415,75766
+ fignore,2416,75814
+ vignore 2417,75857
+} fvdef;2418,75902
+static bool fvextern;2420,75912
+ tnone,2428,76090
+ tkeyseen,2429,76120
+ ttypeseen,2430,76161
+ tinbody,2431,76200
+ tend,2432,76239
+ tignore 2433,76280
+} typdef;2434,76321
+ snone,2443,76500
+ skeyseen,2445,76576
+ stagseen,2446,76621
+ scolonseen 2447,76662
+} structdef;2448,76716
+static const char *objtag objtag2453,76810
+ dnone,2460,76943
+ dsharpseen,2461,76973
+ ddefineseen,2462,77026
+ dignorerest 2463,77071
+} definedef;2464,77113
+ onone,2472,77268
+ oprotocol,2473,77298
+ oimplementation,2474,77348
+ otagseen,2475,77396
+ oparenseen,2476,77432
+ ocatseen,2477,77487
+ oinbody,2478,77526
+ omethodsign,2479,77569
+ omethodtag,2480,77627
+ omethodcolon,2481,77667
+ omethodparm,2482,77710
+ oignore 2483,77756
+} objdef;2484,77788
+static struct tok2491,77945
+ char *line;line2493,77965
+ int offset;2494,78015
+ int length;2495,78068
+ bool valid;2502,78353
+ bool named;2505,78488
+ int lineno;2506,78529
+ long linepos;2507,78577
+} token;2508,78627
+static void pushclass_above 2514,78785
+static void popclass_above 2515,78833
+static void write_classname 2516,78867
+ char **cname;cname2519,78951
+ int *bracelev;bracelev2520,78994
+ int nl;2521,79043
+ int size;2522,79097
+} cstack;2523,79137
+#define nestlev 2525,79265
+#define instruct 2527,79370
+pushclass_above 2531,79490
+popclass_above 2550,79949
+write_classname 2564,80163
+static bool consider_token 2592,80762
+static void make_C_tag 2593,80834
+consider_token 2613,81342
+ long linepos;2922,88500
+ linebuffer lb;2923,88516
+} lbs[lbs2924,88533
+#define current_lb_is_new 2926,88544
+#define switch_line_buffers(2927,88589
+#define curlb 2929,88642
+#define newlb 2930,88673
+#define curlinepos 2931,88704
+#define newlinepos 2932,88745
+#define plainc 2934,88787
+#define cplpl 2935,88831
+#define cjava 2936,88862
+#define CNL_SAVE_DEFINEDEF(2938,88906
+#define CNL(2947,89118
+make_C_tag 2960,89376
+C_entries 2986,90195
+default_C_entries 3833,110157
+plain_C_entries 3840,110277
+Cplusplus_entries 3847,110365
+Cjava_entries 3854,110461
+Cstar_entries 3861,110551
+Yacc_entries 3868,110643
+#define LOOP_ON_INPUT_LINES(3875,110721
+#define LOOKING_AT(3884,111057
+#define LOOKING_AT_NOCASE(3891,111462
+just_read_file 3901,111862
+static void F_takeprec 3910,111966
+static void F_getit 3911,111997
+F_takeprec 3914,112040
+F_getit 3937,112367
+Fortran_functions 3961,112841
+Ada_getit 4052,114670
+Ada_funcs 4115,116045
+Asm_labels 4228,118583
+Perl_functions 4261,119550
+Python_functions 4357,122058
+PHP_functions 4387,122685
+Cobol_paragraphs 4466,124472
+Makefile_targets 4494,125030
+Pascal_functions 4529,125951
+static void L_getit 4706,130278
+L_getit 4709,130319
+Lisp_functions 4725,130665
+Lua_functions 4785,131851
+PS_functions 4811,132386
+Forth_words 4841,133054
+Scheme_functions 4877,134093
+static linebuffer *TEX_toktab TEX_toktab4908,134782
+static const char *TEX_defenv TEX_defenv4912,134975
+static void TEX_mode 4917,135173
+static void TEX_decode_env 4918,135204
+static char TEX_esc 4920,135262
+static char TEX_opgrp 4921,135290
+static char TEX_clgrp 4922,135319
+TeX_commands 4928,135396
+#define TEX_LESC 4986,136653
+#define TEX_SESC 4987,136675
+TEX_mode 4992,136805
+TEX_decode_env 5026,137510
+Texinfo_nodes 5071,138555
+HTML_labels 5094,139014
+static size_t prolog_pr 5214,142193
+static void prolog_skip_comment 5215,142235
+static size_t prolog_atom 5216,142291
+Prolog_functions 5219,142348
+prolog_skip_comment 5255,143129
+prolog_pr 5281,143737
+prolog_atom 5319,144629
+static int erlang_func 5374,145541
+static void erlang_attribute 5375,145582
+static int erlang_atom 5376,145621
+Erlang_functions 5379,145667
+erlang_func 5438,146966
+erlang_attribute 5476,147643
+erlang_atom 5496,148062
+static char *scan_separators scan_separators5520,148488
+static void add_regex 5521,148527
+static char *substitute substitute5522,148571
+scan_separators 5534,149081
+analyze_regex 5586,150461
+add_regex 5654,152051
+substitute 5767,154798
+free_regexps 5814,155838
+regex_tag_multiline 5836,156292
+nocase_tail 5913,158264
+get_tag 5928,158520
+readline_internal 5959,159456
+readline 6037,161297
+savestr 6230,167244
+savenstr 6240,167474
+skip_spaces 6249,167680
+skip_non_spaces 6258,167834
+skip_name 6267,167984
+fatal 6277,168157
+pfatal 6284,168254
+suggest_asking_for_help 6291,168333
+error 6300,168555
+concat 6313,168847
+etags_getcwd 6329,169260
+relative_filename 6350,169726
+absolute_filename 6389,170752
+absolute_dirname 6453,172417
+filename_is_absolute 6472,172846
+canonicalize_filename 6484,173097
+# define ISUPPER(6491,173236
+linebuffer_init 6514,173657
+linebuffer_setlen 6524,173888
+xmalloc 6536,174149
+xrealloc 6545,174315
c-src/exit.c,99
size_t n;28,972
@@ -764,2059 +760,2059 @@ pp287,1504
pp3(100,1616
c-src/emacs/src/gmalloc.c,7311
-#define USE_PTHREAD25,1002
-#undef get_current_dir_name33,1126
-extern void emacs_abort 47,1305
-#undef malloc64,2110
-#undef realloc65,2124
-#undef calloc66,2139
-#undef free67,2153
-#define malloc 68,2165
-#define realloc 69,2188
-#define calloc 70,2213
-#define aligned_alloc 71,2236
-#define free 72,2273
-extern void *bss_sbrk bss_sbrk76,2335
-extern int bss_sbrk_did_unexec;77,2375
-extern char bss_sbrk_buffer[bss_sbrk_buffer78,2407
-extern void *bss_sbrk_buffer_end;bss_sbrk_buffer_end79,2438
-#define DUMPED 80,2472
-#define ALLOCATED_BEFORE_DUMPING(81,2507
-extern void *malloc malloc94,2718
-#define INT_BIT 124,3934
-#define BLOCKLOG 125,3977
-#define BLOCKSIZE 126,4018
-#define BLOCKIFY(127,4052
-#define HEAP 131,4215
-#define FINAL_FREE_BLOCKS 135,4391
- int type;145,4676
- size_t nfree;150,4720
- size_t first;151,4777
- } frag;152,4834
- ptrdiff_t size;156,5055
- } info;157,5076
- } busy;158,5087
- size_t size;163,5215
- size_t next;164,5272
- size_t prev;165,5321
- } free;166,5374
- } malloc_info;167,5388
-extern char *_heapbase;_heapbase170,5449
-extern malloc_info *_heapinfo;_heapinfo173,5541
-#define BLOCK(176,5620
-#define ADDRESS(177,5682
-extern size_t _heapindex;180,5797
-extern size_t _heaplimit;183,5866
-struct list186,5939
- struct list *next;next188,5955
- struct list *prev;prev189,5978
-extern struct list _fraghead[_fraghead193,6056
-struct alignlist196,6153
- struct alignlist *next;next198,6174
- void *aligned;aligned199,6202
- void *exact;exact200,6270
-extern struct alignlist *_aligned_blocks;_aligned_blocks202,6334
-extern size_t _chunks_used;205,6401
-extern size_t _bytes_used;206,6429
-extern size_t _chunks_free;207,6456
-extern size_t _bytes_free;208,6484
-extern void *_malloc_internal _malloc_internal213,6673
-extern void *_realloc_internal _realloc_internal214,6713
-extern void _free_internal 215,6762
-extern void *_malloc_internal_nolock _malloc_internal_nolock216,6799
-extern void *_realloc_internal_nolock _realloc_internal_nolock217,6846
-extern void _free_internal_nolock 218,6902
-extern pthread_mutex_t _malloc_mutex,221,6966
-extern pthread_mutex_t _malloc_mutex, _aligned_blocks_mutex;221,6966
-extern int _malloc_thread_enabled_p;222,7027
-#define LOCK(223,7064
-#define UNLOCK(228,7195
-#define LOCK_ALIGNED_BLOCKS(233,7329
-#define UNLOCK_ALIGNED_BLOCKS(238,7484
-#define LOCK(244,7649
-#define UNLOCK(245,7664
-#define LOCK_ALIGNED_BLOCKS(246,7681
-#define UNLOCK_ALIGNED_BLOCKS(247,7711
-extern void *malloc_find_object_address malloc_find_object_address252,7865
-extern void *(*__morecore)__morecore256,8021
-extern void *__default_morecore __default_morecore259,8105
-extern void (*__after_morecore_hook)__after_morecore_hook263,8269
-extern size_t __malloc_extra_blocks;267,8442
-extern int __malloc_initialized;270,8552
-extern int __malloc_initialize 272,8646
-extern void (*__malloc_initialize_hook)__malloc_initialize_hook275,8723
-extern void (*__free_hook)__free_hook276,8771
-extern void *(*__malloc_hook)__malloc_hook277,8811
-extern void *(*__realloc_hook)__realloc_hook278,8856
-extern void *(*__memalign_hook)__memalign_hook279,8913
-enum mcheck_status283,9092
- MCHECK_DISABLED 285,9115
- MCHECK_OK,286,9187
- MCHECK_FREE,287,9226
- MCHECK_HEAD,288,9270
- MCHECK_TAIL 289,9334
-extern int mcheck 296,9701
-extern enum mcheck_status mprobe 301,9952
-extern void mtrace 304,10055
-extern void muntrace 305,10082
-struct mstats308,10153
- size_t bytes_total;310,10171
- size_t chunks_used;311,10225
- size_t bytes_used;312,10285
- size_t chunks_free;313,10351
- size_t bytes_free;314,10406
-extern struct mstats mstats 318,10518
-extern void memory_warnings 321,10625
-void *(*__malloc_hook)__malloc_hook352,11743
-char *_heapbase;_heapbase355,11829
-malloc_info *_heapinfo;_heapinfo358,11927
-static size_t heapsize;361,11983
-size_t _heapindex;364,12047
-size_t _heaplimit;367,12109
-struct list _fraghead[_fraghead370,12171
-size_t _chunks_used;373,12229
-size_t _bytes_used;374,12250
-size_t _chunks_free;375,12270
-size_t _bytes_free;376,12291
-int __malloc_initialized;379,12340
-size_t __malloc_extra_blocks;381,12367
-void (*__malloc_initialize_hook)__malloc_initialize_hook383,12398
-void (*__after_morecore_hook)__after_morecore_hook384,12439
-static int state_protected_p;400,12912
-static size_t last_state_size;401,12942
-static malloc_info *last_heapinfo;last_heapinfo402,12973
-protect_malloc_state 405,13014
-#define PROTECT_MALLOC_STATE(426,13627
-#define PROTECT_MALLOC_STATE(429,13697
-align 435,13794
-get_contiguous_space 466,14616
-register_heapinfo 497,15325
-pthread_mutex_t _malloc_mutex 517,15879
-pthread_mutex_t _aligned_blocks_mutex 518,15938
-int _malloc_thread_enabled_p;519,16005
-malloc_atfork_handler_prepare 522,16048
-malloc_atfork_handler_parent 529,16139
-malloc_atfork_handler_child 536,16233
-malloc_enable_thread 544,16375
-malloc_initialize_1 563,16961
-__malloc_initialize 594,17793
-static int morecore_recursing;604,17926
-morecore_nolock 609,18066
-_malloc_internal_nolock 722,21584
-_malloc_internal 920,28102
-malloc 932,28247
-extern void *_malloc _malloc956,29033
-extern void _free 957,29064
-extern void *_realloc _realloc958,29092
-_malloc 961,29140
-_free 967,29196
-_realloc 973,29240
-void (*__free_hook)__free_hook1001,30259
-struct alignlist *_aligned_blocks _aligned_blocks1004,30345
-_free_internal_nolock 1009,30474
-_free_internal 1255,38476
-free 1265,38603
-weak_alias 1277,38799
-#define min(1306,39813
-void *(*__realloc_hook)__realloc_hook1310,39898
-_realloc_internal_nolock 1319,40309
-_realloc_internal 1435,43563
-realloc 1447,43726
-calloc 1478,44894
-#define __sbrk 1513,46042
-extern void *__sbrk __sbrk1518,46247
-__default_morecore 1525,46511
-void *(*__memalign_hook)__memalign_hook1554,47456
-aligned_alloc 1557,47522
-memalign 1647,49704
-posix_memalign 1656,49909
-extern void *valloc valloc1695,51140
-extern int getpagesize 1700,51278
-static size_t pagesize;1703,51317
-valloc 1706,51349
-#undef malloc1715,51490
-#undef realloc1716,51504
-#undef calloc1717,51519
-#undef aligned_alloc1718,51533
-#undef free1719,51554
-extern void *malloc malloc1722,51609
-extern void *realloc realloc1723,51644
-extern void *calloc calloc1724,51691
-extern void free 1725,51740
-extern void *aligned_alloc aligned_alloc1727,51796
-extern int posix_memalign 1729,51890
-hybrid_malloc 1736,52083
-hybrid_calloc 1744,52188
-hybrid_free 1752,52319
-hybrid_aligned_alloc 1765,52626
-hybrid_realloc 1780,52984
-char *gget_current_dir_name gget_current_dir_name1808,53753
-hybrid_get_current_dir_name 1811,53797
-static void (*old_free_hook)old_free_hook1846,54921
-static void *(*old_malloc_hook)old_malloc_hook1847,54963
-static void *(*old_realloc_hook)old_realloc_hook1848,55010
-static void (*abortfunc)abortfunc1851,55124
-#define MAGICWORD 1854,55206
-#define MAGICFREE 1855,55261
-#define MAGICBYTE 1856,55316
-#define MALLOCFLOOD 1857,55348
-#define FREEFLOOD 1858,55382
-struct hdr1860,55415
- size_t size;1862,55430
- size_t magic;1863,55484
-checkhdr 1867,55581
-freehook 1891,56022
-mallochook 1927,56804
-reallochook 1944,57143
-mabort 1978,57901
-static int mcheck_used 2012,58586
-mcheck 2015,58619
-mprobe 2035,59138
+#define USE_PTHREAD25,1003
+#undef get_current_dir_name33,1127
+extern void emacs_abort 47,1306
+#undef malloc64,2111
+#undef realloc65,2125
+#undef calloc66,2140
+#undef free67,2154
+#define malloc 68,2166
+#define realloc 69,2189
+#define calloc 70,2214
+#define aligned_alloc 71,2237
+#define free 72,2274
+extern void *bss_sbrk bss_sbrk76,2336
+extern int bss_sbrk_did_unexec;77,2376
+extern char bss_sbrk_buffer[bss_sbrk_buffer78,2408
+extern void *bss_sbrk_buffer_end;bss_sbrk_buffer_end79,2439
+#define DUMPED 80,2473
+#define ALLOCATED_BEFORE_DUMPING(81,2508
+extern void *malloc malloc94,2719
+#define INT_BIT 124,3935
+#define BLOCKLOG 125,3978
+#define BLOCKSIZE 126,4019
+#define BLOCKIFY(127,4053
+#define HEAP 131,4216
+#define FINAL_FREE_BLOCKS 135,4392
+ int type;145,4677
+ size_t nfree;150,4721
+ size_t first;151,4778
+ } frag;152,4835
+ ptrdiff_t size;156,5056
+ } info;157,5077
+ } busy;158,5088
+ size_t size;163,5216
+ size_t next;164,5273
+ size_t prev;165,5322
+ } free;166,5375
+ } malloc_info;167,5389
+extern char *_heapbase;_heapbase170,5450
+extern malloc_info *_heapinfo;_heapinfo173,5542
+#define BLOCK(176,5621
+#define ADDRESS(177,5683
+extern size_t _heapindex;180,5798
+extern size_t _heaplimit;183,5867
+struct list186,5940
+ struct list *next;next188,5956
+ struct list *prev;prev189,5979
+extern struct list _fraghead[_fraghead193,6057
+struct alignlist196,6154
+ struct alignlist *next;next198,6175
+ void *aligned;aligned199,6203
+ void *exact;exact200,6271
+extern struct alignlist *_aligned_blocks;_aligned_blocks202,6335
+extern size_t _chunks_used;205,6402
+extern size_t _bytes_used;206,6430
+extern size_t _chunks_free;207,6457
+extern size_t _bytes_free;208,6485
+extern void *_malloc_internal _malloc_internal213,6674
+extern void *_realloc_internal _realloc_internal214,6714
+extern void _free_internal 215,6763
+extern void *_malloc_internal_nolock _malloc_internal_nolock216,6800
+extern void *_realloc_internal_nolock _realloc_internal_nolock217,6847
+extern void _free_internal_nolock 218,6903
+extern pthread_mutex_t _malloc_mutex,221,6967
+extern pthread_mutex_t _malloc_mutex, _aligned_blocks_mutex;221,6967
+extern int _malloc_thread_enabled_p;222,7028
+#define LOCK(223,7065
+#define UNLOCK(228,7196
+#define LOCK_ALIGNED_BLOCKS(233,7330
+#define UNLOCK_ALIGNED_BLOCKS(238,7485
+#define LOCK(244,7650
+#define UNLOCK(245,7665
+#define LOCK_ALIGNED_BLOCKS(246,7682
+#define UNLOCK_ALIGNED_BLOCKS(247,7712
+extern void *malloc_find_object_address malloc_find_object_address252,7866
+extern void *(*__morecore)__morecore256,8022
+extern void *__default_morecore __default_morecore259,8106
+extern void (*__after_morecore_hook)__after_morecore_hook263,8270
+extern size_t __malloc_extra_blocks;267,8443
+extern int __malloc_initialized;270,8553
+extern int __malloc_initialize 272,8647
+extern void (*__malloc_initialize_hook)__malloc_initialize_hook275,8724
+extern void (*__free_hook)__free_hook276,8772
+extern void *(*__malloc_hook)__malloc_hook277,8812
+extern void *(*__realloc_hook)__realloc_hook278,8857
+extern void *(*__memalign_hook)__memalign_hook279,8914
+enum mcheck_status283,9093
+ MCHECK_DISABLED 285,9116
+ MCHECK_OK,286,9188
+ MCHECK_FREE,287,9227
+ MCHECK_HEAD,288,9271
+ MCHECK_TAIL 289,9335
+extern int mcheck 296,9702
+extern enum mcheck_status mprobe 301,9953
+extern void mtrace 304,10056
+extern void muntrace 305,10083
+struct mstats308,10154
+ size_t bytes_total;310,10172
+ size_t chunks_used;311,10226
+ size_t bytes_used;312,10286
+ size_t chunks_free;313,10352
+ size_t bytes_free;314,10407
+extern struct mstats mstats 318,10519
+extern void memory_warnings 321,10626
+void *(*__malloc_hook)__malloc_hook352,11745
+char *_heapbase;_heapbase355,11831
+malloc_info *_heapinfo;_heapinfo358,11929
+static size_t heapsize;361,11985
+size_t _heapindex;364,12049
+size_t _heaplimit;367,12111
+struct list _fraghead[_fraghead370,12173
+size_t _chunks_used;373,12231
+size_t _bytes_used;374,12252
+size_t _chunks_free;375,12272
+size_t _bytes_free;376,12293
+int __malloc_initialized;379,12342
+size_t __malloc_extra_blocks;381,12369
+void (*__malloc_initialize_hook)__malloc_initialize_hook383,12400
+void (*__after_morecore_hook)__after_morecore_hook384,12441
+static int state_protected_p;400,12914
+static size_t last_state_size;401,12944
+static malloc_info *last_heapinfo;last_heapinfo402,12975
+protect_malloc_state 405,13016
+#define PROTECT_MALLOC_STATE(426,13629
+#define PROTECT_MALLOC_STATE(429,13699
+align 435,13796
+get_contiguous_space 466,14618
+register_heapinfo 497,15327
+pthread_mutex_t _malloc_mutex 517,15881
+pthread_mutex_t _aligned_blocks_mutex 518,15940
+int _malloc_thread_enabled_p;519,16007
+malloc_atfork_handler_prepare 522,16050
+malloc_atfork_handler_parent 529,16141
+malloc_atfork_handler_child 536,16235
+malloc_enable_thread 544,16377
+malloc_initialize_1 563,16963
+__malloc_initialize 594,17795
+static int morecore_recursing;604,17928
+morecore_nolock 609,18068
+_malloc_internal_nolock 722,21586
+_malloc_internal 920,28104
+malloc 932,28249
+extern void *_malloc _malloc956,29035
+extern void _free 957,29066
+extern void *_realloc _realloc958,29094
+_malloc 961,29142
+_free 967,29198
+_realloc 973,29242
+void (*__free_hook)__free_hook1001,30262
+struct alignlist *_aligned_blocks _aligned_blocks1004,30348
+_free_internal_nolock 1009,30477
+_free_internal 1255,38479
+free 1265,38606
+weak_alias 1277,38802
+#define min(1306,39817
+void *(*__realloc_hook)__realloc_hook1310,39902
+_realloc_internal_nolock 1319,40313
+_realloc_internal 1435,43567
+realloc 1447,43730
+calloc 1478,44899
+#define __sbrk 1513,46048
+extern void *__sbrk __sbrk1518,46253
+__default_morecore 1525,46517
+void *(*__memalign_hook)__memalign_hook1554,47463
+aligned_alloc 1557,47529
+memalign 1647,49711
+posix_memalign 1656,49916
+extern void *valloc valloc1695,51148
+extern int getpagesize 1700,51286
+static size_t pagesize;1703,51325
+valloc 1706,51357
+#undef malloc1715,51498
+#undef realloc1716,51512
+#undef calloc1717,51527
+#undef aligned_alloc1718,51541
+#undef free1719,51562
+extern void *malloc malloc1722,51617
+extern void *realloc realloc1723,51652
+extern void *calloc calloc1724,51699
+extern void free 1725,51748
+extern void *aligned_alloc aligned_alloc1727,51804
+extern int posix_memalign 1729,51898
+hybrid_malloc 1736,52091
+hybrid_calloc 1744,52196
+hybrid_free 1752,52327
+hybrid_aligned_alloc 1765,52634
+hybrid_realloc 1780,52990
+char *gget_current_dir_name gget_current_dir_name1808,53759
+hybrid_get_current_dir_name 1811,53803
+static void (*old_free_hook)old_free_hook1846,54928
+static void *(*old_malloc_hook)old_malloc_hook1847,54970
+static void *(*old_realloc_hook)old_realloc_hook1848,55017
+static void (*abortfunc)abortfunc1851,55131
+#define MAGICWORD 1854,55213
+#define MAGICFREE 1855,55268
+#define MAGICBYTE 1856,55323
+#define MALLOCFLOOD 1857,55355
+#define FREEFLOOD 1858,55389
+struct hdr1860,55422
+ size_t size;1862,55437
+ size_t magic;1863,55491
+checkhdr 1867,55588
+freehook 1891,56029
+mallochook 1927,56811
+reallochook 1944,57150
+mabort 1978,57908
+static int mcheck_used 2012,58593
+mcheck 2015,58626
+mprobe 2035,59145
c-src/emacs/src/regex.h,5300
-#define _REGEX_H 21,836
-typedef unsigned long reg_syntax_t;43,1577
-#define RE_BACKSLASH_ESCAPE_IN_LISTS 47,1749
-#define RE_BK_PLUS_QM 52,1969
-#define RE_CHAR_CLASSES 58,2298
-#define RE_CONTEXT_INDEP_ANCHORS 72,3032
-#define RE_CONTEXT_INDEP_OPS 80,3458
-#define RE_CONTEXT_INVALID_OPS 84,3658
-#define RE_DOT_NEWLINE 88,3801
-#define RE_DOT_NOT_NULL 92,3937
-#define RE_HAT_LISTS_NOT_NEWLINE 96,4082
-#define RE_INTERVALS 101,4292
-#define RE_LIMITED_OPS 105,4441
-#define RE_NEWLINE_ALT 109,4583
-#define RE_NO_BK_BRACES 114,4773
-#define RE_NO_BK_PARENS 118,4964
-#define RE_NO_BK_REFS 122,5120
-#define RE_NO_BK_VBAR 126,5316
-#define RE_NO_EMPTY_RANGES 132,5610
-#define RE_UNMATCHED_RIGHT_PAREN_ORD 136,5766
-#define RE_NO_POSIX_BACKTRACKING 140,5937
-#define RE_NO_GNU_OPS 144,6133
-#define RE_FRUGAL 147,6253
-#define RE_SHY_GROUPS 150,6360
-#define RE_NO_NEWLINE_ANCHOR 153,6468
-#define RE_DEBUG 161,6884
-extern reg_syntax_t re_syntax_options;167,7170
-extern Lisp_Object re_match_object;172,7344
-extern size_t re_max_failures;176,7454
-#define RE_SYNTAX_EMACS 183,7684
-#define RE_SYNTAX_AWK 186,7780
-#define RE_SYNTAX_GNU_AWK 193,8084
-#define RE_SYNTAX_POSIX_AWK 197,8255
-#define RE_SYNTAX_GREP 201,8393
-#define RE_SYNTAX_EGREP 206,8549
-#define RE_SYNTAX_POSIX_EGREP 212,8765
-#define RE_SYNTAX_ED 216,8910
-#define RE_SYNTAX_SED 218,8954
-#define _RE_SYNTAX_POSIX_COMMON 221,9072
-#define RE_SYNTAX_POSIX_BASIC 225,9215
-#define RE_SYNTAX_POSIX_MINIMAL_BASIC 231,9508
-#define RE_SYNTAX_POSIX_EXTENDED 234,9598
-#define RE_SYNTAX_POSIX_MINIMAL_EXTENDED 242,9967
-# undef RE_DUP_MAX253,10454
-#define RE_DUP_MAX 256,10540
-#define REG_EXTENDED 263,10762
-#define REG_ICASE 267,10886
-#define REG_NEWLINE 272,11070
-#define REG_NOSUB 276,11248
-#define REG_NOTBOL 286,11614
-#define REG_NOTEOL 289,11688
- REG_ENOSYS 297,11859
- REG_NOERROR 300,11941
- REG_NOMATCH,301,11976
- REG_BADPAT,305,12123
- REG_ECOLLATE,306,12162
- REG_ECTYPE,307,12203
- REG_EESCAPE,308,12255
- REG_ESUBREG,309,12298
- REG_EBRACK,310,12345
- REG_EPAREN,311,12391
- REG_EBRACE,312,12436
- REG_BADBR,313,12472
- REG_ERANGE,314,12519
- REG_ESPACE,315,12560
- REG_BADRPT,316,12601
- REG_EEND,319,12693
- REG_ESIZE,320,12728
- REG_ERPAREN,321,12790
- REG_ERANGEX 322,12859
-} reg_errcode_t;323,12911
-# define RE_TRANSLATE_TYPE 332,13273
-struct re_pattern_buffer335,13315
- unsigned char *buffer;buffer341,13538
- size_t allocated;344,13614
- size_t used;347,13686
- reg_syntax_t syntax;350,13769
- char *fastmap;fastmap355,13975
- RE_TRANSLATE_TYPE translate;361,14241
- size_t re_nsub;364,14329
- unsigned can_be_null 370,14624
-#define REGS_UNALLOCATED 376,14889
-#define REGS_REALLOCATE 377,14916
-#define REGS_FIXED 378,14942
- unsigned regs_allocated 379,14963
- unsigned fastmap_accurate 383,15136
- unsigned no_sub 387,15267
- unsigned not_bol 391,15398
- unsigned not_eol 394,15475
- unsigned used_syntax 398,15655
- unsigned multibyte 403,15805
- unsigned target_multibyte 407,15941
- int charset_unibyte;410,16032
-typedef struct re_pattern_buffer regex_t;416,16098
-typedef ssize_t regoff_t;423,16492
-struct re_registers428,16652
- unsigned num_regs;430,16674
- regoff_t *start;start431,16695
- regoff_t *end;end432,16714
-# define RE_NREGS 440,16942
- regoff_t rm_so;449,17159
- regoff_t rm_eo;450,17239
-} regmatch_t;451,17317
-extern reg_syntax_t re_set_syntax 457,17512
-extern const char *re_compile_pattern re_compile_pattern462,17776
-extern int re_compile_fastmap 469,18058
-extern regoff_t re_search 477,18466
-extern regoff_t re_search_2 485,18781
-extern regoff_t re_match 495,19177
-extern regoff_t re_match_2 501,19407
-extern void re_set_registers 520,20197
-extern char *re_comp re_comp528,20469
-extern int re_exec 529,20506
-# define _Restrict_ 540,20886
-# define _Restrict_ 542,20979
-# define _Restrict_544,21018
-# define _Restrict_arr_ 555,21418
-# define _Restrict_arr_557,21461
-extern reg_errcode_t regcomp 562,21530
-extern reg_errcode_t regexec 566,21656
-extern size_t regerror 571,21850
-extern void regfree 574,21956
-# define CHAR_CLASS_MAX_LENGTH 593,22470
-# define CHAR_CLASS_MAX_LENGTH 597,22648
-typedef wctype_t re_wctype_t;599,22692
-typedef wchar_t re_wchar_t;600,22722
-# define re_wctype 601,22750
-# define re_iswctype 602,22776
-# define re_wctype_to_bit(603,22806
-# define CHAR_CLASS_MAX_LENGTH 605,22844
-# define btowc(606,22906
-typedef enum { RECC_ERROR 609,22953
- RECC_ALNUM,610,22984
- RECC_ALNUM, RECC_ALPHA,610,22984
- RECC_ALNUM, RECC_ALPHA, RECC_WORD,610,22984
- RECC_GRAPH,611,23027
- RECC_GRAPH, RECC_PRINT,611,23027
- RECC_LOWER,612,23059
- RECC_LOWER, RECC_UPPER,612,23059
- RECC_PUNCT,613,23091
- RECC_PUNCT, RECC_CNTRL,613,23091
- RECC_DIGIT,614,23123
- RECC_DIGIT, RECC_XDIGIT,614,23123
- RECC_BLANK,615,23156
- RECC_BLANK, RECC_SPACE,615,23156
- RECC_MULTIBYTE,616,23188
- RECC_MULTIBYTE, RECC_NONASCII,616,23188
- RECC_ASCII,617,23227
- RECC_ASCII, RECC_UNIBYTE617,23227
-} re_wctype_t;618,23260
-extern char re_iswctype 620,23276
-extern re_wctype_t re_wctype 621,23329
-typedef int re_wchar_t;623,23387
-extern void re_set_whitespace_regexp 625,23412
+#define _REGEX_H 21,837
+typedef unsigned long reg_syntax_t;43,1578
+#define RE_BACKSLASH_ESCAPE_IN_LISTS 47,1750
+#define RE_BK_PLUS_QM 52,1970
+#define RE_CHAR_CLASSES 58,2299
+#define RE_CONTEXT_INDEP_ANCHORS 72,3033
+#define RE_CONTEXT_INDEP_OPS 80,3459
+#define RE_CONTEXT_INVALID_OPS 84,3659
+#define RE_DOT_NEWLINE 88,3802
+#define RE_DOT_NOT_NULL 92,3938
+#define RE_HAT_LISTS_NOT_NEWLINE 96,4083
+#define RE_INTERVALS 101,4293
+#define RE_LIMITED_OPS 105,4442
+#define RE_NEWLINE_ALT 109,4584
+#define RE_NO_BK_BRACES 114,4774
+#define RE_NO_BK_PARENS 118,4965
+#define RE_NO_BK_REFS 122,5121
+#define RE_NO_BK_VBAR 126,5317
+#define RE_NO_EMPTY_RANGES 132,5611
+#define RE_UNMATCHED_RIGHT_PAREN_ORD 136,5767
+#define RE_NO_POSIX_BACKTRACKING 140,5938
+#define RE_NO_GNU_OPS 144,6134
+#define RE_FRUGAL 147,6254
+#define RE_SHY_GROUPS 150,6361
+#define RE_NO_NEWLINE_ANCHOR 153,6469
+#define RE_DEBUG 161,6885
+extern reg_syntax_t re_syntax_options;167,7171
+extern Lisp_Object re_match_object;172,7345
+extern size_t re_max_failures;176,7455
+#define RE_SYNTAX_EMACS 183,7685
+#define RE_SYNTAX_AWK 186,7781
+#define RE_SYNTAX_GNU_AWK 193,8085
+#define RE_SYNTAX_POSIX_AWK 197,8256
+#define RE_SYNTAX_GREP 201,8394
+#define RE_SYNTAX_EGREP 206,8550
+#define RE_SYNTAX_POSIX_EGREP 212,8766
+#define RE_SYNTAX_ED 216,8911
+#define RE_SYNTAX_SED 218,8955
+#define _RE_SYNTAX_POSIX_COMMON 221,9073
+#define RE_SYNTAX_POSIX_BASIC 225,9216
+#define RE_SYNTAX_POSIX_MINIMAL_BASIC 231,9509
+#define RE_SYNTAX_POSIX_EXTENDED 234,9599
+#define RE_SYNTAX_POSIX_MINIMAL_EXTENDED 242,9968
+# undef RE_DUP_MAX253,10455
+#define RE_DUP_MAX 256,10541
+#define REG_EXTENDED 263,10763
+#define REG_ICASE 267,10887
+#define REG_NEWLINE 272,11071
+#define REG_NOSUB 276,11249
+#define REG_NOTBOL 286,11615
+#define REG_NOTEOL 289,11689
+ REG_ENOSYS 297,11860
+ REG_NOERROR 300,11942
+ REG_NOMATCH,301,11977
+ REG_BADPAT,305,12124
+ REG_ECOLLATE,306,12163
+ REG_ECTYPE,307,12204
+ REG_EESCAPE,308,12256
+ REG_ESUBREG,309,12299
+ REG_EBRACK,310,12346
+ REG_EPAREN,311,12392
+ REG_EBRACE,312,12437
+ REG_BADBR,313,12473
+ REG_ERANGE,314,12520
+ REG_ESPACE,315,12561
+ REG_BADRPT,316,12602
+ REG_EEND,319,12694
+ REG_ESIZE,320,12729
+ REG_ERPAREN,321,12791
+ REG_ERANGEX 322,12860
+} reg_errcode_t;323,12912
+# define RE_TRANSLATE_TYPE 332,13274
+struct re_pattern_buffer335,13316
+ unsigned char *buffer;buffer341,13539
+ size_t allocated;344,13615
+ size_t used;347,13687
+ reg_syntax_t syntax;350,13770
+ char *fastmap;fastmap355,13976
+ RE_TRANSLATE_TYPE translate;361,14242
+ size_t re_nsub;364,14330
+ unsigned can_be_null 370,14625
+#define REGS_UNALLOCATED 376,14890
+#define REGS_REALLOCATE 377,14917
+#define REGS_FIXED 378,14943
+ unsigned regs_allocated 379,14964
+ unsigned fastmap_accurate 383,15137
+ unsigned no_sub 387,15268
+ unsigned not_bol 391,15399
+ unsigned not_eol 394,15476
+ unsigned used_syntax 398,15656
+ unsigned multibyte 403,15806
+ unsigned target_multibyte 407,15942
+ int charset_unibyte;410,16033
+typedef struct re_pattern_buffer regex_t;416,16099
+typedef ssize_t regoff_t;423,16493
+struct re_registers428,16653
+ unsigned num_regs;430,16675
+ regoff_t *start;start431,16696
+ regoff_t *end;end432,16715
+# define RE_NREGS 440,16943
+ regoff_t rm_so;449,17160
+ regoff_t rm_eo;450,17240
+} regmatch_t;451,17318
+extern reg_syntax_t re_set_syntax 457,17513
+extern const char *re_compile_pattern re_compile_pattern462,17777
+extern int re_compile_fastmap 469,18059
+extern regoff_t re_search 477,18467
+extern regoff_t re_search_2 485,18782
+extern regoff_t re_match 495,19178
+extern regoff_t re_match_2 501,19408
+extern void re_set_registers 520,20198
+extern char *re_comp re_comp528,20470
+extern int re_exec 529,20507
+# define _Restrict_ 540,20887
+# define _Restrict_ 542,20980
+# define _Restrict_544,21019
+# define _Restrict_arr_ 555,21419
+# define _Restrict_arr_557,21462
+extern reg_errcode_t regcomp 562,21531
+extern reg_errcode_t regexec 566,21657
+extern size_t regerror 571,21851
+extern void regfree 574,21957
+# define CHAR_CLASS_MAX_LENGTH 593,22471
+# define CHAR_CLASS_MAX_LENGTH 597,22649
+typedef wctype_t re_wctype_t;599,22693
+typedef wchar_t re_wchar_t;600,22723
+# define re_wctype 601,22751
+# define re_iswctype 602,22777
+# define re_wctype_to_bit(603,22807
+# define CHAR_CLASS_MAX_LENGTH 605,22845
+# define btowc(606,22907
+typedef enum { RECC_ERROR 609,22954
+ RECC_ALNUM,610,22985
+ RECC_ALNUM, RECC_ALPHA,610,22985
+ RECC_ALNUM, RECC_ALPHA, RECC_WORD,610,22985
+ RECC_GRAPH,611,23028
+ RECC_GRAPH, RECC_PRINT,611,23028
+ RECC_LOWER,612,23060
+ RECC_LOWER, RECC_UPPER,612,23060
+ RECC_PUNCT,613,23092
+ RECC_PUNCT, RECC_CNTRL,613,23092
+ RECC_DIGIT,614,23124
+ RECC_DIGIT, RECC_XDIGIT,614,23124
+ RECC_BLANK,615,23157
+ RECC_BLANK, RECC_SPACE,615,23157
+ RECC_MULTIBYTE,616,23189
+ RECC_MULTIBYTE, RECC_NONASCII,616,23189
+ RECC_ASCII,617,23228
+ RECC_ASCII, RECC_UNIBYTE617,23228
+} re_wctype_t;618,23261
+extern char re_iswctype 620,23277
+extern re_wctype_t re_wctype 621,23330
+typedef int re_wchar_t;623,23388
+extern void re_set_whitespace_regexp 625,23413
c-src/emacs/src/keyboard.c,25243
-volatile int interrupt_input_blocked;76,1808
-volatile bool pending_signals;80,1944
-#define KBD_BUFFER_SIZE 82,1976
-KBOARD *initial_kboard;initial_kboard84,2006
-KBOARD *current_kboard;current_kboard85,2030
-static KBOARD *all_kboards;all_kboards86,2054
-static bool single_kboard;89,2154
-#define NUM_RECENT_KEYS 91,2182
-static int recent_keys_index;94,2269
-static int total_keys;97,2357
-static Lisp_Object recent_keys;100,2443
-Lisp_Object this_command_keys;107,2777
-ptrdiff_t this_command_key_count;108,2808
-static bool this_command_key_count_reset;112,2922
-static Lisp_Object raw_keybuf;116,3074
-static int raw_keybuf_count;117,3105
-#define GROW_RAW_KEYBUF 119,3135
-static ptrdiff_t this_single_command_key_start;125,3350
-static ptrdiff_t before_command_key_count;129,3498
-static ptrdiff_t before_command_echo_length;130,3541
-sigjmp_buf return_to_command_loop;135,3677
-static Lisp_Object recover_top_level_message;138,3791
-static Lisp_Object regular_top_level_message;143,3930
-static sys_jmp_buf getcjmp;147,4031
-bool waiting_for_input;150,4095
-static bool echoing;154,4186
-static struct kboard *ok_to_echo_at_next_pause;ok_to_echo_at_next_pause159,4328
-struct kboard *echo_kboard;echo_kboard166,4632
-Lisp_Object echo_message_buffer;171,4744
-bool immediate_quit;174,4837
-int quit_char;192,5623
-EMACS_INT command_loop_level;195,5680
-Lisp_Object unread_switch_frame;204,6108
-static ptrdiff_t last_non_minibuf_size;207,6216
-uintmax_t num_input_events;210,6334
-static EMACS_INT last_auto_save;214,6428
-static ptrdiff_t last_point_position;217,6523
-Lisp_Object internal_last_event_frame;228,7028
-static Lisp_Object read_key_sequence_cmd;232,7168
-static Lisp_Object read_key_sequence_remapped;233,7210
-static FILE *dribble;dribble236,7310
-bool input_pending;239,7368
-static bool input_was_pending;287,10022
-static struct input_event kbd_buffer[kbd_buffer291,10107
-static struct input_event *kbd_fetch_ptr;kbd_fetch_ptr297,10386
-static struct input_event * volatile kbd_store_ptr;302,10601
-static void recursive_edit_unwind 313,11088
-static Lisp_Object command_loop 314,11144
-static void echo_now 316,11185
-static ptrdiff_t echo_length 317,11214
-unsigned timers_run;320,11296
-struct timespec *input_available_clear_time;input_available_clear_time324,11408
-bool interrupt_input;328,11573
-bool interrupts_deferred;331,11671
-static struct timespec timer_idleness_start_time;335,11746
-static struct timespec timer_last_idleness_start_time;340,11916
-#define READABLE_EVENTS_DO_TIMERS_NOW 346,12046
-#define READABLE_EVENTS_FILTER_EVENTS 347,12094
-#define READABLE_EVENTS_IGNORE_SQUEEZABLES 348,12142
-static void (*keyboard_init_hook)keyboard_init_hook351,12264
-static bool get_input_pending 353,12307
-static bool readable_events 354,12344
-static Lisp_Object read_char_x_menu_prompt 355,12379
-static Lisp_Object read_char_minibuf_menu_prompt 357,12502
-static Lisp_Object make_lispy_event 358,12571
-static Lisp_Object make_lispy_movement 359,12631
-static Lisp_Object modify_event_symbol 363,12840
-static Lisp_Object make_lispy_switch_frame 366,13050
-static Lisp_Object make_lispy_focus_in 367,13108
-static Lisp_Object make_lispy_focus_out 369,13188
-static bool help_char_p 371,13275
-static void save_getcjmp 372,13314
-static void restore_getcjmp 373,13354
-static Lisp_Object apply_modifiers 374,13397
-static void clear_event 375,13452
-static void restore_kboard_configuration 376,13500
-static void deliver_input_available_signal 378,13568
-static void handle_interrupt 380,13631
-static _Noreturn void quit_throw_to_read_char 381,13668
-static void process_special_events 382,13722
-static void timer_start_idle 383,13765
-static void timer_stop_idle 384,13802
-static void timer_resume_idle 385,13838
-static void deliver_user_signal 386,13876
-static char *find_user_signal_name find_user_signal_name387,13915
-static void store_user_signal_events 388,13957
-kset_echo_string 392,14088
-kset_kbd_queue 397,14184
-kset_keyboard_translate_table 402,14276
-kset_last_prefix_arg 407,14399
-kset_last_repeatable_command 412,14504
-kset_local_function_key_map 417,14625
-kset_overriding_terminal_local_map 422,14744
-kset_real_last_command 427,14877
-kset_system_key_syms 432,14986
-echo_add_key 443,15249
-echo_char 527,17527
-echo_dash 541,17813
-echo_now 586,19140
-cancel_echoing 635,20614
-echo_length 648,20922
-echo_truncate 660,21253
-add_command_key 672,21582
-recursive_edit_1 697,22406
-record_auto_save 742,23848
-force_auto_save_soon 751,24016
-DEFUN ("recursive-edit", Frecursive_edit,759,24137
-DEFUN ("recursive-edit", Frecursive_edit,recursive-edit759,24137
-recursive_edit_unwind 804,25747
-any_kboard_state 817,26013
-single_kboard_state 838,26665
-not_single_kboard_state 848,26803
-struct kboard_stack858,27065
- KBOARD *kboard;kboard860,27087
- struct kboard_stack *next;next861,27105
-static struct kboard_stack *kboard_stack;kboard_stack864,27138
-push_kboard 867,27186
-pop_kboard 879,27375
-temporarily_switch_to_single_kboard 914,28263
-record_single_kboard_state 943,29437
-restore_kboard_configuration 952,29621
-cmd_error 970,30077
-cmd_error_internal 1024,31510
-DEFUN ("command-error-default-function", Fcommand_error_default_function,1043,32030
-DEFUN ("command-error-default-function", Fcommand_error_default_function,command-error-default-function1043,32030
-static Lisp_Object command_loop_2 1086,33637
-static Lisp_Object top_level_1 1087,33686
-command_loop 1094,33916
-command_loop_2 1134,35135
-top_level_2 1146,35339
-top_level_1 1152,35417
-DEFUN ("top-level", Ftop_level,1164,35787
-DEFUN ("top-level", Ftop_level,top-level1164,35787
-user_error 1183,36288
-DEFUN ("exit-recursive-edit", Fexit_recursive_edit,1189,36429
-DEFUN ("exit-recursive-edit", Fexit_recursive_edit,exit-recursive-edit1189,36429
-DEFUN ("abort-recursive-edit", Fabort_recursive_edit,1201,36819
-DEFUN ("abort-recursive-edit", Fabort_recursive_edit,abort-recursive-edit1201,36819
-tracking_off 1216,37281
-DEFUN ("internal--track-mouse", Ftrack_mouse,1234,37816
-DEFUN ("internal--track-mouse", Ftrack_mouse,track-mouse1234,37816
-bool ignore_mouse_drag_p;1256,38392
-some_mouse_moved 1259,38441
-static int read_key_sequence 1282,38799
-static void adjust_point_for_property 1284,38917
-Lisp_Object last_undo_boundary;1287,39032
-command_loop_1 1294,39273
-read_menu_command 1649,50889
-adjust_point_for_property 1678,51617
-safe_run_hooks_1 1831,57339
-safe_run_hooks_error 1841,57569
-safe_run_hook_funcall 1878,58576
-safe_run_hooks 1893,59058
-int poll_suppress_count;1908,59397
-static struct atimer *poll_timer;poll_timer1915,59487
-poll_for_input_1 1919,59589
-poll_for_input 1930,59789
-start_polling 1942,60053
-input_polling_used 1979,61091
-stop_polling 1994,61390
-set_poll_suppress_count 2009,61759
-bind_polling_period 2029,62141
-make_ctrl_char 2048,62492
-show_help_echo 2113,64455
-static Lisp_Object kbd_buffer_get_event 2152,65484
-static void record_char 2154,65596
-static Lisp_Object help_form_saved_window_configs;2156,65638
-read_char_help_form_unwind 2158,65701
-#define STOP_POLLING 2166,65959
-#define RESUME_POLLING 2170,66084
-read_event_from_main_queue 2175,66229
-read_decoded_event_from_main_queue 2249,68417
-#define MAX_ENCODED_BYTES 2254,68664
-echo_keystrokes_p 2342,71556
-read_char 2376,72848
-record_menu_key 3225,98949
-help_char_p 3258,99674
-record_char 3273,99953
-save_getcjmp 3412,104235
-restore_getcjmp 3418,104326
-readable_events 3430,104697
-int stop_character EXTERNALLY_VISIBLE;3497,106437
-event_to_kboard 3500,106493
-kbd_buffer_nr_stored 3522,107142
-kbd_buffer_store_event 3534,107483
-kbd_buffer_store_event_hold 3550,108025
-kbd_buffer_unget_event 3684,111617
-#define INPUT_EVENT_POS_MAX 3698,112018
-#define INPUT_EVENT_POS_MIN 3701,112147
-position_to_Time 3706,112287
-Time_to_position 3716,112514
-gen_help_event 3738,113171
-kbd_buffer_store_help_event 3756,113611
-discard_mouse_events 3773,113976
-kbd_buffer_events_waiting 3803,114711
-clear_event 3823,115068
-kbd_buffer_get_event 3836,115408
-process_special_events 4258,127881
-swallow_events 4322,129705
-timer_start_idle 4339,130098
-timer_stop_idle 4355,130576
-timer_resume_idle 4363,130720
-struct input_event last_timer_event EXTERNALLY_VISIBLE;4372,130912
-Lisp_Object pending_funcalls;4377,131172
-decode_timer 4381,131293
-timer_check_2 4414,132246
-timer_check 4572,136817
-DEFUN ("current-idle-time", Fcurrent_idle_time,4607,137662
-DEFUN ("current-idle-time", Fcurrent_idle_time,current-idle-time4607,137662
-static Lisp_Object accent_key_syms;4625,138239
-static Lisp_Object func_key_syms;4626,138275
-static Lisp_Object mouse_syms;4627,138309
-static Lisp_Object wheel_syms;4628,138340
-static Lisp_Object drag_n_drop_syms;4629,138371
-static const int lispy_accent_codes[lispy_accent_codes4634,138516
-static const char *const lispy_accent_keys[lispy_accent_keys4741,139878
-#define FUNCTION_KEY_OFFSET 4766,140314
-const char *const lispy_function_keys[lispy_function_keys4768,140347
-static const char *const lispy_multimedia_keys[lispy_multimedia_keys4962,148901
-static const char *const lispy_kana_keys[lispy_kana_keys5026,150135
-#define FUNCTION_KEY_OFFSET 5061,151751
-static const char *const lispy_function_keys[lispy_function_keys5065,151894
-#define ISO_FUNCTION_KEY_OFFSET 5149,154429
-static const char *const iso_lispy_function_keys[iso_lispy_function_keys5151,154469
-static Lisp_Object Vlispy_mouse_stem;5172,155328
-static const char *const lispy_wheel_names[lispy_wheel_names5174,155367
-static const char *const lispy_drag_n_drop_names[lispy_drag_n_drop_names5181,155619
-static short const scroll_bar_parts[scroll_bar_parts5189,155885
-static Lisp_Object button_down_location;5210,156910
-static int last_mouse_button;5215,157065
-static int last_mouse_x;5216,157095
-static int last_mouse_y;5217,157120
-static Time button_down_time;5218,157145
-static int double_click_count;5222,157229
-make_lispy_position 5228,157390
-toolkit_menubar_in_use 5456,163953
-make_scroll_bar_position 5469,164321
-make_lispy_event 5485,164967
-make_lispy_movement 6104,183531
-make_lispy_switch_frame 6131,184262
-make_lispy_focus_in 6137,184369
-make_lispy_focus_out 6145,184495
-parse_modifiers_uncached 6163,184945
-#define SINGLE_LETTER_MOD(6185,185465
-#undef SINGLE_LETTER_MOD6212,185906
-#define MULTI_LETTER_MOD(6214,185932
-#undef MULTI_LETTER_MOD6231,186400
-apply_modifiers_uncached 6273,187574
-static const char *const modifier_names[modifier_names6319,189193
-#define NUM_MOD_NAMES 6325,189399
-static Lisp_Object modifier_symbols;6327,189449
-lispy_modifier_list 6331,189586
-#define KEY_TO_CHAR(6353,190252
-parse_modifiers 6356,190328
-DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,6399,191517
-DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,event-symbol-parse-modifiers6399,191517
-apply_modifiers 6422,192391
-reorder_modifiers 6491,194720
-modify_event_symbol 6536,196528
-DEFUN ("event-convert-list", Fevent_convert_list,6628,199244
-DEFUN ("event-convert-list", Fevent_convert_list,event-convert-list6628,199244
-parse_solitary_modifier 6695,201135
-#define SINGLE_LETTER_MOD(6701,201258
-#define MULTI_LETTER_MOD(6705,201343
-#undef SINGLE_LETTER_MOD6763,202641
-#undef MULTI_LETTER_MOD6764,202666
-lucid_event_type_list_p 6775,202889
-get_input_pending 6814,203960
-record_asynch_buffer_change 6834,204579
-gobble_input 6872,205702
-tty_read_avail_input 6967,208310
-handle_async_input 7149,214039
-process_pending_signals 7165,214359
-unblock_input_to 7177,214645
-unblock_input 7200,215277
-totally_unblock_input 7209,215445
-handle_input_available_signal 7217,215529
-deliver_input_available_signal 7226,215700
-struct user_signal_info7235,215865
- int sig;7238,215915
- char *name;name7241,215956
- int npending;7244,216007
- struct user_signal_info *next;next7246,216024
-static struct user_signal_info *user_signals user_signals7250,216090
-add_user_signal 7253,216149
-handle_user_signal 7275,216598
-deliver_user_signal 7316,217558
-find_user_signal_name 7322,217659
-store_user_signal_events 7334,217841
-static void menu_bar_item 7362,218341
-static Lisp_Object menu_bar_one_keymap_changed_items;7363,218416
-static Lisp_Object menu_bar_items_vector;7368,218630
-static int menu_bar_items_index;7369,218672
-static const char *separator_names[separator_names7372,218707
-menu_separator_name_p 7393,219148
-menu_bar_items 7426,219852
-Lisp_Object item_properties;7568,224603
-menu_bar_item 7571,224645
-menu_item_eval_property_1 7647,227175
-eval_dyn 7658,227465
-menu_item_eval_property 7666,227675
-parse_menu_item 7686,228341
-static Lisp_Object tool_bar_items_vector;7965,236336
-static Lisp_Object tool_bar_item_properties;7970,236510
-static int ntool_bar_items;7974,236606
-static void init_tool_bar_items 7978,236664
-static void process_tool_bar_item 7979,236711
-static bool parse_tool_bar_item 7981,236801
-static void append_tool_bar_item 7982,236861
-tool_bar_items 7990,237083
-process_tool_bar_item 8075,239892
-#define PROP(8112,240969
-set_prop 8114,241038
-parse_tool_bar_item 8167,242453
-#undef PROP8379,248844
-init_tool_bar_items 8387,248969
-append_tool_bar_item 8401,249261
-read_char_x_menu_prompt 8443,250771
-read_char_minibuf_menu_prompt 8503,252445
-#define PUSH_C_STR(8527,253014
-follow_key 8726,258553
-active_maps 8733,258695
-typedef struct keyremap8742,259021
- Lisp_Object parent;8745,259107
- Lisp_Object map;8748,259224
- int start,8753,259446
- int start, end;8753,259446
-} keyremap;8754,259464
-access_keymap_keyremap 8764,259808
-keyremap_step 8811,261450
-test_undefined 8867,262934
-read_key_sequence 8916,264861
-read_key_sequence_vs 9826,295821
-DEFUN ("read-key-sequence", Fread_key_sequence,9885,297294
-DEFUN ("read-key-sequence", Fread_key_sequence,read-key-sequence9885,297294
-DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,9938,299982
-DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,read-key-sequence-vector9938,299982
-detect_input_pending 9950,300488
-detect_input_pending_ignore_squeezables 9959,300654
-detect_input_pending_run_timers 9967,300870
-clear_input_pending 9985,301362
-requeued_events_pending_p 9997,301732
-DEFUN ("input-pending-p", Finput_pending_p,10002,301813
-DEFUN ("input-pending-p", Finput_pending_p,input-pending-p10002,301813
-DEFUN ("recent-keys", Frecent_keys,10024,302596
-DEFUN ("recent-keys", Frecent_keys,recent-keys10024,302596
-DEFUN ("this-command-keys", Fthis_command_keys,10055,303517
-DEFUN ("this-command-keys", Fthis_command_keys,this-command-keys10055,303517
-DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,10068,303958
-DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,this-command-keys-vector10068,303958
-DEFUN ("this-single-command-keys", Fthis_single_command_keys,10080,304380
-DEFUN ("this-single-command-keys", Fthis_single_command_keys,this-single-command-keys10080,304380
-DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,10096,304955
-DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,this-single-command-raw-keys10096,304955
-DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,10109,305495
-DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,reset-this-command-lengths10109,305495
-DEFUN ("clear-this-command-keys", Fclear_this_command_keys,10136,306510
-DEFUN ("clear-this-command-keys", Fclear_this_command_keys,clear-this-command-keys10136,306510
-DEFUN ("recursion-depth", Frecursion_depth,10158,307069
-DEFUN ("recursion-depth", Frecursion_depth,recursion-depth10158,307069
-DEFUN ("open-dribble-file", Fopen_dribble_file,10169,307406
-DEFUN ("open-dribble-file", Fopen_dribble_file,open-dribble-file10169,307406
-DEFUN ("discard-input", Fdiscard_input,10203,308447
-DEFUN ("discard-input", Fdiscard_input,discard-input10203,308447
-DEFUN ("suspend-emacs", Fsuspend_emacs,10225,308949
-DEFUN ("suspend-emacs", Fsuspend_emacs,suspend-emacs10225,308949
-stuff_buffered_input 10285,311045
-set_waiting_for_input 10323,312016
-clear_waiting_for_input 10337,312390
-handle_interrupt_signal 10351,312754
-deliver_interrupt_signal 10378,313642
-static int volatile force_quit_count;10387,313932
-handle_interrupt 10401,314414
-quit_throw_to_read_char 10541,318711
-DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,10562,319288
-DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,set-input-interrupt-mode10562,319288
-DEFUN ("set-output-flow-control", Fset_output_flow_control,10609,320516
-DEFUN ("set-output-flow-control", Fset_output_flow_control,set-output-flow-control10609,320516
-DEFUN ("set-input-meta-mode", Fset_input_meta_mode,10643,321432
-DEFUN ("set-input-meta-mode", Fset_input_meta_mode,set-input-meta-mode10643,321432
-DEFUN ("set-quit-char", Fset_quit_char,10694,322706
-DEFUN ("set-quit-char", Fset_quit_char,set-quit-char10694,322706
-DEFUN ("set-input-mode", Fset_input_mode,10729,323570
-DEFUN ("set-input-mode", Fset_input_mode,set-input-mode10729,323570
-DEFUN ("current-input-mode", Fcurrent_input_mode,10750,324459
-DEFUN ("current-input-mode", Fcurrent_input_mode,current-input-mode10750,324459
-DEFUN ("posn-at-x-y", Fposn_at_x_y,10787,325837
-DEFUN ("posn-at-x-y", Fposn_at_x_y,posn-at-x-y10787,325837
-DEFUN ("posn-at-point", Fposn_at_point,10824,327060
-DEFUN ("posn-at-point", Fposn_at_point,posn-at-point10824,327060
-init_kboard 10861,328214
-allocate_kboard 10893,329284
-wipe_kboard 10909,329637
-delete_kboard 10917,329751
-init_keyboard 10942,330281
-struct event_head11021,332696
- short var;11023,332716
- short kind;11024,332729
-static const struct event_head head_table[head_table11027,332747
-syms_of_keyboard 11045,333577
- DEFVAR_LISP ("internal--top-level-message"11058,333972
- DEFVAR_LISP ("last-command-event"11312,342173
- DEFVAR_LISP ("last-nonmenu-event"11315,342297
- DEFVAR_LISP ("last-input-event"11321,342636
- DEFVAR_LISP ("unread-command-events"11324,342730
- DEFVAR_LISP ("unread-post-input-method-events"11332,343190
- DEFVAR_LISP ("unread-input-method-events"11338,343529
- DEFVAR_LISP ("meta-prefix-char"11346,343898
- DEFVAR_KBOARD ("last-command"11351,344106
- DEFVAR_KBOARD ("real-last-command"11368,344787
- DEFVAR_KBOARD ("last-repeatable-command"11372,344973
- DEFVAR_LISP ("this-command"11378,345261
- DEFVAR_LISP ("real-this-command"11384,345498
- DEFVAR_LISP ("this-command-keys-shift-translated"11388,345680
- DEFVAR_LISP ("this-original-command"11396,346123
- DEFVAR_INT ("auto-save-interval"11403,346520
- DEFVAR_LISP ("auto-save-timeout"11408,346734
- DEFVAR_LISP ("echo-keystrokes"11415,347079
- DEFVAR_INT ("polling-period"11421,347350
- DEFVAR_LISP ("double-click-time"11428,347693
- DEFVAR_INT ("double-click-fuzz"11435,348029
- DEFVAR_INT ("num-input-keys"11446,348519
- DEFVAR_INT ("num-nonmacro-input-events"11452,348794
- DEFVAR_LISP ("last-event-frame"11457,349032
- DEFVAR_LISP ("tty-erase-char"11463,349311
- DEFVAR_LISP ("help-char"11466,349434
- DEFVAR_LISP ("help-event-list"11472,349717
- DEFVAR_LISP ("help-form"11477,349928
- DEFVAR_LISP ("prefix-help-command"11483,350176
- DEFVAR_LISP ("top-level"11489,350454
- DEFVAR_KBOARD ("keyboard-translate-table"11495,350675
- DEFVAR_BOOL ("cannot-suspend"11511,351488
- DEFVAR_BOOL ("menu-prompting"11516,351715
- DEFVAR_LISP ("menu-prompt-more-char"11526,352145
- DEFVAR_INT ("extra-keyboard-modifiers"11531,352391
- DEFVAR_LISP ("deactivate-mark"11545,353117
- DEFVAR_LISP ("pre-command-hook"11553,353486
- DEFVAR_LISP ("post-command-hook"11560,353841
- DEFVAR_LISP ("echo-area-clear-hook"11568,354204
- DEFVAR_LISP ("lucid-menu-bar-dirty-flag"11574,354419
- DEFVAR_LISP ("menu-bar-final-items"11578,354622
- DEFVAR_LISP ("tool-bar-separator-image-expression"11583,354872
- DEFVAR_KBOARD ("overriding-terminal-local-map"11589,355230
- DEFVAR_LISP ("overriding-local-map"11598,355652
- DEFVAR_LISP ("overriding-local-map-menu-flag"11607,356103
- DEFVAR_LISP ("special-event-map"11613,356442
- DEFVAR_LISP ("track-mouse"11617,356630
- DEFVAR_KBOARD ("system-key-alist"11620,356757
- DEFVAR_KBOARD ("local-function-key-map"11629,357138
- DEFVAR_KBOARD ("input-decode-map"11658,358597
- DEFVAR_LISP ("function-key-map"11675,359385
- DEFVAR_LISP ("key-translation-map"11683,359801
- DEFVAR_LISP ("deferred-action-list"11689,360145
- DEFVAR_LISP ("deferred-action-function"11694,360393
- DEFVAR_LISP ("delayed-warnings-list"11700,360692
- DEFVAR_LISP ("timer-list"11708,361100
- DEFVAR_LISP ("timer-idle-list"11712,361252
- DEFVAR_LISP ("input-method-function"11716,361415
- DEFVAR_LISP ("input-method-previous-message"11737,362384
- DEFVAR_LISP ("show-help-function"11744,362745
- DEFVAR_LISP ("disable-point-adjustment"11749,362977
- DEFVAR_LISP ("global-disable-point-adjustment"11761,363527
- DEFVAR_LISP ("minibuffer-message-timeout"11770,363893
- DEFVAR_LISP ("throw-on-input"11775,364171
- DEFVAR_LISP ("command-error-function"11781,364422
- DEFVAR_LISP ("enable-disabled-menus-and-buttons"11790,364909
- DEFVAR_LISP ("select-active-regions"11798,365236
- DEFVAR_LISP ("saved-region-selection"11807,365628
- DEFVAR_LISP ("selection-inhibit-update-commands"11815,366013
- DEFVAR_LISP ("debug-on-event"11825,366554
-keys_of_keyboard 11841,367115
-mark_kboards 11916,370434
- DEFVAR_LISP ("internal--top-level-message",\111058,333972
- DEFVAR_LISP ("last-command-event",\111312,342173
- DEFVAR_LISP ("last-nonmenu-event",\111315,342297
- DEFVAR_LISP ("last-input-event",\111321,342636
- DEFVAR_LISP ("unread-command-events",\111324,342730
- DEFVAR_LISP ("unread-post-input-method-events",\111332,343190
- DEFVAR_LISP ("unread-input-method-events",\111338,343529
- DEFVAR_LISP ("meta-prefix-char",\111346,343898
- DEFVAR_KBOARD ("last-command",\111351,344106
- DEFVAR_KBOARD ("real-last-command",\111368,344787
- DEFVAR_KBOARD ("last-repeatable-command",\111372,344973
- DEFVAR_LISP ("this-command",\111378,345261
- DEFVAR_LISP ("real-this-command",\111384,345498
- DEFVAR_LISP ("this-command-keys-shift-translated",\111388,345680
- DEFVAR_LISP ("this-original-command",\111396,346123
- DEFVAR_INT ("auto-save-interval",\111403,346520
- DEFVAR_LISP ("auto-save-timeout",\111408,346734
- DEFVAR_LISP ("echo-keystrokes",\111415,347079
- DEFVAR_INT ("polling-period",\111421,347350
- DEFVAR_LISP ("double-click-time",\111428,347693
- DEFVAR_INT ("double-click-fuzz",\111435,348029
- DEFVAR_INT ("num-input-keys",\111446,348519
- DEFVAR_INT ("num-nonmacro-input-events",\111452,348794
- DEFVAR_LISP ("last-event-frame",\111457,349032
- DEFVAR_LISP ("tty-erase-char",\111463,349311
- DEFVAR_LISP ("help-char",\111466,349434
- DEFVAR_LISP ("help-event-list",\111472,349717
- DEFVAR_LISP ("help-form",\111477,349928
- DEFVAR_LISP ("prefix-help-command",\111483,350176
- DEFVAR_LISP ("top-level",\111489,350454
- DEFVAR_KBOARD ("keyboard-translate-table",\111495,350675
- DEFVAR_BOOL ("cannot-suspend",\111511,351488
- DEFVAR_BOOL ("menu-prompting",\111516,351715
- DEFVAR_LISP ("menu-prompt-more-char",\111526,352145
- DEFVAR_INT ("extra-keyboard-modifiers",\111531,352391
- DEFVAR_LISP ("deactivate-mark",\111545,353117
- DEFVAR_LISP ("pre-command-hook",\111553,353486
- DEFVAR_LISP ("post-command-hook",\111560,353841
- DEFVAR_LISP ("echo-area-clear-hook",\111568,354204
- DEFVAR_LISP ("lucid-menu-bar-dirty-flag",\111574,354419
- DEFVAR_LISP ("menu-bar-final-items",\111578,354622
- DEFVAR_LISP ("tool-bar-separator-image-expression",\111583,354872
- DEFVAR_KBOARD ("overriding-terminal-local-map",\111589,355230
- DEFVAR_LISP ("overriding-local-map",\111598,355652
- DEFVAR_LISP ("overriding-local-map-menu-flag",\111607,356103
- DEFVAR_LISP ("special-event-map",\111613,356442
- DEFVAR_LISP ("track-mouse",\111617,356630
- DEFVAR_KBOARD ("system-key-alist",\111620,356757
- DEFVAR_KBOARD ("local-function-key-map",\111629,357138
- DEFVAR_KBOARD ("input-decode-map",\111658,358597
- DEFVAR_LISP ("function-key-map",\111675,359385
- DEFVAR_LISP ("key-translation-map",\111683,359801
- DEFVAR_LISP ("deferred-action-list",\111689,360145
- DEFVAR_LISP ("deferred-action-function",\111694,360393
- DEFVAR_LISP ("delayed-warnings-list",\111700,360692
- DEFVAR_LISP ("timer-list",\111708,361100
- DEFVAR_LISP ("timer-idle-list",\111712,361252
- DEFVAR_LISP ("input-method-function",\111716,361415
- DEFVAR_LISP ("input-method-previous-message",\111737,362384
- DEFVAR_LISP ("show-help-function",\111744,362745
- DEFVAR_LISP ("disable-point-adjustment",\111749,362977
- DEFVAR_LISP ("global-disable-point-adjustment",\111761,363527
- DEFVAR_LISP ("minibuffer-message-timeout",\111770,363893
- DEFVAR_LISP ("throw-on-input",\111775,364171
- DEFVAR_LISP ("command-error-function",\111781,364422
- DEFVAR_LISP ("enable-disabled-menus-and-buttons",\111790,364909
- DEFVAR_LISP ("select-active-regions",\111798,365236
- DEFVAR_LISP ("saved-region-selection",\111807,365628
- DEFVAR_LISP ("selection-inhibit-update-commands",\111815,366013
- DEFVAR_LISP ("debug-on-event",\111825,366554
+volatile int interrupt_input_blocked;76,1809
+volatile bool pending_signals;80,1945
+#define KBD_BUFFER_SIZE 82,1977
+KBOARD *initial_kboard;initial_kboard84,2007
+KBOARD *current_kboard;current_kboard85,2031
+static KBOARD *all_kboards;all_kboards86,2055
+static bool single_kboard;89,2155
+#define NUM_RECENT_KEYS 91,2183
+static int recent_keys_index;94,2270
+static int total_keys;97,2358
+static Lisp_Object recent_keys;100,2444
+Lisp_Object this_command_keys;107,2778
+ptrdiff_t this_command_key_count;108,2809
+static bool this_command_key_count_reset;112,2923
+static Lisp_Object raw_keybuf;116,3075
+static int raw_keybuf_count;117,3106
+#define GROW_RAW_KEYBUF 119,3136
+static ptrdiff_t this_single_command_key_start;125,3351
+static ptrdiff_t before_command_key_count;129,3499
+static ptrdiff_t before_command_echo_length;130,3542
+sigjmp_buf return_to_command_loop;135,3678
+static Lisp_Object recover_top_level_message;138,3792
+static Lisp_Object regular_top_level_message;143,3931
+static sys_jmp_buf getcjmp;147,4032
+bool waiting_for_input;150,4096
+static bool echoing;154,4187
+static struct kboard *ok_to_echo_at_next_pause;ok_to_echo_at_next_pause159,4329
+struct kboard *echo_kboard;echo_kboard166,4633
+Lisp_Object echo_message_buffer;171,4745
+bool immediate_quit;174,4838
+int quit_char;192,5624
+EMACS_INT command_loop_level;195,5681
+Lisp_Object unread_switch_frame;204,6109
+static ptrdiff_t last_non_minibuf_size;207,6217
+uintmax_t num_input_events;210,6335
+static EMACS_INT last_auto_save;214,6429
+static ptrdiff_t last_point_position;217,6524
+Lisp_Object internal_last_event_frame;228,7029
+static Lisp_Object read_key_sequence_cmd;232,7169
+static Lisp_Object read_key_sequence_remapped;233,7211
+static FILE *dribble;dribble236,7311
+bool input_pending;239,7369
+static bool input_was_pending;287,10023
+static struct input_event kbd_buffer[kbd_buffer291,10108
+static struct input_event *kbd_fetch_ptr;kbd_fetch_ptr297,10387
+static struct input_event * volatile kbd_store_ptr;302,10602
+static void recursive_edit_unwind 313,11089
+static Lisp_Object command_loop 314,11145
+static void echo_now 316,11186
+static ptrdiff_t echo_length 317,11215
+unsigned timers_run;320,11297
+struct timespec *input_available_clear_time;input_available_clear_time324,11409
+bool interrupt_input;328,11574
+bool interrupts_deferred;331,11672
+static struct timespec timer_idleness_start_time;335,11747
+static struct timespec timer_last_idleness_start_time;340,11917
+#define READABLE_EVENTS_DO_TIMERS_NOW 346,12047
+#define READABLE_EVENTS_FILTER_EVENTS 347,12095
+#define READABLE_EVENTS_IGNORE_SQUEEZABLES 348,12143
+static void (*keyboard_init_hook)keyboard_init_hook351,12265
+static bool get_input_pending 353,12308
+static bool readable_events 354,12345
+static Lisp_Object read_char_x_menu_prompt 355,12380
+static Lisp_Object read_char_minibuf_menu_prompt 357,12503
+static Lisp_Object make_lispy_event 358,12572
+static Lisp_Object make_lispy_movement 359,12632
+static Lisp_Object modify_event_symbol 363,12841
+static Lisp_Object make_lispy_switch_frame 366,13051
+static Lisp_Object make_lispy_focus_in 367,13109
+static Lisp_Object make_lispy_focus_out 369,13189
+static bool help_char_p 371,13276
+static void save_getcjmp 372,13315
+static void restore_getcjmp 373,13355
+static Lisp_Object apply_modifiers 374,13398
+static void clear_event 375,13453
+static void restore_kboard_configuration 376,13501
+static void deliver_input_available_signal 378,13569
+static void handle_interrupt 380,13632
+static _Noreturn void quit_throw_to_read_char 381,13669
+static void process_special_events 382,13723
+static void timer_start_idle 383,13766
+static void timer_stop_idle 384,13803
+static void timer_resume_idle 385,13839
+static void deliver_user_signal 386,13877
+static char *find_user_signal_name find_user_signal_name387,13916
+static void store_user_signal_events 388,13958
+kset_echo_string 392,14089
+kset_kbd_queue 397,14185
+kset_keyboard_translate_table 402,14277
+kset_last_prefix_arg 407,14400
+kset_last_repeatable_command 412,14505
+kset_local_function_key_map 417,14626
+kset_overriding_terminal_local_map 422,14745
+kset_real_last_command 427,14878
+kset_system_key_syms 432,14987
+echo_add_key 443,15250
+echo_char 527,17528
+echo_dash 541,17814
+echo_now 586,19141
+cancel_echoing 635,20615
+echo_length 648,20923
+echo_truncate 660,21254
+add_command_key 672,21583
+recursive_edit_1 697,22407
+record_auto_save 742,23849
+force_auto_save_soon 751,24017
+DEFUN ("recursive-edit", Frecursive_edit,759,24138
+DEFUN ("recursive-edit", Frecursive_edit,recursive-edit759,24138
+recursive_edit_unwind 804,25751
+any_kboard_state 817,26017
+single_kboard_state 838,26669
+not_single_kboard_state 848,26807
+struct kboard_stack858,27069
+ KBOARD *kboard;kboard860,27091
+ struct kboard_stack *next;next861,27109
+static struct kboard_stack *kboard_stack;kboard_stack864,27142
+push_kboard 867,27190
+pop_kboard 879,27379
+temporarily_switch_to_single_kboard 914,28267
+record_single_kboard_state 943,29441
+restore_kboard_configuration 952,29625
+cmd_error 970,30081
+cmd_error_internal 1024,31514
+DEFUN ("command-error-default-function", Fcommand_error_default_function,1043,32034
+DEFUN ("command-error-default-function", Fcommand_error_default_function,command-error-default-function1043,32034
+static Lisp_Object command_loop_2 1086,33641
+static Lisp_Object top_level_1 1087,33690
+command_loop 1094,33920
+command_loop_2 1134,35139
+top_level_2 1146,35343
+top_level_1 1152,35421
+DEFUN ("top-level", Ftop_level,1164,35791
+DEFUN ("top-level", Ftop_level,top-level1164,35791
+user_error 1183,36292
+DEFUN ("exit-recursive-edit", Fexit_recursive_edit,1189,36433
+DEFUN ("exit-recursive-edit", Fexit_recursive_edit,exit-recursive-edit1189,36433
+DEFUN ("abort-recursive-edit", Fabort_recursive_edit,1201,36823
+DEFUN ("abort-recursive-edit", Fabort_recursive_edit,abort-recursive-edit1201,36823
+tracking_off 1216,37285
+DEFUN ("internal--track-mouse", Ftrack_mouse,1234,37820
+DEFUN ("internal--track-mouse", Ftrack_mouse,track-mouse1234,37820
+bool ignore_mouse_drag_p;1256,38396
+some_mouse_moved 1259,38445
+static int read_key_sequence 1282,38803
+static void adjust_point_for_property 1284,38921
+Lisp_Object last_undo_boundary;1287,39036
+command_loop_1 1294,39277
+read_menu_command 1649,50893
+adjust_point_for_property 1678,51621
+safe_run_hooks_1 1831,57343
+safe_run_hooks_error 1841,57573
+safe_run_hook_funcall 1878,58580
+safe_run_hooks 1893,59062
+int poll_suppress_count;1908,59401
+static struct atimer *poll_timer;poll_timer1915,59491
+poll_for_input_1 1919,59593
+poll_for_input 1930,59793
+start_polling 1942,60057
+input_polling_used 1979,61095
+stop_polling 1994,61394
+set_poll_suppress_count 2009,61763
+bind_polling_period 2029,62145
+make_ctrl_char 2048,62496
+show_help_echo 2113,64459
+static Lisp_Object kbd_buffer_get_event 2152,65488
+static void record_char 2154,65600
+static Lisp_Object help_form_saved_window_configs;2156,65642
+read_char_help_form_unwind 2158,65705
+#define STOP_POLLING 2166,65963
+#define RESUME_POLLING 2170,66088
+read_event_from_main_queue 2175,66233
+read_decoded_event_from_main_queue 2249,68421
+#define MAX_ENCODED_BYTES 2254,68668
+echo_keystrokes_p 2342,71560
+read_char 2376,72852
+record_menu_key 3225,98953
+help_char_p 3258,99678
+record_char 3273,99957
+save_getcjmp 3412,104239
+restore_getcjmp 3418,104330
+readable_events 3430,104701
+int stop_character EXTERNALLY_VISIBLE;3497,106441
+event_to_kboard 3500,106497
+kbd_buffer_nr_stored 3522,107146
+kbd_buffer_store_event 3534,107487
+kbd_buffer_store_event_hold 3550,108029
+kbd_buffer_unget_event 3684,111621
+#define INPUT_EVENT_POS_MAX 3698,112022
+#define INPUT_EVENT_POS_MIN 3701,112151
+position_to_Time 3706,112291
+Time_to_position 3716,112518
+gen_help_event 3738,113175
+kbd_buffer_store_help_event 3756,113615
+discard_mouse_events 3773,113980
+kbd_buffer_events_waiting 3803,114715
+clear_event 3823,115072
+kbd_buffer_get_event 3836,115412
+process_special_events 4258,127885
+swallow_events 4322,129709
+timer_start_idle 4339,130102
+timer_stop_idle 4355,130580
+timer_resume_idle 4363,130724
+struct input_event last_timer_event EXTERNALLY_VISIBLE;4372,130916
+Lisp_Object pending_funcalls;4377,131176
+decode_timer 4381,131297
+timer_check_2 4414,132250
+timer_check 4572,136821
+DEFUN ("current-idle-time", Fcurrent_idle_time,4607,137666
+DEFUN ("current-idle-time", Fcurrent_idle_time,current-idle-time4607,137666
+static Lisp_Object accent_key_syms;4625,138243
+static Lisp_Object func_key_syms;4626,138279
+static Lisp_Object mouse_syms;4627,138313
+static Lisp_Object wheel_syms;4628,138344
+static Lisp_Object drag_n_drop_syms;4629,138375
+static const int lispy_accent_codes[lispy_accent_codes4634,138520
+static const char *const lispy_accent_keys[lispy_accent_keys4741,139882
+#define FUNCTION_KEY_OFFSET 4766,140318
+const char *const lispy_function_keys[lispy_function_keys4768,140351
+static const char *const lispy_multimedia_keys[lispy_multimedia_keys4962,148905
+static const char *const lispy_kana_keys[lispy_kana_keys5026,150139
+#define FUNCTION_KEY_OFFSET 5061,151755
+static const char *const lispy_function_keys[lispy_function_keys5065,151898
+#define ISO_FUNCTION_KEY_OFFSET 5149,154433
+static const char *const iso_lispy_function_keys[iso_lispy_function_keys5151,154473
+static Lisp_Object Vlispy_mouse_stem;5172,155332
+static const char *const lispy_wheel_names[lispy_wheel_names5174,155371
+static const char *const lispy_drag_n_drop_names[lispy_drag_n_drop_names5181,155623
+static short const scroll_bar_parts[scroll_bar_parts5189,155889
+static Lisp_Object button_down_location;5210,156914
+static int last_mouse_button;5215,157069
+static int last_mouse_x;5216,157099
+static int last_mouse_y;5217,157124
+static Time button_down_time;5218,157149
+static int double_click_count;5222,157233
+make_lispy_position 5228,157394
+toolkit_menubar_in_use 5456,163957
+make_scroll_bar_position 5469,164325
+make_lispy_event 5485,164971
+make_lispy_movement 6104,183534
+make_lispy_switch_frame 6131,184265
+make_lispy_focus_in 6137,184372
+make_lispy_focus_out 6145,184498
+parse_modifiers_uncached 6163,184948
+#define SINGLE_LETTER_MOD(6185,185468
+#undef SINGLE_LETTER_MOD6212,185909
+#define MULTI_LETTER_MOD(6214,185935
+#undef MULTI_LETTER_MOD6231,186403
+apply_modifiers_uncached 6273,187577
+static const char *const modifier_names[modifier_names6319,189196
+#define NUM_MOD_NAMES 6325,189402
+static Lisp_Object modifier_symbols;6327,189452
+lispy_modifier_list 6331,189589
+#define KEY_TO_CHAR(6353,190255
+parse_modifiers 6356,190331
+DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,6399,191520
+DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,event-symbol-parse-modifiers6399,191520
+apply_modifiers 6422,192394
+reorder_modifiers 6491,194723
+modify_event_symbol 6536,196531
+DEFUN ("event-convert-list", Fevent_convert_list,6628,199247
+DEFUN ("event-convert-list", Fevent_convert_list,event-convert-list6628,199247
+parse_solitary_modifier 6695,201138
+#define SINGLE_LETTER_MOD(6701,201261
+#define MULTI_LETTER_MOD(6705,201346
+#undef SINGLE_LETTER_MOD6763,202644
+#undef MULTI_LETTER_MOD6764,202669
+lucid_event_type_list_p 6775,202892
+get_input_pending 6814,203963
+record_asynch_buffer_change 6834,204582
+gobble_input 6872,205705
+tty_read_avail_input 6967,208313
+handle_async_input 7149,214042
+process_pending_signals 7165,214362
+unblock_input_to 7177,214648
+unblock_input 7200,215280
+totally_unblock_input 7209,215448
+handle_input_available_signal 7217,215532
+deliver_input_available_signal 7226,215703
+struct user_signal_info7235,215868
+ int sig;7238,215918
+ char *name;name7241,215959
+ int npending;7244,216010
+ struct user_signal_info *next;next7246,216027
+static struct user_signal_info *user_signals user_signals7250,216093
+add_user_signal 7253,216152
+handle_user_signal 7275,216601
+deliver_user_signal 7316,217561
+find_user_signal_name 7322,217662
+store_user_signal_events 7334,217844
+static void menu_bar_item 7362,218344
+static Lisp_Object menu_bar_one_keymap_changed_items;7363,218419
+static Lisp_Object menu_bar_items_vector;7368,218633
+static int menu_bar_items_index;7369,218675
+static const char *separator_names[separator_names7372,218710
+menu_separator_name_p 7393,219151
+menu_bar_items 7426,219855
+Lisp_Object item_properties;7568,224606
+menu_bar_item 7571,224648
+menu_item_eval_property_1 7647,227178
+eval_dyn 7658,227468
+menu_item_eval_property 7666,227678
+parse_menu_item 7686,228344
+static Lisp_Object tool_bar_items_vector;7965,236339
+static Lisp_Object tool_bar_item_properties;7970,236513
+static int ntool_bar_items;7974,236609
+static void init_tool_bar_items 7978,236667
+static void process_tool_bar_item 7979,236714
+static bool parse_tool_bar_item 7981,236804
+static void append_tool_bar_item 7982,236864
+tool_bar_items 7990,237086
+process_tool_bar_item 8075,239895
+#define PROP(8112,240972
+set_prop 8114,241041
+parse_tool_bar_item 8167,242456
+#undef PROP8379,248847
+init_tool_bar_items 8387,248972
+append_tool_bar_item 8401,249264
+read_char_x_menu_prompt 8443,250774
+read_char_minibuf_menu_prompt 8503,252448
+#define PUSH_C_STR(8527,253017
+follow_key 8726,258556
+active_maps 8733,258698
+typedef struct keyremap8742,259024
+ Lisp_Object parent;8745,259110
+ Lisp_Object map;8748,259227
+ int start,8753,259449
+ int start, end;8753,259449
+} keyremap;8754,259467
+access_keymap_keyremap 8764,259811
+keyremap_step 8811,261453
+test_undefined 8867,262937
+read_key_sequence 8916,264864
+read_key_sequence_vs 9826,295824
+DEFUN ("read-key-sequence", Fread_key_sequence,9885,297297
+DEFUN ("read-key-sequence", Fread_key_sequence,read-key-sequence9885,297297
+DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,9938,299985
+DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,read-key-sequence-vector9938,299985
+detect_input_pending 9950,300491
+detect_input_pending_ignore_squeezables 9959,300657
+detect_input_pending_run_timers 9967,300873
+clear_input_pending 9985,301365
+requeued_events_pending_p 9997,301735
+DEFUN ("input-pending-p", Finput_pending_p,10002,301816
+DEFUN ("input-pending-p", Finput_pending_p,input-pending-p10002,301816
+DEFUN ("recent-keys", Frecent_keys,10024,302599
+DEFUN ("recent-keys", Frecent_keys,recent-keys10024,302599
+DEFUN ("this-command-keys", Fthis_command_keys,10055,303520
+DEFUN ("this-command-keys", Fthis_command_keys,this-command-keys10055,303520
+DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,10068,303961
+DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,this-command-keys-vector10068,303961
+DEFUN ("this-single-command-keys", Fthis_single_command_keys,10080,304383
+DEFUN ("this-single-command-keys", Fthis_single_command_keys,this-single-command-keys10080,304383
+DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,10096,304958
+DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,this-single-command-raw-keys10096,304958
+DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,10109,305498
+DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,reset-this-command-lengths10109,305498
+DEFUN ("clear-this-command-keys", Fclear_this_command_keys,10136,306513
+DEFUN ("clear-this-command-keys", Fclear_this_command_keys,clear-this-command-keys10136,306513
+DEFUN ("recursion-depth", Frecursion_depth,10158,307072
+DEFUN ("recursion-depth", Frecursion_depth,recursion-depth10158,307072
+DEFUN ("open-dribble-file", Fopen_dribble_file,10169,307409
+DEFUN ("open-dribble-file", Fopen_dribble_file,open-dribble-file10169,307409
+DEFUN ("discard-input", Fdiscard_input,10203,308450
+DEFUN ("discard-input", Fdiscard_input,discard-input10203,308450
+DEFUN ("suspend-emacs", Fsuspend_emacs,10225,308952
+DEFUN ("suspend-emacs", Fsuspend_emacs,suspend-emacs10225,308952
+stuff_buffered_input 10285,311048
+set_waiting_for_input 10323,312019
+clear_waiting_for_input 10337,312393
+handle_interrupt_signal 10351,312757
+deliver_interrupt_signal 10378,313645
+static int volatile force_quit_count;10387,313935
+handle_interrupt 10401,314417
+quit_throw_to_read_char 10541,318714
+DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,10562,319291
+DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,set-input-interrupt-mode10562,319291
+DEFUN ("set-output-flow-control", Fset_output_flow_control,10609,320519
+DEFUN ("set-output-flow-control", Fset_output_flow_control,set-output-flow-control10609,320519
+DEFUN ("set-input-meta-mode", Fset_input_meta_mode,10643,321435
+DEFUN ("set-input-meta-mode", Fset_input_meta_mode,set-input-meta-mode10643,321435
+DEFUN ("set-quit-char", Fset_quit_char,10694,322709
+DEFUN ("set-quit-char", Fset_quit_char,set-quit-char10694,322709
+DEFUN ("set-input-mode", Fset_input_mode,10729,323573
+DEFUN ("set-input-mode", Fset_input_mode,set-input-mode10729,323573
+DEFUN ("current-input-mode", Fcurrent_input_mode,10750,324462
+DEFUN ("current-input-mode", Fcurrent_input_mode,current-input-mode10750,324462
+DEFUN ("posn-at-x-y", Fposn_at_x_y,10787,325840
+DEFUN ("posn-at-x-y", Fposn_at_x_y,posn-at-x-y10787,325840
+DEFUN ("posn-at-point", Fposn_at_point,10824,327063
+DEFUN ("posn-at-point", Fposn_at_point,posn-at-point10824,327063
+init_kboard 10861,328217
+allocate_kboard 10893,329287
+wipe_kboard 10909,329640
+delete_kboard 10917,329754
+init_keyboard 10942,330284
+struct event_head11021,332699
+ short var;11023,332719
+ short kind;11024,332732
+static const struct event_head head_table[head_table11027,332750
+syms_of_keyboard 11045,333580
+ DEFVAR_LISP ("internal--top-level-message"11058,333975
+ DEFVAR_LISP ("last-command-event"11312,342176
+ DEFVAR_LISP ("last-nonmenu-event"11315,342300
+ DEFVAR_LISP ("last-input-event"11321,342639
+ DEFVAR_LISP ("unread-command-events"11324,342733
+ DEFVAR_LISP ("unread-post-input-method-events"11332,343193
+ DEFVAR_LISP ("unread-input-method-events"11338,343532
+ DEFVAR_LISP ("meta-prefix-char"11346,343901
+ DEFVAR_KBOARD ("last-command"11351,344109
+ DEFVAR_KBOARD ("real-last-command"11368,344790
+ DEFVAR_KBOARD ("last-repeatable-command"11372,344976
+ DEFVAR_LISP ("this-command"11378,345264
+ DEFVAR_LISP ("real-this-command"11384,345501
+ DEFVAR_LISP ("this-command-keys-shift-translated"11388,345683
+ DEFVAR_LISP ("this-original-command"11396,346126
+ DEFVAR_INT ("auto-save-interval"11403,346523
+ DEFVAR_LISP ("auto-save-timeout"11408,346737
+ DEFVAR_LISP ("echo-keystrokes"11415,347082
+ DEFVAR_INT ("polling-period"11421,347353
+ DEFVAR_LISP ("double-click-time"11428,347696
+ DEFVAR_INT ("double-click-fuzz"11435,348032
+ DEFVAR_INT ("num-input-keys"11446,348522
+ DEFVAR_INT ("num-nonmacro-input-events"11452,348797
+ DEFVAR_LISP ("last-event-frame"11457,349035
+ DEFVAR_LISP ("tty-erase-char"11463,349314
+ DEFVAR_LISP ("help-char"11466,349437
+ DEFVAR_LISP ("help-event-list"11472,349720
+ DEFVAR_LISP ("help-form"11477,349931
+ DEFVAR_LISP ("prefix-help-command"11483,350179
+ DEFVAR_LISP ("top-level"11489,350457
+ DEFVAR_KBOARD ("keyboard-translate-table"11495,350678
+ DEFVAR_BOOL ("cannot-suspend"11511,351491
+ DEFVAR_BOOL ("menu-prompting"11516,351718
+ DEFVAR_LISP ("menu-prompt-more-char"11526,352148
+ DEFVAR_INT ("extra-keyboard-modifiers"11531,352394
+ DEFVAR_LISP ("deactivate-mark"11545,353120
+ DEFVAR_LISP ("pre-command-hook"11553,353489
+ DEFVAR_LISP ("post-command-hook"11560,353844
+ DEFVAR_LISP ("echo-area-clear-hook"11568,354207
+ DEFVAR_LISP ("lucid-menu-bar-dirty-flag"11574,354422
+ DEFVAR_LISP ("menu-bar-final-items"11578,354625
+ DEFVAR_LISP ("tool-bar-separator-image-expression"11583,354875
+ DEFVAR_KBOARD ("overriding-terminal-local-map"11589,355233
+ DEFVAR_LISP ("overriding-local-map"11598,355655
+ DEFVAR_LISP ("overriding-local-map-menu-flag"11607,356106
+ DEFVAR_LISP ("special-event-map"11613,356445
+ DEFVAR_LISP ("track-mouse"11617,356633
+ DEFVAR_KBOARD ("system-key-alist"11620,356760
+ DEFVAR_KBOARD ("local-function-key-map"11629,357141
+ DEFVAR_KBOARD ("input-decode-map"11658,358600
+ DEFVAR_LISP ("function-key-map"11675,359388
+ DEFVAR_LISP ("key-translation-map"11683,359804
+ DEFVAR_LISP ("deferred-action-list"11689,360148
+ DEFVAR_LISP ("deferred-action-function"11694,360396
+ DEFVAR_LISP ("delayed-warnings-list"11700,360695
+ DEFVAR_LISP ("timer-list"11708,361103
+ DEFVAR_LISP ("timer-idle-list"11712,361255
+ DEFVAR_LISP ("input-method-function"11716,361418
+ DEFVAR_LISP ("input-method-previous-message"11737,362387
+ DEFVAR_LISP ("show-help-function"11744,362748
+ DEFVAR_LISP ("disable-point-adjustment"11749,362980
+ DEFVAR_LISP ("global-disable-point-adjustment"11761,363530
+ DEFVAR_LISP ("minibuffer-message-timeout"11770,363896
+ DEFVAR_LISP ("throw-on-input"11775,364174
+ DEFVAR_LISP ("command-error-function"11781,364425
+ DEFVAR_LISP ("enable-disabled-menus-and-buttons"11790,364912
+ DEFVAR_LISP ("select-active-regions"11798,365239
+ DEFVAR_LISP ("saved-region-selection"11807,365631
+ DEFVAR_LISP ("selection-inhibit-update-commands"11815,366016
+ DEFVAR_LISP ("debug-on-event"11825,366557
+keys_of_keyboard 11841,367118
+mark_kboards 11916,370437
+ DEFVAR_LISP ("internal--top-level-message",\111058,333975
+ DEFVAR_LISP ("last-command-event",\111312,342176
+ DEFVAR_LISP ("last-nonmenu-event",\111315,342300
+ DEFVAR_LISP ("last-input-event",\111321,342639
+ DEFVAR_LISP ("unread-command-events",\111324,342733
+ DEFVAR_LISP ("unread-post-input-method-events",\111332,343193
+ DEFVAR_LISP ("unread-input-method-events",\111338,343532
+ DEFVAR_LISP ("meta-prefix-char",\111346,343901
+ DEFVAR_KBOARD ("last-command",\111351,344109
+ DEFVAR_KBOARD ("real-last-command",\111368,344790
+ DEFVAR_KBOARD ("last-repeatable-command",\111372,344976
+ DEFVAR_LISP ("this-command",\111378,345264
+ DEFVAR_LISP ("real-this-command",\111384,345501
+ DEFVAR_LISP ("this-command-keys-shift-translated",\111388,345683
+ DEFVAR_LISP ("this-original-command",\111396,346126
+ DEFVAR_INT ("auto-save-interval",\111403,346523
+ DEFVAR_LISP ("auto-save-timeout",\111408,346737
+ DEFVAR_LISP ("echo-keystrokes",\111415,347082
+ DEFVAR_INT ("polling-period",\111421,347353
+ DEFVAR_LISP ("double-click-time",\111428,347696
+ DEFVAR_INT ("double-click-fuzz",\111435,348032
+ DEFVAR_INT ("num-input-keys",\111446,348522
+ DEFVAR_INT ("num-nonmacro-input-events",\111452,348797
+ DEFVAR_LISP ("last-event-frame",\111457,349035
+ DEFVAR_LISP ("tty-erase-char",\111463,349314
+ DEFVAR_LISP ("help-char",\111466,349437
+ DEFVAR_LISP ("help-event-list",\111472,349720
+ DEFVAR_LISP ("help-form",\111477,349931
+ DEFVAR_LISP ("prefix-help-command",\111483,350179
+ DEFVAR_LISP ("top-level",\111489,350457
+ DEFVAR_KBOARD ("keyboard-translate-table",\111495,350678
+ DEFVAR_BOOL ("cannot-suspend",\111511,351491
+ DEFVAR_BOOL ("menu-prompting",\111516,351718
+ DEFVAR_LISP ("menu-prompt-more-char",\111526,352148
+ DEFVAR_INT ("extra-keyboard-modifiers",\111531,352394
+ DEFVAR_LISP ("deactivate-mark",\111545,353120
+ DEFVAR_LISP ("pre-command-hook",\111553,353489
+ DEFVAR_LISP ("post-command-hook",\111560,353844
+ DEFVAR_LISP ("echo-area-clear-hook",\111568,354207
+ DEFVAR_LISP ("lucid-menu-bar-dirty-flag",\111574,354422
+ DEFVAR_LISP ("menu-bar-final-items",\111578,354625
+ DEFVAR_LISP ("tool-bar-separator-image-expression",\111583,354875
+ DEFVAR_KBOARD ("overriding-terminal-local-map",\111589,355233
+ DEFVAR_LISP ("overriding-local-map",\111598,355655
+ DEFVAR_LISP ("overriding-local-map-menu-flag",\111607,356106
+ DEFVAR_LISP ("special-event-map",\111613,356445
+ DEFVAR_LISP ("track-mouse",\111617,356633
+ DEFVAR_KBOARD ("system-key-alist",\111620,356760
+ DEFVAR_KBOARD ("local-function-key-map",\111629,357141
+ DEFVAR_KBOARD ("input-decode-map",\111658,358600
+ DEFVAR_LISP ("function-key-map",\111675,359388
+ DEFVAR_LISP ("key-translation-map",\111683,359804
+ DEFVAR_LISP ("deferred-action-list",\111689,360148
+ DEFVAR_LISP ("deferred-action-function",\111694,360396
+ DEFVAR_LISP ("delayed-warnings-list",\111700,360695
+ DEFVAR_LISP ("timer-list",\111708,361103
+ DEFVAR_LISP ("timer-idle-list",\111712,361255
+ DEFVAR_LISP ("input-method-function",\111716,361418
+ DEFVAR_LISP ("input-method-previous-message",\111737,362387
+ DEFVAR_LISP ("show-help-function",\111744,362748
+ DEFVAR_LISP ("disable-point-adjustment",\111749,362980
+ DEFVAR_LISP ("global-disable-point-adjustment",\111761,363530
+ DEFVAR_LISP ("minibuffer-message-timeout",\111770,363896
+ DEFVAR_LISP ("throw-on-input",\111775,364174
+ DEFVAR_LISP ("command-error-function",\111781,364425
+ DEFVAR_LISP ("enable-disabled-menus-and-buttons",\111790,364912
+ DEFVAR_LISP ("select-active-regions",\111798,365239
+ DEFVAR_LISP ("saved-region-selection",\111807,365631
+ DEFVAR_LISP ("selection-inhibit-update-commands",\111815,366016
+ DEFVAR_LISP ("debug-on-event",\111825,366557
c-src/emacs/src/lisp.h,41391
-#define EMACS_LISP_H22,800
-#define DECLARE_GDB_SYM(47,1421
-# define DEFINE_GDB_SYMBOL_BEGIN(49,1508
-# define DEFINE_GDB_SYMBOL_END(50,1578
-# define DEFINE_GDB_SYMBOL_BEGIN(52,1625
-# define DEFINE_GDB_SYMBOL_END(53,1702
-#undef min57,1790
-#undef max58,1801
-#define max(59,1812
-#define min(60,1854
-#define ARRAYELTS(63,1936
-#define GCTYPEBITS 67,2079
-DEFINE_GDB_SYMBOL_BEGIN GCTYPEBITS66,2037
-# define NONPOINTER_BITS 78,2567
-# define NONPOINTER_BITS 80,2600
-typedef int EMACS_INT;91,3023
-typedef unsigned int EMACS_UINT;92,3046
-# define EMACS_INT_MAX 93,3079
-# define pI 94,3111
-typedef long int EMACS_INT;96,3203
-typedef unsigned long EMACS_UINT;97,3231
-# define EMACS_INT_MAX 98,3265
-# define pI 99,3298
-typedef long long int EMACS_INT;103,3477
-typedef unsigned long long int EMACS_UINT;104,3510
-# define EMACS_INT_MAX 105,3553
-# define pI 106,3587
-enum { BOOL_VECTOR_BITS_PER_CHAR 114,3804
-#define BOOL_VECTOR_BITS_PER_CHAR 115,3840
-typedef size_t bits_word;123,4165
-# define BITS_WORD_MAX 124,4191
-enum { BITS_PER_BITS_WORD 125,4223
-typedef unsigned char bits_word;127,4290
-# define BITS_WORD_MAX 128,4323
-enum { BITS_PER_BITS_WORD 129,4386
-verify 131,4450
- BITS_PER_CHAR 136,4570
- BITS_PER_SHORT 137,4605
- BITS_PER_LONG 138,4657
- BITS_PER_EMACS_INT 139,4712
-typedef intmax_t printmax_t;148,5089
-typedef uintmax_t uprintmax_t;149,5118
-# define pMd 150,5149
-# define pMu 151,5170
-typedef EMACS_INT printmax_t;153,5197
-typedef EMACS_UINT uprintmax_t;154,5227
-# define pMd 155,5259
-# define pMu 156,5278
-# define pD 165,5664
-# define pD 167,5709
-# define pD 169,5756
-# define pD 171,5779
-# define eassert(200,7062
-# define eassume(201,7140
-extern _Noreturn void die 204,7206
-extern bool suppress_checking EXTERNALLY_VISIBLE;206,7268
-# define eassert(208,7319
-# define eassume(212,7450
-enum Lisp_Bits239,8519
-#define GCALIGNMENT 243,8647
- VALBITS 246,8742
- INTTYPEBITS 249,8838
- FIXNUM_BITS 252,8945
-#define VAL_MAX 263,9327
-#define USE_LSB_TAG 271,9777
-DEFINE_GDB_SYMBOL_BEGIN USE_LSB_TAG270,9733
-# define alignas(281,10077
-# define GCALIGNED 288,10227
-# define GCALIGNED 290,10292
-# define lisp_h_XLI(327,11642
-# define lisp_h_XIL(328,11673
-# define lisp_h_XLI(330,11724
-# define lisp_h_XIL(331,11751
-#define lisp_h_CHECK_LIST_CONS(333,11785
-#define lisp_h_CHECK_NUMBER(334,11856
-#define lisp_h_CHECK_SYMBOL(335,11927
-#define lisp_h_CHECK_TYPE(336,11996
-#define lisp_h_CONSP(338,12107
-#define lisp_h_EQ(339,12156
-#define lisp_h_FLOATP(340,12201
-#define lisp_h_INTEGERP(341,12252
-#define lisp_h_MARKERP(342,12333
-#define lisp_h_MISCP(343,12408
-#define lisp_h_NILP(344,12457
-#define lisp_h_SET_SYMBOL_VAL(345,12493
-#define lisp_h_SYMBOL_CONSTANT_P(347,12607
-#define lisp_h_SYMBOL_VAL(348,12671
-#define lisp_h_SYMBOLP(350,12772
-#define lisp_h_VECTORLIKEP(351,12825
-#define lisp_h_XCAR(352,12886
-#define lisp_h_XCDR(353,12924
-#define lisp_h_XCONS(354,12964
-#define lisp_h_XHASH(356,13059
-#define lisp_h_XPNTR(357,13093
-# define lisp_h_check_cons_list(360,13221
-# define lisp_h_make_number(363,13289
-# define lisp_h_XFASTINT(365,13392
-# define lisp_h_XINT(366,13429
-# define lisp_h_XSYMBOL(367,13478
-# define lisp_h_XTYPE(371,13631
-# define lisp_h_XUNTAG(372,13696
-# define XLI(381,14086
-# define XIL(382,14117
-# define CHECK_LIST_CONS(383,14148
-# define CHECK_NUMBER(384,14209
-# define CHECK_SYMBOL(385,14258
-# define CHECK_TYPE(386,14307
-# define CONSP(387,14382
-# define EQ(388,14417
-# define FLOATP(389,14452
-# define INTEGERP(390,14489
-# define MARKERP(391,14530
-# define MISCP(392,14569
-# define NILP(393,14604
-# define SET_SYMBOL_VAL(394,14637
-# define SYMBOL_CONSTANT_P(395,14700
-# define SYMBOL_VAL(396,14763
-# define SYMBOLP(397,14812
-# define VECTORLIKEP(398,14851
-# define XCAR(399,14898
-# define XCDR(400,14931
-# define XCONS(401,14964
-# define XHASH(402,14999
-# define XPNTR(403,15034
-# define check_cons_list(405,15097
-# define make_number(408,15176
-# define XFASTINT(409,15224
-# define XINT(410,15266
-# define XSYMBOL(411,15300
-# define XTYPE(412,15340
-# define XUNTAG(413,15376
-#define LISP_MACRO_DEFUN(421,15672
-#define LISP_MACRO_DEFUN_VOID(425,15845
-#define INTMASK 437,16289
-#define case_Lisp_Int 438,16342
-#define ENUM_BF(445,16681
-#define ENUM_BF(447,16722
-enum Lisp_Type451,16763
- Lisp_Symbol 454,16851
- Lisp_Misc 458,16993
- Lisp_Int0 461,17067
- Lisp_Int1 462,17086
- Lisp_String 466,17264
- Lisp_Vectorlike 472,17543
- Lisp_Cons 475,17632
- Lisp_Float 477,17670
-enum Lisp_Misc_Type485,18016
- Lisp_Misc_Free 487,18040
- Lisp_Misc_Marker,488,18069
- Lisp_Misc_Overlay,489,18091
- Lisp_Misc_Save_Value,490,18114
- Lisp_Misc_Finalizer,491,18140
- Lisp_Misc_Float,494,18275
- Lisp_Misc_Limit496,18359
-enum Lisp_Fwd_Type502,18543
- Lisp_Fwd_Int,504,18566
- Lisp_Fwd_Bool,505,18619
- Lisp_Fwd_Obj,506,18670
- Lisp_Fwd_Buffer_Obj,507,18729
- Lisp_Fwd_Kboard_Obj 508,18800
-typedef struct { EMACS_INT i;567,21781
-typedef struct { EMACS_INT i; } Lisp_Object;567,21781
-#define LISP_INITIALLY(569,21827
-#undef CHECK_LISP_OBJECT_TYPE571,21858
-enum CHECK_LISP_OBJECT_TYPE 572,21888
-enum CHECK_LISP_OBJECT_TYPE { CHECK_LISP_OBJECT_TYPE 572,21888
-typedef EMACS_INT Lisp_Object;577,22064
-#define LISP_INITIALLY(578,22095
-enum CHECK_LISP_OBJECT_TYPE 579,22125
-enum CHECK_LISP_OBJECT_TYPE { CHECK_LISP_OBJECT_TYPE 579,22125
-#define LISP_INITIALLY_ZERO 582,22226
-INLINE bool BOOL_VECTOR_P 588,22350
-INLINE bool BUFFER_OBJFWDP 589,22391
-INLINE bool BUFFERP 590,22438
-INLINE bool CHAR_TABLE_P 591,22473
-INLINE Lisp_Object CHAR_TABLE_REF_ASCII 592,22513
-INLINE bool 593,22579
-INLINE bool 594,22614
-INLINE bool functionp 595,22650
-INLINE bool 596,22687
-INLINE bool 597,22725
-INLINE bool 598,22762
-INLINE bool 599,22797
-INLINE bool OVERLAYP 600,22831
-INLINE bool PROCESSP 601,22867
-INLINE bool PSEUDOVECTORP 602,22903
-INLINE bool SAVE_VALUEP 603,22949
-INLINE bool FINALIZERP 604,22988
-INLINE void set_sub_char_table_contents 605,23026
-INLINE bool STRINGP 607,23116
-INLINE bool SUB_CHAR_TABLE_P 608,23151
-INLINE bool SUBRP 609,23195
-INLINE bool 610,23228
-INLINE bool 611,23265
-INLINE bool WINDOWP 612,23306
-INLINE bool TERMINALP 613,23341
-INLINE struct Lisp_Save_Value *XSAVE_VALUE XSAVE_VALUE614,23378
-INLINE struct Lisp_Finalizer *XFINALIZER XFINALIZER615,23436
-INLINE struct Lisp_Symbol *(XSYMBOL)616,23492
-INLINE void 617,23544
-extern Lisp_Object char_table_ref 620,23616
-extern void char_table_set 621,23670
-extern _Noreturn Lisp_Object wrong_type_argument 624,23757
-extern _Noreturn void wrong_choice 625,23834
-extern bool might_dump;628,23925
-extern bool initialized;631,24061
-extern double extract_float 634,24117
-enum symbol_interned639,24199
- SYMBOL_UNINTERNED 641,24222
- SYMBOL_INTERNED 642,24247
- SYMBOL_INTERNED_IN_INITIAL_OBARRAY 643,24270
-enum symbol_redirect646,24315
- SYMBOL_PLAINVAL 648,24338
- SYMBOL_VARALIAS 649,24362
- SYMBOL_LOCALIZED 650,24386
- SYMBOL_FORWARDED 651,24410
-struct Lisp_Symbol654,24437
- bool_bf gcmarkbit 656,24458
- ENUM_BF (symbol_redirect) redirect 663,24793
- unsigned constant 668,25011
- unsigned interned 672,25131
- bool_bf declared_special 676,25293
- bool_bf pinned 679,25394
- Lisp_Object name;682,25463
- Lisp_Object value;687,25631
- struct Lisp_Symbol *alias;alias688,25654
- struct Lisp_Buffer_Local_Value *blv;blv689,25685
- union Lisp_Fwd *fwd;fwd690,25726
- } val;691,25751
- Lisp_Object function;694,25823
- Lisp_Object plist;697,25885
- struct Lisp_Symbol *next;next700,25974
-#define EXFUN(707,26252
-#define DEFUN_ARGS_MANY 712,26446
-#define DEFUN_ARGS_UNEVALLED 713,26498
-#define DEFUN_ARGS_0 714,26541
-#define DEFUN_ARGS_1 715,26569
-#define DEFUN_ARGS_2 716,26604
-#define DEFUN_ARGS_3 717,26652
-#define DEFUN_ARGS_4 718,26713
-#define DEFUN_ARGS_5 719,26787
-#define DEFUN_ARGS_6 721,26880
-#define DEFUN_ARGS_7 723,26986
-#define DEFUN_ARGS_8 725,27105
-#define TAG_PTR(729,27296
-#define TAG_SYMOFFSET(734,27543
-#define XLI_BUILTIN_LISPSYM(741,27842
-#define DEFINE_LISP_SYMBOL(746,28101
-# define DEFINE_NON_NIL_Q_SYMBOL_MACROS 755,28572
-LISP_MACRO_DEFUN 762,28777
-# define ARRAY_MARK_FLAG 768,29024
-# define PSEUDOVECTOR_FLAG 774,29267
-enum pvec_type780,29568
- PVEC_NORMAL_VECTOR,782,29585
- PVEC_FREE,783,29607
- PVEC_PROCESS,784,29620
- PVEC_FRAME,785,29636
- PVEC_WINDOW,786,29650
- PVEC_BOOL_VECTOR,787,29665
- PVEC_BUFFER,788,29685
- PVEC_HASH_TABLE,789,29700
- PVEC_TERMINAL,790,29719
- PVEC_WINDOW_CONFIGURATION,791,29736
- PVEC_SUBR,792,29765
- PVEC_OTHER,793,29778
- PVEC_COMPILED,795,29856
- PVEC_CHAR_TABLE,796,29873
- PVEC_SUB_CHAR_TABLE,797,29892
- PVEC_FONT 798,29915
-enum More_Lisp_Bits801,29991
- PSEUDOVECTOR_SIZE_BITS 808,30382
- PSEUDOVECTOR_SIZE_MASK 809,30415
- PSEUDOVECTOR_REST_BITS 813,30625
- PSEUDOVECTOR_REST_MASK 814,30658
- PSEUDOVECTOR_AREA_BITS 818,30823
- PVEC_TYPE_MASK 819,30901
-# define VALMASK 829,31302
-DEFINE_GDB_SYMBOL_BEGIN VALMASK828,31257
-#define MOST_POSITIVE_FIXNUM 834,31532
-#define MOST_NEGATIVE_FIXNUM 835,31592
-XINT 874,32684
-XFASTINT 889,33035
-XSYMBOL 899,33263
-XTYPE 910,33481
-XUNTAG 918,33661
-LISP_MACRO_DEFUN 927,33857
-LISP_MACRO_DEFUN 940,34242
-#define FIXNUM_OVERFLOW_P(958,34855
-LISP_MACRO_DEFUN FIXNUM_OVERFLOW_P952,34632
-LISP_MACRO_DEFUN 970,35171
-XSTRING 980,35391
-#define SYMBOL_INDEX(988,35575
-XFLOAT 991,35636
-XPROCESS 1000,35778
-XWINDOW 1007,35895
-XTERMINAL 1014,36012
-XSUBR 1021,36134
-XBUFFER 1028,36245
-XCHAR_TABLE 1035,36369
-XSUB_CHAR_TABLE 1042,36506
-XBOOL_VECTOR 1049,36648
-make_lisp_ptr 1058,36827
-make_lisp_symbol 1066,37013
-builtin_lisp_symbol 1074,37197
-#define XSETINT(1079,37279
-#define XSETFASTINT(1080,37325
-#define XSETCONS(1081,37375
-#define XSETVECTOR(1082,37435
-#define XSETSTRING(1083,37503
-#define XSETSYMBOL(1084,37567
-#define XSETFLOAT(1085,37621
-#define XSETMISC(1086,37683
-#define XSETPVECTYPE(1090,37772
-#define XSETPVECTYPESIZE(1092,37888
-#define XSETPSEUDOVECTOR(1099,38185
-#define XSETTYPED_PSEUDOVECTOR(1105,38369
-#define XSETWINDOW_CONFIGURATION(1110,38579
-#define XSETPROCESS(1112,38675
-#define XSETWINDOW(1113,38741
-#define XSETTERMINAL(1114,38805
-#define XSETSUBR(1115,38873
-#define XSETCOMPILED(1116,38933
-#define XSETBUFFER(1117,39001
-#define XSETCHAR_TABLE(1118,39065
-#define XSETBOOL_VECTOR(1119,39137
-#define XSETSUB_CHAR_TABLE(1120,39211
-XINTPTR 1128,39581
-make_pointer_integer 1134,39661
-LISP_MACRO_DEFUN_VOID 1143,39826
-typedef struct interval *INTERVAL;INTERVAL1149,39987
- Lisp_Object cdr;1159,40162
- struct Lisp_Cons *chain;chain1162,40236
-xcar_addr 1174,40760
-xcdr_addr 1179,40837
-LISP_MACRO_DEFUN 1185,40931
-XSETCDR 1198,41307
-CAR 1205,41457
-CDR 1212,41591
-CAR_SAFE 1221,41791
-CDR_SAFE 1226,41877
-STRING_MULTIBYTE 1243,42250
-#define STRING_BYTES_BOUND 1261,43057
-#define STRING_SET_UNIBYTE(1265,43201
-#define STRING_SET_MULTIBYTE(1275,43516
-SDATA 1286,43830
-SSDATA 1291,43908
-SREF 1297,44037
-SSET 1302,44128
-SCHARS 1307,44242
-extern ptrdiff_t string_bytes 1313,44337
-STRING_BYTES 1316,44415
-SBYTES 1326,44595
-STRING_SET_CHARS 1331,44681
-struct vectorlike_header1343,45232
- ptrdiff_t size;1364,46383
-struct Lisp_Vector1369,46482
- struct vectorlike_header header;1371,46505
- Lisp_Object contents[contents1372,46542
- ALIGNOF_STRUCT_LISP_VECTOR1378,46681
-struct Lisp_Bool_Vector1384,46864
- struct vectorlike_header header;1388,47012
- EMACS_INT size;1390,47086
- bits_word data[data1395,47319
-bool_vector_size 1399,47385
-bool_vector_data 1407,47523
-bool_vector_uchar_data 1413,47617
-bool_vector_words 1421,47803
-bool_vector_bytes 1428,47998
-bool_vector_bitref 1437,48238
-bool_vector_ref 1445,48478
-bool_vector_set 1453,48618
- header_size 1471,49047
- bool_header_size 1472,49106
- word_size 1473,49171
-AREF 1479,49284
-aref_addr 1485,49391
-ASIZE 1491,49501
-ASET 1497,49583
-gc_aset 1504,49742
-enum { NIL_IS_ZERO 1515,50269
-memclear 1520,50464
-#define VECSIZE(1531,50762
-#define PSEUDOVECSIZE(1538,51047
-#define UNSIGNED_CMP(1546,51480
-#define ASCII_CHAR_P(1552,51734
-enum CHARTAB_SIZE_BITS1565,52489
- CHARTAB_SIZE_BITS_0 1567,52516
- CHARTAB_SIZE_BITS_1 1568,52545
- CHARTAB_SIZE_BITS_2 1569,52574
- CHARTAB_SIZE_BITS_3 1570,52603
-extern const int chartab_size[chartab_size1573,52637
-struct Lisp_Char_Table1575,52672
- struct vectorlike_header header;1581,52928
- Lisp_Object defalt;1585,53078
- Lisp_Object parent;1590,53280
- Lisp_Object purpose;1594,53398
- Lisp_Object ascii;1598,53564
- Lisp_Object contents[contents1600,53588
- Lisp_Object extras[extras1603,53699
-struct Lisp_Sub_Char_Table1606,53752
- struct vectorlike_header header;1610,53918
- int depth;1618,54341
- int min_char;1621,54417
- Lisp_Object contents[contents1624,54492
-CHAR_TABLE_REF_ASCII 1628,54566
-CHAR_TABLE_REF 1648,55113
-CHAR_TABLE_SET 1658,55402
-struct Lisp_Subr1670,55786
- struct vectorlike_header header;1672,55807
- Lisp_Object (*a0)a01674,55856
- Lisp_Object (*a1)a11675,55888
- Lisp_Object (*a2)a21676,55927
- Lisp_Object (*a3)a31677,55979
- Lisp_Object (*a4)a41678,56044
- Lisp_Object (*a5)a51679,56122
- Lisp_Object (*a6)a61680,56213
- Lisp_Object (*a7)a71681,56317
- Lisp_Object (*a8)a81682,56434
- Lisp_Object (*aUNEVALLED)aUNEVALLED1683,56564
- Lisp_Object (*aMANY)aMANY1684,56616
- } function;1685,56671
- short min_args,1686,56687
- short min_args, max_args;1686,56687
- const char *symbol_name;symbol_name1687,56717
- const char *intspec;intspec1688,56746
- const char *doc;doc1689,56771
-enum char_table_specials1692,56798
- CHAR_TABLE_STANDARD_SLOTS 1697,56993
- SUB_CHAR_TABLE_OFFSET 1701,57214
-CHAR_TABLE_EXTRA_SLOTS 1707,57377
-verify 1714,57596
-LISP_MACRO_DEFUN 1723,57921
-SYMBOL_BLV 1732,58181
-SYMBOL_FWD 1738,58316
-LISP_MACRO_DEFUN_VOID 1744,58428
-SET_SYMBOL_BLV 1754,58691
-SET_SYMBOL_FWD 1760,58850
-SYMBOL_NAME 1767,59001
-SYMBOL_INTERNED_P 1775,59130
-SYMBOL_INTERNED_IN_INITIAL_OBARRAY_P 1783,59299
-#define DEFSYM(1796,59809
-LISP_MACRO_DEFUN DEFSYM1792,59630
-struct hash_table_test1805,60062
- Lisp_Object name;1808,60139
- Lisp_Object user_hash_function;1811,60206
- Lisp_Object user_cmp_function;1814,60297
- bool (*cmpfn)cmpfn1817,60372
- EMACS_UINT (*hashfn)hashfn1820,60486
-struct Lisp_Hash_Table1823,60555
- struct vectorlike_header header;1826,60649
- Lisp_Object weak;1830,60783
- Lisp_Object rehash_size;1835,61007
- Lisp_Object rehash_threshold;1839,61129
- Lisp_Object hash;1843,61260
- Lisp_Object next;1848,61490
- Lisp_Object next_free;1851,61560
- Lisp_Object index;1856,61771
- ptrdiff_t count;1863,62041
- Lisp_Object key_and_value;1868,62240
- struct hash_table_test test;1871,62314
- struct Lisp_Hash_Table *next_weak;next_weak1875,62457
-XHASH_TABLE 1880,62531
-#define XSET_HASH_TABLE(1885,62602
-HASH_TABLE_P 1889,62703
-HASH_KEY 1896,62860
-HASH_VALUE 1903,63040
-HASH_NEXT 1911,63254
-HASH_HASH 1918,63431
-HASH_INDEX 1926,63677
-HASH_TABLE_SIZE 1933,63826
-enum DEFAULT_HASH_SIZE 1940,63956
-enum DEFAULT_HASH_SIZE { DEFAULT_HASH_SIZE 1940,63956
-static double const DEFAULT_REHASH_THRESHOLD 1946,64176
-static double const DEFAULT_REHASH_SIZE 1950,64299
-sxhash_combine 1956,64465
-SXHASH_REDUCE 1964,64648
-struct Lisp_Misc_Any 1971,64806
- ENUM_BF (Lisp_Misc_Type) type 1973,64866
- bool_bf gcmarkbit 1974,64927
- unsigned spacer 1975,64952
-struct Lisp_Marker1978,64980
- ENUM_BF (Lisp_Misc_Type) type 1980,65001
- bool_bf gcmarkbit 1981,65065
- unsigned spacer 1982,65090
- bool_bf need_adjustment 1986,65282
- bool_bf insertion_type 1989,65423
- struct buffer *buffer;buffer2000,66016
- struct Lisp_Marker *next;next2009,66367
- ptrdiff_t charpos;2011,66455
- ptrdiff_t bytepos;2016,66713
-struct Lisp_Overlay2021,66841
- ENUM_BF (Lisp_Misc_Type) type 2034,67349
- bool_bf gcmarkbit 2035,67415
- unsigned spacer 2036,67442
- struct Lisp_Overlay *next;next2037,67468
- Lisp_Object start;2038,67499
- Lisp_Object end;2039,67522
- Lisp_Object plist;2040,67543
- SAVE_UNUSED,2047,67644
- SAVE_INTEGER,2048,67661
- SAVE_FUNCPOINTER,2049,67679
- SAVE_POINTER,2050,67701
- SAVE_OBJECT2051,67719
-enum { SAVE_SLOT_BITS 2055,67804
-enum { SAVE_VALUE_SLOTS 2058,67901
-enum { SAVE_TYPE_BITS 2062,68009
-enum Lisp_Save_Type2064,68075
- SAVE_TYPE_INT_INT 2066,68099
- SAVE_TYPE_INT_INT_INT2067,68172
- SAVE_TYPE_OBJ_OBJ 2069,68262
- SAVE_TYPE_OBJ_OBJ_OBJ 2070,68333
- SAVE_TYPE_OBJ_OBJ_OBJ_OBJ2071,68414
- SAVE_TYPE_PTR_INT 2073,68509
- SAVE_TYPE_PTR_OBJ 2074,68582
- SAVE_TYPE_PTR_PTR 2075,68654
- SAVE_TYPE_FUNCPTR_PTR_OBJ2076,68727
- SAVE_TYPE_MEMORY 2080,68885
-typedef void (*voidfuncptr)voidfuncptr2108,69839
-struct Lisp_Save_Value2110,69876
- ENUM_BF (Lisp_Misc_Type) type 2112,69903
- bool_bf gcmarkbit 2113,69972
- unsigned spacer : 32 - (16 + 1 + SAVE_TYPE_BITS)2114,69999
- ENUM_BF (Lisp_Save_Type) save_type : SAVE_TYPE_BITS;2123,70489
- void *pointer;pointer2125,70558
- voidfuncptr funcpointer;2126,70579
- ptrdiff_t integer;2127,70610
- Lisp_Object object;2128,70635
- } data[data2129,70661
-save_type 2134,70755
-XSAVE_POINTER 2143,70985
-set_save_pointer 2149,71147
-XSAVE_FUNCPOINTER 2155,71329
-XSAVE_INTEGER 2164,71549
-set_save_integer 2170,71711
-XSAVE_OBJECT 2179,71932
-struct Lisp_Finalizer2186,72109
- struct Lisp_Misc_Any base;2188,72135
- struct Lisp_Finalizer *prev;prev2191,72223
- struct Lisp_Finalizer *next;next2192,72256
- Lisp_Object function;2197,72493
-struct Lisp_Free2201,72584
- ENUM_BF (Lisp_Misc_Type) type 2203,72605
- bool_bf gcmarkbit 2204,72668
- unsigned spacer 2205,72695
- union Lisp_Misc *chain;chain2206,72721
-union Lisp_Misc2212,72885
- struct Lisp_Misc_Any u_any;2214,72905
- struct Lisp_Free u_free;2215,72976
- struct Lisp_Marker u_marker;2216,73005
- struct Lisp_Overlay u_overlay;2217,73038
- struct Lisp_Save_Value u_save_value;2218,73073
- struct Lisp_Finalizer u_finalizer;2219,73114
-XMISC 2223,73184
-XMISCANY 2229,73273
-XMISCTYPE 2236,73382
-XMARKER 2242,73470
-XOVERLAY 2249,73585
-XSAVE_VALUE 2256,73706
-XFINALIZER 2263,73835
-struct Lisp_Intfwd2274,74120
- enum Lisp_Fwd_Type type;2276,74143
- EMACS_INT *intvar;intvar2277,74193
-struct Lisp_Boolfwd2284,74414
- enum Lisp_Fwd_Type type;2286,74438
- bool *boolvar;boolvar2287,74489
-struct Lisp_Objfwd2294,74705
- enum Lisp_Fwd_Type type;2296,74728
- Lisp_Object *objvar;objvar2297,74778
-struct Lisp_Buffer_Objfwd2302,74937
- enum Lisp_Fwd_Type type;2304,74967
- int offset;2305,75024
- Lisp_Object predicate;2307,75116
-struct Lisp_Buffer_Local_Value2334,76473
- bool_bf local_if_set 2338,76618
- bool_bf frame_local 2341,76800
- bool_bf found 2344,76942
- union Lisp_Fwd *fwd;fwd2346,77044
- Lisp_Object where;2348,77187
- Lisp_Object defcell;2351,77313
- Lisp_Object valcell;2357,77617
-struct Lisp_Kboard_Objfwd2362,77732
- enum Lisp_Fwd_Type type;2364,77762
- int offset;2365,77819
-union Lisp_Fwd2368,77841
- struct Lisp_Intfwd u_intfwd;2370,77860
- struct Lisp_Boolfwd u_boolfwd;2371,77893
- struct Lisp_Objfwd u_objfwd;2372,77928
- struct Lisp_Buffer_Objfwd u_buffer_objfwd;2373,77961
- struct Lisp_Kboard_Objfwd u_kboard_objfwd;2374,78008
-XFWDTYPE 2378,78087
-XBUFFER_OBJFWD 2384,78183
-struct Lisp_Float2391,78319
- double data;2395,78357
- struct Lisp_Float *chain;chain2396,78376
- } u;2397,78408
-XFLOAT_DATA 2401,78437
- IEEE_FLOATING_POINT2415,78946
-#define _UCHAR_T2423,79269
-typedef unsigned char UCHAR;2424,79286
-enum Lisp_Compiled2429,79369
- COMPILED_ARGLIST 2431,79392
- COMPILED_BYTECODE 2432,79418
- COMPILED_CONSTANTS 2433,79445
- COMPILED_STACK_DEPTH 2434,79473
- COMPILED_DOC_STRING 2435,79503
- COMPILED_INTERACTIVE 2436,79532
-enum char_bits2443,79834
- CHAR_ALT 2445,79853
- CHAR_SUPER 2446,79879
- CHAR_HYPER 2447,79907
- CHAR_SHIFT 2448,79935
- CHAR_CTL 2449,79963
- CHAR_META 2450,79989
- CHAR_MODIFIER_MASK 2452,80017
- CHARACTERBITS 2457,80212
-LISP_MACRO_DEFUN 2462,80270
-NATNUMP 2470,80412
-RANGED_INTEGERP 2476,80493
-#define TYPE_RANGED_INTEGERP(2481,80615
-LISP_MACRO_DEFUN 2486,80800
-VECTORP 2500,81273
-OVERLAYP 2505,81376
-SAVE_VALUEP 2510,81475
-FINALIZERP 2516,81581
-AUTOLOADP 2522,81685
-BUFFER_OBJFWDP 2528,81776
-PSEUDOVECTOR_TYPEP 2534,81874
-PSEUDOVECTORP 2542,82127
-WINDOW_CONFIGURATIONP 2558,82479
-PROCESSP 2564,82589
-WINDOWP 2570,82673
-TERMINALP 2576,82755
-SUBRP 2582,82841
-COMPILEDP 2588,82919
-BUFFERP 2594,83005
-CHAR_TABLE_P 2600,83087
-SUB_CHAR_TABLE_P 2606,83178
-BOOL_VECTOR_P 2612,83277
-FRAMEP 2618,83370
-IMAGEP 2625,83487
-ARRAYP 2632,83592
-CHECK_LIST 2638,83711
-LISP_MACRO_DEFUN_VOID 2643,83792
-CHECK_STRING_CAR 2653,84089
-CHECK_CONS 2658,84193
-CHECK_VECTOR 2663,84273
-CHECK_BOOL_VECTOR 2668,84359
-CHECK_VECTOR_OR_STRING 2674,84536
-CHECK_ARRAY 2683,84710
-CHECK_BUFFER 2688,84818
-CHECK_WINDOW 2693,84904
-CHECK_PROCESS 2699,85010
-CHECK_NATNUM 2705,85106
-#define CHECK_RANGED_INTEGER(2710,85183
-#define CHECK_TYPE_RANGED_INTEGER(2721,85566
-#define CHECK_NUMBER_COERCE_MARKER(2729,85836
-XFLOATINT 2738,86089
-CHECK_NUMBER_OR_FLOAT 2744,86160
-#define CHECK_NUMBER_OR_FLOAT_COERCE_MARKER(2749,86259
-CHECK_NUMBER_CAR 2760,86669
-CHECK_NUMBER_CDR 2768,86791
-#define DEFUN(2803,88386
-#define DEFUN(2812,88854
-FUNCTIONP 2822,89209
-extern void defsubr 2829,89361
-enum maxargs2831,89404
- MANY 2833,89421
- UNEVALLED 2834,89436
-#define CALLMANY(2838,89539
-#define CALLN(2844,89892
-extern void defvar_lisp 2846,89962
-extern void defvar_lisp_nopro 2847,90039
-extern void defvar_bool 2848,90122
-extern void defvar_int 2849,90193
-extern void defvar_kboard 2850,90267
-#define DEFVAR_LISP(2869,91097
-#define DEFVAR_LISP_NOPRO(2874,91269
-#define DEFVAR_BOOL(2879,91451
-#define DEFVAR_INT(2884,91624
-#define DEFVAR_BUFFER_DEFAULTS(2890,91795
-#define DEFVAR_KBOARD(2896,91999
-typedef jmp_buf sys_jmp_buf;2906,92323
-# define sys_setjmp(2907,92352
-# define sys_longjmp(2908,92387
-typedef sigjmp_buf sys_jmp_buf;2910,92459
-# define sys_setjmp(2911,92491
-# define sys_longjmp(2912,92531
-typedef jmp_buf sys_jmp_buf;2916,92690
-# define sys_setjmp(2917,92719
-# define sys_longjmp(2918,92753
-enum specbind_tag 2943,93805
- SPECPDL_UNWIND,2944,93825
- SPECPDL_UNWIND_PTR,2945,93894
- SPECPDL_UNWIND_INT,2946,93945
- SPECPDL_UNWIND_VOID,2947,93993
- SPECPDL_BACKTRACE,2948,94047
- SPECPDL_LET,2949,94105
- SPECPDL_LET_LOCAL,2951,94235
- SPECPDL_LET_DEFAULT 2952,94292
-union specbinding2955,94364
- ENUM_BF (specbind_tag) kind : CHAR_BIT;2957,94386
- ENUM_BF (specbind_tag) kind : CHAR_BIT;2959,94443
- void (*func)func2960,94489
- Lisp_Object arg;2961,94523
- } unwind;2962,94546
- ENUM_BF (specbind_tag) kind : CHAR_BIT;2964,94573
- void (*func)func2965,94619
- void *arg;arg2966,94648
- } unwind_ptr;2967,94665
- ENUM_BF (specbind_tag) kind : CHAR_BIT;2969,94696
- void (*func)func2970,94742
- int arg;2971,94768
- } unwind_int;2972,94783
- ENUM_BF (specbind_tag) kind : CHAR_BIT;2974,94814
- void (*func)func2975,94860
- } unwind_void;2976,94887
- ENUM_BF (specbind_tag) kind : CHAR_BIT;2978,94919
- Lisp_Object symbol,2980,95026
- Lisp_Object symbol, old_value,2980,95026
- Lisp_Object symbol, old_value, where;2980,95026
- } let;2981,95070
- ENUM_BF (specbind_tag) kind : CHAR_BIT;2983,95094
- bool_bf debug_on_exit 2984,95140
- Lisp_Object function;2985,95173
- Lisp_Object *args;args2986,95201
- ptrdiff_t nargs;2987,95226
- } bt;2988,95249
-extern union specbinding *specpdl;specpdl2991,95265
-extern union specbinding *specpdl_ptr;specpdl_ptr2992,95300
-extern ptrdiff_t specpdl_size;2993,95339
-SPECPDL_INDEX 2996,95388
-enum handlertype 3021,96410
-enum handlertype { CATCHER,3021,96410
-enum handlertype { CATCHER, CONDITION_CASE 3021,96410
-struct handler3023,96457
- enum handlertype type;3025,96474
- Lisp_Object tag_or_ch;3026,96499
- Lisp_Object val;3027,96524
- struct handler *next;next3028,96543
- struct handler *nextfree;nextfree3029,96567
- Lisp_Object *bytecode_top;bytecode_top3036,96925
- int bytecode_dest;3037,96954
- struct gcpro *gcpro;gcpro3042,97191
- sys_jmp_buf jmp;3044,97221
- EMACS_INT lisp_eval_depth;3045,97240
- ptrdiff_t pdlcount;3046,97269
- int poll_suppress_count;3047,97291
- int interrupt_input_blocked;3048,97318
- struct byte_stack *byte_stack;byte_stack3049,97349
-#define PUSH_HANDLER(3053,97446
-extern Lisp_Object memory_signal_data;3075,98152
-extern char *stack_bottom;stack_bottom3079,98285
-extern void process_pending_signals 3097,99102
-extern bool volatile pending_signals;3098,99146
-extern void process_quit_flag 3100,99185
-#define QUIT 3101,99223
-#define QUITP 3112,99473
-extern Lisp_Object Vascii_downcase_table;3114,99534
-extern Lisp_Object Vascii_canon_table;3115,99576
-extern struct gcpro *gcprolist;gcprolist3130,100283
-struct gcpro3132,100316
- struct gcpro *next;next3134,100331
- volatile Lisp_Object *var;var3137,100400
- ptrdiff_t nvars;3140,100482
- const char *name;name3144,100567
- int lineno;3147,100623
- int idx;3150,100684
- int level;3153,100720
-#define GC_USE_GCPROS_AS_BEFORE 3171,101297
-#define GC_MAKE_GCPROS_NOOPS 3172,101332
-#define GC_MARK_STACK_CHECK_GCPROS 3173,101364
-#define GC_USE_GCPROS_CHECK_ZOMBIES 3174,101401
-#define GC_MARK_STACK 3177,101462
-#define BYTE_MARK_STACK 3181,101562
-#define GCPRO1(3190,101833
-#define GCPRO2(3191,101873
-#define GCPRO3(3192,101939
-#define GCPRO4(3194,102034
-#define GCPRO5(3196,102154
-#define GCPRO6(3198,102299
-#define GCPRO7(3201,102474
-#define UNGCPRO 3202,102553
-#define GCPRO1(3208,102653
-#define GCPRO2(3212,102775
-#define GCPRO3(3217,102967
-#define GCPRO4(3223,103229
-#define GCPRO5(3230,103560
-#define GCPRO6(3238,103961
-#define GCPRO7(3247,104431
-#define UNGCPRO 3257,104971
-extern int gcpro_level;3261,105040
-#define GCPRO1(3263,105065
-#define GCPRO2(3269,105299
-#define GCPRO3(3278,105717
-#define GCPRO4(3289,106274
-#define GCPRO5(3302,106972
-#define GCPRO6(3317,107812
-#define GCPRO7(3334,108793
-#define UNGCPRO 3353,109916
-#define RETURN_UNGCPRO(3363,110183
-void staticpro 3375,110456
-vcopy 3384,110657
-set_hash_key_slot 3393,110932
-set_hash_value_slot 3399,111071
-set_symbol_function 3408,111306
-set_symbol_plist 3414,111421
-set_symbol_next 3420,111524
-blv_found 3428,111697
-set_overlay_plist 3437,111880
-string_intervals 3445,112031
-set_string_intervals 3453,112153
-set_char_table_defalt 3462,112355
-set_char_table_purpose 3467,112467
-set_char_table_extras 3475,112636
-set_char_table_contents 3482,112845
-set_sub_char_table_contents 3489,113040
-extern Lisp_Object indirect_function 3495,113199
-extern Lisp_Object find_symbol_value 3496,113251
-enum Arith_Comparison 3497,113303
- ARITH_EQUAL,3498,113327
- ARITH_NOTEQUAL,3499,113342
- ARITH_LESS,3500,113360
- ARITH_GRTR,3501,113374
- ARITH_LESS_OR_EQUAL,3502,113388
- ARITH_GRTR_OR_EQUAL3503,113411
-extern Lisp_Object arithcompare 3505,113436
-#define INTEGER_TO_CONS(3511,113762
-#define CONS_TO_INTEGER(3529,114625
-extern intmax_t cons_to_signed 3533,114840
-extern uintmax_t cons_to_unsigned 3534,114906
-extern struct Lisp_Symbol *indirect_variable indirect_variable3536,114967
-extern _Noreturn void args_out_of_range 3537,115036
-extern _Noreturn void args_out_of_range_3 3538,115104
-extern Lisp_Object do_symval_forwarding 3540,115195
-extern void set_internal 3541,115255
-extern void syms_of_data 3542,115327
-extern void swap_in_global_binding 3543,115360
-extern void syms_of_cmds 3546,115444
-extern void keys_of_cmds 3547,115477
-extern Lisp_Object detect_coding_system 3550,115539
-extern void init_coding 3552,115692
-extern void init_coding_once 3553,115724
-extern void syms_of_coding 3554,115761
-extern ptrdiff_t chars_in_text 3557,115828
-extern ptrdiff_t multibyte_chars_in_text 3558,115895
-extern void syms_of_character 3559,115972
-extern void init_charset 3562,116040
-extern void init_charset_once 3563,116073
-extern void syms_of_charset 3564,116111
-extern void init_syntax_once 3569,116231
-extern void syms_of_syntax 3570,116268
-enum { NEXT_ALMOST_PRIME_LIMIT 3573,116329
-extern EMACS_INT next_almost_prime 3574,116368
-enum constype 3739,123820
-enum constype {CONSTYPE_HEAP,CONSTYPE_HEAP3739,123820
-enum constype {CONSTYPE_HEAP, CONSTYPE_PURE}CONSTYPE_PURE3739,123820
-extern Lisp_Object listn 3740,123866
-list2i 3745,124010
-list3i 3751,124119
-list4i 3757,124258
-extern Lisp_Object make_uninit_bool_vector 3763,124410
-extern Lisp_Object bool_vector_fill 3764,124466
-extern _Noreturn void string_overflow 3765,124530
-extern Lisp_Object make_string 3766,124576
-extern Lisp_Object make_formatted_string 3767,124634
-extern Lisp_Object make_multibyte_string 3779,124988
-extern Lisp_Object make_event_array 3780,125067
-extern Lisp_Object make_uninit_string 3781,125131
-extern Lisp_Object make_uninit_multibyte_string 3782,125182
-extern Lisp_Object make_string_from_bytes 3783,125254
-extern Lisp_Object make_specified_string 3784,125334
-extern Lisp_Object make_pure_string 3786,125426
-extern Lisp_Object make_pure_c_string 3787,125506
-build_pure_c_string 3792,125662
-build_string 3801,125867
-extern Lisp_Object pure_cons 3806,125945
-extern void make_byte_code 3807,126002
-extern struct Lisp_Vector *allocate_vector allocate_vector3808,126053
-make_uninit_vector 3820,126438
-make_uninit_sub_char_table 3833,126657
-extern struct Lisp_Vector *allocate_pseudovector allocate_pseudovector3844,126966
-#define ALLOCATE_PSEUDOVECTOR(3850,127201
-#define ALLOCATE_ZEROED_PSEUDOVECTOR(3858,127537
-extern bool gc_in_progress;3863,127738
-extern bool abort_on_gc;3864,127766
-extern Lisp_Object make_float 3865,127791
-extern void display_malloc_warning 3866,127831
-extern ptrdiff_t inhibit_garbage_collection 3867,127874
-extern Lisp_Object make_save_int_int_int 3868,127926
-extern Lisp_Object make_save_obj_obj_obj_obj 3869,128002
-extern Lisp_Object make_save_ptr 3871,128112
-extern Lisp_Object make_save_ptr_int 3872,128155
-extern Lisp_Object make_save_ptr_ptr 3873,128213
-extern Lisp_Object make_save_funcptr_ptr_obj 3874,128268
-extern Lisp_Object make_save_memory 3876,128364
-extern void free_save_value 3877,128428
-extern Lisp_Object build_overlay 3878,128471
-extern void free_marker 3879,128545
-extern void free_cons 3880,128584
-extern void init_alloc_once 3881,128628
-extern void init_alloc 3882,128664
-extern void syms_of_alloc 3883,128695
-extern struct buffer * allocate_buffer 3884,128729
-extern int valid_lisp_object_p 3885,128776
-extern int relocatable_string_data_p 3886,128822
-extern void check_cons_list 3888,128901
-INLINE void 3890,128943
-extern void *r_alloc r_alloc3895,129064
-#define FLOAT_TO_STRING_BUFSIZE 3927,130527
-extern int openp 3957,131676
-extern Lisp_Object string_to_number 3959,131786
-extern void map_obarray 3960,131849
-extern void dir_warning 3962,131963
-extern void init_obarray 3963,132016
-extern void init_lread 3964,132049
-extern void syms_of_lread 3965,132080
-intern 3968,132134
-intern_c_string 3974,132222
-extern EMACS_INT lisp_eval_depth;3980,132335
-extern Lisp_Object Vautoload_queue;3981,132369
-extern Lisp_Object Vrun_hooks;3982,132405
-extern Lisp_Object Vsignaling_function;3983,132436
-extern Lisp_Object inhibit_lisp_code;3984,132476
-extern struct handler *handlerlist;handlerlist3985,132514
-extern void run_hook 3994,132756
-extern void run_hook_with_args_2 3995,132792
-extern Lisp_Object run_hook_with_args 3996,132866
-extern _Noreturn void xsignal 3999,133025
-extern _Noreturn void xsignal0 4000,133083
-extern _Noreturn void xsignal1 4001,133129
-extern _Noreturn void xsignal2 4002,133188
-extern _Noreturn void xsignal3 4003,133260
-extern _Noreturn void signal_error 4005,133349
-extern Lisp_Object eval_sub 4006,133413
-extern Lisp_Object apply1 4007,133461
-extern Lisp_Object call0 4008,133515
-extern Lisp_Object call1 4009,133555
-extern Lisp_Object call2 4010,133608
-extern Lisp_Object call3 4011,133674
-extern Lisp_Object call4 4012,133753
-extern Lisp_Object call5 4013,133845
-extern Lisp_Object call6 4014,133950
-extern Lisp_Object call7 4015,134068
-extern Lisp_Object internal_catch 4016,134199
-extern Lisp_Object internal_lisp_condition_case 4017,134292
-extern Lisp_Object internal_condition_case 4018,134381
-extern Lisp_Object internal_condition_case_1 4019,134494
-extern Lisp_Object internal_condition_case_2 4020,134629
-extern Lisp_Object internal_condition_case_n4021,134790
-extern void specbind 4024,134986
-extern void record_unwind_protect 4025,135035
-extern void record_unwind_protect_ptr 4026,135108
-extern void record_unwind_protect_int 4027,135175
-extern void record_unwind_protect_void 4028,135236
-extern void record_unwind_protect_nothing 4029,135294
-extern void clear_unwind_protect 4030,135344
-extern void set_unwind_protect 4031,135390
-extern void set_unwind_protect_ptr 4032,135471
-extern Lisp_Object unbind_to 4033,135546
-extern _Noreturn void error 4034,135601
-fast_string_match_ignore_case 4136,140089
-extern ptrdiff_t fast_c_string_match_ignore_case 4141,140239
-extern ptrdiff_t fast_looking_at 4143,140336
-extern ptrdiff_t find_newline 4145,140475
-extern ptrdiff_t scan_newline 4147,140604
-extern ptrdiff_t scan_newline_from_point 4149,140707
-extern ptrdiff_t find_newline_no_quit 4150,140787
-extern ptrdiff_t find_before_next_newline 4152,140884
-extern void syms_of_search 4154,140982
-extern void clear_regexp_cache 4155,141017
-extern Lisp_Object Vminibuffer_list;4159,141087
-extern Lisp_Object last_minibuf_string;4160,141124
-extern Lisp_Object get_minibuffer 4161,141164
-extern void init_minibuf_once 4162,141211
-extern void syms_of_minibuf 4163,141249
-extern void syms_of_callint 4167,141316
-extern void syms_of_casefiddle 4171,141386
-extern void keys_of_casefiddle 4172,141425
-extern void init_casetab_once 4176,141495
-extern void syms_of_casetab 4177,141533
-extern Lisp_Object echo_message_buffer;4181,141601
-extern struct kboard *echo_kboard;echo_kboard4182,141641
-extern void cancel_echoing 4183,141676
-extern Lisp_Object last_undo_boundary;4184,141711
-extern bool input_pending;4185,141750
-extern sigjmp_buf return_to_command_loop;4187,141813
-extern Lisp_Object menu_bar_items 4189,141862
-extern Lisp_Object tool_bar_items 4190,141911
-extern void discard_mouse_events 4191,141967
-void handle_input_available_signal 4193,142028
-extern Lisp_Object pending_funcalls;4195,142077
-extern bool detect_input_pending 4196,142114
-extern bool detect_input_pending_ignore_squeezables 4197,142155
-extern bool detect_input_pending_run_timers 4198,142215
-extern void safe_run_hooks 4199,142267
-extern void cmd_error_internal 4200,142309
-extern Lisp_Object command_loop_1 4201,142369
-extern Lisp_Object read_menu_command 4202,142411
-extern Lisp_Object recursive_edit_1 4203,142456
-extern void record_auto_save 4204,142500
-extern void force_auto_save_soon 4205,142537
-extern void init_keyboard 4206,142578
-extern void syms_of_keyboard 4207,142612
-extern void keys_of_keyboard 4208,142649
-extern ptrdiff_t current_column 4211,142715
-extern void invalidate_current_column 4212,142755
-extern bool indented_beyond_p 4213,142801
-extern void syms_of_indent 4214,142866
-extern void store_frame_param 4217,142929
-extern void store_in_alist 4218,143003
-extern Lisp_Object do_switch_frame 4219,143073
-extern Lisp_Object get_frame_param 4220,143146
-extern void frames_discard_buffer 4221,143212
-extern void syms_of_frame 4222,143261
-extern char **initial_argv;initial_argv4225,143323
-extern int initial_argc;4226,143351
-extern bool display_arg;4228,143426
-extern Lisp_Object decode_env_path 4230,143458
-extern Lisp_Object empty_unibyte_string,4231,143529
-extern Lisp_Object empty_unibyte_string, empty_multibyte_string;4231,143529
-extern _Noreturn void terminate_due_to_signal 4232,143594
-extern Lisp_Object Vlibrary_cache;4234,143669
-void fixup_locale 4237,143730
-void synchronize_system_messages_locale 4238,143756
-void synchronize_system_time_locale 4239,143804
-INLINE void fixup_locale 4241,143854
-INLINE void synchronize_system_messages_locale 4242,143889
-INLINE void synchronize_system_time_locale 4243,143946
-extern void shut_down_emacs 4245,144006
-extern bool noninteractive;4248,144132
-extern bool no_site_lisp;4251,144224
-extern int daemon_pipe[daemon_pipe4256,144392
-#define IS_DAEMON 4257,144419
-#define DAEMON_RUNNING 4258,144459
-extern void *w32_daemon_event;w32_daemon_event4260,144527
-#define IS_DAEMON 4261,144558
-#define DAEMON_RUNNING 4262,144603
-extern bool fatal_error_in_progress;4266,144724
-extern bool inhibit_window_system;4269,144830
-extern bool running_asynch_code;4271,144923
-extern void kill_buffer_processes 4274,144986
-extern int wait_reading_process_output 4275,145035
-# define WAIT_READING_MAX 4281,145422
-# define WAIT_READING_MAX 4283,145494
-extern void add_timer_wait_descriptor 4286,145558
-extern void add_keyboard_wait_descriptor 4288,145610
-extern void delete_keyboard_wait_descriptor 4289,145658
-extern void add_gpm_wait_descriptor 4291,145725
-extern void delete_gpm_wait_descriptor 4292,145768
-extern void init_process_emacs 4294,145821
-extern void syms_of_process 4295,145860
-extern void setup_process_coding_systems 4296,145896
-extern int child_setup 4302,146016
-extern void init_callproc_1 4303,146084
-extern void init_callproc 4304,146120
-extern void set_initial_environment 4305,146154
-extern void syms_of_callproc 4306,146198
-extern Lisp_Object read_doc_string 4309,146261
-extern Lisp_Object get_doc_string 4310,146311
-extern void syms_of_doc 4311,146372
-extern int read_bytecode_char 4312,146404
-extern void syms_of_bytecode 4315,146473
-extern struct byte_stack *byte_stack_list;byte_stack_list4316,146510
-extern void mark_byte_stack 4318,146573
-extern void unmark_byte_stack 4320,146616
-extern Lisp_Object exec_byte_code 4321,146654
-extern void init_macros 4325,146804
-extern void syms_of_macros 4326,146836
-extern void truncate_undo_list 4329,146898
-extern void record_insert 4330,146948
-extern void record_delete 4331,146998
-extern void record_first_change 4332,147056
-extern void record_change 4333,147096
-extern void record_property_change 4334,147146
-extern void syms_of_undo 4337,147288
-extern void report_interval_modification 4340,147352
-extern void syms_of_menu 4343,147448
-extern void syms_of_xmenu 4346,147509
-extern char *get_current_dir_name get_current_dir_name4356,147711
-extern void stuff_char 4358,147760
-extern void init_foreground_group 4359,147793
-extern void sys_subshell 4360,147835
-extern void sys_suspend 4361,147868
-extern void discard_tty_input 4362,147900
-extern void init_sys_modes 4363,147938
-extern void reset_sys_modes 4364,147994
-extern void init_all_sys_modes 4365,148051
-extern void reset_all_sys_modes 4366,148090
-extern void child_setup_tty 4367,148130
-extern void setup_pty 4368,148165
-extern int set_window_size 4369,148194
-extern EMACS_INT get_random 4370,148238
-extern void seed_random 4371,148274
-extern void init_random 4372,148319
-extern void emacs_backtrace 4373,148351
-extern _Noreturn void emacs_abort 4374,148386
-extern void xputenv 4527,152700
-extern char *egetenv_internal egetenv_internal4529,152737
-egetenv 4532,152809
-extern void init_system_name 4539,153012
-#define eabs(4545,153305
-#define make_fixnum_or_float(4550,153438
-enum MAX_ALLOCA 4556,153689
-enum MAX_ALLOCA { MAX_ALLOCA 4556,153689
-extern void *record_xmalloc record_xmalloc4558,153734
-#define USE_SAFE_ALLOCA 4560,153800
-#define AVAIL_ALLOCA(4564,153933
-#define SAFE_ALLOCA(4568,154044
-#define SAFE_NALLOCA(4576,154385
-#define SAFE_ALLOCA_STRING(4590,154861
-#define SAFE_FREE(4598,155113
-#define SAFE_ALLOCA_LISP(4625,155691
-# define USE_STACK_LISP_OBJECTS 4652,156813
-# undef USE_STACK_LISP_OBJECTS4658,156979
-# define USE_STACK_LISP_OBJECTS 4659,157010
-enum { defined_GC_CHECK_STRING_BYTES 4663,157085
-enum { defined_GC_CHECK_STRING_BYTES 4665,157138
-union Aligned_Cons4670,157272
- struct Lisp_Cons s;4672,157293
- double d;4673,157315
- double d; intmax_t i;4673,157315
- double d; intmax_t i; void *p;p4673,157315
-union Aligned_String4676,157352
- struct Lisp_String s;4678,157375
- double d;4679,157399
- double d; intmax_t i;4679,157399
- double d; intmax_t i; void *p;p4679,157399
- USE_STACK_CONS 4689,157707
- USE_STACK_STRING 4691,157813
-#define STACK_CONS(4699,158150
-#define AUTO_CONS_EXPR(4701,158247
-#define AUTO_CONS(4709,158610
-#define AUTO_LIST1(4710,158681
-#define AUTO_LIST2(4712,158789
-#define AUTO_LIST3(4716,158944
-#define AUTO_LIST4(4720,159119
-extern const char *verify_ascii verify_ascii4730,159456
-# define verify_ascii(4732,159510
-#define AUTO_STRING(4740,159818
-#define FOR_EACH_TAIL(4752,160282
-#define FOR_EACH_ALIST_VALUE(4766,160773
-maybe_gc 4774,161060
-functionp 4784,161299
+#define EMACS_LISP_H22,801
+#define DECLARE_GDB_SYM(47,1422
+# define DEFINE_GDB_SYMBOL_BEGIN(49,1509
+# define DEFINE_GDB_SYMBOL_END(50,1579
+# define DEFINE_GDB_SYMBOL_BEGIN(52,1626
+# define DEFINE_GDB_SYMBOL_END(53,1703
+#undef min57,1791
+#undef max58,1802
+#define max(59,1813
+#define min(60,1855
+#define ARRAYELTS(63,1937
+#define GCTYPEBITS 67,2080
+DEFINE_GDB_SYMBOL_BEGIN GCTYPEBITS66,2038
+# define NONPOINTER_BITS 78,2568
+# define NONPOINTER_BITS 80,2601
+typedef int EMACS_INT;91,3024
+typedef unsigned int EMACS_UINT;92,3047
+# define EMACS_INT_MAX 93,3080
+# define pI 94,3112
+typedef long int EMACS_INT;96,3204
+typedef unsigned long EMACS_UINT;97,3232
+# define EMACS_INT_MAX 98,3266
+# define pI 99,3299
+typedef long long int EMACS_INT;103,3478
+typedef unsigned long long int EMACS_UINT;104,3511
+# define EMACS_INT_MAX 105,3554
+# define pI 106,3588
+enum { BOOL_VECTOR_BITS_PER_CHAR 114,3805
+#define BOOL_VECTOR_BITS_PER_CHAR 115,3841
+typedef size_t bits_word;123,4166
+# define BITS_WORD_MAX 124,4192
+enum { BITS_PER_BITS_WORD 125,4224
+typedef unsigned char bits_word;127,4291
+# define BITS_WORD_MAX 128,4324
+enum { BITS_PER_BITS_WORD 129,4387
+verify 131,4451
+ BITS_PER_CHAR 136,4571
+ BITS_PER_SHORT 137,4606
+ BITS_PER_LONG 138,4658
+ BITS_PER_EMACS_INT 139,4713
+typedef intmax_t printmax_t;148,5090
+typedef uintmax_t uprintmax_t;149,5119
+# define pMd 150,5150
+# define pMu 151,5171
+typedef EMACS_INT printmax_t;153,5198
+typedef EMACS_UINT uprintmax_t;154,5228
+# define pMd 155,5260
+# define pMu 156,5279
+# define pD 165,5665
+# define pD 167,5710
+# define pD 169,5757
+# define pD 171,5780
+# define eassert(200,7063
+# define eassume(201,7141
+extern _Noreturn void die 204,7207
+extern bool suppress_checking EXTERNALLY_VISIBLE;206,7269
+# define eassert(208,7320
+# define eassume(212,7451
+enum Lisp_Bits239,8520
+#define GCALIGNMENT 243,8648
+ VALBITS 246,8743
+ INTTYPEBITS 249,8839
+ FIXNUM_BITS 252,8946
+#define VAL_MAX 263,9328
+#define USE_LSB_TAG 271,9778
+DEFINE_GDB_SYMBOL_BEGIN USE_LSB_TAG270,9734
+# define alignas(281,10078
+# define GCALIGNED 288,10228
+# define GCALIGNED 290,10293
+# define lisp_h_XLI(327,11643
+# define lisp_h_XIL(328,11674
+# define lisp_h_XLI(330,11725
+# define lisp_h_XIL(331,11752
+#define lisp_h_CHECK_LIST_CONS(333,11786
+#define lisp_h_CHECK_NUMBER(334,11857
+#define lisp_h_CHECK_SYMBOL(335,11928
+#define lisp_h_CHECK_TYPE(336,11997
+#define lisp_h_CONSP(338,12108
+#define lisp_h_EQ(339,12157
+#define lisp_h_FLOATP(340,12202
+#define lisp_h_INTEGERP(341,12253
+#define lisp_h_MARKERP(342,12334
+#define lisp_h_MISCP(343,12409
+#define lisp_h_NILP(344,12458
+#define lisp_h_SET_SYMBOL_VAL(345,12494
+#define lisp_h_SYMBOL_CONSTANT_P(347,12608
+#define lisp_h_SYMBOL_VAL(348,12672
+#define lisp_h_SYMBOLP(350,12773
+#define lisp_h_VECTORLIKEP(351,12826
+#define lisp_h_XCAR(352,12887
+#define lisp_h_XCDR(353,12925
+#define lisp_h_XCONS(354,12965
+#define lisp_h_XHASH(356,13060
+#define lisp_h_XPNTR(357,13094
+# define lisp_h_check_cons_list(360,13222
+# define lisp_h_make_number(363,13290
+# define lisp_h_XFASTINT(365,13393
+# define lisp_h_XINT(366,13430
+# define lisp_h_XSYMBOL(367,13479
+# define lisp_h_XTYPE(371,13632
+# define lisp_h_XUNTAG(372,13697
+# define XLI(381,14087
+# define XIL(382,14118
+# define CHECK_LIST_CONS(383,14149
+# define CHECK_NUMBER(384,14210
+# define CHECK_SYMBOL(385,14259
+# define CHECK_TYPE(386,14308
+# define CONSP(387,14383
+# define EQ(388,14418
+# define FLOATP(389,14453
+# define INTEGERP(390,14490
+# define MARKERP(391,14531
+# define MISCP(392,14570
+# define NILP(393,14605
+# define SET_SYMBOL_VAL(394,14638
+# define SYMBOL_CONSTANT_P(395,14701
+# define SYMBOL_VAL(396,14764
+# define SYMBOLP(397,14813
+# define VECTORLIKEP(398,14852
+# define XCAR(399,14899
+# define XCDR(400,14932
+# define XCONS(401,14965
+# define XHASH(402,15000
+# define XPNTR(403,15035
+# define check_cons_list(405,15098
+# define make_number(408,15177
+# define XFASTINT(409,15225
+# define XINT(410,15267
+# define XSYMBOL(411,15301
+# define XTYPE(412,15341
+# define XUNTAG(413,15377
+#define LISP_MACRO_DEFUN(421,15673
+#define LISP_MACRO_DEFUN_VOID(425,15846
+#define INTMASK 437,16290
+#define case_Lisp_Int 438,16343
+#define ENUM_BF(445,16682
+#define ENUM_BF(447,16723
+enum Lisp_Type451,16764
+ Lisp_Symbol 454,16852
+ Lisp_Misc 458,16994
+ Lisp_Int0 461,17068
+ Lisp_Int1 462,17087
+ Lisp_String 466,17265
+ Lisp_Vectorlike 472,17544
+ Lisp_Cons 475,17633
+ Lisp_Float 477,17671
+enum Lisp_Misc_Type485,18017
+ Lisp_Misc_Free 487,18041
+ Lisp_Misc_Marker,488,18070
+ Lisp_Misc_Overlay,489,18092
+ Lisp_Misc_Save_Value,490,18115
+ Lisp_Misc_Finalizer,491,18141
+ Lisp_Misc_Float,494,18276
+ Lisp_Misc_Limit496,18360
+enum Lisp_Fwd_Type502,18544
+ Lisp_Fwd_Int,504,18567
+ Lisp_Fwd_Bool,505,18620
+ Lisp_Fwd_Obj,506,18671
+ Lisp_Fwd_Buffer_Obj,507,18730
+ Lisp_Fwd_Kboard_Obj 508,18801
+typedef struct { EMACS_INT i;567,21772
+typedef struct { EMACS_INT i; } Lisp_Object;567,21772
+#define LISP_INITIALLY(569,21818
+#undef CHECK_LISP_OBJECT_TYPE571,21849
+enum CHECK_LISP_OBJECT_TYPE 572,21879
+enum CHECK_LISP_OBJECT_TYPE { CHECK_LISP_OBJECT_TYPE 572,21879
+typedef EMACS_INT Lisp_Object;577,22055
+#define LISP_INITIALLY(578,22086
+enum CHECK_LISP_OBJECT_TYPE 579,22116
+enum CHECK_LISP_OBJECT_TYPE { CHECK_LISP_OBJECT_TYPE 579,22116
+#define LISP_INITIALLY_ZERO 582,22217
+INLINE bool BOOL_VECTOR_P 588,22341
+INLINE bool BUFFER_OBJFWDP 589,22382
+INLINE bool BUFFERP 590,22429
+INLINE bool CHAR_TABLE_P 591,22464
+INLINE Lisp_Object CHAR_TABLE_REF_ASCII 592,22504
+INLINE bool 593,22570
+INLINE bool 594,22605
+INLINE bool functionp 595,22641
+INLINE bool 596,22678
+INLINE bool 597,22716
+INLINE bool 598,22753
+INLINE bool 599,22788
+INLINE bool OVERLAYP 600,22822
+INLINE bool PROCESSP 601,22858
+INLINE bool PSEUDOVECTORP 602,22894
+INLINE bool SAVE_VALUEP 603,22940
+INLINE bool FINALIZERP 604,22979
+INLINE void set_sub_char_table_contents 605,23017
+INLINE bool STRINGP 607,23107
+INLINE bool SUB_CHAR_TABLE_P 608,23142
+INLINE bool SUBRP 609,23186
+INLINE bool 610,23219
+INLINE bool 611,23256
+INLINE bool WINDOWP 612,23297
+INLINE bool TERMINALP 613,23332
+INLINE struct Lisp_Save_Value *XSAVE_VALUE XSAVE_VALUE614,23369
+INLINE struct Lisp_Finalizer *XFINALIZER XFINALIZER615,23427
+INLINE struct Lisp_Symbol *(XSYMBOL)616,23483
+INLINE void 617,23535
+extern Lisp_Object char_table_ref 620,23607
+extern void char_table_set 621,23661
+extern _Noreturn Lisp_Object wrong_type_argument 624,23748
+extern _Noreturn void wrong_choice 625,23825
+extern bool might_dump;628,23916
+extern bool initialized;631,24052
+extern double extract_float 634,24108
+enum symbol_interned639,24190
+ SYMBOL_UNINTERNED 641,24213
+ SYMBOL_INTERNED 642,24238
+ SYMBOL_INTERNED_IN_INITIAL_OBARRAY 643,24261
+enum symbol_redirect646,24306
+ SYMBOL_PLAINVAL 648,24329
+ SYMBOL_VARALIAS 649,24353
+ SYMBOL_LOCALIZED 650,24377
+ SYMBOL_FORWARDED 651,24401
+struct Lisp_Symbol654,24428
+ bool_bf gcmarkbit 656,24449
+ ENUM_BF (symbol_redirect) redirect 663,24784
+ unsigned constant 668,25002
+ unsigned interned 672,25122
+ bool_bf declared_special 676,25284
+ bool_bf pinned 679,25385
+ Lisp_Object name;682,25454
+ Lisp_Object value;687,25622
+ struct Lisp_Symbol *alias;alias688,25645
+ struct Lisp_Buffer_Local_Value *blv;blv689,25676
+ union Lisp_Fwd *fwd;fwd690,25717
+ } val;691,25742
+ Lisp_Object function;694,25814
+ Lisp_Object plist;697,25876
+ struct Lisp_Symbol *next;next700,25965
+#define EXFUN(707,26243
+#define DEFUN_ARGS_MANY 712,26437
+#define DEFUN_ARGS_UNEVALLED 713,26489
+#define DEFUN_ARGS_0 714,26532
+#define DEFUN_ARGS_1 715,26560
+#define DEFUN_ARGS_2 716,26595
+#define DEFUN_ARGS_3 717,26643
+#define DEFUN_ARGS_4 718,26704
+#define DEFUN_ARGS_5 719,26778
+#define DEFUN_ARGS_6 721,26871
+#define DEFUN_ARGS_7 723,26977
+#define DEFUN_ARGS_8 725,27096
+#define TAG_PTR(729,27287
+#define TAG_SYMOFFSET(734,27534
+#define XLI_BUILTIN_LISPSYM(741,27833
+#define DEFINE_LISP_SYMBOL(746,28092
+# define DEFINE_NON_NIL_Q_SYMBOL_MACROS 755,28563
+LISP_MACRO_DEFUN 762,28768
+# define ARRAY_MARK_FLAG 768,29015
+# define PSEUDOVECTOR_FLAG 774,29258
+enum pvec_type780,29559
+ PVEC_NORMAL_VECTOR,782,29576
+ PVEC_FREE,783,29598
+ PVEC_PROCESS,784,29611
+ PVEC_FRAME,785,29627
+ PVEC_WINDOW,786,29641
+ PVEC_BOOL_VECTOR,787,29656
+ PVEC_BUFFER,788,29676
+ PVEC_HASH_TABLE,789,29691
+ PVEC_TERMINAL,790,29710
+ PVEC_WINDOW_CONFIGURATION,791,29727
+ PVEC_SUBR,792,29756
+ PVEC_OTHER,793,29769
+ PVEC_COMPILED,795,29847
+ PVEC_CHAR_TABLE,796,29864
+ PVEC_SUB_CHAR_TABLE,797,29883
+ PVEC_FONT 798,29906
+enum More_Lisp_Bits801,29982
+ PSEUDOVECTOR_SIZE_BITS 808,30373
+ PSEUDOVECTOR_SIZE_MASK 809,30406
+ PSEUDOVECTOR_REST_BITS 813,30616
+ PSEUDOVECTOR_REST_MASK 814,30649
+ PSEUDOVECTOR_AREA_BITS 818,30814
+ PVEC_TYPE_MASK 819,30892
+# define VALMASK 829,31293
+DEFINE_GDB_SYMBOL_BEGIN VALMASK828,31248
+#define MOST_POSITIVE_FIXNUM 834,31523
+#define MOST_NEGATIVE_FIXNUM 835,31583
+XINT 874,32675
+XFASTINT 889,33026
+XSYMBOL 899,33254
+XTYPE 910,33472
+XUNTAG 918,33652
+LISP_MACRO_DEFUN 927,33848
+LISP_MACRO_DEFUN 940,34233
+#define FIXNUM_OVERFLOW_P(958,34846
+LISP_MACRO_DEFUN FIXNUM_OVERFLOW_P952,34623
+LISP_MACRO_DEFUN 970,35162
+XSTRING 980,35382
+#define SYMBOL_INDEX(988,35566
+XFLOAT 991,35627
+XPROCESS 1000,35769
+XWINDOW 1007,35886
+XTERMINAL 1014,36003
+XSUBR 1021,36125
+XBUFFER 1028,36236
+XCHAR_TABLE 1035,36360
+XSUB_CHAR_TABLE 1042,36497
+XBOOL_VECTOR 1049,36639
+make_lisp_ptr 1058,36818
+make_lisp_symbol 1066,37004
+builtin_lisp_symbol 1074,37188
+#define XSETINT(1079,37270
+#define XSETFASTINT(1080,37316
+#define XSETCONS(1081,37366
+#define XSETVECTOR(1082,37426
+#define XSETSTRING(1083,37494
+#define XSETSYMBOL(1084,37558
+#define XSETFLOAT(1085,37612
+#define XSETMISC(1086,37674
+#define XSETPVECTYPE(1090,37763
+#define XSETPVECTYPESIZE(1092,37879
+#define XSETPSEUDOVECTOR(1099,38176
+#define XSETTYPED_PSEUDOVECTOR(1105,38360
+#define XSETWINDOW_CONFIGURATION(1110,38570
+#define XSETPROCESS(1112,38666
+#define XSETWINDOW(1113,38732
+#define XSETTERMINAL(1114,38796
+#define XSETSUBR(1115,38864
+#define XSETCOMPILED(1116,38924
+#define XSETBUFFER(1117,38992
+#define XSETCHAR_TABLE(1118,39056
+#define XSETBOOL_VECTOR(1119,39128
+#define XSETSUB_CHAR_TABLE(1120,39202
+XINTPTR 1128,39572
+make_pointer_integer 1134,39652
+LISP_MACRO_DEFUN_VOID 1143,39817
+typedef struct interval *INTERVAL;INTERVAL1149,39978
+ Lisp_Object cdr;1159,40153
+ struct Lisp_Cons *chain;chain1162,40227
+xcar_addr 1174,40751
+xcdr_addr 1179,40828
+LISP_MACRO_DEFUN 1185,40922
+XSETCDR 1198,41298
+CAR 1205,41448
+CDR 1212,41582
+CAR_SAFE 1221,41782
+CDR_SAFE 1226,41868
+STRING_MULTIBYTE 1243,42241
+#define STRING_BYTES_BOUND 1261,43048
+#define STRING_SET_UNIBYTE(1265,43192
+#define STRING_SET_MULTIBYTE(1275,43507
+SDATA 1286,43821
+SSDATA 1291,43899
+SREF 1297,44028
+SSET 1302,44119
+SCHARS 1307,44233
+extern ptrdiff_t string_bytes 1313,44328
+STRING_BYTES 1316,44406
+SBYTES 1326,44586
+STRING_SET_CHARS 1331,44672
+struct vectorlike_header1343,45223
+ ptrdiff_t size;1364,46374
+struct Lisp_Vector1369,46473
+ struct vectorlike_header header;1371,46496
+ Lisp_Object contents[contents1372,46533
+ ALIGNOF_STRUCT_LISP_VECTOR1378,46672
+struct Lisp_Bool_Vector1384,46855
+ struct vectorlike_header header;1388,47003
+ EMACS_INT size;1390,47077
+ bits_word data[data1395,47310
+bool_vector_size 1399,47376
+bool_vector_data 1407,47514
+bool_vector_uchar_data 1413,47608
+bool_vector_words 1421,47794
+bool_vector_bytes 1428,47989
+bool_vector_bitref 1437,48229
+bool_vector_ref 1445,48469
+bool_vector_set 1453,48609
+ header_size 1471,49038
+ bool_header_size 1472,49097
+ word_size 1473,49162
+AREF 1479,49275
+aref_addr 1485,49382
+ASIZE 1491,49492
+ASET 1497,49574
+gc_aset 1504,49733
+enum { NIL_IS_ZERO 1515,50260
+memclear 1520,50455
+#define VECSIZE(1531,50753
+#define PSEUDOVECSIZE(1538,51038
+#define UNSIGNED_CMP(1546,51471
+#define ASCII_CHAR_P(1552,51725
+enum CHARTAB_SIZE_BITS1565,52480
+ CHARTAB_SIZE_BITS_0 1567,52507
+ CHARTAB_SIZE_BITS_1 1568,52536
+ CHARTAB_SIZE_BITS_2 1569,52565
+ CHARTAB_SIZE_BITS_3 1570,52594
+extern const int chartab_size[chartab_size1573,52628
+struct Lisp_Char_Table1575,52663
+ struct vectorlike_header header;1581,52919
+ Lisp_Object defalt;1585,53069
+ Lisp_Object parent;1590,53271
+ Lisp_Object purpose;1594,53389
+ Lisp_Object ascii;1598,53555
+ Lisp_Object contents[contents1600,53579
+ Lisp_Object extras[extras1603,53690
+struct Lisp_Sub_Char_Table1606,53743
+ struct vectorlike_header header;1610,53909
+ int depth;1618,54332
+ int min_char;1621,54408
+ Lisp_Object contents[contents1624,54483
+CHAR_TABLE_REF_ASCII 1628,54557
+CHAR_TABLE_REF 1648,55104
+CHAR_TABLE_SET 1658,55393
+struct Lisp_Subr1670,55777
+ struct vectorlike_header header;1672,55798
+ Lisp_Object (*a0)a01674,55847
+ Lisp_Object (*a1)a11675,55879
+ Lisp_Object (*a2)a21676,55918
+ Lisp_Object (*a3)a31677,55970
+ Lisp_Object (*a4)a41678,56035
+ Lisp_Object (*a5)a51679,56113
+ Lisp_Object (*a6)a61680,56204
+ Lisp_Object (*a7)a71681,56308
+ Lisp_Object (*a8)a81682,56425
+ Lisp_Object (*aUNEVALLED)aUNEVALLED1683,56555
+ Lisp_Object (*aMANY)aMANY1684,56607
+ } function;1685,56662
+ short min_args,1686,56678
+ short min_args, max_args;1686,56678
+ const char *symbol_name;symbol_name1687,56708
+ const char *intspec;intspec1688,56737
+ const char *doc;doc1689,56762
+enum char_table_specials1692,56789
+ CHAR_TABLE_STANDARD_SLOTS 1697,56984
+ SUB_CHAR_TABLE_OFFSET 1701,57205
+CHAR_TABLE_EXTRA_SLOTS 1707,57368
+verify 1714,57587
+LISP_MACRO_DEFUN 1723,57912
+SYMBOL_BLV 1732,58172
+SYMBOL_FWD 1738,58307
+LISP_MACRO_DEFUN_VOID 1744,58419
+SET_SYMBOL_BLV 1754,58682
+SET_SYMBOL_FWD 1760,58841
+SYMBOL_NAME 1767,58992
+SYMBOL_INTERNED_P 1775,59121
+SYMBOL_INTERNED_IN_INITIAL_OBARRAY_P 1783,59290
+#define DEFSYM(1796,59800
+LISP_MACRO_DEFUN DEFSYM1792,59621
+struct hash_table_test1805,60053
+ Lisp_Object name;1808,60130
+ Lisp_Object user_hash_function;1811,60197
+ Lisp_Object user_cmp_function;1814,60288
+ bool (*cmpfn)cmpfn1817,60363
+ EMACS_UINT (*hashfn)hashfn1820,60477
+struct Lisp_Hash_Table1823,60546
+ struct vectorlike_header header;1826,60640
+ Lisp_Object weak;1830,60774
+ Lisp_Object rehash_size;1835,60998
+ Lisp_Object rehash_threshold;1839,61120
+ Lisp_Object hash;1843,61251
+ Lisp_Object next;1848,61481
+ Lisp_Object next_free;1851,61551
+ Lisp_Object index;1856,61762
+ ptrdiff_t count;1863,62032
+ Lisp_Object key_and_value;1868,62231
+ struct hash_table_test test;1871,62305
+ struct Lisp_Hash_Table *next_weak;next_weak1875,62448
+XHASH_TABLE 1880,62522
+#define XSET_HASH_TABLE(1885,62593
+HASH_TABLE_P 1889,62694
+HASH_KEY 1896,62851
+HASH_VALUE 1903,63031
+HASH_NEXT 1911,63245
+HASH_HASH 1918,63422
+HASH_INDEX 1926,63668
+HASH_TABLE_SIZE 1933,63817
+enum DEFAULT_HASH_SIZE 1940,63947
+enum DEFAULT_HASH_SIZE { DEFAULT_HASH_SIZE 1940,63947
+static double const DEFAULT_REHASH_THRESHOLD 1946,64167
+static double const DEFAULT_REHASH_SIZE 1950,64290
+sxhash_combine 1956,64456
+SXHASH_REDUCE 1964,64639
+struct Lisp_Misc_Any 1971,64797
+ ENUM_BF (Lisp_Misc_Type) type 1973,64857
+ bool_bf gcmarkbit 1974,64918
+ unsigned spacer 1975,64943
+struct Lisp_Marker1978,64971
+ ENUM_BF (Lisp_Misc_Type) type 1980,64992
+ bool_bf gcmarkbit 1981,65056
+ unsigned spacer 1982,65081
+ bool_bf need_adjustment 1986,65273
+ bool_bf insertion_type 1989,65414
+ struct buffer *buffer;buffer2000,66007
+ struct Lisp_Marker *next;next2009,66358
+ ptrdiff_t charpos;2011,66446
+ ptrdiff_t bytepos;2016,66704
+struct Lisp_Overlay2021,66832
+ ENUM_BF (Lisp_Misc_Type) type 2034,67340
+ bool_bf gcmarkbit 2035,67406
+ unsigned spacer 2036,67433
+ struct Lisp_Overlay *next;next2037,67459
+ Lisp_Object start;2038,67490
+ Lisp_Object end;2039,67513
+ Lisp_Object plist;2040,67534
+ SAVE_UNUSED,2047,67635
+ SAVE_INTEGER,2048,67652
+ SAVE_FUNCPOINTER,2049,67670
+ SAVE_POINTER,2050,67692
+ SAVE_OBJECT2051,67710
+enum { SAVE_SLOT_BITS 2055,67795
+enum { SAVE_VALUE_SLOTS 2058,67892
+enum { SAVE_TYPE_BITS 2062,68000
+enum Lisp_Save_Type2064,68066
+ SAVE_TYPE_INT_INT 2066,68090
+ SAVE_TYPE_INT_INT_INT2067,68163
+ SAVE_TYPE_OBJ_OBJ 2069,68253
+ SAVE_TYPE_OBJ_OBJ_OBJ 2070,68324
+ SAVE_TYPE_OBJ_OBJ_OBJ_OBJ2071,68405
+ SAVE_TYPE_PTR_INT 2073,68500
+ SAVE_TYPE_PTR_OBJ 2074,68573
+ SAVE_TYPE_PTR_PTR 2075,68645
+ SAVE_TYPE_FUNCPTR_PTR_OBJ2076,68718
+ SAVE_TYPE_MEMORY 2080,68876
+typedef void (*voidfuncptr)voidfuncptr2108,69830
+struct Lisp_Save_Value2110,69867
+ ENUM_BF (Lisp_Misc_Type) type 2112,69894
+ bool_bf gcmarkbit 2113,69963
+ unsigned spacer : 32 - (16 + 1 + SAVE_TYPE_BITS)2114,69990
+ ENUM_BF (Lisp_Save_Type) save_type : SAVE_TYPE_BITS;2123,70480
+ void *pointer;pointer2125,70549
+ voidfuncptr funcpointer;2126,70570
+ ptrdiff_t integer;2127,70601
+ Lisp_Object object;2128,70626
+ } data[data2129,70652
+save_type 2134,70746
+XSAVE_POINTER 2143,70976
+set_save_pointer 2149,71138
+XSAVE_FUNCPOINTER 2155,71320
+XSAVE_INTEGER 2164,71540
+set_save_integer 2170,71702
+XSAVE_OBJECT 2179,71923
+struct Lisp_Finalizer2186,72100
+ struct Lisp_Misc_Any base;2188,72126
+ struct Lisp_Finalizer *prev;prev2191,72214
+ struct Lisp_Finalizer *next;next2192,72247
+ Lisp_Object function;2197,72484
+struct Lisp_Free2201,72575
+ ENUM_BF (Lisp_Misc_Type) type 2203,72596
+ bool_bf gcmarkbit 2204,72659
+ unsigned spacer 2205,72686
+ union Lisp_Misc *chain;chain2206,72712
+union Lisp_Misc2212,72876
+ struct Lisp_Misc_Any u_any;2214,72896
+ struct Lisp_Free u_free;2215,72967
+ struct Lisp_Marker u_marker;2216,72996
+ struct Lisp_Overlay u_overlay;2217,73029
+ struct Lisp_Save_Value u_save_value;2218,73064
+ struct Lisp_Finalizer u_finalizer;2219,73105
+XMISC 2223,73175
+XMISCANY 2229,73264
+XMISCTYPE 2236,73373
+XMARKER 2242,73461
+XOVERLAY 2249,73576
+XSAVE_VALUE 2256,73697
+XFINALIZER 2263,73826
+struct Lisp_Intfwd2274,74111
+ enum Lisp_Fwd_Type type;2276,74134
+ EMACS_INT *intvar;intvar2277,74184
+struct Lisp_Boolfwd2284,74405
+ enum Lisp_Fwd_Type type;2286,74429
+ bool *boolvar;boolvar2287,74480
+struct Lisp_Objfwd2294,74696
+ enum Lisp_Fwd_Type type;2296,74719
+ Lisp_Object *objvar;objvar2297,74769
+struct Lisp_Buffer_Objfwd2302,74928
+ enum Lisp_Fwd_Type type;2304,74958
+ int offset;2305,75015
+ Lisp_Object predicate;2307,75107
+struct Lisp_Buffer_Local_Value2334,76464
+ bool_bf local_if_set 2338,76609
+ bool_bf frame_local 2341,76791
+ bool_bf found 2344,76933
+ union Lisp_Fwd *fwd;fwd2346,77035
+ Lisp_Object where;2348,77178
+ Lisp_Object defcell;2351,77304
+ Lisp_Object valcell;2357,77608
+struct Lisp_Kboard_Objfwd2362,77723
+ enum Lisp_Fwd_Type type;2364,77753
+ int offset;2365,77810
+union Lisp_Fwd2368,77832
+ struct Lisp_Intfwd u_intfwd;2370,77851
+ struct Lisp_Boolfwd u_boolfwd;2371,77884
+ struct Lisp_Objfwd u_objfwd;2372,77919
+ struct Lisp_Buffer_Objfwd u_buffer_objfwd;2373,77952
+ struct Lisp_Kboard_Objfwd u_kboard_objfwd;2374,77999
+XFWDTYPE 2378,78078
+XBUFFER_OBJFWD 2384,78174
+struct Lisp_Float2391,78310
+ double data;2395,78348
+ struct Lisp_Float *chain;chain2396,78367
+ } u;2397,78399
+XFLOAT_DATA 2401,78428
+ IEEE_FLOATING_POINT2415,78937
+#define _UCHAR_T2423,79260
+typedef unsigned char UCHAR;2424,79277
+enum Lisp_Compiled2429,79360
+ COMPILED_ARGLIST 2431,79383
+ COMPILED_BYTECODE 2432,79409
+ COMPILED_CONSTANTS 2433,79436
+ COMPILED_STACK_DEPTH 2434,79464
+ COMPILED_DOC_STRING 2435,79494
+ COMPILED_INTERACTIVE 2436,79523
+enum char_bits2443,79825
+ CHAR_ALT 2445,79844
+ CHAR_SUPER 2446,79870
+ CHAR_HYPER 2447,79898
+ CHAR_SHIFT 2448,79926
+ CHAR_CTL 2449,79954
+ CHAR_META 2450,79980
+ CHAR_MODIFIER_MASK 2452,80008
+ CHARACTERBITS 2457,80203
+LISP_MACRO_DEFUN 2462,80261
+NATNUMP 2470,80403
+RANGED_INTEGERP 2476,80484
+#define TYPE_RANGED_INTEGERP(2481,80606
+LISP_MACRO_DEFUN 2486,80791
+VECTORP 2500,81264
+OVERLAYP 2505,81367
+SAVE_VALUEP 2510,81466
+FINALIZERP 2516,81572
+AUTOLOADP 2522,81676
+BUFFER_OBJFWDP 2528,81767
+PSEUDOVECTOR_TYPEP 2534,81865
+PSEUDOVECTORP 2542,82118
+WINDOW_CONFIGURATIONP 2558,82470
+PROCESSP 2564,82580
+WINDOWP 2570,82664
+TERMINALP 2576,82746
+SUBRP 2582,82832
+COMPILEDP 2588,82910
+BUFFERP 2594,82996
+CHAR_TABLE_P 2600,83078
+SUB_CHAR_TABLE_P 2606,83169
+BOOL_VECTOR_P 2612,83268
+FRAMEP 2618,83361
+IMAGEP 2625,83478
+ARRAYP 2632,83583
+CHECK_LIST 2638,83702
+LISP_MACRO_DEFUN_VOID 2643,83783
+CHECK_STRING_CAR 2653,84080
+CHECK_CONS 2658,84184
+CHECK_VECTOR 2663,84264
+CHECK_BOOL_VECTOR 2668,84350
+CHECK_VECTOR_OR_STRING 2674,84527
+CHECK_ARRAY 2683,84701
+CHECK_BUFFER 2688,84809
+CHECK_WINDOW 2693,84895
+CHECK_PROCESS 2699,85001
+CHECK_NATNUM 2705,85097
+#define CHECK_RANGED_INTEGER(2710,85174
+#define CHECK_TYPE_RANGED_INTEGER(2721,85557
+#define CHECK_NUMBER_COERCE_MARKER(2729,85827
+XFLOATINT 2738,86080
+CHECK_NUMBER_OR_FLOAT 2744,86151
+#define CHECK_NUMBER_OR_FLOAT_COERCE_MARKER(2749,86250
+CHECK_NUMBER_CAR 2760,86660
+CHECK_NUMBER_CDR 2768,86782
+#define DEFUN(2803,88377
+#define DEFUN(2812,88845
+FUNCTIONP 2822,89200
+extern void defsubr 2829,89352
+enum maxargs2831,89395
+ MANY 2833,89412
+ UNEVALLED 2834,89427
+#define CALLMANY(2838,89530
+#define CALLN(2844,89883
+extern void defvar_lisp 2846,89953
+extern void defvar_lisp_nopro 2847,90030
+extern void defvar_bool 2848,90113
+extern void defvar_int 2849,90184
+extern void defvar_kboard 2850,90258
+#define DEFVAR_LISP(2869,91088
+#define DEFVAR_LISP_NOPRO(2874,91260
+#define DEFVAR_BOOL(2879,91442
+#define DEFVAR_INT(2884,91615
+#define DEFVAR_BUFFER_DEFAULTS(2890,91786
+#define DEFVAR_KBOARD(2896,91990
+typedef jmp_buf sys_jmp_buf;2906,92314
+# define sys_setjmp(2907,92343
+# define sys_longjmp(2908,92378
+typedef sigjmp_buf sys_jmp_buf;2910,92450
+# define sys_setjmp(2911,92482
+# define sys_longjmp(2912,92522
+typedef jmp_buf sys_jmp_buf;2916,92681
+# define sys_setjmp(2917,92710
+# define sys_longjmp(2918,92744
+enum specbind_tag 2943,93796
+ SPECPDL_UNWIND,2944,93816
+ SPECPDL_UNWIND_PTR,2945,93885
+ SPECPDL_UNWIND_INT,2946,93936
+ SPECPDL_UNWIND_VOID,2947,93984
+ SPECPDL_BACKTRACE,2948,94038
+ SPECPDL_LET,2949,94096
+ SPECPDL_LET_LOCAL,2951,94226
+ SPECPDL_LET_DEFAULT 2952,94283
+union specbinding2955,94355
+ ENUM_BF (specbind_tag) kind : CHAR_BIT;2957,94377
+ ENUM_BF (specbind_tag) kind : CHAR_BIT;2959,94434
+ void (*func)func2960,94480
+ Lisp_Object arg;2961,94514
+ } unwind;2962,94537
+ ENUM_BF (specbind_tag) kind : CHAR_BIT;2964,94564
+ void (*func)func2965,94610
+ void *arg;arg2966,94639
+ } unwind_ptr;2967,94656
+ ENUM_BF (specbind_tag) kind : CHAR_BIT;2969,94687
+ void (*func)func2970,94733
+ int arg;2971,94759
+ } unwind_int;2972,94774
+ ENUM_BF (specbind_tag) kind : CHAR_BIT;2974,94805
+ void (*func)func2975,94851
+ } unwind_void;2976,94878
+ ENUM_BF (specbind_tag) kind : CHAR_BIT;2978,94910
+ Lisp_Object symbol,2980,95017
+ Lisp_Object symbol, old_value,2980,95017
+ Lisp_Object symbol, old_value, where;2980,95017
+ } let;2981,95061
+ ENUM_BF (specbind_tag) kind : CHAR_BIT;2983,95085
+ bool_bf debug_on_exit 2984,95131
+ Lisp_Object function;2985,95164
+ Lisp_Object *args;args2986,95192
+ ptrdiff_t nargs;2987,95217
+ } bt;2988,95240
+extern union specbinding *specpdl;specpdl2991,95256
+extern union specbinding *specpdl_ptr;specpdl_ptr2992,95291
+extern ptrdiff_t specpdl_size;2993,95330
+SPECPDL_INDEX 2996,95379
+enum handlertype 3021,96401
+enum handlertype { CATCHER,3021,96401
+enum handlertype { CATCHER, CONDITION_CASE 3021,96401
+struct handler3023,96448
+ enum handlertype type;3025,96465
+ Lisp_Object tag_or_ch;3026,96490
+ Lisp_Object val;3027,96515
+ struct handler *next;next3028,96534
+ struct handler *nextfree;nextfree3029,96558
+ Lisp_Object *bytecode_top;bytecode_top3036,96916
+ int bytecode_dest;3037,96945
+ struct gcpro *gcpro;gcpro3042,97182
+ sys_jmp_buf jmp;3044,97212
+ EMACS_INT lisp_eval_depth;3045,97231
+ ptrdiff_t pdlcount;3046,97260
+ int poll_suppress_count;3047,97282
+ int interrupt_input_blocked;3048,97309
+ struct byte_stack *byte_stack;byte_stack3049,97340
+#define PUSH_HANDLER(3053,97437
+extern Lisp_Object memory_signal_data;3075,98143
+extern char *stack_bottom;stack_bottom3079,98276
+extern void process_pending_signals 3097,99093
+extern bool volatile pending_signals;3098,99137
+extern void process_quit_flag 3100,99176
+#define QUIT 3101,99214
+#define QUITP 3112,99464
+extern Lisp_Object Vascii_downcase_table;3114,99525
+extern Lisp_Object Vascii_canon_table;3115,99567
+extern struct gcpro *gcprolist;gcprolist3130,100274
+struct gcpro3132,100307
+ struct gcpro *next;next3134,100322
+ volatile Lisp_Object *var;var3137,100391
+ ptrdiff_t nvars;3140,100473
+ const char *name;name3144,100558
+ int lineno;3147,100614
+ int idx;3150,100675
+ int level;3153,100711
+#define GC_USE_GCPROS_AS_BEFORE 3171,101288
+#define GC_MAKE_GCPROS_NOOPS 3172,101323
+#define GC_MARK_STACK_CHECK_GCPROS 3173,101355
+#define GC_USE_GCPROS_CHECK_ZOMBIES 3174,101392
+#define GC_MARK_STACK 3177,101453
+#define BYTE_MARK_STACK 3181,101553
+#define GCPRO1(3190,101824
+#define GCPRO2(3191,101864
+#define GCPRO3(3192,101930
+#define GCPRO4(3194,102025
+#define GCPRO5(3196,102145
+#define GCPRO6(3198,102290
+#define GCPRO7(3201,102465
+#define UNGCPRO 3202,102544
+#define GCPRO1(3208,102644
+#define GCPRO2(3212,102766
+#define GCPRO3(3217,102958
+#define GCPRO4(3223,103220
+#define GCPRO5(3230,103551
+#define GCPRO6(3238,103952
+#define GCPRO7(3247,104422
+#define UNGCPRO 3257,104962
+extern int gcpro_level;3261,105031
+#define GCPRO1(3263,105056
+#define GCPRO2(3269,105290
+#define GCPRO3(3278,105708
+#define GCPRO4(3289,106265
+#define GCPRO5(3302,106963
+#define GCPRO6(3317,107803
+#define GCPRO7(3334,108784
+#define UNGCPRO 3353,109907
+#define RETURN_UNGCPRO(3363,110174
+void staticpro 3375,110447
+vcopy 3384,110648
+set_hash_key_slot 3393,110923
+set_hash_value_slot 3399,111062
+set_symbol_function 3408,111297
+set_symbol_plist 3414,111412
+set_symbol_next 3420,111515
+blv_found 3428,111688
+set_overlay_plist 3437,111871
+string_intervals 3445,112022
+set_string_intervals 3453,112144
+set_char_table_defalt 3462,112346
+set_char_table_purpose 3467,112458
+set_char_table_extras 3475,112627
+set_char_table_contents 3482,112836
+set_sub_char_table_contents 3489,113031
+extern Lisp_Object indirect_function 3495,113190
+extern Lisp_Object find_symbol_value 3496,113242
+enum Arith_Comparison 3497,113294
+ ARITH_EQUAL,3498,113318
+ ARITH_NOTEQUAL,3499,113333
+ ARITH_LESS,3500,113351
+ ARITH_GRTR,3501,113365
+ ARITH_LESS_OR_EQUAL,3502,113379
+ ARITH_GRTR_OR_EQUAL3503,113402
+extern Lisp_Object arithcompare 3505,113427
+#define INTEGER_TO_CONS(3511,113753
+#define CONS_TO_INTEGER(3529,114616
+extern intmax_t cons_to_signed 3533,114831
+extern uintmax_t cons_to_unsigned 3534,114897
+extern struct Lisp_Symbol *indirect_variable indirect_variable3536,114958
+extern _Noreturn void args_out_of_range 3537,115027
+extern _Noreturn void args_out_of_range_3 3538,115095
+extern Lisp_Object do_symval_forwarding 3540,115186
+extern void set_internal 3541,115246
+extern void syms_of_data 3542,115318
+extern void swap_in_global_binding 3543,115351
+extern void syms_of_cmds 3546,115435
+extern void keys_of_cmds 3547,115468
+extern Lisp_Object detect_coding_system 3550,115530
+extern void init_coding 3552,115683
+extern void init_coding_once 3553,115715
+extern void syms_of_coding 3554,115752
+extern ptrdiff_t chars_in_text 3557,115819
+extern ptrdiff_t multibyte_chars_in_text 3558,115886
+extern void syms_of_character 3559,115963
+extern void init_charset 3562,116031
+extern void init_charset_once 3563,116064
+extern void syms_of_charset 3564,116102
+extern void init_syntax_once 3569,116222
+extern void syms_of_syntax 3570,116259
+enum { NEXT_ALMOST_PRIME_LIMIT 3573,116320
+extern EMACS_INT next_almost_prime 3574,116359
+enum constype 3739,123811
+enum constype {CONSTYPE_HEAP,CONSTYPE_HEAP3739,123811
+enum constype {CONSTYPE_HEAP, CONSTYPE_PURE}CONSTYPE_PURE3739,123811
+extern Lisp_Object listn 3740,123857
+list2i 3745,124001
+list3i 3751,124110
+list4i 3757,124249
+extern Lisp_Object make_uninit_bool_vector 3763,124401
+extern Lisp_Object bool_vector_fill 3764,124457
+extern _Noreturn void string_overflow 3765,124521
+extern Lisp_Object make_string 3766,124567
+extern Lisp_Object make_formatted_string 3767,124625
+extern Lisp_Object make_multibyte_string 3779,124979
+extern Lisp_Object make_event_array 3780,125058
+extern Lisp_Object make_uninit_string 3781,125122
+extern Lisp_Object make_uninit_multibyte_string 3782,125173
+extern Lisp_Object make_string_from_bytes 3783,125245
+extern Lisp_Object make_specified_string 3784,125325
+extern Lisp_Object make_pure_string 3786,125417
+extern Lisp_Object make_pure_c_string 3787,125497
+build_pure_c_string 3792,125653
+build_string 3801,125858
+extern Lisp_Object pure_cons 3806,125936
+extern void make_byte_code 3807,125993
+extern struct Lisp_Vector *allocate_vector allocate_vector3808,126044
+make_uninit_vector 3820,126429
+make_uninit_sub_char_table 3833,126648
+extern struct Lisp_Vector *allocate_pseudovector allocate_pseudovector3844,126957
+#define ALLOCATE_PSEUDOVECTOR(3850,127192
+#define ALLOCATE_ZEROED_PSEUDOVECTOR(3858,127528
+extern bool gc_in_progress;3863,127729
+extern bool abort_on_gc;3864,127757
+extern Lisp_Object make_float 3865,127782
+extern void display_malloc_warning 3866,127822
+extern ptrdiff_t inhibit_garbage_collection 3867,127865
+extern Lisp_Object make_save_int_int_int 3868,127917
+extern Lisp_Object make_save_obj_obj_obj_obj 3869,127993
+extern Lisp_Object make_save_ptr 3871,128103
+extern Lisp_Object make_save_ptr_int 3872,128146
+extern Lisp_Object make_save_ptr_ptr 3873,128204
+extern Lisp_Object make_save_funcptr_ptr_obj 3874,128259
+extern Lisp_Object make_save_memory 3876,128355
+extern void free_save_value 3877,128419
+extern Lisp_Object build_overlay 3878,128462
+extern void free_marker 3879,128536
+extern void free_cons 3880,128575
+extern void init_alloc_once 3881,128619
+extern void init_alloc 3882,128655
+extern void syms_of_alloc 3883,128686
+extern struct buffer * allocate_buffer 3884,128720
+extern int valid_lisp_object_p 3885,128767
+extern int relocatable_string_data_p 3886,128813
+extern void check_cons_list 3888,128892
+INLINE void 3890,128934
+extern void *r_alloc r_alloc3895,129055
+#define FLOAT_TO_STRING_BUFSIZE 3927,130518
+extern int openp 3957,131667
+extern Lisp_Object string_to_number 3959,131777
+extern void map_obarray 3960,131840
+extern void dir_warning 3962,131954
+extern void init_obarray 3963,132007
+extern void init_lread 3964,132040
+extern void syms_of_lread 3965,132071
+intern 3968,132125
+intern_c_string 3974,132213
+extern EMACS_INT lisp_eval_depth;3980,132326
+extern Lisp_Object Vautoload_queue;3981,132360
+extern Lisp_Object Vrun_hooks;3982,132396
+extern Lisp_Object Vsignaling_function;3983,132427
+extern Lisp_Object inhibit_lisp_code;3984,132467
+extern struct handler *handlerlist;handlerlist3985,132505
+extern void run_hook 3994,132747
+extern void run_hook_with_args_2 3995,132783
+extern Lisp_Object run_hook_with_args 3996,132857
+extern _Noreturn void xsignal 3999,133016
+extern _Noreturn void xsignal0 4000,133074
+extern _Noreturn void xsignal1 4001,133120
+extern _Noreturn void xsignal2 4002,133179
+extern _Noreturn void xsignal3 4003,133251
+extern _Noreturn void signal_error 4005,133340
+extern Lisp_Object eval_sub 4006,133404
+extern Lisp_Object apply1 4007,133452
+extern Lisp_Object call0 4008,133506
+extern Lisp_Object call1 4009,133546
+extern Lisp_Object call2 4010,133599
+extern Lisp_Object call3 4011,133665
+extern Lisp_Object call4 4012,133744
+extern Lisp_Object call5 4013,133836
+extern Lisp_Object call6 4014,133941
+extern Lisp_Object call7 4015,134059
+extern Lisp_Object internal_catch 4016,134190
+extern Lisp_Object internal_lisp_condition_case 4017,134283
+extern Lisp_Object internal_condition_case 4018,134372
+extern Lisp_Object internal_condition_case_1 4019,134485
+extern Lisp_Object internal_condition_case_2 4020,134620
+extern Lisp_Object internal_condition_case_n4021,134781
+extern void specbind 4024,134977
+extern void record_unwind_protect 4025,135026
+extern void record_unwind_protect_ptr 4026,135099
+extern void record_unwind_protect_int 4027,135166
+extern void record_unwind_protect_void 4028,135227
+extern void record_unwind_protect_nothing 4029,135285
+extern void clear_unwind_protect 4030,135335
+extern void set_unwind_protect 4031,135381
+extern void set_unwind_protect_ptr 4032,135462
+extern Lisp_Object unbind_to 4033,135537
+extern _Noreturn void error 4034,135592
+fast_string_match_ignore_case 4136,140080
+extern ptrdiff_t fast_c_string_match_ignore_case 4141,140230
+extern ptrdiff_t fast_looking_at 4143,140327
+extern ptrdiff_t find_newline 4145,140466
+extern ptrdiff_t scan_newline 4147,140595
+extern ptrdiff_t scan_newline_from_point 4149,140698
+extern ptrdiff_t find_newline_no_quit 4150,140778
+extern ptrdiff_t find_before_next_newline 4152,140875
+extern void syms_of_search 4154,140973
+extern void clear_regexp_cache 4155,141008
+extern Lisp_Object Vminibuffer_list;4159,141078
+extern Lisp_Object last_minibuf_string;4160,141115
+extern Lisp_Object get_minibuffer 4161,141155
+extern void init_minibuf_once 4162,141202
+extern void syms_of_minibuf 4163,141240
+extern void syms_of_callint 4167,141307
+extern void syms_of_casefiddle 4171,141377
+extern void keys_of_casefiddle 4172,141416
+extern void init_casetab_once 4176,141486
+extern void syms_of_casetab 4177,141524
+extern Lisp_Object echo_message_buffer;4181,141592
+extern struct kboard *echo_kboard;echo_kboard4182,141632
+extern void cancel_echoing 4183,141667
+extern Lisp_Object last_undo_boundary;4184,141702
+extern bool input_pending;4185,141741
+extern sigjmp_buf return_to_command_loop;4187,141804
+extern Lisp_Object menu_bar_items 4189,141853
+extern Lisp_Object tool_bar_items 4190,141902
+extern void discard_mouse_events 4191,141958
+void handle_input_available_signal 4193,142019
+extern Lisp_Object pending_funcalls;4195,142068
+extern bool detect_input_pending 4196,142105
+extern bool detect_input_pending_ignore_squeezables 4197,142146
+extern bool detect_input_pending_run_timers 4198,142206
+extern void safe_run_hooks 4199,142258
+extern void cmd_error_internal 4200,142300
+extern Lisp_Object command_loop_1 4201,142360
+extern Lisp_Object read_menu_command 4202,142402
+extern Lisp_Object recursive_edit_1 4203,142447
+extern void record_auto_save 4204,142491
+extern void force_auto_save_soon 4205,142528
+extern void init_keyboard 4206,142569
+extern void syms_of_keyboard 4207,142603
+extern void keys_of_keyboard 4208,142640
+extern ptrdiff_t current_column 4211,142706
+extern void invalidate_current_column 4212,142746
+extern bool indented_beyond_p 4213,142792
+extern void syms_of_indent 4214,142857
+extern void store_frame_param 4217,142920
+extern void store_in_alist 4218,142994
+extern Lisp_Object do_switch_frame 4219,143064
+extern Lisp_Object get_frame_param 4220,143137
+extern void frames_discard_buffer 4221,143203
+extern void syms_of_frame 4222,143252
+extern char **initial_argv;initial_argv4225,143314
+extern int initial_argc;4226,143342
+extern bool display_arg;4228,143417
+extern Lisp_Object decode_env_path 4230,143449
+extern Lisp_Object empty_unibyte_string,4231,143520
+extern Lisp_Object empty_unibyte_string, empty_multibyte_string;4231,143520
+extern _Noreturn void terminate_due_to_signal 4232,143585
+extern Lisp_Object Vlibrary_cache;4234,143660
+void fixup_locale 4237,143721
+void synchronize_system_messages_locale 4238,143747
+void synchronize_system_time_locale 4239,143795
+INLINE void fixup_locale 4241,143845
+INLINE void synchronize_system_messages_locale 4242,143880
+INLINE void synchronize_system_time_locale 4243,143937
+extern void shut_down_emacs 4245,143997
+extern bool noninteractive;4248,144123
+extern bool no_site_lisp;4251,144215
+extern int daemon_pipe[daemon_pipe4256,144383
+#define IS_DAEMON 4257,144410
+#define DAEMON_RUNNING 4258,144450
+extern void *w32_daemon_event;w32_daemon_event4260,144518
+#define IS_DAEMON 4261,144549
+#define DAEMON_RUNNING 4262,144594
+extern bool fatal_error_in_progress;4266,144715
+extern bool inhibit_window_system;4269,144821
+extern bool running_asynch_code;4271,144914
+extern void kill_buffer_processes 4274,144977
+extern int wait_reading_process_output 4275,145026
+# define WAIT_READING_MAX 4281,145413
+# define WAIT_READING_MAX 4283,145485
+extern void add_timer_wait_descriptor 4286,145549
+extern void add_keyboard_wait_descriptor 4288,145601
+extern void delete_keyboard_wait_descriptor 4289,145649
+extern void add_gpm_wait_descriptor 4291,145716
+extern void delete_gpm_wait_descriptor 4292,145759
+extern void init_process_emacs 4294,145812
+extern void syms_of_process 4295,145851
+extern void setup_process_coding_systems 4296,145887
+extern int child_setup 4302,146007
+extern void init_callproc_1 4303,146075
+extern void init_callproc 4304,146111
+extern void set_initial_environment 4305,146145
+extern void syms_of_callproc 4306,146189
+extern Lisp_Object read_doc_string 4309,146252
+extern Lisp_Object get_doc_string 4310,146302
+extern void syms_of_doc 4311,146363
+extern int read_bytecode_char 4312,146395
+extern void syms_of_bytecode 4315,146464
+extern struct byte_stack *byte_stack_list;byte_stack_list4316,146501
+extern void mark_byte_stack 4318,146564
+extern void unmark_byte_stack 4320,146607
+extern Lisp_Object exec_byte_code 4321,146645
+extern void init_macros 4325,146795
+extern void syms_of_macros 4326,146827
+extern void truncate_undo_list 4329,146889
+extern void record_insert 4330,146939
+extern void record_delete 4331,146989
+extern void record_first_change 4332,147047
+extern void record_change 4333,147087
+extern void record_property_change 4334,147137
+extern void syms_of_undo 4337,147279
+extern void report_interval_modification 4340,147343
+extern void syms_of_menu 4343,147439
+extern void syms_of_xmenu 4346,147500
+extern char *get_current_dir_name get_current_dir_name4356,147702
+extern void stuff_char 4358,147751
+extern void init_foreground_group 4359,147784
+extern void sys_subshell 4360,147826
+extern void sys_suspend 4361,147859
+extern void discard_tty_input 4362,147891
+extern void init_sys_modes 4363,147929
+extern void reset_sys_modes 4364,147985
+extern void init_all_sys_modes 4365,148042
+extern void reset_all_sys_modes 4366,148081
+extern void child_setup_tty 4367,148121
+extern void setup_pty 4368,148156
+extern int set_window_size 4369,148185
+extern EMACS_INT get_random 4370,148229
+extern void seed_random 4371,148265
+extern void init_random 4372,148310
+extern void emacs_backtrace 4373,148342
+extern _Noreturn void emacs_abort 4374,148377
+extern void xputenv 4527,152691
+extern char *egetenv_internal egetenv_internal4529,152728
+egetenv 4532,152800
+extern void init_system_name 4539,153003
+#define eabs(4545,153296
+#define make_fixnum_or_float(4550,153429
+enum MAX_ALLOCA 4556,153680
+enum MAX_ALLOCA { MAX_ALLOCA 4556,153680
+extern void *record_xmalloc record_xmalloc4558,153725
+#define USE_SAFE_ALLOCA 4560,153791
+#define AVAIL_ALLOCA(4564,153924
+#define SAFE_ALLOCA(4568,154035
+#define SAFE_NALLOCA(4576,154376
+#define SAFE_ALLOCA_STRING(4590,154852
+#define SAFE_FREE(4598,155104
+#define SAFE_ALLOCA_LISP(4625,155682
+# define USE_STACK_LISP_OBJECTS 4652,156804
+# undef USE_STACK_LISP_OBJECTS4658,156970
+# define USE_STACK_LISP_OBJECTS 4659,157001
+enum { defined_GC_CHECK_STRING_BYTES 4663,157076
+enum { defined_GC_CHECK_STRING_BYTES 4665,157129
+union Aligned_Cons4670,157263
+ struct Lisp_Cons s;4672,157284
+ double d;4673,157306
+ double d; intmax_t i;4673,157306
+ double d; intmax_t i; void *p;p4673,157306
+union Aligned_String4676,157343
+ struct Lisp_String s;4678,157366
+ double d;4679,157390
+ double d; intmax_t i;4679,157390
+ double d; intmax_t i; void *p;p4679,157390
+ USE_STACK_CONS 4689,157698
+ USE_STACK_STRING 4691,157804
+#define STACK_CONS(4699,158141
+#define AUTO_CONS_EXPR(4701,158238
+#define AUTO_CONS(4709,158601
+#define AUTO_LIST1(4710,158672
+#define AUTO_LIST2(4712,158780
+#define AUTO_LIST3(4716,158935
+#define AUTO_LIST4(4720,159110
+extern const char *verify_ascii verify_ascii4730,159447
+# define verify_ascii(4732,159501
+#define AUTO_STRING(4740,159809
+#define FOR_EACH_TAIL(4752,160273
+#define FOR_EACH_ALIST_VALUE(4766,160764
+maybe_gc 4774,161051
+functionp 4784,161290
c-src/machsyscalls.c,23
#define SYSCALL(6,113
@@ -3033,27 +3029,27 @@ cp-src/burton.cpp,124
cp-src/functions.cpp,778
void Date::setDate setDate5,148
-void Date::plus plus32,939
-void Date::minus minus42,1229
-void Date::shift shift52,1407
-Date & Date::operator = operator =62,1628
-Date & Date::operator += operator +=69,1789
-Date & Date::operator -= operator -=78,1939
-Date & Date::operator ++ operator ++87,2080
-Date & Date::operator -- operator --96,2216
-int Date::operator - operator -104,2331
-int Date::operator < operator <112,2483
-int Date::operator > operator >116,2557
-int Date::operator == operator ==120,2631
-ostream& operator << operator <<124,2707
-istream& operator >> operator >>133,2943
-bool isLeap 159,3543
-bool isHoliday 163,3629
-void asort(173,3865
-void ReadVacation 186,4064
-void Debug 201,4523
-int WorkingDays(211,4867
-Date StartDay(226,5129
+void Date::plus plus32,938
+void Date::minus minus42,1226
+void Date::shift shift52,1404
+Date & Date::operator = operator =62,1625
+Date & Date::operator += operator +=69,1786
+Date & Date::operator -= operator -=78,1935
+Date & Date::operator ++ operator ++87,2076
+Date & Date::operator -- operator --96,2212
+int Date::operator - operator -104,2327
+int Date::operator < operator <112,2479
+int Date::operator > operator >116,2553
+int Date::operator == operator ==120,2627
+ostream& operator << operator <<124,2703
+istream& operator >> operator >>133,2939
+bool isLeap 159,3539
+bool isHoliday 163,3625
+void asort(173,3861
+void ReadVacation 186,4060
+void Debug 201,4519
+int WorkingDays(211,4863
+Date StartDay(226,5125
cp-src/MDiagArray2.h,1194
#define octave_MDiagArray2_h 29,870
@@ -3253,137 +3249,137 @@ main(37,571
D(43,659
int x;44,694
-el-src/TAGTEST.EL,179
-(foo::defmumble bletch 1,0
-(defun foo==bar foo==bar2,33
-(defalias 'pending-delete-mode pending-delete-mode6,149
-(defalias (quote explicitly-quoted-pending-delete-mode)9,222
+el-src/TAGTEST.EL,181
+(foo::defmumble bletch 3,33
+(defun foo==bar foo==bar4,66
+(defalias 'pending-delete-mode pending-delete-mode8,182
+(defalias (quote explicitly-quoted-pending-delete-mode)11,255
el-src/emacs/lisp/progmodes/etags.el,5188
-(defvar tags-file-name 34,1034
-(defgroup etags 43,1498
-(defcustom tags-case-fold-search 47,1566
-(defcustom tags-table-list 59,2051
-(defcustom tags-compression-info-list69,2449
-(defcustom tags-add-tables 88,3231
-(defcustom tags-revert-without-query 98,3627
-(defvar tags-table-computed-list 103,3778
-(defvar tags-table-computed-list-for 112,4262
-(defvar tags-table-list-pointer 117,4510
-(defvar tags-table-list-started-at 121,4701
-(defvar tags-table-set-list 124,4821
-(defcustom find-tag-hook 129,5000
-(defcustom find-tag-default-function 137,5263
-(define-obsolete-variable-alias 'find-tag-marker-ring-lengthfind-tag-marker-ring-length145,5602
-(defcustom tags-tag-face 148,5699
-(defcustom tags-apropos-verbose 154,5834
-(defcustom tags-apropos-additional-actions 160,5998
-(defvaralias 'find-tag-marker-ring find-tag-marker-ring183,6917
-(defvar default-tags-table-function 189,7097
-(defvar tags-location-ring 194,7323
-(defvar tags-table-files 201,7599
-(defvar tags-completion-table 206,7766
-(defvar tags-included-tables 209,7858
-(defvar next-file-list 212,7953
-(defvar tags-table-format-functions 217,8059
-(defvar file-of-tag-function 224,8440
-(defvar tags-table-files-function 228,8634
-(defvar tags-completion-table-function 230,8745
-(defvar snarf-tag-function 232,8840
-(defvar goto-tag-location-function 236,9049
-(defvar find-tag-regexp-search-function 239,9222
-(defvar find-tag-regexp-tag-order 241,9343
-(defvar find-tag-regexp-next-line-after-failure-p 243,9452
-(defvar find-tag-search-function 245,9572
-(defvar find-tag-tag-order 247,9679
-(defvar find-tag-next-line-after-failure-p 249,9774
-(defvar list-tags-function 251,9880
-(defvar tags-apropos-function 253,9968
-(defvar tags-included-tables-function 255,10062
-(defvar verify-tags-table-function 257,10181
-(defun initialize-new-tags-table 260,10292
-(defun tags-table-mode 276,10980
-(defun visit-tags-table 285,11245
-(defun tags-table-check-computed-list 321,12783
-(defun tags-table-extend-computed-list 360,14654
-(defun tags-expand-table-name 400,16367
-(defun tags-table-list-member 409,16710
-(defun tags-verify-table 421,17182
-(defun tags-table-including 470,19302
-(defun tags-next-table 522,21346
-(defun visit-tags-table-buffer 543,22203
-(defun tags-reset-tags-tables 712,28513
-(defun file-of-tag 731,29170
-(defun tags-table-files 740,29519
-(defun tags-included-tables 749,29869
-(defun tags-completion-table 755,30115
-(defun tags-lazy-completion-table 783,31309
-(defun tags-completion-at-point-function 799,31944
-(defun find-tag-tag 818,32694
-(defvar last-tag 837,33367
-(defun find-tag-interactive 840,33426
-(defvar find-tag-history 852,33841
-(defvar etags-case-fold-search)855,33906
-(defvar etags-syntax-table)856,33938
-(defvar local-find-tag-hook)857,33966
-(defun find-tag-noselect 860,34011
-(defun find-tag 932,37125
-(defun find-tag-other-window 959,38341
-(defun find-tag-other-frame 1000,40269
-(defun find-tag-regexp 1025,41443
-(defalias 'pop-tag-mark pop-tag-mark1049,42605
-(defvar tag-lines-already-matched 1052,42656
-(defun find-tag-in-order 1055,42763
-(defun tag-find-file-of-tag-noselect 1167,47109
-(defun tag-find-file-of-tag 1200,48955
-(defun etags-recognize-tags-table 1208,49181
-(defun etags-verify-tags-table 1241,50812
-(defun etags-file-of-tag 1246,51010
-(defun etags-tags-completion-table 1256,51345
-(defun etags-snarf-tag 1286,52551
-(defun etags-goto-tag-location 1324,54120
-(defun etags-list-tags 1388,56563
-(defmacro tags-with-face 1423,57838
-(defun etags-tags-apropos-additional 1431,58171
-(defun etags-tags-apropos 1465,59408
-(defun etags-tags-table-files 1527,61617
-(defun etags-tags-included-tables 1542,62053
-(defun tags-recognize-empty-tags-table 1559,62593
-(defun tag-exact-file-name-match-p 1587,63739
-(defun tag-file-name-match-p 1596,64132
-(defun tag-exact-match-p 1609,64688
-(defun tag-implicit-name-match-p 1620,65256
-(defun tag-symbol-match-p 1633,65856
-(defun tag-word-match-p 1643,66292
-(defun tag-partial-file-name-match-p 1652,66690
-(defun tag-any-match-p 1662,67134
-(defun tag-re-match-p 1667,67318
-(defcustom tags-loop-revert-buffers 1675,67567
-(defun next-file 1685,67976
-(defvar tags-loop-operate 1760,70890
-(defvar tags-loop-scan1763,70984
-(defun tags-loop-eval 1771,71313
-(defun tags-loop-continue 1782,71642
-(defun tags-search 1850,73948
-(defun tags-query-replace 1871,74774
-(defun tags-complete-tags-table-file 1896,75998
-(defun list-tags 1906,76377
-(defun tags-apropos 1934,77330
-(define-button-type 'tags-select-tags-tabletags-select-tags-table1957,78156
-(defun select-tags-table 1964,78395
-(defvar select-tags-table-mode-map 2019,80522
-(define-derived-mode select-tags-table-mode 2030,80905
-(defun select-tags-table-select 2034,81089
-(defun select-tags-table-quit 2043,81455
-(defun complete-tag 2049,81610
-(defconst etags--xref-limit 2074,82551
-(defvar etags-xref-find-definitions-tag-order 2076,82586
-(defun etags-xref-find 2082,82876
-(defun etags--xref-find-definitions 2096,83405
-(defclass xref-etags-location 2129,85119
-(defun xref-make-etags-location 2135,85342
-(cl-defmethod xref-location-marker 2139,85497
-(cl-defmethod xref-location-line 2146,85741
+(defvar tags-file-name 34,1035
+(defgroup etags 43,1499
+(defcustom tags-case-fold-search 47,1567
+(defcustom tags-table-list 59,2052
+(defcustom tags-compression-info-list69,2450
+(defcustom tags-add-tables 88,3232
+(defcustom tags-revert-without-query 98,3628
+(defvar tags-table-computed-list 103,3779
+(defvar tags-table-computed-list-for 112,4263
+(defvar tags-table-list-pointer 117,4511
+(defvar tags-table-list-started-at 121,4702
+(defvar tags-table-set-list 124,4822
+(defcustom find-tag-hook 129,5001
+(defcustom find-tag-default-function 137,5264
+(define-obsolete-variable-alias 'find-tag-marker-ring-lengthfind-tag-marker-ring-length145,5603
+(defcustom tags-tag-face 148,5700
+(defcustom tags-apropos-verbose 154,5835
+(defcustom tags-apropos-additional-actions 160,5999
+(defvaralias 'find-tag-marker-ring find-tag-marker-ring183,6921
+(defvar default-tags-table-function 189,7101
+(defvar tags-location-ring 194,7327
+(defvar tags-table-files 201,7603
+(defvar tags-completion-table 206,7770
+(defvar tags-included-tables 209,7862
+(defvar next-file-list 212,7957
+(defvar tags-table-format-functions 217,8063
+(defvar file-of-tag-function 224,8444
+(defvar tags-table-files-function 228,8638
+(defvar tags-completion-table-function 230,8749
+(defvar snarf-tag-function 232,8844
+(defvar goto-tag-location-function 236,9053
+(defvar find-tag-regexp-search-function 239,9226
+(defvar find-tag-regexp-tag-order 241,9347
+(defvar find-tag-regexp-next-line-after-failure-p 243,9456
+(defvar find-tag-search-function 245,9576
+(defvar find-tag-tag-order 247,9683
+(defvar find-tag-next-line-after-failure-p 249,9778
+(defvar list-tags-function 251,9884
+(defvar tags-apropos-function 253,9972
+(defvar tags-included-tables-function 255,10066
+(defvar verify-tags-table-function 257,10185
+(defun initialize-new-tags-table 260,10296
+(defun tags-table-mode 276,10984
+(defun visit-tags-table 285,11249
+(defun tags-table-check-computed-list 321,12787
+(defun tags-table-extend-computed-list 360,14658
+(defun tags-expand-table-name 400,16371
+(defun tags-table-list-member 409,16714
+(defun tags-verify-table 421,17186
+(defun tags-table-including 470,19306
+(defun tags-next-table 522,21350
+(defun visit-tags-table-buffer 543,22207
+(defun tags-reset-tags-tables 712,28517
+(defun file-of-tag 731,29174
+(defun tags-table-files 740,29524
+(defun tags-included-tables 749,29874
+(defun tags-completion-table 755,30120
+(defun tags-lazy-completion-table 783,31314
+(defun tags-completion-at-point-function 799,31949
+(defun find-tag-tag 818,32699
+(defvar last-tag 837,33372
+(defun find-tag-interactive 840,33431
+(defvar find-tag-history 852,33846
+(defvar etags-case-fold-search)855,33911
+(defvar etags-syntax-table)856,33943
+(defvar local-find-tag-hook)857,33971
+(defun find-tag-noselect 860,34016
+(defun find-tag 932,37130
+(defun find-tag-other-window 959,38346
+(defun find-tag-other-frame 1000,40274
+(defun find-tag-regexp 1025,41448
+(defalias 'pop-tag-mark pop-tag-mark1049,42610
+(defvar tag-lines-already-matched 1052,42661
+(defun find-tag-in-order 1055,42768
+(defun tag-find-file-of-tag-noselect 1167,47114
+(defun tag-find-file-of-tag 1200,48960
+(defun etags-recognize-tags-table 1208,49186
+(defun etags-verify-tags-table 1241,50817
+(defun etags-file-of-tag 1246,51015
+(defun etags-tags-completion-table 1256,51350
+(defun etags-snarf-tag 1286,52556
+(defun etags-goto-tag-location 1324,54125
+(defun etags-list-tags 1388,56568
+(defmacro tags-with-face 1423,57843
+(defun etags-tags-apropos-additional 1431,58176
+(defun etags-tags-apropos 1465,59413
+(defun etags-tags-table-files 1527,61622
+(defun etags-tags-included-tables 1542,62058
+(defun tags-recognize-empty-tags-table 1559,62598
+(defun tag-exact-file-name-match-p 1587,63744
+(defun tag-file-name-match-p 1596,64137
+(defun tag-exact-match-p 1609,64693
+(defun tag-implicit-name-match-p 1620,65261
+(defun tag-symbol-match-p 1633,65861
+(defun tag-word-match-p 1643,66297
+(defun tag-partial-file-name-match-p 1652,66695
+(defun tag-any-match-p 1662,67139
+(defun tag-re-match-p 1667,67323
+(defcustom tags-loop-revert-buffers 1675,67572
+(defun next-file 1685,67981
+(defvar tags-loop-operate 1760,70895
+(defvar tags-loop-scan1763,70989
+(defun tags-loop-eval 1771,71318
+(defun tags-loop-continue 1782,71647
+(defun tags-search 1850,73953
+(defun tags-query-replace 1871,74779
+(defun tags-complete-tags-table-file 1896,76003
+(defun list-tags 1906,76382
+(defun tags-apropos 1934,77335
+(define-button-type 'tags-select-tags-tabletags-select-tags-table1957,78161
+(defun select-tags-table 1964,78400
+(defvar select-tags-table-mode-map 2019,80527
+(define-derived-mode select-tags-table-mode 2030,80910
+(defun select-tags-table-select 2034,81094
+(defun select-tags-table-quit 2043,81460
+(defun complete-tag 2049,81615
+(defconst etags--xref-limit 2074,82556
+(defvar etags-xref-find-definitions-tag-order 2076,82591
+(defun etags-xref-find 2082,82881
+(defun etags--xref-find-definitions 2096,83410
+(defclass xref-etags-location 2129,85124
+(defun xref-make-etags-location 2135,85347
+(cl-defmethod xref-location-marker 2139,85502
+(cl-defmethod xref-location-line 2146,85746
erl-src/gs_dialog.erl,98
-define(VERSION2,32
@@ -3457,10 +3453,10 @@ func main(29,285
html-src/softwarelibero.html,200
Cos'è il software libero?4,38
-Licenze d'uso di un programmalicenze65,2500
-Sfatiamo alcuni miti138,6118
-Il movimento open sourceoss191,8037
-Impatto pratico del software liberoimpatto231,10066
+Licenze d'uso di un programmalicenze65,2502
+Sfatiamo alcuni miti138,6122
+Il movimento open sourceoss191,8041
+Impatto pratico del software liberoimpatto231,10070
html-src/index.shtml,104
&nbsp;8,281
@@ -3486,13 +3482,13 @@ MTGmtg41,1482
Fracasfracas65,2624
GaliLEOgalileo101,4232
Leasqrleasqr114,4677
-Free software that I wrote for the GNU project or for my personal or workgnu142,6065
-Etagsetags148,6180
-checkiso161,6729
-cgrep178,7547
-debian-bug.eldebian-bug190,7979
-tcpdump205,8564
-Links to interesting softwarelinks216,8891
+Free software that I wrote for the GNU project or for my personal or workgnu142,6066
+Etagsetags148,6181
+checkiso161,6731
+cgrep178,7549
+debian-bug.eldebian-bug190,7981
+tcpdump205,8566
+Links to interesting softwarelinks216,8893
lua-src/allegro.lua,400
local function get_layer_by_name 7,175
@@ -4050,22 +4046,22 @@ ord_add_element(71,1867
ord_del_element(85,2344
ord_disjoint(100,2783
ord_intersect(108,2953
-ord_intersection(126,3552
-ord_intersection3(130,3691
-ord_intersection(150,4531
-ord_intersection4(154,4703
-ord_intersection(176,5664
-ord_intersection2(181,5812
-ord_member(200,6318
-ord_seteq(216,6683
-ord_setproduct(225,6971
-ord_subset(240,7377
-ord_subtract(257,7861
-ord_symdiff(265,8054
-ord_union(288,8887
-ord_union4(303,9352
-ord_union(324,10171
-ord_union_all(329,10313
+ord_intersection(126,3553
+ord_intersection3(130,3692
+ord_intersection(150,4533
+ord_intersection4(154,4705
+ord_intersection(176,5666
+ord_intersection2(181,5814
+ord_member(200,6320
+ord_seteq(216,6685
+ord_setproduct(225,6973
+ord_subset(240,7379
+ord_subtract(257,7863
+ord_symdiff(265,8056
+ord_union(288,8889
+ord_union4(303,9354
+ord_union(324,10173
+ord_union_all(329,10315
prol-src/natded.prolog,2319
expandmng(100,2879
@@ -4087,92 +4083,92 @@ complete(328,10055
add_active(340,10527
parse(353,10949
derived_analyses(364,11341
-build(378,11965
-buildact(392,12521
-mapsyn(412,13542
-add_edge(434,14278
-findcats(447,14758
-normalize_tree(465,15478
-normalize_trees(475,15856
-expandmng_tree(486,16248
-expandmng_trees(496,16614
-cat(511,17013
-subtree(644,21266
-hypothetical_mem(653,21565
-make_coor(667,22130
-start_up:-start_up688,23013
-tokenizeatom(710,23921
-tokenize(720,24348
-isoperator(752,25377
-isoptab(756,25431
-specialsymbol(765,25756
-sstab(771,25861
-parse_cgi(787,26347
-keyvalseq(792,26510
-andkeyvalseq(796,26609
-keyval(799,26688
-valseq(807,26920
-plusvalseq(810,27007
-val(816,27109
-argvals(824,27426
-commaargvals(828,27503
-atomval(833,27578
-atom(836,27640
-action(846,28004
-keyvalcgi(864,28649
-keyvalscgi(865,28670
-outsyn(868,28726
-act(876,29060
-actout(901,29906
-texttreelist(912,30089
-htmltreelist(918,30190
-fitchtreelist(924,30304
-pp_html_table_tree(938,30759
-pp_html_tree(949,31113
-pp_html_trees(988,32381
-pp_html_table_fitch_tree(999,32769
-pp_html_fitch_tree(1017,33672
-removeexp(1129,39002
-splitexp(1142,39490
-pp_exp(1155,39990
-map_word(1168,40249
-pp_exps(1180,40474
-pp_tree(1188,40777
-pp_trees(1216,41807
-pp_word_list(1225,42128
-pp_word(1231,42262
-pp_word_list_rest(1238,42569
-pp_cat(1248,42929
-pp_syn(1255,43196
-pp_syn_paren(1276,43899
-pp_paren(1293,44377
-pp_syn_back(1300,44661
-pp_bas_cat(1311,45001
-writecat(1322,45409
-writesubs(1351,46455
-writesups(1361,46757
-writelistsubs(1371,47090
-pp_lam(1380,47408
-pp_lam_bracket(1398,48022
-pp_lam_paren(1407,48338
-pp_rule(1429,49238
-member(1447,49866
-append_list(1451,49919
-append(1456,50010
-at_least_one_member(1460,50076
-numbervars(1464,50171
-reverse(1467,50209
-select(1471,50290
-select_last(1475,50357
-cat_atoms(1479,50436
-writelist(1485,50524
-write_lex_cat(1492,50676
-writebreaklex(1500,50988
-write_lex(1513,51265
-writebreak(1521,51541
-tt:-tt1531,51713
-mt:-mt1534,51784
-cmt:-cmt1537,51878
+build(378,11967
+buildact(392,12523
+mapsyn(412,13544
+add_edge(434,14280
+findcats(447,14760
+normalize_tree(465,15480
+normalize_trees(475,15858
+expandmng_tree(486,16250
+expandmng_trees(496,16616
+cat(511,17015
+subtree(644,21268
+hypothetical_mem(653,21567
+make_coor(667,22132
+start_up:-start_up688,23015
+tokenizeatom(710,23923
+tokenize(720,24350
+isoperator(752,25379
+isoptab(756,25433
+specialsymbol(765,25758
+sstab(771,25863
+parse_cgi(787,26349
+keyvalseq(792,26512
+andkeyvalseq(796,26611
+keyval(799,26690
+valseq(807,26922
+plusvalseq(810,27009
+val(816,27111
+argvals(824,27428
+commaargvals(828,27505
+atomval(833,27580
+atom(836,27642
+action(846,28006
+keyvalcgi(864,28651
+keyvalscgi(865,28672
+outsyn(868,28728
+act(876,29062
+actout(901,29908
+texttreelist(912,30091
+htmltreelist(918,30192
+fitchtreelist(924,30306
+pp_html_table_tree(938,30761
+pp_html_tree(949,31115
+pp_html_trees(988,32383
+pp_html_table_fitch_tree(999,32771
+pp_html_fitch_tree(1017,33674
+removeexp(1129,39004
+splitexp(1142,39492
+pp_exp(1155,39992
+map_word(1168,40251
+pp_exps(1180,40476
+pp_tree(1188,40779
+pp_trees(1216,41809
+pp_word_list(1225,42130
+pp_word(1231,42264
+pp_word_list_rest(1238,42571
+pp_cat(1248,42931
+pp_syn(1255,43198
+pp_syn_paren(1276,43901
+pp_paren(1293,44379
+pp_syn_back(1300,44663
+pp_bas_cat(1311,45003
+writecat(1322,45411
+writesubs(1351,46457
+writesups(1361,46759
+writelistsubs(1371,47092
+pp_lam(1380,47410
+pp_lam_bracket(1398,48024
+pp_lam_paren(1407,48340
+pp_rule(1429,49240
+member(1447,49868
+append_list(1451,49921
+append(1456,50012
+at_least_one_member(1460,50078
+numbervars(1464,50173
+reverse(1467,50211
+select(1471,50292
+select_last(1475,50359
+cat_atoms(1479,50438
+writelist(1485,50526
+write_lex_cat(1492,50678
+writebreaklex(1500,50990
+write_lex(1513,51267
+writebreak(1521,51543
+tt:-tt1531,51715
+mt:-mt1534,51786
+cmt:-cmt1537,51880
pyt-src/server.py,1438
class Controls:Controls17,358
@@ -4280,6 +4276,11 @@ module A9,57
alias_method ( :foo2,foo237,586
A::Constant Constant42,655
+rs-src/test.rs,52
+enum IpAddrKind 3,11
+fn test1(8,48
+fn main(12,88
+
scm-src/test.scm,260
(define hello 1,0
(set! hello 3,32
@@ -4297,730 +4298,884 @@ tex-src/gzip.texi,303
@node Top,62,2139
@node Copying,80,2652
@node Overview,83,2705
-@node Sample,166,7272
-@node Invoking gzip,Invoking gzip210,8828
-@node Advanced usage,Advanced usage357,13496
-@node Environment,420,15208
-@node Tapes,437,15769
-@node Problems,460,16768
-@node Concept Index,Concept Index473,17288
+@node Sample,166,7273
+@node Invoking gzip,Invoking gzip210,8829
+@node Advanced usage,Advanced usage357,13497
+@node Environment,420,15209
+@node Tapes,437,15770
+@node Problems,460,16769
+@node Concept Index,Concept Index473,17289
tex-src/texinfo.tex,30627
-\def\texinfoversion{\texinfoversion26,1032
-\def\tie{\tie49,1523
-\def\gloggingall{\gloggingall72,2273
-\def\loggingall{\loggingall73,2342
-\def\onepageout#1{\onepageout99,3279
-\def\croppageout#1{\croppageout115,4029
-\def\cropmarks{\cropmarks142,5089
-\def\pagebody#1{\pagebody144,5136
-\def\ewtop{\ewtop157,5591
-\def\nstop{\nstop158,5655
-\def\ewbot{\ewbot160,5738
-\def\nsbot{\nsbot161,5802
-\def\parsearg #1{\parsearg170,6101
-\def\parseargx{\parseargx172,6179
-\def\parseargline{\parseargline182,6419
-\def\flushcr{\flushcr186,6540
-\newif\ifENV \ENVfalse \def\inENV{\inENV190,6739
-\def\ENVcheck{\ENVcheck191,6803
-\outer\def\begin{\begin198,7050
-\def\beginxxx #1{\beginxxx200,7088
-\def\end{\end208,7343
-\def\endxxx #1{\endxxx210,7371
-\def\errorE#1{\errorE216,7560
-\def\singlespace{\singlespace222,7754
-\def\@{\@232,7977
-\def\`{\`236,8077
-\def\'{\'237,8089
-\def\mylbrace {\mylbrace241,8137
-\def\myrbrace {\myrbrace242,8170
-\def\:{\:247,8284
-\def\*{\*250,8338
-\def\.{\.253,8414
-\def\w#1{\w258,8645
-\def\group{\group268,9128
- \def\Egroup{\Egroup273,9292
-\def\need{\need289,9734
-\def\needx#1{\needx300,10011
-\def\dots{\dots339,11397
-\def\page{\page343,11461
-\def\exdent{\exdent353,11788
-\def\exdentyyy #1{\exdentyyy354,11821
-\def\nofillexdent{\nofillexdent357,11965
-\def\nofillexdentyyy #1{\nofillexdentyyy358,12010
-\def\include{\include365,12194
-\def\includezzz #1{\includezzz366,12229
-\def\thisfile{\thisfile369,12280
-\def\center{\center373,12343
-\def\centerzzz #1{\centerzzz374,12376
-\def\sp{\sp380,12518
-\def\spxxx #1{\spxxx381,12543
-\def\comment{\comment387,12717
-\def\commentxxx #1{\commentxxx390,12814
-\def\ignoresections{\ignoresections396,12983
-\let\chapter=\relax=\relax397,13005
-\let\section=\relax=\relax406,13250
-\let\subsection=\relax=\relax409,13311
-\let\subsubsection=\relax=\relax410,13334
-\let\appendix=\relax=\relax411,13360
-\let\appendixsec=\relaxsec=\relax412,13381
-\let\appendixsection=\relaxsection=\relax413,13405
-\let\appendixsubsec=\relaxsubsec=\relax414,13433
-\let\appendixsubsection=\relaxsubsection=\relax415,13460
-\let\appendixsubsubsec=\relaxsubsubsec=\relax416,13491
-\let\appendixsubsubsection=\relaxsubsubsection=\relax417,13521
-\def\ignore{\ignore423,13623
-\long\def\ignorexxx #1\end ignore{\ignorexxx427,13763
-\def\direntry{\direntry429,13822
-\long\def\direntryxxx #1\end direntry{\direntryxxx430,13861
-\def\ifset{\ifset434,13971
-\def\ifsetxxx #1{\ifsetxxx436,14029
-\def\Eifset{\Eifset440,14156
-\def\ifsetfail{\ifsetfail441,14170
-\long\def\ifsetfailxxx #1\end ifset{\ifsetfailxxx442,14226
-\def\ifclear{\ifclear444,14287
-\def\ifclearxxx #1{\ifclearxxx446,14349
-\def\Eifclear{\Eifclear450,14480
-\def\ifclearfail{\ifclearfail451,14496
-\long\def\ifclearfailxxx #1\end ifclear{\ifclearfailxxx452,14556
-\def\set{\set456,14707
-\def\setxxx #1{\setxxx457,14734
-\def\clear{\clear460,14796
-\def\clearxxx #1{\clearxxx461,14827
-\def\iftex{\iftex466,14944
-\def\Eiftex{\Eiftex467,14957
-\def\ifinfo{\ifinfo468,14971
-\long\def\ifinfoxxx #1\end ifinfo{\ifinfoxxx469,15021
-\long\def\menu #1\end menu{\menu471,15080
-\def\asis#1{\asis472,15109
-\def\math#1{\math485,15652
-\def\node{\node487,15696
-\def\nodezzz#1{\nodezzz488,15734
-\def\nodexxx[#1,#2]{\nodexxx[489,15765
-\def\donoderef{\donoderef492,15827
-\def\unnumbnoderef{\unnumbnoderef496,15948
-\def\appendixnoderef{\appendixnoderef500,16079
-\expandafter\expandafter\expandafter\appendixsetref{setref501,16125
-\let\refill=\relaxill=\relax504,16214
-\def\setfilename{\setfilename509,16428
-\outer\def\bye{\bye518,16674
-\def\inforef #1{\inforef520,16730
-\def\inforefzzz #1,#2,#3,#4**{\inforefzzz521,16768
-\def\losespace #1{\losespace523,16865
-\def\sf{\sf532,17069
-\font\defbf=cmbx10 scaled \magstep1 %was 1314bf=cmbx10558,17864
-\font\deftt=cmtt10 scaled \magstep1tt=cmtt10559,17910
-\def\df{\df560,17946
-\def\resetmathfonts{\resetmathfonts635,20540
-\def\textfonts{\textfonts648,21129
-\def\chapfonts{\chapfonts653,21344
-\def\secfonts{\secfonts658,21560
-\def\subsecfonts{\subsecfonts663,21765
-\def\indexfonts{\indexfonts668,21982
-\def\smartitalicx{\smartitalicx691,22714
-\def\smartitalic#1{\smartitalic692,22790
-\let\cite=\smartitalic=\smartitalic698,22935
-\def\b#1{\b700,22959
-\def\t#1{\t703,22994
-\def\samp #1{\samp706,23146
-\def\key #1{\key707,23179
-\def\ctrl #1{\ctrl708,23240
-\def\tclose#1{\tclose716,23442
-\def\ {\720,23608
-\def\xkey{\xkey728,23877
-\def\kbdfoo#1#2#3\par{\kbdfoo729,23893
-\def\dmn#1{\dmn738,24194
-\def\kbd#1{\kbd740,24221
-\def\l#1{\l742,24278
-\def\r#1{\r744,24307
-\def\sc#1{\sc746,24375
-\def\ii#1{\ii747,24418
-\def\titlefont#1{\titlefont755,24651
-\def\titlepage{\titlepage761,24754
- \def\subtitlefont{\subtitlefont766,24981
- \def\authorfont{\authorfont768,25065
- \def\title{\title774,25275
- \def\titlezzz##1{\titlezzz775,25310
- \def\subtitle{\subtitle783,25625
- \def\subtitlezzz##1{\subtitlezzz784,25666
- \def\author{\author787,25784
- \def\authorzzz##1{\authorzzz788,25821
- \def\page{\page794,26112
-\def\Etitlepage{\Etitlepage804,26281
-\def\finishtitlepage{\finishtitlepage817,26669
-\def\evenheading{\evenheading846,27677
-\def\oddheading{\oddheading847,27720
-\def\everyheading{\everyheading848,27761
-\def\evenfooting{\evenfooting850,27807
-\def\oddfooting{\oddfooting851,27850
-\def\everyfooting{\everyfooting852,27891
-\def\headings #1 {\headings893,29583
-\def\HEADINGSoff{\HEADINGSoff895,29632
-\def\HEADINGSdouble{\HEADINGSdouble904,30059
-\def\HEADINGSsingle{\HEADINGSsingle914,30379
-\def\HEADINGSon{\HEADINGSon922,30600
-\def\HEADINGSafter{\HEADINGSafter924,30634
-\def\HEADINGSdoublex{\HEADINGSdoublex926,30729
-\def\HEADINGSsingleafter{\HEADINGSsingleafter933,30917
-\def\HEADINGSsinglex{\HEADINGSsinglex934,30978
-\def\today{\today943,31253
-\def\thistitle{\thistitle958,31798
-\def\settitle{\settitle959,31823
-\def\settitlezzz #1{\settitlezzz960,31860
-\def\internalBitem{\internalBitem992,32790
-\def\internalBitemx{\internalBitemx993,32840
-\def\internalBxitem "#1"{\internalBxitem995,32885
-\def\internalBxitemx "#1"{\internalBxitemx996,32965
-\def\internalBkitem{\internalBkitem998,33040
-\def\internalBkitemx{\internalBkitemx999,33092
-\def\kitemzzz #1{\kitemzzz1001,33139
-\def\xitemzzz #1{\xitemzzz1004,33241
-\def\itemzzz #1{\itemzzz1007,33344
-\def\item{\item1037,34415
-\def\itemx{\itemx1038,34466
-\def\kitem{\kitem1039,34519
-\def\kitemx{\kitemx1040,34572
-\def\xitem{\xitem1041,34627
-\def\xitemx{\xitemx1042,34680
-\def\description{\description1045,34790
-\def\table{\table1047,34840
-\def\ftable{\ftable1052,34984
-\def\Eftable{\Eftable1056,35130
-\def\vtable{\vtable1059,35199
-\def\Evtable{\Evtable1063,35345
-\def\dontindex #1{\dontindex1066,35414
-\def\fnitemindex #1{\fnitemindex1067,35434
-\def\vritemindex #1{\vritemindex1068,35479
-\def\tablez #1#2#3#4#5#6{\tablez1074,35628
-\def\Edescription{\Edescription1077,35686
-\def\itemfont{\itemfont1082,35888
-\def\Etable{\Etable1090,36114
-\def\itemize{\itemize1103,36438
-\def\itemizezzz #1{\itemizezzz1105,36474
-\def\itemizey #1#2{\itemizey1110,36569
-\def#2{1119,36815
-\def\itemcontents{\itemcontents1120,36856
-\def\bullet{\bullet1123,36904
-\def\minus{\minus1124,36931
-\def\frenchspacing{\frenchspacing1128,37039
-\def\splitoff#1#2\endmark{\splitoff1134,37264
-\def\enumerate{\enumerate1140,37494
-\def\enumeratezzz #1{\enumeratezzz1141,37533
-\def\enumeratey #1 #2\endenumeratey{\enumeratey1142,37586
- \def\thearg{\thearg1146,37733
- \ifx\thearg\empty \def\thearg{\thearg1147,37752
-\def\numericenumerate{\numericenumerate1184,39086
-\def\lowercaseenumerate{\lowercaseenumerate1190,39216
-\def\uppercaseenumerate{\uppercaseenumerate1203,39563
-\def\startenumeration#1{\startenumeration1219,40053
-\def\alphaenumerate{\alphaenumerate1227,40235
-\def\capsenumerate{\capsenumerate1228,40270
-\def\Ealphaenumerate{\Ealphaenumerate1229,40304
-\def\Ecapsenumerate{\Ecapsenumerate1230,40338
-\def\itemizeitem{\itemizeitem1234,40418
-\def\newindex #1{\newindex1259,41275
-\def\defindex{\defindex1268,41564
-\def\newcodeindex #1{\newcodeindex1272,41672
-\def\defcodeindex{\defcodeindex1279,41932
-\def\synindex #1 #2 {\synindex1283,42112
-\def\syncodeindex #1 #2 {\syncodeindex1292,42452
-\def\doindex#1{\doindex1309,43131
-\def\singleindexer #1{\singleindexer1310,43190
-\def\docodeindex#1{\docodeindex1313,43302
-\def\singlecodeindexer #1{\singlecodeindexer1314,43369
-\def\indexdummies{\indexdummies1316,43427
-\def\_{\_1317,43447
-\def\w{\w1318,43475
-\def\bf{\bf1319,43502
-\def\rm{\rm1320,43531
-\def\sl{\sl1321,43560
-\def\sf{\sf1322,43589
-\def\tt{\tt1323,43617
-\def\gtr{\gtr1324,43645
-\def\less{\less1325,43675
-\def\hat{\hat1326,43707
-\def\char{\char1327,43737
-\def\TeX{\TeX1328,43769
-\def\dots{\dots1329,43799
-\def\copyright{\copyright1330,43832
-\def\tclose##1{\tclose1331,43875
-\def\code##1{\code1332,43920
-\def\samp##1{\samp1333,43961
-\def\t##1{\t1334,44002
-\def\r##1{\r1335,44037
-\def\i##1{\i1336,44072
-\def\b##1{\b1337,44107
-\def\cite##1{\cite1338,44142
-\def\key##1{\key1339,44183
-\def\file##1{\file1340,44222
-\def\var##1{\var1341,44263
-\def\kbd##1{\kbd1342,44302
-\def\indexdummyfont#1{\indexdummyfont1347,44458
-\def\indexdummytex{\indexdummytex1348,44484
-\def\indexdummydots{\indexdummydots1349,44508
-\def\indexnofonts{\indexnofonts1351,44534
-\let\w=\indexdummyfontdummyfont1352,44554
-\let\t=\indexdummyfontdummyfont1353,44577
-\let\r=\indexdummyfontdummyfont1354,44600
-\let\i=\indexdummyfontdummyfont1355,44623
-\let\b=\indexdummyfontdummyfont1356,44646
-\let\emph=\indexdummyfontdummyfont1357,44669
-\let\strong=\indexdummyfontdummyfont1358,44695
-\let\cite=\indexdummyfont=\indexdummyfont1359,44723
-\let\sc=\indexdummyfontdummyfont1360,44749
-\let\tclose=\indexdummyfontdummyfont1364,44921
-\let\code=\indexdummyfontdummyfont1365,44949
-\let\file=\indexdummyfontdummyfont1366,44975
-\let\samp=\indexdummyfontdummyfont1367,45001
-\let\kbd=\indexdummyfontdummyfont1368,45027
-\let\key=\indexdummyfontdummyfont1369,45052
-\let\var=\indexdummyfontdummyfont1370,45077
-\let\TeX=\indexdummytexdummytex1371,45102
-\let\dots=\indexdummydotsdummydots1372,45126
-\let\indexbackslash=0 %overridden during \printindex.backslash=01382,45378
-\def\doind #1#2{\doind1384,45434
-{\indexdummies % Must do this here, since \bf, etc expand at this stagedummies1386,45477
-\def\rawbackslashxx{\rawbackslashxx1389,45617
-{\indexnofontsnofonts1394,45879
-\def\dosubind #1#2#3{\dosubind1405,46190
-{\indexdummies % Must do this here, since \bf, etc expand at this stagedummies1407,46238
-\def\rawbackslashxx{\rawbackslashxx1410,46342
-{\indexnofontsnofonts1414,46496
-\def\findex {\findex1443,47427
-\def\kindex {\kindex1444,47450
-\def\cindex {\cindex1445,47473
-\def\vindex {\vindex1446,47496
-\def\tindex {\tindex1447,47519
-\def\pindex {\pindex1448,47542
-\def\cindexsub {\cindexsub1450,47566
-\def\printindex{\printindex1462,47893
-\def\doprintindex#1{\doprintindex1464,47934
- \def\indexbackslash{\indexbackslash1481,48419
- \indexfonts\rm \tolerance=9500 \advance\baselineskip -1ptfonts\rm1482,48458
-\def\initial #1{\initial1517,49530
-\def\entry #1#2{\entry1523,49737
- \null\nobreak\indexdotfill % Have leaders before the page number.dotfill1540,50384
-\def\indexdotfill{\indexdotfill1549,50712
-\def\primary #1{\primary1552,50818
-\def\secondary #1#2{\secondary1556,50900
-\noindent\hskip\secondaryindent\hbox{#1}\indexdotfill #2\pardotfill1559,50982
-\newbox\partialpageialpage1566,51155
-\def\begindoublecolumns{\begindoublecolumns1572,51313
- \output={\global\setbox\partialpage=ialpage=1573,51349
-\def\enddoublecolumns{\enddoublecolumns1577,51537
-\def\doublecolumnout{\doublecolumnout1580,51622
- \dimen@=\pageheight \advance\dimen@ by-\ht\partialpageialpage1581,51691
-\def\pagesofar{\pagesofar1584,51869
-\def\balancecolumns{\balancecolumns1588,52106
- \availdimen@=\pageheight \advance\availdimen@ by-\ht\partialpageialpage1594,52277
- \dimen@=\pageheight \advance\dimen@ by-\ht\partialpageialpage1600,52538
-\newcount \appendixno \appendixno = `\@no1627,53443
-\def\appendixletter{\appendixletter1628,53484
-\def\opencontents{\opencontents1632,53587
-\def\thischapter{\thischapter1637,53768
-\def\seccheck#1{\seccheck1638,53806
-\def\chapternofonts{\chapternofonts1643,53910
-\def\result{\result1646,53985
-\def\equiv{\equiv1647,54020
-\def\expansion{\expansion1648,54053
-\def\print{\print1649,54094
-\def\TeX{\TeX1650,54127
-\def\dots{\dots1651,54156
-\def\copyright{\copyright1652,54187
-\def\tt{\tt1653,54228
-\def\bf{\bf1654,54255
-\def\w{\w1655,54283
-\def\less{\less1656,54308
-\def\gtr{\gtr1657,54339
-\def\hat{\hat1658,54368
-\def\char{\char1659,54397
-\def\tclose##1{\tclose1660,54428
-\def\code##1{\code1661,54472
-\def\samp##1{\samp1662,54512
-\def\r##1{\r1663,54552
-\def\b##1{\b1664,54586
-\def\key##1{\key1665,54620
-\def\file##1{\file1666,54658
-\def\kbd##1{\kbd1667,54698
-\def\i##1{\i1669,54806
-\def\cite##1{\cite1670,54840
-\def\var##1{\var1671,54880
-\def\emph##1{\emph1672,54918
-\def\dfn##1{\dfn1673,54958
-\def\thischaptername{\thischaptername1676,54999
-\outer\def\chapter{\chapter1677,55038
-\def\chapterzzz #1{\chapterzzz1678,55079
-{\chapternofonts%nofonts%1687,55475
-\global\let\section = \numberedsec=1692,55628
-\global\let\subsection = \numberedsubsec=1693,55663
-\global\let\subsubsection = \numberedsubsubsec=1694,55704
-\outer\def\appendix{\appendix1697,55755
-\def\appendixzzz #1{\appendixzzz1698,55798
-\global\advance \appendixno by 1 \message{no1700,55875
-\chapmacro {#1}{Appendix \appendixletter}letter1701,55944
-\xdef\thischapter{Appendix \appendixletter: \noexpand\thischaptername}letter:1704,56037
-{\chapternofonts%nofonts%1705,56109
- {#1}{Appendix \appendixletter}letter1707,56165
-\appendixnoderef %noderef1710,56265
-\global\let\section = \appendixsec=1711,56284
-\global\let\subsection = \appendixsubsec=1712,56319
-\global\let\subsubsection = \appendixsubsubsec=1713,56360
-\outer\def\top{\top1716,56411
-\outer\def\unnumbered{\unnumbered1717,56451
-\def\unnumberedzzz #1{\unnumberedzzz1718,56498
-{\chapternofonts%nofonts%1722,56661
-\global\let\section = \unnumberedsec=1727,56811
-\global\let\subsection = \unnumberedsubsec=1728,56848
-\global\let\subsubsection = \unnumberedsubsubsec=1729,56891
-\outer\def\numberedsec{\numberedsec1732,56944
-\def\seczzz #1{\seczzz1733,56985
-{\chapternofonts%nofonts%1736,57141
-\outer\def\appendixsection{\appendixsection1745,57327
-\outer\def\appendixsec{\appendixsec1746,57384
-\def\appendixsectionzzz #1{\appendixsectionzzz1747,57437
-\gdef\thissection{#1}\secheading {#1}{\appendixletter}letter1749,57549
-{\chapternofonts%nofonts%1750,57617
-{#1}{\appendixletter}letter1752,57673
-\appendixnoderef %noderef1755,57773
-\outer\def\unnumberedsec{\unnumberedsec1759,57813
-\def\unnumberedseczzz #1{\unnumberedseczzz1760,57866
-{\chapternofonts%nofonts%1762,57961
-\outer\def\numberedsubsec{\numberedsubsec1770,58129
-\def\numberedsubseczzz #1{\numberedsubseczzz1771,58184
-{\chapternofonts%nofonts%1774,58363
-\outer\def\appendixsubsec{\appendixsubsec1783,58567
-\def\appendixsubseczzz #1{\appendixsubseczzz1784,58622
-\subsecheading {#1}{\appendixletter}letter1786,58744
-{\chapternofonts%nofonts%1787,58809
-{#1}{\appendixletter}letter1789,58868
-\appendixnoderef %noderef1792,58983
-\outer\def\unnumberedsubsec{\unnumberedsubsec1796,59023
-\def\unnumberedsubseczzz #1{\unnumberedsubseczzz1797,59082
-{\chapternofonts%nofonts%1799,59183
-\outer\def\numberedsubsubsec{\numberedsubsubsec1807,59354
-\def\numberedsubsubseczzz #1{\numberedsubsubseczzz1808,59415
-{\chapternofonts%nofonts%1812,59612
-\outer\def\appendixsubsubsec{\appendixsubsubsec1823,59845
-\def\appendixsubsubseczzz #1{\appendixsubsubseczzz1824,59906
- {\appendixletter}letter1827,60045
-{\chapternofonts%nofonts%1828,60111
- {\appendixletter}letter1830,60176
-\appendixnoderef %noderef1834,60310
-\outer\def\unnumberedsubsubsec{\unnumberedsubsubsec1838,60350
-\def\unnumberedsubsubseczzz #1{\unnumberedsubsubseczzz1839,60415
-{\chapternofonts%nofonts%1841,60522
-\def\infotop{\infotop1851,60851
-\def\infounnumbered{\infounnumbered1852,60889
-\def\infounnumberedsec{\infounnumberedsec1853,60934
-\def\infounnumberedsubsec{\infounnumberedsubsec1854,60985
-\def\infounnumberedsubsubsec{\infounnumberedsubsubsec1855,61042
-\def\infoappendix{\infoappendix1857,61106
-\def\infoappendixsec{\infoappendixsec1858,61147
-\def\infoappendixsubsec{\infoappendixsubsec1859,61194
-\def\infoappendixsubsubsec{\infoappendixsubsubsec1860,61247
-\def\infochapter{\infochapter1862,61307
-\def\infosection{\infosection1863,61346
-\def\infosubsection{\infosubsection1864,61385
-\def\infosubsubsection{\infosubsubsection1865,61430
-\global\let\section = \numberedsec=1870,61667
-\global\let\subsection = \numberedsubsec=1871,61702
-\global\let\subsubsection = \numberedsubsubsec=1872,61743
-\def\majorheading{\majorheading1886,62250
-\def\majorheadingzzz #1{\majorheadingzzz1887,62295
-\def\chapheading{\chapheading1893,62528
-\def\chapheadingzzz #1{\chapheadingzzz1894,62571
-\def\heading{\heading1899,62766
-\def\subheading{\subheading1901,62803
-\def\subsubheading{\subsubheading1903,62846
-\def\dobreak#1#2{\dobreak1910,63123
-\def\setchapterstyle #1 {\setchapterstyle1912,63201
-\def\chapbreak{\chapbreak1919,63456
-\def\chappager{\chappager1920,63506
-\def\chapoddpage{\chapoddpage1921,63544
-\def\setchapternewpage #1 {\setchapternewpage1923,63623
-\def\CHAPPAGoff{\CHAPPAGoff1925,63680
-\def\CHAPPAGon{\CHAPPAGon1929,63774
-\global\def\HEADINGSon{\HEADINGSon1932,63865
-\def\CHAPPAGodd{\CHAPPAGodd1934,63907
-\global\def\HEADINGSon{\HEADINGSon1937,64003
-\def\CHAPFplain{\CHAPFplain1941,64057
-\def\chfplain #1#2{\chfplain1945,64149
-\def\unnchfplain #1{\unnchfplain1956,64372
-\def\unnchfopen #1{\unnchfopen1964,64601
-\def\chfopen #1#2{\chfopen1970,64809
-\def\CHAPFopen{\CHAPFopen1975,64953
-\def\subsecheadingbreak{\subsecheadingbreak1982,65171
-\def\secheadingbreak{\secheadingbreak1985,65300
-\def\secheading #1#2#3{\secheading1993,65582
-\def\plainsecheading #1{\plainsecheading1994,65638
-\def\secheadingi #1{\secheadingi1995,65681
-\def\subsecheading #1#2#3#4{\subsecheading2006,66049
-\def\subsecheadingi #1{\subsecheadingi2007,66116
-\def\subsubsecfonts{\subsubsecfonts2014,66413
-\def\subsubsecheading #1#2#3#4#5{\subsubsecheading2017,66536
-\def\subsubsecheadingi #1{\subsubsecheadingi2018,66614
-\def\startcontents#1{\startcontents2032,67086
- \unnumbchapmacro{#1}\def\thischapter{\thischapter2040,67359
-\outer\def\contents{\contents2049,67718
-\outer\def\summarycontents{\summarycontents2057,67862
- \def\secentry ##1##2##3##4{\secentry2067,68233
- \def\unnumbsecentry ##1##2{\unnumbsecentry2068,68268
- \def\subsecentry ##1##2##3##4##5{\subsecentry2069,68303
- \def\unnumbsubsecentry ##1##2{\unnumbsubsecentry2070,68344
- \def\subsubsecentry ##1##2##3##4##5##6{\subsubsecentry2071,68382
- \def\unnumbsubsubsecentry ##1##2{\unnumbsubsubsecentry2072,68429
-\def\chapentry#1#2#3{\chapentry2085,68863
-\def\shortchapentry#1#2#3{\shortchapentry2088,68980
- {#2\labelspace #1}space2091,69090
-\def\unnumbchapentry#1#2{\unnumbchapentry2094,69144
-\def\shortunnumberedentry#1#2{\shortunnumberedentry2095,69191
-\def\secentry#1#2#3#4{\secentry2102,69355
-\def\unnumbsecentry#1#2{\unnumbsecentry2103,69414
-\def\subsecentry#1#2#3#4#5{\subsecentry2106,69475
-\def\unnumbsubsecentry#1#2{\unnumbsubsecentry2107,69545
-\def\subsubsecentry#1#2#3#4#5#6{\subsubsecentry2110,69619
- \dosubsubsecentry{#2.#3.#4.#5\labelspace#1}space2111,69653
-\def\unnumbsubsubsecentry#1#2{\unnumbsubsubsecentry2112,69704
-\def\dochapentry#1#2{\dochapentry2123,70078
-\def\dosecentry#1#2{\dosecentry2138,70683
-\def\dosubsecentry#1#2{\dosubsecentry2145,70861
-\def\dosubsubsecentry#1#2{\dosubsubsecentry2152,71046
-\def\labelspace{\labelspace2160,71297
-\def\dopageno#1{\dopageno2162,71332
-\def\doshortpageno#1{\doshortpageno2163,71358
-\def\chapentryfonts{\chapentryfonts2165,71390
-\def\secentryfonts{\secentryfonts2166,71425
-\def\point{\point2192,72384
-\def\result{\result2194,72405
-\def\expansion{\expansion2195,72478
-\def\print{\print2196,72549
-\def\equiv{\equiv2198,72616
-\def\error{\error2218,73389
-\def\tex{\tex2224,73618
-\def\@{\@2242,74001
-\gdef\sepspaces{\def {\ }}}\2265,74733
-\def\aboveenvbreak{\aboveenvbreak2268,74815
-\def\afterenvbreak{\afterenvbreak2272,74981
-\def\ctl{\ctl2286,75492
-\def\ctr{\ctr2287,75564
-\def\cbl{\cbl2288,75603
-\def\cbr{\cbr2289,75643
-\def\carttop{\carttop2290,75682
-\def\cartbot{\cartbot2293,75790
-\long\def\cartouche{\cartouche2299,75930
-\def\Ecartouche{\Ecartouche2326,76718
-\def\lisp{\lisp2338,76853
-\def\Elisp{\Elisp2348,77200
-\def\next##1{\next2360,77526
-\def\Eexample{\Eexample2364,77568
-\def\Esmallexample{\Esmallexample2367,77615
-\def\smalllispx{\smalllispx2373,77793
-\def\Esmalllisp{\Esmalllisp2383,78147
-\obeyspaces \obeylines \ninett \indexfonts \rawbackslashfonts2396,78503
-\def\next##1{\next2397,78560
-\def\display{\display2401,78640
-\def\Edisplay{\Edisplay2410,78959
-\def\next##1{\next2422,79270
-\def\format{\format2426,79373
-\def\Eformat{\Eformat2434,79669
-\def\next##1{\next2437,79758
-\def\flushleft{\flushleft2441,79810
-\def\Eflushleft{\Eflushleft2451,80181
-\def\next##1{\next2454,80274
-\def\flushright{\flushright2456,80296
-\def\Eflushright{\Eflushright2466,80668
-\def\next##1{\next2470,80799
-\def\quotation{\quotation2474,80857
-\def\Equotation{\Equotation2480,81049
-\def\setdeffont #1 {\setdeffont2493,81447
-\newskip\defbodyindent \defbodyindent=.4inbodyindent2495,81493
-\newskip\defargsindent \defargsindent=50ptargsindent2496,81536
-\newskip\deftypemargin \deftypemargin=12pttypemargin2497,81579
-\newskip\deflastargmargin \deflastargmargin=18ptlastargmargin2498,81622
-\def\activeparens{\activeparens2503,81820
-\def\opnr{\opnr2529,83032
-\def\lbrb{\lbrb2530,83097
-\def\defname #1#2{\defname2536,83298
-\advance\dimen2 by -\defbodyindentbodyindent2540,83416
-\advance\dimen3 by -\defbodyindentbodyindent2542,83470
-\setbox0=\hbox{\hskip \deflastargmargin{lastargmargin2544,83524
-\dimen1=\hsize \advance \dimen1 by -\defargsindent %size for continuationsargsindent2546,83666
-\parshape 2 0in \dimen0 \defargsindent \dimen1 %argsindent2547,83741
-\rlap{\rightline{{\rm #2}\hskip \deftypemargin}typemargin2554,84110
-\advance\leftskip by -\defbodyindentbodyindent2557,84244
-\exdentamount=\defbodyindentbodyindent2558,84281
-\def\defparsebody #1#2#3{\defparsebody2568,84640
-\def#1{2572,84824
-\def#2{2573,84860
-\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2575,84932
-\exdentamount=\defbodyindentbodyindent2576,85006
-\def\defmethparsebody #1#2#3#4 {\defmethparsebody2581,85110
-\def#1{2585,85271
-\def#2##1 {2586,85307
-\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2588,85390
-\exdentamount=\defbodyindentbodyindent2589,85464
-\def\defopparsebody #1#2#3#4#5 {\defopparsebody2592,85549
-\def#1{2596,85710
-\def#2##1 ##2 {2597,85746
-\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2600,85846
-\exdentamount=\defbodyindentbodyindent2601,85920
-\def\defvarparsebody #1#2#3{\defvarparsebody2608,86191
-\def#1{2612,86378
-\def#2{2613,86414
-\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2615,86473
-\exdentamount=\defbodyindentbodyindent2616,86547
-\def\defvrparsebody #1#2#3#4 {\defvrparsebody2621,86638
-\def#1{2625,86797
-\def#2##1 {2626,86833
-\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2628,86903
-\exdentamount=\defbodyindentbodyindent2629,86977
-\def\defopvarparsebody #1#2#3#4#5 {\defopvarparsebody2632,87049
-\def#1{2636,87213
-\def#2##1 ##2 {2637,87249
-\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2640,87336
-\exdentamount=\defbodyindentbodyindent2641,87410
-\def\defunargs #1{\defunargs2664,88170
-\def\deftypefunargs #1{\deftypefunargs2676,88552
-\def\deffn{\deffn2690,88934
-\def\deffnheader #1#2#3{\deffnheader2692,88991
-\begingroup\defname {name2693,89039
-\def\defun{\defun2699,89184
-\def\defunheader #1#2{\defunheader2701,89237
-\begingroup\defname {name2702,89312
-\defunargs {unargs2703,89348
-\def\deftypefun{\deftypefun2709,89496
-\def\deftypefunheader #1#2{\deftypefunheader2712,89618
-\def\deftypefunheaderx #1#2 #3\relax{\deftypefunheaderx2714,89727
-\begingroup\defname {name2716,89819
-\deftypefunargs {typefunargs2717,89865
-\def\deftypefn{\deftypefn2723,90036
-\def\deftypefnheader #1#2#3{\deftypefnheader2726,90185
-\def\deftypefnheaderx #1#2#3 #4\relax{\deftypefnheaderx2728,90321
-\begingroup\defname {name2730,90414
-\deftypefunargs {typefunargs2731,90454
-\def\defmac{\defmac2737,90575
-\def\defmacheader #1#2{\defmacheader2739,90632
-\begingroup\defname {name2740,90708
-\defunargs {unargs2741,90741
-\def\defspec{\defspec2747,90865
-\def\defspecheader #1#2{\defspecheader2749,90926
-\begingroup\defname {name2750,91003
-\defunargs {unargs2751,91043
-\def\deffnx #1 {\deffnx2758,91238
-\def\defunx #1 {\defunx2759,91295
-\def\defmacx #1 {\defmacx2760,91352
-\def\defspecx #1 {\defspecx2761,91411
-\def\deftypefnx #1 {\deftypefnx2762,91472
-\def\deftypeunx #1 {\deftypeunx2763,91537
-\def\defop #1 {\defop2769,91683
-\defopparsebody\Edefop\defopx\defopheader\defoptype}opparsebody\Edefop\defopx\defopheader\defoptype2770,91718
-\def\defopheader #1#2#3{\defopheader2772,91772
-\begingroup\defname {name2774,91861
-\defunargs {unargs2775,91907
-\def\defmethod{\defmethod2780,91968
-\def\defmethodheader #1#2#3{\defmethodheader2782,92041
-\begingroup\defname {name2784,92129
-\defunargs {unargs2785,92169
-\def\defcv #1 {\defcv2790,92243
-\defopvarparsebody\Edefcv\defcvx\defcvarheader\defcvtype}opvarparsebody\Edefcv\defcvx\defcvarheader\defcvtype2791,92278
-\def\defcvarheader #1#2#3{\defcvarheader2793,92337
-\begingroup\defname {name2795,92423
-\defvarargs {varargs2796,92469
-\def\defivar{\defivar2801,92542
-\def\defivarheader #1#2#3{\defivarheader2803,92605
-\begingroup\defname {name2805,92691
-\defvarargs {varargs2806,92742
-\def\defopx #1 {\defopx2812,92891
-\def\defmethodx #1 {\defmethodx2813,92948
-\def\defcvx #1 {\defcvx2814,93013
-\def\defivarx #1 {\defivarx2815,93070
-\def\defvarargs #1{\defvarargs2822,93341
-\def\defvr{\defvr2828,93485
-\def\defvrheader #1#2#3{\defvrheader2830,93540
-\begingroup\defname {name2831,93588
-\def\defvar{\defvar2835,93673
-\def\defvarheader #1#2{\defvarheader2837,93733
-\begingroup\defname {name2838,93804
-\defvarargs {varargs2839,93840
-\def\defopt{\defopt2844,93906
-\def\defoptheader #1#2{\defoptheader2846,93966
-\begingroup\defname {name2847,94037
-\defvarargs {varargs2848,94076
-\def\deftypevar{\deftypevar2853,94133
-\def\deftypevarheader #1#2{\deftypevarheader2856,94249
-\begingroup\defname {name2858,94332
-\def\deftypevr{\deftypevr2865,94506
-\def\deftypevrheader #1#2#3{\deftypevrheader2867,94577
-\begingroup\defname {name2868,94629
-\def\defvrx #1 {\defvrx2876,94866
-\def\defvarx #1 {\defvarx2877,94923
-\def\defoptx #1 {\defoptx2878,94982
-\def\deftypevarx #1 {\deftypevarx2879,95041
-\def\deftypevrx #1 {\deftypevrx2880,95108
-\def\deftpargs #1{\deftpargs2885,95257
-\def\deftp{\deftp2889,95337
-\def\deftpheader #1#2#3{\deftpheader2891,95392
-\begingroup\defname {name2892,95440
-\def\deftpx #1 {\deftpx2897,95599
-\def\setref#1{\setref2908,95920
-\def\unnumbsetref#1{\unnumbsetref2913,96034
-\def\appendixsetref#1{\appendixsetref2918,96141
-\def\pxref#1{\pxref2929,96552
-\def\xref#1{\xref2930,96588
-\def\ref#1{\ref2931,96623
-\def\xrefX[#1,#2,#3,#4,#5,#6]{\xrefX[2932,96653
-\def\printedmanual{\printedmanual2933,96696
-\def\printednodename{\printednodename2934,96734
-\def\printednodename{\printednodename2939,96859
-section ``\printednodename'' in \cite{\printedmanual}\printedmanual2954,97492
-\refx{x2957,97570
-\def\dosetq #1#2{\dosetq2965,97790
-\def\internalsetq #1#2{\internalsetq2973,98048
-\def\Ypagenumber{\Ypagenumber2977,98149
-\def\Ytitle{\Ytitle2979,98175
-\def\Ynothing{\Ynothing2981,98202
-\def\Ysectionnumberandtype{\Ysectionnumberandtype2983,98219
-\def\Yappendixletterandtype{\Yappendixletterandtype2992,98535
-\ifnum\secno=0 Appendix\xreftie'char\the\appendixno{no2993,98565
-\else \ifnum \subsecno=0 Section\xreftie'char\the\appendixno.\the\secno %no.\the\secno2994,98620
-Section\xreftie'char\the\appendixno.\the\secno.\the\subsecno %no.\the\secno.\the\subsecno2996,98724
-Section\xreftie'char\the\appendixno.\the\secno.\the\subsecno.\the\subsubsecno %no.\the\secno.\the\subsecno.\the\subsubsecno2998,98795
- \def\linenumber{\linenumber3009,99134
-\def\refx#1#2{\refx3015,99318
-\def\xrdef #1#2{\xrdef3037,99944
-\def\readauxfile{\readauxfile3040,100029
-\def\supereject{\supereject3110,101810
-\footstrut\parindent=\defaultparindent\hang\textindent{aultparindent\hang\textindent3131,102495
-\def\openindices{\openindices3139,102681
-\newdimen\defaultparindent \defaultparindent = 15ptaultparindent3151,102906
-\parindent = \defaultparindentaultparindent3152,102958
-\def\smallbook{\smallbook3175,103682
-\global\def\Esmallexample{\Esmallexample3192,104109
-\def\afourpaper{\afourpaper3196,104200
-\def\finalout{\finalout3224,105008
-\def\normaldoublequote{\normaldoublequote3235,105269
-\def\normaltilde{\normaltilde3236,105295
-\def\normalcaret{\normalcaret3237,105315
-\def\normalunderscore{\normalunderscore3238,105335
-\def\normalverticalbar{\normalverticalbar3239,105360
-\def\normalless{\normalless3240,105386
-\def\normalgreater{\normalgreater3241,105405
-\def\normalplus{\normalplus3242,105427
-\def\ifusingtt#1#2{\ifusingtt3253,105919
-\def\activedoublequote{\activedoublequote3261,106247
-\def~{~3264,106333
-\def^{^3267,106394
-\def_{_3270,106433
-\def\_{\_3272,106507
-\def\lvvmode{\lvvmode3279,106844
-\def|{|3282,106894
-\def<{<3285,106957
-\def>{>3288,107014
-\def+{+3290,107052
-\def\turnoffactive{\turnoffactive3296,107213
-\global\def={=3307,107499
-\def\normalbackslash{\normalbackslash3321,107881
+\def\texinfoversion{\texinfoversion26,1035
+\def\tie{\tie49,1526
+\def\gloggingall{\gloggingall72,2276
+\def\loggingall{\loggingall73,2345
+\def\onepageout#1{\onepageout99,3282
+\def\croppageout#1{\croppageout115,4032
+\def\cropmarks{\cropmarks142,5092
+\def\pagebody#1{\pagebody144,5139
+\def\ewtop{\ewtop157,5594
+\def\nstop{\nstop158,5658
+\def\ewbot{\ewbot160,5741
+\def\nsbot{\nsbot161,5805
+\def\parsearg #1{\parsearg170,6104
+\def\parseargx{\parseargx172,6182
+\def\parseargline{\parseargline182,6422
+\def\flushcr{\flushcr186,6543
+\newif\ifENV \ENVfalse \def\inENV{\inENV190,6742
+\def\ENVcheck{\ENVcheck191,6806
+\outer\def\begin{\begin198,7053
+\def\beginxxx #1{\beginxxx200,7091
+\def\end{\end208,7346
+\def\endxxx #1{\endxxx210,7374
+\def\errorE#1{\errorE216,7563
+\def\singlespace{\singlespace222,7757
+\def\@{\@232,7980
+\def\`{\`236,8080
+\def\'{\'237,8092
+\def\mylbrace {\mylbrace241,8140
+\def\myrbrace {\myrbrace242,8173
+\def\:{\:247,8287
+\def\*{\*250,8341
+\def\.{\.253,8417
+\def\w#1{\w258,8648
+\def\group{\group268,9131
+ \def\Egroup{\Egroup273,9295
+\def\need{\need289,9737
+\def\needx#1{\needx300,10014
+\def\dots{\dots339,11400
+\def\page{\page343,11464
+\def\exdent{\exdent353,11791
+\def\exdentyyy #1{\exdentyyy354,11824
+\def\nofillexdent{\nofillexdent357,11968
+\def\nofillexdentyyy #1{\nofillexdentyyy358,12013
+\def\include{\include365,12197
+\def\includezzz #1{\includezzz366,12232
+\def\thisfile{\thisfile369,12283
+\def\center{\center373,12346
+\def\centerzzz #1{\centerzzz374,12379
+\def\sp{\sp380,12521
+\def\spxxx #1{\spxxx381,12546
+\def\comment{\comment387,12720
+\def\commentxxx #1{\commentxxx390,12817
+\def\ignoresections{\ignoresections396,12986
+\let\chapter=\relax=\relax397,13008
+\let\section=\relax=\relax406,13253
+\let\subsection=\relax=\relax409,13314
+\let\subsubsection=\relax=\relax410,13337
+\let\appendix=\relax=\relax411,13363
+\let\appendixsec=\relaxsec=\relax412,13384
+\let\appendixsection=\relaxsection=\relax413,13408
+\let\appendixsubsec=\relaxsubsec=\relax414,13436
+\let\appendixsubsection=\relaxsubsection=\relax415,13463
+\let\appendixsubsubsec=\relaxsubsubsec=\relax416,13494
+\let\appendixsubsubsection=\relaxsubsubsection=\relax417,13524
+\def\ignore{\ignore423,13626
+\long\def\ignorexxx #1\end ignore{\ignorexxx427,13766
+\def\direntry{\direntry429,13825
+\long\def\direntryxxx #1\end direntry{\direntryxxx430,13864
+\def\ifset{\ifset434,13974
+\def\ifsetxxx #1{\ifsetxxx436,14032
+\def\Eifset{\Eifset440,14159
+\def\ifsetfail{\ifsetfail441,14173
+\long\def\ifsetfailxxx #1\end ifset{\ifsetfailxxx442,14229
+\def\ifclear{\ifclear444,14290
+\def\ifclearxxx #1{\ifclearxxx446,14352
+\def\Eifclear{\Eifclear450,14483
+\def\ifclearfail{\ifclearfail451,14499
+\long\def\ifclearfailxxx #1\end ifclear{\ifclearfailxxx452,14559
+\def\set{\set456,14710
+\def\setxxx #1{\setxxx457,14737
+\def\clear{\clear460,14799
+\def\clearxxx #1{\clearxxx461,14830
+\def\iftex{\iftex466,14947
+\def\Eiftex{\Eiftex467,14960
+\def\ifinfo{\ifinfo468,14974
+\long\def\ifinfoxxx #1\end ifinfo{\ifinfoxxx469,15024
+\long\def\menu #1\end menu{\menu471,15083
+\def\asis#1{\asis472,15112
+\def\math#1{\math485,15655
+\def\node{\node487,15699
+\def\nodezzz#1{\nodezzz488,15737
+\def\nodexxx[#1,#2]{\nodexxx[489,15768
+\def\donoderef{\donoderef492,15830
+\def\unnumbnoderef{\unnumbnoderef496,15951
+\def\appendixnoderef{\appendixnoderef500,16082
+\expandafter\expandafter\expandafter\appendixsetref{setref501,16128
+\let\refill=\relaxill=\relax504,16217
+\def\setfilename{\setfilename509,16431
+\outer\def\bye{\bye518,16677
+\def\inforef #1{\inforef520,16733
+\def\inforefzzz #1,#2,#3,#4**{\inforefzzz521,16771
+\def\losespace #1{\losespace523,16868
+\def\sf{\sf532,17072
+\font\defbf=cmbx10 scaled \magstep1 %was 1314bf=cmbx10558,17867
+\font\deftt=cmtt10 scaled \magstep1tt=cmtt10559,17913
+\def\df{\df560,17949
+\def\resetmathfonts{\resetmathfonts635,20543
+\def\textfonts{\textfonts648,21132
+\def\chapfonts{\chapfonts653,21347
+\def\secfonts{\secfonts658,21563
+\def\subsecfonts{\subsecfonts663,21768
+\def\indexfonts{\indexfonts668,21985
+\def\smartitalicx{\smartitalicx691,22717
+\def\smartitalic#1{\smartitalic692,22793
+\let\cite=\smartitalic=\smartitalic698,22938
+\def\b#1{\b700,22962
+\def\t#1{\t703,22997
+\def\samp #1{\samp706,23149
+\def\key #1{\key707,23182
+\def\ctrl #1{\ctrl708,23243
+\def\tclose#1{\tclose716,23445
+\def\ {\720,23611
+\def\xkey{\xkey728,23880
+\def\kbdfoo#1#2#3\par{\kbdfoo729,23896
+\def\dmn#1{\dmn738,24197
+\def\kbd#1{\kbd740,24224
+\def\l#1{\l742,24281
+\def\r#1{\r744,24310
+\def\sc#1{\sc746,24378
+\def\ii#1{\ii747,24421
+\def\titlefont#1{\titlefont755,24654
+\def\titlepage{\titlepage761,24757
+ \def\subtitlefont{\subtitlefont766,24984
+ \def\authorfont{\authorfont768,25068
+ \def\title{\title774,25278
+ \def\titlezzz##1{\titlezzz775,25313
+ \def\subtitle{\subtitle783,25628
+ \def\subtitlezzz##1{\subtitlezzz784,25669
+ \def\author{\author787,25787
+ \def\authorzzz##1{\authorzzz788,25824
+ \def\page{\page794,26115
+\def\Etitlepage{\Etitlepage804,26284
+\def\finishtitlepage{\finishtitlepage817,26672
+\def\evenheading{\evenheading846,27680
+\def\oddheading{\oddheading847,27723
+\def\everyheading{\everyheading848,27764
+\def\evenfooting{\evenfooting850,27810
+\def\oddfooting{\oddfooting851,27853
+\def\everyfooting{\everyfooting852,27894
+\def\headings #1 {\headings893,29586
+\def\HEADINGSoff{\HEADINGSoff895,29635
+\def\HEADINGSdouble{\HEADINGSdouble904,30062
+\def\HEADINGSsingle{\HEADINGSsingle914,30382
+\def\HEADINGSon{\HEADINGSon922,30603
+\def\HEADINGSafter{\HEADINGSafter924,30637
+\def\HEADINGSdoublex{\HEADINGSdoublex926,30732
+\def\HEADINGSsingleafter{\HEADINGSsingleafter933,30920
+\def\HEADINGSsinglex{\HEADINGSsinglex934,30981
+\def\today{\today943,31256
+\def\thistitle{\thistitle958,31801
+\def\settitle{\settitle959,31826
+\def\settitlezzz #1{\settitlezzz960,31863
+\def\internalBitem{\internalBitem992,32793
+\def\internalBitemx{\internalBitemx993,32843
+\def\internalBxitem "#1"{\internalBxitem995,32888
+\def\internalBxitemx "#1"{\internalBxitemx996,32968
+\def\internalBkitem{\internalBkitem998,33043
+\def\internalBkitemx{\internalBkitemx999,33095
+\def\kitemzzz #1{\kitemzzz1001,33142
+\def\xitemzzz #1{\xitemzzz1004,33244
+\def\itemzzz #1{\itemzzz1007,33347
+\def\item{\item1037,34418
+\def\itemx{\itemx1038,34469
+\def\kitem{\kitem1039,34522
+\def\kitemx{\kitemx1040,34575
+\def\xitem{\xitem1041,34630
+\def\xitemx{\xitemx1042,34683
+\def\description{\description1045,34793
+\def\table{\table1047,34843
+\def\ftable{\ftable1052,34987
+\def\Eftable{\Eftable1056,35133
+\def\vtable{\vtable1059,35202
+\def\Evtable{\Evtable1063,35348
+\def\dontindex #1{\dontindex1066,35417
+\def\fnitemindex #1{\fnitemindex1067,35437
+\def\vritemindex #1{\vritemindex1068,35482
+\def\tablez #1#2#3#4#5#6{\tablez1074,35631
+\def\Edescription{\Edescription1077,35689
+\def\itemfont{\itemfont1082,35890
+\def\Etable{\Etable1090,36116
+\def\itemize{\itemize1103,36440
+\def\itemizezzz #1{\itemizezzz1105,36476
+\def\itemizey #1#2{\itemizey1110,36571
+\def#2{1119,36817
+\def\itemcontents{\itemcontents1120,36858
+\def\bullet{\bullet1123,36906
+\def\minus{\minus1124,36933
+\def\frenchspacing{\frenchspacing1128,37041
+\def\splitoff#1#2\endmark{\splitoff1134,37266
+\def\enumerate{\enumerate1140,37496
+\def\enumeratezzz #1{\enumeratezzz1141,37535
+\def\enumeratey #1 #2\endenumeratey{\enumeratey1142,37588
+ \def\thearg{\thearg1146,37735
+ \ifx\thearg\empty \def\thearg{\thearg1147,37754
+\def\numericenumerate{\numericenumerate1184,39088
+\def\lowercaseenumerate{\lowercaseenumerate1190,39218
+\def\uppercaseenumerate{\uppercaseenumerate1203,39565
+\def\startenumeration#1{\startenumeration1219,40055
+\def\alphaenumerate{\alphaenumerate1227,40237
+\def\capsenumerate{\capsenumerate1228,40272
+\def\Ealphaenumerate{\Ealphaenumerate1229,40306
+\def\Ecapsenumerate{\Ecapsenumerate1230,40340
+\def\itemizeitem{\itemizeitem1234,40420
+\def\newindex #1{\newindex1259,41277
+\def\defindex{\defindex1268,41566
+\def\newcodeindex #1{\newcodeindex1272,41674
+\def\defcodeindex{\defcodeindex1279,41934
+\def\synindex #1 #2 {\synindex1283,42114
+\def\syncodeindex #1 #2 {\syncodeindex1292,42454
+\def\doindex#1{\doindex1309,43133
+\def\singleindexer #1{\singleindexer1310,43192
+\def\docodeindex#1{\docodeindex1313,43304
+\def\singlecodeindexer #1{\singlecodeindexer1314,43371
+\def\indexdummies{\indexdummies1316,43429
+\def\_{\_1317,43449
+\def\w{\w1318,43477
+\def\bf{\bf1319,43504
+\def\rm{\rm1320,43533
+\def\sl{\sl1321,43562
+\def\sf{\sf1322,43591
+\def\tt{\tt1323,43619
+\def\gtr{\gtr1324,43647
+\def\less{\less1325,43677
+\def\hat{\hat1326,43709
+\def\char{\char1327,43739
+\def\TeX{\TeX1328,43771
+\def\dots{\dots1329,43801
+\def\copyright{\copyright1330,43834
+\def\tclose##1{\tclose1331,43877
+\def\code##1{\code1332,43922
+\def\samp##1{\samp1333,43963
+\def\t##1{\t1334,44004
+\def\r##1{\r1335,44039
+\def\i##1{\i1336,44074
+\def\b##1{\b1337,44109
+\def\cite##1{\cite1338,44144
+\def\key##1{\key1339,44185
+\def\file##1{\file1340,44224
+\def\var##1{\var1341,44265
+\def\kbd##1{\kbd1342,44304
+\def\indexdummyfont#1{\indexdummyfont1347,44460
+\def\indexdummytex{\indexdummytex1348,44486
+\def\indexdummydots{\indexdummydots1349,44510
+\def\indexnofonts{\indexnofonts1351,44536
+\let\w=\indexdummyfontdummyfont1352,44556
+\let\t=\indexdummyfontdummyfont1353,44579
+\let\r=\indexdummyfontdummyfont1354,44602
+\let\i=\indexdummyfontdummyfont1355,44625
+\let\b=\indexdummyfontdummyfont1356,44648
+\let\emph=\indexdummyfontdummyfont1357,44671
+\let\strong=\indexdummyfontdummyfont1358,44697
+\let\cite=\indexdummyfont=\indexdummyfont1359,44725
+\let\sc=\indexdummyfontdummyfont1360,44751
+\let\tclose=\indexdummyfontdummyfont1364,44923
+\let\code=\indexdummyfontdummyfont1365,44951
+\let\file=\indexdummyfontdummyfont1366,44977
+\let\samp=\indexdummyfontdummyfont1367,45003
+\let\kbd=\indexdummyfontdummyfont1368,45029
+\let\key=\indexdummyfontdummyfont1369,45054
+\let\var=\indexdummyfontdummyfont1370,45079
+\let\TeX=\indexdummytexdummytex1371,45104
+\let\dots=\indexdummydotsdummydots1372,45128
+\let\indexbackslash=0 %overridden during \printindex.backslash=01382,45380
+\def\doind #1#2{\doind1384,45436
+{\indexdummies % Must do this here, since \bf, etc expand at this stagedummies1386,45479
+\def\rawbackslashxx{\rawbackslashxx1389,45619
+{\indexnofontsnofonts1394,45881
+\def\dosubind #1#2#3{\dosubind1405,46192
+{\indexdummies % Must do this here, since \bf, etc expand at this stagedummies1407,46240
+\def\rawbackslashxx{\rawbackslashxx1410,46344
+{\indexnofontsnofonts1414,46498
+\def\findex {\findex1443,47429
+\def\kindex {\kindex1444,47452
+\def\cindex {\cindex1445,47475
+\def\vindex {\vindex1446,47498
+\def\tindex {\tindex1447,47521
+\def\pindex {\pindex1448,47544
+\def\cindexsub {\cindexsub1450,47568
+\def\printindex{\printindex1462,47895
+\def\doprintindex#1{\doprintindex1464,47936
+ \def\indexbackslash{\indexbackslash1481,48421
+ \indexfonts\rm \tolerance=9500 \advance\baselineskip -1ptfonts\rm1482,48460
+\def\initial #1{\initial1517,49532
+\def\entry #1#2{\entry1523,49739
+ \null\nobreak\indexdotfill % Have leaders before the page number.dotfill1540,50386
+\def\indexdotfill{\indexdotfill1549,50714
+\def\primary #1{\primary1552,50820
+\def\secondary #1#2{\secondary1556,50902
+\noindent\hskip\secondaryindent\hbox{#1}\indexdotfill #2\pardotfill1559,50984
+\newbox\partialpageialpage1566,51157
+\def\begindoublecolumns{\begindoublecolumns1572,51315
+ \output={\global\setbox\partialpage=ialpage=1573,51351
+\def\enddoublecolumns{\enddoublecolumns1577,51539
+\def\doublecolumnout{\doublecolumnout1580,51624
+ \dimen@=\pageheight \advance\dimen@ by-\ht\partialpageialpage1581,51693
+\def\pagesofar{\pagesofar1584,51871
+\def\balancecolumns{\balancecolumns1588,52108
+ \availdimen@=\pageheight \advance\availdimen@ by-\ht\partialpageialpage1594,52279
+ \dimen@=\pageheight \advance\dimen@ by-\ht\partialpageialpage1600,52540
+\newcount \appendixno \appendixno = `\@no1627,53445
+\def\appendixletter{\appendixletter1628,53486
+\def\opencontents{\opencontents1632,53589
+\def\thischapter{\thischapter1637,53770
+\def\seccheck#1{\seccheck1638,53808
+\def\chapternofonts{\chapternofonts1643,53912
+\def\result{\result1646,53987
+\def\equiv{\equiv1647,54022
+\def\expansion{\expansion1648,54055
+\def\print{\print1649,54096
+\def\TeX{\TeX1650,54129
+\def\dots{\dots1651,54158
+\def\copyright{\copyright1652,54189
+\def\tt{\tt1653,54230
+\def\bf{\bf1654,54257
+\def\w{\w1655,54285
+\def\less{\less1656,54310
+\def\gtr{\gtr1657,54341
+\def\hat{\hat1658,54370
+\def\char{\char1659,54399
+\def\tclose##1{\tclose1660,54430
+\def\code##1{\code1661,54474
+\def\samp##1{\samp1662,54514
+\def\r##1{\r1663,54554
+\def\b##1{\b1664,54588
+\def\key##1{\key1665,54622
+\def\file##1{\file1666,54660
+\def\kbd##1{\kbd1667,54700
+\def\i##1{\i1669,54808
+\def\cite##1{\cite1670,54842
+\def\var##1{\var1671,54882
+\def\emph##1{\emph1672,54920
+\def\dfn##1{\dfn1673,54960
+\def\thischaptername{\thischaptername1676,55001
+\outer\def\chapter{\chapter1677,55040
+\def\chapterzzz #1{\chapterzzz1678,55081
+{\chapternofonts%nofonts%1687,55477
+\global\let\section = \numberedsec=1692,55630
+\global\let\subsection = \numberedsubsec=1693,55665
+\global\let\subsubsection = \numberedsubsubsec=1694,55706
+\outer\def\appendix{\appendix1697,55757
+\def\appendixzzz #1{\appendixzzz1698,55800
+\global\advance \appendixno by 1 \message{no1700,55877
+\chapmacro {#1}{Appendix \appendixletter}letter1701,55946
+\xdef\thischapter{Appendix \appendixletter: \noexpand\thischaptername}letter:1704,56039
+{\chapternofonts%nofonts%1705,56111
+ {#1}{Appendix \appendixletter}letter1707,56167
+\appendixnoderef %noderef1710,56267
+\global\let\section = \appendixsec=1711,56286
+\global\let\subsection = \appendixsubsec=1712,56321
+\global\let\subsubsection = \appendixsubsubsec=1713,56362
+\outer\def\top{\top1716,56413
+\outer\def\unnumbered{\unnumbered1717,56453
+\def\unnumberedzzz #1{\unnumberedzzz1718,56500
+{\chapternofonts%nofonts%1722,56663
+\global\let\section = \unnumberedsec=1727,56813
+\global\let\subsection = \unnumberedsubsec=1728,56850
+\global\let\subsubsection = \unnumberedsubsubsec=1729,56893
+\outer\def\numberedsec{\numberedsec1732,56946
+\def\seczzz #1{\seczzz1733,56987
+{\chapternofonts%nofonts%1736,57143
+\outer\def\appendixsection{\appendixsection1745,57329
+\outer\def\appendixsec{\appendixsec1746,57386
+\def\appendixsectionzzz #1{\appendixsectionzzz1747,57439
+\gdef\thissection{#1}\secheading {#1}{\appendixletter}letter1749,57551
+{\chapternofonts%nofonts%1750,57619
+{#1}{\appendixletter}letter1752,57675
+\appendixnoderef %noderef1755,57775
+\outer\def\unnumberedsec{\unnumberedsec1759,57815
+\def\unnumberedseczzz #1{\unnumberedseczzz1760,57868
+{\chapternofonts%nofonts%1762,57963
+\outer\def\numberedsubsec{\numberedsubsec1770,58131
+\def\numberedsubseczzz #1{\numberedsubseczzz1771,58186
+{\chapternofonts%nofonts%1774,58365
+\outer\def\appendixsubsec{\appendixsubsec1783,58569
+\def\appendixsubseczzz #1{\appendixsubseczzz1784,58624
+\subsecheading {#1}{\appendixletter}letter1786,58746
+{\chapternofonts%nofonts%1787,58811
+{#1}{\appendixletter}letter1789,58870
+\appendixnoderef %noderef1792,58985
+\outer\def\unnumberedsubsec{\unnumberedsubsec1796,59025
+\def\unnumberedsubseczzz #1{\unnumberedsubseczzz1797,59084
+{\chapternofonts%nofonts%1799,59185
+\outer\def\numberedsubsubsec{\numberedsubsubsec1807,59356
+\def\numberedsubsubseczzz #1{\numberedsubsubseczzz1808,59417
+{\chapternofonts%nofonts%1812,59614
+\outer\def\appendixsubsubsec{\appendixsubsubsec1823,59847
+\def\appendixsubsubseczzz #1{\appendixsubsubseczzz1824,59908
+ {\appendixletter}letter1827,60047
+{\chapternofonts%nofonts%1828,60113
+ {\appendixletter}letter1830,60178
+\appendixnoderef %noderef1834,60312
+\outer\def\unnumberedsubsubsec{\unnumberedsubsubsec1838,60352
+\def\unnumberedsubsubseczzz #1{\unnumberedsubsubseczzz1839,60417
+{\chapternofonts%nofonts%1841,60524
+\def\infotop{\infotop1851,60853
+\def\infounnumbered{\infounnumbered1852,60891
+\def\infounnumberedsec{\infounnumberedsec1853,60936
+\def\infounnumberedsubsec{\infounnumberedsubsec1854,60987
+\def\infounnumberedsubsubsec{\infounnumberedsubsubsec1855,61044
+\def\infoappendix{\infoappendix1857,61108
+\def\infoappendixsec{\infoappendixsec1858,61149
+\def\infoappendixsubsec{\infoappendixsubsec1859,61196
+\def\infoappendixsubsubsec{\infoappendixsubsubsec1860,61249
+\def\infochapter{\infochapter1862,61309
+\def\infosection{\infosection1863,61348
+\def\infosubsection{\infosubsection1864,61387
+\def\infosubsubsection{\infosubsubsection1865,61432
+\global\let\section = \numberedsec=1870,61669
+\global\let\subsection = \numberedsubsec=1871,61704
+\global\let\subsubsection = \numberedsubsubsec=1872,61745
+\def\majorheading{\majorheading1886,62252
+\def\majorheadingzzz #1{\majorheadingzzz1887,62297
+\def\chapheading{\chapheading1893,62530
+\def\chapheadingzzz #1{\chapheadingzzz1894,62573
+\def\heading{\heading1899,62768
+\def\subheading{\subheading1901,62805
+\def\subsubheading{\subsubheading1903,62848
+\def\dobreak#1#2{\dobreak1910,63125
+\def\setchapterstyle #1 {\setchapterstyle1912,63203
+\def\chapbreak{\chapbreak1919,63458
+\def\chappager{\chappager1920,63508
+\def\chapoddpage{\chapoddpage1921,63546
+\def\setchapternewpage #1 {\setchapternewpage1923,63625
+\def\CHAPPAGoff{\CHAPPAGoff1925,63682
+\def\CHAPPAGon{\CHAPPAGon1929,63776
+\global\def\HEADINGSon{\HEADINGSon1932,63867
+\def\CHAPPAGodd{\CHAPPAGodd1934,63909
+\global\def\HEADINGSon{\HEADINGSon1937,64005
+\def\CHAPFplain{\CHAPFplain1941,64059
+\def\chfplain #1#2{\chfplain1945,64151
+\def\unnchfplain #1{\unnchfplain1956,64374
+\def\unnchfopen #1{\unnchfopen1964,64603
+\def\chfopen #1#2{\chfopen1970,64811
+\def\CHAPFopen{\CHAPFopen1975,64955
+\def\subsecheadingbreak{\subsecheadingbreak1982,65173
+\def\secheadingbreak{\secheadingbreak1985,65302
+\def\secheading #1#2#3{\secheading1993,65584
+\def\plainsecheading #1{\plainsecheading1994,65640
+\def\secheadingi #1{\secheadingi1995,65683
+\def\subsecheading #1#2#3#4{\subsecheading2006,66051
+\def\subsecheadingi #1{\subsecheadingi2007,66118
+\def\subsubsecfonts{\subsubsecfonts2014,66415
+\def\subsubsecheading #1#2#3#4#5{\subsubsecheading2017,66538
+\def\subsubsecheadingi #1{\subsubsecheadingi2018,66616
+\def\startcontents#1{\startcontents2032,67088
+ \unnumbchapmacro{#1}\def\thischapter{\thischapter2040,67361
+\outer\def\contents{\contents2049,67720
+\outer\def\summarycontents{\summarycontents2057,67864
+ \def\secentry ##1##2##3##4{\secentry2067,68235
+ \def\unnumbsecentry ##1##2{\unnumbsecentry2068,68270
+ \def\subsecentry ##1##2##3##4##5{\subsecentry2069,68305
+ \def\unnumbsubsecentry ##1##2{\unnumbsubsecentry2070,68346
+ \def\subsubsecentry ##1##2##3##4##5##6{\subsubsecentry2071,68384
+ \def\unnumbsubsubsecentry ##1##2{\unnumbsubsubsecentry2072,68431
+\def\chapentry#1#2#3{\chapentry2085,68865
+\def\shortchapentry#1#2#3{\shortchapentry2088,68982
+ {#2\labelspace #1}space2091,69092
+\def\unnumbchapentry#1#2{\unnumbchapentry2094,69146
+\def\shortunnumberedentry#1#2{\shortunnumberedentry2095,69193
+\def\secentry#1#2#3#4{\secentry2102,69357
+\def\unnumbsecentry#1#2{\unnumbsecentry2103,69416
+\def\subsecentry#1#2#3#4#5{\subsecentry2106,69477
+\def\unnumbsubsecentry#1#2{\unnumbsubsecentry2107,69547
+\def\subsubsecentry#1#2#3#4#5#6{\subsubsecentry2110,69621
+ \dosubsubsecentry{#2.#3.#4.#5\labelspace#1}space2111,69655
+\def\unnumbsubsubsecentry#1#2{\unnumbsubsubsecentry2112,69706
+\def\dochapentry#1#2{\dochapentry2123,70080
+\def\dosecentry#1#2{\dosecentry2138,70685
+\def\dosubsecentry#1#2{\dosubsecentry2145,70863
+\def\dosubsubsecentry#1#2{\dosubsubsecentry2152,71048
+\def\labelspace{\labelspace2160,71299
+\def\dopageno#1{\dopageno2162,71334
+\def\doshortpageno#1{\doshortpageno2163,71360
+\def\chapentryfonts{\chapentryfonts2165,71392
+\def\secentryfonts{\secentryfonts2166,71427
+\def\point{\point2192,72386
+\def\result{\result2194,72407
+\def\expansion{\expansion2195,72480
+\def\print{\print2196,72551
+\def\equiv{\equiv2198,72618
+\def\error{\error2218,73391
+\def\tex{\tex2224,73620
+\def\@{\@2242,74003
+\gdef\sepspaces{\def {\ }}}\2265,74735
+\def\aboveenvbreak{\aboveenvbreak2268,74817
+\def\afterenvbreak{\afterenvbreak2272,74983
+\def\ctl{\ctl2286,75494
+\def\ctr{\ctr2287,75566
+\def\cbl{\cbl2288,75605
+\def\cbr{\cbr2289,75645
+\def\carttop{\carttop2290,75684
+\def\cartbot{\cartbot2293,75792
+\long\def\cartouche{\cartouche2299,75932
+\def\Ecartouche{\Ecartouche2326,76720
+\def\lisp{\lisp2338,76855
+\def\Elisp{\Elisp2348,77202
+\def\next##1{\next2360,77528
+\def\Eexample{\Eexample2364,77570
+\def\Esmallexample{\Esmallexample2367,77617
+\def\smalllispx{\smalllispx2373,77795
+\def\Esmalllisp{\Esmalllisp2383,78149
+\obeyspaces \obeylines \ninett \indexfonts \rawbackslashfonts2396,78505
+\def\next##1{\next2397,78562
+\def\display{\display2401,78642
+\def\Edisplay{\Edisplay2410,78961
+\def\next##1{\next2422,79272
+\def\format{\format2426,79375
+\def\Eformat{\Eformat2434,79671
+\def\next##1{\next2437,79760
+\def\flushleft{\flushleft2441,79812
+\def\Eflushleft{\Eflushleft2451,80183
+\def\next##1{\next2454,80276
+\def\flushright{\flushright2456,80298
+\def\Eflushright{\Eflushright2466,80670
+\def\next##1{\next2470,80801
+\def\quotation{\quotation2474,80859
+\def\Equotation{\Equotation2480,81051
+\def\setdeffont #1 {\setdeffont2493,81449
+\newskip\defbodyindent \defbodyindent=.4inbodyindent2495,81495
+\newskip\defargsindent \defargsindent=50ptargsindent2496,81538
+\newskip\deftypemargin \deftypemargin=12pttypemargin2497,81581
+\newskip\deflastargmargin \deflastargmargin=18ptlastargmargin2498,81624
+\def\activeparens{\activeparens2503,81822
+\def\opnr{\opnr2529,83034
+\def\lbrb{\lbrb2530,83099
+\def\defname #1#2{\defname2536,83300
+\advance\dimen2 by -\defbodyindentbodyindent2540,83418
+\advance\dimen3 by -\defbodyindentbodyindent2542,83472
+\setbox0=\hbox{\hskip \deflastargmargin{lastargmargin2544,83526
+\dimen1=\hsize \advance \dimen1 by -\defargsindent %size for continuationsargsindent2546,83668
+\parshape 2 0in \dimen0 \defargsindent \dimen1 %argsindent2547,83743
+\rlap{\rightline{{\rm #2}\hskip \deftypemargin}typemargin2554,84112
+\advance\leftskip by -\defbodyindentbodyindent2557,84246
+\exdentamount=\defbodyindentbodyindent2558,84283
+\def\defparsebody #1#2#3{\defparsebody2568,84642
+\def#1{2572,84826
+\def#2{2573,84862
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2575,84934
+\exdentamount=\defbodyindentbodyindent2576,85008
+\def\defmethparsebody #1#2#3#4 {\defmethparsebody2581,85112
+\def#1{2585,85273
+\def#2##1 {2586,85309
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2588,85392
+\exdentamount=\defbodyindentbodyindent2589,85466
+\def\defopparsebody #1#2#3#4#5 {\defopparsebody2592,85551
+\def#1{2596,85712
+\def#2##1 ##2 {2597,85748
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2600,85848
+\exdentamount=\defbodyindentbodyindent2601,85922
+\def\defvarparsebody #1#2#3{\defvarparsebody2608,86193
+\def#1{2612,86380
+\def#2{2613,86416
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2615,86475
+\exdentamount=\defbodyindentbodyindent2616,86549
+\def\defvrparsebody #1#2#3#4 {\defvrparsebody2621,86640
+\def#1{2625,86799
+\def#2##1 {2626,86835
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2628,86905
+\exdentamount=\defbodyindentbodyindent2629,86979
+\def\defopvarparsebody #1#2#3#4#5 {\defopvarparsebody2632,87051
+\def#1{2636,87215
+\def#2##1 ##2 {2637,87251
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2640,87338
+\exdentamount=\defbodyindentbodyindent2641,87412
+\def\defunargs #1{\defunargs2664,88172
+\def\deftypefunargs #1{\deftypefunargs2676,88554
+\def\deffn{\deffn2690,88936
+\def\deffnheader #1#2#3{\deffnheader2692,88993
+\begingroup\defname {name2693,89041
+\def\defun{\defun2699,89186
+\def\defunheader #1#2{\defunheader2701,89239
+\begingroup\defname {name2702,89314
+\defunargs {unargs2703,89350
+\def\deftypefun{\deftypefun2709,89498
+\def\deftypefunheader #1#2{\deftypefunheader2712,89620
+\def\deftypefunheaderx #1#2 #3\relax{\deftypefunheaderx2714,89729
+\begingroup\defname {name2716,89821
+\deftypefunargs {typefunargs2717,89867
+\def\deftypefn{\deftypefn2723,90038
+\def\deftypefnheader #1#2#3{\deftypefnheader2726,90187
+\def\deftypefnheaderx #1#2#3 #4\relax{\deftypefnheaderx2728,90323
+\begingroup\defname {name2730,90416
+\deftypefunargs {typefunargs2731,90456
+\def\defmac{\defmac2737,90577
+\def\defmacheader #1#2{\defmacheader2739,90634
+\begingroup\defname {name2740,90710
+\defunargs {unargs2741,90743
+\def\defspec{\defspec2747,90867
+\def\defspecheader #1#2{\defspecheader2749,90928
+\begingroup\defname {name2750,91005
+\defunargs {unargs2751,91045
+\def\deffnx #1 {\deffnx2758,91240
+\def\defunx #1 {\defunx2759,91297
+\def\defmacx #1 {\defmacx2760,91354
+\def\defspecx #1 {\defspecx2761,91413
+\def\deftypefnx #1 {\deftypefnx2762,91474
+\def\deftypeunx #1 {\deftypeunx2763,91539
+\def\defop #1 {\defop2769,91685
+\defopparsebody\Edefop\defopx\defopheader\defoptype}opparsebody\Edefop\defopx\defopheader\defoptype2770,91720
+\def\defopheader #1#2#3{\defopheader2772,91774
+\begingroup\defname {name2774,91863
+\defunargs {unargs2775,91909
+\def\defmethod{\defmethod2780,91970
+\def\defmethodheader #1#2#3{\defmethodheader2782,92043
+\begingroup\defname {name2784,92131
+\defunargs {unargs2785,92171
+\def\defcv #1 {\defcv2790,92245
+\defopvarparsebody\Edefcv\defcvx\defcvarheader\defcvtype}opvarparsebody\Edefcv\defcvx\defcvarheader\defcvtype2791,92280
+\def\defcvarheader #1#2#3{\defcvarheader2793,92339
+\begingroup\defname {name2795,92425
+\defvarargs {varargs2796,92471
+\def\defivar{\defivar2801,92544
+\def\defivarheader #1#2#3{\defivarheader2803,92607
+\begingroup\defname {name2805,92693
+\defvarargs {varargs2806,92744
+\def\defopx #1 {\defopx2812,92893
+\def\defmethodx #1 {\defmethodx2813,92950
+\def\defcvx #1 {\defcvx2814,93015
+\def\defivarx #1 {\defivarx2815,93072
+\def\defvarargs #1{\defvarargs2822,93343
+\def\defvr{\defvr2828,93487
+\def\defvrheader #1#2#3{\defvrheader2830,93542
+\begingroup\defname {name2831,93590
+\def\defvar{\defvar2835,93675
+\def\defvarheader #1#2{\defvarheader2837,93735
+\begingroup\defname {name2838,93806
+\defvarargs {varargs2839,93842
+\def\defopt{\defopt2844,93908
+\def\defoptheader #1#2{\defoptheader2846,93968
+\begingroup\defname {name2847,94039
+\defvarargs {varargs2848,94078
+\def\deftypevar{\deftypevar2853,94135
+\def\deftypevarheader #1#2{\deftypevarheader2856,94251
+\begingroup\defname {name2858,94334
+\def\deftypevr{\deftypevr2865,94508
+\def\deftypevrheader #1#2#3{\deftypevrheader2867,94579
+\begingroup\defname {name2868,94631
+\def\defvrx #1 {\defvrx2876,94868
+\def\defvarx #1 {\defvarx2877,94925
+\def\defoptx #1 {\defoptx2878,94984
+\def\deftypevarx #1 {\deftypevarx2879,95043
+\def\deftypevrx #1 {\deftypevrx2880,95110
+\def\deftpargs #1{\deftpargs2885,95259
+\def\deftp{\deftp2889,95339
+\def\deftpheader #1#2#3{\deftpheader2891,95394
+\begingroup\defname {name2892,95442
+\def\deftpx #1 {\deftpx2897,95601
+\def\setref#1{\setref2908,95922
+\def\unnumbsetref#1{\unnumbsetref2913,96036
+\def\appendixsetref#1{\appendixsetref2918,96143
+\def\pxref#1{\pxref2929,96554
+\def\xref#1{\xref2930,96590
+\def\ref#1{\ref2931,96625
+\def\xrefX[#1,#2,#3,#4,#5,#6]{\xrefX[2932,96655
+\def\printedmanual{\printedmanual2933,96698
+\def\printednodename{\printednodename2934,96736
+\def\printednodename{\printednodename2939,96861
+section ``\printednodename'' in \cite{\printedmanual}\printedmanual2954,97493
+\refx{x2957,97571
+\def\dosetq #1#2{\dosetq2965,97791
+\def\internalsetq #1#2{\internalsetq2973,98049
+\def\Ypagenumber{\Ypagenumber2977,98150
+\def\Ytitle{\Ytitle2979,98176
+\def\Ynothing{\Ynothing2981,98203
+\def\Ysectionnumberandtype{\Ysectionnumberandtype2983,98220
+\def\Yappendixletterandtype{\Yappendixletterandtype2992,98536
+\ifnum\secno=0 Appendix\xreftie'char\the\appendixno{no2993,98566
+\else \ifnum \subsecno=0 Section\xreftie'char\the\appendixno.\the\secno %no.\the\secno2994,98621
+Section\xreftie'char\the\appendixno.\the\secno.\the\subsecno %no.\the\secno.\the\subsecno2996,98725
+Section\xreftie'char\the\appendixno.\the\secno.\the\subsecno.\the\subsubsecno %no.\the\secno.\the\subsecno.\the\subsubsecno2998,98796
+ \def\linenumber{\linenumber3009,99135
+\def\refx#1#2{\refx3015,99319
+\def\xrdef #1#2{\xrdef3037,99945
+\def\readauxfile{\readauxfile3040,100030
+\def\supereject{\supereject3110,101811
+\footstrut\parindent=\defaultparindent\hang\textindent{aultparindent\hang\textindent3131,102496
+\def\openindices{\openindices3139,102682
+\newdimen\defaultparindent \defaultparindent = 15ptaultparindent3151,102907
+\parindent = \defaultparindentaultparindent3152,102959
+\def\smallbook{\smallbook3175,103683
+\global\def\Esmallexample{\Esmallexample3192,104110
+\def\afourpaper{\afourpaper3196,104201
+\def\finalout{\finalout3224,105009
+\def\normaldoublequote{\normaldoublequote3235,105270
+\def\normaltilde{\normaltilde3236,105296
+\def\normalcaret{\normalcaret3237,105316
+\def\normalunderscore{\normalunderscore3238,105336
+\def\normalverticalbar{\normalverticalbar3239,105361
+\def\normalless{\normalless3240,105387
+\def\normalgreater{\normalgreater3241,105406
+\def\normalplus{\normalplus3242,105428
+\def\ifusingtt#1#2{\ifusingtt3253,105920
+\def\activedoublequote{\activedoublequote3261,106248
+\def~{~3264,106334
+\def^{^3267,106395
+\def_{_3270,106434
+\def\_{\_3272,106508
+\def\lvvmode{\lvvmode3279,106845
+\def|{|3282,106895
+\def<{<3285,106958
+\def>{>3288,107015
+\def+{+3290,107053
+\def\turnoffactive{\turnoffactive3296,107214
+\global\def={=3307,107500
+\def\normalbackslash{\normalbackslash3321,107882
+
+merc-src/accumulator.m,4915
+:- interface146,5371
+:- import_module hlds148,5386
+:- import_module univ152,5478
+:- pred accu_transform_proc159,5793
+:- implementation166,6115
+:- import_module libs180,6552
+:- import_module mdbcomp184,6681
+:- import_module parse_tree186,6742
+:- import_module assoc_list194,7013
+:- import_module bool195,7042
+:- import_module int196,7065
+:- import_module io197,7087
+:- import_module list198,7108
+:- import_module map199,7131
+:- import_module maybe200,7153
+:- import_module pair201,7177
+:- import_module require202,7200
+:- import_module set203,7226
+:- import_module solutions204,7248
+:- import_module string205,7276
+:- import_module term206,7301
+:- import_module varset207,7324
+:- type top_level213,7499
+:- type accu_goal_id225,7900
+:- type accu_case228,7964
+:- type accu_goal_store234,8091
+:- type accu_subst238,8216
+:- type accu_warning240,8264
+accu_transform_proc247,8578
+:- pred generate_warnings334,12550
+generate_warnings337,12669
+:- pred generate_warning342,12895
+generate_warning345,13001
+:- pred should_attempt_accu_transform365,13886
+should_attempt_accu_transform370,14123
+:- pred should_attempt_accu_transform_2398,15406
+should_attempt_accu_transform_2405,15763
+:- pred accu_standardize440,17390
+accu_standardize442,17455
+:- pred identify_goal_type465,18169
+identify_goal_type469,18359
+:- pred is_recursive_case549,21175
+is_recursive_case551,21253
+:- type store_info560,21713
+:- func initialize_goal_store570,22060
+initialize_goal_store573,22166
+:- pred accu_store580,22421
+accu_store584,22576
+:- pred identify_recursive_calls601,23288
+identify_recursive_calls604,23406
+:- pred identify_out_and_out_prime626,24397
+identify_out_and_out_prime631,24632
+:- type accu_sets676,26426
+:- pred accu_stage1689,26978
+accu_stage1693,27156
+:- pred accu_stage1_2727,28348
+accu_stage1_2731,28516
+:- pred accu_sets_init781,30558
+accu_sets_init783,30606
+:- func set_upto796,30985
+set_upto798,31040
+:- pred accu_before812,31499
+accu_before815,31640
+:- pred accu_assoc835,32478
+accu_assoc838,32618
+:- pred accu_construct862,33713
+accu_construct865,33857
+:- pred accu_construct_assoc896,35308
+accu_construct_assoc899,35458
+:- pred accu_update938,37070
+accu_update941,37211
+:- pred member_lessthan_goalid964,38220
+member_lessthan_goalid967,38343
+:- type accu_assoc975,38653
+:- pred accu_is_associative986,39139
+accu_is_associative989,39251
+:- pred associativity_assertion1014,40264
+associativity_assertion1017,40405
+:- pred commutativity_assertion1037,41243
+commutativity_assertion1040,41370
+:- pred accu_is_update1057,41953
+accu_is_update1060,42067
+:- pred is_associative_construction1078,42803
+is_associative_construction1081,42899
+:- type accu_substs1095,43481
+:- type accu_base1103,43745
+:- pred accu_stage21124,44606
+accu_stage21131,44947
+:- pred accu_substs_init1179,46958
+accu_substs_init1182,47098
+:- pred acc_var_subst_init1194,47574
+acc_var_subst_init1198,47719
+:- pred create_new_var1207,48148
+create_new_var1210,48289
+:- pred accu_process_assoc_set1223,48863
+accu_process_assoc_set1229,49151
+:- pred accu_has_heuristic1297,52082
+accu_has_heuristic1299,52162
+:- pred accu_heuristic1304,52337
+accu_heuristic1307,52458
+:- pred accu_process_update_set1318,52907
+accu_process_update_set1325,53222
+:- pred accu_divide_base_case1380,55845
+accu_divide_base_case1385,56060
+:- pred accu_related1412,57147
+accu_related1415,57271
+:- inst stored_goal_plain_call1444,58416
+:- pred lookup_call1449,58602
+lookup_call1452,58716
+:- pred accu_stage31470,59433
+accu_stage31477,59827
+:- pred acc_proc_info1508,61327
+acc_proc_info1512,61486
+:- pred acc_pred_info1556,63450
+acc_pred_info1559,63598
+:- pred accu_create_goal1600,65286
+accu_create_goal1607,65629
+:- func create_acc_call1621,66401
+create_acc_call1625,66570
+:- pred create_orig_goal1634,66988
+create_orig_goal1638,67177
+:- pred create_acc_goal1662,68158
+create_acc_goal1667,68381
+:- func create_new_orig_recursive_goals1709,70226
+create_new_orig_recursive_goals1712,70369
+:- func create_new_recursive_goals1723,70919
+create_new_recursive_goals1727,71109
+:- func create_new_base_goals1738,71718
+create_new_base_goals1741,71832
+:- pred acc_unification1749,72157
+acc_unification1751,72226
+:- pred accu_top_level1766,72897
+accu_top_level1770,73059
+:- pred update_accumulator_pred1856,76291
+update_accumulator_pred1859,76412
+:- func accu_rename1876,77254
+accu_rename1879,77364
+:- func base_case_ids1889,77785
+base_case_ids1891,77847
+:- func base_case_ids_set1898,78049
+base_case_ids_set1900,78114
+:- func accu_goal_list1905,78270
+accu_goal_list1907,78350
+:- pred calculate_goal_info1916,78681
+calculate_goal_info1918,78754
+:- func chain_subst1932,79320
+chain_subst1934,79379
+:- pred chain_subst_21938,79483
+chain_subst_21941,79577
+:- some [T] pred unravel_univ1956,80061
+:- pragma foreign_export1957,80117
+unravel_univ1961,80341
c-src/c.c,76
T f(1,0
@@ -5160,13 +5315,13 @@ extern struct node *yylval;yylval306,6246
unsigned char parse_cell_or_range 309,6291
unsigned char parse_cell_or_range 311,6355
yylex FUN0(315,6405
-parse_cell_or_range FUN2(587,11771
-#define CK_ABS_R(671,13213
-#define CK_REL_R(675,13292
-#define CK_ABS_C(680,13421
-#define CK_REL_C(684,13500
-#define MAYBEREL(689,13629
-str_to_col FUN1(847,16830
+parse_cell_or_range FUN2(587,11772
+#define CK_ABS_R(671,13214
+#define CK_REL_R(675,13293
+#define CK_ABS_C(680,13422
+#define CK_REL_C(684,13501
+#define MAYBEREL(689,13630
+str_to_col FUN1(847,16831
y-src/parse.c,520
#define YYBISON 4,64
diff --git a/test/manual/etags/ETAGS.good_6 b/test/manual/etags/ETAGS.good_6
index a75fd806968..09abde35c51 100644
--- a/test/manual/etags/ETAGS.good_6
+++ b/test/manual/etags/ETAGS.good_6
@@ -175,7 +175,7 @@ package body Truc.Bidule Truc.Bidule/b138,2153
protected body Bidule Bidule/b139,2181
protected body Machin_T Machin_T/b146,2281
-c-src/abbrev.c,3274
+c-src/abbrev.c,3055
Lisp_Object Vabbrev_table_name_list;43,1429
Lisp_Object Vglobal_abbrev_table;48,1574
Lisp_Object Vfundamental_mode_abbrev_table;52,1685
@@ -186,57 +186,53 @@ Lisp_Object Vabbrev_start_location_buffer;66,2046
Lisp_Object Vlast_abbrev;70,2155
Lisp_Object Vlast_abbrev_text;75,2324
int last_abbrev_point;79,2414
-Lisp_Object Vpre_abbrev_expand_hook,83,2487
-Lisp_Object Vpre_abbrev_expand_hook, Qpre_abbrev_expand_hook;83,2487
-DEFUN ("make-abbrev-table", Fmake_abbrev_table,85,2551
-DEFUN ("make-abbrev-table", Fmake_abbrev_table,make-abbrev-table85,2551
-DEFUN ("clear-abbrev-table", Fclear_abbrev_table,92,2743
-DEFUN ("clear-abbrev-table", Fclear_abbrev_table,clear-abbrev-table92,2743
-DEFUN ("define-abbrev", Fdefine_abbrev,107,3124
-DEFUN ("define-abbrev", Fdefine_abbrev,define-abbrev107,3124
-DEFUN ("define-global-abbrev", Fdefine_global_abbrev,149,4443
-DEFUN ("define-global-abbrev", Fdefine_global_abbrev,define-global-abbrev149,4443
-DEFUN ("define-mode-abbrev", Fdefine_mode_abbrev,160,4814
-DEFUN ("define-mode-abbrev", Fdefine_mode_abbrev,define-mode-abbrev160,4814
-DEFUN ("abbrev-symbol", Fabbrev_symbol,174,5282
-DEFUN ("abbrev-symbol", Fabbrev_symbol,abbrev-symbol174,5282
-DEFUN ("abbrev-expansion", Fabbrev_expansion,202,6246
-DEFUN ("abbrev-expansion", Fabbrev_expansion,abbrev-expansion202,6246
-DEFUN ("expand-abbrev", Fexpand_abbrev,218,6761
-DEFUN ("expand-abbrev", Fexpand_abbrev,expand-abbrev218,6761
-DEFUN ("unexpand-abbrev", Funexpand_abbrev,389,11682
-DEFUN ("unexpand-abbrev", Funexpand_abbrev,unexpand-abbrev389,11682
-write_abbrev 426,12889
-describe_abbrev 445,13324
-DEFUN ("insert-abbrev-table-description", Finsert_abbrev_table_description,466,13839
-DEFUN ("insert-abbrev-table-description", Finsert_abbrev_table_description,insert-abbrev-table-description466,13839
-DEFUN ("define-abbrev-table", Fdefine_abbrev_table,506,14995
-DEFUN ("define-abbrev-table", Fdefine_abbrev_table,define-abbrev-table506,14995
-syms_of_abbrev 540,16072
- DEFVAR_LISP ("abbrev-table-name-list"542,16092
- DEFVAR_LISP ("global-abbrev-table"548,16354
- DEFVAR_LISP ("fundamental-mode-abbrev-table"555,16676
- DEFVAR_LISP ("last-abbrev"561,17018
- DEFVAR_LISP ("last-abbrev-text"564,17141
- DEFVAR_INT ("last-abbrev-location"568,17299
- DEFVAR_LISP ("abbrev-start-location"575,17498
- DEFVAR_LISP ("abbrev-start-location-buffer"581,17775
- DEFVAR_PER_BUFFER ("local-abbrev-table"586,18039
- DEFVAR_BOOL ("abbrevs-changed"589,18182
- DEFVAR_BOOL ("abbrev-all-caps"594,18385
- DEFVAR_LISP ("pre-abbrev-expand-hook"598,18541
- DEFVAR_LISP ("abbrev-table-name-list",\1542,16092
- DEFVAR_LISP ("global-abbrev-table",\1548,16354
- DEFVAR_LISP ("fundamental-mode-abbrev-table",\1555,16676
- DEFVAR_LISP ("last-abbrev",\1561,17018
- DEFVAR_LISP ("last-abbrev-text",\1564,17141
- DEFVAR_INT ("last-abbrev-location",\1568,17299
- DEFVAR_LISP ("abbrev-start-location",\1575,17498
- DEFVAR_LISP ("abbrev-start-location-buffer",\1581,17775
- DEFVAR_PER_BUFFER ("local-abbrev-table",\1586,18039
- DEFVAR_BOOL ("abbrevs-changed",\1589,18182
- DEFVAR_BOOL ("abbrev-all-caps",\1594,18385
- DEFVAR_LISP ("pre-abbrev-expand-hook",\1598,18541
+DEFUN ("make-abbrev-table", Fmake_abbrev_table,82,2440
+DEFUN ("make-abbrev-table", Fmake_abbrev_table,make-abbrev-table82,2440
+DEFUN ("clear-abbrev-table", Fclear_abbrev_table,89,2632
+DEFUN ("clear-abbrev-table", Fclear_abbrev_table,clear-abbrev-table89,2632
+DEFUN ("define-abbrev", Fdefine_abbrev,104,3013
+DEFUN ("define-abbrev", Fdefine_abbrev,define-abbrev104,3013
+DEFUN ("define-global-abbrev", Fdefine_global_abbrev,146,4332
+DEFUN ("define-global-abbrev", Fdefine_global_abbrev,define-global-abbrev146,4332
+DEFUN ("define-mode-abbrev", Fdefine_mode_abbrev,157,4703
+DEFUN ("define-mode-abbrev", Fdefine_mode_abbrev,define-mode-abbrev157,4703
+DEFUN ("abbrev-symbol", Fabbrev_symbol,171,5171
+DEFUN ("abbrev-symbol", Fabbrev_symbol,abbrev-symbol171,5171
+DEFUN ("abbrev-expansion", Fabbrev_expansion,199,6135
+DEFUN ("abbrev-expansion", Fabbrev_expansion,abbrev-expansion199,6135
+DEFUN ("expand-abbrev", Fexpand_abbrev,215,6650
+DEFUN ("expand-abbrev", Fexpand_abbrev,expand-abbrev215,6650
+DEFUN ("unexpand-abbrev", Funexpand_abbrev,383,11495
+DEFUN ("unexpand-abbrev", Funexpand_abbrev,unexpand-abbrev383,11495
+write_abbrev 420,12702
+describe_abbrev 439,13137
+DEFUN ("insert-abbrev-table-description", Finsert_abbrev_table_description,460,13652
+DEFUN ("insert-abbrev-table-description", Finsert_abbrev_table_description,insert-abbrev-table-description460,13652
+DEFUN ("define-abbrev-table", Fdefine_abbrev_table,500,14808
+DEFUN ("define-abbrev-table", Fdefine_abbrev_table,define-abbrev-table500,14808
+syms_of_abbrev 534,15885
+ DEFVAR_LISP ("abbrev-table-name-list"536,15905
+ DEFVAR_LISP ("global-abbrev-table"542,16167
+ DEFVAR_LISP ("fundamental-mode-abbrev-table"549,16489
+ DEFVAR_LISP ("last-abbrev"555,16831
+ DEFVAR_LISP ("last-abbrev-text"558,16954
+ DEFVAR_INT ("last-abbrev-location"562,17112
+ DEFVAR_LISP ("abbrev-start-location"569,17311
+ DEFVAR_LISP ("abbrev-start-location-buffer"575,17588
+ DEFVAR_PER_BUFFER ("local-abbrev-table"580,17852
+ DEFVAR_BOOL ("abbrevs-changed"583,17995
+ DEFVAR_BOOL ("abbrev-all-caps"588,18198
+ DEFVAR_LISP ("abbrev-table-name-list",\1536,15905
+ DEFVAR_LISP ("global-abbrev-table",\1542,16167
+ DEFVAR_LISP ("fundamental-mode-abbrev-table",\1549,16489
+ DEFVAR_LISP ("last-abbrev",\1555,16831
+ DEFVAR_LISP ("last-abbrev-text",\1558,16954
+ DEFVAR_INT ("last-abbrev-location",\1562,17112
+ DEFVAR_LISP ("abbrev-start-location",\1569,17311
+ DEFVAR_LISP ("abbrev-start-location-buffer",\1575,17588
+ DEFVAR_PER_BUFFER ("local-abbrev-table",\1580,17852
+ DEFVAR_BOOL ("abbrevs-changed",\1583,17995
+ DEFVAR_BOOL ("abbrev-all-caps",\1588,18198
c-src/torture.c,197
(*tag1 tag118,452
@@ -276,439 +272,439 @@ extern int getopt_long_only 116,4187
extern int _getopt_internal 118,4220
c-src/etags.c,14175
-char pot_etags_version[pot_etags_version81,3470
-# undef DEBUG84,3552
-# define DEBUG 85,3567
-# define DEBUG 87,3594
-# define NDEBUG 88,3617
-# define _GNU_SOURCE 94,3705
-# undef MSDOS100,3876
-# undef WINDOWSNT101,3890
-# define WINDOWSNT102,3909
-# undef MSDOS106,3968
-# define MSDOS 107,3982
-# define MSDOS 110,4032
-# define MAXPATHLEN 115,4111
-# undef HAVE_NTGUI116,4141
-# undef DOS_NT117,4160
-# define DOS_NT118,4176
-# undef assert 135,4482
-# define assert(136,4541
-# undef CTAGS146,4857
-# define CTAGS 147,4872
-# define CTAGS 149,4898
-#define streq(152,4927
-#define strcaseeq(153,4996
-#define strneq(154,5075
-#define strncaseeq(155,5151
-#define CHARS 157,5238
-#define CHAR(158,5278
-#define iswhite(159,5329
-#define notinname(160,5394
-#define begtoken(161,5469
-#define intoken(162,5542
-#define endtoken(163,5614
-#define ISALNUM(165,5684
-#define ISALPHA(166,5722
-#define ISDIGIT(167,5760
-#define ISLOWER(168,5798
-#define lowcase(170,5837
-#define xnew(179,6015
-#define xrnew(180,6083
-typedef void Lang_function 182,6164
- const char *suffix;suffix186,6219
- const char *command;command187,6294
-} compressor;188,6365
- const char *name;name192,6397
- const char *help;help193,6449
- Lang_function *function;function194,6508
- const char **suffixes;suffixes195,6556
- const char **filenames;filenames196,6633
- const char **interpreters;interpreters197,6702
- bool metasource;198,6771
-} language;199,6835
-typedef struct fdesc201,6848
- struct fdesc *next;next203,6871
- char *infname;infname204,6920
- char *infabsname;infabsname205,6973
- char *infabsdir;infabsdir206,7038
- char *taggedfname;taggedfname207,7091
- language *lang;lang208,7149
- char *prop;prop209,7191
- bool usecharno;210,7249
- bool written;211,7311
-} fdesc;212,7366
-typedef struct node_st214,7376
- struct node_st *left,left216,7428
- struct node_st *left, *right;right216,7428
- fdesc *fdp;fdp217,7486
- char *name;name218,7548
- char *regex;regex219,7580
- bool valid;220,7617
- bool is_func;221,7670
- bool been_warned;222,7733
- int lno;223,7801
- long cno;224,7842
-} node;225,7894
- long size;236,8208
- int len;237,8221
- char *buffer;buffer238,8232
-} linebuffer;239,8248
- at_language,245,8344
- at_regexp,246,8393
- at_filename,247,8437
- at_stdin,248,8473
- at_end 249,8516
- } arg_type;250,8557
- language *lang;lang251,8593
- char *what;what252,8656
-} argument;253,8698
-typedef struct regexp256,8758
- struct regexp *p_next;p_next258,8782
- language *lang;lang259,8837
- char *pattern;pattern260,8897
- char *name;name261,8940
- struct re_pattern_buffer *pat;pat262,8971
- struct re_registers regs;263,9031
- bool error_signaled;264,9078
- bool force_explicit_name;265,9141
- bool ignore_case;266,9206
- bool multi_line;267,9259
-} regexp;268,9325
-static void Ada_funcs 274,9428
-static void Asm_labels 275,9460
-static void C_entries 276,9493
-static void default_C_entries 277,9536
-static void plain_C_entries 278,9576
-static void Cjava_entries 279,9614
-static void Cobol_paragraphs 280,9650
-static void Cplusplus_entries 281,9689
-static void Cstar_entries 282,9729
-static void Erlang_functions 283,9765
-static void Forth_words 284,9804
-static void Fortran_functions 285,9838
-static void HTML_labels 286,9878
-static void Lisp_functions 287,9912
-static void Lua_functions 288,9949
-static void Makefile_targets 289,9985
-static void Pascal_functions 290,10024
-static void Perl_functions 291,10063
-static void PHP_functions 292,10100
-static void PS_functions 293,10136
-static void Prolog_functions 294,10171
-static void Python_functions 295,10210
-static void Scheme_functions 296,10249
-static void TeX_commands 297,10288
-static void Texinfo_nodes 298,10323
-static void Yacc_entries 299,10359
-static void just_read_file 300,10394
-static language *get_language_from_langname get_language_from_langname302,10432
-static void readline 303,10492
-static long readline_internal 304,10537
-static bool nocase_tail 305,10591
-static void get_tag 306,10631
-static void analyze_regex 308,10671
-static void free_regexps 309,10707
-static void regex_tag_multiline 310,10740
-static void error 311,10780
-# undef STDIN408,15073
-#define STDIN 411,15095
-static compressor compressors[compressors457,17664
-static const char *Ada_suffixes Ada_suffixes473,17907
-static const char Ada_help 475,17977
-static const char *Asm_suffixes Asm_suffixes493,18580
-static const char Asm_help 504,18976
-static const char *default_C_suffixes default_C_suffixes512,19312
-static const char default_C_help 515,19413
-static const char default_C_help 523,19850
-static const char *Cplusplus_suffixes Cplusplus_suffixes535,20460
-static const char Cplusplus_help 540,20658
-static const char *Cjava_suffixes Cjava_suffixes549,21113
-static char Cjava_help 551,21172
-static const char *Cobol_suffixes Cobol_suffixes556,21337
-static char Cobol_help 558,21402
-static const char *Cstar_suffixes Cstar_suffixes562,21543
-static const char *Erlang_suffixes Erlang_suffixes565,21607
-static const char Erlang_help 567,21673
-const char *Forth_suffixes Forth_suffixes571,21799
-static const char Forth_help 573,21857
-static const char *Fortran_suffixes Fortran_suffixes577,22008
-static const char Fortran_help 579,22085
-static const char *HTML_suffixes HTML_suffixes582,22190
-static const char HTML_help 584,22264
-static const char *Lisp_suffixes Lisp_suffixes589,22452
-static const char Lisp_help 591,22556
-static const char *Lua_suffixes Lua_suffixes598,22871
-static const char Lua_help 600,22934
-static const char *Makefile_filenames Makefile_filenames603,23010
-static const char Makefile_help 605,23133
-static const char *Objc_suffixes Objc_suffixes609,23277
-static const char Objc_help 613,23399
-static const char *Pascal_suffixes Pascal_suffixes619,23714
-static const char Pascal_help 621,23778
-static const char *Perl_suffixes Perl_suffixes626,23966
-static const char *Perl_interpreters Perl_interpreters628,24028
-static const char Perl_help 630,24100
-static const char *PHP_suffixes PHP_suffixes637,24451
-static const char PHP_help 639,24523
-static const char *plain_C_suffixes plain_C_suffixes643,24678
-static const char *PS_suffixes PS_suffixes647,24762
-static const char PS_help 649,24848
-static const char *Prolog_suffixes Prolog_suffixes652,24931
-static const char Prolog_help 654,24993
-static const char *Python_suffixes Python_suffixes658,25107
-static const char Python_help 660,25165
-static const char *Scheme_suffixes Scheme_suffixes665,25347
-static const char Scheme_help 667,25460
-static const char *TeX_suffixes TeX_suffixes672,25683
-static const char TeX_help 674,25781
-static const char *Texinfo_suffixes Texinfo_suffixes686,26316
-static const char Texinfo_help 688,26395
-static const char *Yacc_suffixes Yacc_suffixes691,26492
-static const char Yacc_help 693,26606
-static const char auto_help 699,26856
-static const char none_help 703,27020
-static const char no_lang_help 707,27143
-static language lang_names 718,27355
-print_language_names 753,29532
-# define EMACS_NAME 786,30755
-# define VERSION 789,30811
-print_version 792,30869
-# define PRINT_UNDOCUMENTED_OPTIONS_HELP 804,31173
-print_help 808,31250
-main 981,37438
-get_compressor_from_suffix 1319,46217
-get_language_from_langname 1355,47158
-get_language_from_interpreter 1377,47545
-get_language_from_filename 1399,47976
-process_file_name 1433,48834
-process_file 1555,51665
-init 1632,54150
-find_entries 1656,54901
-make_tag 1814,59707
-pfnote 1856,60942
-free_tree 1917,62744
-free_fdesc 1935,63029
-add_node 1955,63472
-invalidate_nodes 2035,65537
-static int total_size_of_entries 2067,66150
-static int number_len 2068,66193
-total_size_of_entries 2087,66694
-put_entries 2107,67154
-#define C_EXT 2193,68995
-#define C_PLAIN 2194,69037
-#define C_PLPL 2195,69070
-#define C_STAR 2196,69104
-#define C_JAVA 2197,69137
-#define C_AUTO 2198,69172
-#define YACC 2199,69242
-enum sym_type2204,69312
- st_none,2206,69328
- st_C_objprot,2207,69339
- st_C_objprot, st_C_objimpl,2207,69339
- st_C_objprot, st_C_objimpl, st_C_objend,2207,69339
- st_C_gnumacro,2208,69382
- st_C_ignore,2209,69399
- st_C_ignore, st_C_attribute,2209,69399
- st_C_javastruct,2210,69430
- st_C_operator,2211,69449
- st_C_class,2212,69466
- st_C_class, st_C_template,2212,69466
- st_C_struct,2213,69495
- st_C_struct, st_C_extern,2213,69495
- st_C_struct, st_C_extern, st_C_enum,2213,69495
- st_C_struct, st_C_extern, st_C_enum, st_C_define,2213,69495
- st_C_struct, st_C_extern, st_C_enum, st_C_define, st_C_typedef2213,69495
-struct C_stab_entry 2271,71278
-struct C_stab_entry { const char *name;name2271,71278
-struct C_stab_entry { const char *name; int c_ext;2271,71278
-struct C_stab_entry { const char *name; int c_ext; enum sym_type type;2271,71278
-hash 2275,71409
-in_word_set 2321,72937
- TOTAL_KEYWORDS 2325,73018
- MIN_WORD_LENGTH 2326,73045
- MAX_WORD_LENGTH 2327,73072
- MIN_HASH_VALUE 2328,73100
- MAX_HASH_VALUE 2329,73126
-C_symtype 2387,74985
-static bool inattribute;2400,75234
- fvnone,2408,75435
- fdefunkey,2409,75466
- fdefunname,2410,75512
- foperator,2411,75556
- fvnameseen,2412,75613
- fstartlist,2413,75666
- finlist,2414,75722
- flistseen,2415,75765
- fignore,2416,75813
- vignore 2417,75856
-} fvdef;2418,75901
-static bool fvextern;2420,75911
- tnone,2428,76089
- tkeyseen,2429,76119
- ttypeseen,2430,76160
- tinbody,2431,76199
- tend,2432,76238
- tignore 2433,76279
-} typdef;2434,76320
- snone,2443,76499
- skeyseen,2445,76575
- stagseen,2446,76620
- scolonseen 2447,76661
-} structdef;2448,76715
-static const char *objtag objtag2453,76809
- dnone,2460,76942
- dsharpseen,2461,76972
- ddefineseen,2462,77025
- dignorerest 2463,77070
-} definedef;2464,77112
- onone,2472,77267
- oprotocol,2473,77297
- oimplementation,2474,77347
- otagseen,2475,77395
- oparenseen,2476,77431
- ocatseen,2477,77486
- oinbody,2478,77525
- omethodsign,2479,77568
- omethodtag,2480,77626
- omethodcolon,2481,77666
- omethodparm,2482,77709
- oignore 2483,77755
-} objdef;2484,77787
-static struct tok2491,77944
- char *line;line2493,77964
- int offset;2494,78014
- int length;2495,78067
- bool valid;2502,78352
- bool named;2505,78487
- int lineno;2506,78528
- long linepos;2507,78576
-} token;2508,78626
-static void pushclass_above 2514,78784
-static void popclass_above 2515,78832
-static void write_classname 2516,78866
- char **cname;cname2519,78950
- int *bracelev;bracelev2520,78993
- int nl;2521,79042
- int size;2522,79096
-} cstack;2523,79136
-#define nestlev 2525,79264
-#define instruct 2527,79369
-pushclass_above 2531,79489
-popclass_above 2550,79948
-write_classname 2564,80162
-static bool consider_token 2592,80761
-static void make_C_tag 2593,80833
-consider_token 2613,81341
- long linepos;2922,88499
- linebuffer lb;2923,88515
-} lbs[lbs2924,88532
-#define current_lb_is_new 2926,88543
-#define switch_line_buffers(2927,88588
-#define curlb 2929,88641
-#define newlb 2930,88672
-#define curlinepos 2931,88703
-#define newlinepos 2932,88744
-#define plainc 2934,88786
-#define cplpl 2935,88830
-#define cjava 2936,88861
-#define CNL_SAVE_DEFINEDEF(2938,88905
-#define CNL(2947,89117
-make_C_tag 2960,89375
-C_entries 2986,90194
-default_C_entries 3833,110156
-plain_C_entries 3840,110276
-Cplusplus_entries 3847,110364
-Cjava_entries 3854,110460
-Cstar_entries 3861,110550
-Yacc_entries 3868,110642
-#define LOOP_ON_INPUT_LINES(3875,110720
-#define LOOKING_AT(3884,111056
-#define LOOKING_AT_NOCASE(3891,111461
-just_read_file 3901,111861
-static void F_takeprec 3910,111965
-static void F_getit 3911,111996
-F_takeprec 3914,112039
-F_getit 3937,112366
-Fortran_functions 3961,112840
-Ada_getit 4052,114669
-Ada_funcs 4115,116044
-Asm_labels 4228,118582
-Perl_functions 4261,119549
-Python_functions 4357,122057
-PHP_functions 4387,122684
-Cobol_paragraphs 4466,124471
-Makefile_targets 4494,125029
-Pascal_functions 4529,125950
-static void L_getit 4706,130277
-L_getit 4709,130318
-Lisp_functions 4725,130664
-Lua_functions 4785,131850
-PS_functions 4811,132385
-Forth_words 4841,133053
-Scheme_functions 4877,134092
-static linebuffer *TEX_toktab TEX_toktab4908,134781
-static const char *TEX_defenv TEX_defenv4912,134974
-static void TEX_mode 4917,135172
-static void TEX_decode_env 4918,135203
-static char TEX_esc 4920,135261
-static char TEX_opgrp 4921,135289
-static char TEX_clgrp 4922,135318
-TeX_commands 4928,135395
-#define TEX_LESC 4986,136652
-#define TEX_SESC 4987,136674
-TEX_mode 4992,136804
-TEX_decode_env 5026,137509
-Texinfo_nodes 5071,138554
-HTML_labels 5094,139013
-static size_t prolog_pr 5214,142192
-static void prolog_skip_comment 5215,142234
-static size_t prolog_atom 5216,142290
-Prolog_functions 5219,142347
-prolog_skip_comment 5255,143128
-prolog_pr 5281,143736
-prolog_atom 5319,144628
-static int erlang_func 5374,145540
-static void erlang_attribute 5375,145581
-static int erlang_atom 5376,145620
-Erlang_functions 5379,145666
-erlang_func 5438,146965
-erlang_attribute 5476,147642
-erlang_atom 5496,148061
-static char *scan_separators scan_separators5520,148487
-static void add_regex 5521,148526
-static char *substitute substitute5522,148570
-scan_separators 5534,149080
-analyze_regex 5586,150460
-add_regex 5654,152050
-substitute 5767,154797
-free_regexps 5814,155837
-regex_tag_multiline 5836,156291
-nocase_tail 5913,158263
-get_tag 5928,158519
-readline_internal 5959,159455
-readline 6037,161296
-savestr 6230,167243
-savenstr 6240,167473
-skip_spaces 6249,167679
-skip_non_spaces 6258,167833
-skip_name 6267,167983
-fatal 6277,168156
-pfatal 6284,168253
-suggest_asking_for_help 6291,168332
-error 6300,168554
-concat 6313,168846
-etags_getcwd 6329,169259
-relative_filename 6350,169725
-absolute_filename 6389,170751
-absolute_dirname 6453,172416
-filename_is_absolute 6472,172845
-canonicalize_filename 6484,173096
-# define ISUPPER(6491,173235
-linebuffer_init 6514,173656
-linebuffer_setlen 6524,173887
-xmalloc 6536,174148
-xrealloc 6545,174314
+char pot_etags_version[pot_etags_version81,3471
+# undef DEBUG84,3553
+# define DEBUG 85,3568
+# define DEBUG 87,3595
+# define NDEBUG 88,3618
+# define _GNU_SOURCE 94,3706
+# undef MSDOS100,3877
+# undef WINDOWSNT101,3891
+# define WINDOWSNT102,3910
+# undef MSDOS106,3969
+# define MSDOS 107,3983
+# define MSDOS 110,4033
+# define MAXPATHLEN 115,4112
+# undef HAVE_NTGUI116,4142
+# undef DOS_NT117,4161
+# define DOS_NT118,4177
+# undef assert 135,4483
+# define assert(136,4542
+# undef CTAGS146,4858
+# define CTAGS 147,4873
+# define CTAGS 149,4899
+#define streq(152,4928
+#define strcaseeq(153,4997
+#define strneq(154,5076
+#define strncaseeq(155,5152
+#define CHARS 157,5239
+#define CHAR(158,5279
+#define iswhite(159,5330
+#define notinname(160,5395
+#define begtoken(161,5470
+#define intoken(162,5543
+#define endtoken(163,5615
+#define ISALNUM(165,5685
+#define ISALPHA(166,5723
+#define ISDIGIT(167,5761
+#define ISLOWER(168,5799
+#define lowcase(170,5838
+#define xnew(179,6016
+#define xrnew(180,6084
+typedef void Lang_function 182,6165
+ const char *suffix;suffix186,6220
+ const char *command;command187,6295
+} compressor;188,6366
+ const char *name;name192,6398
+ const char *help;help193,6450
+ Lang_function *function;function194,6509
+ const char **suffixes;suffixes195,6557
+ const char **filenames;filenames196,6634
+ const char **interpreters;interpreters197,6703
+ bool metasource;198,6772
+} language;199,6836
+typedef struct fdesc201,6849
+ struct fdesc *next;next203,6872
+ char *infname;infname204,6921
+ char *infabsname;infabsname205,6974
+ char *infabsdir;infabsdir206,7039
+ char *taggedfname;taggedfname207,7092
+ language *lang;lang208,7150
+ char *prop;prop209,7192
+ bool usecharno;210,7250
+ bool written;211,7312
+} fdesc;212,7367
+typedef struct node_st214,7377
+ struct node_st *left,left216,7429
+ struct node_st *left, *right;right216,7429
+ fdesc *fdp;fdp217,7487
+ char *name;name218,7549
+ char *regex;regex219,7581
+ bool valid;220,7618
+ bool is_func;221,7671
+ bool been_warned;222,7734
+ int lno;223,7802
+ long cno;224,7843
+} node;225,7895
+ long size;236,8209
+ int len;237,8222
+ char *buffer;buffer238,8233
+} linebuffer;239,8249
+ at_language,245,8345
+ at_regexp,246,8394
+ at_filename,247,8438
+ at_stdin,248,8474
+ at_end 249,8517
+ } arg_type;250,8558
+ language *lang;lang251,8594
+ char *what;what252,8657
+} argument;253,8699
+typedef struct regexp256,8759
+ struct regexp *p_next;p_next258,8783
+ language *lang;lang259,8838
+ char *pattern;pattern260,8898
+ char *name;name261,8941
+ struct re_pattern_buffer *pat;pat262,8972
+ struct re_registers regs;263,9032
+ bool error_signaled;264,9079
+ bool force_explicit_name;265,9142
+ bool ignore_case;266,9207
+ bool multi_line;267,9260
+} regexp;268,9326
+static void Ada_funcs 274,9429
+static void Asm_labels 275,9461
+static void C_entries 276,9494
+static void default_C_entries 277,9537
+static void plain_C_entries 278,9577
+static void Cjava_entries 279,9615
+static void Cobol_paragraphs 280,9651
+static void Cplusplus_entries 281,9690
+static void Cstar_entries 282,9730
+static void Erlang_functions 283,9766
+static void Forth_words 284,9805
+static void Fortran_functions 285,9839
+static void HTML_labels 286,9879
+static void Lisp_functions 287,9913
+static void Lua_functions 288,9950
+static void Makefile_targets 289,9986
+static void Pascal_functions 290,10025
+static void Perl_functions 291,10064
+static void PHP_functions 292,10101
+static void PS_functions 293,10137
+static void Prolog_functions 294,10172
+static void Python_functions 295,10211
+static void Scheme_functions 296,10250
+static void TeX_commands 297,10289
+static void Texinfo_nodes 298,10324
+static void Yacc_entries 299,10360
+static void just_read_file 300,10395
+static language *get_language_from_langname get_language_from_langname302,10433
+static void readline 303,10493
+static long readline_internal 304,10538
+static bool nocase_tail 305,10592
+static void get_tag 306,10632
+static void analyze_regex 308,10672
+static void free_regexps 309,10708
+static void regex_tag_multiline 310,10741
+static void error 311,10781
+# undef STDIN408,15074
+#define STDIN 411,15096
+static compressor compressors[compressors457,17665
+static const char *Ada_suffixes Ada_suffixes473,17908
+static const char Ada_help 475,17978
+static const char *Asm_suffixes Asm_suffixes493,18581
+static const char Asm_help 504,18977
+static const char *default_C_suffixes default_C_suffixes512,19313
+static const char default_C_help 515,19414
+static const char default_C_help 523,19851
+static const char *Cplusplus_suffixes Cplusplus_suffixes535,20461
+static const char Cplusplus_help 540,20659
+static const char *Cjava_suffixes Cjava_suffixes549,21114
+static char Cjava_help 551,21173
+static const char *Cobol_suffixes Cobol_suffixes556,21338
+static char Cobol_help 558,21403
+static const char *Cstar_suffixes Cstar_suffixes562,21544
+static const char *Erlang_suffixes Erlang_suffixes565,21608
+static const char Erlang_help 567,21674
+const char *Forth_suffixes Forth_suffixes571,21800
+static const char Forth_help 573,21858
+static const char *Fortran_suffixes Fortran_suffixes577,22009
+static const char Fortran_help 579,22086
+static const char *HTML_suffixes HTML_suffixes582,22191
+static const char HTML_help 584,22265
+static const char *Lisp_suffixes Lisp_suffixes589,22453
+static const char Lisp_help 591,22557
+static const char *Lua_suffixes Lua_suffixes598,22872
+static const char Lua_help 600,22935
+static const char *Makefile_filenames Makefile_filenames603,23011
+static const char Makefile_help 605,23134
+static const char *Objc_suffixes Objc_suffixes609,23278
+static const char Objc_help 613,23400
+static const char *Pascal_suffixes Pascal_suffixes619,23715
+static const char Pascal_help 621,23779
+static const char *Perl_suffixes Perl_suffixes626,23967
+static const char *Perl_interpreters Perl_interpreters628,24029
+static const char Perl_help 630,24101
+static const char *PHP_suffixes PHP_suffixes637,24452
+static const char PHP_help 639,24524
+static const char *plain_C_suffixes plain_C_suffixes643,24679
+static const char *PS_suffixes PS_suffixes647,24763
+static const char PS_help 649,24849
+static const char *Prolog_suffixes Prolog_suffixes652,24932
+static const char Prolog_help 654,24994
+static const char *Python_suffixes Python_suffixes658,25108
+static const char Python_help 660,25166
+static const char *Scheme_suffixes Scheme_suffixes665,25348
+static const char Scheme_help 667,25461
+static const char *TeX_suffixes TeX_suffixes672,25684
+static const char TeX_help 674,25782
+static const char *Texinfo_suffixes Texinfo_suffixes686,26317
+static const char Texinfo_help 688,26396
+static const char *Yacc_suffixes Yacc_suffixes691,26493
+static const char Yacc_help 693,26607
+static const char auto_help 699,26857
+static const char none_help 703,27021
+static const char no_lang_help 707,27144
+static language lang_names 718,27356
+print_language_names 753,29533
+# define EMACS_NAME 786,30756
+# define VERSION 789,30812
+print_version 792,30870
+# define PRINT_UNDOCUMENTED_OPTIONS_HELP 804,31174
+print_help 808,31251
+main 981,37439
+get_compressor_from_suffix 1319,46218
+get_language_from_langname 1355,47159
+get_language_from_interpreter 1377,47546
+get_language_from_filename 1399,47977
+process_file_name 1433,48835
+process_file 1555,51666
+init 1632,54151
+find_entries 1656,54902
+make_tag 1814,59708
+pfnote 1856,60943
+free_tree 1917,62745
+free_fdesc 1935,63030
+add_node 1955,63473
+invalidate_nodes 2035,65538
+static int total_size_of_entries 2067,66151
+static int number_len 2068,66194
+total_size_of_entries 2087,66695
+put_entries 2107,67155
+#define C_EXT 2193,68996
+#define C_PLAIN 2194,69038
+#define C_PLPL 2195,69071
+#define C_STAR 2196,69105
+#define C_JAVA 2197,69138
+#define C_AUTO 2198,69173
+#define YACC 2199,69243
+enum sym_type2204,69313
+ st_none,2206,69329
+ st_C_objprot,2207,69340
+ st_C_objprot, st_C_objimpl,2207,69340
+ st_C_objprot, st_C_objimpl, st_C_objend,2207,69340
+ st_C_gnumacro,2208,69383
+ st_C_ignore,2209,69400
+ st_C_ignore, st_C_attribute,2209,69400
+ st_C_javastruct,2210,69431
+ st_C_operator,2211,69450
+ st_C_class,2212,69467
+ st_C_class, st_C_template,2212,69467
+ st_C_struct,2213,69496
+ st_C_struct, st_C_extern,2213,69496
+ st_C_struct, st_C_extern, st_C_enum,2213,69496
+ st_C_struct, st_C_extern, st_C_enum, st_C_define,2213,69496
+ st_C_struct, st_C_extern, st_C_enum, st_C_define, st_C_typedef2213,69496
+struct C_stab_entry 2271,71279
+struct C_stab_entry { const char *name;name2271,71279
+struct C_stab_entry { const char *name; int c_ext;2271,71279
+struct C_stab_entry { const char *name; int c_ext; enum sym_type type;2271,71279
+hash 2275,71410
+in_word_set 2321,72938
+ TOTAL_KEYWORDS 2325,73019
+ MIN_WORD_LENGTH 2326,73046
+ MAX_WORD_LENGTH 2327,73073
+ MIN_HASH_VALUE 2328,73101
+ MAX_HASH_VALUE 2329,73127
+C_symtype 2387,74986
+static bool inattribute;2400,75235
+ fvnone,2408,75436
+ fdefunkey,2409,75467
+ fdefunname,2410,75513
+ foperator,2411,75557
+ fvnameseen,2412,75614
+ fstartlist,2413,75667
+ finlist,2414,75723
+ flistseen,2415,75766
+ fignore,2416,75814
+ vignore 2417,75857
+} fvdef;2418,75902
+static bool fvextern;2420,75912
+ tnone,2428,76090
+ tkeyseen,2429,76120
+ ttypeseen,2430,76161
+ tinbody,2431,76200
+ tend,2432,76239
+ tignore 2433,76280
+} typdef;2434,76321
+ snone,2443,76500
+ skeyseen,2445,76576
+ stagseen,2446,76621
+ scolonseen 2447,76662
+} structdef;2448,76716
+static const char *objtag objtag2453,76810
+ dnone,2460,76943
+ dsharpseen,2461,76973
+ ddefineseen,2462,77026
+ dignorerest 2463,77071
+} definedef;2464,77113
+ onone,2472,77268
+ oprotocol,2473,77298
+ oimplementation,2474,77348
+ otagseen,2475,77396
+ oparenseen,2476,77432
+ ocatseen,2477,77487
+ oinbody,2478,77526
+ omethodsign,2479,77569
+ omethodtag,2480,77627
+ omethodcolon,2481,77667
+ omethodparm,2482,77710
+ oignore 2483,77756
+} objdef;2484,77788
+static struct tok2491,77945
+ char *line;line2493,77965
+ int offset;2494,78015
+ int length;2495,78068
+ bool valid;2502,78353
+ bool named;2505,78488
+ int lineno;2506,78529
+ long linepos;2507,78577
+} token;2508,78627
+static void pushclass_above 2514,78785
+static void popclass_above 2515,78833
+static void write_classname 2516,78867
+ char **cname;cname2519,78951
+ int *bracelev;bracelev2520,78994
+ int nl;2521,79043
+ int size;2522,79097
+} cstack;2523,79137
+#define nestlev 2525,79265
+#define instruct 2527,79370
+pushclass_above 2531,79490
+popclass_above 2550,79949
+write_classname 2564,80163
+static bool consider_token 2592,80762
+static void make_C_tag 2593,80834
+consider_token 2613,81342
+ long linepos;2922,88500
+ linebuffer lb;2923,88516
+} lbs[lbs2924,88533
+#define current_lb_is_new 2926,88544
+#define switch_line_buffers(2927,88589
+#define curlb 2929,88642
+#define newlb 2930,88673
+#define curlinepos 2931,88704
+#define newlinepos 2932,88745
+#define plainc 2934,88787
+#define cplpl 2935,88831
+#define cjava 2936,88862
+#define CNL_SAVE_DEFINEDEF(2938,88906
+#define CNL(2947,89118
+make_C_tag 2960,89376
+C_entries 2986,90195
+default_C_entries 3833,110157
+plain_C_entries 3840,110277
+Cplusplus_entries 3847,110365
+Cjava_entries 3854,110461
+Cstar_entries 3861,110551
+Yacc_entries 3868,110643
+#define LOOP_ON_INPUT_LINES(3875,110721
+#define LOOKING_AT(3884,111057
+#define LOOKING_AT_NOCASE(3891,111462
+just_read_file 3901,111862
+static void F_takeprec 3910,111966
+static void F_getit 3911,111997
+F_takeprec 3914,112040
+F_getit 3937,112367
+Fortran_functions 3961,112841
+Ada_getit 4052,114670
+Ada_funcs 4115,116045
+Asm_labels 4228,118583
+Perl_functions 4261,119550
+Python_functions 4357,122058
+PHP_functions 4387,122685
+Cobol_paragraphs 4466,124472
+Makefile_targets 4494,125030
+Pascal_functions 4529,125951
+static void L_getit 4706,130278
+L_getit 4709,130319
+Lisp_functions 4725,130665
+Lua_functions 4785,131851
+PS_functions 4811,132386
+Forth_words 4841,133054
+Scheme_functions 4877,134093
+static linebuffer *TEX_toktab TEX_toktab4908,134782
+static const char *TEX_defenv TEX_defenv4912,134975
+static void TEX_mode 4917,135173
+static void TEX_decode_env 4918,135204
+static char TEX_esc 4920,135262
+static char TEX_opgrp 4921,135290
+static char TEX_clgrp 4922,135319
+TeX_commands 4928,135396
+#define TEX_LESC 4986,136653
+#define TEX_SESC 4987,136675
+TEX_mode 4992,136805
+TEX_decode_env 5026,137510
+Texinfo_nodes 5071,138555
+HTML_labels 5094,139014
+static size_t prolog_pr 5214,142193
+static void prolog_skip_comment 5215,142235
+static size_t prolog_atom 5216,142291
+Prolog_functions 5219,142348
+prolog_skip_comment 5255,143129
+prolog_pr 5281,143737
+prolog_atom 5319,144629
+static int erlang_func 5374,145541
+static void erlang_attribute 5375,145582
+static int erlang_atom 5376,145621
+Erlang_functions 5379,145667
+erlang_func 5438,146966
+erlang_attribute 5476,147643
+erlang_atom 5496,148062
+static char *scan_separators scan_separators5520,148488
+static void add_regex 5521,148527
+static char *substitute substitute5522,148571
+scan_separators 5534,149081
+analyze_regex 5586,150461
+add_regex 5654,152051
+substitute 5767,154798
+free_regexps 5814,155838
+regex_tag_multiline 5836,156292
+nocase_tail 5913,158264
+get_tag 5928,158520
+readline_internal 5959,159456
+readline 6037,161297
+savestr 6230,167244
+savenstr 6240,167474
+skip_spaces 6249,167680
+skip_non_spaces 6258,167834
+skip_name 6267,167984
+fatal 6277,168157
+pfatal 6284,168254
+suggest_asking_for_help 6291,168333
+error 6300,168555
+concat 6313,168847
+etags_getcwd 6329,169260
+relative_filename 6350,169726
+absolute_filename 6389,170752
+absolute_dirname 6453,172417
+filename_is_absolute 6472,172846
+canonicalize_filename 6484,173097
+# define ISUPPER(6491,173236
+linebuffer_init 6514,173657
+linebuffer_setlen 6524,173888
+xmalloc 6536,174149
+xrealloc 6545,174315
c-src/exit.c,99
size_t n;28,972
@@ -764,2059 +760,2059 @@ pp287,1504
pp3(100,1616
c-src/emacs/src/gmalloc.c,7311
-#define USE_PTHREAD25,1002
-#undef get_current_dir_name33,1126
-extern void emacs_abort 47,1305
-#undef malloc64,2110
-#undef realloc65,2124
-#undef calloc66,2139
-#undef free67,2153
-#define malloc 68,2165
-#define realloc 69,2188
-#define calloc 70,2213
-#define aligned_alloc 71,2236
-#define free 72,2273
-extern void *bss_sbrk bss_sbrk76,2335
-extern int bss_sbrk_did_unexec;77,2375
-extern char bss_sbrk_buffer[bss_sbrk_buffer78,2407
-extern void *bss_sbrk_buffer_end;bss_sbrk_buffer_end79,2438
-#define DUMPED 80,2472
-#define ALLOCATED_BEFORE_DUMPING(81,2507
-extern void *malloc malloc94,2718
-#define INT_BIT 124,3934
-#define BLOCKLOG 125,3977
-#define BLOCKSIZE 126,4018
-#define BLOCKIFY(127,4052
-#define HEAP 131,4215
-#define FINAL_FREE_BLOCKS 135,4391
- int type;145,4676
- size_t nfree;150,4720
- size_t first;151,4777
- } frag;152,4834
- ptrdiff_t size;156,5055
- } info;157,5076
- } busy;158,5087
- size_t size;163,5215
- size_t next;164,5272
- size_t prev;165,5321
- } free;166,5374
- } malloc_info;167,5388
-extern char *_heapbase;_heapbase170,5449
-extern malloc_info *_heapinfo;_heapinfo173,5541
-#define BLOCK(176,5620
-#define ADDRESS(177,5682
-extern size_t _heapindex;180,5797
-extern size_t _heaplimit;183,5866
-struct list186,5939
- struct list *next;next188,5955
- struct list *prev;prev189,5978
-extern struct list _fraghead[_fraghead193,6056
-struct alignlist196,6153
- struct alignlist *next;next198,6174
- void *aligned;aligned199,6202
- void *exact;exact200,6270
-extern struct alignlist *_aligned_blocks;_aligned_blocks202,6334
-extern size_t _chunks_used;205,6401
-extern size_t _bytes_used;206,6429
-extern size_t _chunks_free;207,6456
-extern size_t _bytes_free;208,6484
-extern void *_malloc_internal _malloc_internal213,6673
-extern void *_realloc_internal _realloc_internal214,6713
-extern void _free_internal 215,6762
-extern void *_malloc_internal_nolock _malloc_internal_nolock216,6799
-extern void *_realloc_internal_nolock _realloc_internal_nolock217,6846
-extern void _free_internal_nolock 218,6902
-extern pthread_mutex_t _malloc_mutex,221,6966
-extern pthread_mutex_t _malloc_mutex, _aligned_blocks_mutex;221,6966
-extern int _malloc_thread_enabled_p;222,7027
-#define LOCK(223,7064
-#define UNLOCK(228,7195
-#define LOCK_ALIGNED_BLOCKS(233,7329
-#define UNLOCK_ALIGNED_BLOCKS(238,7484
-#define LOCK(244,7649
-#define UNLOCK(245,7664
-#define LOCK_ALIGNED_BLOCKS(246,7681
-#define UNLOCK_ALIGNED_BLOCKS(247,7711
-extern void *malloc_find_object_address malloc_find_object_address252,7865
-extern void *(*__morecore)__morecore256,8021
-extern void *__default_morecore __default_morecore259,8105
-extern void (*__after_morecore_hook)__after_morecore_hook263,8269
-extern size_t __malloc_extra_blocks;267,8442
-extern int __malloc_initialized;270,8552
-extern int __malloc_initialize 272,8646
-extern void (*__malloc_initialize_hook)__malloc_initialize_hook275,8723
-extern void (*__free_hook)__free_hook276,8771
-extern void *(*__malloc_hook)__malloc_hook277,8811
-extern void *(*__realloc_hook)__realloc_hook278,8856
-extern void *(*__memalign_hook)__memalign_hook279,8913
-enum mcheck_status283,9092
- MCHECK_DISABLED 285,9115
- MCHECK_OK,286,9187
- MCHECK_FREE,287,9226
- MCHECK_HEAD,288,9270
- MCHECK_TAIL 289,9334
-extern int mcheck 296,9701
-extern enum mcheck_status mprobe 301,9952
-extern void mtrace 304,10055
-extern void muntrace 305,10082
-struct mstats308,10153
- size_t bytes_total;310,10171
- size_t chunks_used;311,10225
- size_t bytes_used;312,10285
- size_t chunks_free;313,10351
- size_t bytes_free;314,10406
-extern struct mstats mstats 318,10518
-extern void memory_warnings 321,10625
-void *(*__malloc_hook)__malloc_hook352,11743
-char *_heapbase;_heapbase355,11829
-malloc_info *_heapinfo;_heapinfo358,11927
-static size_t heapsize;361,11983
-size_t _heapindex;364,12047
-size_t _heaplimit;367,12109
-struct list _fraghead[_fraghead370,12171
-size_t _chunks_used;373,12229
-size_t _bytes_used;374,12250
-size_t _chunks_free;375,12270
-size_t _bytes_free;376,12291
-int __malloc_initialized;379,12340
-size_t __malloc_extra_blocks;381,12367
-void (*__malloc_initialize_hook)__malloc_initialize_hook383,12398
-void (*__after_morecore_hook)__after_morecore_hook384,12439
-static int state_protected_p;400,12912
-static size_t last_state_size;401,12942
-static malloc_info *last_heapinfo;last_heapinfo402,12973
-protect_malloc_state 405,13014
-#define PROTECT_MALLOC_STATE(426,13627
-#define PROTECT_MALLOC_STATE(429,13697
-align 435,13794
-get_contiguous_space 466,14616
-register_heapinfo 497,15325
-pthread_mutex_t _malloc_mutex 517,15879
-pthread_mutex_t _aligned_blocks_mutex 518,15938
-int _malloc_thread_enabled_p;519,16005
-malloc_atfork_handler_prepare 522,16048
-malloc_atfork_handler_parent 529,16139
-malloc_atfork_handler_child 536,16233
-malloc_enable_thread 544,16375
-malloc_initialize_1 563,16961
-__malloc_initialize 594,17793
-static int morecore_recursing;604,17926
-morecore_nolock 609,18066
-_malloc_internal_nolock 722,21584
-_malloc_internal 920,28102
-malloc 932,28247
-extern void *_malloc _malloc956,29033
-extern void _free 957,29064
-extern void *_realloc _realloc958,29092
-_malloc 961,29140
-_free 967,29196
-_realloc 973,29240
-void (*__free_hook)__free_hook1001,30259
-struct alignlist *_aligned_blocks _aligned_blocks1004,30345
-_free_internal_nolock 1009,30474
-_free_internal 1255,38476
-free 1265,38603
-weak_alias 1277,38799
-#define min(1306,39813
-void *(*__realloc_hook)__realloc_hook1310,39898
-_realloc_internal_nolock 1319,40309
-_realloc_internal 1435,43563
-realloc 1447,43726
-calloc 1478,44894
-#define __sbrk 1513,46042
-extern void *__sbrk __sbrk1518,46247
-__default_morecore 1525,46511
-void *(*__memalign_hook)__memalign_hook1554,47456
-aligned_alloc 1557,47522
-memalign 1647,49704
-posix_memalign 1656,49909
-extern void *valloc valloc1695,51140
-extern int getpagesize 1700,51278
-static size_t pagesize;1703,51317
-valloc 1706,51349
-#undef malloc1715,51490
-#undef realloc1716,51504
-#undef calloc1717,51519
-#undef aligned_alloc1718,51533
-#undef free1719,51554
-extern void *malloc malloc1722,51609
-extern void *realloc realloc1723,51644
-extern void *calloc calloc1724,51691
-extern void free 1725,51740
-extern void *aligned_alloc aligned_alloc1727,51796
-extern int posix_memalign 1729,51890
-hybrid_malloc 1736,52083
-hybrid_calloc 1744,52188
-hybrid_free 1752,52319
-hybrid_aligned_alloc 1765,52626
-hybrid_realloc 1780,52984
-char *gget_current_dir_name gget_current_dir_name1808,53753
-hybrid_get_current_dir_name 1811,53797
-static void (*old_free_hook)old_free_hook1846,54921
-static void *(*old_malloc_hook)old_malloc_hook1847,54963
-static void *(*old_realloc_hook)old_realloc_hook1848,55010
-static void (*abortfunc)abortfunc1851,55124
-#define MAGICWORD 1854,55206
-#define MAGICFREE 1855,55261
-#define MAGICBYTE 1856,55316
-#define MALLOCFLOOD 1857,55348
-#define FREEFLOOD 1858,55382
-struct hdr1860,55415
- size_t size;1862,55430
- size_t magic;1863,55484
-checkhdr 1867,55581
-freehook 1891,56022
-mallochook 1927,56804
-reallochook 1944,57143
-mabort 1978,57901
-static int mcheck_used 2012,58586
-mcheck 2015,58619
-mprobe 2035,59138
+#define USE_PTHREAD25,1003
+#undef get_current_dir_name33,1127
+extern void emacs_abort 47,1306
+#undef malloc64,2111
+#undef realloc65,2125
+#undef calloc66,2140
+#undef free67,2154
+#define malloc 68,2166
+#define realloc 69,2189
+#define calloc 70,2214
+#define aligned_alloc 71,2237
+#define free 72,2274
+extern void *bss_sbrk bss_sbrk76,2336
+extern int bss_sbrk_did_unexec;77,2376
+extern char bss_sbrk_buffer[bss_sbrk_buffer78,2408
+extern void *bss_sbrk_buffer_end;bss_sbrk_buffer_end79,2439
+#define DUMPED 80,2473
+#define ALLOCATED_BEFORE_DUMPING(81,2508
+extern void *malloc malloc94,2719
+#define INT_BIT 124,3935
+#define BLOCKLOG 125,3978
+#define BLOCKSIZE 126,4019
+#define BLOCKIFY(127,4053
+#define HEAP 131,4216
+#define FINAL_FREE_BLOCKS 135,4392
+ int type;145,4677
+ size_t nfree;150,4721
+ size_t first;151,4778
+ } frag;152,4835
+ ptrdiff_t size;156,5056
+ } info;157,5077
+ } busy;158,5088
+ size_t size;163,5216
+ size_t next;164,5273
+ size_t prev;165,5322
+ } free;166,5375
+ } malloc_info;167,5389
+extern char *_heapbase;_heapbase170,5450
+extern malloc_info *_heapinfo;_heapinfo173,5542
+#define BLOCK(176,5621
+#define ADDRESS(177,5683
+extern size_t _heapindex;180,5798
+extern size_t _heaplimit;183,5867
+struct list186,5940
+ struct list *next;next188,5956
+ struct list *prev;prev189,5979
+extern struct list _fraghead[_fraghead193,6057
+struct alignlist196,6154
+ struct alignlist *next;next198,6175
+ void *aligned;aligned199,6203
+ void *exact;exact200,6271
+extern struct alignlist *_aligned_blocks;_aligned_blocks202,6335
+extern size_t _chunks_used;205,6402
+extern size_t _bytes_used;206,6430
+extern size_t _chunks_free;207,6457
+extern size_t _bytes_free;208,6485
+extern void *_malloc_internal _malloc_internal213,6674
+extern void *_realloc_internal _realloc_internal214,6714
+extern void _free_internal 215,6763
+extern void *_malloc_internal_nolock _malloc_internal_nolock216,6800
+extern void *_realloc_internal_nolock _realloc_internal_nolock217,6847
+extern void _free_internal_nolock 218,6903
+extern pthread_mutex_t _malloc_mutex,221,6967
+extern pthread_mutex_t _malloc_mutex, _aligned_blocks_mutex;221,6967
+extern int _malloc_thread_enabled_p;222,7028
+#define LOCK(223,7065
+#define UNLOCK(228,7196
+#define LOCK_ALIGNED_BLOCKS(233,7330
+#define UNLOCK_ALIGNED_BLOCKS(238,7485
+#define LOCK(244,7650
+#define UNLOCK(245,7665
+#define LOCK_ALIGNED_BLOCKS(246,7682
+#define UNLOCK_ALIGNED_BLOCKS(247,7712
+extern void *malloc_find_object_address malloc_find_object_address252,7866
+extern void *(*__morecore)__morecore256,8022
+extern void *__default_morecore __default_morecore259,8106
+extern void (*__after_morecore_hook)__after_morecore_hook263,8270
+extern size_t __malloc_extra_blocks;267,8443
+extern int __malloc_initialized;270,8553
+extern int __malloc_initialize 272,8647
+extern void (*__malloc_initialize_hook)__malloc_initialize_hook275,8724
+extern void (*__free_hook)__free_hook276,8772
+extern void *(*__malloc_hook)__malloc_hook277,8812
+extern void *(*__realloc_hook)__realloc_hook278,8857
+extern void *(*__memalign_hook)__memalign_hook279,8914
+enum mcheck_status283,9093
+ MCHECK_DISABLED 285,9116
+ MCHECK_OK,286,9188
+ MCHECK_FREE,287,9227
+ MCHECK_HEAD,288,9271
+ MCHECK_TAIL 289,9335
+extern int mcheck 296,9702
+extern enum mcheck_status mprobe 301,9953
+extern void mtrace 304,10056
+extern void muntrace 305,10083
+struct mstats308,10154
+ size_t bytes_total;310,10172
+ size_t chunks_used;311,10226
+ size_t bytes_used;312,10286
+ size_t chunks_free;313,10352
+ size_t bytes_free;314,10407
+extern struct mstats mstats 318,10519
+extern void memory_warnings 321,10626
+void *(*__malloc_hook)__malloc_hook352,11745
+char *_heapbase;_heapbase355,11831
+malloc_info *_heapinfo;_heapinfo358,11929
+static size_t heapsize;361,11985
+size_t _heapindex;364,12049
+size_t _heaplimit;367,12111
+struct list _fraghead[_fraghead370,12173
+size_t _chunks_used;373,12231
+size_t _bytes_used;374,12252
+size_t _chunks_free;375,12272
+size_t _bytes_free;376,12293
+int __malloc_initialized;379,12342
+size_t __malloc_extra_blocks;381,12369
+void (*__malloc_initialize_hook)__malloc_initialize_hook383,12400
+void (*__after_morecore_hook)__after_morecore_hook384,12441
+static int state_protected_p;400,12914
+static size_t last_state_size;401,12944
+static malloc_info *last_heapinfo;last_heapinfo402,12975
+protect_malloc_state 405,13016
+#define PROTECT_MALLOC_STATE(426,13629
+#define PROTECT_MALLOC_STATE(429,13699
+align 435,13796
+get_contiguous_space 466,14618
+register_heapinfo 497,15327
+pthread_mutex_t _malloc_mutex 517,15881
+pthread_mutex_t _aligned_blocks_mutex 518,15940
+int _malloc_thread_enabled_p;519,16007
+malloc_atfork_handler_prepare 522,16050
+malloc_atfork_handler_parent 529,16141
+malloc_atfork_handler_child 536,16235
+malloc_enable_thread 544,16377
+malloc_initialize_1 563,16963
+__malloc_initialize 594,17795
+static int morecore_recursing;604,17928
+morecore_nolock 609,18068
+_malloc_internal_nolock 722,21586
+_malloc_internal 920,28104
+malloc 932,28249
+extern void *_malloc _malloc956,29035
+extern void _free 957,29066
+extern void *_realloc _realloc958,29094
+_malloc 961,29142
+_free 967,29198
+_realloc 973,29242
+void (*__free_hook)__free_hook1001,30262
+struct alignlist *_aligned_blocks _aligned_blocks1004,30348
+_free_internal_nolock 1009,30477
+_free_internal 1255,38479
+free 1265,38606
+weak_alias 1277,38802
+#define min(1306,39817
+void *(*__realloc_hook)__realloc_hook1310,39902
+_realloc_internal_nolock 1319,40313
+_realloc_internal 1435,43567
+realloc 1447,43730
+calloc 1478,44899
+#define __sbrk 1513,46048
+extern void *__sbrk __sbrk1518,46253
+__default_morecore 1525,46517
+void *(*__memalign_hook)__memalign_hook1554,47463
+aligned_alloc 1557,47529
+memalign 1647,49711
+posix_memalign 1656,49916
+extern void *valloc valloc1695,51148
+extern int getpagesize 1700,51286
+static size_t pagesize;1703,51325
+valloc 1706,51357
+#undef malloc1715,51498
+#undef realloc1716,51512
+#undef calloc1717,51527
+#undef aligned_alloc1718,51541
+#undef free1719,51562
+extern void *malloc malloc1722,51617
+extern void *realloc realloc1723,51652
+extern void *calloc calloc1724,51699
+extern void free 1725,51748
+extern void *aligned_alloc aligned_alloc1727,51804
+extern int posix_memalign 1729,51898
+hybrid_malloc 1736,52091
+hybrid_calloc 1744,52196
+hybrid_free 1752,52327
+hybrid_aligned_alloc 1765,52634
+hybrid_realloc 1780,52990
+char *gget_current_dir_name gget_current_dir_name1808,53759
+hybrid_get_current_dir_name 1811,53803
+static void (*old_free_hook)old_free_hook1846,54928
+static void *(*old_malloc_hook)old_malloc_hook1847,54970
+static void *(*old_realloc_hook)old_realloc_hook1848,55017
+static void (*abortfunc)abortfunc1851,55131
+#define MAGICWORD 1854,55213
+#define MAGICFREE 1855,55268
+#define MAGICBYTE 1856,55323
+#define MALLOCFLOOD 1857,55355
+#define FREEFLOOD 1858,55389
+struct hdr1860,55422
+ size_t size;1862,55437
+ size_t magic;1863,55491
+checkhdr 1867,55588
+freehook 1891,56029
+mallochook 1927,56811
+reallochook 1944,57150
+mabort 1978,57908
+static int mcheck_used 2012,58593
+mcheck 2015,58626
+mprobe 2035,59145
c-src/emacs/src/regex.h,5300
-#define _REGEX_H 21,836
-typedef unsigned long reg_syntax_t;43,1577
-#define RE_BACKSLASH_ESCAPE_IN_LISTS 47,1749
-#define RE_BK_PLUS_QM 52,1969
-#define RE_CHAR_CLASSES 58,2298
-#define RE_CONTEXT_INDEP_ANCHORS 72,3032
-#define RE_CONTEXT_INDEP_OPS 80,3458
-#define RE_CONTEXT_INVALID_OPS 84,3658
-#define RE_DOT_NEWLINE 88,3801
-#define RE_DOT_NOT_NULL 92,3937
-#define RE_HAT_LISTS_NOT_NEWLINE 96,4082
-#define RE_INTERVALS 101,4292
-#define RE_LIMITED_OPS 105,4441
-#define RE_NEWLINE_ALT 109,4583
-#define RE_NO_BK_BRACES 114,4773
-#define RE_NO_BK_PARENS 118,4964
-#define RE_NO_BK_REFS 122,5120
-#define RE_NO_BK_VBAR 126,5316
-#define RE_NO_EMPTY_RANGES 132,5610
-#define RE_UNMATCHED_RIGHT_PAREN_ORD 136,5766
-#define RE_NO_POSIX_BACKTRACKING 140,5937
-#define RE_NO_GNU_OPS 144,6133
-#define RE_FRUGAL 147,6253
-#define RE_SHY_GROUPS 150,6360
-#define RE_NO_NEWLINE_ANCHOR 153,6468
-#define RE_DEBUG 161,6884
-extern reg_syntax_t re_syntax_options;167,7170
-extern Lisp_Object re_match_object;172,7344
-extern size_t re_max_failures;176,7454
-#define RE_SYNTAX_EMACS 183,7684
-#define RE_SYNTAX_AWK 186,7780
-#define RE_SYNTAX_GNU_AWK 193,8084
-#define RE_SYNTAX_POSIX_AWK 197,8255
-#define RE_SYNTAX_GREP 201,8393
-#define RE_SYNTAX_EGREP 206,8549
-#define RE_SYNTAX_POSIX_EGREP 212,8765
-#define RE_SYNTAX_ED 216,8910
-#define RE_SYNTAX_SED 218,8954
-#define _RE_SYNTAX_POSIX_COMMON 221,9072
-#define RE_SYNTAX_POSIX_BASIC 225,9215
-#define RE_SYNTAX_POSIX_MINIMAL_BASIC 231,9508
-#define RE_SYNTAX_POSIX_EXTENDED 234,9598
-#define RE_SYNTAX_POSIX_MINIMAL_EXTENDED 242,9967
-# undef RE_DUP_MAX253,10454
-#define RE_DUP_MAX 256,10540
-#define REG_EXTENDED 263,10762
-#define REG_ICASE 267,10886
-#define REG_NEWLINE 272,11070
-#define REG_NOSUB 276,11248
-#define REG_NOTBOL 286,11614
-#define REG_NOTEOL 289,11688
- REG_ENOSYS 297,11859
- REG_NOERROR 300,11941
- REG_NOMATCH,301,11976
- REG_BADPAT,305,12123
- REG_ECOLLATE,306,12162
- REG_ECTYPE,307,12203
- REG_EESCAPE,308,12255
- REG_ESUBREG,309,12298
- REG_EBRACK,310,12345
- REG_EPAREN,311,12391
- REG_EBRACE,312,12436
- REG_BADBR,313,12472
- REG_ERANGE,314,12519
- REG_ESPACE,315,12560
- REG_BADRPT,316,12601
- REG_EEND,319,12693
- REG_ESIZE,320,12728
- REG_ERPAREN,321,12790
- REG_ERANGEX 322,12859
-} reg_errcode_t;323,12911
-# define RE_TRANSLATE_TYPE 332,13273
-struct re_pattern_buffer335,13315
- unsigned char *buffer;buffer341,13538
- size_t allocated;344,13614
- size_t used;347,13686
- reg_syntax_t syntax;350,13769
- char *fastmap;fastmap355,13975
- RE_TRANSLATE_TYPE translate;361,14241
- size_t re_nsub;364,14329
- unsigned can_be_null 370,14624
-#define REGS_UNALLOCATED 376,14889
-#define REGS_REALLOCATE 377,14916
-#define REGS_FIXED 378,14942
- unsigned regs_allocated 379,14963
- unsigned fastmap_accurate 383,15136
- unsigned no_sub 387,15267
- unsigned not_bol 391,15398
- unsigned not_eol 394,15475
- unsigned used_syntax 398,15655
- unsigned multibyte 403,15805
- unsigned target_multibyte 407,15941
- int charset_unibyte;410,16032
-typedef struct re_pattern_buffer regex_t;416,16098
-typedef ssize_t regoff_t;423,16492
-struct re_registers428,16652
- unsigned num_regs;430,16674
- regoff_t *start;start431,16695
- regoff_t *end;end432,16714
-# define RE_NREGS 440,16942
- regoff_t rm_so;449,17159
- regoff_t rm_eo;450,17239
-} regmatch_t;451,17317
-extern reg_syntax_t re_set_syntax 457,17512
-extern const char *re_compile_pattern re_compile_pattern462,17776
-extern int re_compile_fastmap 469,18058
-extern regoff_t re_search 477,18466
-extern regoff_t re_search_2 485,18781
-extern regoff_t re_match 495,19177
-extern regoff_t re_match_2 501,19407
-extern void re_set_registers 520,20197
-extern char *re_comp re_comp528,20469
-extern int re_exec 529,20506
-# define _Restrict_ 540,20886
-# define _Restrict_ 542,20979
-# define _Restrict_544,21018
-# define _Restrict_arr_ 555,21418
-# define _Restrict_arr_557,21461
-extern reg_errcode_t regcomp 562,21530
-extern reg_errcode_t regexec 566,21656
-extern size_t regerror 571,21850
-extern void regfree 574,21956
-# define CHAR_CLASS_MAX_LENGTH 593,22470
-# define CHAR_CLASS_MAX_LENGTH 597,22648
-typedef wctype_t re_wctype_t;599,22692
-typedef wchar_t re_wchar_t;600,22722
-# define re_wctype 601,22750
-# define re_iswctype 602,22776
-# define re_wctype_to_bit(603,22806
-# define CHAR_CLASS_MAX_LENGTH 605,22844
-# define btowc(606,22906
-typedef enum { RECC_ERROR 609,22953
- RECC_ALNUM,610,22984
- RECC_ALNUM, RECC_ALPHA,610,22984
- RECC_ALNUM, RECC_ALPHA, RECC_WORD,610,22984
- RECC_GRAPH,611,23027
- RECC_GRAPH, RECC_PRINT,611,23027
- RECC_LOWER,612,23059
- RECC_LOWER, RECC_UPPER,612,23059
- RECC_PUNCT,613,23091
- RECC_PUNCT, RECC_CNTRL,613,23091
- RECC_DIGIT,614,23123
- RECC_DIGIT, RECC_XDIGIT,614,23123
- RECC_BLANK,615,23156
- RECC_BLANK, RECC_SPACE,615,23156
- RECC_MULTIBYTE,616,23188
- RECC_MULTIBYTE, RECC_NONASCII,616,23188
- RECC_ASCII,617,23227
- RECC_ASCII, RECC_UNIBYTE617,23227
-} re_wctype_t;618,23260
-extern char re_iswctype 620,23276
-extern re_wctype_t re_wctype 621,23329
-typedef int re_wchar_t;623,23387
-extern void re_set_whitespace_regexp 625,23412
+#define _REGEX_H 21,837
+typedef unsigned long reg_syntax_t;43,1578
+#define RE_BACKSLASH_ESCAPE_IN_LISTS 47,1750
+#define RE_BK_PLUS_QM 52,1970
+#define RE_CHAR_CLASSES 58,2299
+#define RE_CONTEXT_INDEP_ANCHORS 72,3033
+#define RE_CONTEXT_INDEP_OPS 80,3459
+#define RE_CONTEXT_INVALID_OPS 84,3659
+#define RE_DOT_NEWLINE 88,3802
+#define RE_DOT_NOT_NULL 92,3938
+#define RE_HAT_LISTS_NOT_NEWLINE 96,4083
+#define RE_INTERVALS 101,4293
+#define RE_LIMITED_OPS 105,4442
+#define RE_NEWLINE_ALT 109,4584
+#define RE_NO_BK_BRACES 114,4774
+#define RE_NO_BK_PARENS 118,4965
+#define RE_NO_BK_REFS 122,5121
+#define RE_NO_BK_VBAR 126,5317
+#define RE_NO_EMPTY_RANGES 132,5611
+#define RE_UNMATCHED_RIGHT_PAREN_ORD 136,5767
+#define RE_NO_POSIX_BACKTRACKING 140,5938
+#define RE_NO_GNU_OPS 144,6134
+#define RE_FRUGAL 147,6254
+#define RE_SHY_GROUPS 150,6361
+#define RE_NO_NEWLINE_ANCHOR 153,6469
+#define RE_DEBUG 161,6885
+extern reg_syntax_t re_syntax_options;167,7171
+extern Lisp_Object re_match_object;172,7345
+extern size_t re_max_failures;176,7455
+#define RE_SYNTAX_EMACS 183,7685
+#define RE_SYNTAX_AWK 186,7781
+#define RE_SYNTAX_GNU_AWK 193,8085
+#define RE_SYNTAX_POSIX_AWK 197,8256
+#define RE_SYNTAX_GREP 201,8394
+#define RE_SYNTAX_EGREP 206,8550
+#define RE_SYNTAX_POSIX_EGREP 212,8766
+#define RE_SYNTAX_ED 216,8911
+#define RE_SYNTAX_SED 218,8955
+#define _RE_SYNTAX_POSIX_COMMON 221,9073
+#define RE_SYNTAX_POSIX_BASIC 225,9216
+#define RE_SYNTAX_POSIX_MINIMAL_BASIC 231,9509
+#define RE_SYNTAX_POSIX_EXTENDED 234,9599
+#define RE_SYNTAX_POSIX_MINIMAL_EXTENDED 242,9968
+# undef RE_DUP_MAX253,10455
+#define RE_DUP_MAX 256,10541
+#define REG_EXTENDED 263,10763
+#define REG_ICASE 267,10887
+#define REG_NEWLINE 272,11071
+#define REG_NOSUB 276,11249
+#define REG_NOTBOL 286,11615
+#define REG_NOTEOL 289,11689
+ REG_ENOSYS 297,11860
+ REG_NOERROR 300,11942
+ REG_NOMATCH,301,11977
+ REG_BADPAT,305,12124
+ REG_ECOLLATE,306,12163
+ REG_ECTYPE,307,12204
+ REG_EESCAPE,308,12256
+ REG_ESUBREG,309,12299
+ REG_EBRACK,310,12346
+ REG_EPAREN,311,12392
+ REG_EBRACE,312,12437
+ REG_BADBR,313,12473
+ REG_ERANGE,314,12520
+ REG_ESPACE,315,12561
+ REG_BADRPT,316,12602
+ REG_EEND,319,12694
+ REG_ESIZE,320,12729
+ REG_ERPAREN,321,12791
+ REG_ERANGEX 322,12860
+} reg_errcode_t;323,12912
+# define RE_TRANSLATE_TYPE 332,13274
+struct re_pattern_buffer335,13316
+ unsigned char *buffer;buffer341,13539
+ size_t allocated;344,13615
+ size_t used;347,13687
+ reg_syntax_t syntax;350,13770
+ char *fastmap;fastmap355,13976
+ RE_TRANSLATE_TYPE translate;361,14242
+ size_t re_nsub;364,14330
+ unsigned can_be_null 370,14625
+#define REGS_UNALLOCATED 376,14890
+#define REGS_REALLOCATE 377,14917
+#define REGS_FIXED 378,14943
+ unsigned regs_allocated 379,14964
+ unsigned fastmap_accurate 383,15137
+ unsigned no_sub 387,15268
+ unsigned not_bol 391,15399
+ unsigned not_eol 394,15476
+ unsigned used_syntax 398,15656
+ unsigned multibyte 403,15806
+ unsigned target_multibyte 407,15942
+ int charset_unibyte;410,16033
+typedef struct re_pattern_buffer regex_t;416,16099
+typedef ssize_t regoff_t;423,16493
+struct re_registers428,16653
+ unsigned num_regs;430,16675
+ regoff_t *start;start431,16696
+ regoff_t *end;end432,16715
+# define RE_NREGS 440,16943
+ regoff_t rm_so;449,17160
+ regoff_t rm_eo;450,17240
+} regmatch_t;451,17318
+extern reg_syntax_t re_set_syntax 457,17513
+extern const char *re_compile_pattern re_compile_pattern462,17777
+extern int re_compile_fastmap 469,18059
+extern regoff_t re_search 477,18467
+extern regoff_t re_search_2 485,18782
+extern regoff_t re_match 495,19178
+extern regoff_t re_match_2 501,19408
+extern void re_set_registers 520,20198
+extern char *re_comp re_comp528,20470
+extern int re_exec 529,20507
+# define _Restrict_ 540,20887
+# define _Restrict_ 542,20980
+# define _Restrict_544,21019
+# define _Restrict_arr_ 555,21419
+# define _Restrict_arr_557,21462
+extern reg_errcode_t regcomp 562,21531
+extern reg_errcode_t regexec 566,21657
+extern size_t regerror 571,21851
+extern void regfree 574,21957
+# define CHAR_CLASS_MAX_LENGTH 593,22471
+# define CHAR_CLASS_MAX_LENGTH 597,22649
+typedef wctype_t re_wctype_t;599,22693
+typedef wchar_t re_wchar_t;600,22723
+# define re_wctype 601,22751
+# define re_iswctype 602,22777
+# define re_wctype_to_bit(603,22807
+# define CHAR_CLASS_MAX_LENGTH 605,22845
+# define btowc(606,22907
+typedef enum { RECC_ERROR 609,22954
+ RECC_ALNUM,610,22985
+ RECC_ALNUM, RECC_ALPHA,610,22985
+ RECC_ALNUM, RECC_ALPHA, RECC_WORD,610,22985
+ RECC_GRAPH,611,23028
+ RECC_GRAPH, RECC_PRINT,611,23028
+ RECC_LOWER,612,23060
+ RECC_LOWER, RECC_UPPER,612,23060
+ RECC_PUNCT,613,23092
+ RECC_PUNCT, RECC_CNTRL,613,23092
+ RECC_DIGIT,614,23124
+ RECC_DIGIT, RECC_XDIGIT,614,23124
+ RECC_BLANK,615,23157
+ RECC_BLANK, RECC_SPACE,615,23157
+ RECC_MULTIBYTE,616,23189
+ RECC_MULTIBYTE, RECC_NONASCII,616,23189
+ RECC_ASCII,617,23228
+ RECC_ASCII, RECC_UNIBYTE617,23228
+} re_wctype_t;618,23261
+extern char re_iswctype 620,23277
+extern re_wctype_t re_wctype 621,23330
+typedef int re_wchar_t;623,23388
+extern void re_set_whitespace_regexp 625,23413
c-src/emacs/src/keyboard.c,25243
-volatile int interrupt_input_blocked;76,1808
-volatile bool pending_signals;80,1944
-#define KBD_BUFFER_SIZE 82,1976
-KBOARD *initial_kboard;initial_kboard84,2006
-KBOARD *current_kboard;current_kboard85,2030
-static KBOARD *all_kboards;all_kboards86,2054
-static bool single_kboard;89,2154
-#define NUM_RECENT_KEYS 91,2182
-static int recent_keys_index;94,2269
-static int total_keys;97,2357
-static Lisp_Object recent_keys;100,2443
-Lisp_Object this_command_keys;107,2777
-ptrdiff_t this_command_key_count;108,2808
-static bool this_command_key_count_reset;112,2922
-static Lisp_Object raw_keybuf;116,3074
-static int raw_keybuf_count;117,3105
-#define GROW_RAW_KEYBUF 119,3135
-static ptrdiff_t this_single_command_key_start;125,3350
-static ptrdiff_t before_command_key_count;129,3498
-static ptrdiff_t before_command_echo_length;130,3541
-sigjmp_buf return_to_command_loop;135,3677
-static Lisp_Object recover_top_level_message;138,3791
-static Lisp_Object regular_top_level_message;143,3930
-static sys_jmp_buf getcjmp;147,4031
-bool waiting_for_input;150,4095
-static bool echoing;154,4186
-static struct kboard *ok_to_echo_at_next_pause;ok_to_echo_at_next_pause159,4328
-struct kboard *echo_kboard;echo_kboard166,4632
-Lisp_Object echo_message_buffer;171,4744
-bool immediate_quit;174,4837
-int quit_char;192,5623
-EMACS_INT command_loop_level;195,5680
-Lisp_Object unread_switch_frame;204,6108
-static ptrdiff_t last_non_minibuf_size;207,6216
-uintmax_t num_input_events;210,6334
-static EMACS_INT last_auto_save;214,6428
-static ptrdiff_t last_point_position;217,6523
-Lisp_Object internal_last_event_frame;228,7028
-static Lisp_Object read_key_sequence_cmd;232,7168
-static Lisp_Object read_key_sequence_remapped;233,7210
-static FILE *dribble;dribble236,7310
-bool input_pending;239,7368
-static bool input_was_pending;287,10022
-static struct input_event kbd_buffer[kbd_buffer291,10107
-static struct input_event *kbd_fetch_ptr;kbd_fetch_ptr297,10386
-static struct input_event * volatile kbd_store_ptr;302,10601
-static void recursive_edit_unwind 313,11088
-static Lisp_Object command_loop 314,11144
-static void echo_now 316,11185
-static ptrdiff_t echo_length 317,11214
-unsigned timers_run;320,11296
-struct timespec *input_available_clear_time;input_available_clear_time324,11408
-bool interrupt_input;328,11573
-bool interrupts_deferred;331,11671
-static struct timespec timer_idleness_start_time;335,11746
-static struct timespec timer_last_idleness_start_time;340,11916
-#define READABLE_EVENTS_DO_TIMERS_NOW 346,12046
-#define READABLE_EVENTS_FILTER_EVENTS 347,12094
-#define READABLE_EVENTS_IGNORE_SQUEEZABLES 348,12142
-static void (*keyboard_init_hook)keyboard_init_hook351,12264
-static bool get_input_pending 353,12307
-static bool readable_events 354,12344
-static Lisp_Object read_char_x_menu_prompt 355,12379
-static Lisp_Object read_char_minibuf_menu_prompt 357,12502
-static Lisp_Object make_lispy_event 358,12571
-static Lisp_Object make_lispy_movement 359,12631
-static Lisp_Object modify_event_symbol 363,12840
-static Lisp_Object make_lispy_switch_frame 366,13050
-static Lisp_Object make_lispy_focus_in 367,13108
-static Lisp_Object make_lispy_focus_out 369,13188
-static bool help_char_p 371,13275
-static void save_getcjmp 372,13314
-static void restore_getcjmp 373,13354
-static Lisp_Object apply_modifiers 374,13397
-static void clear_event 375,13452
-static void restore_kboard_configuration 376,13500
-static void deliver_input_available_signal 378,13568
-static void handle_interrupt 380,13631
-static _Noreturn void quit_throw_to_read_char 381,13668
-static void process_special_events 382,13722
-static void timer_start_idle 383,13765
-static void timer_stop_idle 384,13802
-static void timer_resume_idle 385,13838
-static void deliver_user_signal 386,13876
-static char *find_user_signal_name find_user_signal_name387,13915
-static void store_user_signal_events 388,13957
-kset_echo_string 392,14088
-kset_kbd_queue 397,14184
-kset_keyboard_translate_table 402,14276
-kset_last_prefix_arg 407,14399
-kset_last_repeatable_command 412,14504
-kset_local_function_key_map 417,14625
-kset_overriding_terminal_local_map 422,14744
-kset_real_last_command 427,14877
-kset_system_key_syms 432,14986
-echo_add_key 443,15249
-echo_char 527,17527
-echo_dash 541,17813
-echo_now 586,19140
-cancel_echoing 635,20614
-echo_length 648,20922
-echo_truncate 660,21253
-add_command_key 672,21582
-recursive_edit_1 697,22406
-record_auto_save 742,23848
-force_auto_save_soon 751,24016
-DEFUN ("recursive-edit", Frecursive_edit,759,24137
-DEFUN ("recursive-edit", Frecursive_edit,recursive-edit759,24137
-recursive_edit_unwind 804,25747
-any_kboard_state 817,26013
-single_kboard_state 838,26665
-not_single_kboard_state 848,26803
-struct kboard_stack858,27065
- KBOARD *kboard;kboard860,27087
- struct kboard_stack *next;next861,27105
-static struct kboard_stack *kboard_stack;kboard_stack864,27138
-push_kboard 867,27186
-pop_kboard 879,27375
-temporarily_switch_to_single_kboard 914,28263
-record_single_kboard_state 943,29437
-restore_kboard_configuration 952,29621
-cmd_error 970,30077
-cmd_error_internal 1024,31510
-DEFUN ("command-error-default-function", Fcommand_error_default_function,1043,32030
-DEFUN ("command-error-default-function", Fcommand_error_default_function,command-error-default-function1043,32030
-static Lisp_Object command_loop_2 1086,33637
-static Lisp_Object top_level_1 1087,33686
-command_loop 1094,33916
-command_loop_2 1134,35135
-top_level_2 1146,35339
-top_level_1 1152,35417
-DEFUN ("top-level", Ftop_level,1164,35787
-DEFUN ("top-level", Ftop_level,top-level1164,35787
-user_error 1183,36288
-DEFUN ("exit-recursive-edit", Fexit_recursive_edit,1189,36429
-DEFUN ("exit-recursive-edit", Fexit_recursive_edit,exit-recursive-edit1189,36429
-DEFUN ("abort-recursive-edit", Fabort_recursive_edit,1201,36819
-DEFUN ("abort-recursive-edit", Fabort_recursive_edit,abort-recursive-edit1201,36819
-tracking_off 1216,37281
-DEFUN ("internal--track-mouse", Ftrack_mouse,1234,37816
-DEFUN ("internal--track-mouse", Ftrack_mouse,track-mouse1234,37816
-bool ignore_mouse_drag_p;1256,38392
-some_mouse_moved 1259,38441
-static int read_key_sequence 1282,38799
-static void adjust_point_for_property 1284,38917
-Lisp_Object last_undo_boundary;1287,39032
-command_loop_1 1294,39273
-read_menu_command 1649,50889
-adjust_point_for_property 1678,51617
-safe_run_hooks_1 1831,57339
-safe_run_hooks_error 1841,57569
-safe_run_hook_funcall 1878,58576
-safe_run_hooks 1893,59058
-int poll_suppress_count;1908,59397
-static struct atimer *poll_timer;poll_timer1915,59487
-poll_for_input_1 1919,59589
-poll_for_input 1930,59789
-start_polling 1942,60053
-input_polling_used 1979,61091
-stop_polling 1994,61390
-set_poll_suppress_count 2009,61759
-bind_polling_period 2029,62141
-make_ctrl_char 2048,62492
-show_help_echo 2113,64455
-static Lisp_Object kbd_buffer_get_event 2152,65484
-static void record_char 2154,65596
-static Lisp_Object help_form_saved_window_configs;2156,65638
-read_char_help_form_unwind 2158,65701
-#define STOP_POLLING 2166,65959
-#define RESUME_POLLING 2170,66084
-read_event_from_main_queue 2175,66229
-read_decoded_event_from_main_queue 2249,68417
-#define MAX_ENCODED_BYTES 2254,68664
-echo_keystrokes_p 2342,71556
-read_char 2376,72848
-record_menu_key 3225,98949
-help_char_p 3258,99674
-record_char 3273,99953
-save_getcjmp 3412,104235
-restore_getcjmp 3418,104326
-readable_events 3430,104697
-int stop_character EXTERNALLY_VISIBLE;3497,106437
-event_to_kboard 3500,106493
-kbd_buffer_nr_stored 3522,107142
-kbd_buffer_store_event 3534,107483
-kbd_buffer_store_event_hold 3550,108025
-kbd_buffer_unget_event 3684,111617
-#define INPUT_EVENT_POS_MAX 3698,112018
-#define INPUT_EVENT_POS_MIN 3701,112147
-position_to_Time 3706,112287
-Time_to_position 3716,112514
-gen_help_event 3738,113171
-kbd_buffer_store_help_event 3756,113611
-discard_mouse_events 3773,113976
-kbd_buffer_events_waiting 3803,114711
-clear_event 3823,115068
-kbd_buffer_get_event 3836,115408
-process_special_events 4258,127881
-swallow_events 4322,129705
-timer_start_idle 4339,130098
-timer_stop_idle 4355,130576
-timer_resume_idle 4363,130720
-struct input_event last_timer_event EXTERNALLY_VISIBLE;4372,130912
-Lisp_Object pending_funcalls;4377,131172
-decode_timer 4381,131293
-timer_check_2 4414,132246
-timer_check 4572,136817
-DEFUN ("current-idle-time", Fcurrent_idle_time,4607,137662
-DEFUN ("current-idle-time", Fcurrent_idle_time,current-idle-time4607,137662
-static Lisp_Object accent_key_syms;4625,138239
-static Lisp_Object func_key_syms;4626,138275
-static Lisp_Object mouse_syms;4627,138309
-static Lisp_Object wheel_syms;4628,138340
-static Lisp_Object drag_n_drop_syms;4629,138371
-static const int lispy_accent_codes[lispy_accent_codes4634,138516
-static const char *const lispy_accent_keys[lispy_accent_keys4741,139878
-#define FUNCTION_KEY_OFFSET 4766,140314
-const char *const lispy_function_keys[lispy_function_keys4768,140347
-static const char *const lispy_multimedia_keys[lispy_multimedia_keys4962,148901
-static const char *const lispy_kana_keys[lispy_kana_keys5026,150135
-#define FUNCTION_KEY_OFFSET 5061,151751
-static const char *const lispy_function_keys[lispy_function_keys5065,151894
-#define ISO_FUNCTION_KEY_OFFSET 5149,154429
-static const char *const iso_lispy_function_keys[iso_lispy_function_keys5151,154469
-static Lisp_Object Vlispy_mouse_stem;5172,155328
-static const char *const lispy_wheel_names[lispy_wheel_names5174,155367
-static const char *const lispy_drag_n_drop_names[lispy_drag_n_drop_names5181,155619
-static short const scroll_bar_parts[scroll_bar_parts5189,155885
-static Lisp_Object button_down_location;5210,156910
-static int last_mouse_button;5215,157065
-static int last_mouse_x;5216,157095
-static int last_mouse_y;5217,157120
-static Time button_down_time;5218,157145
-static int double_click_count;5222,157229
-make_lispy_position 5228,157390
-toolkit_menubar_in_use 5456,163953
-make_scroll_bar_position 5469,164321
-make_lispy_event 5485,164967
-make_lispy_movement 6104,183531
-make_lispy_switch_frame 6131,184262
-make_lispy_focus_in 6137,184369
-make_lispy_focus_out 6145,184495
-parse_modifiers_uncached 6163,184945
-#define SINGLE_LETTER_MOD(6185,185465
-#undef SINGLE_LETTER_MOD6212,185906
-#define MULTI_LETTER_MOD(6214,185932
-#undef MULTI_LETTER_MOD6231,186400
-apply_modifiers_uncached 6273,187574
-static const char *const modifier_names[modifier_names6319,189193
-#define NUM_MOD_NAMES 6325,189399
-static Lisp_Object modifier_symbols;6327,189449
-lispy_modifier_list 6331,189586
-#define KEY_TO_CHAR(6353,190252
-parse_modifiers 6356,190328
-DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,6399,191517
-DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,event-symbol-parse-modifiers6399,191517
-apply_modifiers 6422,192391
-reorder_modifiers 6491,194720
-modify_event_symbol 6536,196528
-DEFUN ("event-convert-list", Fevent_convert_list,6628,199244
-DEFUN ("event-convert-list", Fevent_convert_list,event-convert-list6628,199244
-parse_solitary_modifier 6695,201135
-#define SINGLE_LETTER_MOD(6701,201258
-#define MULTI_LETTER_MOD(6705,201343
-#undef SINGLE_LETTER_MOD6763,202641
-#undef MULTI_LETTER_MOD6764,202666
-lucid_event_type_list_p 6775,202889
-get_input_pending 6814,203960
-record_asynch_buffer_change 6834,204579
-gobble_input 6872,205702
-tty_read_avail_input 6967,208310
-handle_async_input 7149,214039
-process_pending_signals 7165,214359
-unblock_input_to 7177,214645
-unblock_input 7200,215277
-totally_unblock_input 7209,215445
-handle_input_available_signal 7217,215529
-deliver_input_available_signal 7226,215700
-struct user_signal_info7235,215865
- int sig;7238,215915
- char *name;name7241,215956
- int npending;7244,216007
- struct user_signal_info *next;next7246,216024
-static struct user_signal_info *user_signals user_signals7250,216090
-add_user_signal 7253,216149
-handle_user_signal 7275,216598
-deliver_user_signal 7316,217558
-find_user_signal_name 7322,217659
-store_user_signal_events 7334,217841
-static void menu_bar_item 7362,218341
-static Lisp_Object menu_bar_one_keymap_changed_items;7363,218416
-static Lisp_Object menu_bar_items_vector;7368,218630
-static int menu_bar_items_index;7369,218672
-static const char *separator_names[separator_names7372,218707
-menu_separator_name_p 7393,219148
-menu_bar_items 7426,219852
-Lisp_Object item_properties;7568,224603
-menu_bar_item 7571,224645
-menu_item_eval_property_1 7647,227175
-eval_dyn 7658,227465
-menu_item_eval_property 7666,227675
-parse_menu_item 7686,228341
-static Lisp_Object tool_bar_items_vector;7965,236336
-static Lisp_Object tool_bar_item_properties;7970,236510
-static int ntool_bar_items;7974,236606
-static void init_tool_bar_items 7978,236664
-static void process_tool_bar_item 7979,236711
-static bool parse_tool_bar_item 7981,236801
-static void append_tool_bar_item 7982,236861
-tool_bar_items 7990,237083
-process_tool_bar_item 8075,239892
-#define PROP(8112,240969
-set_prop 8114,241038
-parse_tool_bar_item 8167,242453
-#undef PROP8379,248844
-init_tool_bar_items 8387,248969
-append_tool_bar_item 8401,249261
-read_char_x_menu_prompt 8443,250771
-read_char_minibuf_menu_prompt 8503,252445
-#define PUSH_C_STR(8527,253014
-follow_key 8726,258553
-active_maps 8733,258695
-typedef struct keyremap8742,259021
- Lisp_Object parent;8745,259107
- Lisp_Object map;8748,259224
- int start,8753,259446
- int start, end;8753,259446
-} keyremap;8754,259464
-access_keymap_keyremap 8764,259808
-keyremap_step 8811,261450
-test_undefined 8867,262934
-read_key_sequence 8916,264861
-read_key_sequence_vs 9826,295821
-DEFUN ("read-key-sequence", Fread_key_sequence,9885,297294
-DEFUN ("read-key-sequence", Fread_key_sequence,read-key-sequence9885,297294
-DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,9938,299982
-DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,read-key-sequence-vector9938,299982
-detect_input_pending 9950,300488
-detect_input_pending_ignore_squeezables 9959,300654
-detect_input_pending_run_timers 9967,300870
-clear_input_pending 9985,301362
-requeued_events_pending_p 9997,301732
-DEFUN ("input-pending-p", Finput_pending_p,10002,301813
-DEFUN ("input-pending-p", Finput_pending_p,input-pending-p10002,301813
-DEFUN ("recent-keys", Frecent_keys,10024,302596
-DEFUN ("recent-keys", Frecent_keys,recent-keys10024,302596
-DEFUN ("this-command-keys", Fthis_command_keys,10055,303517
-DEFUN ("this-command-keys", Fthis_command_keys,this-command-keys10055,303517
-DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,10068,303958
-DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,this-command-keys-vector10068,303958
-DEFUN ("this-single-command-keys", Fthis_single_command_keys,10080,304380
-DEFUN ("this-single-command-keys", Fthis_single_command_keys,this-single-command-keys10080,304380
-DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,10096,304955
-DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,this-single-command-raw-keys10096,304955
-DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,10109,305495
-DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,reset-this-command-lengths10109,305495
-DEFUN ("clear-this-command-keys", Fclear_this_command_keys,10136,306510
-DEFUN ("clear-this-command-keys", Fclear_this_command_keys,clear-this-command-keys10136,306510
-DEFUN ("recursion-depth", Frecursion_depth,10158,307069
-DEFUN ("recursion-depth", Frecursion_depth,recursion-depth10158,307069
-DEFUN ("open-dribble-file", Fopen_dribble_file,10169,307406
-DEFUN ("open-dribble-file", Fopen_dribble_file,open-dribble-file10169,307406
-DEFUN ("discard-input", Fdiscard_input,10203,308447
-DEFUN ("discard-input", Fdiscard_input,discard-input10203,308447
-DEFUN ("suspend-emacs", Fsuspend_emacs,10225,308949
-DEFUN ("suspend-emacs", Fsuspend_emacs,suspend-emacs10225,308949
-stuff_buffered_input 10285,311045
-set_waiting_for_input 10323,312016
-clear_waiting_for_input 10337,312390
-handle_interrupt_signal 10351,312754
-deliver_interrupt_signal 10378,313642
-static int volatile force_quit_count;10387,313932
-handle_interrupt 10401,314414
-quit_throw_to_read_char 10541,318711
-DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,10562,319288
-DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,set-input-interrupt-mode10562,319288
-DEFUN ("set-output-flow-control", Fset_output_flow_control,10609,320516
-DEFUN ("set-output-flow-control", Fset_output_flow_control,set-output-flow-control10609,320516
-DEFUN ("set-input-meta-mode", Fset_input_meta_mode,10643,321432
-DEFUN ("set-input-meta-mode", Fset_input_meta_mode,set-input-meta-mode10643,321432
-DEFUN ("set-quit-char", Fset_quit_char,10694,322706
-DEFUN ("set-quit-char", Fset_quit_char,set-quit-char10694,322706
-DEFUN ("set-input-mode", Fset_input_mode,10729,323570
-DEFUN ("set-input-mode", Fset_input_mode,set-input-mode10729,323570
-DEFUN ("current-input-mode", Fcurrent_input_mode,10750,324459
-DEFUN ("current-input-mode", Fcurrent_input_mode,current-input-mode10750,324459
-DEFUN ("posn-at-x-y", Fposn_at_x_y,10787,325837
-DEFUN ("posn-at-x-y", Fposn_at_x_y,posn-at-x-y10787,325837
-DEFUN ("posn-at-point", Fposn_at_point,10824,327060
-DEFUN ("posn-at-point", Fposn_at_point,posn-at-point10824,327060
-init_kboard 10861,328214
-allocate_kboard 10893,329284
-wipe_kboard 10909,329637
-delete_kboard 10917,329751
-init_keyboard 10942,330281
-struct event_head11021,332696
- short var;11023,332716
- short kind;11024,332729
-static const struct event_head head_table[head_table11027,332747
-syms_of_keyboard 11045,333577
- DEFVAR_LISP ("internal--top-level-message"11058,333972
- DEFVAR_LISP ("last-command-event"11312,342173
- DEFVAR_LISP ("last-nonmenu-event"11315,342297
- DEFVAR_LISP ("last-input-event"11321,342636
- DEFVAR_LISP ("unread-command-events"11324,342730
- DEFVAR_LISP ("unread-post-input-method-events"11332,343190
- DEFVAR_LISP ("unread-input-method-events"11338,343529
- DEFVAR_LISP ("meta-prefix-char"11346,343898
- DEFVAR_KBOARD ("last-command"11351,344106
- DEFVAR_KBOARD ("real-last-command"11368,344787
- DEFVAR_KBOARD ("last-repeatable-command"11372,344973
- DEFVAR_LISP ("this-command"11378,345261
- DEFVAR_LISP ("real-this-command"11384,345498
- DEFVAR_LISP ("this-command-keys-shift-translated"11388,345680
- DEFVAR_LISP ("this-original-command"11396,346123
- DEFVAR_INT ("auto-save-interval"11403,346520
- DEFVAR_LISP ("auto-save-timeout"11408,346734
- DEFVAR_LISP ("echo-keystrokes"11415,347079
- DEFVAR_INT ("polling-period"11421,347350
- DEFVAR_LISP ("double-click-time"11428,347693
- DEFVAR_INT ("double-click-fuzz"11435,348029
- DEFVAR_INT ("num-input-keys"11446,348519
- DEFVAR_INT ("num-nonmacro-input-events"11452,348794
- DEFVAR_LISP ("last-event-frame"11457,349032
- DEFVAR_LISP ("tty-erase-char"11463,349311
- DEFVAR_LISP ("help-char"11466,349434
- DEFVAR_LISP ("help-event-list"11472,349717
- DEFVAR_LISP ("help-form"11477,349928
- DEFVAR_LISP ("prefix-help-command"11483,350176
- DEFVAR_LISP ("top-level"11489,350454
- DEFVAR_KBOARD ("keyboard-translate-table"11495,350675
- DEFVAR_BOOL ("cannot-suspend"11511,351488
- DEFVAR_BOOL ("menu-prompting"11516,351715
- DEFVAR_LISP ("menu-prompt-more-char"11526,352145
- DEFVAR_INT ("extra-keyboard-modifiers"11531,352391
- DEFVAR_LISP ("deactivate-mark"11545,353117
- DEFVAR_LISP ("pre-command-hook"11553,353486
- DEFVAR_LISP ("post-command-hook"11560,353841
- DEFVAR_LISP ("echo-area-clear-hook"11568,354204
- DEFVAR_LISP ("lucid-menu-bar-dirty-flag"11574,354419
- DEFVAR_LISP ("menu-bar-final-items"11578,354622
- DEFVAR_LISP ("tool-bar-separator-image-expression"11583,354872
- DEFVAR_KBOARD ("overriding-terminal-local-map"11589,355230
- DEFVAR_LISP ("overriding-local-map"11598,355652
- DEFVAR_LISP ("overriding-local-map-menu-flag"11607,356103
- DEFVAR_LISP ("special-event-map"11613,356442
- DEFVAR_LISP ("track-mouse"11617,356630
- DEFVAR_KBOARD ("system-key-alist"11620,356757
- DEFVAR_KBOARD ("local-function-key-map"11629,357138
- DEFVAR_KBOARD ("input-decode-map"11658,358597
- DEFVAR_LISP ("function-key-map"11675,359385
- DEFVAR_LISP ("key-translation-map"11683,359801
- DEFVAR_LISP ("deferred-action-list"11689,360145
- DEFVAR_LISP ("deferred-action-function"11694,360393
- DEFVAR_LISP ("delayed-warnings-list"11700,360692
- DEFVAR_LISP ("timer-list"11708,361100
- DEFVAR_LISP ("timer-idle-list"11712,361252
- DEFVAR_LISP ("input-method-function"11716,361415
- DEFVAR_LISP ("input-method-previous-message"11737,362384
- DEFVAR_LISP ("show-help-function"11744,362745
- DEFVAR_LISP ("disable-point-adjustment"11749,362977
- DEFVAR_LISP ("global-disable-point-adjustment"11761,363527
- DEFVAR_LISP ("minibuffer-message-timeout"11770,363893
- DEFVAR_LISP ("throw-on-input"11775,364171
- DEFVAR_LISP ("command-error-function"11781,364422
- DEFVAR_LISP ("enable-disabled-menus-and-buttons"11790,364909
- DEFVAR_LISP ("select-active-regions"11798,365236
- DEFVAR_LISP ("saved-region-selection"11807,365628
- DEFVAR_LISP ("selection-inhibit-update-commands"11815,366013
- DEFVAR_LISP ("debug-on-event"11825,366554
-keys_of_keyboard 11841,367115
-mark_kboards 11916,370434
- DEFVAR_LISP ("internal--top-level-message",\111058,333972
- DEFVAR_LISP ("last-command-event",\111312,342173
- DEFVAR_LISP ("last-nonmenu-event",\111315,342297
- DEFVAR_LISP ("last-input-event",\111321,342636
- DEFVAR_LISP ("unread-command-events",\111324,342730
- DEFVAR_LISP ("unread-post-input-method-events",\111332,343190
- DEFVAR_LISP ("unread-input-method-events",\111338,343529
- DEFVAR_LISP ("meta-prefix-char",\111346,343898
- DEFVAR_KBOARD ("last-command",\111351,344106
- DEFVAR_KBOARD ("real-last-command",\111368,344787
- DEFVAR_KBOARD ("last-repeatable-command",\111372,344973
- DEFVAR_LISP ("this-command",\111378,345261
- DEFVAR_LISP ("real-this-command",\111384,345498
- DEFVAR_LISP ("this-command-keys-shift-translated",\111388,345680
- DEFVAR_LISP ("this-original-command",\111396,346123
- DEFVAR_INT ("auto-save-interval",\111403,346520
- DEFVAR_LISP ("auto-save-timeout",\111408,346734
- DEFVAR_LISP ("echo-keystrokes",\111415,347079
- DEFVAR_INT ("polling-period",\111421,347350
- DEFVAR_LISP ("double-click-time",\111428,347693
- DEFVAR_INT ("double-click-fuzz",\111435,348029
- DEFVAR_INT ("num-input-keys",\111446,348519
- DEFVAR_INT ("num-nonmacro-input-events",\111452,348794
- DEFVAR_LISP ("last-event-frame",\111457,349032
- DEFVAR_LISP ("tty-erase-char",\111463,349311
- DEFVAR_LISP ("help-char",\111466,349434
- DEFVAR_LISP ("help-event-list",\111472,349717
- DEFVAR_LISP ("help-form",\111477,349928
- DEFVAR_LISP ("prefix-help-command",\111483,350176
- DEFVAR_LISP ("top-level",\111489,350454
- DEFVAR_KBOARD ("keyboard-translate-table",\111495,350675
- DEFVAR_BOOL ("cannot-suspend",\111511,351488
- DEFVAR_BOOL ("menu-prompting",\111516,351715
- DEFVAR_LISP ("menu-prompt-more-char",\111526,352145
- DEFVAR_INT ("extra-keyboard-modifiers",\111531,352391
- DEFVAR_LISP ("deactivate-mark",\111545,353117
- DEFVAR_LISP ("pre-command-hook",\111553,353486
- DEFVAR_LISP ("post-command-hook",\111560,353841
- DEFVAR_LISP ("echo-area-clear-hook",\111568,354204
- DEFVAR_LISP ("lucid-menu-bar-dirty-flag",\111574,354419
- DEFVAR_LISP ("menu-bar-final-items",\111578,354622
- DEFVAR_LISP ("tool-bar-separator-image-expression",\111583,354872
- DEFVAR_KBOARD ("overriding-terminal-local-map",\111589,355230
- DEFVAR_LISP ("overriding-local-map",\111598,355652
- DEFVAR_LISP ("overriding-local-map-menu-flag",\111607,356103
- DEFVAR_LISP ("special-event-map",\111613,356442
- DEFVAR_LISP ("track-mouse",\111617,356630
- DEFVAR_KBOARD ("system-key-alist",\111620,356757
- DEFVAR_KBOARD ("local-function-key-map",\111629,357138
- DEFVAR_KBOARD ("input-decode-map",\111658,358597
- DEFVAR_LISP ("function-key-map",\111675,359385
- DEFVAR_LISP ("key-translation-map",\111683,359801
- DEFVAR_LISP ("deferred-action-list",\111689,360145
- DEFVAR_LISP ("deferred-action-function",\111694,360393
- DEFVAR_LISP ("delayed-warnings-list",\111700,360692
- DEFVAR_LISP ("timer-list",\111708,361100
- DEFVAR_LISP ("timer-idle-list",\111712,361252
- DEFVAR_LISP ("input-method-function",\111716,361415
- DEFVAR_LISP ("input-method-previous-message",\111737,362384
- DEFVAR_LISP ("show-help-function",\111744,362745
- DEFVAR_LISP ("disable-point-adjustment",\111749,362977
- DEFVAR_LISP ("global-disable-point-adjustment",\111761,363527
- DEFVAR_LISP ("minibuffer-message-timeout",\111770,363893
- DEFVAR_LISP ("throw-on-input",\111775,364171
- DEFVAR_LISP ("command-error-function",\111781,364422
- DEFVAR_LISP ("enable-disabled-menus-and-buttons",\111790,364909
- DEFVAR_LISP ("select-active-regions",\111798,365236
- DEFVAR_LISP ("saved-region-selection",\111807,365628
- DEFVAR_LISP ("selection-inhibit-update-commands",\111815,366013
- DEFVAR_LISP ("debug-on-event",\111825,366554
+volatile int interrupt_input_blocked;76,1809
+volatile bool pending_signals;80,1945
+#define KBD_BUFFER_SIZE 82,1977
+KBOARD *initial_kboard;initial_kboard84,2007
+KBOARD *current_kboard;current_kboard85,2031
+static KBOARD *all_kboards;all_kboards86,2055
+static bool single_kboard;89,2155
+#define NUM_RECENT_KEYS 91,2183
+static int recent_keys_index;94,2270
+static int total_keys;97,2358
+static Lisp_Object recent_keys;100,2444
+Lisp_Object this_command_keys;107,2778
+ptrdiff_t this_command_key_count;108,2809
+static bool this_command_key_count_reset;112,2923
+static Lisp_Object raw_keybuf;116,3075
+static int raw_keybuf_count;117,3106
+#define GROW_RAW_KEYBUF 119,3136
+static ptrdiff_t this_single_command_key_start;125,3351
+static ptrdiff_t before_command_key_count;129,3499
+static ptrdiff_t before_command_echo_length;130,3542
+sigjmp_buf return_to_command_loop;135,3678
+static Lisp_Object recover_top_level_message;138,3792
+static Lisp_Object regular_top_level_message;143,3931
+static sys_jmp_buf getcjmp;147,4032
+bool waiting_for_input;150,4096
+static bool echoing;154,4187
+static struct kboard *ok_to_echo_at_next_pause;ok_to_echo_at_next_pause159,4329
+struct kboard *echo_kboard;echo_kboard166,4633
+Lisp_Object echo_message_buffer;171,4745
+bool immediate_quit;174,4838
+int quit_char;192,5624
+EMACS_INT command_loop_level;195,5681
+Lisp_Object unread_switch_frame;204,6109
+static ptrdiff_t last_non_minibuf_size;207,6217
+uintmax_t num_input_events;210,6335
+static EMACS_INT last_auto_save;214,6429
+static ptrdiff_t last_point_position;217,6524
+Lisp_Object internal_last_event_frame;228,7029
+static Lisp_Object read_key_sequence_cmd;232,7169
+static Lisp_Object read_key_sequence_remapped;233,7211
+static FILE *dribble;dribble236,7311
+bool input_pending;239,7369
+static bool input_was_pending;287,10023
+static struct input_event kbd_buffer[kbd_buffer291,10108
+static struct input_event *kbd_fetch_ptr;kbd_fetch_ptr297,10387
+static struct input_event * volatile kbd_store_ptr;302,10602
+static void recursive_edit_unwind 313,11089
+static Lisp_Object command_loop 314,11145
+static void echo_now 316,11186
+static ptrdiff_t echo_length 317,11215
+unsigned timers_run;320,11297
+struct timespec *input_available_clear_time;input_available_clear_time324,11409
+bool interrupt_input;328,11574
+bool interrupts_deferred;331,11672
+static struct timespec timer_idleness_start_time;335,11747
+static struct timespec timer_last_idleness_start_time;340,11917
+#define READABLE_EVENTS_DO_TIMERS_NOW 346,12047
+#define READABLE_EVENTS_FILTER_EVENTS 347,12095
+#define READABLE_EVENTS_IGNORE_SQUEEZABLES 348,12143
+static void (*keyboard_init_hook)keyboard_init_hook351,12265
+static bool get_input_pending 353,12308
+static bool readable_events 354,12345
+static Lisp_Object read_char_x_menu_prompt 355,12380
+static Lisp_Object read_char_minibuf_menu_prompt 357,12503
+static Lisp_Object make_lispy_event 358,12572
+static Lisp_Object make_lispy_movement 359,12632
+static Lisp_Object modify_event_symbol 363,12841
+static Lisp_Object make_lispy_switch_frame 366,13051
+static Lisp_Object make_lispy_focus_in 367,13109
+static Lisp_Object make_lispy_focus_out 369,13189
+static bool help_char_p 371,13276
+static void save_getcjmp 372,13315
+static void restore_getcjmp 373,13355
+static Lisp_Object apply_modifiers 374,13398
+static void clear_event 375,13453
+static void restore_kboard_configuration 376,13501
+static void deliver_input_available_signal 378,13569
+static void handle_interrupt 380,13632
+static _Noreturn void quit_throw_to_read_char 381,13669
+static void process_special_events 382,13723
+static void timer_start_idle 383,13766
+static void timer_stop_idle 384,13803
+static void timer_resume_idle 385,13839
+static void deliver_user_signal 386,13877
+static char *find_user_signal_name find_user_signal_name387,13916
+static void store_user_signal_events 388,13958
+kset_echo_string 392,14089
+kset_kbd_queue 397,14185
+kset_keyboard_translate_table 402,14277
+kset_last_prefix_arg 407,14400
+kset_last_repeatable_command 412,14505
+kset_local_function_key_map 417,14626
+kset_overriding_terminal_local_map 422,14745
+kset_real_last_command 427,14878
+kset_system_key_syms 432,14987
+echo_add_key 443,15250
+echo_char 527,17528
+echo_dash 541,17814
+echo_now 586,19141
+cancel_echoing 635,20615
+echo_length 648,20923
+echo_truncate 660,21254
+add_command_key 672,21583
+recursive_edit_1 697,22407
+record_auto_save 742,23849
+force_auto_save_soon 751,24017
+DEFUN ("recursive-edit", Frecursive_edit,759,24138
+DEFUN ("recursive-edit", Frecursive_edit,recursive-edit759,24138
+recursive_edit_unwind 804,25751
+any_kboard_state 817,26017
+single_kboard_state 838,26669
+not_single_kboard_state 848,26807
+struct kboard_stack858,27069
+ KBOARD *kboard;kboard860,27091
+ struct kboard_stack *next;next861,27109
+static struct kboard_stack *kboard_stack;kboard_stack864,27142
+push_kboard 867,27190
+pop_kboard 879,27379
+temporarily_switch_to_single_kboard 914,28267
+record_single_kboard_state 943,29441
+restore_kboard_configuration 952,29625
+cmd_error 970,30081
+cmd_error_internal 1024,31514
+DEFUN ("command-error-default-function", Fcommand_error_default_function,1043,32034
+DEFUN ("command-error-default-function", Fcommand_error_default_function,command-error-default-function1043,32034
+static Lisp_Object command_loop_2 1086,33641
+static Lisp_Object top_level_1 1087,33690
+command_loop 1094,33920
+command_loop_2 1134,35139
+top_level_2 1146,35343
+top_level_1 1152,35421
+DEFUN ("top-level", Ftop_level,1164,35791
+DEFUN ("top-level", Ftop_level,top-level1164,35791
+user_error 1183,36292
+DEFUN ("exit-recursive-edit", Fexit_recursive_edit,1189,36433
+DEFUN ("exit-recursive-edit", Fexit_recursive_edit,exit-recursive-edit1189,36433
+DEFUN ("abort-recursive-edit", Fabort_recursive_edit,1201,36823
+DEFUN ("abort-recursive-edit", Fabort_recursive_edit,abort-recursive-edit1201,36823
+tracking_off 1216,37285
+DEFUN ("internal--track-mouse", Ftrack_mouse,1234,37820
+DEFUN ("internal--track-mouse", Ftrack_mouse,track-mouse1234,37820
+bool ignore_mouse_drag_p;1256,38396
+some_mouse_moved 1259,38445
+static int read_key_sequence 1282,38803
+static void adjust_point_for_property 1284,38921
+Lisp_Object last_undo_boundary;1287,39036
+command_loop_1 1294,39277
+read_menu_command 1649,50893
+adjust_point_for_property 1678,51621
+safe_run_hooks_1 1831,57343
+safe_run_hooks_error 1841,57573
+safe_run_hook_funcall 1878,58580
+safe_run_hooks 1893,59062
+int poll_suppress_count;1908,59401
+static struct atimer *poll_timer;poll_timer1915,59491
+poll_for_input_1 1919,59593
+poll_for_input 1930,59793
+start_polling 1942,60057
+input_polling_used 1979,61095
+stop_polling 1994,61394
+set_poll_suppress_count 2009,61763
+bind_polling_period 2029,62145
+make_ctrl_char 2048,62496
+show_help_echo 2113,64459
+static Lisp_Object kbd_buffer_get_event 2152,65488
+static void record_char 2154,65600
+static Lisp_Object help_form_saved_window_configs;2156,65642
+read_char_help_form_unwind 2158,65705
+#define STOP_POLLING 2166,65963
+#define RESUME_POLLING 2170,66088
+read_event_from_main_queue 2175,66233
+read_decoded_event_from_main_queue 2249,68421
+#define MAX_ENCODED_BYTES 2254,68668
+echo_keystrokes_p 2342,71560
+read_char 2376,72852
+record_menu_key 3225,98953
+help_char_p 3258,99678
+record_char 3273,99957
+save_getcjmp 3412,104239
+restore_getcjmp 3418,104330
+readable_events 3430,104701
+int stop_character EXTERNALLY_VISIBLE;3497,106441
+event_to_kboard 3500,106497
+kbd_buffer_nr_stored 3522,107146
+kbd_buffer_store_event 3534,107487
+kbd_buffer_store_event_hold 3550,108029
+kbd_buffer_unget_event 3684,111621
+#define INPUT_EVENT_POS_MAX 3698,112022
+#define INPUT_EVENT_POS_MIN 3701,112151
+position_to_Time 3706,112291
+Time_to_position 3716,112518
+gen_help_event 3738,113175
+kbd_buffer_store_help_event 3756,113615
+discard_mouse_events 3773,113980
+kbd_buffer_events_waiting 3803,114715
+clear_event 3823,115072
+kbd_buffer_get_event 3836,115412
+process_special_events 4258,127885
+swallow_events 4322,129709
+timer_start_idle 4339,130102
+timer_stop_idle 4355,130580
+timer_resume_idle 4363,130724
+struct input_event last_timer_event EXTERNALLY_VISIBLE;4372,130916
+Lisp_Object pending_funcalls;4377,131176
+decode_timer 4381,131297
+timer_check_2 4414,132250
+timer_check 4572,136821
+DEFUN ("current-idle-time", Fcurrent_idle_time,4607,137666
+DEFUN ("current-idle-time", Fcurrent_idle_time,current-idle-time4607,137666
+static Lisp_Object accent_key_syms;4625,138243
+static Lisp_Object func_key_syms;4626,138279
+static Lisp_Object mouse_syms;4627,138313
+static Lisp_Object wheel_syms;4628,138344
+static Lisp_Object drag_n_drop_syms;4629,138375
+static const int lispy_accent_codes[lispy_accent_codes4634,138520
+static const char *const lispy_accent_keys[lispy_accent_keys4741,139882
+#define FUNCTION_KEY_OFFSET 4766,140318
+const char *const lispy_function_keys[lispy_function_keys4768,140351
+static const char *const lispy_multimedia_keys[lispy_multimedia_keys4962,148905
+static const char *const lispy_kana_keys[lispy_kana_keys5026,150139
+#define FUNCTION_KEY_OFFSET 5061,151755
+static const char *const lispy_function_keys[lispy_function_keys5065,151898
+#define ISO_FUNCTION_KEY_OFFSET 5149,154433
+static const char *const iso_lispy_function_keys[iso_lispy_function_keys5151,154473
+static Lisp_Object Vlispy_mouse_stem;5172,155332
+static const char *const lispy_wheel_names[lispy_wheel_names5174,155371
+static const char *const lispy_drag_n_drop_names[lispy_drag_n_drop_names5181,155623
+static short const scroll_bar_parts[scroll_bar_parts5189,155889
+static Lisp_Object button_down_location;5210,156914
+static int last_mouse_button;5215,157069
+static int last_mouse_x;5216,157099
+static int last_mouse_y;5217,157124
+static Time button_down_time;5218,157149
+static int double_click_count;5222,157233
+make_lispy_position 5228,157394
+toolkit_menubar_in_use 5456,163957
+make_scroll_bar_position 5469,164325
+make_lispy_event 5485,164971
+make_lispy_movement 6104,183534
+make_lispy_switch_frame 6131,184265
+make_lispy_focus_in 6137,184372
+make_lispy_focus_out 6145,184498
+parse_modifiers_uncached 6163,184948
+#define SINGLE_LETTER_MOD(6185,185468
+#undef SINGLE_LETTER_MOD6212,185909
+#define MULTI_LETTER_MOD(6214,185935
+#undef MULTI_LETTER_MOD6231,186403
+apply_modifiers_uncached 6273,187577
+static const char *const modifier_names[modifier_names6319,189196
+#define NUM_MOD_NAMES 6325,189402
+static Lisp_Object modifier_symbols;6327,189452
+lispy_modifier_list 6331,189589
+#define KEY_TO_CHAR(6353,190255
+parse_modifiers 6356,190331
+DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,6399,191520
+DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,event-symbol-parse-modifiers6399,191520
+apply_modifiers 6422,192394
+reorder_modifiers 6491,194723
+modify_event_symbol 6536,196531
+DEFUN ("event-convert-list", Fevent_convert_list,6628,199247
+DEFUN ("event-convert-list", Fevent_convert_list,event-convert-list6628,199247
+parse_solitary_modifier 6695,201138
+#define SINGLE_LETTER_MOD(6701,201261
+#define MULTI_LETTER_MOD(6705,201346
+#undef SINGLE_LETTER_MOD6763,202644
+#undef MULTI_LETTER_MOD6764,202669
+lucid_event_type_list_p 6775,202892
+get_input_pending 6814,203963
+record_asynch_buffer_change 6834,204582
+gobble_input 6872,205705
+tty_read_avail_input 6967,208313
+handle_async_input 7149,214042
+process_pending_signals 7165,214362
+unblock_input_to 7177,214648
+unblock_input 7200,215280
+totally_unblock_input 7209,215448
+handle_input_available_signal 7217,215532
+deliver_input_available_signal 7226,215703
+struct user_signal_info7235,215868
+ int sig;7238,215918
+ char *name;name7241,215959
+ int npending;7244,216010
+ struct user_signal_info *next;next7246,216027
+static struct user_signal_info *user_signals user_signals7250,216093
+add_user_signal 7253,216152
+handle_user_signal 7275,216601
+deliver_user_signal 7316,217561
+find_user_signal_name 7322,217662
+store_user_signal_events 7334,217844
+static void menu_bar_item 7362,218344
+static Lisp_Object menu_bar_one_keymap_changed_items;7363,218419
+static Lisp_Object menu_bar_items_vector;7368,218633
+static int menu_bar_items_index;7369,218675
+static const char *separator_names[separator_names7372,218710
+menu_separator_name_p 7393,219151
+menu_bar_items 7426,219855
+Lisp_Object item_properties;7568,224606
+menu_bar_item 7571,224648
+menu_item_eval_property_1 7647,227178
+eval_dyn 7658,227468
+menu_item_eval_property 7666,227678
+parse_menu_item 7686,228344
+static Lisp_Object tool_bar_items_vector;7965,236339
+static Lisp_Object tool_bar_item_properties;7970,236513
+static int ntool_bar_items;7974,236609
+static void init_tool_bar_items 7978,236667
+static void process_tool_bar_item 7979,236714
+static bool parse_tool_bar_item 7981,236804
+static void append_tool_bar_item 7982,236864
+tool_bar_items 7990,237086
+process_tool_bar_item 8075,239895
+#define PROP(8112,240972
+set_prop 8114,241041
+parse_tool_bar_item 8167,242456
+#undef PROP8379,248847
+init_tool_bar_items 8387,248972
+append_tool_bar_item 8401,249264
+read_char_x_menu_prompt 8443,250774
+read_char_minibuf_menu_prompt 8503,252448
+#define PUSH_C_STR(8527,253017
+follow_key 8726,258556
+active_maps 8733,258698
+typedef struct keyremap8742,259024
+ Lisp_Object parent;8745,259110
+ Lisp_Object map;8748,259227
+ int start,8753,259449
+ int start, end;8753,259449
+} keyremap;8754,259467
+access_keymap_keyremap 8764,259811
+keyremap_step 8811,261453
+test_undefined 8867,262937
+read_key_sequence 8916,264864
+read_key_sequence_vs 9826,295824
+DEFUN ("read-key-sequence", Fread_key_sequence,9885,297297
+DEFUN ("read-key-sequence", Fread_key_sequence,read-key-sequence9885,297297
+DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,9938,299985
+DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,read-key-sequence-vector9938,299985
+detect_input_pending 9950,300491
+detect_input_pending_ignore_squeezables 9959,300657
+detect_input_pending_run_timers 9967,300873
+clear_input_pending 9985,301365
+requeued_events_pending_p 9997,301735
+DEFUN ("input-pending-p", Finput_pending_p,10002,301816
+DEFUN ("input-pending-p", Finput_pending_p,input-pending-p10002,301816
+DEFUN ("recent-keys", Frecent_keys,10024,302599
+DEFUN ("recent-keys", Frecent_keys,recent-keys10024,302599
+DEFUN ("this-command-keys", Fthis_command_keys,10055,303520
+DEFUN ("this-command-keys", Fthis_command_keys,this-command-keys10055,303520
+DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,10068,303961
+DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,this-command-keys-vector10068,303961
+DEFUN ("this-single-command-keys", Fthis_single_command_keys,10080,304383
+DEFUN ("this-single-command-keys", Fthis_single_command_keys,this-single-command-keys10080,304383
+DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,10096,304958
+DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,this-single-command-raw-keys10096,304958
+DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,10109,305498
+DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,reset-this-command-lengths10109,305498
+DEFUN ("clear-this-command-keys", Fclear_this_command_keys,10136,306513
+DEFUN ("clear-this-command-keys", Fclear_this_command_keys,clear-this-command-keys10136,306513
+DEFUN ("recursion-depth", Frecursion_depth,10158,307072
+DEFUN ("recursion-depth", Frecursion_depth,recursion-depth10158,307072
+DEFUN ("open-dribble-file", Fopen_dribble_file,10169,307409
+DEFUN ("open-dribble-file", Fopen_dribble_file,open-dribble-file10169,307409
+DEFUN ("discard-input", Fdiscard_input,10203,308450
+DEFUN ("discard-input", Fdiscard_input,discard-input10203,308450
+DEFUN ("suspend-emacs", Fsuspend_emacs,10225,308952
+DEFUN ("suspend-emacs", Fsuspend_emacs,suspend-emacs10225,308952
+stuff_buffered_input 10285,311048
+set_waiting_for_input 10323,312019
+clear_waiting_for_input 10337,312393
+handle_interrupt_signal 10351,312757
+deliver_interrupt_signal 10378,313645
+static int volatile force_quit_count;10387,313935
+handle_interrupt 10401,314417
+quit_throw_to_read_char 10541,318714
+DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,10562,319291
+DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,set-input-interrupt-mode10562,319291
+DEFUN ("set-output-flow-control", Fset_output_flow_control,10609,320519
+DEFUN ("set-output-flow-control", Fset_output_flow_control,set-output-flow-control10609,320519
+DEFUN ("set-input-meta-mode", Fset_input_meta_mode,10643,321435
+DEFUN ("set-input-meta-mode", Fset_input_meta_mode,set-input-meta-mode10643,321435
+DEFUN ("set-quit-char", Fset_quit_char,10694,322709
+DEFUN ("set-quit-char", Fset_quit_char,set-quit-char10694,322709
+DEFUN ("set-input-mode", Fset_input_mode,10729,323573
+DEFUN ("set-input-mode", Fset_input_mode,set-input-mode10729,323573
+DEFUN ("current-input-mode", Fcurrent_input_mode,10750,324462
+DEFUN ("current-input-mode", Fcurrent_input_mode,current-input-mode10750,324462
+DEFUN ("posn-at-x-y", Fposn_at_x_y,10787,325840
+DEFUN ("posn-at-x-y", Fposn_at_x_y,posn-at-x-y10787,325840
+DEFUN ("posn-at-point", Fposn_at_point,10824,327063
+DEFUN ("posn-at-point", Fposn_at_point,posn-at-point10824,327063
+init_kboard 10861,328217
+allocate_kboard 10893,329287
+wipe_kboard 10909,329640
+delete_kboard 10917,329754
+init_keyboard 10942,330284
+struct event_head11021,332699
+ short var;11023,332719
+ short kind;11024,332732
+static const struct event_head head_table[head_table11027,332750
+syms_of_keyboard 11045,333580
+ DEFVAR_LISP ("internal--top-level-message"11058,333975
+ DEFVAR_LISP ("last-command-event"11312,342176
+ DEFVAR_LISP ("last-nonmenu-event"11315,342300
+ DEFVAR_LISP ("last-input-event"11321,342639
+ DEFVAR_LISP ("unread-command-events"11324,342733
+ DEFVAR_LISP ("unread-post-input-method-events"11332,343193
+ DEFVAR_LISP ("unread-input-method-events"11338,343532
+ DEFVAR_LISP ("meta-prefix-char"11346,343901
+ DEFVAR_KBOARD ("last-command"11351,344109
+ DEFVAR_KBOARD ("real-last-command"11368,344790
+ DEFVAR_KBOARD ("last-repeatable-command"11372,344976
+ DEFVAR_LISP ("this-command"11378,345264
+ DEFVAR_LISP ("real-this-command"11384,345501
+ DEFVAR_LISP ("this-command-keys-shift-translated"11388,345683
+ DEFVAR_LISP ("this-original-command"11396,346126
+ DEFVAR_INT ("auto-save-interval"11403,346523
+ DEFVAR_LISP ("auto-save-timeout"11408,346737
+ DEFVAR_LISP ("echo-keystrokes"11415,347082
+ DEFVAR_INT ("polling-period"11421,347353
+ DEFVAR_LISP ("double-click-time"11428,347696
+ DEFVAR_INT ("double-click-fuzz"11435,348032
+ DEFVAR_INT ("num-input-keys"11446,348522
+ DEFVAR_INT ("num-nonmacro-input-events"11452,348797
+ DEFVAR_LISP ("last-event-frame"11457,349035
+ DEFVAR_LISP ("tty-erase-char"11463,349314
+ DEFVAR_LISP ("help-char"11466,349437
+ DEFVAR_LISP ("help-event-list"11472,349720
+ DEFVAR_LISP ("help-form"11477,349931
+ DEFVAR_LISP ("prefix-help-command"11483,350179
+ DEFVAR_LISP ("top-level"11489,350457
+ DEFVAR_KBOARD ("keyboard-translate-table"11495,350678
+ DEFVAR_BOOL ("cannot-suspend"11511,351491
+ DEFVAR_BOOL ("menu-prompting"11516,351718
+ DEFVAR_LISP ("menu-prompt-more-char"11526,352148
+ DEFVAR_INT ("extra-keyboard-modifiers"11531,352394
+ DEFVAR_LISP ("deactivate-mark"11545,353120
+ DEFVAR_LISP ("pre-command-hook"11553,353489
+ DEFVAR_LISP ("post-command-hook"11560,353844
+ DEFVAR_LISP ("echo-area-clear-hook"11568,354207
+ DEFVAR_LISP ("lucid-menu-bar-dirty-flag"11574,354422
+ DEFVAR_LISP ("menu-bar-final-items"11578,354625
+ DEFVAR_LISP ("tool-bar-separator-image-expression"11583,354875
+ DEFVAR_KBOARD ("overriding-terminal-local-map"11589,355233
+ DEFVAR_LISP ("overriding-local-map"11598,355655
+ DEFVAR_LISP ("overriding-local-map-menu-flag"11607,356106
+ DEFVAR_LISP ("special-event-map"11613,356445
+ DEFVAR_LISP ("track-mouse"11617,356633
+ DEFVAR_KBOARD ("system-key-alist"11620,356760
+ DEFVAR_KBOARD ("local-function-key-map"11629,357141
+ DEFVAR_KBOARD ("input-decode-map"11658,358600
+ DEFVAR_LISP ("function-key-map"11675,359388
+ DEFVAR_LISP ("key-translation-map"11683,359804
+ DEFVAR_LISP ("deferred-action-list"11689,360148
+ DEFVAR_LISP ("deferred-action-function"11694,360396
+ DEFVAR_LISP ("delayed-warnings-list"11700,360695
+ DEFVAR_LISP ("timer-list"11708,361103
+ DEFVAR_LISP ("timer-idle-list"11712,361255
+ DEFVAR_LISP ("input-method-function"11716,361418
+ DEFVAR_LISP ("input-method-previous-message"11737,362387
+ DEFVAR_LISP ("show-help-function"11744,362748
+ DEFVAR_LISP ("disable-point-adjustment"11749,362980
+ DEFVAR_LISP ("global-disable-point-adjustment"11761,363530
+ DEFVAR_LISP ("minibuffer-message-timeout"11770,363896
+ DEFVAR_LISP ("throw-on-input"11775,364174
+ DEFVAR_LISP ("command-error-function"11781,364425
+ DEFVAR_LISP ("enable-disabled-menus-and-buttons"11790,364912
+ DEFVAR_LISP ("select-active-regions"11798,365239
+ DEFVAR_LISP ("saved-region-selection"11807,365631
+ DEFVAR_LISP ("selection-inhibit-update-commands"11815,366016
+ DEFVAR_LISP ("debug-on-event"11825,366557
+keys_of_keyboard 11841,367118
+mark_kboards 11916,370437
+ DEFVAR_LISP ("internal--top-level-message",\111058,333975
+ DEFVAR_LISP ("last-command-event",\111312,342176
+ DEFVAR_LISP ("last-nonmenu-event",\111315,342300
+ DEFVAR_LISP ("last-input-event",\111321,342639
+ DEFVAR_LISP ("unread-command-events",\111324,342733
+ DEFVAR_LISP ("unread-post-input-method-events",\111332,343193
+ DEFVAR_LISP ("unread-input-method-events",\111338,343532
+ DEFVAR_LISP ("meta-prefix-char",\111346,343901
+ DEFVAR_KBOARD ("last-command",\111351,344109
+ DEFVAR_KBOARD ("real-last-command",\111368,344790
+ DEFVAR_KBOARD ("last-repeatable-command",\111372,344976
+ DEFVAR_LISP ("this-command",\111378,345264
+ DEFVAR_LISP ("real-this-command",\111384,345501
+ DEFVAR_LISP ("this-command-keys-shift-translated",\111388,345683
+ DEFVAR_LISP ("this-original-command",\111396,346126
+ DEFVAR_INT ("auto-save-interval",\111403,346523
+ DEFVAR_LISP ("auto-save-timeout",\111408,346737
+ DEFVAR_LISP ("echo-keystrokes",\111415,347082
+ DEFVAR_INT ("polling-period",\111421,347353
+ DEFVAR_LISP ("double-click-time",\111428,347696
+ DEFVAR_INT ("double-click-fuzz",\111435,348032
+ DEFVAR_INT ("num-input-keys",\111446,348522
+ DEFVAR_INT ("num-nonmacro-input-events",\111452,348797
+ DEFVAR_LISP ("last-event-frame",\111457,349035
+ DEFVAR_LISP ("tty-erase-char",\111463,349314
+ DEFVAR_LISP ("help-char",\111466,349437
+ DEFVAR_LISP ("help-event-list",\111472,349720
+ DEFVAR_LISP ("help-form",\111477,349931
+ DEFVAR_LISP ("prefix-help-command",\111483,350179
+ DEFVAR_LISP ("top-level",\111489,350457
+ DEFVAR_KBOARD ("keyboard-translate-table",\111495,350678
+ DEFVAR_BOOL ("cannot-suspend",\111511,351491
+ DEFVAR_BOOL ("menu-prompting",\111516,351718
+ DEFVAR_LISP ("menu-prompt-more-char",\111526,352148
+ DEFVAR_INT ("extra-keyboard-modifiers",\111531,352394
+ DEFVAR_LISP ("deactivate-mark",\111545,353120
+ DEFVAR_LISP ("pre-command-hook",\111553,353489
+ DEFVAR_LISP ("post-command-hook",\111560,353844
+ DEFVAR_LISP ("echo-area-clear-hook",\111568,354207
+ DEFVAR_LISP ("lucid-menu-bar-dirty-flag",\111574,354422
+ DEFVAR_LISP ("menu-bar-final-items",\111578,354625
+ DEFVAR_LISP ("tool-bar-separator-image-expression",\111583,354875
+ DEFVAR_KBOARD ("overriding-terminal-local-map",\111589,355233
+ DEFVAR_LISP ("overriding-local-map",\111598,355655
+ DEFVAR_LISP ("overriding-local-map-menu-flag",\111607,356106
+ DEFVAR_LISP ("special-event-map",\111613,356445
+ DEFVAR_LISP ("track-mouse",\111617,356633
+ DEFVAR_KBOARD ("system-key-alist",\111620,356760
+ DEFVAR_KBOARD ("local-function-key-map",\111629,357141
+ DEFVAR_KBOARD ("input-decode-map",\111658,358600
+ DEFVAR_LISP ("function-key-map",\111675,359388
+ DEFVAR_LISP ("key-translation-map",\111683,359804
+ DEFVAR_LISP ("deferred-action-list",\111689,360148
+ DEFVAR_LISP ("deferred-action-function",\111694,360396
+ DEFVAR_LISP ("delayed-warnings-list",\111700,360695
+ DEFVAR_LISP ("timer-list",\111708,361103
+ DEFVAR_LISP ("timer-idle-list",\111712,361255
+ DEFVAR_LISP ("input-method-function",\111716,361418
+ DEFVAR_LISP ("input-method-previous-message",\111737,362387
+ DEFVAR_LISP ("show-help-function",\111744,362748
+ DEFVAR_LISP ("disable-point-adjustment",\111749,362980
+ DEFVAR_LISP ("global-disable-point-adjustment",\111761,363530
+ DEFVAR_LISP ("minibuffer-message-timeout",\111770,363896
+ DEFVAR_LISP ("throw-on-input",\111775,364174
+ DEFVAR_LISP ("command-error-function",\111781,364425
+ DEFVAR_LISP ("enable-disabled-menus-and-buttons",\111790,364912
+ DEFVAR_LISP ("select-active-regions",\111798,365239
+ DEFVAR_LISP ("saved-region-selection",\111807,365631
+ DEFVAR_LISP ("selection-inhibit-update-commands",\111815,366016
+ DEFVAR_LISP ("debug-on-event",\111825,366557
c-src/emacs/src/lisp.h,41391
-#define EMACS_LISP_H22,800
-#define DECLARE_GDB_SYM(47,1421
-# define DEFINE_GDB_SYMBOL_BEGIN(49,1508
-# define DEFINE_GDB_SYMBOL_END(50,1578
-# define DEFINE_GDB_SYMBOL_BEGIN(52,1625
-# define DEFINE_GDB_SYMBOL_END(53,1702
-#undef min57,1790
-#undef max58,1801
-#define max(59,1812
-#define min(60,1854
-#define ARRAYELTS(63,1936
-#define GCTYPEBITS 67,2079
-DEFINE_GDB_SYMBOL_BEGIN GCTYPEBITS66,2037
-# define NONPOINTER_BITS 78,2567
-# define NONPOINTER_BITS 80,2600
-typedef int EMACS_INT;91,3023
-typedef unsigned int EMACS_UINT;92,3046
-# define EMACS_INT_MAX 93,3079
-# define pI 94,3111
-typedef long int EMACS_INT;96,3203
-typedef unsigned long EMACS_UINT;97,3231
-# define EMACS_INT_MAX 98,3265
-# define pI 99,3298
-typedef long long int EMACS_INT;103,3477
-typedef unsigned long long int EMACS_UINT;104,3510
-# define EMACS_INT_MAX 105,3553
-# define pI 106,3587
-enum { BOOL_VECTOR_BITS_PER_CHAR 114,3804
-#define BOOL_VECTOR_BITS_PER_CHAR 115,3840
-typedef size_t bits_word;123,4165
-# define BITS_WORD_MAX 124,4191
-enum { BITS_PER_BITS_WORD 125,4223
-typedef unsigned char bits_word;127,4290
-# define BITS_WORD_MAX 128,4323
-enum { BITS_PER_BITS_WORD 129,4386
-verify 131,4450
- BITS_PER_CHAR 136,4570
- BITS_PER_SHORT 137,4605
- BITS_PER_LONG 138,4657
- BITS_PER_EMACS_INT 139,4712
-typedef intmax_t printmax_t;148,5089
-typedef uintmax_t uprintmax_t;149,5118
-# define pMd 150,5149
-# define pMu 151,5170
-typedef EMACS_INT printmax_t;153,5197
-typedef EMACS_UINT uprintmax_t;154,5227
-# define pMd 155,5259
-# define pMu 156,5278
-# define pD 165,5664
-# define pD 167,5709
-# define pD 169,5756
-# define pD 171,5779
-# define eassert(200,7062
-# define eassume(201,7140
-extern _Noreturn void die 204,7206
-extern bool suppress_checking EXTERNALLY_VISIBLE;206,7268
-# define eassert(208,7319
-# define eassume(212,7450
-enum Lisp_Bits239,8519
-#define GCALIGNMENT 243,8647
- VALBITS 246,8742
- INTTYPEBITS 249,8838
- FIXNUM_BITS 252,8945
-#define VAL_MAX 263,9327
-#define USE_LSB_TAG 271,9777
-DEFINE_GDB_SYMBOL_BEGIN USE_LSB_TAG270,9733
-# define alignas(281,10077
-# define GCALIGNED 288,10227
-# define GCALIGNED 290,10292
-# define lisp_h_XLI(327,11642
-# define lisp_h_XIL(328,11673
-# define lisp_h_XLI(330,11724
-# define lisp_h_XIL(331,11751
-#define lisp_h_CHECK_LIST_CONS(333,11785
-#define lisp_h_CHECK_NUMBER(334,11856
-#define lisp_h_CHECK_SYMBOL(335,11927
-#define lisp_h_CHECK_TYPE(336,11996
-#define lisp_h_CONSP(338,12107
-#define lisp_h_EQ(339,12156
-#define lisp_h_FLOATP(340,12201
-#define lisp_h_INTEGERP(341,12252
-#define lisp_h_MARKERP(342,12333
-#define lisp_h_MISCP(343,12408
-#define lisp_h_NILP(344,12457
-#define lisp_h_SET_SYMBOL_VAL(345,12493
-#define lisp_h_SYMBOL_CONSTANT_P(347,12607
-#define lisp_h_SYMBOL_VAL(348,12671
-#define lisp_h_SYMBOLP(350,12772
-#define lisp_h_VECTORLIKEP(351,12825
-#define lisp_h_XCAR(352,12886
-#define lisp_h_XCDR(353,12924
-#define lisp_h_XCONS(354,12964
-#define lisp_h_XHASH(356,13059
-#define lisp_h_XPNTR(357,13093
-# define lisp_h_check_cons_list(360,13221
-# define lisp_h_make_number(363,13289
-# define lisp_h_XFASTINT(365,13392
-# define lisp_h_XINT(366,13429
-# define lisp_h_XSYMBOL(367,13478
-# define lisp_h_XTYPE(371,13631
-# define lisp_h_XUNTAG(372,13696
-# define XLI(381,14086
-# define XIL(382,14117
-# define CHECK_LIST_CONS(383,14148
-# define CHECK_NUMBER(384,14209
-# define CHECK_SYMBOL(385,14258
-# define CHECK_TYPE(386,14307
-# define CONSP(387,14382
-# define EQ(388,14417
-# define FLOATP(389,14452
-# define INTEGERP(390,14489
-# define MARKERP(391,14530
-# define MISCP(392,14569
-# define NILP(393,14604
-# define SET_SYMBOL_VAL(394,14637
-# define SYMBOL_CONSTANT_P(395,14700
-# define SYMBOL_VAL(396,14763
-# define SYMBOLP(397,14812
-# define VECTORLIKEP(398,14851
-# define XCAR(399,14898
-# define XCDR(400,14931
-# define XCONS(401,14964
-# define XHASH(402,14999
-# define XPNTR(403,15034
-# define check_cons_list(405,15097
-# define make_number(408,15176
-# define XFASTINT(409,15224
-# define XINT(410,15266
-# define XSYMBOL(411,15300
-# define XTYPE(412,15340
-# define XUNTAG(413,15376
-#define LISP_MACRO_DEFUN(421,15672
-#define LISP_MACRO_DEFUN_VOID(425,15845
-#define INTMASK 437,16289
-#define case_Lisp_Int 438,16342
-#define ENUM_BF(445,16681
-#define ENUM_BF(447,16722
-enum Lisp_Type451,16763
- Lisp_Symbol 454,16851
- Lisp_Misc 458,16993
- Lisp_Int0 461,17067
- Lisp_Int1 462,17086
- Lisp_String 466,17264
- Lisp_Vectorlike 472,17543
- Lisp_Cons 475,17632
- Lisp_Float 477,17670
-enum Lisp_Misc_Type485,18016
- Lisp_Misc_Free 487,18040
- Lisp_Misc_Marker,488,18069
- Lisp_Misc_Overlay,489,18091
- Lisp_Misc_Save_Value,490,18114
- Lisp_Misc_Finalizer,491,18140
- Lisp_Misc_Float,494,18275
- Lisp_Misc_Limit496,18359
-enum Lisp_Fwd_Type502,18543
- Lisp_Fwd_Int,504,18566
- Lisp_Fwd_Bool,505,18619
- Lisp_Fwd_Obj,506,18670
- Lisp_Fwd_Buffer_Obj,507,18729
- Lisp_Fwd_Kboard_Obj 508,18800
-typedef struct { EMACS_INT i;567,21781
-typedef struct { EMACS_INT i; } Lisp_Object;567,21781
-#define LISP_INITIALLY(569,21827
-#undef CHECK_LISP_OBJECT_TYPE571,21858
-enum CHECK_LISP_OBJECT_TYPE 572,21888
-enum CHECK_LISP_OBJECT_TYPE { CHECK_LISP_OBJECT_TYPE 572,21888
-typedef EMACS_INT Lisp_Object;577,22064
-#define LISP_INITIALLY(578,22095
-enum CHECK_LISP_OBJECT_TYPE 579,22125
-enum CHECK_LISP_OBJECT_TYPE { CHECK_LISP_OBJECT_TYPE 579,22125
-#define LISP_INITIALLY_ZERO 582,22226
-INLINE bool BOOL_VECTOR_P 588,22350
-INLINE bool BUFFER_OBJFWDP 589,22391
-INLINE bool BUFFERP 590,22438
-INLINE bool CHAR_TABLE_P 591,22473
-INLINE Lisp_Object CHAR_TABLE_REF_ASCII 592,22513
-INLINE bool 593,22579
-INLINE bool 594,22614
-INLINE bool functionp 595,22650
-INLINE bool 596,22687
-INLINE bool 597,22725
-INLINE bool 598,22762
-INLINE bool 599,22797
-INLINE bool OVERLAYP 600,22831
-INLINE bool PROCESSP 601,22867
-INLINE bool PSEUDOVECTORP 602,22903
-INLINE bool SAVE_VALUEP 603,22949
-INLINE bool FINALIZERP 604,22988
-INLINE void set_sub_char_table_contents 605,23026
-INLINE bool STRINGP 607,23116
-INLINE bool SUB_CHAR_TABLE_P 608,23151
-INLINE bool SUBRP 609,23195
-INLINE bool 610,23228
-INLINE bool 611,23265
-INLINE bool WINDOWP 612,23306
-INLINE bool TERMINALP 613,23341
-INLINE struct Lisp_Save_Value *XSAVE_VALUE XSAVE_VALUE614,23378
-INLINE struct Lisp_Finalizer *XFINALIZER XFINALIZER615,23436
-INLINE struct Lisp_Symbol *(XSYMBOL)616,23492
-INLINE void 617,23544
-extern Lisp_Object char_table_ref 620,23616
-extern void char_table_set 621,23670
-extern _Noreturn Lisp_Object wrong_type_argument 624,23757
-extern _Noreturn void wrong_choice 625,23834
-extern bool might_dump;628,23925
-extern bool initialized;631,24061
-extern double extract_float 634,24117
-enum symbol_interned639,24199
- SYMBOL_UNINTERNED 641,24222
- SYMBOL_INTERNED 642,24247
- SYMBOL_INTERNED_IN_INITIAL_OBARRAY 643,24270
-enum symbol_redirect646,24315
- SYMBOL_PLAINVAL 648,24338
- SYMBOL_VARALIAS 649,24362
- SYMBOL_LOCALIZED 650,24386
- SYMBOL_FORWARDED 651,24410
-struct Lisp_Symbol654,24437
- bool_bf gcmarkbit 656,24458
- ENUM_BF (symbol_redirect) redirect 663,24793
- unsigned constant 668,25011
- unsigned interned 672,25131
- bool_bf declared_special 676,25293
- bool_bf pinned 679,25394
- Lisp_Object name;682,25463
- Lisp_Object value;687,25631
- struct Lisp_Symbol *alias;alias688,25654
- struct Lisp_Buffer_Local_Value *blv;blv689,25685
- union Lisp_Fwd *fwd;fwd690,25726
- } val;691,25751
- Lisp_Object function;694,25823
- Lisp_Object plist;697,25885
- struct Lisp_Symbol *next;next700,25974
-#define EXFUN(707,26252
-#define DEFUN_ARGS_MANY 712,26446
-#define DEFUN_ARGS_UNEVALLED 713,26498
-#define DEFUN_ARGS_0 714,26541
-#define DEFUN_ARGS_1 715,26569
-#define DEFUN_ARGS_2 716,26604
-#define DEFUN_ARGS_3 717,26652
-#define DEFUN_ARGS_4 718,26713
-#define DEFUN_ARGS_5 719,26787
-#define DEFUN_ARGS_6 721,26880
-#define DEFUN_ARGS_7 723,26986
-#define DEFUN_ARGS_8 725,27105
-#define TAG_PTR(729,27296
-#define TAG_SYMOFFSET(734,27543
-#define XLI_BUILTIN_LISPSYM(741,27842
-#define DEFINE_LISP_SYMBOL(746,28101
-# define DEFINE_NON_NIL_Q_SYMBOL_MACROS 755,28572
-LISP_MACRO_DEFUN 762,28777
-# define ARRAY_MARK_FLAG 768,29024
-# define PSEUDOVECTOR_FLAG 774,29267
-enum pvec_type780,29568
- PVEC_NORMAL_VECTOR,782,29585
- PVEC_FREE,783,29607
- PVEC_PROCESS,784,29620
- PVEC_FRAME,785,29636
- PVEC_WINDOW,786,29650
- PVEC_BOOL_VECTOR,787,29665
- PVEC_BUFFER,788,29685
- PVEC_HASH_TABLE,789,29700
- PVEC_TERMINAL,790,29719
- PVEC_WINDOW_CONFIGURATION,791,29736
- PVEC_SUBR,792,29765
- PVEC_OTHER,793,29778
- PVEC_COMPILED,795,29856
- PVEC_CHAR_TABLE,796,29873
- PVEC_SUB_CHAR_TABLE,797,29892
- PVEC_FONT 798,29915
-enum More_Lisp_Bits801,29991
- PSEUDOVECTOR_SIZE_BITS 808,30382
- PSEUDOVECTOR_SIZE_MASK 809,30415
- PSEUDOVECTOR_REST_BITS 813,30625
- PSEUDOVECTOR_REST_MASK 814,30658
- PSEUDOVECTOR_AREA_BITS 818,30823
- PVEC_TYPE_MASK 819,30901
-# define VALMASK 829,31302
-DEFINE_GDB_SYMBOL_BEGIN VALMASK828,31257
-#define MOST_POSITIVE_FIXNUM 834,31532
-#define MOST_NEGATIVE_FIXNUM 835,31592
-XINT 874,32684
-XFASTINT 889,33035
-XSYMBOL 899,33263
-XTYPE 910,33481
-XUNTAG 918,33661
-LISP_MACRO_DEFUN 927,33857
-LISP_MACRO_DEFUN 940,34242
-#define FIXNUM_OVERFLOW_P(958,34855
-LISP_MACRO_DEFUN FIXNUM_OVERFLOW_P952,34632
-LISP_MACRO_DEFUN 970,35171
-XSTRING 980,35391
-#define SYMBOL_INDEX(988,35575
-XFLOAT 991,35636
-XPROCESS 1000,35778
-XWINDOW 1007,35895
-XTERMINAL 1014,36012
-XSUBR 1021,36134
-XBUFFER 1028,36245
-XCHAR_TABLE 1035,36369
-XSUB_CHAR_TABLE 1042,36506
-XBOOL_VECTOR 1049,36648
-make_lisp_ptr 1058,36827
-make_lisp_symbol 1066,37013
-builtin_lisp_symbol 1074,37197
-#define XSETINT(1079,37279
-#define XSETFASTINT(1080,37325
-#define XSETCONS(1081,37375
-#define XSETVECTOR(1082,37435
-#define XSETSTRING(1083,37503
-#define XSETSYMBOL(1084,37567
-#define XSETFLOAT(1085,37621
-#define XSETMISC(1086,37683
-#define XSETPVECTYPE(1090,37772
-#define XSETPVECTYPESIZE(1092,37888
-#define XSETPSEUDOVECTOR(1099,38185
-#define XSETTYPED_PSEUDOVECTOR(1105,38369
-#define XSETWINDOW_CONFIGURATION(1110,38579
-#define XSETPROCESS(1112,38675
-#define XSETWINDOW(1113,38741
-#define XSETTERMINAL(1114,38805
-#define XSETSUBR(1115,38873
-#define XSETCOMPILED(1116,38933
-#define XSETBUFFER(1117,39001
-#define XSETCHAR_TABLE(1118,39065
-#define XSETBOOL_VECTOR(1119,39137
-#define XSETSUB_CHAR_TABLE(1120,39211
-XINTPTR 1128,39581
-make_pointer_integer 1134,39661
-LISP_MACRO_DEFUN_VOID 1143,39826
-typedef struct interval *INTERVAL;INTERVAL1149,39987
- Lisp_Object cdr;1159,40162
- struct Lisp_Cons *chain;chain1162,40236
-xcar_addr 1174,40760
-xcdr_addr 1179,40837
-LISP_MACRO_DEFUN 1185,40931
-XSETCDR 1198,41307
-CAR 1205,41457
-CDR 1212,41591
-CAR_SAFE 1221,41791
-CDR_SAFE 1226,41877
-STRING_MULTIBYTE 1243,42250
-#define STRING_BYTES_BOUND 1261,43057
-#define STRING_SET_UNIBYTE(1265,43201
-#define STRING_SET_MULTIBYTE(1275,43516
-SDATA 1286,43830
-SSDATA 1291,43908
-SREF 1297,44037
-SSET 1302,44128
-SCHARS 1307,44242
-extern ptrdiff_t string_bytes 1313,44337
-STRING_BYTES 1316,44415
-SBYTES 1326,44595
-STRING_SET_CHARS 1331,44681
-struct vectorlike_header1343,45232
- ptrdiff_t size;1364,46383
-struct Lisp_Vector1369,46482
- struct vectorlike_header header;1371,46505
- Lisp_Object contents[contents1372,46542
- ALIGNOF_STRUCT_LISP_VECTOR1378,46681
-struct Lisp_Bool_Vector1384,46864
- struct vectorlike_header header;1388,47012
- EMACS_INT size;1390,47086
- bits_word data[data1395,47319
-bool_vector_size 1399,47385
-bool_vector_data 1407,47523
-bool_vector_uchar_data 1413,47617
-bool_vector_words 1421,47803
-bool_vector_bytes 1428,47998
-bool_vector_bitref 1437,48238
-bool_vector_ref 1445,48478
-bool_vector_set 1453,48618
- header_size 1471,49047
- bool_header_size 1472,49106
- word_size 1473,49171
-AREF 1479,49284
-aref_addr 1485,49391
-ASIZE 1491,49501
-ASET 1497,49583
-gc_aset 1504,49742
-enum { NIL_IS_ZERO 1515,50269
-memclear 1520,50464
-#define VECSIZE(1531,50762
-#define PSEUDOVECSIZE(1538,51047
-#define UNSIGNED_CMP(1546,51480
-#define ASCII_CHAR_P(1552,51734
-enum CHARTAB_SIZE_BITS1565,52489
- CHARTAB_SIZE_BITS_0 1567,52516
- CHARTAB_SIZE_BITS_1 1568,52545
- CHARTAB_SIZE_BITS_2 1569,52574
- CHARTAB_SIZE_BITS_3 1570,52603
-extern const int chartab_size[chartab_size1573,52637
-struct Lisp_Char_Table1575,52672
- struct vectorlike_header header;1581,52928
- Lisp_Object defalt;1585,53078
- Lisp_Object parent;1590,53280
- Lisp_Object purpose;1594,53398
- Lisp_Object ascii;1598,53564
- Lisp_Object contents[contents1600,53588
- Lisp_Object extras[extras1603,53699
-struct Lisp_Sub_Char_Table1606,53752
- struct vectorlike_header header;1610,53918
- int depth;1618,54341
- int min_char;1621,54417
- Lisp_Object contents[contents1624,54492
-CHAR_TABLE_REF_ASCII 1628,54566
-CHAR_TABLE_REF 1648,55113
-CHAR_TABLE_SET 1658,55402
-struct Lisp_Subr1670,55786
- struct vectorlike_header header;1672,55807
- Lisp_Object (*a0)a01674,55856
- Lisp_Object (*a1)a11675,55888
- Lisp_Object (*a2)a21676,55927
- Lisp_Object (*a3)a31677,55979
- Lisp_Object (*a4)a41678,56044
- Lisp_Object (*a5)a51679,56122
- Lisp_Object (*a6)a61680,56213
- Lisp_Object (*a7)a71681,56317
- Lisp_Object (*a8)a81682,56434
- Lisp_Object (*aUNEVALLED)aUNEVALLED1683,56564
- Lisp_Object (*aMANY)aMANY1684,56616
- } function;1685,56671
- short min_args,1686,56687
- short min_args, max_args;1686,56687
- const char *symbol_name;symbol_name1687,56717
- const char *intspec;intspec1688,56746
- const char *doc;doc1689,56771
-enum char_table_specials1692,56798
- CHAR_TABLE_STANDARD_SLOTS 1697,56993
- SUB_CHAR_TABLE_OFFSET 1701,57214
-CHAR_TABLE_EXTRA_SLOTS 1707,57377
-verify 1714,57596
-LISP_MACRO_DEFUN 1723,57921
-SYMBOL_BLV 1732,58181
-SYMBOL_FWD 1738,58316
-LISP_MACRO_DEFUN_VOID 1744,58428
-SET_SYMBOL_BLV 1754,58691
-SET_SYMBOL_FWD 1760,58850
-SYMBOL_NAME 1767,59001
-SYMBOL_INTERNED_P 1775,59130
-SYMBOL_INTERNED_IN_INITIAL_OBARRAY_P 1783,59299
-#define DEFSYM(1796,59809
-LISP_MACRO_DEFUN DEFSYM1792,59630
-struct hash_table_test1805,60062
- Lisp_Object name;1808,60139
- Lisp_Object user_hash_function;1811,60206
- Lisp_Object user_cmp_function;1814,60297
- bool (*cmpfn)cmpfn1817,60372
- EMACS_UINT (*hashfn)hashfn1820,60486
-struct Lisp_Hash_Table1823,60555
- struct vectorlike_header header;1826,60649
- Lisp_Object weak;1830,60783
- Lisp_Object rehash_size;1835,61007
- Lisp_Object rehash_threshold;1839,61129
- Lisp_Object hash;1843,61260
- Lisp_Object next;1848,61490
- Lisp_Object next_free;1851,61560
- Lisp_Object index;1856,61771
- ptrdiff_t count;1863,62041
- Lisp_Object key_and_value;1868,62240
- struct hash_table_test test;1871,62314
- struct Lisp_Hash_Table *next_weak;next_weak1875,62457
-XHASH_TABLE 1880,62531
-#define XSET_HASH_TABLE(1885,62602
-HASH_TABLE_P 1889,62703
-HASH_KEY 1896,62860
-HASH_VALUE 1903,63040
-HASH_NEXT 1911,63254
-HASH_HASH 1918,63431
-HASH_INDEX 1926,63677
-HASH_TABLE_SIZE 1933,63826
-enum DEFAULT_HASH_SIZE 1940,63956
-enum DEFAULT_HASH_SIZE { DEFAULT_HASH_SIZE 1940,63956
-static double const DEFAULT_REHASH_THRESHOLD 1946,64176
-static double const DEFAULT_REHASH_SIZE 1950,64299
-sxhash_combine 1956,64465
-SXHASH_REDUCE 1964,64648
-struct Lisp_Misc_Any 1971,64806
- ENUM_BF (Lisp_Misc_Type) type 1973,64866
- bool_bf gcmarkbit 1974,64927
- unsigned spacer 1975,64952
-struct Lisp_Marker1978,64980
- ENUM_BF (Lisp_Misc_Type) type 1980,65001
- bool_bf gcmarkbit 1981,65065
- unsigned spacer 1982,65090
- bool_bf need_adjustment 1986,65282
- bool_bf insertion_type 1989,65423
- struct buffer *buffer;buffer2000,66016
- struct Lisp_Marker *next;next2009,66367
- ptrdiff_t charpos;2011,66455
- ptrdiff_t bytepos;2016,66713
-struct Lisp_Overlay2021,66841
- ENUM_BF (Lisp_Misc_Type) type 2034,67349
- bool_bf gcmarkbit 2035,67415
- unsigned spacer 2036,67442
- struct Lisp_Overlay *next;next2037,67468
- Lisp_Object start;2038,67499
- Lisp_Object end;2039,67522
- Lisp_Object plist;2040,67543
- SAVE_UNUSED,2047,67644
- SAVE_INTEGER,2048,67661
- SAVE_FUNCPOINTER,2049,67679
- SAVE_POINTER,2050,67701
- SAVE_OBJECT2051,67719
-enum { SAVE_SLOT_BITS 2055,67804
-enum { SAVE_VALUE_SLOTS 2058,67901
-enum { SAVE_TYPE_BITS 2062,68009
-enum Lisp_Save_Type2064,68075
- SAVE_TYPE_INT_INT 2066,68099
- SAVE_TYPE_INT_INT_INT2067,68172
- SAVE_TYPE_OBJ_OBJ 2069,68262
- SAVE_TYPE_OBJ_OBJ_OBJ 2070,68333
- SAVE_TYPE_OBJ_OBJ_OBJ_OBJ2071,68414
- SAVE_TYPE_PTR_INT 2073,68509
- SAVE_TYPE_PTR_OBJ 2074,68582
- SAVE_TYPE_PTR_PTR 2075,68654
- SAVE_TYPE_FUNCPTR_PTR_OBJ2076,68727
- SAVE_TYPE_MEMORY 2080,68885
-typedef void (*voidfuncptr)voidfuncptr2108,69839
-struct Lisp_Save_Value2110,69876
- ENUM_BF (Lisp_Misc_Type) type 2112,69903
- bool_bf gcmarkbit 2113,69972
- unsigned spacer : 32 - (16 + 1 + SAVE_TYPE_BITS)2114,69999
- ENUM_BF (Lisp_Save_Type) save_type : SAVE_TYPE_BITS;2123,70489
- void *pointer;pointer2125,70558
- voidfuncptr funcpointer;2126,70579
- ptrdiff_t integer;2127,70610
- Lisp_Object object;2128,70635
- } data[data2129,70661
-save_type 2134,70755
-XSAVE_POINTER 2143,70985
-set_save_pointer 2149,71147
-XSAVE_FUNCPOINTER 2155,71329
-XSAVE_INTEGER 2164,71549
-set_save_integer 2170,71711
-XSAVE_OBJECT 2179,71932
-struct Lisp_Finalizer2186,72109
- struct Lisp_Misc_Any base;2188,72135
- struct Lisp_Finalizer *prev;prev2191,72223
- struct Lisp_Finalizer *next;next2192,72256
- Lisp_Object function;2197,72493
-struct Lisp_Free2201,72584
- ENUM_BF (Lisp_Misc_Type) type 2203,72605
- bool_bf gcmarkbit 2204,72668
- unsigned spacer 2205,72695
- union Lisp_Misc *chain;chain2206,72721
-union Lisp_Misc2212,72885
- struct Lisp_Misc_Any u_any;2214,72905
- struct Lisp_Free u_free;2215,72976
- struct Lisp_Marker u_marker;2216,73005
- struct Lisp_Overlay u_overlay;2217,73038
- struct Lisp_Save_Value u_save_value;2218,73073
- struct Lisp_Finalizer u_finalizer;2219,73114
-XMISC 2223,73184
-XMISCANY 2229,73273
-XMISCTYPE 2236,73382
-XMARKER 2242,73470
-XOVERLAY 2249,73585
-XSAVE_VALUE 2256,73706
-XFINALIZER 2263,73835
-struct Lisp_Intfwd2274,74120
- enum Lisp_Fwd_Type type;2276,74143
- EMACS_INT *intvar;intvar2277,74193
-struct Lisp_Boolfwd2284,74414
- enum Lisp_Fwd_Type type;2286,74438
- bool *boolvar;boolvar2287,74489
-struct Lisp_Objfwd2294,74705
- enum Lisp_Fwd_Type type;2296,74728
- Lisp_Object *objvar;objvar2297,74778
-struct Lisp_Buffer_Objfwd2302,74937
- enum Lisp_Fwd_Type type;2304,74967
- int offset;2305,75024
- Lisp_Object predicate;2307,75116
-struct Lisp_Buffer_Local_Value2334,76473
- bool_bf local_if_set 2338,76618
- bool_bf frame_local 2341,76800
- bool_bf found 2344,76942
- union Lisp_Fwd *fwd;fwd2346,77044
- Lisp_Object where;2348,77187
- Lisp_Object defcell;2351,77313
- Lisp_Object valcell;2357,77617
-struct Lisp_Kboard_Objfwd2362,77732
- enum Lisp_Fwd_Type type;2364,77762
- int offset;2365,77819
-union Lisp_Fwd2368,77841
- struct Lisp_Intfwd u_intfwd;2370,77860
- struct Lisp_Boolfwd u_boolfwd;2371,77893
- struct Lisp_Objfwd u_objfwd;2372,77928
- struct Lisp_Buffer_Objfwd u_buffer_objfwd;2373,77961
- struct Lisp_Kboard_Objfwd u_kboard_objfwd;2374,78008
-XFWDTYPE 2378,78087
-XBUFFER_OBJFWD 2384,78183
-struct Lisp_Float2391,78319
- double data;2395,78357
- struct Lisp_Float *chain;chain2396,78376
- } u;2397,78408
-XFLOAT_DATA 2401,78437
- IEEE_FLOATING_POINT2415,78946
-#define _UCHAR_T2423,79269
-typedef unsigned char UCHAR;2424,79286
-enum Lisp_Compiled2429,79369
- COMPILED_ARGLIST 2431,79392
- COMPILED_BYTECODE 2432,79418
- COMPILED_CONSTANTS 2433,79445
- COMPILED_STACK_DEPTH 2434,79473
- COMPILED_DOC_STRING 2435,79503
- COMPILED_INTERACTIVE 2436,79532
-enum char_bits2443,79834
- CHAR_ALT 2445,79853
- CHAR_SUPER 2446,79879
- CHAR_HYPER 2447,79907
- CHAR_SHIFT 2448,79935
- CHAR_CTL 2449,79963
- CHAR_META 2450,79989
- CHAR_MODIFIER_MASK 2452,80017
- CHARACTERBITS 2457,80212
-LISP_MACRO_DEFUN 2462,80270
-NATNUMP 2470,80412
-RANGED_INTEGERP 2476,80493
-#define TYPE_RANGED_INTEGERP(2481,80615
-LISP_MACRO_DEFUN 2486,80800
-VECTORP 2500,81273
-OVERLAYP 2505,81376
-SAVE_VALUEP 2510,81475
-FINALIZERP 2516,81581
-AUTOLOADP 2522,81685
-BUFFER_OBJFWDP 2528,81776
-PSEUDOVECTOR_TYPEP 2534,81874
-PSEUDOVECTORP 2542,82127
-WINDOW_CONFIGURATIONP 2558,82479
-PROCESSP 2564,82589
-WINDOWP 2570,82673
-TERMINALP 2576,82755
-SUBRP 2582,82841
-COMPILEDP 2588,82919
-BUFFERP 2594,83005
-CHAR_TABLE_P 2600,83087
-SUB_CHAR_TABLE_P 2606,83178
-BOOL_VECTOR_P 2612,83277
-FRAMEP 2618,83370
-IMAGEP 2625,83487
-ARRAYP 2632,83592
-CHECK_LIST 2638,83711
-LISP_MACRO_DEFUN_VOID 2643,83792
-CHECK_STRING_CAR 2653,84089
-CHECK_CONS 2658,84193
-CHECK_VECTOR 2663,84273
-CHECK_BOOL_VECTOR 2668,84359
-CHECK_VECTOR_OR_STRING 2674,84536
-CHECK_ARRAY 2683,84710
-CHECK_BUFFER 2688,84818
-CHECK_WINDOW 2693,84904
-CHECK_PROCESS 2699,85010
-CHECK_NATNUM 2705,85106
-#define CHECK_RANGED_INTEGER(2710,85183
-#define CHECK_TYPE_RANGED_INTEGER(2721,85566
-#define CHECK_NUMBER_COERCE_MARKER(2729,85836
-XFLOATINT 2738,86089
-CHECK_NUMBER_OR_FLOAT 2744,86160
-#define CHECK_NUMBER_OR_FLOAT_COERCE_MARKER(2749,86259
-CHECK_NUMBER_CAR 2760,86669
-CHECK_NUMBER_CDR 2768,86791
-#define DEFUN(2803,88386
-#define DEFUN(2812,88854
-FUNCTIONP 2822,89209
-extern void defsubr 2829,89361
-enum maxargs2831,89404
- MANY 2833,89421
- UNEVALLED 2834,89436
-#define CALLMANY(2838,89539
-#define CALLN(2844,89892
-extern void defvar_lisp 2846,89962
-extern void defvar_lisp_nopro 2847,90039
-extern void defvar_bool 2848,90122
-extern void defvar_int 2849,90193
-extern void defvar_kboard 2850,90267
-#define DEFVAR_LISP(2869,91097
-#define DEFVAR_LISP_NOPRO(2874,91269
-#define DEFVAR_BOOL(2879,91451
-#define DEFVAR_INT(2884,91624
-#define DEFVAR_BUFFER_DEFAULTS(2890,91795
-#define DEFVAR_KBOARD(2896,91999
-typedef jmp_buf sys_jmp_buf;2906,92323
-# define sys_setjmp(2907,92352
-# define sys_longjmp(2908,92387
-typedef sigjmp_buf sys_jmp_buf;2910,92459
-# define sys_setjmp(2911,92491
-# define sys_longjmp(2912,92531
-typedef jmp_buf sys_jmp_buf;2916,92690
-# define sys_setjmp(2917,92719
-# define sys_longjmp(2918,92753
-enum specbind_tag 2943,93805
- SPECPDL_UNWIND,2944,93825
- SPECPDL_UNWIND_PTR,2945,93894
- SPECPDL_UNWIND_INT,2946,93945
- SPECPDL_UNWIND_VOID,2947,93993
- SPECPDL_BACKTRACE,2948,94047
- SPECPDL_LET,2949,94105
- SPECPDL_LET_LOCAL,2951,94235
- SPECPDL_LET_DEFAULT 2952,94292
-union specbinding2955,94364
- ENUM_BF (specbind_tag) kind : CHAR_BIT;2957,94386
- ENUM_BF (specbind_tag) kind : CHAR_BIT;2959,94443
- void (*func)func2960,94489
- Lisp_Object arg;2961,94523
- } unwind;2962,94546
- ENUM_BF (specbind_tag) kind : CHAR_BIT;2964,94573
- void (*func)func2965,94619
- void *arg;arg2966,94648
- } unwind_ptr;2967,94665
- ENUM_BF (specbind_tag) kind : CHAR_BIT;2969,94696
- void (*func)func2970,94742
- int arg;2971,94768
- } unwind_int;2972,94783
- ENUM_BF (specbind_tag) kind : CHAR_BIT;2974,94814
- void (*func)func2975,94860
- } unwind_void;2976,94887
- ENUM_BF (specbind_tag) kind : CHAR_BIT;2978,94919
- Lisp_Object symbol,2980,95026
- Lisp_Object symbol, old_value,2980,95026
- Lisp_Object symbol, old_value, where;2980,95026
- } let;2981,95070
- ENUM_BF (specbind_tag) kind : CHAR_BIT;2983,95094
- bool_bf debug_on_exit 2984,95140
- Lisp_Object function;2985,95173
- Lisp_Object *args;args2986,95201
- ptrdiff_t nargs;2987,95226
- } bt;2988,95249
-extern union specbinding *specpdl;specpdl2991,95265
-extern union specbinding *specpdl_ptr;specpdl_ptr2992,95300
-extern ptrdiff_t specpdl_size;2993,95339
-SPECPDL_INDEX 2996,95388
-enum handlertype 3021,96410
-enum handlertype { CATCHER,3021,96410
-enum handlertype { CATCHER, CONDITION_CASE 3021,96410
-struct handler3023,96457
- enum handlertype type;3025,96474
- Lisp_Object tag_or_ch;3026,96499
- Lisp_Object val;3027,96524
- struct handler *next;next3028,96543
- struct handler *nextfree;nextfree3029,96567
- Lisp_Object *bytecode_top;bytecode_top3036,96925
- int bytecode_dest;3037,96954
- struct gcpro *gcpro;gcpro3042,97191
- sys_jmp_buf jmp;3044,97221
- EMACS_INT lisp_eval_depth;3045,97240
- ptrdiff_t pdlcount;3046,97269
- int poll_suppress_count;3047,97291
- int interrupt_input_blocked;3048,97318
- struct byte_stack *byte_stack;byte_stack3049,97349
-#define PUSH_HANDLER(3053,97446
-extern Lisp_Object memory_signal_data;3075,98152
-extern char *stack_bottom;stack_bottom3079,98285
-extern void process_pending_signals 3097,99102
-extern bool volatile pending_signals;3098,99146
-extern void process_quit_flag 3100,99185
-#define QUIT 3101,99223
-#define QUITP 3112,99473
-extern Lisp_Object Vascii_downcase_table;3114,99534
-extern Lisp_Object Vascii_canon_table;3115,99576
-extern struct gcpro *gcprolist;gcprolist3130,100283
-struct gcpro3132,100316
- struct gcpro *next;next3134,100331
- volatile Lisp_Object *var;var3137,100400
- ptrdiff_t nvars;3140,100482
- const char *name;name3144,100567
- int lineno;3147,100623
- int idx;3150,100684
- int level;3153,100720
-#define GC_USE_GCPROS_AS_BEFORE 3171,101297
-#define GC_MAKE_GCPROS_NOOPS 3172,101332
-#define GC_MARK_STACK_CHECK_GCPROS 3173,101364
-#define GC_USE_GCPROS_CHECK_ZOMBIES 3174,101401
-#define GC_MARK_STACK 3177,101462
-#define BYTE_MARK_STACK 3181,101562
-#define GCPRO1(3190,101833
-#define GCPRO2(3191,101873
-#define GCPRO3(3192,101939
-#define GCPRO4(3194,102034
-#define GCPRO5(3196,102154
-#define GCPRO6(3198,102299
-#define GCPRO7(3201,102474
-#define UNGCPRO 3202,102553
-#define GCPRO1(3208,102653
-#define GCPRO2(3212,102775
-#define GCPRO3(3217,102967
-#define GCPRO4(3223,103229
-#define GCPRO5(3230,103560
-#define GCPRO6(3238,103961
-#define GCPRO7(3247,104431
-#define UNGCPRO 3257,104971
-extern int gcpro_level;3261,105040
-#define GCPRO1(3263,105065
-#define GCPRO2(3269,105299
-#define GCPRO3(3278,105717
-#define GCPRO4(3289,106274
-#define GCPRO5(3302,106972
-#define GCPRO6(3317,107812
-#define GCPRO7(3334,108793
-#define UNGCPRO 3353,109916
-#define RETURN_UNGCPRO(3363,110183
-void staticpro 3375,110456
-vcopy 3384,110657
-set_hash_key_slot 3393,110932
-set_hash_value_slot 3399,111071
-set_symbol_function 3408,111306
-set_symbol_plist 3414,111421
-set_symbol_next 3420,111524
-blv_found 3428,111697
-set_overlay_plist 3437,111880
-string_intervals 3445,112031
-set_string_intervals 3453,112153
-set_char_table_defalt 3462,112355
-set_char_table_purpose 3467,112467
-set_char_table_extras 3475,112636
-set_char_table_contents 3482,112845
-set_sub_char_table_contents 3489,113040
-extern Lisp_Object indirect_function 3495,113199
-extern Lisp_Object find_symbol_value 3496,113251
-enum Arith_Comparison 3497,113303
- ARITH_EQUAL,3498,113327
- ARITH_NOTEQUAL,3499,113342
- ARITH_LESS,3500,113360
- ARITH_GRTR,3501,113374
- ARITH_LESS_OR_EQUAL,3502,113388
- ARITH_GRTR_OR_EQUAL3503,113411
-extern Lisp_Object arithcompare 3505,113436
-#define INTEGER_TO_CONS(3511,113762
-#define CONS_TO_INTEGER(3529,114625
-extern intmax_t cons_to_signed 3533,114840
-extern uintmax_t cons_to_unsigned 3534,114906
-extern struct Lisp_Symbol *indirect_variable indirect_variable3536,114967
-extern _Noreturn void args_out_of_range 3537,115036
-extern _Noreturn void args_out_of_range_3 3538,115104
-extern Lisp_Object do_symval_forwarding 3540,115195
-extern void set_internal 3541,115255
-extern void syms_of_data 3542,115327
-extern void swap_in_global_binding 3543,115360
-extern void syms_of_cmds 3546,115444
-extern void keys_of_cmds 3547,115477
-extern Lisp_Object detect_coding_system 3550,115539
-extern void init_coding 3552,115692
-extern void init_coding_once 3553,115724
-extern void syms_of_coding 3554,115761
-extern ptrdiff_t chars_in_text 3557,115828
-extern ptrdiff_t multibyte_chars_in_text 3558,115895
-extern void syms_of_character 3559,115972
-extern void init_charset 3562,116040
-extern void init_charset_once 3563,116073
-extern void syms_of_charset 3564,116111
-extern void init_syntax_once 3569,116231
-extern void syms_of_syntax 3570,116268
-enum { NEXT_ALMOST_PRIME_LIMIT 3573,116329
-extern EMACS_INT next_almost_prime 3574,116368
-enum constype 3739,123820
-enum constype {CONSTYPE_HEAP,CONSTYPE_HEAP3739,123820
-enum constype {CONSTYPE_HEAP, CONSTYPE_PURE}CONSTYPE_PURE3739,123820
-extern Lisp_Object listn 3740,123866
-list2i 3745,124010
-list3i 3751,124119
-list4i 3757,124258
-extern Lisp_Object make_uninit_bool_vector 3763,124410
-extern Lisp_Object bool_vector_fill 3764,124466
-extern _Noreturn void string_overflow 3765,124530
-extern Lisp_Object make_string 3766,124576
-extern Lisp_Object make_formatted_string 3767,124634
-extern Lisp_Object make_multibyte_string 3779,124988
-extern Lisp_Object make_event_array 3780,125067
-extern Lisp_Object make_uninit_string 3781,125131
-extern Lisp_Object make_uninit_multibyte_string 3782,125182
-extern Lisp_Object make_string_from_bytes 3783,125254
-extern Lisp_Object make_specified_string 3784,125334
-extern Lisp_Object make_pure_string 3786,125426
-extern Lisp_Object make_pure_c_string 3787,125506
-build_pure_c_string 3792,125662
-build_string 3801,125867
-extern Lisp_Object pure_cons 3806,125945
-extern void make_byte_code 3807,126002
-extern struct Lisp_Vector *allocate_vector allocate_vector3808,126053
-make_uninit_vector 3820,126438
-make_uninit_sub_char_table 3833,126657
-extern struct Lisp_Vector *allocate_pseudovector allocate_pseudovector3844,126966
-#define ALLOCATE_PSEUDOVECTOR(3850,127201
-#define ALLOCATE_ZEROED_PSEUDOVECTOR(3858,127537
-extern bool gc_in_progress;3863,127738
-extern bool abort_on_gc;3864,127766
-extern Lisp_Object make_float 3865,127791
-extern void display_malloc_warning 3866,127831
-extern ptrdiff_t inhibit_garbage_collection 3867,127874
-extern Lisp_Object make_save_int_int_int 3868,127926
-extern Lisp_Object make_save_obj_obj_obj_obj 3869,128002
-extern Lisp_Object make_save_ptr 3871,128112
-extern Lisp_Object make_save_ptr_int 3872,128155
-extern Lisp_Object make_save_ptr_ptr 3873,128213
-extern Lisp_Object make_save_funcptr_ptr_obj 3874,128268
-extern Lisp_Object make_save_memory 3876,128364
-extern void free_save_value 3877,128428
-extern Lisp_Object build_overlay 3878,128471
-extern void free_marker 3879,128545
-extern void free_cons 3880,128584
-extern void init_alloc_once 3881,128628
-extern void init_alloc 3882,128664
-extern void syms_of_alloc 3883,128695
-extern struct buffer * allocate_buffer 3884,128729
-extern int valid_lisp_object_p 3885,128776
-extern int relocatable_string_data_p 3886,128822
-extern void check_cons_list 3888,128901
-INLINE void 3890,128943
-extern void *r_alloc r_alloc3895,129064
-#define FLOAT_TO_STRING_BUFSIZE 3927,130527
-extern int openp 3957,131676
-extern Lisp_Object string_to_number 3959,131786
-extern void map_obarray 3960,131849
-extern void dir_warning 3962,131963
-extern void init_obarray 3963,132016
-extern void init_lread 3964,132049
-extern void syms_of_lread 3965,132080
-intern 3968,132134
-intern_c_string 3974,132222
-extern EMACS_INT lisp_eval_depth;3980,132335
-extern Lisp_Object Vautoload_queue;3981,132369
-extern Lisp_Object Vrun_hooks;3982,132405
-extern Lisp_Object Vsignaling_function;3983,132436
-extern Lisp_Object inhibit_lisp_code;3984,132476
-extern struct handler *handlerlist;handlerlist3985,132514
-extern void run_hook 3994,132756
-extern void run_hook_with_args_2 3995,132792
-extern Lisp_Object run_hook_with_args 3996,132866
-extern _Noreturn void xsignal 3999,133025
-extern _Noreturn void xsignal0 4000,133083
-extern _Noreturn void xsignal1 4001,133129
-extern _Noreturn void xsignal2 4002,133188
-extern _Noreturn void xsignal3 4003,133260
-extern _Noreturn void signal_error 4005,133349
-extern Lisp_Object eval_sub 4006,133413
-extern Lisp_Object apply1 4007,133461
-extern Lisp_Object call0 4008,133515
-extern Lisp_Object call1 4009,133555
-extern Lisp_Object call2 4010,133608
-extern Lisp_Object call3 4011,133674
-extern Lisp_Object call4 4012,133753
-extern Lisp_Object call5 4013,133845
-extern Lisp_Object call6 4014,133950
-extern Lisp_Object call7 4015,134068
-extern Lisp_Object internal_catch 4016,134199
-extern Lisp_Object internal_lisp_condition_case 4017,134292
-extern Lisp_Object internal_condition_case 4018,134381
-extern Lisp_Object internal_condition_case_1 4019,134494
-extern Lisp_Object internal_condition_case_2 4020,134629
-extern Lisp_Object internal_condition_case_n4021,134790
-extern void specbind 4024,134986
-extern void record_unwind_protect 4025,135035
-extern void record_unwind_protect_ptr 4026,135108
-extern void record_unwind_protect_int 4027,135175
-extern void record_unwind_protect_void 4028,135236
-extern void record_unwind_protect_nothing 4029,135294
-extern void clear_unwind_protect 4030,135344
-extern void set_unwind_protect 4031,135390
-extern void set_unwind_protect_ptr 4032,135471
-extern Lisp_Object unbind_to 4033,135546
-extern _Noreturn void error 4034,135601
-fast_string_match_ignore_case 4136,140089
-extern ptrdiff_t fast_c_string_match_ignore_case 4141,140239
-extern ptrdiff_t fast_looking_at 4143,140336
-extern ptrdiff_t find_newline 4145,140475
-extern ptrdiff_t scan_newline 4147,140604
-extern ptrdiff_t scan_newline_from_point 4149,140707
-extern ptrdiff_t find_newline_no_quit 4150,140787
-extern ptrdiff_t find_before_next_newline 4152,140884
-extern void syms_of_search 4154,140982
-extern void clear_regexp_cache 4155,141017
-extern Lisp_Object Vminibuffer_list;4159,141087
-extern Lisp_Object last_minibuf_string;4160,141124
-extern Lisp_Object get_minibuffer 4161,141164
-extern void init_minibuf_once 4162,141211
-extern void syms_of_minibuf 4163,141249
-extern void syms_of_callint 4167,141316
-extern void syms_of_casefiddle 4171,141386
-extern void keys_of_casefiddle 4172,141425
-extern void init_casetab_once 4176,141495
-extern void syms_of_casetab 4177,141533
-extern Lisp_Object echo_message_buffer;4181,141601
-extern struct kboard *echo_kboard;echo_kboard4182,141641
-extern void cancel_echoing 4183,141676
-extern Lisp_Object last_undo_boundary;4184,141711
-extern bool input_pending;4185,141750
-extern sigjmp_buf return_to_command_loop;4187,141813
-extern Lisp_Object menu_bar_items 4189,141862
-extern Lisp_Object tool_bar_items 4190,141911
-extern void discard_mouse_events 4191,141967
-void handle_input_available_signal 4193,142028
-extern Lisp_Object pending_funcalls;4195,142077
-extern bool detect_input_pending 4196,142114
-extern bool detect_input_pending_ignore_squeezables 4197,142155
-extern bool detect_input_pending_run_timers 4198,142215
-extern void safe_run_hooks 4199,142267
-extern void cmd_error_internal 4200,142309
-extern Lisp_Object command_loop_1 4201,142369
-extern Lisp_Object read_menu_command 4202,142411
-extern Lisp_Object recursive_edit_1 4203,142456
-extern void record_auto_save 4204,142500
-extern void force_auto_save_soon 4205,142537
-extern void init_keyboard 4206,142578
-extern void syms_of_keyboard 4207,142612
-extern void keys_of_keyboard 4208,142649
-extern ptrdiff_t current_column 4211,142715
-extern void invalidate_current_column 4212,142755
-extern bool indented_beyond_p 4213,142801
-extern void syms_of_indent 4214,142866
-extern void store_frame_param 4217,142929
-extern void store_in_alist 4218,143003
-extern Lisp_Object do_switch_frame 4219,143073
-extern Lisp_Object get_frame_param 4220,143146
-extern void frames_discard_buffer 4221,143212
-extern void syms_of_frame 4222,143261
-extern char **initial_argv;initial_argv4225,143323
-extern int initial_argc;4226,143351
-extern bool display_arg;4228,143426
-extern Lisp_Object decode_env_path 4230,143458
-extern Lisp_Object empty_unibyte_string,4231,143529
-extern Lisp_Object empty_unibyte_string, empty_multibyte_string;4231,143529
-extern _Noreturn void terminate_due_to_signal 4232,143594
-extern Lisp_Object Vlibrary_cache;4234,143669
-void fixup_locale 4237,143730
-void synchronize_system_messages_locale 4238,143756
-void synchronize_system_time_locale 4239,143804
-INLINE void fixup_locale 4241,143854
-INLINE void synchronize_system_messages_locale 4242,143889
-INLINE void synchronize_system_time_locale 4243,143946
-extern void shut_down_emacs 4245,144006
-extern bool noninteractive;4248,144132
-extern bool no_site_lisp;4251,144224
-extern int daemon_pipe[daemon_pipe4256,144392
-#define IS_DAEMON 4257,144419
-#define DAEMON_RUNNING 4258,144459
-extern void *w32_daemon_event;w32_daemon_event4260,144527
-#define IS_DAEMON 4261,144558
-#define DAEMON_RUNNING 4262,144603
-extern bool fatal_error_in_progress;4266,144724
-extern bool inhibit_window_system;4269,144830
-extern bool running_asynch_code;4271,144923
-extern void kill_buffer_processes 4274,144986
-extern int wait_reading_process_output 4275,145035
-# define WAIT_READING_MAX 4281,145422
-# define WAIT_READING_MAX 4283,145494
-extern void add_timer_wait_descriptor 4286,145558
-extern void add_keyboard_wait_descriptor 4288,145610
-extern void delete_keyboard_wait_descriptor 4289,145658
-extern void add_gpm_wait_descriptor 4291,145725
-extern void delete_gpm_wait_descriptor 4292,145768
-extern void init_process_emacs 4294,145821
-extern void syms_of_process 4295,145860
-extern void setup_process_coding_systems 4296,145896
-extern int child_setup 4302,146016
-extern void init_callproc_1 4303,146084
-extern void init_callproc 4304,146120
-extern void set_initial_environment 4305,146154
-extern void syms_of_callproc 4306,146198
-extern Lisp_Object read_doc_string 4309,146261
-extern Lisp_Object get_doc_string 4310,146311
-extern void syms_of_doc 4311,146372
-extern int read_bytecode_char 4312,146404
-extern void syms_of_bytecode 4315,146473
-extern struct byte_stack *byte_stack_list;byte_stack_list4316,146510
-extern void mark_byte_stack 4318,146573
-extern void unmark_byte_stack 4320,146616
-extern Lisp_Object exec_byte_code 4321,146654
-extern void init_macros 4325,146804
-extern void syms_of_macros 4326,146836
-extern void truncate_undo_list 4329,146898
-extern void record_insert 4330,146948
-extern void record_delete 4331,146998
-extern void record_first_change 4332,147056
-extern void record_change 4333,147096
-extern void record_property_change 4334,147146
-extern void syms_of_undo 4337,147288
-extern void report_interval_modification 4340,147352
-extern void syms_of_menu 4343,147448
-extern void syms_of_xmenu 4346,147509
-extern char *get_current_dir_name get_current_dir_name4356,147711
-extern void stuff_char 4358,147760
-extern void init_foreground_group 4359,147793
-extern void sys_subshell 4360,147835
-extern void sys_suspend 4361,147868
-extern void discard_tty_input 4362,147900
-extern void init_sys_modes 4363,147938
-extern void reset_sys_modes 4364,147994
-extern void init_all_sys_modes 4365,148051
-extern void reset_all_sys_modes 4366,148090
-extern void child_setup_tty 4367,148130
-extern void setup_pty 4368,148165
-extern int set_window_size 4369,148194
-extern EMACS_INT get_random 4370,148238
-extern void seed_random 4371,148274
-extern void init_random 4372,148319
-extern void emacs_backtrace 4373,148351
-extern _Noreturn void emacs_abort 4374,148386
-extern void xputenv 4527,152700
-extern char *egetenv_internal egetenv_internal4529,152737
-egetenv 4532,152809
-extern void init_system_name 4539,153012
-#define eabs(4545,153305
-#define make_fixnum_or_float(4550,153438
-enum MAX_ALLOCA 4556,153689
-enum MAX_ALLOCA { MAX_ALLOCA 4556,153689
-extern void *record_xmalloc record_xmalloc4558,153734
-#define USE_SAFE_ALLOCA 4560,153800
-#define AVAIL_ALLOCA(4564,153933
-#define SAFE_ALLOCA(4568,154044
-#define SAFE_NALLOCA(4576,154385
-#define SAFE_ALLOCA_STRING(4590,154861
-#define SAFE_FREE(4598,155113
-#define SAFE_ALLOCA_LISP(4625,155691
-# define USE_STACK_LISP_OBJECTS 4652,156813
-# undef USE_STACK_LISP_OBJECTS4658,156979
-# define USE_STACK_LISP_OBJECTS 4659,157010
-enum { defined_GC_CHECK_STRING_BYTES 4663,157085
-enum { defined_GC_CHECK_STRING_BYTES 4665,157138
-union Aligned_Cons4670,157272
- struct Lisp_Cons s;4672,157293
- double d;4673,157315
- double d; intmax_t i;4673,157315
- double d; intmax_t i; void *p;p4673,157315
-union Aligned_String4676,157352
- struct Lisp_String s;4678,157375
- double d;4679,157399
- double d; intmax_t i;4679,157399
- double d; intmax_t i; void *p;p4679,157399
- USE_STACK_CONS 4689,157707
- USE_STACK_STRING 4691,157813
-#define STACK_CONS(4699,158150
-#define AUTO_CONS_EXPR(4701,158247
-#define AUTO_CONS(4709,158610
-#define AUTO_LIST1(4710,158681
-#define AUTO_LIST2(4712,158789
-#define AUTO_LIST3(4716,158944
-#define AUTO_LIST4(4720,159119
-extern const char *verify_ascii verify_ascii4730,159456
-# define verify_ascii(4732,159510
-#define AUTO_STRING(4740,159818
-#define FOR_EACH_TAIL(4752,160282
-#define FOR_EACH_ALIST_VALUE(4766,160773
-maybe_gc 4774,161060
-functionp 4784,161299
+#define EMACS_LISP_H22,801
+#define DECLARE_GDB_SYM(47,1422
+# define DEFINE_GDB_SYMBOL_BEGIN(49,1509
+# define DEFINE_GDB_SYMBOL_END(50,1579
+# define DEFINE_GDB_SYMBOL_BEGIN(52,1626
+# define DEFINE_GDB_SYMBOL_END(53,1703
+#undef min57,1791
+#undef max58,1802
+#define max(59,1813
+#define min(60,1855
+#define ARRAYELTS(63,1937
+#define GCTYPEBITS 67,2080
+DEFINE_GDB_SYMBOL_BEGIN GCTYPEBITS66,2038
+# define NONPOINTER_BITS 78,2568
+# define NONPOINTER_BITS 80,2601
+typedef int EMACS_INT;91,3024
+typedef unsigned int EMACS_UINT;92,3047
+# define EMACS_INT_MAX 93,3080
+# define pI 94,3112
+typedef long int EMACS_INT;96,3204
+typedef unsigned long EMACS_UINT;97,3232
+# define EMACS_INT_MAX 98,3266
+# define pI 99,3299
+typedef long long int EMACS_INT;103,3478
+typedef unsigned long long int EMACS_UINT;104,3511
+# define EMACS_INT_MAX 105,3554
+# define pI 106,3588
+enum { BOOL_VECTOR_BITS_PER_CHAR 114,3805
+#define BOOL_VECTOR_BITS_PER_CHAR 115,3841
+typedef size_t bits_word;123,4166
+# define BITS_WORD_MAX 124,4192
+enum { BITS_PER_BITS_WORD 125,4224
+typedef unsigned char bits_word;127,4291
+# define BITS_WORD_MAX 128,4324
+enum { BITS_PER_BITS_WORD 129,4387
+verify 131,4451
+ BITS_PER_CHAR 136,4571
+ BITS_PER_SHORT 137,4606
+ BITS_PER_LONG 138,4658
+ BITS_PER_EMACS_INT 139,4713
+typedef intmax_t printmax_t;148,5090
+typedef uintmax_t uprintmax_t;149,5119
+# define pMd 150,5150
+# define pMu 151,5171
+typedef EMACS_INT printmax_t;153,5198
+typedef EMACS_UINT uprintmax_t;154,5228
+# define pMd 155,5260
+# define pMu 156,5279
+# define pD 165,5665
+# define pD 167,5710
+# define pD 169,5757
+# define pD 171,5780
+# define eassert(200,7063
+# define eassume(201,7141
+extern _Noreturn void die 204,7207
+extern bool suppress_checking EXTERNALLY_VISIBLE;206,7269
+# define eassert(208,7320
+# define eassume(212,7451
+enum Lisp_Bits239,8520
+#define GCALIGNMENT 243,8648
+ VALBITS 246,8743
+ INTTYPEBITS 249,8839
+ FIXNUM_BITS 252,8946
+#define VAL_MAX 263,9328
+#define USE_LSB_TAG 271,9778
+DEFINE_GDB_SYMBOL_BEGIN USE_LSB_TAG270,9734
+# define alignas(281,10078
+# define GCALIGNED 288,10228
+# define GCALIGNED 290,10293
+# define lisp_h_XLI(327,11643
+# define lisp_h_XIL(328,11674
+# define lisp_h_XLI(330,11725
+# define lisp_h_XIL(331,11752
+#define lisp_h_CHECK_LIST_CONS(333,11786
+#define lisp_h_CHECK_NUMBER(334,11857
+#define lisp_h_CHECK_SYMBOL(335,11928
+#define lisp_h_CHECK_TYPE(336,11997
+#define lisp_h_CONSP(338,12108
+#define lisp_h_EQ(339,12157
+#define lisp_h_FLOATP(340,12202
+#define lisp_h_INTEGERP(341,12253
+#define lisp_h_MARKERP(342,12334
+#define lisp_h_MISCP(343,12409
+#define lisp_h_NILP(344,12458
+#define lisp_h_SET_SYMBOL_VAL(345,12494
+#define lisp_h_SYMBOL_CONSTANT_P(347,12608
+#define lisp_h_SYMBOL_VAL(348,12672
+#define lisp_h_SYMBOLP(350,12773
+#define lisp_h_VECTORLIKEP(351,12826
+#define lisp_h_XCAR(352,12887
+#define lisp_h_XCDR(353,12925
+#define lisp_h_XCONS(354,12965
+#define lisp_h_XHASH(356,13060
+#define lisp_h_XPNTR(357,13094
+# define lisp_h_check_cons_list(360,13222
+# define lisp_h_make_number(363,13290
+# define lisp_h_XFASTINT(365,13393
+# define lisp_h_XINT(366,13430
+# define lisp_h_XSYMBOL(367,13479
+# define lisp_h_XTYPE(371,13632
+# define lisp_h_XUNTAG(372,13697
+# define XLI(381,14087
+# define XIL(382,14118
+# define CHECK_LIST_CONS(383,14149
+# define CHECK_NUMBER(384,14210
+# define CHECK_SYMBOL(385,14259
+# define CHECK_TYPE(386,14308
+# define CONSP(387,14383
+# define EQ(388,14418
+# define FLOATP(389,14453
+# define INTEGERP(390,14490
+# define MARKERP(391,14531
+# define MISCP(392,14570
+# define NILP(393,14605
+# define SET_SYMBOL_VAL(394,14638
+# define SYMBOL_CONSTANT_P(395,14701
+# define SYMBOL_VAL(396,14764
+# define SYMBOLP(397,14813
+# define VECTORLIKEP(398,14852
+# define XCAR(399,14899
+# define XCDR(400,14932
+# define XCONS(401,14965
+# define XHASH(402,15000
+# define XPNTR(403,15035
+# define check_cons_list(405,15098
+# define make_number(408,15177
+# define XFASTINT(409,15225
+# define XINT(410,15267
+# define XSYMBOL(411,15301
+# define XTYPE(412,15341
+# define XUNTAG(413,15377
+#define LISP_MACRO_DEFUN(421,15673
+#define LISP_MACRO_DEFUN_VOID(425,15846
+#define INTMASK 437,16290
+#define case_Lisp_Int 438,16343
+#define ENUM_BF(445,16682
+#define ENUM_BF(447,16723
+enum Lisp_Type451,16764
+ Lisp_Symbol 454,16852
+ Lisp_Misc 458,16994
+ Lisp_Int0 461,17068
+ Lisp_Int1 462,17087
+ Lisp_String 466,17265
+ Lisp_Vectorlike 472,17544
+ Lisp_Cons 475,17633
+ Lisp_Float 477,17671
+enum Lisp_Misc_Type485,18017
+ Lisp_Misc_Free 487,18041
+ Lisp_Misc_Marker,488,18070
+ Lisp_Misc_Overlay,489,18092
+ Lisp_Misc_Save_Value,490,18115
+ Lisp_Misc_Finalizer,491,18141
+ Lisp_Misc_Float,494,18276
+ Lisp_Misc_Limit496,18360
+enum Lisp_Fwd_Type502,18544
+ Lisp_Fwd_Int,504,18567
+ Lisp_Fwd_Bool,505,18620
+ Lisp_Fwd_Obj,506,18671
+ Lisp_Fwd_Buffer_Obj,507,18730
+ Lisp_Fwd_Kboard_Obj 508,18801
+typedef struct { EMACS_INT i;567,21772
+typedef struct { EMACS_INT i; } Lisp_Object;567,21772
+#define LISP_INITIALLY(569,21818
+#undef CHECK_LISP_OBJECT_TYPE571,21849
+enum CHECK_LISP_OBJECT_TYPE 572,21879
+enum CHECK_LISP_OBJECT_TYPE { CHECK_LISP_OBJECT_TYPE 572,21879
+typedef EMACS_INT Lisp_Object;577,22055
+#define LISP_INITIALLY(578,22086
+enum CHECK_LISP_OBJECT_TYPE 579,22116
+enum CHECK_LISP_OBJECT_TYPE { CHECK_LISP_OBJECT_TYPE 579,22116
+#define LISP_INITIALLY_ZERO 582,22217
+INLINE bool BOOL_VECTOR_P 588,22341
+INLINE bool BUFFER_OBJFWDP 589,22382
+INLINE bool BUFFERP 590,22429
+INLINE bool CHAR_TABLE_P 591,22464
+INLINE Lisp_Object CHAR_TABLE_REF_ASCII 592,22504
+INLINE bool 593,22570
+INLINE bool 594,22605
+INLINE bool functionp 595,22641
+INLINE bool 596,22678
+INLINE bool 597,22716
+INLINE bool 598,22753
+INLINE bool 599,22788
+INLINE bool OVERLAYP 600,22822
+INLINE bool PROCESSP 601,22858
+INLINE bool PSEUDOVECTORP 602,22894
+INLINE bool SAVE_VALUEP 603,22940
+INLINE bool FINALIZERP 604,22979
+INLINE void set_sub_char_table_contents 605,23017
+INLINE bool STRINGP 607,23107
+INLINE bool SUB_CHAR_TABLE_P 608,23142
+INLINE bool SUBRP 609,23186
+INLINE bool 610,23219
+INLINE bool 611,23256
+INLINE bool WINDOWP 612,23297
+INLINE bool TERMINALP 613,23332
+INLINE struct Lisp_Save_Value *XSAVE_VALUE XSAVE_VALUE614,23369
+INLINE struct Lisp_Finalizer *XFINALIZER XFINALIZER615,23427
+INLINE struct Lisp_Symbol *(XSYMBOL)616,23483
+INLINE void 617,23535
+extern Lisp_Object char_table_ref 620,23607
+extern void char_table_set 621,23661
+extern _Noreturn Lisp_Object wrong_type_argument 624,23748
+extern _Noreturn void wrong_choice 625,23825
+extern bool might_dump;628,23916
+extern bool initialized;631,24052
+extern double extract_float 634,24108
+enum symbol_interned639,24190
+ SYMBOL_UNINTERNED 641,24213
+ SYMBOL_INTERNED 642,24238
+ SYMBOL_INTERNED_IN_INITIAL_OBARRAY 643,24261
+enum symbol_redirect646,24306
+ SYMBOL_PLAINVAL 648,24329
+ SYMBOL_VARALIAS 649,24353
+ SYMBOL_LOCALIZED 650,24377
+ SYMBOL_FORWARDED 651,24401
+struct Lisp_Symbol654,24428
+ bool_bf gcmarkbit 656,24449
+ ENUM_BF (symbol_redirect) redirect 663,24784
+ unsigned constant 668,25002
+ unsigned interned 672,25122
+ bool_bf declared_special 676,25284
+ bool_bf pinned 679,25385
+ Lisp_Object name;682,25454
+ Lisp_Object value;687,25622
+ struct Lisp_Symbol *alias;alias688,25645
+ struct Lisp_Buffer_Local_Value *blv;blv689,25676
+ union Lisp_Fwd *fwd;fwd690,25717
+ } val;691,25742
+ Lisp_Object function;694,25814
+ Lisp_Object plist;697,25876
+ struct Lisp_Symbol *next;next700,25965
+#define EXFUN(707,26243
+#define DEFUN_ARGS_MANY 712,26437
+#define DEFUN_ARGS_UNEVALLED 713,26489
+#define DEFUN_ARGS_0 714,26532
+#define DEFUN_ARGS_1 715,26560
+#define DEFUN_ARGS_2 716,26595
+#define DEFUN_ARGS_3 717,26643
+#define DEFUN_ARGS_4 718,26704
+#define DEFUN_ARGS_5 719,26778
+#define DEFUN_ARGS_6 721,26871
+#define DEFUN_ARGS_7 723,26977
+#define DEFUN_ARGS_8 725,27096
+#define TAG_PTR(729,27287
+#define TAG_SYMOFFSET(734,27534
+#define XLI_BUILTIN_LISPSYM(741,27833
+#define DEFINE_LISP_SYMBOL(746,28092
+# define DEFINE_NON_NIL_Q_SYMBOL_MACROS 755,28563
+LISP_MACRO_DEFUN 762,28768
+# define ARRAY_MARK_FLAG 768,29015
+# define PSEUDOVECTOR_FLAG 774,29258
+enum pvec_type780,29559
+ PVEC_NORMAL_VECTOR,782,29576
+ PVEC_FREE,783,29598
+ PVEC_PROCESS,784,29611
+ PVEC_FRAME,785,29627
+ PVEC_WINDOW,786,29641
+ PVEC_BOOL_VECTOR,787,29656
+ PVEC_BUFFER,788,29676
+ PVEC_HASH_TABLE,789,29691
+ PVEC_TERMINAL,790,29710
+ PVEC_WINDOW_CONFIGURATION,791,29727
+ PVEC_SUBR,792,29756
+ PVEC_OTHER,793,29769
+ PVEC_COMPILED,795,29847
+ PVEC_CHAR_TABLE,796,29864
+ PVEC_SUB_CHAR_TABLE,797,29883
+ PVEC_FONT 798,29906
+enum More_Lisp_Bits801,29982
+ PSEUDOVECTOR_SIZE_BITS 808,30373
+ PSEUDOVECTOR_SIZE_MASK 809,30406
+ PSEUDOVECTOR_REST_BITS 813,30616
+ PSEUDOVECTOR_REST_MASK 814,30649
+ PSEUDOVECTOR_AREA_BITS 818,30814
+ PVEC_TYPE_MASK 819,30892
+# define VALMASK 829,31293
+DEFINE_GDB_SYMBOL_BEGIN VALMASK828,31248
+#define MOST_POSITIVE_FIXNUM 834,31523
+#define MOST_NEGATIVE_FIXNUM 835,31583
+XINT 874,32675
+XFASTINT 889,33026
+XSYMBOL 899,33254
+XTYPE 910,33472
+XUNTAG 918,33652
+LISP_MACRO_DEFUN 927,33848
+LISP_MACRO_DEFUN 940,34233
+#define FIXNUM_OVERFLOW_P(958,34846
+LISP_MACRO_DEFUN FIXNUM_OVERFLOW_P952,34623
+LISP_MACRO_DEFUN 970,35162
+XSTRING 980,35382
+#define SYMBOL_INDEX(988,35566
+XFLOAT 991,35627
+XPROCESS 1000,35769
+XWINDOW 1007,35886
+XTERMINAL 1014,36003
+XSUBR 1021,36125
+XBUFFER 1028,36236
+XCHAR_TABLE 1035,36360
+XSUB_CHAR_TABLE 1042,36497
+XBOOL_VECTOR 1049,36639
+make_lisp_ptr 1058,36818
+make_lisp_symbol 1066,37004
+builtin_lisp_symbol 1074,37188
+#define XSETINT(1079,37270
+#define XSETFASTINT(1080,37316
+#define XSETCONS(1081,37366
+#define XSETVECTOR(1082,37426
+#define XSETSTRING(1083,37494
+#define XSETSYMBOL(1084,37558
+#define XSETFLOAT(1085,37612
+#define XSETMISC(1086,37674
+#define XSETPVECTYPE(1090,37763
+#define XSETPVECTYPESIZE(1092,37879
+#define XSETPSEUDOVECTOR(1099,38176
+#define XSETTYPED_PSEUDOVECTOR(1105,38360
+#define XSETWINDOW_CONFIGURATION(1110,38570
+#define XSETPROCESS(1112,38666
+#define XSETWINDOW(1113,38732
+#define XSETTERMINAL(1114,38796
+#define XSETSUBR(1115,38864
+#define XSETCOMPILED(1116,38924
+#define XSETBUFFER(1117,38992
+#define XSETCHAR_TABLE(1118,39056
+#define XSETBOOL_VECTOR(1119,39128
+#define XSETSUB_CHAR_TABLE(1120,39202
+XINTPTR 1128,39572
+make_pointer_integer 1134,39652
+LISP_MACRO_DEFUN_VOID 1143,39817
+typedef struct interval *INTERVAL;INTERVAL1149,39978
+ Lisp_Object cdr;1159,40153
+ struct Lisp_Cons *chain;chain1162,40227
+xcar_addr 1174,40751
+xcdr_addr 1179,40828
+LISP_MACRO_DEFUN 1185,40922
+XSETCDR 1198,41298
+CAR 1205,41448
+CDR 1212,41582
+CAR_SAFE 1221,41782
+CDR_SAFE 1226,41868
+STRING_MULTIBYTE 1243,42241
+#define STRING_BYTES_BOUND 1261,43048
+#define STRING_SET_UNIBYTE(1265,43192
+#define STRING_SET_MULTIBYTE(1275,43507
+SDATA 1286,43821
+SSDATA 1291,43899
+SREF 1297,44028
+SSET 1302,44119
+SCHARS 1307,44233
+extern ptrdiff_t string_bytes 1313,44328
+STRING_BYTES 1316,44406
+SBYTES 1326,44586
+STRING_SET_CHARS 1331,44672
+struct vectorlike_header1343,45223
+ ptrdiff_t size;1364,46374
+struct Lisp_Vector1369,46473
+ struct vectorlike_header header;1371,46496
+ Lisp_Object contents[contents1372,46533
+ ALIGNOF_STRUCT_LISP_VECTOR1378,46672
+struct Lisp_Bool_Vector1384,46855
+ struct vectorlike_header header;1388,47003
+ EMACS_INT size;1390,47077
+ bits_word data[data1395,47310
+bool_vector_size 1399,47376
+bool_vector_data 1407,47514
+bool_vector_uchar_data 1413,47608
+bool_vector_words 1421,47794
+bool_vector_bytes 1428,47989
+bool_vector_bitref 1437,48229
+bool_vector_ref 1445,48469
+bool_vector_set 1453,48609
+ header_size 1471,49038
+ bool_header_size 1472,49097
+ word_size 1473,49162
+AREF 1479,49275
+aref_addr 1485,49382
+ASIZE 1491,49492
+ASET 1497,49574
+gc_aset 1504,49733
+enum { NIL_IS_ZERO 1515,50260
+memclear 1520,50455
+#define VECSIZE(1531,50753
+#define PSEUDOVECSIZE(1538,51038
+#define UNSIGNED_CMP(1546,51471
+#define ASCII_CHAR_P(1552,51725
+enum CHARTAB_SIZE_BITS1565,52480
+ CHARTAB_SIZE_BITS_0 1567,52507
+ CHARTAB_SIZE_BITS_1 1568,52536
+ CHARTAB_SIZE_BITS_2 1569,52565
+ CHARTAB_SIZE_BITS_3 1570,52594
+extern const int chartab_size[chartab_size1573,52628
+struct Lisp_Char_Table1575,52663
+ struct vectorlike_header header;1581,52919
+ Lisp_Object defalt;1585,53069
+ Lisp_Object parent;1590,53271
+ Lisp_Object purpose;1594,53389
+ Lisp_Object ascii;1598,53555
+ Lisp_Object contents[contents1600,53579
+ Lisp_Object extras[extras1603,53690
+struct Lisp_Sub_Char_Table1606,53743
+ struct vectorlike_header header;1610,53909
+ int depth;1618,54332
+ int min_char;1621,54408
+ Lisp_Object contents[contents1624,54483
+CHAR_TABLE_REF_ASCII 1628,54557
+CHAR_TABLE_REF 1648,55104
+CHAR_TABLE_SET 1658,55393
+struct Lisp_Subr1670,55777
+ struct vectorlike_header header;1672,55798
+ Lisp_Object (*a0)a01674,55847
+ Lisp_Object (*a1)a11675,55879
+ Lisp_Object (*a2)a21676,55918
+ Lisp_Object (*a3)a31677,55970
+ Lisp_Object (*a4)a41678,56035
+ Lisp_Object (*a5)a51679,56113
+ Lisp_Object (*a6)a61680,56204
+ Lisp_Object (*a7)a71681,56308
+ Lisp_Object (*a8)a81682,56425
+ Lisp_Object (*aUNEVALLED)aUNEVALLED1683,56555
+ Lisp_Object (*aMANY)aMANY1684,56607
+ } function;1685,56662
+ short min_args,1686,56678
+ short min_args, max_args;1686,56678
+ const char *symbol_name;symbol_name1687,56708
+ const char *intspec;intspec1688,56737
+ const char *doc;doc1689,56762
+enum char_table_specials1692,56789
+ CHAR_TABLE_STANDARD_SLOTS 1697,56984
+ SUB_CHAR_TABLE_OFFSET 1701,57205
+CHAR_TABLE_EXTRA_SLOTS 1707,57368
+verify 1714,57587
+LISP_MACRO_DEFUN 1723,57912
+SYMBOL_BLV 1732,58172
+SYMBOL_FWD 1738,58307
+LISP_MACRO_DEFUN_VOID 1744,58419
+SET_SYMBOL_BLV 1754,58682
+SET_SYMBOL_FWD 1760,58841
+SYMBOL_NAME 1767,58992
+SYMBOL_INTERNED_P 1775,59121
+SYMBOL_INTERNED_IN_INITIAL_OBARRAY_P 1783,59290
+#define DEFSYM(1796,59800
+LISP_MACRO_DEFUN DEFSYM1792,59621
+struct hash_table_test1805,60053
+ Lisp_Object name;1808,60130
+ Lisp_Object user_hash_function;1811,60197
+ Lisp_Object user_cmp_function;1814,60288
+ bool (*cmpfn)cmpfn1817,60363
+ EMACS_UINT (*hashfn)hashfn1820,60477
+struct Lisp_Hash_Table1823,60546
+ struct vectorlike_header header;1826,60640
+ Lisp_Object weak;1830,60774
+ Lisp_Object rehash_size;1835,60998
+ Lisp_Object rehash_threshold;1839,61120
+ Lisp_Object hash;1843,61251
+ Lisp_Object next;1848,61481
+ Lisp_Object next_free;1851,61551
+ Lisp_Object index;1856,61762
+ ptrdiff_t count;1863,62032
+ Lisp_Object key_and_value;1868,62231
+ struct hash_table_test test;1871,62305
+ struct Lisp_Hash_Table *next_weak;next_weak1875,62448
+XHASH_TABLE 1880,62522
+#define XSET_HASH_TABLE(1885,62593
+HASH_TABLE_P 1889,62694
+HASH_KEY 1896,62851
+HASH_VALUE 1903,63031
+HASH_NEXT 1911,63245
+HASH_HASH 1918,63422
+HASH_INDEX 1926,63668
+HASH_TABLE_SIZE 1933,63817
+enum DEFAULT_HASH_SIZE 1940,63947
+enum DEFAULT_HASH_SIZE { DEFAULT_HASH_SIZE 1940,63947
+static double const DEFAULT_REHASH_THRESHOLD 1946,64167
+static double const DEFAULT_REHASH_SIZE 1950,64290
+sxhash_combine 1956,64456
+SXHASH_REDUCE 1964,64639
+struct Lisp_Misc_Any 1971,64797
+ ENUM_BF (Lisp_Misc_Type) type 1973,64857
+ bool_bf gcmarkbit 1974,64918
+ unsigned spacer 1975,64943
+struct Lisp_Marker1978,64971
+ ENUM_BF (Lisp_Misc_Type) type 1980,64992
+ bool_bf gcmarkbit 1981,65056
+ unsigned spacer 1982,65081
+ bool_bf need_adjustment 1986,65273
+ bool_bf insertion_type 1989,65414
+ struct buffer *buffer;buffer2000,66007
+ struct Lisp_Marker *next;next2009,66358
+ ptrdiff_t charpos;2011,66446
+ ptrdiff_t bytepos;2016,66704
+struct Lisp_Overlay2021,66832
+ ENUM_BF (Lisp_Misc_Type) type 2034,67340
+ bool_bf gcmarkbit 2035,67406
+ unsigned spacer 2036,67433
+ struct Lisp_Overlay *next;next2037,67459
+ Lisp_Object start;2038,67490
+ Lisp_Object end;2039,67513
+ Lisp_Object plist;2040,67534
+ SAVE_UNUSED,2047,67635
+ SAVE_INTEGER,2048,67652
+ SAVE_FUNCPOINTER,2049,67670
+ SAVE_POINTER,2050,67692
+ SAVE_OBJECT2051,67710
+enum { SAVE_SLOT_BITS 2055,67795
+enum { SAVE_VALUE_SLOTS 2058,67892
+enum { SAVE_TYPE_BITS 2062,68000
+enum Lisp_Save_Type2064,68066
+ SAVE_TYPE_INT_INT 2066,68090
+ SAVE_TYPE_INT_INT_INT2067,68163
+ SAVE_TYPE_OBJ_OBJ 2069,68253
+ SAVE_TYPE_OBJ_OBJ_OBJ 2070,68324
+ SAVE_TYPE_OBJ_OBJ_OBJ_OBJ2071,68405
+ SAVE_TYPE_PTR_INT 2073,68500
+ SAVE_TYPE_PTR_OBJ 2074,68573
+ SAVE_TYPE_PTR_PTR 2075,68645
+ SAVE_TYPE_FUNCPTR_PTR_OBJ2076,68718
+ SAVE_TYPE_MEMORY 2080,68876
+typedef void (*voidfuncptr)voidfuncptr2108,69830
+struct Lisp_Save_Value2110,69867
+ ENUM_BF (Lisp_Misc_Type) type 2112,69894
+ bool_bf gcmarkbit 2113,69963
+ unsigned spacer : 32 - (16 + 1 + SAVE_TYPE_BITS)2114,69990
+ ENUM_BF (Lisp_Save_Type) save_type : SAVE_TYPE_BITS;2123,70480
+ void *pointer;pointer2125,70549
+ voidfuncptr funcpointer;2126,70570
+ ptrdiff_t integer;2127,70601
+ Lisp_Object object;2128,70626
+ } data[data2129,70652
+save_type 2134,70746
+XSAVE_POINTER 2143,70976
+set_save_pointer 2149,71138
+XSAVE_FUNCPOINTER 2155,71320
+XSAVE_INTEGER 2164,71540
+set_save_integer 2170,71702
+XSAVE_OBJECT 2179,71923
+struct Lisp_Finalizer2186,72100
+ struct Lisp_Misc_Any base;2188,72126
+ struct Lisp_Finalizer *prev;prev2191,72214
+ struct Lisp_Finalizer *next;next2192,72247
+ Lisp_Object function;2197,72484
+struct Lisp_Free2201,72575
+ ENUM_BF (Lisp_Misc_Type) type 2203,72596
+ bool_bf gcmarkbit 2204,72659
+ unsigned spacer 2205,72686
+ union Lisp_Misc *chain;chain2206,72712
+union Lisp_Misc2212,72876
+ struct Lisp_Misc_Any u_any;2214,72896
+ struct Lisp_Free u_free;2215,72967
+ struct Lisp_Marker u_marker;2216,72996
+ struct Lisp_Overlay u_overlay;2217,73029
+ struct Lisp_Save_Value u_save_value;2218,73064
+ struct Lisp_Finalizer u_finalizer;2219,73105
+XMISC 2223,73175
+XMISCANY 2229,73264
+XMISCTYPE 2236,73373
+XMARKER 2242,73461
+XOVERLAY 2249,73576
+XSAVE_VALUE 2256,73697
+XFINALIZER 2263,73826
+struct Lisp_Intfwd2274,74111
+ enum Lisp_Fwd_Type type;2276,74134
+ EMACS_INT *intvar;intvar2277,74184
+struct Lisp_Boolfwd2284,74405
+ enum Lisp_Fwd_Type type;2286,74429
+ bool *boolvar;boolvar2287,74480
+struct Lisp_Objfwd2294,74696
+ enum Lisp_Fwd_Type type;2296,74719
+ Lisp_Object *objvar;objvar2297,74769
+struct Lisp_Buffer_Objfwd2302,74928
+ enum Lisp_Fwd_Type type;2304,74958
+ int offset;2305,75015
+ Lisp_Object predicate;2307,75107
+struct Lisp_Buffer_Local_Value2334,76464
+ bool_bf local_if_set 2338,76609
+ bool_bf frame_local 2341,76791
+ bool_bf found 2344,76933
+ union Lisp_Fwd *fwd;fwd2346,77035
+ Lisp_Object where;2348,77178
+ Lisp_Object defcell;2351,77304
+ Lisp_Object valcell;2357,77608
+struct Lisp_Kboard_Objfwd2362,77723
+ enum Lisp_Fwd_Type type;2364,77753
+ int offset;2365,77810
+union Lisp_Fwd2368,77832
+ struct Lisp_Intfwd u_intfwd;2370,77851
+ struct Lisp_Boolfwd u_boolfwd;2371,77884
+ struct Lisp_Objfwd u_objfwd;2372,77919
+ struct Lisp_Buffer_Objfwd u_buffer_objfwd;2373,77952
+ struct Lisp_Kboard_Objfwd u_kboard_objfwd;2374,77999
+XFWDTYPE 2378,78078
+XBUFFER_OBJFWD 2384,78174
+struct Lisp_Float2391,78310
+ double data;2395,78348
+ struct Lisp_Float *chain;chain2396,78367
+ } u;2397,78399
+XFLOAT_DATA 2401,78428
+ IEEE_FLOATING_POINT2415,78937
+#define _UCHAR_T2423,79260
+typedef unsigned char UCHAR;2424,79277
+enum Lisp_Compiled2429,79360
+ COMPILED_ARGLIST 2431,79383
+ COMPILED_BYTECODE 2432,79409
+ COMPILED_CONSTANTS 2433,79436
+ COMPILED_STACK_DEPTH 2434,79464
+ COMPILED_DOC_STRING 2435,79494
+ COMPILED_INTERACTIVE 2436,79523
+enum char_bits2443,79825
+ CHAR_ALT 2445,79844
+ CHAR_SUPER 2446,79870
+ CHAR_HYPER 2447,79898
+ CHAR_SHIFT 2448,79926
+ CHAR_CTL 2449,79954
+ CHAR_META 2450,79980
+ CHAR_MODIFIER_MASK 2452,80008
+ CHARACTERBITS 2457,80203
+LISP_MACRO_DEFUN 2462,80261
+NATNUMP 2470,80403
+RANGED_INTEGERP 2476,80484
+#define TYPE_RANGED_INTEGERP(2481,80606
+LISP_MACRO_DEFUN 2486,80791
+VECTORP 2500,81264
+OVERLAYP 2505,81367
+SAVE_VALUEP 2510,81466
+FINALIZERP 2516,81572
+AUTOLOADP 2522,81676
+BUFFER_OBJFWDP 2528,81767
+PSEUDOVECTOR_TYPEP 2534,81865
+PSEUDOVECTORP 2542,82118
+WINDOW_CONFIGURATIONP 2558,82470
+PROCESSP 2564,82580
+WINDOWP 2570,82664
+TERMINALP 2576,82746
+SUBRP 2582,82832
+COMPILEDP 2588,82910
+BUFFERP 2594,82996
+CHAR_TABLE_P 2600,83078
+SUB_CHAR_TABLE_P 2606,83169
+BOOL_VECTOR_P 2612,83268
+FRAMEP 2618,83361
+IMAGEP 2625,83478
+ARRAYP 2632,83583
+CHECK_LIST 2638,83702
+LISP_MACRO_DEFUN_VOID 2643,83783
+CHECK_STRING_CAR 2653,84080
+CHECK_CONS 2658,84184
+CHECK_VECTOR 2663,84264
+CHECK_BOOL_VECTOR 2668,84350
+CHECK_VECTOR_OR_STRING 2674,84527
+CHECK_ARRAY 2683,84701
+CHECK_BUFFER 2688,84809
+CHECK_WINDOW 2693,84895
+CHECK_PROCESS 2699,85001
+CHECK_NATNUM 2705,85097
+#define CHECK_RANGED_INTEGER(2710,85174
+#define CHECK_TYPE_RANGED_INTEGER(2721,85557
+#define CHECK_NUMBER_COERCE_MARKER(2729,85827
+XFLOATINT 2738,86080
+CHECK_NUMBER_OR_FLOAT 2744,86151
+#define CHECK_NUMBER_OR_FLOAT_COERCE_MARKER(2749,86250
+CHECK_NUMBER_CAR 2760,86660
+CHECK_NUMBER_CDR 2768,86782
+#define DEFUN(2803,88377
+#define DEFUN(2812,88845
+FUNCTIONP 2822,89200
+extern void defsubr 2829,89352
+enum maxargs2831,89395
+ MANY 2833,89412
+ UNEVALLED 2834,89427
+#define CALLMANY(2838,89530
+#define CALLN(2844,89883
+extern void defvar_lisp 2846,89953
+extern void defvar_lisp_nopro 2847,90030
+extern void defvar_bool 2848,90113
+extern void defvar_int 2849,90184
+extern void defvar_kboard 2850,90258
+#define DEFVAR_LISP(2869,91088
+#define DEFVAR_LISP_NOPRO(2874,91260
+#define DEFVAR_BOOL(2879,91442
+#define DEFVAR_INT(2884,91615
+#define DEFVAR_BUFFER_DEFAULTS(2890,91786
+#define DEFVAR_KBOARD(2896,91990
+typedef jmp_buf sys_jmp_buf;2906,92314
+# define sys_setjmp(2907,92343
+# define sys_longjmp(2908,92378
+typedef sigjmp_buf sys_jmp_buf;2910,92450
+# define sys_setjmp(2911,92482
+# define sys_longjmp(2912,92522
+typedef jmp_buf sys_jmp_buf;2916,92681
+# define sys_setjmp(2917,92710
+# define sys_longjmp(2918,92744
+enum specbind_tag 2943,93796
+ SPECPDL_UNWIND,2944,93816
+ SPECPDL_UNWIND_PTR,2945,93885
+ SPECPDL_UNWIND_INT,2946,93936
+ SPECPDL_UNWIND_VOID,2947,93984
+ SPECPDL_BACKTRACE,2948,94038
+ SPECPDL_LET,2949,94096
+ SPECPDL_LET_LOCAL,2951,94226
+ SPECPDL_LET_DEFAULT 2952,94283
+union specbinding2955,94355
+ ENUM_BF (specbind_tag) kind : CHAR_BIT;2957,94377
+ ENUM_BF (specbind_tag) kind : CHAR_BIT;2959,94434
+ void (*func)func2960,94480
+ Lisp_Object arg;2961,94514
+ } unwind;2962,94537
+ ENUM_BF (specbind_tag) kind : CHAR_BIT;2964,94564
+ void (*func)func2965,94610
+ void *arg;arg2966,94639
+ } unwind_ptr;2967,94656
+ ENUM_BF (specbind_tag) kind : CHAR_BIT;2969,94687
+ void (*func)func2970,94733
+ int arg;2971,94759
+ } unwind_int;2972,94774
+ ENUM_BF (specbind_tag) kind : CHAR_BIT;2974,94805
+ void (*func)func2975,94851
+ } unwind_void;2976,94878
+ ENUM_BF (specbind_tag) kind : CHAR_BIT;2978,94910
+ Lisp_Object symbol,2980,95017
+ Lisp_Object symbol, old_value,2980,95017
+ Lisp_Object symbol, old_value, where;2980,95017
+ } let;2981,95061
+ ENUM_BF (specbind_tag) kind : CHAR_BIT;2983,95085
+ bool_bf debug_on_exit 2984,95131
+ Lisp_Object function;2985,95164
+ Lisp_Object *args;args2986,95192
+ ptrdiff_t nargs;2987,95217
+ } bt;2988,95240
+extern union specbinding *specpdl;specpdl2991,95256
+extern union specbinding *specpdl_ptr;specpdl_ptr2992,95291
+extern ptrdiff_t specpdl_size;2993,95330
+SPECPDL_INDEX 2996,95379
+enum handlertype 3021,96401
+enum handlertype { CATCHER,3021,96401
+enum handlertype { CATCHER, CONDITION_CASE 3021,96401
+struct handler3023,96448
+ enum handlertype type;3025,96465
+ Lisp_Object tag_or_ch;3026,96490
+ Lisp_Object val;3027,96515
+ struct handler *next;next3028,96534
+ struct handler *nextfree;nextfree3029,96558
+ Lisp_Object *bytecode_top;bytecode_top3036,96916
+ int bytecode_dest;3037,96945
+ struct gcpro *gcpro;gcpro3042,97182
+ sys_jmp_buf jmp;3044,97212
+ EMACS_INT lisp_eval_depth;3045,97231
+ ptrdiff_t pdlcount;3046,97260
+ int poll_suppress_count;3047,97282
+ int interrupt_input_blocked;3048,97309
+ struct byte_stack *byte_stack;byte_stack3049,97340
+#define PUSH_HANDLER(3053,97437
+extern Lisp_Object memory_signal_data;3075,98143
+extern char *stack_bottom;stack_bottom3079,98276
+extern void process_pending_signals 3097,99093
+extern bool volatile pending_signals;3098,99137
+extern void process_quit_flag 3100,99176
+#define QUIT 3101,99214
+#define QUITP 3112,99464
+extern Lisp_Object Vascii_downcase_table;3114,99525
+extern Lisp_Object Vascii_canon_table;3115,99567
+extern struct gcpro *gcprolist;gcprolist3130,100274
+struct gcpro3132,100307
+ struct gcpro *next;next3134,100322
+ volatile Lisp_Object *var;var3137,100391
+ ptrdiff_t nvars;3140,100473
+ const char *name;name3144,100558
+ int lineno;3147,100614
+ int idx;3150,100675
+ int level;3153,100711
+#define GC_USE_GCPROS_AS_BEFORE 3171,101288
+#define GC_MAKE_GCPROS_NOOPS 3172,101323
+#define GC_MARK_STACK_CHECK_GCPROS 3173,101355
+#define GC_USE_GCPROS_CHECK_ZOMBIES 3174,101392
+#define GC_MARK_STACK 3177,101453
+#define BYTE_MARK_STACK 3181,101553
+#define GCPRO1(3190,101824
+#define GCPRO2(3191,101864
+#define GCPRO3(3192,101930
+#define GCPRO4(3194,102025
+#define GCPRO5(3196,102145
+#define GCPRO6(3198,102290
+#define GCPRO7(3201,102465
+#define UNGCPRO 3202,102544
+#define GCPRO1(3208,102644
+#define GCPRO2(3212,102766
+#define GCPRO3(3217,102958
+#define GCPRO4(3223,103220
+#define GCPRO5(3230,103551
+#define GCPRO6(3238,103952
+#define GCPRO7(3247,104422
+#define UNGCPRO 3257,104962
+extern int gcpro_level;3261,105031
+#define GCPRO1(3263,105056
+#define GCPRO2(3269,105290
+#define GCPRO3(3278,105708
+#define GCPRO4(3289,106265
+#define GCPRO5(3302,106963
+#define GCPRO6(3317,107803
+#define GCPRO7(3334,108784
+#define UNGCPRO 3353,109907
+#define RETURN_UNGCPRO(3363,110174
+void staticpro 3375,110447
+vcopy 3384,110648
+set_hash_key_slot 3393,110923
+set_hash_value_slot 3399,111062
+set_symbol_function 3408,111297
+set_symbol_plist 3414,111412
+set_symbol_next 3420,111515
+blv_found 3428,111688
+set_overlay_plist 3437,111871
+string_intervals 3445,112022
+set_string_intervals 3453,112144
+set_char_table_defalt 3462,112346
+set_char_table_purpose 3467,112458
+set_char_table_extras 3475,112627
+set_char_table_contents 3482,112836
+set_sub_char_table_contents 3489,113031
+extern Lisp_Object indirect_function 3495,113190
+extern Lisp_Object find_symbol_value 3496,113242
+enum Arith_Comparison 3497,113294
+ ARITH_EQUAL,3498,113318
+ ARITH_NOTEQUAL,3499,113333
+ ARITH_LESS,3500,113351
+ ARITH_GRTR,3501,113365
+ ARITH_LESS_OR_EQUAL,3502,113379
+ ARITH_GRTR_OR_EQUAL3503,113402
+extern Lisp_Object arithcompare 3505,113427
+#define INTEGER_TO_CONS(3511,113753
+#define CONS_TO_INTEGER(3529,114616
+extern intmax_t cons_to_signed 3533,114831
+extern uintmax_t cons_to_unsigned 3534,114897
+extern struct Lisp_Symbol *indirect_variable indirect_variable3536,114958
+extern _Noreturn void args_out_of_range 3537,115027
+extern _Noreturn void args_out_of_range_3 3538,115095
+extern Lisp_Object do_symval_forwarding 3540,115186
+extern void set_internal 3541,115246
+extern void syms_of_data 3542,115318
+extern void swap_in_global_binding 3543,115351
+extern void syms_of_cmds 3546,115435
+extern void keys_of_cmds 3547,115468
+extern Lisp_Object detect_coding_system 3550,115530
+extern void init_coding 3552,115683
+extern void init_coding_once 3553,115715
+extern void syms_of_coding 3554,115752
+extern ptrdiff_t chars_in_text 3557,115819
+extern ptrdiff_t multibyte_chars_in_text 3558,115886
+extern void syms_of_character 3559,115963
+extern void init_charset 3562,116031
+extern void init_charset_once 3563,116064
+extern void syms_of_charset 3564,116102
+extern void init_syntax_once 3569,116222
+extern void syms_of_syntax 3570,116259
+enum { NEXT_ALMOST_PRIME_LIMIT 3573,116320
+extern EMACS_INT next_almost_prime 3574,116359
+enum constype 3739,123811
+enum constype {CONSTYPE_HEAP,CONSTYPE_HEAP3739,123811
+enum constype {CONSTYPE_HEAP, CONSTYPE_PURE}CONSTYPE_PURE3739,123811
+extern Lisp_Object listn 3740,123857
+list2i 3745,124001
+list3i 3751,124110
+list4i 3757,124249
+extern Lisp_Object make_uninit_bool_vector 3763,124401
+extern Lisp_Object bool_vector_fill 3764,124457
+extern _Noreturn void string_overflow 3765,124521
+extern Lisp_Object make_string 3766,124567
+extern Lisp_Object make_formatted_string 3767,124625
+extern Lisp_Object make_multibyte_string 3779,124979
+extern Lisp_Object make_event_array 3780,125058
+extern Lisp_Object make_uninit_string 3781,125122
+extern Lisp_Object make_uninit_multibyte_string 3782,125173
+extern Lisp_Object make_string_from_bytes 3783,125245
+extern Lisp_Object make_specified_string 3784,125325
+extern Lisp_Object make_pure_string 3786,125417
+extern Lisp_Object make_pure_c_string 3787,125497
+build_pure_c_string 3792,125653
+build_string 3801,125858
+extern Lisp_Object pure_cons 3806,125936
+extern void make_byte_code 3807,125993
+extern struct Lisp_Vector *allocate_vector allocate_vector3808,126044
+make_uninit_vector 3820,126429
+make_uninit_sub_char_table 3833,126648
+extern struct Lisp_Vector *allocate_pseudovector allocate_pseudovector3844,126957
+#define ALLOCATE_PSEUDOVECTOR(3850,127192
+#define ALLOCATE_ZEROED_PSEUDOVECTOR(3858,127528
+extern bool gc_in_progress;3863,127729
+extern bool abort_on_gc;3864,127757
+extern Lisp_Object make_float 3865,127782
+extern void display_malloc_warning 3866,127822
+extern ptrdiff_t inhibit_garbage_collection 3867,127865
+extern Lisp_Object make_save_int_int_int 3868,127917
+extern Lisp_Object make_save_obj_obj_obj_obj 3869,127993
+extern Lisp_Object make_save_ptr 3871,128103
+extern Lisp_Object make_save_ptr_int 3872,128146
+extern Lisp_Object make_save_ptr_ptr 3873,128204
+extern Lisp_Object make_save_funcptr_ptr_obj 3874,128259
+extern Lisp_Object make_save_memory 3876,128355
+extern void free_save_value 3877,128419
+extern Lisp_Object build_overlay 3878,128462
+extern void free_marker 3879,128536
+extern void free_cons 3880,128575
+extern void init_alloc_once 3881,128619
+extern void init_alloc 3882,128655
+extern void syms_of_alloc 3883,128686
+extern struct buffer * allocate_buffer 3884,128720
+extern int valid_lisp_object_p 3885,128767
+extern int relocatable_string_data_p 3886,128813
+extern void check_cons_list 3888,128892
+INLINE void 3890,128934
+extern void *r_alloc r_alloc3895,129055
+#define FLOAT_TO_STRING_BUFSIZE 3927,130518
+extern int openp 3957,131667
+extern Lisp_Object string_to_number 3959,131777
+extern void map_obarray 3960,131840
+extern void dir_warning 3962,131954
+extern void init_obarray 3963,132007
+extern void init_lread 3964,132040
+extern void syms_of_lread 3965,132071
+intern 3968,132125
+intern_c_string 3974,132213
+extern EMACS_INT lisp_eval_depth;3980,132326
+extern Lisp_Object Vautoload_queue;3981,132360
+extern Lisp_Object Vrun_hooks;3982,132396
+extern Lisp_Object Vsignaling_function;3983,132427
+extern Lisp_Object inhibit_lisp_code;3984,132467
+extern struct handler *handlerlist;handlerlist3985,132505
+extern void run_hook 3994,132747
+extern void run_hook_with_args_2 3995,132783
+extern Lisp_Object run_hook_with_args 3996,132857
+extern _Noreturn void xsignal 3999,133016
+extern _Noreturn void xsignal0 4000,133074
+extern _Noreturn void xsignal1 4001,133120
+extern _Noreturn void xsignal2 4002,133179
+extern _Noreturn void xsignal3 4003,133251
+extern _Noreturn void signal_error 4005,133340
+extern Lisp_Object eval_sub 4006,133404
+extern Lisp_Object apply1 4007,133452
+extern Lisp_Object call0 4008,133506
+extern Lisp_Object call1 4009,133546
+extern Lisp_Object call2 4010,133599
+extern Lisp_Object call3 4011,133665
+extern Lisp_Object call4 4012,133744
+extern Lisp_Object call5 4013,133836
+extern Lisp_Object call6 4014,133941
+extern Lisp_Object call7 4015,134059
+extern Lisp_Object internal_catch 4016,134190
+extern Lisp_Object internal_lisp_condition_case 4017,134283
+extern Lisp_Object internal_condition_case 4018,134372
+extern Lisp_Object internal_condition_case_1 4019,134485
+extern Lisp_Object internal_condition_case_2 4020,134620
+extern Lisp_Object internal_condition_case_n4021,134781
+extern void specbind 4024,134977
+extern void record_unwind_protect 4025,135026
+extern void record_unwind_protect_ptr 4026,135099
+extern void record_unwind_protect_int 4027,135166
+extern void record_unwind_protect_void 4028,135227
+extern void record_unwind_protect_nothing 4029,135285
+extern void clear_unwind_protect 4030,135335
+extern void set_unwind_protect 4031,135381
+extern void set_unwind_protect_ptr 4032,135462
+extern Lisp_Object unbind_to 4033,135537
+extern _Noreturn void error 4034,135592
+fast_string_match_ignore_case 4136,140080
+extern ptrdiff_t fast_c_string_match_ignore_case 4141,140230
+extern ptrdiff_t fast_looking_at 4143,140327
+extern ptrdiff_t find_newline 4145,140466
+extern ptrdiff_t scan_newline 4147,140595
+extern ptrdiff_t scan_newline_from_point 4149,140698
+extern ptrdiff_t find_newline_no_quit 4150,140778
+extern ptrdiff_t find_before_next_newline 4152,140875
+extern void syms_of_search 4154,140973
+extern void clear_regexp_cache 4155,141008
+extern Lisp_Object Vminibuffer_list;4159,141078
+extern Lisp_Object last_minibuf_string;4160,141115
+extern Lisp_Object get_minibuffer 4161,141155
+extern void init_minibuf_once 4162,141202
+extern void syms_of_minibuf 4163,141240
+extern void syms_of_callint 4167,141307
+extern void syms_of_casefiddle 4171,141377
+extern void keys_of_casefiddle 4172,141416
+extern void init_casetab_once 4176,141486
+extern void syms_of_casetab 4177,141524
+extern Lisp_Object echo_message_buffer;4181,141592
+extern struct kboard *echo_kboard;echo_kboard4182,141632
+extern void cancel_echoing 4183,141667
+extern Lisp_Object last_undo_boundary;4184,141702
+extern bool input_pending;4185,141741
+extern sigjmp_buf return_to_command_loop;4187,141804
+extern Lisp_Object menu_bar_items 4189,141853
+extern Lisp_Object tool_bar_items 4190,141902
+extern void discard_mouse_events 4191,141958
+void handle_input_available_signal 4193,142019
+extern Lisp_Object pending_funcalls;4195,142068
+extern bool detect_input_pending 4196,142105
+extern bool detect_input_pending_ignore_squeezables 4197,142146
+extern bool detect_input_pending_run_timers 4198,142206
+extern void safe_run_hooks 4199,142258
+extern void cmd_error_internal 4200,142300
+extern Lisp_Object command_loop_1 4201,142360
+extern Lisp_Object read_menu_command 4202,142402
+extern Lisp_Object recursive_edit_1 4203,142447
+extern void record_auto_save 4204,142491
+extern void force_auto_save_soon 4205,142528
+extern void init_keyboard 4206,142569
+extern void syms_of_keyboard 4207,142603
+extern void keys_of_keyboard 4208,142640
+extern ptrdiff_t current_column 4211,142706
+extern void invalidate_current_column 4212,142746
+extern bool indented_beyond_p 4213,142792
+extern void syms_of_indent 4214,142857
+extern void store_frame_param 4217,142920
+extern void store_in_alist 4218,142994
+extern Lisp_Object do_switch_frame 4219,143064
+extern Lisp_Object get_frame_param 4220,143137
+extern void frames_discard_buffer 4221,143203
+extern void syms_of_frame 4222,143252
+extern char **initial_argv;initial_argv4225,143314
+extern int initial_argc;4226,143342
+extern bool display_arg;4228,143417
+extern Lisp_Object decode_env_path 4230,143449
+extern Lisp_Object empty_unibyte_string,4231,143520
+extern Lisp_Object empty_unibyte_string, empty_multibyte_string;4231,143520
+extern _Noreturn void terminate_due_to_signal 4232,143585
+extern Lisp_Object Vlibrary_cache;4234,143660
+void fixup_locale 4237,143721
+void synchronize_system_messages_locale 4238,143747
+void synchronize_system_time_locale 4239,143795
+INLINE void fixup_locale 4241,143845
+INLINE void synchronize_system_messages_locale 4242,143880
+INLINE void synchronize_system_time_locale 4243,143937
+extern void shut_down_emacs 4245,143997
+extern bool noninteractive;4248,144123
+extern bool no_site_lisp;4251,144215
+extern int daemon_pipe[daemon_pipe4256,144383
+#define IS_DAEMON 4257,144410
+#define DAEMON_RUNNING 4258,144450
+extern void *w32_daemon_event;w32_daemon_event4260,144518
+#define IS_DAEMON 4261,144549
+#define DAEMON_RUNNING 4262,144594
+extern bool fatal_error_in_progress;4266,144715
+extern bool inhibit_window_system;4269,144821
+extern bool running_asynch_code;4271,144914
+extern void kill_buffer_processes 4274,144977
+extern int wait_reading_process_output 4275,145026
+# define WAIT_READING_MAX 4281,145413
+# define WAIT_READING_MAX 4283,145485
+extern void add_timer_wait_descriptor 4286,145549
+extern void add_keyboard_wait_descriptor 4288,145601
+extern void delete_keyboard_wait_descriptor 4289,145649
+extern void add_gpm_wait_descriptor 4291,145716
+extern void delete_gpm_wait_descriptor 4292,145759
+extern void init_process_emacs 4294,145812
+extern void syms_of_process 4295,145851
+extern void setup_process_coding_systems 4296,145887
+extern int child_setup 4302,146007
+extern void init_callproc_1 4303,146075
+extern void init_callproc 4304,146111
+extern void set_initial_environment 4305,146145
+extern void syms_of_callproc 4306,146189
+extern Lisp_Object read_doc_string 4309,146252
+extern Lisp_Object get_doc_string 4310,146302
+extern void syms_of_doc 4311,146363
+extern int read_bytecode_char 4312,146395
+extern void syms_of_bytecode 4315,146464
+extern struct byte_stack *byte_stack_list;byte_stack_list4316,146501
+extern void mark_byte_stack 4318,146564
+extern void unmark_byte_stack 4320,146607
+extern Lisp_Object exec_byte_code 4321,146645
+extern void init_macros 4325,146795
+extern void syms_of_macros 4326,146827
+extern void truncate_undo_list 4329,146889
+extern void record_insert 4330,146939
+extern void record_delete 4331,146989
+extern void record_first_change 4332,147047
+extern void record_change 4333,147087
+extern void record_property_change 4334,147137
+extern void syms_of_undo 4337,147279
+extern void report_interval_modification 4340,147343
+extern void syms_of_menu 4343,147439
+extern void syms_of_xmenu 4346,147500
+extern char *get_current_dir_name get_current_dir_name4356,147702
+extern void stuff_char 4358,147751
+extern void init_foreground_group 4359,147784
+extern void sys_subshell 4360,147826
+extern void sys_suspend 4361,147859
+extern void discard_tty_input 4362,147891
+extern void init_sys_modes 4363,147929
+extern void reset_sys_modes 4364,147985
+extern void init_all_sys_modes 4365,148042
+extern void reset_all_sys_modes 4366,148081
+extern void child_setup_tty 4367,148121
+extern void setup_pty 4368,148156
+extern int set_window_size 4369,148185
+extern EMACS_INT get_random 4370,148229
+extern void seed_random 4371,148265
+extern void init_random 4372,148310
+extern void emacs_backtrace 4373,148342
+extern _Noreturn void emacs_abort 4374,148377
+extern void xputenv 4527,152691
+extern char *egetenv_internal egetenv_internal4529,152728
+egetenv 4532,152800
+extern void init_system_name 4539,153003
+#define eabs(4545,153296
+#define make_fixnum_or_float(4550,153429
+enum MAX_ALLOCA 4556,153680
+enum MAX_ALLOCA { MAX_ALLOCA 4556,153680
+extern void *record_xmalloc record_xmalloc4558,153725
+#define USE_SAFE_ALLOCA 4560,153791
+#define AVAIL_ALLOCA(4564,153924
+#define SAFE_ALLOCA(4568,154035
+#define SAFE_NALLOCA(4576,154376
+#define SAFE_ALLOCA_STRING(4590,154852
+#define SAFE_FREE(4598,155104
+#define SAFE_ALLOCA_LISP(4625,155682
+# define USE_STACK_LISP_OBJECTS 4652,156804
+# undef USE_STACK_LISP_OBJECTS4658,156970
+# define USE_STACK_LISP_OBJECTS 4659,157001
+enum { defined_GC_CHECK_STRING_BYTES 4663,157076
+enum { defined_GC_CHECK_STRING_BYTES 4665,157129
+union Aligned_Cons4670,157263
+ struct Lisp_Cons s;4672,157284
+ double d;4673,157306
+ double d; intmax_t i;4673,157306
+ double d; intmax_t i; void *p;p4673,157306
+union Aligned_String4676,157343
+ struct Lisp_String s;4678,157366
+ double d;4679,157390
+ double d; intmax_t i;4679,157390
+ double d; intmax_t i; void *p;p4679,157390
+ USE_STACK_CONS 4689,157698
+ USE_STACK_STRING 4691,157804
+#define STACK_CONS(4699,158141
+#define AUTO_CONS_EXPR(4701,158238
+#define AUTO_CONS(4709,158601
+#define AUTO_LIST1(4710,158672
+#define AUTO_LIST2(4712,158780
+#define AUTO_LIST3(4716,158935
+#define AUTO_LIST4(4720,159110
+extern const char *verify_ascii verify_ascii4730,159447
+# define verify_ascii(4732,159501
+#define AUTO_STRING(4740,159809
+#define FOR_EACH_TAIL(4752,160273
+#define FOR_EACH_ALIST_VALUE(4766,160764
+maybe_gc 4774,161051
+functionp 4784,161290
c-src/machsyscalls.c,23
#define SYSCALL(6,113
@@ -3033,27 +3029,27 @@ cp-src/burton.cpp,103
cp-src/functions.cpp,807
void Date::setDate 5,148
-void Date::plus 32,939
-void Date::minus 42,1229
-void Date::shift 52,1407
-Date & Date::operator = Date::operator =62,1628
-Date & Date::operator += Date::operator +=69,1789
-Date & Date::operator -= Date::operator -=78,1939
-Date & Date::operator ++ Date::operator ++87,2080
-Date & Date::operator -- Date::operator --96,2216
-int Date::operator - Date::operator -104,2331
-int Date::operator < Date::operator <112,2483
-int Date::operator > Date::operator >116,2557
-int Date::operator == Date::operator ==120,2631
-ostream& operator << operator <<124,2707
-istream& operator >> operator >>133,2943
-bool isLeap 159,3543
-bool isHoliday 163,3629
-void asort(173,3865
-void ReadVacation 186,4064
-void Debug 201,4523
-int WorkingDays(211,4867
-Date StartDay(226,5129
+void Date::plus 32,938
+void Date::minus 42,1226
+void Date::shift 52,1404
+Date & Date::operator = Date::operator =62,1625
+Date & Date::operator += Date::operator +=69,1786
+Date & Date::operator -= Date::operator -=78,1935
+Date & Date::operator ++ Date::operator ++87,2076
+Date & Date::operator -- Date::operator --96,2212
+int Date::operator - Date::operator -104,2327
+int Date::operator < Date::operator <112,2479
+int Date::operator > Date::operator >116,2553
+int Date::operator == Date::operator ==120,2627
+ostream& operator << operator <<124,2703
+istream& operator >> operator >>133,2939
+bool isLeap 159,3539
+bool isHoliday 163,3625
+void asort(173,3861
+void ReadVacation 186,4060
+void Debug 201,4519
+int WorkingDays(211,4863
+Date StartDay(226,5125
cp-src/MDiagArray2.h,1538
#define octave_MDiagArray2_h 29,870
@@ -3253,137 +3249,137 @@ main(37,571
D(D::D43,659
int x;D::x44,694
-el-src/TAGTEST.EL,179
-(foo::defmumble bletch 1,0
-(defun foo==bar foo==bar2,33
-(defalias 'pending-delete-mode pending-delete-mode6,149
-(defalias (quote explicitly-quoted-pending-delete-mode)9,222
+el-src/TAGTEST.EL,181
+(foo::defmumble bletch 3,33
+(defun foo==bar foo==bar4,66
+(defalias 'pending-delete-mode pending-delete-mode8,182
+(defalias (quote explicitly-quoted-pending-delete-mode)11,255
el-src/emacs/lisp/progmodes/etags.el,5188
-(defvar tags-file-name 34,1034
-(defgroup etags 43,1498
-(defcustom tags-case-fold-search 47,1566
-(defcustom tags-table-list 59,2051
-(defcustom tags-compression-info-list69,2449
-(defcustom tags-add-tables 88,3231
-(defcustom tags-revert-without-query 98,3627
-(defvar tags-table-computed-list 103,3778
-(defvar tags-table-computed-list-for 112,4262
-(defvar tags-table-list-pointer 117,4510
-(defvar tags-table-list-started-at 121,4701
-(defvar tags-table-set-list 124,4821
-(defcustom find-tag-hook 129,5000
-(defcustom find-tag-default-function 137,5263
-(define-obsolete-variable-alias 'find-tag-marker-ring-lengthfind-tag-marker-ring-length145,5602
-(defcustom tags-tag-face 148,5699
-(defcustom tags-apropos-verbose 154,5834
-(defcustom tags-apropos-additional-actions 160,5998
-(defvaralias 'find-tag-marker-ring find-tag-marker-ring183,6917
-(defvar default-tags-table-function 189,7097
-(defvar tags-location-ring 194,7323
-(defvar tags-table-files 201,7599
-(defvar tags-completion-table 206,7766
-(defvar tags-included-tables 209,7858
-(defvar next-file-list 212,7953
-(defvar tags-table-format-functions 217,8059
-(defvar file-of-tag-function 224,8440
-(defvar tags-table-files-function 228,8634
-(defvar tags-completion-table-function 230,8745
-(defvar snarf-tag-function 232,8840
-(defvar goto-tag-location-function 236,9049
-(defvar find-tag-regexp-search-function 239,9222
-(defvar find-tag-regexp-tag-order 241,9343
-(defvar find-tag-regexp-next-line-after-failure-p 243,9452
-(defvar find-tag-search-function 245,9572
-(defvar find-tag-tag-order 247,9679
-(defvar find-tag-next-line-after-failure-p 249,9774
-(defvar list-tags-function 251,9880
-(defvar tags-apropos-function 253,9968
-(defvar tags-included-tables-function 255,10062
-(defvar verify-tags-table-function 257,10181
-(defun initialize-new-tags-table 260,10292
-(defun tags-table-mode 276,10980
-(defun visit-tags-table 285,11245
-(defun tags-table-check-computed-list 321,12783
-(defun tags-table-extend-computed-list 360,14654
-(defun tags-expand-table-name 400,16367
-(defun tags-table-list-member 409,16710
-(defun tags-verify-table 421,17182
-(defun tags-table-including 470,19302
-(defun tags-next-table 522,21346
-(defun visit-tags-table-buffer 543,22203
-(defun tags-reset-tags-tables 712,28513
-(defun file-of-tag 731,29170
-(defun tags-table-files 740,29519
-(defun tags-included-tables 749,29869
-(defun tags-completion-table 755,30115
-(defun tags-lazy-completion-table 783,31309
-(defun tags-completion-at-point-function 799,31944
-(defun find-tag-tag 818,32694
-(defvar last-tag 837,33367
-(defun find-tag-interactive 840,33426
-(defvar find-tag-history 852,33841
-(defvar etags-case-fold-search)855,33906
-(defvar etags-syntax-table)856,33938
-(defvar local-find-tag-hook)857,33966
-(defun find-tag-noselect 860,34011
-(defun find-tag 932,37125
-(defun find-tag-other-window 959,38341
-(defun find-tag-other-frame 1000,40269
-(defun find-tag-regexp 1025,41443
-(defalias 'pop-tag-mark pop-tag-mark1049,42605
-(defvar tag-lines-already-matched 1052,42656
-(defun find-tag-in-order 1055,42763
-(defun tag-find-file-of-tag-noselect 1167,47109
-(defun tag-find-file-of-tag 1200,48955
-(defun etags-recognize-tags-table 1208,49181
-(defun etags-verify-tags-table 1241,50812
-(defun etags-file-of-tag 1246,51010
-(defun etags-tags-completion-table 1256,51345
-(defun etags-snarf-tag 1286,52551
-(defun etags-goto-tag-location 1324,54120
-(defun etags-list-tags 1388,56563
-(defmacro tags-with-face 1423,57838
-(defun etags-tags-apropos-additional 1431,58171
-(defun etags-tags-apropos 1465,59408
-(defun etags-tags-table-files 1527,61617
-(defun etags-tags-included-tables 1542,62053
-(defun tags-recognize-empty-tags-table 1559,62593
-(defun tag-exact-file-name-match-p 1587,63739
-(defun tag-file-name-match-p 1596,64132
-(defun tag-exact-match-p 1609,64688
-(defun tag-implicit-name-match-p 1620,65256
-(defun tag-symbol-match-p 1633,65856
-(defun tag-word-match-p 1643,66292
-(defun tag-partial-file-name-match-p 1652,66690
-(defun tag-any-match-p 1662,67134
-(defun tag-re-match-p 1667,67318
-(defcustom tags-loop-revert-buffers 1675,67567
-(defun next-file 1685,67976
-(defvar tags-loop-operate 1760,70890
-(defvar tags-loop-scan1763,70984
-(defun tags-loop-eval 1771,71313
-(defun tags-loop-continue 1782,71642
-(defun tags-search 1850,73948
-(defun tags-query-replace 1871,74774
-(defun tags-complete-tags-table-file 1896,75998
-(defun list-tags 1906,76377
-(defun tags-apropos 1934,77330
-(define-button-type 'tags-select-tags-tabletags-select-tags-table1957,78156
-(defun select-tags-table 1964,78395
-(defvar select-tags-table-mode-map 2019,80522
-(define-derived-mode select-tags-table-mode 2030,80905
-(defun select-tags-table-select 2034,81089
-(defun select-tags-table-quit 2043,81455
-(defun complete-tag 2049,81610
-(defconst etags--xref-limit 2074,82551
-(defvar etags-xref-find-definitions-tag-order 2076,82586
-(defun etags-xref-find 2082,82876
-(defun etags--xref-find-definitions 2096,83405
-(defclass xref-etags-location 2129,85119
-(defun xref-make-etags-location 2135,85342
-(cl-defmethod xref-location-marker 2139,85497
-(cl-defmethod xref-location-line 2146,85741
+(defvar tags-file-name 34,1035
+(defgroup etags 43,1499
+(defcustom tags-case-fold-search 47,1567
+(defcustom tags-table-list 59,2052
+(defcustom tags-compression-info-list69,2450
+(defcustom tags-add-tables 88,3232
+(defcustom tags-revert-without-query 98,3628
+(defvar tags-table-computed-list 103,3779
+(defvar tags-table-computed-list-for 112,4263
+(defvar tags-table-list-pointer 117,4511
+(defvar tags-table-list-started-at 121,4702
+(defvar tags-table-set-list 124,4822
+(defcustom find-tag-hook 129,5001
+(defcustom find-tag-default-function 137,5264
+(define-obsolete-variable-alias 'find-tag-marker-ring-lengthfind-tag-marker-ring-length145,5603
+(defcustom tags-tag-face 148,5700
+(defcustom tags-apropos-verbose 154,5835
+(defcustom tags-apropos-additional-actions 160,5999
+(defvaralias 'find-tag-marker-ring find-tag-marker-ring183,6921
+(defvar default-tags-table-function 189,7101
+(defvar tags-location-ring 194,7327
+(defvar tags-table-files 201,7603
+(defvar tags-completion-table 206,7770
+(defvar tags-included-tables 209,7862
+(defvar next-file-list 212,7957
+(defvar tags-table-format-functions 217,8063
+(defvar file-of-tag-function 224,8444
+(defvar tags-table-files-function 228,8638
+(defvar tags-completion-table-function 230,8749
+(defvar snarf-tag-function 232,8844
+(defvar goto-tag-location-function 236,9053
+(defvar find-tag-regexp-search-function 239,9226
+(defvar find-tag-regexp-tag-order 241,9347
+(defvar find-tag-regexp-next-line-after-failure-p 243,9456
+(defvar find-tag-search-function 245,9576
+(defvar find-tag-tag-order 247,9683
+(defvar find-tag-next-line-after-failure-p 249,9778
+(defvar list-tags-function 251,9884
+(defvar tags-apropos-function 253,9972
+(defvar tags-included-tables-function 255,10066
+(defvar verify-tags-table-function 257,10185
+(defun initialize-new-tags-table 260,10296
+(defun tags-table-mode 276,10984
+(defun visit-tags-table 285,11249
+(defun tags-table-check-computed-list 321,12787
+(defun tags-table-extend-computed-list 360,14658
+(defun tags-expand-table-name 400,16371
+(defun tags-table-list-member 409,16714
+(defun tags-verify-table 421,17186
+(defun tags-table-including 470,19306
+(defun tags-next-table 522,21350
+(defun visit-tags-table-buffer 543,22207
+(defun tags-reset-tags-tables 712,28517
+(defun file-of-tag 731,29174
+(defun tags-table-files 740,29524
+(defun tags-included-tables 749,29874
+(defun tags-completion-table 755,30120
+(defun tags-lazy-completion-table 783,31314
+(defun tags-completion-at-point-function 799,31949
+(defun find-tag-tag 818,32699
+(defvar last-tag 837,33372
+(defun find-tag-interactive 840,33431
+(defvar find-tag-history 852,33846
+(defvar etags-case-fold-search)855,33911
+(defvar etags-syntax-table)856,33943
+(defvar local-find-tag-hook)857,33971
+(defun find-tag-noselect 860,34016
+(defun find-tag 932,37130
+(defun find-tag-other-window 959,38346
+(defun find-tag-other-frame 1000,40274
+(defun find-tag-regexp 1025,41448
+(defalias 'pop-tag-mark pop-tag-mark1049,42610
+(defvar tag-lines-already-matched 1052,42661
+(defun find-tag-in-order 1055,42768
+(defun tag-find-file-of-tag-noselect 1167,47114
+(defun tag-find-file-of-tag 1200,48960
+(defun etags-recognize-tags-table 1208,49186
+(defun etags-verify-tags-table 1241,50817
+(defun etags-file-of-tag 1246,51015
+(defun etags-tags-completion-table 1256,51350
+(defun etags-snarf-tag 1286,52556
+(defun etags-goto-tag-location 1324,54125
+(defun etags-list-tags 1388,56568
+(defmacro tags-with-face 1423,57843
+(defun etags-tags-apropos-additional 1431,58176
+(defun etags-tags-apropos 1465,59413
+(defun etags-tags-table-files 1527,61622
+(defun etags-tags-included-tables 1542,62058
+(defun tags-recognize-empty-tags-table 1559,62598
+(defun tag-exact-file-name-match-p 1587,63744
+(defun tag-file-name-match-p 1596,64137
+(defun tag-exact-match-p 1609,64693
+(defun tag-implicit-name-match-p 1620,65261
+(defun tag-symbol-match-p 1633,65861
+(defun tag-word-match-p 1643,66297
+(defun tag-partial-file-name-match-p 1652,66695
+(defun tag-any-match-p 1662,67139
+(defun tag-re-match-p 1667,67323
+(defcustom tags-loop-revert-buffers 1675,67572
+(defun next-file 1685,67981
+(defvar tags-loop-operate 1760,70895
+(defvar tags-loop-scan1763,70989
+(defun tags-loop-eval 1771,71318
+(defun tags-loop-continue 1782,71647
+(defun tags-search 1850,73953
+(defun tags-query-replace 1871,74779
+(defun tags-complete-tags-table-file 1896,76003
+(defun list-tags 1906,76382
+(defun tags-apropos 1934,77335
+(define-button-type 'tags-select-tags-tabletags-select-tags-table1957,78161
+(defun select-tags-table 1964,78400
+(defvar select-tags-table-mode-map 2019,80527
+(define-derived-mode select-tags-table-mode 2030,80910
+(defun select-tags-table-select 2034,81094
+(defun select-tags-table-quit 2043,81460
+(defun complete-tag 2049,81615
+(defconst etags--xref-limit 2074,82556
+(defvar etags-xref-find-definitions-tag-order 2076,82591
+(defun etags-xref-find 2082,82881
+(defun etags--xref-find-definitions 2096,83410
+(defclass xref-etags-location 2129,85124
+(defun xref-make-etags-location 2135,85347
+(cl-defmethod xref-location-marker 2139,85502
+(cl-defmethod xref-location-line 2146,85746
erl-src/gs_dialog.erl,98
-define(VERSION2,32
@@ -3457,10 +3453,10 @@ func main(29,285
html-src/softwarelibero.html,200
Cos'è il software libero?4,38
-Licenze d'uso di un programmalicenze65,2500
-Sfatiamo alcuni miti138,6118
-Il movimento open sourceoss191,8037
-Impatto pratico del software liberoimpatto231,10066
+Licenze d'uso di un programmalicenze65,2502
+Sfatiamo alcuni miti138,6122
+Il movimento open sourceoss191,8041
+Impatto pratico del software liberoimpatto231,10070
html-src/index.shtml,104
&nbsp;8,281
@@ -3486,13 +3482,13 @@ MTGmtg41,1482
Fracasfracas65,2624
GaliLEOgalileo101,4232
Leasqrleasqr114,4677
-Free software that I wrote for the GNU project or for my personal or workgnu142,6065
-Etagsetags148,6180
-checkiso161,6729
-cgrep178,7547
-debian-bug.eldebian-bug190,7979
-tcpdump205,8564
-Links to interesting softwarelinks216,8891
+Free software that I wrote for the GNU project or for my personal or workgnu142,6066
+Etagsetags148,6181
+checkiso161,6731
+cgrep178,7549
+debian-bug.eldebian-bug190,7981
+tcpdump205,8566
+Links to interesting softwarelinks216,8893
lua-src/allegro.lua,400
local function get_layer_by_name 7,175
@@ -4050,22 +4046,22 @@ ord_add_element(71,1867
ord_del_element(85,2344
ord_disjoint(100,2783
ord_intersect(108,2953
-ord_intersection(126,3552
-ord_intersection3(130,3691
-ord_intersection(150,4531
-ord_intersection4(154,4703
-ord_intersection(176,5664
-ord_intersection2(181,5812
-ord_member(200,6318
-ord_seteq(216,6683
-ord_setproduct(225,6971
-ord_subset(240,7377
-ord_subtract(257,7861
-ord_symdiff(265,8054
-ord_union(288,8887
-ord_union4(303,9352
-ord_union(324,10171
-ord_union_all(329,10313
+ord_intersection(126,3553
+ord_intersection3(130,3692
+ord_intersection(150,4533
+ord_intersection4(154,4705
+ord_intersection(176,5666
+ord_intersection2(181,5814
+ord_member(200,6320
+ord_seteq(216,6685
+ord_setproduct(225,6973
+ord_subset(240,7379
+ord_subtract(257,7863
+ord_symdiff(265,8056
+ord_union(288,8889
+ord_union4(303,9354
+ord_union(324,10173
+ord_union_all(329,10315
prol-src/natded.prolog,2319
expandmng(100,2879
@@ -4087,92 +4083,92 @@ complete(328,10055
add_active(340,10527
parse(353,10949
derived_analyses(364,11341
-build(378,11965
-buildact(392,12521
-mapsyn(412,13542
-add_edge(434,14278
-findcats(447,14758
-normalize_tree(465,15478
-normalize_trees(475,15856
-expandmng_tree(486,16248
-expandmng_trees(496,16614
-cat(511,17013
-subtree(644,21266
-hypothetical_mem(653,21565
-make_coor(667,22130
-start_up:-start_up688,23013
-tokenizeatom(710,23921
-tokenize(720,24348
-isoperator(752,25377
-isoptab(756,25431
-specialsymbol(765,25756
-sstab(771,25861
-parse_cgi(787,26347
-keyvalseq(792,26510
-andkeyvalseq(796,26609
-keyval(799,26688
-valseq(807,26920
-plusvalseq(810,27007
-val(816,27109
-argvals(824,27426
-commaargvals(828,27503
-atomval(833,27578
-atom(836,27640
-action(846,28004
-keyvalcgi(864,28649
-keyvalscgi(865,28670
-outsyn(868,28726
-act(876,29060
-actout(901,29906
-texttreelist(912,30089
-htmltreelist(918,30190
-fitchtreelist(924,30304
-pp_html_table_tree(938,30759
-pp_html_tree(949,31113
-pp_html_trees(988,32381
-pp_html_table_fitch_tree(999,32769
-pp_html_fitch_tree(1017,33672
-removeexp(1129,39002
-splitexp(1142,39490
-pp_exp(1155,39990
-map_word(1168,40249
-pp_exps(1180,40474
-pp_tree(1188,40777
-pp_trees(1216,41807
-pp_word_list(1225,42128
-pp_word(1231,42262
-pp_word_list_rest(1238,42569
-pp_cat(1248,42929
-pp_syn(1255,43196
-pp_syn_paren(1276,43899
-pp_paren(1293,44377
-pp_syn_back(1300,44661
-pp_bas_cat(1311,45001
-writecat(1322,45409
-writesubs(1351,46455
-writesups(1361,46757
-writelistsubs(1371,47090
-pp_lam(1380,47408
-pp_lam_bracket(1398,48022
-pp_lam_paren(1407,48338
-pp_rule(1429,49238
-member(1447,49866
-append_list(1451,49919
-append(1456,50010
-at_least_one_member(1460,50076
-numbervars(1464,50171
-reverse(1467,50209
-select(1471,50290
-select_last(1475,50357
-cat_atoms(1479,50436
-writelist(1485,50524
-write_lex_cat(1492,50676
-writebreaklex(1500,50988
-write_lex(1513,51265
-writebreak(1521,51541
-tt:-tt1531,51713
-mt:-mt1534,51784
-cmt:-cmt1537,51878
+build(378,11967
+buildact(392,12523
+mapsyn(412,13544
+add_edge(434,14280
+findcats(447,14760
+normalize_tree(465,15480
+normalize_trees(475,15858
+expandmng_tree(486,16250
+expandmng_trees(496,16616
+cat(511,17015
+subtree(644,21268
+hypothetical_mem(653,21567
+make_coor(667,22132
+start_up:-start_up688,23015
+tokenizeatom(710,23923
+tokenize(720,24350
+isoperator(752,25379
+isoptab(756,25433
+specialsymbol(765,25758
+sstab(771,25863
+parse_cgi(787,26349
+keyvalseq(792,26512
+andkeyvalseq(796,26611
+keyval(799,26690
+valseq(807,26922
+plusvalseq(810,27009
+val(816,27111
+argvals(824,27428
+commaargvals(828,27505
+atomval(833,27580
+atom(836,27642
+action(846,28006
+keyvalcgi(864,28651
+keyvalscgi(865,28672
+outsyn(868,28728
+act(876,29062
+actout(901,29908
+texttreelist(912,30091
+htmltreelist(918,30192
+fitchtreelist(924,30306
+pp_html_table_tree(938,30761
+pp_html_tree(949,31115
+pp_html_trees(988,32383
+pp_html_table_fitch_tree(999,32771
+pp_html_fitch_tree(1017,33674
+removeexp(1129,39004
+splitexp(1142,39492
+pp_exp(1155,39992
+map_word(1168,40251
+pp_exps(1180,40476
+pp_tree(1188,40779
+pp_trees(1216,41809
+pp_word_list(1225,42130
+pp_word(1231,42264
+pp_word_list_rest(1238,42571
+pp_cat(1248,42931
+pp_syn(1255,43198
+pp_syn_paren(1276,43901
+pp_paren(1293,44379
+pp_syn_back(1300,44663
+pp_bas_cat(1311,45003
+writecat(1322,45411
+writesubs(1351,46457
+writesups(1361,46759
+writelistsubs(1371,47092
+pp_lam(1380,47410
+pp_lam_bracket(1398,48024
+pp_lam_paren(1407,48340
+pp_rule(1429,49240
+member(1447,49868
+append_list(1451,49921
+append(1456,50012
+at_least_one_member(1460,50078
+numbervars(1464,50173
+reverse(1467,50211
+select(1471,50292
+select_last(1475,50359
+cat_atoms(1479,50438
+writelist(1485,50526
+write_lex_cat(1492,50678
+writebreaklex(1500,50990
+write_lex(1513,51267
+writebreak(1521,51543
+tt:-tt1531,51715
+mt:-mt1534,51786
+cmt:-cmt1537,51880
pyt-src/server.py,1438
class Controls:Controls17,358
@@ -4280,6 +4276,11 @@ module A9,57
alias_method ( :foo2,foo237,586
A::Constant Constant42,655
+rs-src/test.rs,52
+enum IpAddrKind 3,11
+fn test1(8,48
+fn main(12,88
+
scm-src/test.scm,260
(define hello 1,0
(set! hello 3,32
@@ -4297,730 +4298,884 @@ tex-src/gzip.texi,303
@node Top,62,2139
@node Copying,80,2652
@node Overview,83,2705
-@node Sample,166,7272
-@node Invoking gzip,Invoking gzip210,8828
-@node Advanced usage,Advanced usage357,13496
-@node Environment,420,15208
-@node Tapes,437,15769
-@node Problems,460,16768
-@node Concept Index,Concept Index473,17288
+@node Sample,166,7273
+@node Invoking gzip,Invoking gzip210,8829
+@node Advanced usage,Advanced usage357,13497
+@node Environment,420,15209
+@node Tapes,437,15770
+@node Problems,460,16769
+@node Concept Index,Concept Index473,17289
tex-src/texinfo.tex,30627
-\def\texinfoversion{\texinfoversion26,1032
-\def\tie{\tie49,1523
-\def\gloggingall{\gloggingall72,2273
-\def\loggingall{\loggingall73,2342
-\def\onepageout#1{\onepageout99,3279
-\def\croppageout#1{\croppageout115,4029
-\def\cropmarks{\cropmarks142,5089
-\def\pagebody#1{\pagebody144,5136
-\def\ewtop{\ewtop157,5591
-\def\nstop{\nstop158,5655
-\def\ewbot{\ewbot160,5738
-\def\nsbot{\nsbot161,5802
-\def\parsearg #1{\parsearg170,6101
-\def\parseargx{\parseargx172,6179
-\def\parseargline{\parseargline182,6419
-\def\flushcr{\flushcr186,6540
-\newif\ifENV \ENVfalse \def\inENV{\inENV190,6739
-\def\ENVcheck{\ENVcheck191,6803
-\outer\def\begin{\begin198,7050
-\def\beginxxx #1{\beginxxx200,7088
-\def\end{\end208,7343
-\def\endxxx #1{\endxxx210,7371
-\def\errorE#1{\errorE216,7560
-\def\singlespace{\singlespace222,7754
-\def\@{\@232,7977
-\def\`{\`236,8077
-\def\'{\'237,8089
-\def\mylbrace {\mylbrace241,8137
-\def\myrbrace {\myrbrace242,8170
-\def\:{\:247,8284
-\def\*{\*250,8338
-\def\.{\.253,8414
-\def\w#1{\w258,8645
-\def\group{\group268,9128
- \def\Egroup{\Egroup273,9292
-\def\need{\need289,9734
-\def\needx#1{\needx300,10011
-\def\dots{\dots339,11397
-\def\page{\page343,11461
-\def\exdent{\exdent353,11788
-\def\exdentyyy #1{\exdentyyy354,11821
-\def\nofillexdent{\nofillexdent357,11965
-\def\nofillexdentyyy #1{\nofillexdentyyy358,12010
-\def\include{\include365,12194
-\def\includezzz #1{\includezzz366,12229
-\def\thisfile{\thisfile369,12280
-\def\center{\center373,12343
-\def\centerzzz #1{\centerzzz374,12376
-\def\sp{\sp380,12518
-\def\spxxx #1{\spxxx381,12543
-\def\comment{\comment387,12717
-\def\commentxxx #1{\commentxxx390,12814
-\def\ignoresections{\ignoresections396,12983
-\let\chapter=\relax=\relax397,13005
-\let\section=\relax=\relax406,13250
-\let\subsection=\relax=\relax409,13311
-\let\subsubsection=\relax=\relax410,13334
-\let\appendix=\relax=\relax411,13360
-\let\appendixsec=\relaxsec=\relax412,13381
-\let\appendixsection=\relaxsection=\relax413,13405
-\let\appendixsubsec=\relaxsubsec=\relax414,13433
-\let\appendixsubsection=\relaxsubsection=\relax415,13460
-\let\appendixsubsubsec=\relaxsubsubsec=\relax416,13491
-\let\appendixsubsubsection=\relaxsubsubsection=\relax417,13521
-\def\ignore{\ignore423,13623
-\long\def\ignorexxx #1\end ignore{\ignorexxx427,13763
-\def\direntry{\direntry429,13822
-\long\def\direntryxxx #1\end direntry{\direntryxxx430,13861
-\def\ifset{\ifset434,13971
-\def\ifsetxxx #1{\ifsetxxx436,14029
-\def\Eifset{\Eifset440,14156
-\def\ifsetfail{\ifsetfail441,14170
-\long\def\ifsetfailxxx #1\end ifset{\ifsetfailxxx442,14226
-\def\ifclear{\ifclear444,14287
-\def\ifclearxxx #1{\ifclearxxx446,14349
-\def\Eifclear{\Eifclear450,14480
-\def\ifclearfail{\ifclearfail451,14496
-\long\def\ifclearfailxxx #1\end ifclear{\ifclearfailxxx452,14556
-\def\set{\set456,14707
-\def\setxxx #1{\setxxx457,14734
-\def\clear{\clear460,14796
-\def\clearxxx #1{\clearxxx461,14827
-\def\iftex{\iftex466,14944
-\def\Eiftex{\Eiftex467,14957
-\def\ifinfo{\ifinfo468,14971
-\long\def\ifinfoxxx #1\end ifinfo{\ifinfoxxx469,15021
-\long\def\menu #1\end menu{\menu471,15080
-\def\asis#1{\asis472,15109
-\def\math#1{\math485,15652
-\def\node{\node487,15696
-\def\nodezzz#1{\nodezzz488,15734
-\def\nodexxx[#1,#2]{\nodexxx[489,15765
-\def\donoderef{\donoderef492,15827
-\def\unnumbnoderef{\unnumbnoderef496,15948
-\def\appendixnoderef{\appendixnoderef500,16079
-\expandafter\expandafter\expandafter\appendixsetref{setref501,16125
-\let\refill=\relaxill=\relax504,16214
-\def\setfilename{\setfilename509,16428
-\outer\def\bye{\bye518,16674
-\def\inforef #1{\inforef520,16730
-\def\inforefzzz #1,#2,#3,#4**{\inforefzzz521,16768
-\def\losespace #1{\losespace523,16865
-\def\sf{\sf532,17069
-\font\defbf=cmbx10 scaled \magstep1 %was 1314bf=cmbx10558,17864
-\font\deftt=cmtt10 scaled \magstep1tt=cmtt10559,17910
-\def\df{\df560,17946
-\def\resetmathfonts{\resetmathfonts635,20540
-\def\textfonts{\textfonts648,21129
-\def\chapfonts{\chapfonts653,21344
-\def\secfonts{\secfonts658,21560
-\def\subsecfonts{\subsecfonts663,21765
-\def\indexfonts{\indexfonts668,21982
-\def\smartitalicx{\smartitalicx691,22714
-\def\smartitalic#1{\smartitalic692,22790
-\let\cite=\smartitalic=\smartitalic698,22935
-\def\b#1{\b700,22959
-\def\t#1{\t703,22994
-\def\samp #1{\samp706,23146
-\def\key #1{\key707,23179
-\def\ctrl #1{\ctrl708,23240
-\def\tclose#1{\tclose716,23442
-\def\ {\720,23608
-\def\xkey{\xkey728,23877
-\def\kbdfoo#1#2#3\par{\kbdfoo729,23893
-\def\dmn#1{\dmn738,24194
-\def\kbd#1{\kbd740,24221
-\def\l#1{\l742,24278
-\def\r#1{\r744,24307
-\def\sc#1{\sc746,24375
-\def\ii#1{\ii747,24418
-\def\titlefont#1{\titlefont755,24651
-\def\titlepage{\titlepage761,24754
- \def\subtitlefont{\subtitlefont766,24981
- \def\authorfont{\authorfont768,25065
- \def\title{\title774,25275
- \def\titlezzz##1{\titlezzz775,25310
- \def\subtitle{\subtitle783,25625
- \def\subtitlezzz##1{\subtitlezzz784,25666
- \def\author{\author787,25784
- \def\authorzzz##1{\authorzzz788,25821
- \def\page{\page794,26112
-\def\Etitlepage{\Etitlepage804,26281
-\def\finishtitlepage{\finishtitlepage817,26669
-\def\evenheading{\evenheading846,27677
-\def\oddheading{\oddheading847,27720
-\def\everyheading{\everyheading848,27761
-\def\evenfooting{\evenfooting850,27807
-\def\oddfooting{\oddfooting851,27850
-\def\everyfooting{\everyfooting852,27891
-\def\headings #1 {\headings893,29583
-\def\HEADINGSoff{\HEADINGSoff895,29632
-\def\HEADINGSdouble{\HEADINGSdouble904,30059
-\def\HEADINGSsingle{\HEADINGSsingle914,30379
-\def\HEADINGSon{\HEADINGSon922,30600
-\def\HEADINGSafter{\HEADINGSafter924,30634
-\def\HEADINGSdoublex{\HEADINGSdoublex926,30729
-\def\HEADINGSsingleafter{\HEADINGSsingleafter933,30917
-\def\HEADINGSsinglex{\HEADINGSsinglex934,30978
-\def\today{\today943,31253
-\def\thistitle{\thistitle958,31798
-\def\settitle{\settitle959,31823
-\def\settitlezzz #1{\settitlezzz960,31860
-\def\internalBitem{\internalBitem992,32790
-\def\internalBitemx{\internalBitemx993,32840
-\def\internalBxitem "#1"{\internalBxitem995,32885
-\def\internalBxitemx "#1"{\internalBxitemx996,32965
-\def\internalBkitem{\internalBkitem998,33040
-\def\internalBkitemx{\internalBkitemx999,33092
-\def\kitemzzz #1{\kitemzzz1001,33139
-\def\xitemzzz #1{\xitemzzz1004,33241
-\def\itemzzz #1{\itemzzz1007,33344
-\def\item{\item1037,34415
-\def\itemx{\itemx1038,34466
-\def\kitem{\kitem1039,34519
-\def\kitemx{\kitemx1040,34572
-\def\xitem{\xitem1041,34627
-\def\xitemx{\xitemx1042,34680
-\def\description{\description1045,34790
-\def\table{\table1047,34840
-\def\ftable{\ftable1052,34984
-\def\Eftable{\Eftable1056,35130
-\def\vtable{\vtable1059,35199
-\def\Evtable{\Evtable1063,35345
-\def\dontindex #1{\dontindex1066,35414
-\def\fnitemindex #1{\fnitemindex1067,35434
-\def\vritemindex #1{\vritemindex1068,35479
-\def\tablez #1#2#3#4#5#6{\tablez1074,35628
-\def\Edescription{\Edescription1077,35686
-\def\itemfont{\itemfont1082,35888
-\def\Etable{\Etable1090,36114
-\def\itemize{\itemize1103,36438
-\def\itemizezzz #1{\itemizezzz1105,36474
-\def\itemizey #1#2{\itemizey1110,36569
-\def#2{1119,36815
-\def\itemcontents{\itemcontents1120,36856
-\def\bullet{\bullet1123,36904
-\def\minus{\minus1124,36931
-\def\frenchspacing{\frenchspacing1128,37039
-\def\splitoff#1#2\endmark{\splitoff1134,37264
-\def\enumerate{\enumerate1140,37494
-\def\enumeratezzz #1{\enumeratezzz1141,37533
-\def\enumeratey #1 #2\endenumeratey{\enumeratey1142,37586
- \def\thearg{\thearg1146,37733
- \ifx\thearg\empty \def\thearg{\thearg1147,37752
-\def\numericenumerate{\numericenumerate1184,39086
-\def\lowercaseenumerate{\lowercaseenumerate1190,39216
-\def\uppercaseenumerate{\uppercaseenumerate1203,39563
-\def\startenumeration#1{\startenumeration1219,40053
-\def\alphaenumerate{\alphaenumerate1227,40235
-\def\capsenumerate{\capsenumerate1228,40270
-\def\Ealphaenumerate{\Ealphaenumerate1229,40304
-\def\Ecapsenumerate{\Ecapsenumerate1230,40338
-\def\itemizeitem{\itemizeitem1234,40418
-\def\newindex #1{\newindex1259,41275
-\def\defindex{\defindex1268,41564
-\def\newcodeindex #1{\newcodeindex1272,41672
-\def\defcodeindex{\defcodeindex1279,41932
-\def\synindex #1 #2 {\synindex1283,42112
-\def\syncodeindex #1 #2 {\syncodeindex1292,42452
-\def\doindex#1{\doindex1309,43131
-\def\singleindexer #1{\singleindexer1310,43190
-\def\docodeindex#1{\docodeindex1313,43302
-\def\singlecodeindexer #1{\singlecodeindexer1314,43369
-\def\indexdummies{\indexdummies1316,43427
-\def\_{\_1317,43447
-\def\w{\w1318,43475
-\def\bf{\bf1319,43502
-\def\rm{\rm1320,43531
-\def\sl{\sl1321,43560
-\def\sf{\sf1322,43589
-\def\tt{\tt1323,43617
-\def\gtr{\gtr1324,43645
-\def\less{\less1325,43675
-\def\hat{\hat1326,43707
-\def\char{\char1327,43737
-\def\TeX{\TeX1328,43769
-\def\dots{\dots1329,43799
-\def\copyright{\copyright1330,43832
-\def\tclose##1{\tclose1331,43875
-\def\code##1{\code1332,43920
-\def\samp##1{\samp1333,43961
-\def\t##1{\t1334,44002
-\def\r##1{\r1335,44037
-\def\i##1{\i1336,44072
-\def\b##1{\b1337,44107
-\def\cite##1{\cite1338,44142
-\def\key##1{\key1339,44183
-\def\file##1{\file1340,44222
-\def\var##1{\var1341,44263
-\def\kbd##1{\kbd1342,44302
-\def\indexdummyfont#1{\indexdummyfont1347,44458
-\def\indexdummytex{\indexdummytex1348,44484
-\def\indexdummydots{\indexdummydots1349,44508
-\def\indexnofonts{\indexnofonts1351,44534
-\let\w=\indexdummyfontdummyfont1352,44554
-\let\t=\indexdummyfontdummyfont1353,44577
-\let\r=\indexdummyfontdummyfont1354,44600
-\let\i=\indexdummyfontdummyfont1355,44623
-\let\b=\indexdummyfontdummyfont1356,44646
-\let\emph=\indexdummyfontdummyfont1357,44669
-\let\strong=\indexdummyfontdummyfont1358,44695
-\let\cite=\indexdummyfont=\indexdummyfont1359,44723
-\let\sc=\indexdummyfontdummyfont1360,44749
-\let\tclose=\indexdummyfontdummyfont1364,44921
-\let\code=\indexdummyfontdummyfont1365,44949
-\let\file=\indexdummyfontdummyfont1366,44975
-\let\samp=\indexdummyfontdummyfont1367,45001
-\let\kbd=\indexdummyfontdummyfont1368,45027
-\let\key=\indexdummyfontdummyfont1369,45052
-\let\var=\indexdummyfontdummyfont1370,45077
-\let\TeX=\indexdummytexdummytex1371,45102
-\let\dots=\indexdummydotsdummydots1372,45126
-\let\indexbackslash=0 %overridden during \printindex.backslash=01382,45378
-\def\doind #1#2{\doind1384,45434
-{\indexdummies % Must do this here, since \bf, etc expand at this stagedummies1386,45477
-\def\rawbackslashxx{\rawbackslashxx1389,45617
-{\indexnofontsnofonts1394,45879
-\def\dosubind #1#2#3{\dosubind1405,46190
-{\indexdummies % Must do this here, since \bf, etc expand at this stagedummies1407,46238
-\def\rawbackslashxx{\rawbackslashxx1410,46342
-{\indexnofontsnofonts1414,46496
-\def\findex {\findex1443,47427
-\def\kindex {\kindex1444,47450
-\def\cindex {\cindex1445,47473
-\def\vindex {\vindex1446,47496
-\def\tindex {\tindex1447,47519
-\def\pindex {\pindex1448,47542
-\def\cindexsub {\cindexsub1450,47566
-\def\printindex{\printindex1462,47893
-\def\doprintindex#1{\doprintindex1464,47934
- \def\indexbackslash{\indexbackslash1481,48419
- \indexfonts\rm \tolerance=9500 \advance\baselineskip -1ptfonts\rm1482,48458
-\def\initial #1{\initial1517,49530
-\def\entry #1#2{\entry1523,49737
- \null\nobreak\indexdotfill % Have leaders before the page number.dotfill1540,50384
-\def\indexdotfill{\indexdotfill1549,50712
-\def\primary #1{\primary1552,50818
-\def\secondary #1#2{\secondary1556,50900
-\noindent\hskip\secondaryindent\hbox{#1}\indexdotfill #2\pardotfill1559,50982
-\newbox\partialpageialpage1566,51155
-\def\begindoublecolumns{\begindoublecolumns1572,51313
- \output={\global\setbox\partialpage=ialpage=1573,51349
-\def\enddoublecolumns{\enddoublecolumns1577,51537
-\def\doublecolumnout{\doublecolumnout1580,51622
- \dimen@=\pageheight \advance\dimen@ by-\ht\partialpageialpage1581,51691
-\def\pagesofar{\pagesofar1584,51869
-\def\balancecolumns{\balancecolumns1588,52106
- \availdimen@=\pageheight \advance\availdimen@ by-\ht\partialpageialpage1594,52277
- \dimen@=\pageheight \advance\dimen@ by-\ht\partialpageialpage1600,52538
-\newcount \appendixno \appendixno = `\@no1627,53443
-\def\appendixletter{\appendixletter1628,53484
-\def\opencontents{\opencontents1632,53587
-\def\thischapter{\thischapter1637,53768
-\def\seccheck#1{\seccheck1638,53806
-\def\chapternofonts{\chapternofonts1643,53910
-\def\result{\result1646,53985
-\def\equiv{\equiv1647,54020
-\def\expansion{\expansion1648,54053
-\def\print{\print1649,54094
-\def\TeX{\TeX1650,54127
-\def\dots{\dots1651,54156
-\def\copyright{\copyright1652,54187
-\def\tt{\tt1653,54228
-\def\bf{\bf1654,54255
-\def\w{\w1655,54283
-\def\less{\less1656,54308
-\def\gtr{\gtr1657,54339
-\def\hat{\hat1658,54368
-\def\char{\char1659,54397
-\def\tclose##1{\tclose1660,54428
-\def\code##1{\code1661,54472
-\def\samp##1{\samp1662,54512
-\def\r##1{\r1663,54552
-\def\b##1{\b1664,54586
-\def\key##1{\key1665,54620
-\def\file##1{\file1666,54658
-\def\kbd##1{\kbd1667,54698
-\def\i##1{\i1669,54806
-\def\cite##1{\cite1670,54840
-\def\var##1{\var1671,54880
-\def\emph##1{\emph1672,54918
-\def\dfn##1{\dfn1673,54958
-\def\thischaptername{\thischaptername1676,54999
-\outer\def\chapter{\chapter1677,55038
-\def\chapterzzz #1{\chapterzzz1678,55079
-{\chapternofonts%nofonts%1687,55475
-\global\let\section = \numberedsec=1692,55628
-\global\let\subsection = \numberedsubsec=1693,55663
-\global\let\subsubsection = \numberedsubsubsec=1694,55704
-\outer\def\appendix{\appendix1697,55755
-\def\appendixzzz #1{\appendixzzz1698,55798
-\global\advance \appendixno by 1 \message{no1700,55875
-\chapmacro {#1}{Appendix \appendixletter}letter1701,55944
-\xdef\thischapter{Appendix \appendixletter: \noexpand\thischaptername}letter:1704,56037
-{\chapternofonts%nofonts%1705,56109
- {#1}{Appendix \appendixletter}letter1707,56165
-\appendixnoderef %noderef1710,56265
-\global\let\section = \appendixsec=1711,56284
-\global\let\subsection = \appendixsubsec=1712,56319
-\global\let\subsubsection = \appendixsubsubsec=1713,56360
-\outer\def\top{\top1716,56411
-\outer\def\unnumbered{\unnumbered1717,56451
-\def\unnumberedzzz #1{\unnumberedzzz1718,56498
-{\chapternofonts%nofonts%1722,56661
-\global\let\section = \unnumberedsec=1727,56811
-\global\let\subsection = \unnumberedsubsec=1728,56848
-\global\let\subsubsection = \unnumberedsubsubsec=1729,56891
-\outer\def\numberedsec{\numberedsec1732,56944
-\def\seczzz #1{\seczzz1733,56985
-{\chapternofonts%nofonts%1736,57141
-\outer\def\appendixsection{\appendixsection1745,57327
-\outer\def\appendixsec{\appendixsec1746,57384
-\def\appendixsectionzzz #1{\appendixsectionzzz1747,57437
-\gdef\thissection{#1}\secheading {#1}{\appendixletter}letter1749,57549
-{\chapternofonts%nofonts%1750,57617
-{#1}{\appendixletter}letter1752,57673
-\appendixnoderef %noderef1755,57773
-\outer\def\unnumberedsec{\unnumberedsec1759,57813
-\def\unnumberedseczzz #1{\unnumberedseczzz1760,57866
-{\chapternofonts%nofonts%1762,57961
-\outer\def\numberedsubsec{\numberedsubsec1770,58129
-\def\numberedsubseczzz #1{\numberedsubseczzz1771,58184
-{\chapternofonts%nofonts%1774,58363
-\outer\def\appendixsubsec{\appendixsubsec1783,58567
-\def\appendixsubseczzz #1{\appendixsubseczzz1784,58622
-\subsecheading {#1}{\appendixletter}letter1786,58744
-{\chapternofonts%nofonts%1787,58809
-{#1}{\appendixletter}letter1789,58868
-\appendixnoderef %noderef1792,58983
-\outer\def\unnumberedsubsec{\unnumberedsubsec1796,59023
-\def\unnumberedsubseczzz #1{\unnumberedsubseczzz1797,59082
-{\chapternofonts%nofonts%1799,59183
-\outer\def\numberedsubsubsec{\numberedsubsubsec1807,59354
-\def\numberedsubsubseczzz #1{\numberedsubsubseczzz1808,59415
-{\chapternofonts%nofonts%1812,59612
-\outer\def\appendixsubsubsec{\appendixsubsubsec1823,59845
-\def\appendixsubsubseczzz #1{\appendixsubsubseczzz1824,59906
- {\appendixletter}letter1827,60045
-{\chapternofonts%nofonts%1828,60111
- {\appendixletter}letter1830,60176
-\appendixnoderef %noderef1834,60310
-\outer\def\unnumberedsubsubsec{\unnumberedsubsubsec1838,60350
-\def\unnumberedsubsubseczzz #1{\unnumberedsubsubseczzz1839,60415
-{\chapternofonts%nofonts%1841,60522
-\def\infotop{\infotop1851,60851
-\def\infounnumbered{\infounnumbered1852,60889
-\def\infounnumberedsec{\infounnumberedsec1853,60934
-\def\infounnumberedsubsec{\infounnumberedsubsec1854,60985
-\def\infounnumberedsubsubsec{\infounnumberedsubsubsec1855,61042
-\def\infoappendix{\infoappendix1857,61106
-\def\infoappendixsec{\infoappendixsec1858,61147
-\def\infoappendixsubsec{\infoappendixsubsec1859,61194
-\def\infoappendixsubsubsec{\infoappendixsubsubsec1860,61247
-\def\infochapter{\infochapter1862,61307
-\def\infosection{\infosection1863,61346
-\def\infosubsection{\infosubsection1864,61385
-\def\infosubsubsection{\infosubsubsection1865,61430
-\global\let\section = \numberedsec=1870,61667
-\global\let\subsection = \numberedsubsec=1871,61702
-\global\let\subsubsection = \numberedsubsubsec=1872,61743
-\def\majorheading{\majorheading1886,62250
-\def\majorheadingzzz #1{\majorheadingzzz1887,62295
-\def\chapheading{\chapheading1893,62528
-\def\chapheadingzzz #1{\chapheadingzzz1894,62571
-\def\heading{\heading1899,62766
-\def\subheading{\subheading1901,62803
-\def\subsubheading{\subsubheading1903,62846
-\def\dobreak#1#2{\dobreak1910,63123
-\def\setchapterstyle #1 {\setchapterstyle1912,63201
-\def\chapbreak{\chapbreak1919,63456
-\def\chappager{\chappager1920,63506
-\def\chapoddpage{\chapoddpage1921,63544
-\def\setchapternewpage #1 {\setchapternewpage1923,63623
-\def\CHAPPAGoff{\CHAPPAGoff1925,63680
-\def\CHAPPAGon{\CHAPPAGon1929,63774
-\global\def\HEADINGSon{\HEADINGSon1932,63865
-\def\CHAPPAGodd{\CHAPPAGodd1934,63907
-\global\def\HEADINGSon{\HEADINGSon1937,64003
-\def\CHAPFplain{\CHAPFplain1941,64057
-\def\chfplain #1#2{\chfplain1945,64149
-\def\unnchfplain #1{\unnchfplain1956,64372
-\def\unnchfopen #1{\unnchfopen1964,64601
-\def\chfopen #1#2{\chfopen1970,64809
-\def\CHAPFopen{\CHAPFopen1975,64953
-\def\subsecheadingbreak{\subsecheadingbreak1982,65171
-\def\secheadingbreak{\secheadingbreak1985,65300
-\def\secheading #1#2#3{\secheading1993,65582
-\def\plainsecheading #1{\plainsecheading1994,65638
-\def\secheadingi #1{\secheadingi1995,65681
-\def\subsecheading #1#2#3#4{\subsecheading2006,66049
-\def\subsecheadingi #1{\subsecheadingi2007,66116
-\def\subsubsecfonts{\subsubsecfonts2014,66413
-\def\subsubsecheading #1#2#3#4#5{\subsubsecheading2017,66536
-\def\subsubsecheadingi #1{\subsubsecheadingi2018,66614
-\def\startcontents#1{\startcontents2032,67086
- \unnumbchapmacro{#1}\def\thischapter{\thischapter2040,67359
-\outer\def\contents{\contents2049,67718
-\outer\def\summarycontents{\summarycontents2057,67862
- \def\secentry ##1##2##3##4{\secentry2067,68233
- \def\unnumbsecentry ##1##2{\unnumbsecentry2068,68268
- \def\subsecentry ##1##2##3##4##5{\subsecentry2069,68303
- \def\unnumbsubsecentry ##1##2{\unnumbsubsecentry2070,68344
- \def\subsubsecentry ##1##2##3##4##5##6{\subsubsecentry2071,68382
- \def\unnumbsubsubsecentry ##1##2{\unnumbsubsubsecentry2072,68429
-\def\chapentry#1#2#3{\chapentry2085,68863
-\def\shortchapentry#1#2#3{\shortchapentry2088,68980
- {#2\labelspace #1}space2091,69090
-\def\unnumbchapentry#1#2{\unnumbchapentry2094,69144
-\def\shortunnumberedentry#1#2{\shortunnumberedentry2095,69191
-\def\secentry#1#2#3#4{\secentry2102,69355
-\def\unnumbsecentry#1#2{\unnumbsecentry2103,69414
-\def\subsecentry#1#2#3#4#5{\subsecentry2106,69475
-\def\unnumbsubsecentry#1#2{\unnumbsubsecentry2107,69545
-\def\subsubsecentry#1#2#3#4#5#6{\subsubsecentry2110,69619
- \dosubsubsecentry{#2.#3.#4.#5\labelspace#1}space2111,69653
-\def\unnumbsubsubsecentry#1#2{\unnumbsubsubsecentry2112,69704
-\def\dochapentry#1#2{\dochapentry2123,70078
-\def\dosecentry#1#2{\dosecentry2138,70683
-\def\dosubsecentry#1#2{\dosubsecentry2145,70861
-\def\dosubsubsecentry#1#2{\dosubsubsecentry2152,71046
-\def\labelspace{\labelspace2160,71297
-\def\dopageno#1{\dopageno2162,71332
-\def\doshortpageno#1{\doshortpageno2163,71358
-\def\chapentryfonts{\chapentryfonts2165,71390
-\def\secentryfonts{\secentryfonts2166,71425
-\def\point{\point2192,72384
-\def\result{\result2194,72405
-\def\expansion{\expansion2195,72478
-\def\print{\print2196,72549
-\def\equiv{\equiv2198,72616
-\def\error{\error2218,73389
-\def\tex{\tex2224,73618
-\def\@{\@2242,74001
-\gdef\sepspaces{\def {\ }}}\2265,74733
-\def\aboveenvbreak{\aboveenvbreak2268,74815
-\def\afterenvbreak{\afterenvbreak2272,74981
-\def\ctl{\ctl2286,75492
-\def\ctr{\ctr2287,75564
-\def\cbl{\cbl2288,75603
-\def\cbr{\cbr2289,75643
-\def\carttop{\carttop2290,75682
-\def\cartbot{\cartbot2293,75790
-\long\def\cartouche{\cartouche2299,75930
-\def\Ecartouche{\Ecartouche2326,76718
-\def\lisp{\lisp2338,76853
-\def\Elisp{\Elisp2348,77200
-\def\next##1{\next2360,77526
-\def\Eexample{\Eexample2364,77568
-\def\Esmallexample{\Esmallexample2367,77615
-\def\smalllispx{\smalllispx2373,77793
-\def\Esmalllisp{\Esmalllisp2383,78147
-\obeyspaces \obeylines \ninett \indexfonts \rawbackslashfonts2396,78503
-\def\next##1{\next2397,78560
-\def\display{\display2401,78640
-\def\Edisplay{\Edisplay2410,78959
-\def\next##1{\next2422,79270
-\def\format{\format2426,79373
-\def\Eformat{\Eformat2434,79669
-\def\next##1{\next2437,79758
-\def\flushleft{\flushleft2441,79810
-\def\Eflushleft{\Eflushleft2451,80181
-\def\next##1{\next2454,80274
-\def\flushright{\flushright2456,80296
-\def\Eflushright{\Eflushright2466,80668
-\def\next##1{\next2470,80799
-\def\quotation{\quotation2474,80857
-\def\Equotation{\Equotation2480,81049
-\def\setdeffont #1 {\setdeffont2493,81447
-\newskip\defbodyindent \defbodyindent=.4inbodyindent2495,81493
-\newskip\defargsindent \defargsindent=50ptargsindent2496,81536
-\newskip\deftypemargin \deftypemargin=12pttypemargin2497,81579
-\newskip\deflastargmargin \deflastargmargin=18ptlastargmargin2498,81622
-\def\activeparens{\activeparens2503,81820
-\def\opnr{\opnr2529,83032
-\def\lbrb{\lbrb2530,83097
-\def\defname #1#2{\defname2536,83298
-\advance\dimen2 by -\defbodyindentbodyindent2540,83416
-\advance\dimen3 by -\defbodyindentbodyindent2542,83470
-\setbox0=\hbox{\hskip \deflastargmargin{lastargmargin2544,83524
-\dimen1=\hsize \advance \dimen1 by -\defargsindent %size for continuationsargsindent2546,83666
-\parshape 2 0in \dimen0 \defargsindent \dimen1 %argsindent2547,83741
-\rlap{\rightline{{\rm #2}\hskip \deftypemargin}typemargin2554,84110
-\advance\leftskip by -\defbodyindentbodyindent2557,84244
-\exdentamount=\defbodyindentbodyindent2558,84281
-\def\defparsebody #1#2#3{\defparsebody2568,84640
-\def#1{2572,84824
-\def#2{2573,84860
-\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2575,84932
-\exdentamount=\defbodyindentbodyindent2576,85006
-\def\defmethparsebody #1#2#3#4 {\defmethparsebody2581,85110
-\def#1{2585,85271
-\def#2##1 {2586,85307
-\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2588,85390
-\exdentamount=\defbodyindentbodyindent2589,85464
-\def\defopparsebody #1#2#3#4#5 {\defopparsebody2592,85549
-\def#1{2596,85710
-\def#2##1 ##2 {2597,85746
-\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2600,85846
-\exdentamount=\defbodyindentbodyindent2601,85920
-\def\defvarparsebody #1#2#3{\defvarparsebody2608,86191
-\def#1{2612,86378
-\def#2{2613,86414
-\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2615,86473
-\exdentamount=\defbodyindentbodyindent2616,86547
-\def\defvrparsebody #1#2#3#4 {\defvrparsebody2621,86638
-\def#1{2625,86797
-\def#2##1 {2626,86833
-\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2628,86903
-\exdentamount=\defbodyindentbodyindent2629,86977
-\def\defopvarparsebody #1#2#3#4#5 {\defopvarparsebody2632,87049
-\def#1{2636,87213
-\def#2##1 ##2 {2637,87249
-\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2640,87336
-\exdentamount=\defbodyindentbodyindent2641,87410
-\def\defunargs #1{\defunargs2664,88170
-\def\deftypefunargs #1{\deftypefunargs2676,88552
-\def\deffn{\deffn2690,88934
-\def\deffnheader #1#2#3{\deffnheader2692,88991
-\begingroup\defname {name2693,89039
-\def\defun{\defun2699,89184
-\def\defunheader #1#2{\defunheader2701,89237
-\begingroup\defname {name2702,89312
-\defunargs {unargs2703,89348
-\def\deftypefun{\deftypefun2709,89496
-\def\deftypefunheader #1#2{\deftypefunheader2712,89618
-\def\deftypefunheaderx #1#2 #3\relax{\deftypefunheaderx2714,89727
-\begingroup\defname {name2716,89819
-\deftypefunargs {typefunargs2717,89865
-\def\deftypefn{\deftypefn2723,90036
-\def\deftypefnheader #1#2#3{\deftypefnheader2726,90185
-\def\deftypefnheaderx #1#2#3 #4\relax{\deftypefnheaderx2728,90321
-\begingroup\defname {name2730,90414
-\deftypefunargs {typefunargs2731,90454
-\def\defmac{\defmac2737,90575
-\def\defmacheader #1#2{\defmacheader2739,90632
-\begingroup\defname {name2740,90708
-\defunargs {unargs2741,90741
-\def\defspec{\defspec2747,90865
-\def\defspecheader #1#2{\defspecheader2749,90926
-\begingroup\defname {name2750,91003
-\defunargs {unargs2751,91043
-\def\deffnx #1 {\deffnx2758,91238
-\def\defunx #1 {\defunx2759,91295
-\def\defmacx #1 {\defmacx2760,91352
-\def\defspecx #1 {\defspecx2761,91411
-\def\deftypefnx #1 {\deftypefnx2762,91472
-\def\deftypeunx #1 {\deftypeunx2763,91537
-\def\defop #1 {\defop2769,91683
-\defopparsebody\Edefop\defopx\defopheader\defoptype}opparsebody\Edefop\defopx\defopheader\defoptype2770,91718
-\def\defopheader #1#2#3{\defopheader2772,91772
-\begingroup\defname {name2774,91861
-\defunargs {unargs2775,91907
-\def\defmethod{\defmethod2780,91968
-\def\defmethodheader #1#2#3{\defmethodheader2782,92041
-\begingroup\defname {name2784,92129
-\defunargs {unargs2785,92169
-\def\defcv #1 {\defcv2790,92243
-\defopvarparsebody\Edefcv\defcvx\defcvarheader\defcvtype}opvarparsebody\Edefcv\defcvx\defcvarheader\defcvtype2791,92278
-\def\defcvarheader #1#2#3{\defcvarheader2793,92337
-\begingroup\defname {name2795,92423
-\defvarargs {varargs2796,92469
-\def\defivar{\defivar2801,92542
-\def\defivarheader #1#2#3{\defivarheader2803,92605
-\begingroup\defname {name2805,92691
-\defvarargs {varargs2806,92742
-\def\defopx #1 {\defopx2812,92891
-\def\defmethodx #1 {\defmethodx2813,92948
-\def\defcvx #1 {\defcvx2814,93013
-\def\defivarx #1 {\defivarx2815,93070
-\def\defvarargs #1{\defvarargs2822,93341
-\def\defvr{\defvr2828,93485
-\def\defvrheader #1#2#3{\defvrheader2830,93540
-\begingroup\defname {name2831,93588
-\def\defvar{\defvar2835,93673
-\def\defvarheader #1#2{\defvarheader2837,93733
-\begingroup\defname {name2838,93804
-\defvarargs {varargs2839,93840
-\def\defopt{\defopt2844,93906
-\def\defoptheader #1#2{\defoptheader2846,93966
-\begingroup\defname {name2847,94037
-\defvarargs {varargs2848,94076
-\def\deftypevar{\deftypevar2853,94133
-\def\deftypevarheader #1#2{\deftypevarheader2856,94249
-\begingroup\defname {name2858,94332
-\def\deftypevr{\deftypevr2865,94506
-\def\deftypevrheader #1#2#3{\deftypevrheader2867,94577
-\begingroup\defname {name2868,94629
-\def\defvrx #1 {\defvrx2876,94866
-\def\defvarx #1 {\defvarx2877,94923
-\def\defoptx #1 {\defoptx2878,94982
-\def\deftypevarx #1 {\deftypevarx2879,95041
-\def\deftypevrx #1 {\deftypevrx2880,95108
-\def\deftpargs #1{\deftpargs2885,95257
-\def\deftp{\deftp2889,95337
-\def\deftpheader #1#2#3{\deftpheader2891,95392
-\begingroup\defname {name2892,95440
-\def\deftpx #1 {\deftpx2897,95599
-\def\setref#1{\setref2908,95920
-\def\unnumbsetref#1{\unnumbsetref2913,96034
-\def\appendixsetref#1{\appendixsetref2918,96141
-\def\pxref#1{\pxref2929,96552
-\def\xref#1{\xref2930,96588
-\def\ref#1{\ref2931,96623
-\def\xrefX[#1,#2,#3,#4,#5,#6]{\xrefX[2932,96653
-\def\printedmanual{\printedmanual2933,96696
-\def\printednodename{\printednodename2934,96734
-\def\printednodename{\printednodename2939,96859
-section ``\printednodename'' in \cite{\printedmanual}\printedmanual2954,97492
-\refx{x2957,97570
-\def\dosetq #1#2{\dosetq2965,97790
-\def\internalsetq #1#2{\internalsetq2973,98048
-\def\Ypagenumber{\Ypagenumber2977,98149
-\def\Ytitle{\Ytitle2979,98175
-\def\Ynothing{\Ynothing2981,98202
-\def\Ysectionnumberandtype{\Ysectionnumberandtype2983,98219
-\def\Yappendixletterandtype{\Yappendixletterandtype2992,98535
-\ifnum\secno=0 Appendix\xreftie'char\the\appendixno{no2993,98565
-\else \ifnum \subsecno=0 Section\xreftie'char\the\appendixno.\the\secno %no.\the\secno2994,98620
-Section\xreftie'char\the\appendixno.\the\secno.\the\subsecno %no.\the\secno.\the\subsecno2996,98724
-Section\xreftie'char\the\appendixno.\the\secno.\the\subsecno.\the\subsubsecno %no.\the\secno.\the\subsecno.\the\subsubsecno2998,98795
- \def\linenumber{\linenumber3009,99134
-\def\refx#1#2{\refx3015,99318
-\def\xrdef #1#2{\xrdef3037,99944
-\def\readauxfile{\readauxfile3040,100029
-\def\supereject{\supereject3110,101810
-\footstrut\parindent=\defaultparindent\hang\textindent{aultparindent\hang\textindent3131,102495
-\def\openindices{\openindices3139,102681
-\newdimen\defaultparindent \defaultparindent = 15ptaultparindent3151,102906
-\parindent = \defaultparindentaultparindent3152,102958
-\def\smallbook{\smallbook3175,103682
-\global\def\Esmallexample{\Esmallexample3192,104109
-\def\afourpaper{\afourpaper3196,104200
-\def\finalout{\finalout3224,105008
-\def\normaldoublequote{\normaldoublequote3235,105269
-\def\normaltilde{\normaltilde3236,105295
-\def\normalcaret{\normalcaret3237,105315
-\def\normalunderscore{\normalunderscore3238,105335
-\def\normalverticalbar{\normalverticalbar3239,105360
-\def\normalless{\normalless3240,105386
-\def\normalgreater{\normalgreater3241,105405
-\def\normalplus{\normalplus3242,105427
-\def\ifusingtt#1#2{\ifusingtt3253,105919
-\def\activedoublequote{\activedoublequote3261,106247
-\def~{~3264,106333
-\def^{^3267,106394
-\def_{_3270,106433
-\def\_{\_3272,106507
-\def\lvvmode{\lvvmode3279,106844
-\def|{|3282,106894
-\def<{<3285,106957
-\def>{>3288,107014
-\def+{+3290,107052
-\def\turnoffactive{\turnoffactive3296,107213
-\global\def={=3307,107499
-\def\normalbackslash{\normalbackslash3321,107881
+\def\texinfoversion{\texinfoversion26,1035
+\def\tie{\tie49,1526
+\def\gloggingall{\gloggingall72,2276
+\def\loggingall{\loggingall73,2345
+\def\onepageout#1{\onepageout99,3282
+\def\croppageout#1{\croppageout115,4032
+\def\cropmarks{\cropmarks142,5092
+\def\pagebody#1{\pagebody144,5139
+\def\ewtop{\ewtop157,5594
+\def\nstop{\nstop158,5658
+\def\ewbot{\ewbot160,5741
+\def\nsbot{\nsbot161,5805
+\def\parsearg #1{\parsearg170,6104
+\def\parseargx{\parseargx172,6182
+\def\parseargline{\parseargline182,6422
+\def\flushcr{\flushcr186,6543
+\newif\ifENV \ENVfalse \def\inENV{\inENV190,6742
+\def\ENVcheck{\ENVcheck191,6806
+\outer\def\begin{\begin198,7053
+\def\beginxxx #1{\beginxxx200,7091
+\def\end{\end208,7346
+\def\endxxx #1{\endxxx210,7374
+\def\errorE#1{\errorE216,7563
+\def\singlespace{\singlespace222,7757
+\def\@{\@232,7980
+\def\`{\`236,8080
+\def\'{\'237,8092
+\def\mylbrace {\mylbrace241,8140
+\def\myrbrace {\myrbrace242,8173
+\def\:{\:247,8287
+\def\*{\*250,8341
+\def\.{\.253,8417
+\def\w#1{\w258,8648
+\def\group{\group268,9131
+ \def\Egroup{\Egroup273,9295
+\def\need{\need289,9737
+\def\needx#1{\needx300,10014
+\def\dots{\dots339,11400
+\def\page{\page343,11464
+\def\exdent{\exdent353,11791
+\def\exdentyyy #1{\exdentyyy354,11824
+\def\nofillexdent{\nofillexdent357,11968
+\def\nofillexdentyyy #1{\nofillexdentyyy358,12013
+\def\include{\include365,12197
+\def\includezzz #1{\includezzz366,12232
+\def\thisfile{\thisfile369,12283
+\def\center{\center373,12346
+\def\centerzzz #1{\centerzzz374,12379
+\def\sp{\sp380,12521
+\def\spxxx #1{\spxxx381,12546
+\def\comment{\comment387,12720
+\def\commentxxx #1{\commentxxx390,12817
+\def\ignoresections{\ignoresections396,12986
+\let\chapter=\relax=\relax397,13008
+\let\section=\relax=\relax406,13253
+\let\subsection=\relax=\relax409,13314
+\let\subsubsection=\relax=\relax410,13337
+\let\appendix=\relax=\relax411,13363
+\let\appendixsec=\relaxsec=\relax412,13384
+\let\appendixsection=\relaxsection=\relax413,13408
+\let\appendixsubsec=\relaxsubsec=\relax414,13436
+\let\appendixsubsection=\relaxsubsection=\relax415,13463
+\let\appendixsubsubsec=\relaxsubsubsec=\relax416,13494
+\let\appendixsubsubsection=\relaxsubsubsection=\relax417,13524
+\def\ignore{\ignore423,13626
+\long\def\ignorexxx #1\end ignore{\ignorexxx427,13766
+\def\direntry{\direntry429,13825
+\long\def\direntryxxx #1\end direntry{\direntryxxx430,13864
+\def\ifset{\ifset434,13974
+\def\ifsetxxx #1{\ifsetxxx436,14032
+\def\Eifset{\Eifset440,14159
+\def\ifsetfail{\ifsetfail441,14173
+\long\def\ifsetfailxxx #1\end ifset{\ifsetfailxxx442,14229
+\def\ifclear{\ifclear444,14290
+\def\ifclearxxx #1{\ifclearxxx446,14352
+\def\Eifclear{\Eifclear450,14483
+\def\ifclearfail{\ifclearfail451,14499
+\long\def\ifclearfailxxx #1\end ifclear{\ifclearfailxxx452,14559
+\def\set{\set456,14710
+\def\setxxx #1{\setxxx457,14737
+\def\clear{\clear460,14799
+\def\clearxxx #1{\clearxxx461,14830
+\def\iftex{\iftex466,14947
+\def\Eiftex{\Eiftex467,14960
+\def\ifinfo{\ifinfo468,14974
+\long\def\ifinfoxxx #1\end ifinfo{\ifinfoxxx469,15024
+\long\def\menu #1\end menu{\menu471,15083
+\def\asis#1{\asis472,15112
+\def\math#1{\math485,15655
+\def\node{\node487,15699
+\def\nodezzz#1{\nodezzz488,15737
+\def\nodexxx[#1,#2]{\nodexxx[489,15768
+\def\donoderef{\donoderef492,15830
+\def\unnumbnoderef{\unnumbnoderef496,15951
+\def\appendixnoderef{\appendixnoderef500,16082
+\expandafter\expandafter\expandafter\appendixsetref{setref501,16128
+\let\refill=\relaxill=\relax504,16217
+\def\setfilename{\setfilename509,16431
+\outer\def\bye{\bye518,16677
+\def\inforef #1{\inforef520,16733
+\def\inforefzzz #1,#2,#3,#4**{\inforefzzz521,16771
+\def\losespace #1{\losespace523,16868
+\def\sf{\sf532,17072
+\font\defbf=cmbx10 scaled \magstep1 %was 1314bf=cmbx10558,17867
+\font\deftt=cmtt10 scaled \magstep1tt=cmtt10559,17913
+\def\df{\df560,17949
+\def\resetmathfonts{\resetmathfonts635,20543
+\def\textfonts{\textfonts648,21132
+\def\chapfonts{\chapfonts653,21347
+\def\secfonts{\secfonts658,21563
+\def\subsecfonts{\subsecfonts663,21768
+\def\indexfonts{\indexfonts668,21985
+\def\smartitalicx{\smartitalicx691,22717
+\def\smartitalic#1{\smartitalic692,22793
+\let\cite=\smartitalic=\smartitalic698,22938
+\def\b#1{\b700,22962
+\def\t#1{\t703,22997
+\def\samp #1{\samp706,23149
+\def\key #1{\key707,23182
+\def\ctrl #1{\ctrl708,23243
+\def\tclose#1{\tclose716,23445
+\def\ {\720,23611
+\def\xkey{\xkey728,23880
+\def\kbdfoo#1#2#3\par{\kbdfoo729,23896
+\def\dmn#1{\dmn738,24197
+\def\kbd#1{\kbd740,24224
+\def\l#1{\l742,24281
+\def\r#1{\r744,24310
+\def\sc#1{\sc746,24378
+\def\ii#1{\ii747,24421
+\def\titlefont#1{\titlefont755,24654
+\def\titlepage{\titlepage761,24757
+ \def\subtitlefont{\subtitlefont766,24984
+ \def\authorfont{\authorfont768,25068
+ \def\title{\title774,25278
+ \def\titlezzz##1{\titlezzz775,25313
+ \def\subtitle{\subtitle783,25628
+ \def\subtitlezzz##1{\subtitlezzz784,25669
+ \def\author{\author787,25787
+ \def\authorzzz##1{\authorzzz788,25824
+ \def\page{\page794,26115
+\def\Etitlepage{\Etitlepage804,26284
+\def\finishtitlepage{\finishtitlepage817,26672
+\def\evenheading{\evenheading846,27680
+\def\oddheading{\oddheading847,27723
+\def\everyheading{\everyheading848,27764
+\def\evenfooting{\evenfooting850,27810
+\def\oddfooting{\oddfooting851,27853
+\def\everyfooting{\everyfooting852,27894
+\def\headings #1 {\headings893,29586
+\def\HEADINGSoff{\HEADINGSoff895,29635
+\def\HEADINGSdouble{\HEADINGSdouble904,30062
+\def\HEADINGSsingle{\HEADINGSsingle914,30382
+\def\HEADINGSon{\HEADINGSon922,30603
+\def\HEADINGSafter{\HEADINGSafter924,30637
+\def\HEADINGSdoublex{\HEADINGSdoublex926,30732
+\def\HEADINGSsingleafter{\HEADINGSsingleafter933,30920
+\def\HEADINGSsinglex{\HEADINGSsinglex934,30981
+\def\today{\today943,31256
+\def\thistitle{\thistitle958,31801
+\def\settitle{\settitle959,31826
+\def\settitlezzz #1{\settitlezzz960,31863
+\def\internalBitem{\internalBitem992,32793
+\def\internalBitemx{\internalBitemx993,32843
+\def\internalBxitem "#1"{\internalBxitem995,32888
+\def\internalBxitemx "#1"{\internalBxitemx996,32968
+\def\internalBkitem{\internalBkitem998,33043
+\def\internalBkitemx{\internalBkitemx999,33095
+\def\kitemzzz #1{\kitemzzz1001,33142
+\def\xitemzzz #1{\xitemzzz1004,33244
+\def\itemzzz #1{\itemzzz1007,33347
+\def\item{\item1037,34418
+\def\itemx{\itemx1038,34469
+\def\kitem{\kitem1039,34522
+\def\kitemx{\kitemx1040,34575
+\def\xitem{\xitem1041,34630
+\def\xitemx{\xitemx1042,34683
+\def\description{\description1045,34793
+\def\table{\table1047,34843
+\def\ftable{\ftable1052,34987
+\def\Eftable{\Eftable1056,35133
+\def\vtable{\vtable1059,35202
+\def\Evtable{\Evtable1063,35348
+\def\dontindex #1{\dontindex1066,35417
+\def\fnitemindex #1{\fnitemindex1067,35437
+\def\vritemindex #1{\vritemindex1068,35482
+\def\tablez #1#2#3#4#5#6{\tablez1074,35631
+\def\Edescription{\Edescription1077,35689
+\def\itemfont{\itemfont1082,35890
+\def\Etable{\Etable1090,36116
+\def\itemize{\itemize1103,36440
+\def\itemizezzz #1{\itemizezzz1105,36476
+\def\itemizey #1#2{\itemizey1110,36571
+\def#2{1119,36817
+\def\itemcontents{\itemcontents1120,36858
+\def\bullet{\bullet1123,36906
+\def\minus{\minus1124,36933
+\def\frenchspacing{\frenchspacing1128,37041
+\def\splitoff#1#2\endmark{\splitoff1134,37266
+\def\enumerate{\enumerate1140,37496
+\def\enumeratezzz #1{\enumeratezzz1141,37535
+\def\enumeratey #1 #2\endenumeratey{\enumeratey1142,37588
+ \def\thearg{\thearg1146,37735
+ \ifx\thearg\empty \def\thearg{\thearg1147,37754
+\def\numericenumerate{\numericenumerate1184,39088
+\def\lowercaseenumerate{\lowercaseenumerate1190,39218
+\def\uppercaseenumerate{\uppercaseenumerate1203,39565
+\def\startenumeration#1{\startenumeration1219,40055
+\def\alphaenumerate{\alphaenumerate1227,40237
+\def\capsenumerate{\capsenumerate1228,40272
+\def\Ealphaenumerate{\Ealphaenumerate1229,40306
+\def\Ecapsenumerate{\Ecapsenumerate1230,40340
+\def\itemizeitem{\itemizeitem1234,40420
+\def\newindex #1{\newindex1259,41277
+\def\defindex{\defindex1268,41566
+\def\newcodeindex #1{\newcodeindex1272,41674
+\def\defcodeindex{\defcodeindex1279,41934
+\def\synindex #1 #2 {\synindex1283,42114
+\def\syncodeindex #1 #2 {\syncodeindex1292,42454
+\def\doindex#1{\doindex1309,43133
+\def\singleindexer #1{\singleindexer1310,43192
+\def\docodeindex#1{\docodeindex1313,43304
+\def\singlecodeindexer #1{\singlecodeindexer1314,43371
+\def\indexdummies{\indexdummies1316,43429
+\def\_{\_1317,43449
+\def\w{\w1318,43477
+\def\bf{\bf1319,43504
+\def\rm{\rm1320,43533
+\def\sl{\sl1321,43562
+\def\sf{\sf1322,43591
+\def\tt{\tt1323,43619
+\def\gtr{\gtr1324,43647
+\def\less{\less1325,43677
+\def\hat{\hat1326,43709
+\def\char{\char1327,43739
+\def\TeX{\TeX1328,43771
+\def\dots{\dots1329,43801
+\def\copyright{\copyright1330,43834
+\def\tclose##1{\tclose1331,43877
+\def\code##1{\code1332,43922
+\def\samp##1{\samp1333,43963
+\def\t##1{\t1334,44004
+\def\r##1{\r1335,44039
+\def\i##1{\i1336,44074
+\def\b##1{\b1337,44109
+\def\cite##1{\cite1338,44144
+\def\key##1{\key1339,44185
+\def\file##1{\file1340,44224
+\def\var##1{\var1341,44265
+\def\kbd##1{\kbd1342,44304
+\def\indexdummyfont#1{\indexdummyfont1347,44460
+\def\indexdummytex{\indexdummytex1348,44486
+\def\indexdummydots{\indexdummydots1349,44510
+\def\indexnofonts{\indexnofonts1351,44536
+\let\w=\indexdummyfontdummyfont1352,44556
+\let\t=\indexdummyfontdummyfont1353,44579
+\let\r=\indexdummyfontdummyfont1354,44602
+\let\i=\indexdummyfontdummyfont1355,44625
+\let\b=\indexdummyfontdummyfont1356,44648
+\let\emph=\indexdummyfontdummyfont1357,44671
+\let\strong=\indexdummyfontdummyfont1358,44697
+\let\cite=\indexdummyfont=\indexdummyfont1359,44725
+\let\sc=\indexdummyfontdummyfont1360,44751
+\let\tclose=\indexdummyfontdummyfont1364,44923
+\let\code=\indexdummyfontdummyfont1365,44951
+\let\file=\indexdummyfontdummyfont1366,44977
+\let\samp=\indexdummyfontdummyfont1367,45003
+\let\kbd=\indexdummyfontdummyfont1368,45029
+\let\key=\indexdummyfontdummyfont1369,45054
+\let\var=\indexdummyfontdummyfont1370,45079
+\let\TeX=\indexdummytexdummytex1371,45104
+\let\dots=\indexdummydotsdummydots1372,45128
+\let\indexbackslash=0 %overridden during \printindex.backslash=01382,45380
+\def\doind #1#2{\doind1384,45436
+{\indexdummies % Must do this here, since \bf, etc expand at this stagedummies1386,45479
+\def\rawbackslashxx{\rawbackslashxx1389,45619
+{\indexnofontsnofonts1394,45881
+\def\dosubind #1#2#3{\dosubind1405,46192
+{\indexdummies % Must do this here, since \bf, etc expand at this stagedummies1407,46240
+\def\rawbackslashxx{\rawbackslashxx1410,46344
+{\indexnofontsnofonts1414,46498
+\def\findex {\findex1443,47429
+\def\kindex {\kindex1444,47452
+\def\cindex {\cindex1445,47475
+\def\vindex {\vindex1446,47498
+\def\tindex {\tindex1447,47521
+\def\pindex {\pindex1448,47544
+\def\cindexsub {\cindexsub1450,47568
+\def\printindex{\printindex1462,47895
+\def\doprintindex#1{\doprintindex1464,47936
+ \def\indexbackslash{\indexbackslash1481,48421
+ \indexfonts\rm \tolerance=9500 \advance\baselineskip -1ptfonts\rm1482,48460
+\def\initial #1{\initial1517,49532
+\def\entry #1#2{\entry1523,49739
+ \null\nobreak\indexdotfill % Have leaders before the page number.dotfill1540,50386
+\def\indexdotfill{\indexdotfill1549,50714
+\def\primary #1{\primary1552,50820
+\def\secondary #1#2{\secondary1556,50902
+\noindent\hskip\secondaryindent\hbox{#1}\indexdotfill #2\pardotfill1559,50984
+\newbox\partialpageialpage1566,51157
+\def\begindoublecolumns{\begindoublecolumns1572,51315
+ \output={\global\setbox\partialpage=ialpage=1573,51351
+\def\enddoublecolumns{\enddoublecolumns1577,51539
+\def\doublecolumnout{\doublecolumnout1580,51624
+ \dimen@=\pageheight \advance\dimen@ by-\ht\partialpageialpage1581,51693
+\def\pagesofar{\pagesofar1584,51871
+\def\balancecolumns{\balancecolumns1588,52108
+ \availdimen@=\pageheight \advance\availdimen@ by-\ht\partialpageialpage1594,52279
+ \dimen@=\pageheight \advance\dimen@ by-\ht\partialpageialpage1600,52540
+\newcount \appendixno \appendixno = `\@no1627,53445
+\def\appendixletter{\appendixletter1628,53486
+\def\opencontents{\opencontents1632,53589
+\def\thischapter{\thischapter1637,53770
+\def\seccheck#1{\seccheck1638,53808
+\def\chapternofonts{\chapternofonts1643,53912
+\def\result{\result1646,53987
+\def\equiv{\equiv1647,54022
+\def\expansion{\expansion1648,54055
+\def\print{\print1649,54096
+\def\TeX{\TeX1650,54129
+\def\dots{\dots1651,54158
+\def\copyright{\copyright1652,54189
+\def\tt{\tt1653,54230
+\def\bf{\bf1654,54257
+\def\w{\w1655,54285
+\def\less{\less1656,54310
+\def\gtr{\gtr1657,54341
+\def\hat{\hat1658,54370
+\def\char{\char1659,54399
+\def\tclose##1{\tclose1660,54430
+\def\code##1{\code1661,54474
+\def\samp##1{\samp1662,54514
+\def\r##1{\r1663,54554
+\def\b##1{\b1664,54588
+\def\key##1{\key1665,54622
+\def\file##1{\file1666,54660
+\def\kbd##1{\kbd1667,54700
+\def\i##1{\i1669,54808
+\def\cite##1{\cite1670,54842
+\def\var##1{\var1671,54882
+\def\emph##1{\emph1672,54920
+\def\dfn##1{\dfn1673,54960
+\def\thischaptername{\thischaptername1676,55001
+\outer\def\chapter{\chapter1677,55040
+\def\chapterzzz #1{\chapterzzz1678,55081
+{\chapternofonts%nofonts%1687,55477
+\global\let\section = \numberedsec=1692,55630
+\global\let\subsection = \numberedsubsec=1693,55665
+\global\let\subsubsection = \numberedsubsubsec=1694,55706
+\outer\def\appendix{\appendix1697,55757
+\def\appendixzzz #1{\appendixzzz1698,55800
+\global\advance \appendixno by 1 \message{no1700,55877
+\chapmacro {#1}{Appendix \appendixletter}letter1701,55946
+\xdef\thischapter{Appendix \appendixletter: \noexpand\thischaptername}letter:1704,56039
+{\chapternofonts%nofonts%1705,56111
+ {#1}{Appendix \appendixletter}letter1707,56167
+\appendixnoderef %noderef1710,56267
+\global\let\section = \appendixsec=1711,56286
+\global\let\subsection = \appendixsubsec=1712,56321
+\global\let\subsubsection = \appendixsubsubsec=1713,56362
+\outer\def\top{\top1716,56413
+\outer\def\unnumbered{\unnumbered1717,56453
+\def\unnumberedzzz #1{\unnumberedzzz1718,56500
+{\chapternofonts%nofonts%1722,56663
+\global\let\section = \unnumberedsec=1727,56813
+\global\let\subsection = \unnumberedsubsec=1728,56850
+\global\let\subsubsection = \unnumberedsubsubsec=1729,56893
+\outer\def\numberedsec{\numberedsec1732,56946
+\def\seczzz #1{\seczzz1733,56987
+{\chapternofonts%nofonts%1736,57143
+\outer\def\appendixsection{\appendixsection1745,57329
+\outer\def\appendixsec{\appendixsec1746,57386
+\def\appendixsectionzzz #1{\appendixsectionzzz1747,57439
+\gdef\thissection{#1}\secheading {#1}{\appendixletter}letter1749,57551
+{\chapternofonts%nofonts%1750,57619
+{#1}{\appendixletter}letter1752,57675
+\appendixnoderef %noderef1755,57775
+\outer\def\unnumberedsec{\unnumberedsec1759,57815
+\def\unnumberedseczzz #1{\unnumberedseczzz1760,57868
+{\chapternofonts%nofonts%1762,57963
+\outer\def\numberedsubsec{\numberedsubsec1770,58131
+\def\numberedsubseczzz #1{\numberedsubseczzz1771,58186
+{\chapternofonts%nofonts%1774,58365
+\outer\def\appendixsubsec{\appendixsubsec1783,58569
+\def\appendixsubseczzz #1{\appendixsubseczzz1784,58624
+\subsecheading {#1}{\appendixletter}letter1786,58746
+{\chapternofonts%nofonts%1787,58811
+{#1}{\appendixletter}letter1789,58870
+\appendixnoderef %noderef1792,58985
+\outer\def\unnumberedsubsec{\unnumberedsubsec1796,59025
+\def\unnumberedsubseczzz #1{\unnumberedsubseczzz1797,59084
+{\chapternofonts%nofonts%1799,59185
+\outer\def\numberedsubsubsec{\numberedsubsubsec1807,59356
+\def\numberedsubsubseczzz #1{\numberedsubsubseczzz1808,59417
+{\chapternofonts%nofonts%1812,59614
+\outer\def\appendixsubsubsec{\appendixsubsubsec1823,59847
+\def\appendixsubsubseczzz #1{\appendixsubsubseczzz1824,59908
+ {\appendixletter}letter1827,60047
+{\chapternofonts%nofonts%1828,60113
+ {\appendixletter}letter1830,60178
+\appendixnoderef %noderef1834,60312
+\outer\def\unnumberedsubsubsec{\unnumberedsubsubsec1838,60352
+\def\unnumberedsubsubseczzz #1{\unnumberedsubsubseczzz1839,60417
+{\chapternofonts%nofonts%1841,60524
+\def\infotop{\infotop1851,60853
+\def\infounnumbered{\infounnumbered1852,60891
+\def\infounnumberedsec{\infounnumberedsec1853,60936
+\def\infounnumberedsubsec{\infounnumberedsubsec1854,60987
+\def\infounnumberedsubsubsec{\infounnumberedsubsubsec1855,61044
+\def\infoappendix{\infoappendix1857,61108
+\def\infoappendixsec{\infoappendixsec1858,61149
+\def\infoappendixsubsec{\infoappendixsubsec1859,61196
+\def\infoappendixsubsubsec{\infoappendixsubsubsec1860,61249
+\def\infochapter{\infochapter1862,61309
+\def\infosection{\infosection1863,61348
+\def\infosubsection{\infosubsection1864,61387
+\def\infosubsubsection{\infosubsubsection1865,61432
+\global\let\section = \numberedsec=1870,61669
+\global\let\subsection = \numberedsubsec=1871,61704
+\global\let\subsubsection = \numberedsubsubsec=1872,61745
+\def\majorheading{\majorheading1886,62252
+\def\majorheadingzzz #1{\majorheadingzzz1887,62297
+\def\chapheading{\chapheading1893,62530
+\def\chapheadingzzz #1{\chapheadingzzz1894,62573
+\def\heading{\heading1899,62768
+\def\subheading{\subheading1901,62805
+\def\subsubheading{\subsubheading1903,62848
+\def\dobreak#1#2{\dobreak1910,63125
+\def\setchapterstyle #1 {\setchapterstyle1912,63203
+\def\chapbreak{\chapbreak1919,63458
+\def\chappager{\chappager1920,63508
+\def\chapoddpage{\chapoddpage1921,63546
+\def\setchapternewpage #1 {\setchapternewpage1923,63625
+\def\CHAPPAGoff{\CHAPPAGoff1925,63682
+\def\CHAPPAGon{\CHAPPAGon1929,63776
+\global\def\HEADINGSon{\HEADINGSon1932,63867
+\def\CHAPPAGodd{\CHAPPAGodd1934,63909
+\global\def\HEADINGSon{\HEADINGSon1937,64005
+\def\CHAPFplain{\CHAPFplain1941,64059
+\def\chfplain #1#2{\chfplain1945,64151
+\def\unnchfplain #1{\unnchfplain1956,64374
+\def\unnchfopen #1{\unnchfopen1964,64603
+\def\chfopen #1#2{\chfopen1970,64811
+\def\CHAPFopen{\CHAPFopen1975,64955
+\def\subsecheadingbreak{\subsecheadingbreak1982,65173
+\def\secheadingbreak{\secheadingbreak1985,65302
+\def\secheading #1#2#3{\secheading1993,65584
+\def\plainsecheading #1{\plainsecheading1994,65640
+\def\secheadingi #1{\secheadingi1995,65683
+\def\subsecheading #1#2#3#4{\subsecheading2006,66051
+\def\subsecheadingi #1{\subsecheadingi2007,66118
+\def\subsubsecfonts{\subsubsecfonts2014,66415
+\def\subsubsecheading #1#2#3#4#5{\subsubsecheading2017,66538
+\def\subsubsecheadingi #1{\subsubsecheadingi2018,66616
+\def\startcontents#1{\startcontents2032,67088
+ \unnumbchapmacro{#1}\def\thischapter{\thischapter2040,67361
+\outer\def\contents{\contents2049,67720
+\outer\def\summarycontents{\summarycontents2057,67864
+ \def\secentry ##1##2##3##4{\secentry2067,68235
+ \def\unnumbsecentry ##1##2{\unnumbsecentry2068,68270
+ \def\subsecentry ##1##2##3##4##5{\subsecentry2069,68305
+ \def\unnumbsubsecentry ##1##2{\unnumbsubsecentry2070,68346
+ \def\subsubsecentry ##1##2##3##4##5##6{\subsubsecentry2071,68384
+ \def\unnumbsubsubsecentry ##1##2{\unnumbsubsubsecentry2072,68431
+\def\chapentry#1#2#3{\chapentry2085,68865
+\def\shortchapentry#1#2#3{\shortchapentry2088,68982
+ {#2\labelspace #1}space2091,69092
+\def\unnumbchapentry#1#2{\unnumbchapentry2094,69146
+\def\shortunnumberedentry#1#2{\shortunnumberedentry2095,69193
+\def\secentry#1#2#3#4{\secentry2102,69357
+\def\unnumbsecentry#1#2{\unnumbsecentry2103,69416
+\def\subsecentry#1#2#3#4#5{\subsecentry2106,69477
+\def\unnumbsubsecentry#1#2{\unnumbsubsecentry2107,69547
+\def\subsubsecentry#1#2#3#4#5#6{\subsubsecentry2110,69621
+ \dosubsubsecentry{#2.#3.#4.#5\labelspace#1}space2111,69655
+\def\unnumbsubsubsecentry#1#2{\unnumbsubsubsecentry2112,69706
+\def\dochapentry#1#2{\dochapentry2123,70080
+\def\dosecentry#1#2{\dosecentry2138,70685
+\def\dosubsecentry#1#2{\dosubsecentry2145,70863
+\def\dosubsubsecentry#1#2{\dosubsubsecentry2152,71048
+\def\labelspace{\labelspace2160,71299
+\def\dopageno#1{\dopageno2162,71334
+\def\doshortpageno#1{\doshortpageno2163,71360
+\def\chapentryfonts{\chapentryfonts2165,71392
+\def\secentryfonts{\secentryfonts2166,71427
+\def\point{\point2192,72386
+\def\result{\result2194,72407
+\def\expansion{\expansion2195,72480
+\def\print{\print2196,72551
+\def\equiv{\equiv2198,72618
+\def\error{\error2218,73391
+\def\tex{\tex2224,73620
+\def\@{\@2242,74003
+\gdef\sepspaces{\def {\ }}}\2265,74735
+\def\aboveenvbreak{\aboveenvbreak2268,74817
+\def\afterenvbreak{\afterenvbreak2272,74983
+\def\ctl{\ctl2286,75494
+\def\ctr{\ctr2287,75566
+\def\cbl{\cbl2288,75605
+\def\cbr{\cbr2289,75645
+\def\carttop{\carttop2290,75684
+\def\cartbot{\cartbot2293,75792
+\long\def\cartouche{\cartouche2299,75932
+\def\Ecartouche{\Ecartouche2326,76720
+\def\lisp{\lisp2338,76855
+\def\Elisp{\Elisp2348,77202
+\def\next##1{\next2360,77528
+\def\Eexample{\Eexample2364,77570
+\def\Esmallexample{\Esmallexample2367,77617
+\def\smalllispx{\smalllispx2373,77795
+\def\Esmalllisp{\Esmalllisp2383,78149
+\obeyspaces \obeylines \ninett \indexfonts \rawbackslashfonts2396,78505
+\def\next##1{\next2397,78562
+\def\display{\display2401,78642
+\def\Edisplay{\Edisplay2410,78961
+\def\next##1{\next2422,79272
+\def\format{\format2426,79375
+\def\Eformat{\Eformat2434,79671
+\def\next##1{\next2437,79760
+\def\flushleft{\flushleft2441,79812
+\def\Eflushleft{\Eflushleft2451,80183
+\def\next##1{\next2454,80276
+\def\flushright{\flushright2456,80298
+\def\Eflushright{\Eflushright2466,80670
+\def\next##1{\next2470,80801
+\def\quotation{\quotation2474,80859
+\def\Equotation{\Equotation2480,81051
+\def\setdeffont #1 {\setdeffont2493,81449
+\newskip\defbodyindent \defbodyindent=.4inbodyindent2495,81495
+\newskip\defargsindent \defargsindent=50ptargsindent2496,81538
+\newskip\deftypemargin \deftypemargin=12pttypemargin2497,81581
+\newskip\deflastargmargin \deflastargmargin=18ptlastargmargin2498,81624
+\def\activeparens{\activeparens2503,81822
+\def\opnr{\opnr2529,83034
+\def\lbrb{\lbrb2530,83099
+\def\defname #1#2{\defname2536,83300
+\advance\dimen2 by -\defbodyindentbodyindent2540,83418
+\advance\dimen3 by -\defbodyindentbodyindent2542,83472
+\setbox0=\hbox{\hskip \deflastargmargin{lastargmargin2544,83526
+\dimen1=\hsize \advance \dimen1 by -\defargsindent %size for continuationsargsindent2546,83668
+\parshape 2 0in \dimen0 \defargsindent \dimen1 %argsindent2547,83743
+\rlap{\rightline{{\rm #2}\hskip \deftypemargin}typemargin2554,84112
+\advance\leftskip by -\defbodyindentbodyindent2557,84246
+\exdentamount=\defbodyindentbodyindent2558,84283
+\def\defparsebody #1#2#3{\defparsebody2568,84642
+\def#1{2572,84826
+\def#2{2573,84862
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2575,84934
+\exdentamount=\defbodyindentbodyindent2576,85008
+\def\defmethparsebody #1#2#3#4 {\defmethparsebody2581,85112
+\def#1{2585,85273
+\def#2##1 {2586,85309
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2588,85392
+\exdentamount=\defbodyindentbodyindent2589,85466
+\def\defopparsebody #1#2#3#4#5 {\defopparsebody2592,85551
+\def#1{2596,85712
+\def#2##1 ##2 {2597,85748
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2600,85848
+\exdentamount=\defbodyindentbodyindent2601,85922
+\def\defvarparsebody #1#2#3{\defvarparsebody2608,86193
+\def#1{2612,86380
+\def#2{2613,86416
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2615,86475
+\exdentamount=\defbodyindentbodyindent2616,86549
+\def\defvrparsebody #1#2#3#4 {\defvrparsebody2621,86640
+\def#1{2625,86799
+\def#2##1 {2626,86835
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2628,86905
+\exdentamount=\defbodyindentbodyindent2629,86979
+\def\defopvarparsebody #1#2#3#4#5 {\defopvarparsebody2632,87051
+\def#1{2636,87215
+\def#2##1 ##2 {2637,87251
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindentbodyindent2640,87338
+\exdentamount=\defbodyindentbodyindent2641,87412
+\def\defunargs #1{\defunargs2664,88172
+\def\deftypefunargs #1{\deftypefunargs2676,88554
+\def\deffn{\deffn2690,88936
+\def\deffnheader #1#2#3{\deffnheader2692,88993
+\begingroup\defname {name2693,89041
+\def\defun{\defun2699,89186
+\def\defunheader #1#2{\defunheader2701,89239
+\begingroup\defname {name2702,89314
+\defunargs {unargs2703,89350
+\def\deftypefun{\deftypefun2709,89498
+\def\deftypefunheader #1#2{\deftypefunheader2712,89620
+\def\deftypefunheaderx #1#2 #3\relax{\deftypefunheaderx2714,89729
+\begingroup\defname {name2716,89821
+\deftypefunargs {typefunargs2717,89867
+\def\deftypefn{\deftypefn2723,90038
+\def\deftypefnheader #1#2#3{\deftypefnheader2726,90187
+\def\deftypefnheaderx #1#2#3 #4\relax{\deftypefnheaderx2728,90323
+\begingroup\defname {name2730,90416
+\deftypefunargs {typefunargs2731,90456
+\def\defmac{\defmac2737,90577
+\def\defmacheader #1#2{\defmacheader2739,90634
+\begingroup\defname {name2740,90710
+\defunargs {unargs2741,90743
+\def\defspec{\defspec2747,90867
+\def\defspecheader #1#2{\defspecheader2749,90928
+\begingroup\defname {name2750,91005
+\defunargs {unargs2751,91045
+\def\deffnx #1 {\deffnx2758,91240
+\def\defunx #1 {\defunx2759,91297
+\def\defmacx #1 {\defmacx2760,91354
+\def\defspecx #1 {\defspecx2761,91413
+\def\deftypefnx #1 {\deftypefnx2762,91474
+\def\deftypeunx #1 {\deftypeunx2763,91539
+\def\defop #1 {\defop2769,91685
+\defopparsebody\Edefop\defopx\defopheader\defoptype}opparsebody\Edefop\defopx\defopheader\defoptype2770,91720
+\def\defopheader #1#2#3{\defopheader2772,91774
+\begingroup\defname {name2774,91863
+\defunargs {unargs2775,91909
+\def\defmethod{\defmethod2780,91970
+\def\defmethodheader #1#2#3{\defmethodheader2782,92043
+\begingroup\defname {name2784,92131
+\defunargs {unargs2785,92171
+\def\defcv #1 {\defcv2790,92245
+\defopvarparsebody\Edefcv\defcvx\defcvarheader\defcvtype}opvarparsebody\Edefcv\defcvx\defcvarheader\defcvtype2791,92280
+\def\defcvarheader #1#2#3{\defcvarheader2793,92339
+\begingroup\defname {name2795,92425
+\defvarargs {varargs2796,92471
+\def\defivar{\defivar2801,92544
+\def\defivarheader #1#2#3{\defivarheader2803,92607
+\begingroup\defname {name2805,92693
+\defvarargs {varargs2806,92744
+\def\defopx #1 {\defopx2812,92893
+\def\defmethodx #1 {\defmethodx2813,92950
+\def\defcvx #1 {\defcvx2814,93015
+\def\defivarx #1 {\defivarx2815,93072
+\def\defvarargs #1{\defvarargs2822,93343
+\def\defvr{\defvr2828,93487
+\def\defvrheader #1#2#3{\defvrheader2830,93542
+\begingroup\defname {name2831,93590
+\def\defvar{\defvar2835,93675
+\def\defvarheader #1#2{\defvarheader2837,93735
+\begingroup\defname {name2838,93806
+\defvarargs {varargs2839,93842
+\def\defopt{\defopt2844,93908
+\def\defoptheader #1#2{\defoptheader2846,93968
+\begingroup\defname {name2847,94039
+\defvarargs {varargs2848,94078
+\def\deftypevar{\deftypevar2853,94135
+\def\deftypevarheader #1#2{\deftypevarheader2856,94251
+\begingroup\defname {name2858,94334
+\def\deftypevr{\deftypevr2865,94508
+\def\deftypevrheader #1#2#3{\deftypevrheader2867,94579
+\begingroup\defname {name2868,94631
+\def\defvrx #1 {\defvrx2876,94868
+\def\defvarx #1 {\defvarx2877,94925
+\def\defoptx #1 {\defoptx2878,94984
+\def\deftypevarx #1 {\deftypevarx2879,95043
+\def\deftypevrx #1 {\deftypevrx2880,95110
+\def\deftpargs #1{\deftpargs2885,95259
+\def\deftp{\deftp2889,95339
+\def\deftpheader #1#2#3{\deftpheader2891,95394
+\begingroup\defname {name2892,95442
+\def\deftpx #1 {\deftpx2897,95601
+\def\setref#1{\setref2908,95922
+\def\unnumbsetref#1{\unnumbsetref2913,96036
+\def\appendixsetref#1{\appendixsetref2918,96143
+\def\pxref#1{\pxref2929,96554
+\def\xref#1{\xref2930,96590
+\def\ref#1{\ref2931,96625
+\def\xrefX[#1,#2,#3,#4,#5,#6]{\xrefX[2932,96655
+\def\printedmanual{\printedmanual2933,96698
+\def\printednodename{\printednodename2934,96736
+\def\printednodename{\printednodename2939,96861
+section ``\printednodename'' in \cite{\printedmanual}\printedmanual2954,97493
+\refx{x2957,97571
+\def\dosetq #1#2{\dosetq2965,97791
+\def\internalsetq #1#2{\internalsetq2973,98049
+\def\Ypagenumber{\Ypagenumber2977,98150
+\def\Ytitle{\Ytitle2979,98176
+\def\Ynothing{\Ynothing2981,98203
+\def\Ysectionnumberandtype{\Ysectionnumberandtype2983,98220
+\def\Yappendixletterandtype{\Yappendixletterandtype2992,98536
+\ifnum\secno=0 Appendix\xreftie'char\the\appendixno{no2993,98566
+\else \ifnum \subsecno=0 Section\xreftie'char\the\appendixno.\the\secno %no.\the\secno2994,98621
+Section\xreftie'char\the\appendixno.\the\secno.\the\subsecno %no.\the\secno.\the\subsecno2996,98725
+Section\xreftie'char\the\appendixno.\the\secno.\the\subsecno.\the\subsubsecno %no.\the\secno.\the\subsecno.\the\subsubsecno2998,98796
+ \def\linenumber{\linenumber3009,99135
+\def\refx#1#2{\refx3015,99319
+\def\xrdef #1#2{\xrdef3037,99945
+\def\readauxfile{\readauxfile3040,100030
+\def\supereject{\supereject3110,101811
+\footstrut\parindent=\defaultparindent\hang\textindent{aultparindent\hang\textindent3131,102496
+\def\openindices{\openindices3139,102682
+\newdimen\defaultparindent \defaultparindent = 15ptaultparindent3151,102907
+\parindent = \defaultparindentaultparindent3152,102959
+\def\smallbook{\smallbook3175,103683
+\global\def\Esmallexample{\Esmallexample3192,104110
+\def\afourpaper{\afourpaper3196,104201
+\def\finalout{\finalout3224,105009
+\def\normaldoublequote{\normaldoublequote3235,105270
+\def\normaltilde{\normaltilde3236,105296
+\def\normalcaret{\normalcaret3237,105316
+\def\normalunderscore{\normalunderscore3238,105336
+\def\normalverticalbar{\normalverticalbar3239,105361
+\def\normalless{\normalless3240,105387
+\def\normalgreater{\normalgreater3241,105406
+\def\normalplus{\normalplus3242,105428
+\def\ifusingtt#1#2{\ifusingtt3253,105920
+\def\activedoublequote{\activedoublequote3261,106248
+\def~{~3264,106334
+\def^{^3267,106395
+\def_{_3270,106434
+\def\_{\_3272,106508
+\def\lvvmode{\lvvmode3279,106845
+\def|{|3282,106895
+\def<{<3285,106958
+\def>{>3288,107015
+\def+{+3290,107053
+\def\turnoffactive{\turnoffactive3296,107214
+\global\def={=3307,107500
+\def\normalbackslash{\normalbackslash3321,107882
+
+merc-src/accumulator.m,4915
+:- interface146,5371
+:- import_module hlds148,5386
+:- import_module univ152,5478
+:- pred accu_transform_proc159,5793
+:- implementation166,6115
+:- import_module libs180,6552
+:- import_module mdbcomp184,6681
+:- import_module parse_tree186,6742
+:- import_module assoc_list194,7013
+:- import_module bool195,7042
+:- import_module int196,7065
+:- import_module io197,7087
+:- import_module list198,7108
+:- import_module map199,7131
+:- import_module maybe200,7153
+:- import_module pair201,7177
+:- import_module require202,7200
+:- import_module set203,7226
+:- import_module solutions204,7248
+:- import_module string205,7276
+:- import_module term206,7301
+:- import_module varset207,7324
+:- type top_level213,7499
+:- type accu_goal_id225,7900
+:- type accu_case228,7964
+:- type accu_goal_store234,8091
+:- type accu_subst238,8216
+:- type accu_warning240,8264
+accu_transform_proc247,8578
+:- pred generate_warnings334,12550
+generate_warnings337,12669
+:- pred generate_warning342,12895
+generate_warning345,13001
+:- pred should_attempt_accu_transform365,13886
+should_attempt_accu_transform370,14123
+:- pred should_attempt_accu_transform_2398,15406
+should_attempt_accu_transform_2405,15763
+:- pred accu_standardize440,17390
+accu_standardize442,17455
+:- pred identify_goal_type465,18169
+identify_goal_type469,18359
+:- pred is_recursive_case549,21175
+is_recursive_case551,21253
+:- type store_info560,21713
+:- func initialize_goal_store570,22060
+initialize_goal_store573,22166
+:- pred accu_store580,22421
+accu_store584,22576
+:- pred identify_recursive_calls601,23288
+identify_recursive_calls604,23406
+:- pred identify_out_and_out_prime626,24397
+identify_out_and_out_prime631,24632
+:- type accu_sets676,26426
+:- pred accu_stage1689,26978
+accu_stage1693,27156
+:- pred accu_stage1_2727,28348
+accu_stage1_2731,28516
+:- pred accu_sets_init781,30558
+accu_sets_init783,30606
+:- func set_upto796,30985
+set_upto798,31040
+:- pred accu_before812,31499
+accu_before815,31640
+:- pred accu_assoc835,32478
+accu_assoc838,32618
+:- pred accu_construct862,33713
+accu_construct865,33857
+:- pred accu_construct_assoc896,35308
+accu_construct_assoc899,35458
+:- pred accu_update938,37070
+accu_update941,37211
+:- pred member_lessthan_goalid964,38220
+member_lessthan_goalid967,38343
+:- type accu_assoc975,38653
+:- pred accu_is_associative986,39139
+accu_is_associative989,39251
+:- pred associativity_assertion1014,40264
+associativity_assertion1017,40405
+:- pred commutativity_assertion1037,41243
+commutativity_assertion1040,41370
+:- pred accu_is_update1057,41953
+accu_is_update1060,42067
+:- pred is_associative_construction1078,42803
+is_associative_construction1081,42899
+:- type accu_substs1095,43481
+:- type accu_base1103,43745
+:- pred accu_stage21124,44606
+accu_stage21131,44947
+:- pred accu_substs_init1179,46958
+accu_substs_init1182,47098
+:- pred acc_var_subst_init1194,47574
+acc_var_subst_init1198,47719
+:- pred create_new_var1207,48148
+create_new_var1210,48289
+:- pred accu_process_assoc_set1223,48863
+accu_process_assoc_set1229,49151
+:- pred accu_has_heuristic1297,52082
+accu_has_heuristic1299,52162
+:- pred accu_heuristic1304,52337
+accu_heuristic1307,52458
+:- pred accu_process_update_set1318,52907
+accu_process_update_set1325,53222
+:- pred accu_divide_base_case1380,55845
+accu_divide_base_case1385,56060
+:- pred accu_related1412,57147
+accu_related1415,57271
+:- inst stored_goal_plain_call1444,58416
+:- pred lookup_call1449,58602
+lookup_call1452,58716
+:- pred accu_stage31470,59433
+accu_stage31477,59827
+:- pred acc_proc_info1508,61327
+acc_proc_info1512,61486
+:- pred acc_pred_info1556,63450
+acc_pred_info1559,63598
+:- pred accu_create_goal1600,65286
+accu_create_goal1607,65629
+:- func create_acc_call1621,66401
+create_acc_call1625,66570
+:- pred create_orig_goal1634,66988
+create_orig_goal1638,67177
+:- pred create_acc_goal1662,68158
+create_acc_goal1667,68381
+:- func create_new_orig_recursive_goals1709,70226
+create_new_orig_recursive_goals1712,70369
+:- func create_new_recursive_goals1723,70919
+create_new_recursive_goals1727,71109
+:- func create_new_base_goals1738,71718
+create_new_base_goals1741,71832
+:- pred acc_unification1749,72157
+acc_unification1751,72226
+:- pred accu_top_level1766,72897
+accu_top_level1770,73059
+:- pred update_accumulator_pred1856,76291
+update_accumulator_pred1859,76412
+:- func accu_rename1876,77254
+accu_rename1879,77364
+:- func base_case_ids1889,77785
+base_case_ids1891,77847
+:- func base_case_ids_set1898,78049
+base_case_ids_set1900,78114
+:- func accu_goal_list1905,78270
+accu_goal_list1907,78350
+:- pred calculate_goal_info1916,78681
+calculate_goal_info1918,78754
+:- func chain_subst1932,79320
+chain_subst1934,79379
+:- pred chain_subst_21938,79483
+chain_subst_21941,79577
+:- some [T] pred unravel_univ1956,80061
+:- pragma foreign_export1957,80117
+unravel_univ1961,80341
c-src/c.c,76
T f(1,0
@@ -5160,13 +5315,13 @@ extern struct node *yylval;yylval306,6246
unsigned char parse_cell_or_range 309,6291
unsigned char parse_cell_or_range 311,6355
yylex FUN0(315,6405
-parse_cell_or_range FUN2(587,11771
-#define CK_ABS_R(671,13213
-#define CK_REL_R(675,13292
-#define CK_ABS_C(680,13421
-#define CK_REL_C(684,13500
-#define MAYBEREL(689,13629
-str_to_col FUN1(847,16830
+parse_cell_or_range FUN2(587,11772
+#define CK_ABS_R(671,13214
+#define CK_REL_R(675,13293
+#define CK_ABS_C(680,13422
+#define CK_REL_C(684,13501
+#define MAYBEREL(689,13630
+str_to_col FUN1(847,16831
y-src/parse.c,520
#define YYBISON 4,64
diff --git a/test/manual/etags/Makefile b/test/manual/etags/Makefile
index c1df703905e..b3a82fdba8d 100644
--- a/test/manual/etags/Makefile
+++ b/test/manual/etags/Makefile
@@ -16,6 +16,7 @@ HTMLSRC=$(addprefix ./html-src/,softwarelibero.html index.shtml algrthms.html so
#JAVASRC=$(addprefix ./java-src/, )
LUASRC=$(addprefix ./lua-src/,allegro.lua test.lua)
MAKESRC=$(addprefix ./make-src/,Makefile)
+MERCSRC=$(addprefix ./merc-src/,accumulator.m)
OBJCSRC=$(addprefix ./objc-src/,Subprocess.h Subprocess.m PackInsp.h PackInsp.m)
OBJCPPSRC=$(addprefix ./objcpp-src/,SimpleCalc.H SimpleCalc.M)
PASSRC=$(addprefix ./pas-src/,common.pas)
@@ -25,13 +26,14 @@ PSSRC=$(addprefix ./ps-src/,rfc1245.ps)
PROLSRC=$(addprefix ./prol-src/,ordsets.prolog natded.prolog)
PYTSRC=$(addprefix ./pyt-src/,server.py)
RBSRC=$(addprefix ./ruby-src/,test.rb test1.ru)
+RSSRC=$(addprefix ./rs-src/,test.rs)
SCMSRC=$(addprefix ./scm-src/,test.scm)
TEXSRC=$(addprefix ./tex-src/,testenv.tex gzip.texi texinfo.tex nonewline.tex)
YSRC=$(addprefix ./y-src/,parse.y parse.c atest.y cccp.c cccp.y)
SRCS=${ADASRC} ${ASRC} ${CSRC} ${CPSRC} ${ELSRC} ${ERLSRC} ${FSRC}\
${FORTHSRC} ${GOSRC} ${HTMLSRC} ${JAVASRC} ${LUASRC} ${MAKESRC}\
${OBJCSRC} ${OBJCPPSRC} ${PASSRC} ${PHPSRC} ${PERLSRC} ${PSSRC}\
- ${PROLSRC} ${PYTSRC} ${RBSRC} ${SCMSRC} ${TEXSRC} ${YSRC}
+ ${PROLSRC} ${PYTSRC} ${RBSRC} ${RSSRC} ${SCMSRC} ${TEXSRC} ${YSRC} ${MERCSRC}
NONSRCS=./f-src/entry.strange ./erl-src/lists.erl ./cp-src/clheir.hpp.gz
ETAGS_PROG=../../../lib-src/etags
diff --git a/test/manual/etags/README b/test/manual/etags/README
new file mode 100644
index 00000000000..7bce861030b
--- /dev/null
+++ b/test/manual/etags/README
@@ -0,0 +1,60 @@
+This directory contains the test suite for the 'etags' and 'ctags'
+programs.
+
+The input files, which include source files in various languages
+supported by the programs, are in the *-src/ directories (e.g., c-src
+for C sources, ada-src for Ada, tex-src for TeX, etc.).
+
+The expected results are slightly different for each of the 7 commands
+(see below) run by the test suite, and are on files ETAGS.good_N
+(where N is between 1 and 6) and CTAGS.good.
+
+To run the tests, say
+
+ make check
+
+in this directory. This should run the programs 7 times with various
+command line switches, and should not show any differences between the
+produced file ETAGS/CTAGS and the corresponding expected results. Any
+diffs shown by the 'diff' utility should be examined for potential
+regressions in 'etags' or 'ctags'.
+
+In some cases, diffs should be expected. These include:
+
+ . adding new input files in the *-src/ directories
+ . routine changes in the existing input files, such as the yearly
+ update of copyright years, spelling changes, etc.
+ . adding new features to etags.c
+
+When the diffs are expected, they should be examined to make sure
+there are no regressions. To do so, compare the line numbers and byte
+offsets shown in the new ETAGS/CTAGS files against the up-to-date
+input files, and make sure the new values match, whereas the old one
+don't. Also make sure there no new or missing entries in the
+ETAGS/CTAGS files as compared with the expected results. (When new
+input files are added, there obviously will be new entries -- these
+should be compared to the input files to verify correctness.)
+
+Once the differences are deemed to be justified, i.e. you decide that
+the new ETAGS/CTAGS file should become the new expected result, you
+should copy the ETAGS/CTAGS files produced by the test run to the
+corresponding "good" files, one by one. Like this:
+
+ $ make check
+ $ cp ETAGS ETAGS.good_1
+ $ make check
+ $ cp ETAGS ETAGS.good_2
+ $ make check
+ $ cp ETAGS ETAGS.good_3
+ ...
+ $ make check
+ $ cp ETAGS ETAGS.good_6
+ $ make check
+ $ cp CTAGS CTAGS.good
+
+This uses the fact that "make check" will stop after the first
+failure, i.e. after the first time 'diff' reports any diffs, and then
+the ETAGS/CTAGS file from the last invocation is available for
+becoming the new expected-result file. Alternatively, you can see the
+name of the expected-result file which needs to be updated in the
+output of the 'diff' utility.
diff --git a/test/manual/etags/c-src/abbrev.c b/test/manual/etags/c-src/abbrev.c
index c01eee419ff..301ca4e9d81 100644
--- a/test/manual/etags/c-src/abbrev.c
+++ b/test/manual/etags/c-src/abbrev.c
@@ -1,5 +1,5 @@
/* Primitives for word-abbrev mode.
- Copyright (C) 1985-1986, 1993, 1996, 1998, 2016-2017 Free Software
+ Copyright (C) 1985-1986, 1993, 1996, 1998, 2016-2022 Free Software
Foundation, Inc.
This file is part of GNU Emacs.
@@ -78,9 +78,6 @@ Lisp_Object Vlast_abbrev_text;
int last_abbrev_point;
-/* Hook to run before expanding any abbrev. */
-
-Lisp_Object Vpre_abbrev_expand_hook, Qpre_abbrev_expand_hook;
DEFUN ("make-abbrev-table", Fmake_abbrev_table, Smake_abbrev_table, 0, 0, 0,
"Create a new, empty abbrev table object.")
@@ -232,9 +229,6 @@ Returns the abbrev symbol, if expansion took place.")
value = Qnil;
- if (!NILP (Vrun_hooks))
- call1 (Vrun_hooks, Qpre_abbrev_expand_hook);
-
wordstart = 0;
if (!(BUFFERP (Vabbrev_start_location_buffer)
&& XBUFFER (Vabbrev_start_location_buffer) == current_buffer))
@@ -595,14 +589,6 @@ This causes `save-some-buffers' to offer to save the abbrevs.");
"*Set non-nil means expand multi-word abbrevs all caps if abbrev was so.");
abbrev_all_caps = 0;
- DEFVAR_LISP ("pre-abbrev-expand-hook", &Vpre_abbrev_expand_hook,
- "Function or functions to be called before abbrev expansion is done.\n\
-This is the first thing that `expand-abbrev' does, and so this may change\n\
-the current abbrev table before abbrev lookup happens.");
- Vpre_abbrev_expand_hook = Qnil;
- Qpre_abbrev_expand_hook = intern ("pre-abbrev-expand-hook");
- staticpro (&Qpre_abbrev_expand_hook);
-
defsubr (&Smake_abbrev_table);
defsubr (&Sclear_abbrev_table);
defsubr (&Sdefine_abbrev);
diff --git a/test/manual/etags/c-src/emacs/src/gmalloc.c b/test/manual/etags/c-src/emacs/src/gmalloc.c
index 3f8cad83ae5..0a28d0c6d37 100644
--- a/test/manual/etags/c-src/emacs/src/gmalloc.c
+++ b/test/manual/etags/c-src/emacs/src/gmalloc.c
@@ -1,5 +1,5 @@
/* Declarations for `malloc' and friends.
- Copyright (C) 1990-1993, 1995-1996, 1999, 2002-2007, 2013-2017 Free
+ Copyright (C) 1990-1993, 1995-1996, 1999, 2002-2007, 2013-2022 Free
Software Foundation, Inc.
Written May 1989 by Mike Haertel.
diff --git a/test/manual/etags/c-src/emacs/src/keyboard.c b/test/manual/etags/c-src/emacs/src/keyboard.c
index 960e5c71322..506bf0d01c4 100644
--- a/test/manual/etags/c-src/emacs/src/keyboard.c
+++ b/test/manual/etags/c-src/emacs/src/keyboard.c
@@ -1,6 +1,6 @@
/* Keyboard and mouse input; editor command loop.
-Copyright (C) 1985-1989, 1993-1997, 1999-2017 Free Software Foundation,
+Copyright (C) 1985-1989, 1993-1997, 1999-2022 Free Software Foundation,
Inc.
This file is part of GNU Emacs.
@@ -759,7 +759,7 @@ force_auto_save_soon (void)
DEFUN ("recursive-edit", Frecursive_edit, Srecursive_edit, 0, 0, "",
doc: /* Invoke the editor command loop recursively.
To get out of the recursive edit, a command can throw to `exit' -- for
-instance `(throw 'exit nil)'.
+instance `(throw \\='exit nil)'.
If you throw a value other than t, `recursive-edit' returns normally
to the function that called it. Throwing a t value causes
`recursive-edit' to quit, so that control returns to the command loop
@@ -5754,7 +5754,7 @@ make_lispy_event (struct input_event *event)
ignore_mouse_drag_p = 0;
}
- /* Now we're releasing a button - check the co-ordinates to
+ /* Now we're releasing a button - check the coordinates to
see if this was a click or a drag. */
else if (event->modifiers & up_modifier)
{
diff --git a/test/manual/etags/c-src/emacs/src/lisp.h b/test/manual/etags/c-src/emacs/src/lisp.h
index 0c7da366519..1fe50f5f93f 100644
--- a/test/manual/etags/c-src/emacs/src/lisp.h
+++ b/test/manual/etags/c-src/emacs/src/lisp.h
@@ -1,6 +1,6 @@
/* Fundamental definitions for GNU Emacs Lisp interpreter.
-Copyright (C) 1985-1987, 1993-1995, 1997-2017 Free Software Foundation,
+Copyright (C) 1985-1987, 1993-1995, 1997-2022 Free Software Foundation,
Inc.
This file is part of GNU Emacs.
@@ -510,7 +510,7 @@ enum Lisp_Fwd_Type
/* If you want to define a new Lisp data type, here are some
instructions. See the thread at
- https://lists.gnu.org/archive/html/emacs-devel/2012-10/msg00561.html
+ https://lists.gnu.org/r/emacs-devel/2012-10/msg00561.html
for more info.
First, there are already a couple of Lisp types that can be used if
diff --git a/test/manual/etags/c-src/emacs/src/regex.h b/test/manual/etags/c-src/emacs/src/regex.h
index 595b9bb0923..f51e4fc594b 100644
--- a/test/manual/etags/c-src/emacs/src/regex.h
+++ b/test/manual/etags/c-src/emacs/src/regex.h
@@ -1,7 +1,7 @@
/* Definitions for data structures and routines for the regular
expression library, version 0.12.
- Copyright (C) 1985, 1989-1993, 1995, 2000-2017 Free Software
+ Copyright (C) 1985, 1989-1993, 1995, 2000-2022 Free Software
Foundation, Inc.
This program is free software; you can redistribute it and/or modify
diff --git a/test/manual/etags/c-src/etags.c b/test/manual/etags/c-src/etags.c
index b412ef5e64f..efa269d81cf 100644
--- a/test/manual/etags/c-src/etags.c
+++ b/test/manual/etags/c-src/etags.c
@@ -28,7 +28,7 @@ OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-Copyright (C) 1984, 1987-1989, 1993-1995, 1998-2017 Free Software
+Copyright (C) 1984, 1987-1989, 1993-1995, 1998-2022 Free Software
Foundation, Inc.
This file is not considered part of GNU Emacs.
diff --git a/test/manual/etags/c-src/exit.c b/test/manual/etags/c-src/exit.c
index b1952bfddb9..c655b257c9b 100644
--- a/test/manual/etags/c-src/exit.c
+++ b/test/manual/etags/c-src/exit.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 2016-2017 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 2016-2022 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/test/manual/etags/c-src/exit.strange_suffix b/test/manual/etags/c-src/exit.strange_suffix
index b1952bfddb9..c655b257c9b 100644
--- a/test/manual/etags/c-src/exit.strange_suffix
+++ b/test/manual/etags/c-src/exit.strange_suffix
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 2016-2017 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 2016-2022 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/test/manual/etags/c-src/getopt.h b/test/manual/etags/c-src/getopt.h
index aa66fac4ecd..31e2a03c12d 100644
--- a/test/manual/etags/c-src/getopt.h
+++ b/test/manual/etags/c-src/getopt.h
@@ -1,5 +1,5 @@
/* Declarations for getopt.
- Copyright (C) 1989-1992, 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 1989-1992, 2016-2022 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
diff --git a/test/manual/etags/c-src/sysdep.h b/test/manual/etags/c-src/sysdep.h
index 2c121cf53a9..38edc43df3b 100644
--- a/test/manual/etags/c-src/sysdep.h
+++ b/test/manual/etags/c-src/sysdep.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1992-1993, 2016-2017 Free Software Foundation, Inc.
+/* Copyright (C) 1992-1993, 2016-2022 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/test/manual/etags/cp-src/clheir.hpp b/test/manual/etags/cp-src/clheir.hpp
index 55d91228fb3..831da5ca095 100644
--- a/test/manual/etags/cp-src/clheir.hpp
+++ b/test/manual/etags/cp-src/clheir.hpp
@@ -2,7 +2,7 @@
/* CLHEIR.H */
/* ======================================================================= */
-// CLASS HEIRARCHY
+// CLASS HIERARCHY
// Locations or Agents are both of type generic_object. Generic_objects may
// have states, and are responsible for updating their states appropriately
// when their step() functions are executed.
diff --git a/test/manual/etags/cp-src/functions.cpp b/test/manual/etags/cp-src/functions.cpp
index 764498d4084..ddd78f14d9b 100644
--- a/test/manual/etags/cp-src/functions.cpp
+++ b/test/manual/etags/cp-src/functions.cpp
@@ -28,7 +28,7 @@ void Date::setDate ( int d , int m , int y ){
t = mktime ( date ) ;
}
-// Addition operation ::: Warning ::: A combination of addition and substraction does not give a proper result
+// Addition operation ::: Warning ::: A combination of addition and subtraction does not give a proper result
void Date::plus ( int days , int month , int year ){
if ( ! set () )
return;
@@ -38,7 +38,7 @@ void Date::plus ( int days , int month , int year ){
mktime ( date );
}
-//Substraction operation ::: Warning ::: A combination of addition and substraction does not give a proper result
+//Subtraction operation ::: Warning ::: A combination of addition and subtraction does not give a proper result
void Date::minus ( int days , int month , int year ){
if ( ! set () )
return;
@@ -74,7 +74,7 @@ Date & Date::operator += ( int days ){
return(*this);
}
-// Substract number of days
+// Subtract number of days
Date & Date::operator -= ( int days ){
if ( set () ){
date->tm_mday -= days ;
@@ -223,7 +223,7 @@ int WorkingDays(Date a, Date b){
return(wdays);
}
-Date StartDay(Date a,int days){//Function to calculate the apropriate start day to finish in days working days
+Date StartDay(Date a,int days){//Function to calculate the appropriate start day to finish in days working days
Date tmp;
int wdays=0;
if ( ! a.set() )
diff --git a/test/manual/etags/el-src/TAGTEST.EL b/test/manual/etags/el-src/TAGTEST.EL
index 89a67913771..3e6599a4a45 100644
--- a/test/manual/etags/el-src/TAGTEST.EL
+++ b/test/manual/etags/el-src/TAGTEST.EL
@@ -1,3 +1,5 @@
+;;; -*- lexical-binding: t -*-
+
(foo::defmumble bletch beuarghh)
(defun foo==bar () (message "hi")) ; Bug#5624
;;; Ctags test file for lisp mode.
diff --git a/test/manual/etags/el-src/emacs/lisp/progmodes/etags.el b/test/manual/etags/el-src/emacs/lisp/progmodes/etags.el
index 090645c789c..9ae80149559 100644
--- a/test/manual/etags/el-src/emacs/lisp/progmodes/etags.el
+++ b/test/manual/etags/el-src/emacs/lisp/progmodes/etags.el
@@ -1,6 +1,6 @@
;;; etags.el --- etags facility for Emacs -*- lexical-binding: t -*-
-;; Copyright (C) 1985-1986, 1988-1989, 1992-1996, 1998, 2000-2017 Free
+;; Copyright (C) 1985-1986, 1988-1989, 1992-1996, 1998, 2000-2022 Free
;; Software Foundation, Inc.
;; Author: Roland McGrath <roland@gnu.org>
@@ -171,7 +171,7 @@ is the symbol being selected.
Example value:
- '((\"Emacs Lisp\" Info-goto-emacs-command-node obarray)
+ \\='((\"Emacs Lisp\" Info-goto-emacs-command-node obarray)
(\"Common Lisp\" common-lisp-hyperspec common-lisp-hyperspec-obarray)
(\"SCWM\" scwm-documentation scwm-obarray))"
:group 'etags
@@ -732,7 +732,7 @@ Returns t if it visits a tags table, or nil if there are no more in the list."
"Return the file name of the file whose tags point is within.
Assumes the tags table is the current buffer.
If RELATIVE is non-nil, file name returned is relative to tags
-table file's directory. If RELATIVE is nil, file name returned
+table file's directory. If RELATIVE is nil, file name returned
is complete."
(funcall file-of-tag-function relative))
diff --git a/test/manual/etags/html-src/software.html b/test/manual/etags/html-src/software.html
index 7a85b9ab5e6..9c4f0dde8ea 100644
--- a/test/manual/etags/html-src/software.html
+++ b/test/manual/etags/html-src/software.html
@@ -75,7 +75,7 @@
protocol studies:
<UL>
<LI> <A HREF="/curriculum/pot-abstracts.html#R03:FODAIBEAvsDistributed-IJSC96">
- <i>Comparison between distributed and centralised demand
+ <i>Comparison between distributed and centralized demand
assignment TDMA satellite access schemes</i></A>
<LI><A HREF="/curriculum/pot-abstracts.html#R07:FODAIBEAvsCFRA-IJSC97">
@@ -225,7 +225,7 @@ if that happens so I can update this page.
decoding. I keep a <A HREF="codes.html">mirror</A> of this page.
<DT>Forward error correcting codes by Phil Karn
- <DD>Phil Karn's optimised really <A HREF="http://www.ka9q.net/code/fec/">free
+ <DD>Phil Karn's optimized really <A HREF="http://www.ka9q.net/code/fec/">free
codes</A>.
</DL>
diff --git a/test/manual/etags/merc-src/accumulator.m b/test/manual/etags/merc-src/accumulator.m
new file mode 100644
index 00000000000..0ee41216c11
--- /dev/null
+++ b/test/manual/etags/merc-src/accumulator.m
@@ -0,0 +1,1962 @@
+%---------------------------------------------------------------------------%
+% vim: ft=mercury ts=4 sw=4 et
+%---------------------------------------------------------------------------%
+% Copyright (C) 1999-2000,2002-2007, 2009-2012 The University of Melbourne.
+% Copyright (C) 2015 The Mercury team.
+% This file may only be copied under the terms of the GNU General
+% Public License - see the file COPYING in the Mercury distribution.
+%---------------------------------------------------------------------------%
+%
+% Module: accumulator.m.
+% Main authors: petdr.
+%
+% Attempts to transform a single proc to a tail recursive form by
+% introducing accumulators. The algorithm can do this if the code after
+% the recursive call has either the order independent state update or
+% associative property.
+%
+% /* Order independent State update property */
+% :- promise all [A,B,S0,S]
+% (
+% (some[SA] (update(A, S0, SA), update(B, SA, S)))
+% <=>
+% (some[SB] (update(B, S0, SB), update(A, SB, S)))
+% ).
+%
+% /* Associativity property */
+% :- promise all [A,B,C,ABC]
+% (
+% (some[AB] (assoc(A, B, AB), assoc(AB, C, ABC)))
+% <=>
+% (some[BC] (assoc(B, C, BC), assoc(A, BC, ABC)))
+% ).
+%
+% XXX What about exceptions and non-termination?
+%
+% The promise declarations above only provide promises about the declarative
+% semantics, but in order to apply this optimization, we ought to check that
+% it will preserve the operational semantics (modulo whatever changes are
+% allowed by the language semantics options).
+%
+% Currently we check and respect the --fully-strict option, but not the
+% --no-reorder-conj option. XXX we should check --no-reorder-conj!
+% If --no-reorder-conj was set, it would still be OK to apply this
+% transformation, but ONLY in cases where the goals which get reordered
+% are guaranteed not to throw any exceptions.
+%
+% The algorithm implemented is a combination of the algorithms from
+% "Making Mercury Programs Tail Recursive" and
+% "State Update Transformation", which can be found at
+% <http://www.cs.mu.oz.au/research/mercury/information/papers.html>.
+%
+% Note that currently "State Update Transformation" paper only resides
+% in CVS papers archive in the directory update, but has been submitted
+% to PPDP '00.
+%
+% The transformation recognises predicates in the form
+%
+% p(In, OutUpdate, OutAssoc) :-
+% minimal(In),
+% initialize(OutUpdate),
+% base(OutAssoc).
+% p(In, OutUpdate, OutAssoc) :-
+% decompose(In, Current, Rest),
+% p(Rest, OutUpdate0, OutAssoc0),
+% update(Current, OutUpdate0, OutUpdate),
+% assoc(Current, OutAssoc0, OutAssoc).
+%
+% which can be transformed by the algorithm in "State Update Transformation" to
+%
+% p(In, OutUpdate, OutAssoc) :-
+% initialize(AccUpdate),
+% p_acc(In, OutUpdate, OutAssoc, AccUpdate).
+%
+% p_acc(In, OutUpdate, OutAssoc, AccUpdate) :-
+% minimal(In),
+% base(OutAssoc),
+% OutUpdate = AccUpdate.
+% p_acc(In, OutUpdate, OutAssoc, AccUpdate0) :-
+% decompose(In, Current, Rest),
+% update(Current, AccUpdate0, AccUpdate),
+% p_acc(Rest, OutUpdate, OutAssoc0, AccUpdate),
+% assoc(Current, OutAssoc0, OutAssoc).
+%
+% we then apply the algorithm from "Making Mercury Programs Tail Recursive"
+% to p_acc to obtain
+%
+% p_acc(In, OutUpdate, OutAssoc, AccUpdate) :-
+% minimal(In),
+% base(OutAssoc),
+% OutUpdate = AccUpdate.
+% p_acc(In, OutUpdate, OutAssoc, AccUpdate0) :-
+% decompose(In, Current, Rest),
+% update(Current, AccUpdate0, AccUpdate),
+% p_acc2(Rest, OutUpdate, OutAssoc, AccUpdate, Current).
+%
+% p_acc2(In, OutUpdate, OutAssoc, AccUpdate0, AccAssoc0) :-
+% minimal(In),
+% base(Base),
+% assoc(AccAssoc0, Base, OutAssoc),
+% OutUpdate = AccUpdate0.
+% p_acc2(In, OutUpdate, OutAssoc, AccUpdate0, AccAssoc0) :-
+% decompose(In, Current, Rest),
+% update(Current, AccUpdate0, AccUpdate),
+% assoc(AccAssoc0, Current, AccAssoc),
+% p_acc2(Rest, OutUpdate, OutAssoc, AccUpdate, AccAssoc).
+%
+% p_acc is no longer recursive and is only ever called from p, so we
+% inline p_acc into p to obtain the final schema.
+%
+% p(In, OutUpdate, OutAssoc) :-
+% minimal(In),
+% base(OutAssoc),
+% initialize(AccUpdate),
+% OutUpdate = AccUpdate.
+% p(In, OutUpdate, OutAssoc) :-
+% decompose(In, Current, Rest),
+% initialize(AccUpdate0),
+% update(Current, AccUpdate0, AccUpdate),
+% p_acc2(Rest, OutUpdate, OutAssoc, AccUpdate, Current).
+%
+% p_acc2(In, OutUpdate, OutAssoc, AccUpdate0, AccAssoc0) :-
+% minimal(In),
+% base(Base),
+% assoc(AccAssoc0, Base, OutAssoc),
+% OutUpdate = AccUpdate0.
+% p_acc2(In, OutUpdate, OutAssoc, AccUpdate0, AccAssoc0) :-
+% decompose(In, Current, Rest),
+% update(Current, AccUpdate0, AccUpdate),
+% assoc(AccAssoc0, Current, AccAssoc),
+% p_acc2(Rest, OutUpdate, OutAssoc, AccUpdate, AccAssoc).
+%
+% The only real difficulty in this new transformation is identifying the
+% initialize/1 and base/1 goals from the original base case.
+%
+% Note that if the recursive clause contains multiple calls to p, the
+% transformation attempts to move each recursive call to the end
+% until one succeeds. This makes the order of independent recursive
+% calls in the body irrelevant.
+%
+% XXX Replace calls to can_reorder_goals with calls to the version that
+% use the intermodule-analysis framework.
+%
+%---------------------------------------------------------------------------%
+
+:- module transform_hlds.accumulator.
+:- interface.
+
+:- import_module hlds.
+:- import_module hlds.hlds_module.
+:- import_module hlds.hlds_pred.
+
+:- import_module univ.
+
+ % Attempt to transform a procedure into accumulator recursive form.
+ % If we succeed, we will add the recursive version of the procedure
+ % to the module_info. However, we may also encounter errors, which
+ % we will add to the list of error_specs in the univ accumulator.
+ %
+:- pred accu_transform_proc(pred_proc_id::in, pred_info::in,
+ proc_info::in, proc_info::out, module_info::in, module_info::out,
+ univ::in, univ::out) is det.
+
+%---------------------------------------------------------------------------%
+%---------------------------------------------------------------------------%
+
+:- implementation.
+
+:- import_module hlds.assertion.
+:- import_module hlds.goal_util.
+:- import_module hlds.hlds_error_util.
+:- import_module hlds.hlds_goal.
+:- import_module hlds.hlds_out.
+:- import_module hlds.hlds_out.hlds_out_util.
+:- import_module hlds.hlds_promise.
+:- import_module hlds.instmap.
+:- import_module hlds.pred_table.
+:- import_module hlds.quantification.
+:- import_module hlds.status.
+:- import_module hlds.vartypes.
+:- import_module libs.
+:- import_module libs.globals.
+:- import_module libs.optimization_options.
+:- import_module libs.options.
+:- import_module mdbcomp.
+:- import_module mdbcomp.sym_name.
+:- import_module parse_tree.
+:- import_module parse_tree.error_util.
+:- import_module parse_tree.prog_data.
+:- import_module parse_tree.prog_mode.
+:- import_module parse_tree.prog_util.
+:- import_module parse_tree.set_of_var.
+:- import_module transform_hlds.goal_store.
+
+:- import_module assoc_list.
+:- import_module bool.
+:- import_module int.
+:- import_module io.
+:- import_module list.
+:- import_module map.
+:- import_module maybe.
+:- import_module pair.
+:- import_module require.
+:- import_module set.
+:- import_module solutions.
+:- import_module string.
+:- import_module term.
+:- import_module varset.
+
+%---------------------------------------------------------------------------%
+
+ % The form of the goal around the base and recursive cases.
+ %
+:- type top_level
+ ---> switch_base_rec
+ ; switch_rec_base
+ ; disj_base_rec
+ ; disj_rec_base
+ ; ite_base_rec
+ ; ite_rec_base.
+
+ % An accu_goal_id represents a goal. The first field says which conjunction
+ % the goal came from (the base case or the recursive case), and the second
+ % gives the location of the goal in that conjunction.
+ %
+:- type accu_goal_id
+ ---> accu_goal_id(accu_case, int).
+
+:- type accu_case
+ ---> accu_base
+ ; accu_rec.
+
+ % The goal_store associates a goal with each goal_id.
+ %
+:- type accu_goal_store == goal_store(accu_goal_id).
+
+ % A substitution from the first variable name to the second.
+ %
+:- type accu_subst == map(prog_var, prog_var).
+
+:- type accu_warning
+ ---> accu_warn(prog_context, pred_id, prog_var, prog_var).
+ % Warn that two prog_vars in a call to pred_id at the given context
+ % were swapped, which may cause an efficiency problem.
+
+%---------------------------------------------------------------------------%
+
+accu_transform_proc(proc(PredId, ProcId), PredInfo, !ProcInfo, !ModuleInfo,
+ !Cookie) :-
+ module_info_get_globals(!.ModuleInfo, Globals),
+ globals.get_opt_tuple(Globals, OptTuple),
+ DoLCMC = OptTuple ^ ot_opt_lcmc_accumulator,
+ globals.lookup_bool_option(Globals, fully_strict, FullyStrict),
+ ( if
+ should_attempt_accu_transform(!ModuleInfo, PredId, ProcId, PredInfo,
+ !ProcInfo, FullyStrict, DoLCMC, Warnings)
+ then
+ globals.lookup_bool_option(Globals, very_verbose, VeryVerbose),
+ (
+ VeryVerbose = yes,
+ trace [io(!IO)] (
+ module_info_get_name(!.ModuleInfo, ModuleName),
+ get_progress_output_stream(Globals, ModuleName,
+ ProgressStream, !IO),
+ PredStr = pred_id_to_string(!.ModuleInfo, PredId),
+ io.format(ProgressStream,
+ "%% Accumulators introduced into %s\n", [s(PredStr)], !IO)
+ )
+ ;
+ VeryVerbose = no
+ ),
+
+ (
+ Warnings = []
+ ;
+ Warnings = [_ | _],
+ pred_info_get_context(PredInfo, Context),
+ PredPieces = describe_one_pred_name(!.ModuleInfo,
+ should_module_qualify, PredId),
+ InPieces = [words("In") | PredPieces] ++ [suffix(":"), nl],
+ InMsg = simple_msg(Context,
+ [option_is_set(warn_accumulator_swaps, yes,
+ [always(InPieces)])]),
+
+ proc_info_get_varset(!.ProcInfo, VarSet),
+ generate_warnings(!.ModuleInfo, VarSet, Warnings, WarnMsgs),
+ (
+ Warnings = [_],
+ EnsurePieces = [words("Please ensure that this"),
+ words("argument rearrangement does not introduce"),
+ words("performance problems.")]
+ ;
+ Warnings = [_, _ | _],
+ EnsurePieces = [words("Please ensure that these"),
+ words("argument rearrangements do not introduce"),
+ words("performance problems.")]
+ ),
+ SuppressPieces =
+ [words("These warnings can be suppressed by"),
+ quote("--no-warn-accumulator-swaps"), suffix(".")],
+ VerbosePieces = [words("If a predicate has been declared"),
+ words("associative"),
+ words("via a"), quote("promise"), words("declaration,"),
+ words("the compiler will rearrange the order of"),
+ words("the arguments in calls to that predicate,"),
+ words("if by so doing it makes the containing predicate"),
+ words("tail recursive. In such situations, the compiler"),
+ words("will issue this warning. If this reordering"),
+ words("changes the performance characteristics"),
+ words("of the call to the predicate, use"),
+ quote("--no-accumulator-introduction"),
+ words("to turn the optimization off, or "),
+ quote("--no-warn-accumulator-swaps"),
+ words("to turn off the warnings.")],
+ EnsureSuppressMsg = simple_msg(Context,
+ [option_is_set(warn_accumulator_swaps, yes,
+ [always(EnsurePieces), always(SuppressPieces)]),
+ verbose_only(verbose_once, VerbosePieces)]),
+ Severity = severity_conditional(warn_accumulator_swaps, yes,
+ severity_warning, no),
+ Msgs = [InMsg | WarnMsgs] ++ [EnsureSuppressMsg],
+ Spec = error_spec($pred, Severity, phase_accumulator_intro, Msgs),
+
+ det_univ_to_type(!.Cookie, Specs0),
+ Specs = [Spec | Specs0],
+ type_to_univ(Specs, !:Cookie)
+ )
+ else
+ true
+ ).
+
+%---------------------------------------------------------------------------%
+%---------------------------------------------------------------------------%
+
+:- pred generate_warnings(module_info::in, prog_varset::in,
+ list(accu_warning)::in, list(error_msg)::out) is det.
+
+generate_warnings(_, _, [], []).
+generate_warnings(ModuleInfo, VarSet, [Warning | Warnings], [Msg | Msgs]) :-
+ generate_warning(ModuleInfo, VarSet, Warning, Msg),
+ generate_warnings(ModuleInfo, VarSet, Warnings, Msgs).
+
+:- pred generate_warning(module_info::in, prog_varset::in, accu_warning::in,
+ error_msg::out) is det.
+
+generate_warning(ModuleInfo, VarSet, Warning, Msg) :-
+ Warning = accu_warn(Context, PredId, VarA, VarB),
+ PredPieces = describe_one_pred_name(ModuleInfo, should_module_qualify,
+ PredId),
+
+ varset.lookup_name(VarSet, VarA, VarAName),
+ varset.lookup_name(VarSet, VarB, VarBName),
+
+ Pieces = [words("warning: the call to")] ++ PredPieces ++
+ [words("has had the location of the variables"),
+ quote(VarAName), words("and"), quote(VarBName),
+ words("swapped to allow accumulator introduction."), nl],
+ Msg = simplest_msg(Context, Pieces).
+
+%---------------------------------------------------------------------------%
+%---------------------------------------------------------------------------%
+
+ % should_attempt_accu_transform is only true iff the current proc
+ % has been transformed to call the newly created accumulator proc.
+ %
+:- pred should_attempt_accu_transform(module_info::in, module_info::out,
+ pred_id::in, proc_id::in, pred_info::in, proc_info::in, proc_info::out,
+ bool::in, maybe_opt_lcmc_accumulator::in,
+ list(accu_warning)::out) is semidet.
+
+should_attempt_accu_transform(!ModuleInfo, PredId, ProcId, PredInfo,
+ !ProcInfo, FullyStrict, DoLCMC, Warnings) :-
+ proc_info_get_goal(!.ProcInfo, Goal0),
+ proc_info_get_headvars(!.ProcInfo, HeadVars),
+ proc_info_get_initial_instmap(!.ModuleInfo, !.ProcInfo, InitialInstMap),
+ accu_standardize(Goal0, Goal),
+ identify_goal_type(PredId, ProcId, Goal, InitialInstMap,
+ TopLevel, Base, BaseInstMap, Rec, RecInstMap),
+
+ C = initialize_goal_store(Rec, RecInstMap, Base, BaseInstMap),
+ identify_recursive_calls(PredId, ProcId, C, RecCallIds),
+ list.length(Rec, M),
+
+ should_attempt_accu_transform_2(!ModuleInfo, PredId, PredInfo, !ProcInfo,
+ HeadVars, InitialInstMap, TopLevel, FullyStrict, DoLCMC,
+ RecCallIds, C, M, Rec, Warnings).
+
+ % should_attempt_accu_transform_2 takes a list of locations of the
+ % recursive calls, and attempts to introduce accumulator into each of the
+ % recursive calls, stopping at the first one that succeeds.
+ % This catches the following case, as selecting the first recursive call
+ % allows the second recursive call to be moved before it, and
+ % OutA is in the correct spot in list.append.
+ %
+ % p(InA, OutA),
+ % p(InB, OutB),
+ % list.append(OutB, OutA, Out)
+ %
+:- pred should_attempt_accu_transform_2(module_info::in, module_info::out,
+ pred_id::in, pred_info::in, proc_info::in, proc_info::out,
+ list(prog_var)::in, instmap::in, top_level::in, bool::in,
+ maybe_opt_lcmc_accumulator::in,
+ list(accu_goal_id)::in, accu_goal_store::in, int::in, list(hlds_goal)::in,
+ list(accu_warning)::out) is semidet.
+
+should_attempt_accu_transform_2(!ModuleInfo, PredId, PredInfo, !ProcInfo,
+ HeadVars, InitialInstMap, TopLevel, FullyStrict, DoLCMC,
+ [Id | Ids], C, M, Rec, Warnings) :-
+ proc_info_get_vartypes(!.ProcInfo, VarTypes0),
+ identify_out_and_out_prime(!.ModuleInfo, VarTypes0, InitialInstMap,
+ Id, Rec, HeadVars, Out, OutPrime, HeadToCallSubst, CallToHeadSubst),
+ ( if
+ accu_stage1(!.ModuleInfo, VarTypes0, FullyStrict, DoLCMC, Id, M, C,
+ Sets),
+ accu_stage2(!.ModuleInfo, !.ProcInfo, Id, C, Sets, OutPrime, Out,
+ VarSet, VarTypes, Accs, BaseCase, BasePairs, Substs, CS,
+ WarningsPrime),
+ accu_stage3(Id, Accs, VarSet, VarTypes, C, CS, Substs,
+ HeadToCallSubst, CallToHeadSubst, BaseCase, BasePairs, Sets, Out,
+ TopLevel, PredId, PredInfo, !ProcInfo, !ModuleInfo)
+ then
+ Warnings = WarningsPrime
+ else
+ should_attempt_accu_transform_2(!ModuleInfo, PredId, PredInfo,
+ !ProcInfo, HeadVars, InitialInstMap, TopLevel, FullyStrict, DoLCMC,
+ Ids, C, M, Rec, Warnings)
+ ).
+
+%---------------------------------------------------------------------------%
+%---------------------------------------------------------------------------%
+
+ % Transform the goal into a standard form that is amenable to
+ % introducing accumulators.
+ %
+ % At the moment all this does is remove any extra disj/conj wrappers
+ % around the top level goal.
+ %
+ % Future work is for this code to rearrange code with multiple base
+ % and recursive cases into a single base and recursive case.
+ %
+:- pred accu_standardize(hlds_goal::in, hlds_goal::out) is det.
+
+accu_standardize(Goal0, Goal) :-
+ ( if
+ Goal0 = hlds_goal(GoalExpr0, _),
+ (
+ GoalExpr0 = conj(plain_conj, [Goal1])
+ ;
+ GoalExpr0 = disj([Goal1])
+ )
+ then
+ accu_standardize(Goal1, Goal)
+ else
+ Goal = Goal0
+ ).
+
+%---------------------------------------------------------------------------%
+%---------------------------------------------------------------------------%
+
+ % This predicate takes the original goal and identifies the `shape'
+ % of the goal around the recursive and base cases.
+ %
+ % Note that the base case can contain a recursive call, as the
+ % transformation doesn't depend on what is in the base case.
+ %
+:- pred identify_goal_type(pred_id::in, proc_id::in, hlds_goal::in,
+ instmap::in, top_level::out, list(hlds_goal)::out, instmap::out,
+ list(hlds_goal)::out, instmap::out) is semidet.
+
+identify_goal_type(PredId, ProcId, Goal, InitialInstMap, Type,
+ Base, BaseInstMap, Rec, RecInstMap) :-
+ Goal = hlds_goal(GoalExpr, _GoalInfo),
+ (
+ GoalExpr = switch(_Var, _CanFail, Cases),
+ ( if
+ Cases = [case(_IdA, [], GoalA), case(_IdB, [], GoalB)],
+ goal_to_conj_list(GoalA, GoalAList),
+ goal_to_conj_list(GoalB, GoalBList)
+ then
+ ( if is_recursive_case(GoalAList, proc(PredId, ProcId)) then
+ Type = switch_rec_base,
+ Base = GoalBList,
+ Rec = GoalAList
+ else if is_recursive_case(GoalBList, proc(PredId, ProcId)) then
+ Type = switch_base_rec,
+ Base = GoalAList,
+ Rec = GoalBList
+ else
+ fail
+ ),
+ BaseInstMap = InitialInstMap,
+ RecInstMap = InitialInstMap
+ else
+ fail
+ )
+ ;
+ GoalExpr = disj(Goals),
+ ( if
+ Goals = [GoalA, GoalB],
+ goal_to_conj_list(GoalA, GoalAList),
+ goal_to_conj_list(GoalB, GoalBList)
+ then
+ ( if is_recursive_case(GoalAList, proc(PredId, ProcId)) then
+ Type = disj_rec_base,
+ Base = GoalBList,
+ Rec = GoalAList
+ else if is_recursive_case(GoalBList, proc(PredId, ProcId)) then
+ Type = disj_base_rec,
+ Base = GoalAList,
+ Rec = GoalBList
+ else
+ fail
+ ),
+ BaseInstMap = InitialInstMap,
+ RecInstMap = InitialInstMap
+ else
+ fail
+ )
+ ;
+ GoalExpr = if_then_else(_Vars, Cond, Then, Else),
+ Cond = hlds_goal(_CondGoalExpr, CondGoalInfo),
+ CondInstMapDelta = goal_info_get_instmap_delta(CondGoalInfo),
+
+ goal_to_conj_list(Then, GoalAList),
+ goal_to_conj_list(Else, GoalBList),
+ ( if is_recursive_case(GoalAList, proc(PredId, ProcId)) then
+ Type = ite_rec_base,
+ Base = GoalBList,
+ Rec = GoalAList,
+
+ BaseInstMap = InitialInstMap,
+ apply_instmap_delta(CondInstMapDelta, InitialInstMap, RecInstMap)
+ else if is_recursive_case(GoalBList, proc(PredId, ProcId)) then
+ Type = ite_base_rec,
+ Base = GoalAList,
+ Rec = GoalBList,
+
+ RecInstMap = InitialInstMap,
+ apply_instmap_delta(CondInstMapDelta, InitialInstMap, BaseInstMap)
+ else
+ fail
+ )
+ ).
+
+ % is_recursive_case(Gs, Id) is true iff the list of goals, Gs,
+ % contains a call to the procedure specified by Id, where the call
+ % is located in a position that can be used by the transformation
+ % (i.e. not hidden in a compound goal).
+ %
+:- pred is_recursive_case(list(hlds_goal)::in, pred_proc_id::in) is semidet.
+
+is_recursive_case(Goals, proc(PredId, ProcId)) :-
+ list.append(_Initial, [RecursiveCall | _Final], Goals),
+ RecursiveCall = hlds_goal(plain_call(PredId, ProcId, _, _, _, _), _).
+
+%---------------------------------------------------------------------------%
+%---------------------------------------------------------------------------%
+
+ % The store info is folded over the list of goals which
+ % represent the base and recursive case conjunctions.
+:- type store_info
+ ---> store_info(
+ store_loc :: int,
+ % The location of the goal in the conjunction.
+ store_instmap :: instmap,
+ store_goals :: accu_goal_store
+ ).
+
+ % Initialise the goal_store, which will hold the C_{a,b} goals.
+ %
+:- func initialize_goal_store(list(hlds_goal), instmap,
+ list(hlds_goal), instmap) = accu_goal_store.
+
+initialize_goal_store(Rec, RecInstMap, Base, BaseInstMap) = C :-
+ goal_store_init(C0),
+ list.foldl3(accu_store(accu_rec), Rec,
+ 1, _, RecInstMap, _, C0, C1),
+ list.foldl3(accu_store(accu_base), Base,
+ 1, _, BaseInstMap, _, C1, C).
+
+:- pred accu_store(accu_case::in, hlds_goal::in,
+ int::in, int::out, instmap::in, instmap::out,
+ accu_goal_store::in, accu_goal_store::out) is det.
+
+accu_store(Case, Goal, !N, !InstMap, !GoalStore) :-
+ Id = accu_goal_id(Case, !.N),
+ goal_store_det_insert(Id, stored_goal(Goal, !.InstMap), !GoalStore),
+
+ !:N = !.N + 1,
+ Goal = hlds_goal(_, GoalInfo),
+ InstMapDelta = goal_info_get_instmap_delta(GoalInfo),
+ apply_instmap_delta(InstMapDelta, !InstMap).
+
+%---------------------------------------------------------------------------%
+%---------------------------------------------------------------------------%
+
+ % Determine the k's which are recursive calls.
+ % Note that this doesn't find recursive calls which are `hidden'
+ % in compound goals, this is not a problem as currently we can't use
+ % these to do transformation.
+ %
+:- pred identify_recursive_calls(pred_id::in, proc_id::in,
+ accu_goal_store::in, list(accu_goal_id)::out) is det.
+
+identify_recursive_calls(PredId, ProcId, GoalStore, Ids) :-
+ P =
+ ( pred(Key::out) is nondet :-
+ goal_store_member(GoalStore, Key, stored_goal(Goal, _InstMap)),
+ Key = accu_goal_id(accu_rec, _),
+ Goal = hlds_goal(plain_call(PredId, ProcId, _, _, _, _), _)
+ ),
+ solutions.solutions(P, Ids).
+
+%---------------------------------------------------------------------------%
+%---------------------------------------------------------------------------%
+
+ % Determine the variables which are members of the sets Out and Out',
+ % and initialize the substitutions between the two sets.
+ %
+ % This is done by identifying those variables whose instantiatedness change
+ % in the goals after the recursive call and are headvars.
+ %
+ % Note that we are only identifying the output variables which will need
+ % to be accumulated, as there may be other output variables which are
+ % produced prior to the recursive call.
+ %
+:- pred identify_out_and_out_prime(module_info::in, vartypes::in, instmap::in,
+ accu_goal_id::in, list(hlds_goal)::in,
+ list(prog_var)::in, list(prog_var)::out, list(prog_var)::out,
+ accu_subst::out, accu_subst::out) is det.
+
+identify_out_and_out_prime(ModuleInfo, VarTypes, InitialInstMap, GoalId,
+ Rec, HeadVars, Out, OutPrime, HeadToCallSubst, CallToHeadSubst) :-
+ GoalId = accu_goal_id(_Case, K),
+ ( if
+ list.take(K, Rec, InitialGoals),
+ list.drop(K-1, Rec, FinalGoals),
+ FinalGoals = [hlds_goal(plain_call(_, _, Args, _, _, _), _) | Rest]
+ then
+ goal_list_instmap_delta(InitialGoals, InitInstMapDelta),
+ apply_instmap_delta( InitInstMapDelta,
+ InitialInstMap, InstMapBeforeRest),
+
+ goal_list_instmap_delta(Rest, InstMapDelta),
+ apply_instmap_delta(InstMapDelta, InstMapBeforeRest, InstMapAfterRest),
+
+ instmap_changed_vars(ModuleInfo, VarTypes,
+ InstMapBeforeRest, InstMapAfterRest, ChangedVars),
+
+ assoc_list.from_corresponding_lists(HeadVars, Args, HeadArg0),
+
+ Member =
+ ( pred(M::in) is semidet :-
+ M = HeadVar - _,
+ set_of_var.member(ChangedVars, HeadVar)
+ ),
+ list.filter(Member, HeadArg0, HeadArg),
+ list.map(fst, HeadArg, Out),
+ list.map(snd, HeadArg, OutPrime),
+
+ map.from_assoc_list(HeadArg, HeadToCallSubst),
+
+ list.map((pred(X-Y::in, Y-X::out) is det), HeadArg, ArgHead),
+ map.from_assoc_list(ArgHead, CallToHeadSubst)
+ else
+ unexpected($pred, "test failed")
+ ).
+
+%---------------------------------------------------------------------------%
+%---------------------------------------------------------------------------%
+
+ % For each goal after the recursive call, we place that goal
+ % into a set according to what properties that goal has.
+ % For the definition of what goes into each set, inspect the documentation
+ % for the functions named before, assoc, and so on.
+ %
+:- type accu_sets
+ ---> accu_sets(
+ as_before :: set(accu_goal_id),
+ as_assoc :: set(accu_goal_id),
+ as_construct_assoc :: set(accu_goal_id),
+ as_construct :: set(accu_goal_id),
+ as_update :: set(accu_goal_id),
+ as_reject :: set(accu_goal_id)
+ ).
+
+ % Stage 1 is responsible for identifying which goals are associative,
+ % which can be moved before the recursive call and so on.
+ %
+:- pred accu_stage1(module_info::in, vartypes::in, bool::in,
+ maybe_opt_lcmc_accumulator::in, accu_goal_id::in, int::in,
+ accu_goal_store::in, accu_sets::out) is semidet.
+
+accu_stage1(ModuleInfo, VarTypes, FullyStrict, DoLCMC, GoalId, M, GoalStore,
+ Sets) :-
+ GoalId = accu_goal_id(Case, K),
+ NextGoalId = accu_goal_id(Case, K + 1),
+ accu_sets_init(Sets0),
+ accu_stage1_2(ModuleInfo, VarTypes, FullyStrict, NextGoalId, K, M,
+ GoalStore, Sets0, Sets1),
+ Sets1 = accu_sets(Before, Assoc,
+ ConstructAssoc, Construct, Update, Reject),
+ Sets = accu_sets(Before `set.union` set_upto(Case, K - 1), Assoc,
+ ConstructAssoc, Construct, Update, Reject),
+
+ % Continue the transformation only if the set reject is empty and
+ % the set assoc or update contains something that needs to be moved
+ % before the recursive call.
+ set.is_empty(Reject),
+ (
+ not set.is_empty(Assoc)
+ ;
+ not set.is_empty(Update)
+ ),
+ (
+ DoLCMC = do_not_opt_lcmc_accumulator,
+ % If LCMC is not turned on, then there must be no construction
+ % unifications after the recursive call.
+ set.is_empty(Construct),
+ set.is_empty(ConstructAssoc)
+ ;
+ DoLCMC = opt_lcmc_accumulator
+ ).
+
+ % For each goal after the recursive call decide which set
+ % the goal belongs to.
+ %
+:- pred accu_stage1_2(module_info::in, vartypes::in, bool::in,
+ accu_goal_id::in, int::in, int::in, accu_goal_store::in,
+ accu_sets::in, accu_sets::out) is det.
+
+accu_stage1_2(ModuleInfo, VarTypes, FullyStrict, GoalId, K, M, GoalStore,
+ !Sets) :-
+ GoalId = accu_goal_id(Case, I),
+ NextGoalId = accu_goal_id(Case, I + 1),
+ ( if I > M then
+ true
+ else
+ ( if
+ accu_before(ModuleInfo, VarTypes, FullyStrict, GoalId, K,
+ GoalStore, !.Sets)
+ then
+ !Sets ^ as_before := set.insert(!.Sets ^ as_before, GoalId),
+ accu_stage1_2(ModuleInfo, VarTypes, FullyStrict, NextGoalId, K, M,
+ GoalStore, !Sets)
+ else if
+ accu_assoc(ModuleInfo, VarTypes, FullyStrict, GoalId, K,
+ GoalStore, !.Sets)
+ then
+ !Sets ^ as_assoc := set.insert(!.Sets ^ as_assoc, GoalId),
+ accu_stage1_2(ModuleInfo, VarTypes, FullyStrict, NextGoalId, K, M,
+ GoalStore, !Sets)
+ else if
+ accu_construct(ModuleInfo, VarTypes, FullyStrict, GoalId, K,
+ GoalStore, !.Sets)
+ then
+ !Sets ^ as_construct := set.insert(!.Sets ^ as_construct, GoalId),
+ accu_stage1_2(ModuleInfo, VarTypes, FullyStrict, NextGoalId, K, M,
+ GoalStore, !Sets)
+ else if
+ accu_construct_assoc(ModuleInfo, VarTypes, FullyStrict, GoalId, K,
+ GoalStore, !.Sets)
+ then
+ !Sets ^ as_construct_assoc :=
+ set.insert(!.Sets ^ as_construct_assoc, GoalId),
+ accu_stage1_2(ModuleInfo, VarTypes, FullyStrict, NextGoalId, K, M,
+ GoalStore, !Sets)
+ else if
+ accu_update(ModuleInfo, VarTypes, FullyStrict, GoalId, K,
+ GoalStore, !.Sets)
+ then
+ !Sets ^ as_update := set.insert(!.Sets ^ as_update, GoalId),
+ accu_stage1_2(ModuleInfo, VarTypes, FullyStrict, NextGoalId, K, M,
+ GoalStore, !Sets)
+ else
+ !Sets ^ as_reject := set.insert(!.Sets ^ as_reject, GoalId)
+ )
+ ).
+
+%---------------------------------------------------------------------------%
+
+:- pred accu_sets_init(accu_sets::out) is det.
+
+accu_sets_init(Sets) :-
+ set.init(EmptySet),
+ Before = EmptySet,
+ Assoc = EmptySet,
+ ConstructAssoc = EmptySet,
+ Construct = EmptySet,
+ Update = EmptySet,
+ Reject = EmptySet,
+ Sets = accu_sets(Before, Assoc, ConstructAssoc, Construct, Update, Reject).
+
+ % set_upto(Case, K) returns the set
+ % {accu_goal_id(Case, 1) .. accu_goal_id(Case, K)}.
+ %
+:- func set_upto(accu_case, int) = set(accu_goal_id).
+
+set_upto(Case, K) = Set :-
+ ( if K =< 0 then
+ set.init(Set)
+ else
+ Set0 = set_upto(Case, K - 1),
+ set.insert(accu_goal_id(Case, K), Set0, Set)
+ ).
+
+%---------------------------------------------------------------------------%
+
+ % A goal is a member of the before set iff the goal only depends on goals
+ % which are before the recursive call or can be moved before the recursive
+ % call (member of the before set).
+ %
+:- pred accu_before(module_info::in, vartypes::in, bool::in,
+ accu_goal_id::in, int::in, accu_goal_store::in, accu_sets::in) is semidet.
+
+accu_before(ModuleInfo, VarTypes, FullyStrict, GoalId, K, GoalStore, Sets) :-
+ GoalId = accu_goal_id(Case, _I),
+ Before = Sets ^ as_before,
+ goal_store_lookup(GoalStore, GoalId, stored_goal(LaterGoal, LaterInstMap)),
+ (
+ member_lessthan_goalid(GoalStore, GoalId, LessThanGoalId,
+ stored_goal(EarlierGoal, EarlierInstMap)),
+ not can_reorder_goals_old(ModuleInfo, VarTypes, FullyStrict,
+ EarlierInstMap, EarlierGoal, LaterInstMap, LaterGoal)
+ )
+ =>
+ (
+ set.member(LessThanGoalId, set_upto(Case, K - 1) `union` Before)
+ ).
+
+ % A goal is a member of the assoc set iff the goal only depends on goals
+ % upto and including the recursive call and goals which can be moved
+ % before the recursive call (member of the before set) AND the goal
+ % is associative.
+ %
+:- pred accu_assoc(module_info::in, vartypes::in, bool::in,
+ accu_goal_id::in, int::in, accu_goal_store::in, accu_sets::in) is semidet.
+
+accu_assoc(ModuleInfo, VarTypes, FullyStrict, GoalId, K, GoalStore, Sets) :-
+ GoalId = accu_goal_id(Case, _I),
+ Before = Sets ^ as_before,
+ goal_store_lookup(GoalStore, GoalId, stored_goal(LaterGoal, LaterInstMap)),
+ LaterGoal = hlds_goal(plain_call(PredId, _, Args, _, _, _), _),
+ accu_is_associative(ModuleInfo, PredId, Args, _),
+ (
+ % XXX LessThanGoalId was _N - J, not N - J: it ignored the case.
+ % See the diff with the previous version.
+ member_lessthan_goalid(GoalStore, GoalId, LessThanGoalId,
+ stored_goal(EarlierGoal, EarlierInstMap)),
+ not can_reorder_goals_old(ModuleInfo, VarTypes, FullyStrict,
+ EarlierInstMap, EarlierGoal, LaterInstMap, LaterGoal)
+ )
+ =>
+ (
+ set.member(LessThanGoalId, set_upto(Case, K) `union` Before)
+ ).
+
+ % A goal is a member of the construct set iff the goal only depends
+ % on goals upto and including the recursive call and goals which
+ % can be moved before the recursive call (member of the before set)
+ % AND the goal is construction unification.
+ %
+:- pred accu_construct(module_info::in, vartypes::in, bool::in,
+ accu_goal_id::in, int::in, accu_goal_store::in, accu_sets::in) is semidet.
+
+accu_construct(ModuleInfo, VarTypes, FullyStrict, GoalId, K, GoalStore,
+ Sets) :-
+ GoalId = accu_goal_id(Case, _I),
+ Before = Sets ^ as_before,
+ Construct = Sets ^ as_construct,
+ goal_store_lookup(GoalStore, GoalId, stored_goal(LaterGoal, LaterInstMap)),
+ LaterGoal = hlds_goal(unify(_, _, _, Unify, _), _GoalInfo),
+ Unify = construct(_, _, _, _, _, _, _),
+ (
+ % XXX LessThanGoalId was _N - J, not N - J: it ignored the case.
+ % See the diff with the previous version.
+ member_lessthan_goalid(GoalStore, GoalId, LessThanGoalId,
+ stored_goal(EarlierGoal, EarlierInstMap)),
+ not can_reorder_goals_old(ModuleInfo, VarTypes, FullyStrict,
+ EarlierInstMap, EarlierGoal, LaterInstMap, LaterGoal)
+ )
+ =>
+ (
+ set.member(LessThanGoalId,
+ set_upto(Case, K) `union` Before `union` Construct)
+ ).
+
+ % A goal is a member of the construct_assoc set iff the goal depends only
+ % on goals upto and including the recursive call and goals which can be
+ % moved before the recursive call (member of the before set) and goals
+ % which are associative AND the goal is construction unification AND
+ % there is only one member of the assoc set which the construction
+ % unification depends on AND the construction unification can be expressed
+ % as a call to the member of the assoc set which the construction
+ % unification depends on.
+ %
+:- pred accu_construct_assoc(module_info::in, vartypes::in, bool::in,
+ accu_goal_id::in, int::in, accu_goal_store::in, accu_sets::in) is semidet.
+
+accu_construct_assoc(ModuleInfo, VarTypes, FullyStrict,
+ GoalId, K, GoalStore, Sets) :-
+ GoalId = accu_goal_id(Case, _I),
+ Before = Sets ^ as_before,
+ Assoc = Sets ^ as_assoc,
+ ConstructAssoc = Sets ^ as_construct_assoc,
+ goal_store_lookup(GoalStore, GoalId, stored_goal(LaterGoal, LaterInstMap)),
+ LaterGoal = hlds_goal(unify(_, _, _, Unify, _), _GoalInfo),
+ Unify = construct(_, ConsId, _, _, _, _, _),
+
+ goal_store_all_ancestors(GoalStore, GoalId, VarTypes, ModuleInfo,
+ FullyStrict, Ancestors),
+
+ set.is_singleton(Assoc `intersect` Ancestors, AssocId),
+ goal_store_lookup(GoalStore, AssocId,
+ stored_goal(AssocGoal, _AssocInstMap)),
+ AssocGoal = hlds_goal(plain_call(PredId, _, _, _, _, _), _),
+
+ is_associative_construction(ModuleInfo, PredId, ConsId),
+ (
+ % XXX LessThanGoalId was _N - J, not N - J: it ignored the case.
+ % See the diff with the previous version.
+ member_lessthan_goalid(GoalStore, GoalId, LessThanGoalId,
+ stored_goal(EarlierGoal, EarlierInstMap)),
+ not can_reorder_goals_old(ModuleInfo, VarTypes, FullyStrict,
+ EarlierInstMap, EarlierGoal, LaterInstMap, LaterGoal)
+ )
+ =>
+ (
+ set.member(LessThanGoalId,
+ set_upto(Case, K) `union` Before `union` Assoc
+ `union` ConstructAssoc)
+ ).
+
+ % A goal is a member of the update set iff the goal only depends
+ % on goals upto and including the recursive call and goals which
+ % can be moved before the recursive call (member of the before set)
+ % AND the goal updates some state.
+ %
+:- pred accu_update(module_info::in, vartypes::in, bool::in,
+ accu_goal_id::in, int::in, accu_goal_store::in, accu_sets::in) is semidet.
+
+accu_update(ModuleInfo, VarTypes, FullyStrict, GoalId, K, GoalStore, Sets) :-
+ GoalId = accu_goal_id(Case, _I),
+ Before = Sets ^ as_before,
+ goal_store_lookup(GoalStore, GoalId, stored_goal(LaterGoal, LaterInstMap)),
+ LaterGoal = hlds_goal(plain_call(PredId, _, Args, _, _, _), _),
+ accu_is_update(ModuleInfo, PredId, Args, _),
+ (
+ % XXX LessThanGoalId was _N - J, not N - J: it ignored the case.
+ % See the diff with the previous version.
+ member_lessthan_goalid(GoalStore, GoalId, LessThanGoalId,
+ stored_goal(EarlierGoal, EarlierInstMap)),
+ not can_reorder_goals_old(ModuleInfo, VarTypes, FullyStrict,
+ EarlierInstMap, EarlierGoal, LaterInstMap, LaterGoal)
+ )
+ =>
+ (
+ set.member(LessThanGoalId, set_upto(Case, K) `union` Before)
+ ).
+
+ % member_lessthan_goalid(GS, IdA, IdB, GB) is true iff the goal_id, IdB,
+ % and its associated goal, GB, is a member of the goal_store, GS,
+ % and IdB is less than IdA.
+ %
+:- pred member_lessthan_goalid(accu_goal_store::in,
+ accu_goal_id::in, accu_goal_id::out, stored_goal::out) is nondet.
+
+member_lessthan_goalid(GoalStore, GoalId, LessThanGoalId, LessThanGoal) :-
+ goal_store_member(GoalStore, LessThanGoalId, LessThanGoal),
+ GoalId = accu_goal_id(Case, I),
+ LessThanGoalId = accu_goal_id(Case, J),
+ J < I.
+
+%---------------------------------------------------------------------------%
+
+:- type accu_assoc
+ ---> accu_assoc(
+ set_of_progvar, % the associative input args
+ prog_var, % the corresponding output arg
+ bool % is the predicate commutative?
+ ).
+
+ % If accu_is_associative is true, it returns the two arguments which are
+ % associative and the variable which depends on those two arguments,
+ % and an indicator of whether or not the predicate is commutative.
+ %
+:- pred accu_is_associative(module_info::in, pred_id::in, list(prog_var)::in,
+ accu_assoc::out) is semidet.
+
+accu_is_associative(ModuleInfo, PredId, Args, Result) :-
+ module_info_pred_info(ModuleInfo, PredId, PredInfo),
+ pred_info_get_assertions(PredInfo, Assertions),
+ AssertionsList = set.to_sorted_list(Assertions),
+ associativity_assertion(ModuleInfo, AssertionsList, Args,
+ AssociativeVarsOutputVar),
+ ( if
+ commutativity_assertion(ModuleInfo, AssertionsList, Args,
+ _CommutativeVars)
+ then
+ IsCommutative = yes
+ else
+ IsCommutative = no
+ ),
+ AssociativeVarsOutputVar =
+ associative_vars_output_var(AssociativeVars, OutputVar),
+ Result = accu_assoc(AssociativeVars, OutputVar, IsCommutative).
+
+ % Does there exist one (and only one) associativity assertion for the
+ % current predicate?
+ % The 'and only one condition' is required because we currently
+ % do not handle the case of predicates which have individual parts
+ % which are associative, because then we do not know which variable
+ % is descended from which.
+ %
+:- pred associativity_assertion(module_info::in, list(assert_id)::in,
+ list(prog_var)::in, associative_vars_output_var::out) is semidet.
+
+associativity_assertion(ModuleInfo, [AssertId | AssertIds], Args0,
+ AssociativeVarsOutputVar) :-
+ ( if
+ assertion.is_associativity_assertion(ModuleInfo, AssertId,
+ Args0, AssociativeVarsOutputVarPrime)
+ then
+ AssociativeVarsOutputVar = AssociativeVarsOutputVarPrime,
+ not associativity_assertion(ModuleInfo, AssertIds, Args0, _)
+ else
+ associativity_assertion(ModuleInfo, AssertIds, Args0,
+ AssociativeVarsOutputVar)
+ ).
+
+ % Does there exist one (and only one) commutativity assertion for the
+ % current predicate?
+ % The 'and only one condition' is required because we currently
+ % do not handle the case of predicates which have individual
+ % parts which are commutative, because then we do not know which variable
+ % is descended from which.
+ %
+:- pred commutativity_assertion(module_info::in,list(assert_id)::in,
+ list(prog_var)::in, set_of_progvar::out) is semidet.
+
+commutativity_assertion(ModuleInfo, [AssertId | AssertIds], Args0,
+ CommutativeVars) :-
+ ( if
+ assertion.is_commutativity_assertion(ModuleInfo, AssertId,
+ Args0, CommutativeVarsPrime)
+ then
+ CommutativeVars = CommutativeVarsPrime,
+ not commutativity_assertion(ModuleInfo, AssertIds, Args0, _)
+ else
+ commutativity_assertion(ModuleInfo, AssertIds, Args0,
+ CommutativeVars)
+ ).
+
+%---------------------------------------------------------------------------%
+
+ % Does the current predicate update some state?
+ %
+:- pred accu_is_update(module_info::in, pred_id::in, list(prog_var)::in,
+ state_update_vars::out) is semidet.
+
+accu_is_update(ModuleInfo, PredId, Args, ResultStateVars) :-
+ module_info_pred_info(ModuleInfo, PredId, PredInfo),
+ pred_info_get_assertions(PredInfo, Assertions),
+ list.filter_map(
+ ( pred(AssertId::in, StateVars::out) is semidet :-
+ assertion.is_update_assertion(ModuleInfo, AssertId,
+ PredId, Args, StateVars)
+ ),
+ set.to_sorted_list(Assertions), Result),
+ % XXX Maybe we should just match on the first result,
+ % just in case there are duplicate promises.
+ Result = [ResultStateVars].
+
+%---------------------------------------------------------------------------%
+
+ % Can the construction unification be expressed as a call to the
+ % specified predicate.
+ %
+:- pred is_associative_construction(module_info::in, pred_id::in, cons_id::in)
+ is semidet.
+
+is_associative_construction(ModuleInfo, PredId, ConsId) :-
+ module_info_pred_info(ModuleInfo, PredId, PredInfo),
+ pred_info_get_assertions(PredInfo, Assertions),
+ list.filter(
+ ( pred(AssertId::in) is semidet :-
+ assertion.is_construction_equivalence_assertion(ModuleInfo,
+ AssertId, ConsId, PredId)
+ ),
+ set.to_sorted_list(Assertions), Result),
+ Result = [_ | _].
+
+%---------------------------------------------------------------------------%
+%---------------------------------------------------------------------------%
+
+:- type accu_substs
+ ---> accu_substs(
+ acc_var_subst :: accu_subst,
+ rec_call_subst :: accu_subst,
+ assoc_call_subst :: accu_subst,
+ update_subst :: accu_subst
+ ).
+
+:- type accu_base
+ ---> accu_base(
+ % goals which initialize update
+ init_update :: set(accu_goal_id),
+
+ % goals which initialize assoc
+ init_assoc :: set(accu_goal_id),
+
+ % other goals
+ other :: set(accu_goal_id)
+ ).
+
+ % Stage 2 is responsible for identifying the substitutions which
+ % are needed to mimic the unfold/fold process that was used as
+ % the justification of the algorithm in the paper.
+ % It is also responsible for ensuring that the reordering of arguments
+ % doesn't worsen the big-O complexity of the procedure.
+ % It also divides the base case into goals that initialize the
+ % variables used by the update goals, and those used by the assoc
+ % goals and then all the rest.
+ %
+:- pred accu_stage2(module_info::in, proc_info::in,
+ accu_goal_id::in, accu_goal_store::in, accu_sets::in,
+ list(prog_var)::in, list(prog_var)::in, prog_varset::out, vartypes::out,
+ list(prog_var)::out, accu_base::out, list(pair(prog_var))::out,
+ accu_substs::out, accu_goal_store::out, list(accu_warning)::out)
+ is semidet.
+
+accu_stage2(ModuleInfo, ProcInfo0, GoalId, GoalStore, Sets, OutPrime, Out,
+ !:VarSet, !:VarTypes, Accs, BaseCase, BasePairs, !:Substs,
+ CS, Warnings) :-
+ Sets = accu_sets(Before0, Assoc, ConstructAssoc, Construct, Update, _),
+ GoalId = accu_goal_id(Case, K),
+ Before = Before0 `union` set_upto(Case, K-1),
+
+ % Note Update set is not placed in the after set, as the after set is used
+ % to determine the variables that need to be accumulated for the
+ % associative calls.
+ After = Assoc `union` ConstructAssoc `union` Construct,
+
+ P =
+ ( pred(Id::in, Set0::in, Set::out) is det :-
+ goal_store_lookup(GoalStore, Id, stored_goal(Goal, _InstMap)),
+ Goal = hlds_goal(_GoalExpr, GoalInfo),
+ NonLocals = goal_info_get_nonlocals(GoalInfo),
+ set_of_var.union(NonLocals, Set0, Set)
+ ),
+ list.foldl(P, set.to_sorted_list(Before),
+ set_of_var.init, BeforeNonLocals),
+ list.foldl(P, set.to_sorted_list(After),
+ set_of_var.init, AfterNonLocals),
+ InitAccs = set_of_var.intersect(BeforeNonLocals, AfterNonLocals),
+
+ proc_info_get_varset(ProcInfo0, !:VarSet),
+ proc_info_get_vartypes(ProcInfo0, !:VarTypes),
+
+ accu_substs_init(set_of_var.to_sorted_list(InitAccs), !VarSet, !VarTypes,
+ !:Substs),
+
+ set_of_var.list_to_set(OutPrime, OutPrimeSet),
+ accu_process_assoc_set(ModuleInfo, GoalStore, set.to_sorted_list(Assoc),
+ OutPrimeSet, !Substs, !VarSet, !VarTypes, CS, Warnings),
+
+ accu_process_update_set(ModuleInfo, GoalStore, set.to_sorted_list(Update),
+ OutPrimeSet, !Substs, !VarSet, !VarTypes, UpdateOut, UpdateAccOut,
+ BasePairs),
+
+ Accs = set_of_var.to_sorted_list(InitAccs) ++ UpdateAccOut,
+
+ accu_divide_base_case(ModuleInfo, !.VarTypes, GoalStore, UpdateOut, Out,
+ UpdateBase, AssocBase, OtherBase),
+
+ BaseCase = accu_base(UpdateBase, AssocBase, OtherBase).
+
+%---------------------------------------------------------------------------%
+
+:- pred accu_substs_init(list(prog_var)::in, prog_varset::in, prog_varset::out,
+ vartypes::in, vartypes::out, accu_substs::out) is det.
+
+accu_substs_init(InitAccs, !VarSet, !VarTypes, Substs) :-
+ map.init(Subst),
+ acc_var_subst_init(InitAccs, !VarSet, !VarTypes, AccVarSubst),
+ RecCallSubst = Subst,
+ AssocCallSubst = Subst,
+ UpdateSubst = Subst,
+ Substs = accu_substs(AccVarSubst, RecCallSubst, AssocCallSubst,
+ UpdateSubst).
+
+ % Initialise the acc_var_subst to be from Var to A_Var where Var is a
+ % member of InitAccs and A_Var is a fresh variable of the same type of Var.
+ %
+:- pred acc_var_subst_init(list(prog_var)::in,
+ prog_varset::in, prog_varset::out, vartypes::in, vartypes::out,
+ accu_subst::out) is det.
+
+acc_var_subst_init([], !VarSet, !VarTypes, map.init).
+acc_var_subst_init([Var | Vars], !VarSet, !VarTypes, Subst) :-
+ create_new_var(Var, "A_", AccVar, !VarSet, !VarTypes),
+ acc_var_subst_init(Vars, !VarSet, !VarTypes, Subst0),
+ map.det_insert(Var, AccVar, Subst0, Subst).
+
+ % Create a fresh variable which is the same type as the old variable
+ % and has the same name except that it begins with the prefix.
+ %
+:- pred create_new_var(prog_var::in, string::in, prog_var::out,
+ prog_varset::in, prog_varset::out, vartypes::in, vartypes::out) is det.
+
+create_new_var(OldVar, Prefix, NewVar, !VarSet, !VarTypes) :-
+ varset.lookup_name(!.VarSet, OldVar, OldName),
+ string.append(Prefix, OldName, NewName),
+ varset.new_named_var(NewName, NewVar, !VarSet),
+ lookup_var_type(!.VarTypes, OldVar, Type),
+ add_var_type(NewVar, Type, !VarTypes).
+
+%---------------------------------------------------------------------------%
+
+ % For each member of the assoc set determine the substitutions needed,
+ % and also check the efficiency of the procedure isn't worsened
+ % by reordering the arguments to a call.
+ %
+:- pred accu_process_assoc_set(module_info::in, accu_goal_store::in,
+ list(accu_goal_id)::in, set_of_progvar::in,
+ accu_substs::in, accu_substs::out,
+ prog_varset::in, prog_varset::out, vartypes::in, vartypes::out,
+ accu_goal_store::out, list(accu_warning)::out) is semidet.
+
+accu_process_assoc_set(_ModuleInfo, _GS, [], _OutPrime, !Substs,
+ !VarSet, !VarTypes, CS, []) :-
+ goal_store_init(CS).
+accu_process_assoc_set(ModuleInfo, GS, [Id | Ids], OutPrime, !Substs,
+ !VarSet, !VarTypes, CS, Warnings) :-
+ !.Substs = accu_substs(AccVarSubst, RecCallSubst0, AssocCallSubst0,
+ UpdateSubst),
+
+ lookup_call(GS, Id, stored_goal(Goal, InstMap)),
+
+ Goal = hlds_goal(plain_call(PredId, _, Args, _, _, _), GoalInfo),
+ accu_is_associative(ModuleInfo, PredId, Args, AssocInfo),
+ AssocInfo = accu_assoc(Vars, AssocOutput, IsCommutative),
+ OutPrimeVars = set_of_var.intersect(Vars, OutPrime),
+ set_of_var.is_singleton(OutPrimeVars, DuringAssocVar),
+ set_of_var.is_singleton(set_of_var.difference(Vars, OutPrimeVars),
+ BeforeAssocVar),
+
+ map.lookup(AccVarSubst, BeforeAssocVar, AccVar),
+ create_new_var(BeforeAssocVar, "NewAcc_", NewAcc, !VarSet, !VarTypes),
+
+ map.det_insert(DuringAssocVar, AccVar, AssocCallSubst0, AssocCallSubst1),
+ map.det_insert(AssocOutput, NewAcc, AssocCallSubst1, AssocCallSubst),
+ map.det_insert(DuringAssocVar, AssocOutput, RecCallSubst0, RecCallSubst1),
+ map.det_insert(BeforeAssocVar, NewAcc, RecCallSubst1, RecCallSubst),
+
+ !:Substs = accu_substs(AccVarSubst, RecCallSubst, AssocCallSubst,
+ UpdateSubst),
+
+ % ONLY swap the order of the variables if the goal is
+ % associative and not commutative.
+ (
+ IsCommutative = yes,
+ CSGoal = stored_goal(Goal, InstMap),
+ CurWarnings = []
+ ;
+ IsCommutative = no,
+
+ % Ensure that the reordering doesn't cause a efficiency problem.
+ module_info_pred_info(ModuleInfo, PredId, PredInfo),
+ ModuleName = pred_info_module(PredInfo),
+ PredName = pred_info_name(PredInfo),
+ Arity = pred_info_orig_arity(PredInfo),
+ ( if accu_has_heuristic(ModuleName, PredName, Arity) then
+ % Only do the transformation if the accumulator variable is
+ % *not* in a position where it will control the running time
+ % of the predicate.
+ accu_heuristic(ModuleName, PredName, Arity, Args,
+ PossibleDuringAssocVars),
+ set_of_var.member(PossibleDuringAssocVars, DuringAssocVar),
+ CurWarnings = []
+ else
+ ProgContext = goal_info_get_context(GoalInfo),
+ CurWarnings = [accu_warn(ProgContext, PredId, BeforeAssocVar,
+ DuringAssocVar)]
+ ),
+ % Swap the arguments.
+ [A, B] = set_of_var.to_sorted_list(Vars),
+ map.from_assoc_list([A - B, B - A], Subst),
+ rename_some_vars_in_goal(Subst, Goal, SwappedGoal),
+ CSGoal = stored_goal(SwappedGoal, InstMap)
+ ),
+
+ accu_process_assoc_set(ModuleInfo, GS, Ids, OutPrime, !Substs,
+ !VarSet, !VarTypes, CS0, Warnings0),
+ goal_store_det_insert(Id, CSGoal, CS0, CS),
+ Warnings = Warnings0 ++ CurWarnings.
+
+:- pred accu_has_heuristic(module_name::in, string::in, arity::in) is semidet.
+
+accu_has_heuristic(unqualified("list"), "append", 3).
+
+ % heuristic returns the set of which head variables are important
+ % in the running time of the predicate.
+ %
+:- pred accu_heuristic(module_name::in, string::in, arity::in,
+ list(prog_var)::in, set_of_progvar::out) is semidet.
+
+accu_heuristic(unqualified("list"), "append", 3, [_Typeinfo, A, _B, _C],
+ Set) :-
+ set_of_var.make_singleton(A, Set).
+
+%---------------------------------------------------------------------------%
+
+ % For each member of the update set determine the substitutions needed
+ % (creating the accumulator variables when needed).
+ % Also associate with each Output variable which accumulator variable
+ % to get the result from.
+ %
+:- pred accu_process_update_set(module_info::in, accu_goal_store::in,
+ list(accu_goal_id)::in, set_of_progvar::in,
+ accu_substs::in, accu_substs::out,
+ prog_varset::in, prog_varset::out, vartypes::in, vartypes::out,
+ list(prog_var)::out, list(prog_var)::out, list(pair(prog_var))::out)
+ is semidet.
+
+accu_process_update_set(_ModuleInfo, _GS, [], _OutPrime, !Substs,
+ !VarSet, !VarTypes, [], [], []).
+accu_process_update_set(ModuleInfo, GS, [Id | Ids], OutPrime, !Substs,
+ !VarSet, !VarTypes, StateOutputVars, Accs, BasePairs) :-
+ !.Substs = accu_substs(AccVarSubst0, RecCallSubst0, AssocCallSubst,
+ UpdateSubst0),
+ lookup_call(GS, Id, stored_goal(Goal, _InstMap)),
+
+ Goal = hlds_goal(plain_call(PredId, _, Args, _, _, _), _GoalInfo),
+ accu_is_update(ModuleInfo, PredId, Args, StateVars),
+ StateVars = state_update_vars(StateVarA, StateVarB),
+
+ ( if set_of_var.member(OutPrime, StateVarA) then
+ StateInputVar = StateVarA,
+ StateOutputVar = StateVarB
+ else
+ StateInputVar = StateVarB,
+ StateOutputVar = StateVarA
+ ),
+
+ create_new_var(StateInputVar, "Acc_", Acc0, !VarSet, !VarTypes),
+ create_new_var(StateOutputVar, "Acc_", Acc, !VarSet, !VarTypes),
+
+ map.det_insert(StateInputVar, Acc0, UpdateSubst0, UpdateSubst1),
+ map.det_insert(StateOutputVar, Acc, UpdateSubst1, UpdateSubst),
+ map.det_insert(StateInputVar, StateOutputVar, RecCallSubst0, RecCallSubst),
+ map.det_insert(Acc, Acc0, AccVarSubst0, AccVarSubst),
+ !:Substs = accu_substs(AccVarSubst, RecCallSubst, AssocCallSubst,
+ UpdateSubst),
+
+ accu_process_update_set(ModuleInfo, GS, Ids, OutPrime, !Substs,
+ !VarSet, !VarTypes, StateOutputVars0, Accs0, BasePairs0),
+
+ % Rather then concatenating to start of the list we concatenate to the end
+ % of the list. This allows the accumulator introduction to be applied
+ % as the heuristic will succeed (remember after transforming the two
+ % input variables will have their order swapped, so they must be in the
+ % inefficient order to start with)
+
+ StateOutputVars = StateOutputVars0 ++ [StateOutputVar],
+ Accs = Accs0 ++ [Acc],
+ BasePairs = BasePairs0 ++ [StateOutputVar - Acc0].
+
+%---------------------------------------------------------------------------%
+
+ % divide_base_case(UpdateOut, Out, U, A, O) is true iff given the output
+ % variables which are instantiated by update goals, UpdateOut, and all
+ % the variables that need to be accumulated, Out, divide the base case up
+ % into three sets, those base case goals which initialize the variables
+ % used by update calls, U, those which initialize variables used by
+ % assoc calls, A, and the rest of the goals, O. Note that the sets
+ % are not necessarily disjoint, as the result of a goal may be used
+ % to initialize a variable in both U and A, so both U and A will contain
+ % the same goal_id.
+ %
+:- pred accu_divide_base_case(module_info::in, vartypes::in,
+ accu_goal_store::in, list(prog_var)::in, list(prog_var)::in,
+ set(accu_goal_id)::out, set(accu_goal_id)::out, set(accu_goal_id)::out)
+ is det.
+
+accu_divide_base_case(ModuleInfo, VarTypes, C, UpdateOut, Out,
+ UpdateBase, AssocBase, OtherBase) :-
+ list.delete_elems(Out, UpdateOut, AssocOut),
+
+ list.map(accu_related(ModuleInfo, VarTypes, C), UpdateOut, UpdateBaseList),
+ list.map(accu_related(ModuleInfo, VarTypes, C), AssocOut, AssocBaseList),
+ UpdateBase = set.power_union(set.list_to_set(UpdateBaseList)),
+ AssocBase = set.power_union(set.list_to_set(AssocBaseList)),
+
+ Set = base_case_ids_set(C) `difference` (UpdateBase `union` AssocBase),
+ set.to_sorted_list(Set, List),
+
+ list.map(
+ ( pred(GoalId::in, Ancestors::out) is det :-
+ goal_store_all_ancestors(C, GoalId, VarTypes,
+ ModuleInfo, no, Ancestors)
+ ), List, OtherBaseList),
+
+ OtherBase = set.list_to_set(List) `union`
+ (base_case_ids_set(C) `intersect`
+ set.power_union(set.list_to_set(OtherBaseList))).
+
+ % accu_related(ModuleInfo, VarTypes, GoalStore, Var, Related):
+ %
+ % From GoalStore, return all the goal_ids, Related, which are needed
+ % to initialize Var.
+ %
+:- pred accu_related(module_info::in, vartypes::in, accu_goal_store::in,
+ prog_var::in, set(accu_goal_id)::out) is det.
+
+accu_related(ModuleInfo, VarTypes, GoalStore, Var, Related) :-
+ solutions.solutions(
+ ( pred(Key::out) is nondet :-
+ goal_store_member(GoalStore, Key, stored_goal(Goal, InstMap0)),
+ Key = accu_goal_id(accu_base, _),
+ Goal = hlds_goal(_GoalExpr, GoalInfo),
+ InstMapDelta = goal_info_get_instmap_delta(GoalInfo),
+ apply_instmap_delta(InstMapDelta, InstMap0, InstMap),
+ instmap_changed_vars(ModuleInfo, VarTypes,
+ InstMap0, InstMap, ChangedVars),
+ set_of_var.is_singleton(ChangedVars, Var)
+ ), Ids),
+ (
+ Ids = [],
+ unexpected($pred, "no Id")
+ ;
+ Ids = [Id],
+ goal_store_all_ancestors(GoalStore, Id, VarTypes, ModuleInfo, no,
+ Ancestors),
+ list.filter((pred(accu_goal_id(accu_base, _)::in) is semidet),
+ set.to_sorted_list(set.insert(Ancestors, Id)), RelatedList),
+ Related = set.list_to_set(RelatedList)
+ ;
+ Ids = [_, _ | _],
+ unexpected($pred, "more than one Id")
+ ).
+
+%---------------------------------------------------------------------------%
+
+:- inst stored_goal_plain_call for goal_store.stored_goal/0
+ ---> stored_goal(goal_plain_call, ground).
+
+ % Do a goal_store_lookup where the result is known to be a call.
+ %
+:- pred lookup_call(accu_goal_store::in, accu_goal_id::in,
+ stored_goal::out(stored_goal_plain_call)) is det.
+
+lookup_call(GoalStore, Id, stored_goal(Call, InstMap)) :-
+ goal_store_lookup(GoalStore, Id, stored_goal(Goal, InstMap)),
+ ( if
+ Goal = hlds_goal(GoalExpr, GoalInfo),
+ GoalExpr = plain_call(_, _, _, _, _, _)
+ then
+ Call = hlds_goal(GoalExpr, GoalInfo)
+ else
+ unexpected($pred, "not a call")
+ ).
+
+%---------------------------------------------------------------------------%
+%---------------------------------------------------------------------------%
+
+ % accu_stage3 creates the accumulator version of the predicate using
+ % the substitutions determined in stage2. It also redefines the
+ % original procedure to call the accumulator version of the procedure.
+ %
+:- pred accu_stage3(accu_goal_id::in, list(prog_var)::in, prog_varset::in,
+ vartypes::in, accu_goal_store::in, accu_goal_store::in,
+ accu_substs::in, accu_subst::in, accu_subst::in,
+ accu_base::in, list(pair(prog_var))::in, accu_sets::in,
+ list(prog_var)::in, top_level::in, pred_id::in, pred_info::in,
+ proc_info::in, proc_info::out, module_info::in, module_info::out) is det.
+
+accu_stage3(RecCallId, Accs, VarSet, VarTypes, C, CS, Substs,
+ HeadToCallSubst, CallToHeadSubst, BaseCase, BasePairs, Sets, Out,
+ TopLevel, OrigPredId, OrigPredInfo, !OrigProcInfo, !ModuleInfo) :-
+ acc_proc_info(Accs, VarSet, VarTypes, Substs, !.OrigProcInfo,
+ AccTypes, AccProcInfo),
+ acc_pred_info(AccTypes, Out, AccProcInfo, OrigPredId, OrigPredInfo,
+ AccProcId, AccPredInfo),
+ AccName = unqualified(pred_info_name(AccPredInfo)),
+
+ module_info_get_predicate_table(!.ModuleInfo, PredTable0),
+ predicate_table_insert(AccPredInfo, AccPredId, PredTable0, PredTable),
+ module_info_set_predicate_table(PredTable, !ModuleInfo),
+ accu_create_goal(RecCallId, Accs, AccPredId, AccProcId, AccName, Substs,
+ HeadToCallSubst, CallToHeadSubst, BaseCase, BasePairs, Sets, C, CS,
+ OrigBaseGoal, OrigRecGoal, AccBaseGoal, AccRecGoal),
+
+ proc_info_get_goal(!.OrigProcInfo, OrigGoal0),
+ accu_top_level(TopLevel, OrigGoal0, OrigBaseGoal, OrigRecGoal,
+ AccBaseGoal, AccRecGoal, OrigGoal, AccGoal),
+
+ proc_info_set_goal(OrigGoal, !OrigProcInfo),
+ proc_info_set_varset(VarSet, !OrigProcInfo),
+ proc_info_set_vartypes(VarTypes, !OrigProcInfo),
+
+ requantify_proc_general(ordinary_nonlocals_no_lambda, !OrigProcInfo),
+ update_accumulator_pred(AccPredId, AccProcId, AccGoal, !ModuleInfo).
+
+%---------------------------------------------------------------------------%
+
+ % Construct a proc_info for the introduced predicate.
+ %
+:- pred acc_proc_info(list(prog_var)::in, prog_varset::in, vartypes::in,
+ accu_substs::in, proc_info::in, list(mer_type)::out, proc_info::out)
+ is det.
+
+acc_proc_info(Accs0, VarSet, VarTypes, Substs, OrigProcInfo,
+ AccTypes, AccProcInfo) :-
+ % ProcInfo Stuff that must change.
+ proc_info_get_headvars(OrigProcInfo, HeadVars0),
+ proc_info_get_argmodes(OrigProcInfo, HeadModes0),
+
+ proc_info_get_inst_varset(OrigProcInfo, InstVarSet),
+ proc_info_get_inferred_determinism(OrigProcInfo, Detism),
+ proc_info_get_goal(OrigProcInfo, Goal),
+ proc_info_get_context(OrigProcInfo, Context),
+ proc_info_get_rtti_varmaps(OrigProcInfo, RttiVarMaps),
+ proc_info_get_is_address_taken(OrigProcInfo, IsAddressTaken),
+ proc_info_get_has_parallel_conj(OrigProcInfo, HasParallelConj),
+ proc_info_get_var_name_remap(OrigProcInfo, VarNameRemap),
+
+ Substs = accu_substs(AccVarSubst, _RecCallSubst, _AssocCallSubst,
+ _UpdateSubst),
+ list.map(map.lookup(AccVarSubst), Accs0, Accs),
+
+ % We place the extra accumulator variables at the start, because placing
+ % them at the end breaks the convention that the last variable of a
+ % function is the output variable.
+ HeadVars = Accs ++ HeadVars0,
+
+ % XXX we don't want to use the inst of the var as it can be more specific
+ % than it should be. ie int_const(1) when it should be any integer.
+ % However this will no longer handle partially instantiated data
+ % structures.
+ Inst = ground(shared, none_or_default_func),
+ inst_lists_to_mode_list([Inst], [Inst], Mode),
+ list.duplicate(list.length(Accs), list.det_head(Mode), AccModes),
+ HeadModes = AccModes ++ HeadModes0,
+
+ lookup_var_types(VarTypes, Accs, AccTypes),
+
+ SeqNum = item_no_seq_num,
+ proc_info_create(Context, SeqNum, VarSet, VarTypes, HeadVars,
+ InstVarSet, HeadModes, detism_decl_none, Detism, Goal, RttiVarMaps,
+ IsAddressTaken, HasParallelConj, VarNameRemap, AccProcInfo).
+
+%---------------------------------------------------------------------------%
+
+ % Construct the pred_info for the introduced predicate.
+ %
+:- pred acc_pred_info(list(mer_type)::in, list(prog_var)::in, proc_info::in,
+ pred_id::in, pred_info::in, proc_id::out, pred_info::out) is det.
+
+acc_pred_info(NewTypes, OutVars, NewProcInfo, OrigPredId, OrigPredInfo,
+ NewProcId, NewPredInfo) :-
+ % PredInfo stuff that must change.
+ pred_info_get_arg_types(OrigPredInfo, TypeVarSet, ExistQVars, Types0),
+
+ ModuleName = pred_info_module(OrigPredInfo),
+ Name = pred_info_name(OrigPredInfo),
+ PredOrFunc = pred_info_is_pred_or_func(OrigPredInfo),
+ pred_info_get_context(OrigPredInfo, PredContext),
+ pred_info_get_markers(OrigPredInfo, Markers),
+ pred_info_get_class_context(OrigPredInfo, ClassContext),
+ pred_info_get_origin(OrigPredInfo, OldOrigin),
+ pred_info_get_var_name_remap(OrigPredInfo, VarNameRemap),
+
+ set.init(Assertions),
+
+ proc_info_get_context(NewProcInfo, Context),
+ term.context_line(Context, Line),
+ Counter = 0,
+
+ Types = NewTypes ++ Types0,
+
+ make_pred_name_with_context(ModuleName, "AccFrom", PredOrFunc, Name,
+ Line, Counter, SymName),
+
+ OutVarNums = list.map(term.var_to_int, OutVars),
+ Origin = origin_transformed(transform_accumulator(OutVarNums),
+ OldOrigin, OrigPredId),
+ GoalType = goal_not_for_promise(np_goal_type_none),
+ pred_info_create(ModuleName, SymName, PredOrFunc, PredContext, Origin,
+ pred_status(status_local), Markers, Types, TypeVarSet,
+ ExistQVars, ClassContext, Assertions, VarNameRemap, GoalType,
+ NewProcInfo, NewProcId, NewPredInfo).
+
+%---------------------------------------------------------------------------%
+
+ % create_goal creates the new base and recursive case of the
+ % original procedure (OrigBaseGoal and OrigRecGoal) and the base
+ % and recursive cases of accumulator version (AccBaseGoal and
+ % AccRecGoal).
+ %
+:- pred accu_create_goal(accu_goal_id::in, list(prog_var)::in,
+ pred_id::in, proc_id::in, sym_name::in, accu_substs::in,
+ accu_subst::in, accu_subst::in, accu_base::in,
+ list(pair(prog_var))::in, accu_sets::in,
+ accu_goal_store::in, accu_goal_store::in,
+ hlds_goal::out, hlds_goal::out, hlds_goal::out, hlds_goal::out) is det.
+
+accu_create_goal(RecCallId, Accs, AccPredId, AccProcId, AccName, Substs,
+ HeadToCallSubst, CallToHeadSubst, BaseIds, BasePairs,
+ Sets, C, CS, OrigBaseGoal, OrigRecGoal, AccBaseGoal, AccRecGoal) :-
+ lookup_call(C, RecCallId, stored_goal(OrigCall, _InstMap)),
+ Call = create_acc_call(OrigCall, Accs, AccPredId, AccProcId, AccName),
+ create_orig_goal(Call, Substs, HeadToCallSubst, CallToHeadSubst,
+ BaseIds, Sets, C, OrigBaseGoal, OrigRecGoal),
+ create_acc_goal(Call, Substs, HeadToCallSubst, BaseIds, BasePairs,
+ Sets, C, CS, AccBaseGoal, AccRecGoal).
+
+ % create_acc_call takes the original call and generates a call to the
+ % accumulator version of the call, which can have the substitutions
+ % applied to it easily.
+ %
+:- func create_acc_call(hlds_goal::in(goal_plain_call), list(prog_var)::in,
+ pred_id::in, proc_id::in, sym_name::in) = (hlds_goal::out(goal_plain_call))
+ is det.
+
+create_acc_call(OrigCall, Accs, AccPredId, AccProcId, AccName) = Call :-
+ OrigCall = hlds_goal(OrigCallExpr, GoalInfo),
+ OrigCallExpr = plain_call(_PredId, _ProcId, Args, Builtin, Context, _Name),
+ CallExpr = plain_call(AccPredId, AccProcId, Accs ++ Args, Builtin,
+ Context, AccName),
+ Call = hlds_goal(CallExpr, GoalInfo).
+
+ % Create the goals which are to replace the original predicate.
+ %
+:- pred create_orig_goal(hlds_goal::in, accu_substs::in,
+ accu_subst::in, accu_subst::in, accu_base::in, accu_sets::in,
+ accu_goal_store::in, hlds_goal::out, hlds_goal::out) is det.
+
+create_orig_goal(Call, Substs, HeadToCallSubst, CallToHeadSubst,
+ BaseIds, Sets, C, OrigBaseGoal, OrigRecGoal) :-
+ Substs = accu_substs(_AccVarSubst, _RecCallSubst, _AssocCallSubst,
+ UpdateSubst),
+
+ BaseIds = accu_base(UpdateBase, _AssocBase, _OtherBase),
+ Before = Sets ^ as_before,
+ Update = Sets ^ as_update,
+
+ U = create_new_orig_recursive_goals(UpdateBase, Update,
+ HeadToCallSubst, UpdateSubst, C),
+
+ rename_some_vars_in_goal(CallToHeadSubst, Call, BaseCall),
+ Cbefore = accu_goal_list(set.to_sorted_list(Before), C),
+ Uupdate = accu_goal_list(set.to_sorted_list(UpdateBase) ++
+ set.to_sorted_list(Update), U),
+ Cbase = accu_goal_list(base_case_ids(C), C),
+ calculate_goal_info(conj(plain_conj, Cbefore ++ Uupdate ++ [BaseCall]),
+ OrigRecGoal),
+ calculate_goal_info(conj(plain_conj, Cbase), OrigBaseGoal).
+
+ % Create the goals which are to go in the new accumulator version
+ % of the predicate.
+ %
+:- pred create_acc_goal(hlds_goal::in, accu_substs::in, accu_subst::in,
+ accu_base::in, list(pair(prog_var))::in, accu_sets::in,
+ accu_goal_store::in, accu_goal_store::in,
+ hlds_goal::out, hlds_goal::out) is det.
+
+create_acc_goal(Call, Substs, HeadToCallSubst, BaseIds, BasePairs, Sets,
+ C, CS, AccBaseGoal, AccRecGoal) :-
+ Substs = accu_substs(AccVarSubst, RecCallSubst, AssocCallSubst,
+ UpdateSubst),
+
+ BaseIds = accu_base(_UpdateBase, AssocBase, OtherBase),
+ Sets = accu_sets(Before, Assoc, ConstructAssoc, Construct, Update,
+ _Reject),
+
+ rename_some_vars_in_goal(RecCallSubst, Call, RecCall),
+
+ Cbefore = accu_goal_list(set.to_sorted_list(Before), C),
+
+ % Create the goals which will be used in the new recursive case.
+ R = create_new_recursive_goals(Assoc, Construct `union` ConstructAssoc,
+ Update, AssocCallSubst, AccVarSubst, UpdateSubst, C, CS),
+
+ Rassoc = accu_goal_list(set.to_sorted_list(Assoc), R),
+ Rupdate = accu_goal_list(set.to_sorted_list(Update), R),
+ Rconstruct = accu_goal_list(set.to_sorted_list(Construct `union`
+ ConstructAssoc), R),
+
+ % Create the goals which will be used in the new base case.
+ B = create_new_base_goals(Assoc `union` Construct `union`
+ ConstructAssoc, C, AccVarSubst, HeadToCallSubst),
+ Bafter = set.to_sorted_list(Assoc `union`
+ Construct `union` ConstructAssoc),
+
+ BaseCase = accu_goal_list(set.to_sorted_list(AssocBase `union` OtherBase)
+ ++ Bafter, B),
+
+ list.map(acc_unification, BasePairs, UpdateBase),
+
+ calculate_goal_info(conj(plain_conj, Cbefore ++ Rassoc ++ Rupdate
+ ++ [RecCall] ++ Rconstruct), AccRecGoal),
+ calculate_goal_info(conj(plain_conj, UpdateBase ++ BaseCase), AccBaseGoal).
+
+ % Create the U set of goals (those that will be used in the original
+ % recursive case) by renaming all the goals which are used to initialize
+ % the update state variable using the head_to_call followed by the
+ % update_subst, and rename all the update goals using the update_subst.
+ %
+:- func create_new_orig_recursive_goals(set(accu_goal_id), set(accu_goal_id),
+ accu_subst, accu_subst, accu_goal_store) = accu_goal_store.
+
+create_new_orig_recursive_goals(UpdateBase, Update, HeadToCallSubst,
+ UpdateSubst, C)
+ = accu_rename(set.to_sorted_list(Update), UpdateSubst, C, Ubase) :-
+ Ubase = accu_rename(set.to_sorted_list(UpdateBase),
+ chain_subst(HeadToCallSubst, UpdateSubst), C, goal_store_init).
+
+ % Create the R set of goals (those that will be used in the new
+ % recursive case) by renaming all the members of assoc in CS
+ % using assoc_call_subst and all the members of (construct U
+ % construct_assoc) in C with acc_var_subst.
+ %
+:- func create_new_recursive_goals(set(accu_goal_id), set(accu_goal_id),
+ set(accu_goal_id), accu_subst, accu_subst, accu_subst,
+ accu_goal_store, accu_goal_store) = accu_goal_store.
+
+create_new_recursive_goals(Assoc, Constructs, Update,
+ AssocCallSubst, AccVarSubst, UpdateSubst, C, CS)
+ = accu_rename(set.to_sorted_list(Constructs), AccVarSubst, C, RBase) :-
+ RBase0 = accu_rename(set.to_sorted_list(Assoc), AssocCallSubst, CS,
+ goal_store_init),
+ RBase = accu_rename(set.to_sorted_list(Update), UpdateSubst, C, RBase0).
+
+ % Create the B set of goals (those that will be used in the new base case)
+ % by renaming all the base case goals of C with head_to_call and all the
+ % members of (assoc U construct U construct_assoc) of C with acc_var_subst.
+ %
+:- func create_new_base_goals(set(accu_goal_id), accu_goal_store,
+ accu_subst, accu_subst) = accu_goal_store.
+
+create_new_base_goals(Ids, C, AccVarSubst, HeadToCallSubst)
+ = accu_rename(set.to_sorted_list(Ids), AccVarSubst, C, Bbase) :-
+ Bbase = accu_rename(base_case_ids(C), HeadToCallSubst, C, goal_store_init).
+
+ % acc_unification(O-A, G):
+ %
+ % is true if G represents the assignment unification Out = Acc.
+ %
+:- pred acc_unification(pair(prog_var)::in, hlds_goal::out) is det.
+
+acc_unification(Out - Acc, Goal) :-
+ UnifyMode = unify_modes_li_lf_ri_rf(free, ground_inst,
+ ground_inst, ground_inst),
+ Context = unify_context(umc_explicit, []),
+ Expr = unify(Out, rhs_var(Acc), UnifyMode, assign(Out,Acc), Context),
+ set_of_var.list_to_set([Out, Acc], NonLocalVars),
+ InstMapDelta = instmap_delta_bind_var(Out),
+ goal_info_init(NonLocalVars, InstMapDelta, detism_det, purity_pure, Info),
+ Goal = hlds_goal(Expr, Info).
+
+%---------------------------------------------------------------------------%
+
+ % Given the top level structure of the goal create new version
+ % with new base and recursive cases plugged in.
+ %
+:- pred accu_top_level(top_level::in, hlds_goal::in,
+ hlds_goal::in, hlds_goal::in, hlds_goal::in,
+ hlds_goal::in, hlds_goal::out, hlds_goal::out) is det.
+
+accu_top_level(TopLevel, Goal, OrigBaseGoal, OrigRecGoal,
+ NewBaseGoal, NewRecGoal, OrigGoal, NewGoal) :-
+ (
+ TopLevel = switch_base_rec,
+ ( if
+ Goal = hlds_goal(switch(Var, CanFail, Cases0), GoalInfo),
+ Cases0 = [case(IdA, [], _), case(IdB, [], _)]
+ then
+ OrigCases = [case(IdA, [], OrigBaseGoal),
+ case(IdB, [], OrigRecGoal)],
+ OrigGoal = hlds_goal(switch(Var, CanFail, OrigCases), GoalInfo),
+
+ NewCases = [case(IdA, [], NewBaseGoal), case(IdB, [], NewRecGoal)],
+ NewGoal = hlds_goal(switch(Var, CanFail, NewCases), GoalInfo)
+ else
+ unexpected($pred, "not the correct top level")
+ )
+ ;
+ TopLevel = switch_rec_base,
+ ( if
+ Goal = hlds_goal(switch(Var, CanFail, Cases0), GoalInfo),
+ Cases0 = [case(IdA, [], _), case(IdB, [], _)]
+ then
+ OrigCases = [case(IdA, [], OrigRecGoal),
+ case(IdB, [], OrigBaseGoal)],
+ OrigGoal = hlds_goal(switch(Var, CanFail, OrigCases), GoalInfo),
+
+ NewCases = [case(IdA, [], NewRecGoal), case(IdB, [], NewBaseGoal)],
+ NewGoal = hlds_goal(switch(Var, CanFail, NewCases), GoalInfo)
+ else
+ unexpected($pred, "not the correct top level")
+ )
+ ;
+ TopLevel = disj_base_rec,
+ ( if
+ Goal = hlds_goal(disj(Goals), GoalInfo),
+ Goals = [_, _]
+ then
+ OrigGoals = [OrigBaseGoal, OrigRecGoal],
+ OrigGoal = hlds_goal(disj(OrigGoals), GoalInfo),
+
+ NewGoals = [NewBaseGoal, NewRecGoal],
+ NewGoal = hlds_goal(disj(NewGoals), GoalInfo)
+ else
+ unexpected($pred, "not the correct top level")
+ )
+ ;
+ TopLevel = disj_rec_base,
+ ( if
+ Goal = hlds_goal(disj(Goals), GoalInfo),
+ Goals = [_, _]
+ then
+ OrigGoals = [OrigRecGoal, OrigBaseGoal],
+ OrigGoal = hlds_goal(disj(OrigGoals), GoalInfo),
+
+ NewGoals = [NewRecGoal, NewBaseGoal],
+ NewGoal = hlds_goal(disj(NewGoals), GoalInfo)
+ else
+ unexpected($pred, "not the correct top level")
+ )
+ ;
+ TopLevel = ite_base_rec,
+ ( if Goal = hlds_goal(if_then_else(Vars, Cond, _, _), GoalInfo) then
+ OrigGoal = hlds_goal(if_then_else(Vars, Cond,
+ OrigBaseGoal, OrigRecGoal), GoalInfo),
+ NewGoal = hlds_goal(if_then_else(Vars, Cond,
+ NewBaseGoal, NewRecGoal), GoalInfo)
+ else
+ unexpected($pred, "not the correct top level")
+ )
+ ;
+ TopLevel = ite_rec_base,
+ ( if Goal = hlds_goal(if_then_else(Vars, Cond, _, _), GoalInfo) then
+ OrigGoal = hlds_goal(if_then_else(Vars, Cond,
+ OrigRecGoal, OrigBaseGoal), GoalInfo),
+ NewGoal = hlds_goal(if_then_else(Vars, Cond,
+ NewRecGoal, NewBaseGoal), GoalInfo)
+ else
+ unexpected($pred, "not the correct top level")
+ )
+ ).
+
+%---------------------------------------------------------------------------%
+
+ % Place the accumulator version of the predicate in the HLDS.
+ %
+:- pred update_accumulator_pred(pred_id::in, proc_id::in,
+ hlds_goal::in, module_info::in, module_info::out) is det.
+
+update_accumulator_pred(NewPredId, NewProcId, AccGoal, !ModuleInfo) :-
+ module_info_pred_proc_info(!.ModuleInfo, NewPredId, NewProcId,
+ PredInfo, ProcInfo0),
+ proc_info_set_goal(AccGoal, ProcInfo0, ProcInfo1),
+ requantify_proc_general(ordinary_nonlocals_no_lambda, ProcInfo1, ProcInfo),
+ module_info_set_pred_proc_info(NewPredId, NewProcId,
+ PredInfo, ProcInfo, !ModuleInfo).
+
+%---------------------------------------------------------------------------%
+%---------------------------------------------------------------------------%
+
+ % accu_rename(Ids, Subst, From, Initial):
+ %
+ % Return a goal_store, Final, which is the result of looking up each
+ % member of set of goal_ids, Ids, in the goal_store, From, applying
+ % the substitution and then storing the goal into the goal_store, Initial.
+ %
+:- func accu_rename(list(accu_goal_id), accu_subst,
+ accu_goal_store, accu_goal_store) = accu_goal_store.
+
+accu_rename(Ids, Subst, From, Initial) = Final :-
+ list.foldl(
+ ( pred(Id::in, GS0::in, GS::out) is det :-
+ goal_store_lookup(From, Id, stored_goal(Goal0, InstMap)),
+ rename_some_vars_in_goal(Subst, Goal0, Goal),
+ goal_store_det_insert(Id, stored_goal(Goal, InstMap), GS0, GS)
+ ), Ids, Initial, Final).
+
+ % Return all the goal_ids which belong in the base case.
+ %
+:- func base_case_ids(accu_goal_store) = list(accu_goal_id).
+
+base_case_ids(GS) = Base :-
+ solutions.solutions(
+ ( pred(Key::out) is nondet :-
+ goal_store_member(GS, Key, _Goal),
+ Key = accu_goal_id(accu_base, _)
+ ), Base).
+
+:- func base_case_ids_set(accu_goal_store) = set(accu_goal_id).
+
+base_case_ids_set(GS) = set.list_to_set(base_case_ids(GS)).
+
+ % Given a list of goal_ids, return the list of hlds_goals from
+ % the goal_store.
+ %
+:- func accu_goal_list(list(accu_goal_id), accu_goal_store) = list(hlds_goal).
+
+accu_goal_list(Ids, GS) = Goals :-
+ list.map(
+ ( pred(Key::in, G::out) is det :-
+ goal_store_lookup(GS, Key, stored_goal(G, _))
+ ), Ids, Goals).
+
+%---------------------------------------------------------------------------%
+%---------------------------------------------------------------------------%
+
+:- pred calculate_goal_info(hlds_goal_expr::in, hlds_goal::out) is det.
+
+calculate_goal_info(GoalExpr, hlds_goal(GoalExpr, GoalInfo)) :-
+ ( if GoalExpr = conj(plain_conj, GoalList) then
+ goal_list_nonlocals(GoalList, NonLocals),
+ goal_list_instmap_delta(GoalList, InstMapDelta),
+ goal_list_determinism(GoalList, Detism),
+
+ goal_info_init(NonLocals, InstMapDelta, Detism, purity_pure, GoalInfo)
+ else
+ unexpected($pred, "not a conj")
+ ).
+
+%---------------------------------------------------------------------------%
+%---------------------------------------------------------------------------%
+
+:- func chain_subst(accu_subst, accu_subst) = accu_subst.
+
+chain_subst(AtoB, BtoC) = AtoC :-
+ map.keys(AtoB, Keys),
+ chain_subst_2(Keys, AtoB, BtoC, AtoC).
+
+:- pred chain_subst_2(list(A)::in, map(A, B)::in, map(B, C)::in,
+ map(A, C)::out) is det.
+
+chain_subst_2([], _, _, AtoC) :-
+ map.init(AtoC).
+chain_subst_2([A | As], AtoB, BtoC, AtoC) :-
+ chain_subst_2(As, AtoB, BtoC, AtoC0),
+ map.lookup(AtoB, A, B),
+ ( if map.search(BtoC, B, C) then
+ map.det_insert(A, C, AtoC0, AtoC)
+ else
+ AtoC = AtoC0
+ ).
+
+%---------------------------------------------------------------------------%
+:- end_module transform_hlds.accumulator.
+%---------------------------------------------------------------------------%
+
+:- some [T] pred unravel_univ(univ::in, T::out) is det.
+:- pragma foreign_export("C", unravel_univ(in, out), "ML_unravel_univ").
+:- pragma foreign_export("C#", unravel_univ(in, out), "ML_unravel_univ").
+:- pragma foreign_export("Java", unravel_univ(in, out), "ML_unravel_univ").
+
+unravel_univ(Univ, X) :-
+ univ_value(Univ) = X.
diff --git a/test/manual/etags/perl-src/htlmify-cystic b/test/manual/etags/perl-src/htlmify-cystic
index de150a72b8f..d24103015aa 100644
--- a/test/manual/etags/perl-src/htlmify-cystic
+++ b/test/manual/etags/perl-src/htlmify-cystic
@@ -1,4 +1,4 @@
-#! /uns/bin/perl -w
+#! /un/bin/env perl
# htmlify-cystic-l-faq: turn text version of cystic-l faq into html
# run like this: htmlify-cystic-l-faq < cystic-l-faq-all
diff --git a/test/manual/etags/prol-src/natded.prolog b/test/manual/etags/prol-src/natded.prolog
index f0ee6b41b12..08c81d48f61 100644
--- a/test/manual/etags/prol-src/natded.prolog
+++ b/test/manual/etags/prol-src/natded.prolog
@@ -371,7 +371,7 @@ derived_analyses([W|Ws],[W|DerWs]):-
% build(Ws:+<list(<word>)>, Right:+<int>, Left:-<int>)
% ----------------------------------------------------------------------
-% finishes building chart with Ws as remaing word, starting from
+% finishes building chart with Ws as remaining word, starting from
% right position Right and finishing on left position Left
% -- counts backwards, so Left > Right
% ----------------------------------------------------------------------
diff --git a/test/manual/etags/prol-src/ordsets.prolog b/test/manual/etags/prol-src/ordsets.prolog
index 7192129fdce..0fa70f903f0 100644
--- a/test/manual/etags/prol-src/ordsets.prolog
+++ b/test/manual/etags/prol-src/ordsets.prolog
@@ -120,7 +120,7 @@ ord_intersect(>, Head1, Tail1, _, [Head2|Tail2]) :-
% ord_intersection(+Set1, +Set2, ?Intersection)
-% is true when Intersection is the intersecton of Set1
+% is true when Intersection is the intersection of Set1
% and Set2, provided that Set1 and Set2 are ordered sets.
ord_intersection([], _, []).
@@ -144,7 +144,7 @@ ord_intersection3([Head2|Tail2], Head1, Tail1, Intersection) :-
% ord_intersection(+Set1, +Set2, ?Intersection, ?Difference)
% is true when Intersection is the intersection of Set1 and Set2,
-% and Differens is Set2 \ Set1 (like in ord_union/4),
+% and Difference is Set2 \ Set1 (like in ord_union/4),
% provided that Set1 and Set2 are ordered sets.
ord_intersection([], Set2, [], Set2).
diff --git a/test/manual/etags/rs-src/test.rs b/test/manual/etags/rs-src/test.rs
new file mode 100644
index 00000000000..081d0d7d4df
--- /dev/null
+++ b/test/manual/etags/rs-src/test.rs
@@ -0,0 +1,14 @@
+mod test;
+
+enum IpAddrKind {
+ V4,
+ V6,
+}
+
+fn test1() {
+ println!("Testing");
+}
+
+fn main() {
+ test::test1();
+}
diff --git a/test/manual/etags/tex-src/gzip.texi b/test/manual/etags/tex-src/gzip.texi
index ea5f7f5879e..72c5c7e93b6 100644
--- a/test/manual/etags/tex-src/gzip.texi
+++ b/test/manual/etags/tex-src/gzip.texi
@@ -148,7 +148,7 @@ input and writes the uncompressed data on standard output. @code{zcat}
will uncompress files that have the correct magic number whether they
have a @samp{.gz} suffix or not.
-@code{gzip} uses the Lempel-Ziv algorithm used in @code{zip} and PKZIP.
+@code{gzip} uses the Lempel-Ziv algorithm used in @code{zip} and PKZIP@.
The amount of compression obtained depends on the size of the input and
the distribution of common substrings. Typically, text such as source
code or English is reduced by 60-70%. Compression is generally much
diff --git a/test/manual/etags/tex-src/texinfo.tex b/test/manual/etags/tex-src/texinfo.tex
index e98f24cda69..e0de6afe96e 100644
--- a/test/manual/etags/tex-src/texinfo.tex
+++ b/test/manual/etags/tex-src/texinfo.tex
@@ -1,6 +1,6 @@
%% TeX macros to handle texinfo files
-% Copyright (C) 1985-1986, 1988, 1990-1991, 2016-2017 Free Software
+% Copyright (C) 1985--1986, 1988, 1990--1991, 2016--2022 Free Software
% Foundation, Inc.
%This texinfo.tex file is free software; you can redistribute it and/or
@@ -1074,7 +1074,7 @@ July\or August\or September\or October\or November\or December\fi
\def\tablez #1#2#3#4#5#6{%
\aboveenvbreak %
\begingroup %
-\def\Edescription{\Etable}% Neccessary kludge.
+\def\Edescription{\Etable}% Necessary kludge.
\let\itemindex=#1%
\ifnum 0#3>0 \advance \leftskip by #3\mil \fi %
\ifnum 0#4>0 \tableindent=#4\mil \fi %
@@ -2937,7 +2937,7 @@ July\or August\or September\or October\or November\or December\fi
\setbox0=\hbox{\printednodename}%
\ifdim \wd0=0pt%
\def\printednodename{\ignorespaces #1}%
-%%% Uncommment the following line to make the actual chapter or section title
+%%% Uncomment the following line to make the actual chapter or section title
%%% appear inside the square brackets.
%\def\printednodename{#1-title}%
\fi%
diff --git a/test/manual/etags/y-src/cccp.c b/test/manual/etags/y-src/cccp.c
index 380243c6fa4..264adfae663 100644
--- a/test/manual/etags/y-src/cccp.c
+++ b/test/manual/etags/y-src/cccp.c
@@ -320,7 +320,7 @@ static const short yycheck[] =
#line 3 "/usr/share/bison/bison.simple"
/* Skeleton output parser for bison,
- Copyright (C) 1984, 1989-1990, 2000-2001, 2016-2017 Free Software
+ Copyright (C) 1984, 1989-1990, 2000-2001, 2016-2022 Free Software
Foundation, Inc.
This program is free software; you can redistribute it and/or modify
diff --git a/test/manual/etags/y-src/parse.c b/test/manual/etags/y-src/parse.c
index f8d836e649d..61794f713ed 100644
--- a/test/manual/etags/y-src/parse.c
+++ b/test/manual/etags/y-src/parse.c
@@ -28,7 +28,7 @@
#line 1 "y-src/parse.y"
-/* Copyright (C) 1990, 1992-1993, 2016-2017 Free Software Foundation,
+/* Copyright (C) 1990, 1992-1993, 2016-2022 Free Software Foundation,
* Inc.
This file is part of Oleo, the GNU Spreadsheet.
@@ -1917,7 +1917,7 @@ yylex FUN0()
}
#ifdef TEST
if(nn==n_usr_funs) {
- io_error_msg("Couln't turn fp into a ##");
+ io_error_msg("Couldn't turn fp into a ##");
parse_error=BAD_FUNC;
return ERROR;
}
diff --git a/test/manual/etags/y-src/parse.y b/test/manual/etags/y-src/parse.y
index b40847dd559..0bfa92b6303 100644
--- a/test/manual/etags/y-src/parse.y
+++ b/test/manual/etags/y-src/parse.y
@@ -1,5 +1,5 @@
%{
-/* Copyright (C) 1990, 1992-1993, 2016-2017 Free Software Foundation,
+/* Copyright (C) 1990, 1992-1993, 2016-2022 Free Software Foundation,
* Inc.
This file is part of Oleo, the GNU Spreadsheet.
@@ -556,7 +556,7 @@ yylex FUN0()
}
#ifdef TEST
if(nn==n_usr_funs) {
- io_error_msg("Couln't turn fp into a ##");
+ io_error_msg("Couldn't turn fp into a ##");
parse_error=BAD_FUNC;
return ERROR;
}
diff --git a/test/manual/image-circular-tests.el b/test/manual/image-circular-tests.el
new file mode 100644
index 00000000000..1299970f827
--- /dev/null
+++ b/test/manual/image-circular-tests.el
@@ -0,0 +1,68 @@
+;;; image-circular-tests.el --- test image functions with circular objects -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2019, 2021-2022 Free Software Foundation, Inc.
+
+;; Author: Pip Cet <pipcet@gmail.com>
+;; Keywords: internal
+;; Human-Keywords: internal
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+
+(ert-deftest image-test-duplicate-keywords ()
+ "Test that duplicate keywords in an image spec lead to rejection."
+ (should-error (image-size `(image :type xbm :type xbm
+ :data-width 1 :data-height 1
+ :data ,(bool-vector t))
+ t)))
+
+(ert-deftest image-test-circular-plist ()
+ "Test that a circular image spec is rejected."
+ (should-error
+ (let ((l `(image :type xbm :data-width 1 :data-height 1
+ :data ,(bool-vector t))))
+ (setcdr (last l) '#1=(:invalid . #1#))
+ (image-size l t))))
+
+(ert-deftest image-test-:type-property-value ()
+ "Test that :type is allowed as a property value in an image spec."
+ (should (equal (image-size `(image :dummy :type :type xbm
+ :data-width 1 :data-height 1
+ :data ,(bool-vector t))
+ t)
+ (cons 1 1))))
+
+(ert-deftest image-test-circular-specs ()
+ "Test that circular image spec property values do not cause infinite recursion."
+ (should
+ (let* ((circ1 (cons :dummy nil))
+ (circ2 (cons :dummy nil))
+ (spec1 `(image :type xbm :data-width 1 :data-height 1
+ :data ,(bool-vector 1) :ignored ,circ1))
+ (spec2 `(image :type xbm :data-width 1 :data-height 1
+ :data ,(bool-vector 1) :ignored ,circ2)))
+ (setcdr circ1 circ1)
+ (setcdr circ2 circ2)
+ (and (equal (image-size spec1 t) (cons 1 1))
+ (equal (image-size spec2 t) (cons 1 1))))))
+
+(provide 'image-circular-tests)
+;;; image-circular-tests.el ends here.
diff --git a/test/manual/image-size-tests.el b/test/manual/image-size-tests.el
index 509623b8176..ea7af889431 100644
--- a/test/manual/image-size-tests.el
+++ b/test/manual/image-size-tests.el
@@ -1,21 +1,23 @@
-;;; image-size-tests.el -- tests for image scaling
+;;; image-size-tests.el --- tests for image scaling -*- lexical-binding: t; -*-
-;; Copyright (C) 2017 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2022 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
-;; This program is free software; you can redistribute it and/or modify
+;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
-;; This program is distributed in the hope that it will be useful,
+;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
-;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
;; To test: Load the file and eval (image-size-tests).
;; A non-erroring result is a success.
@@ -45,7 +47,8 @@
(= (cdr size) height))))
(defun image-size-tests ()
- (unless (imagemagick-types)
+ (unless (and (fboundp 'imagemagick-types)
+ (imagemagick-types))
(error "This only makes sense if ImageMagick is installed"))
;; Test the image that's wider than it is tall.
;; Default sizes.
diff --git a/test/manual/image-tests.el b/test/manual/image-tests.el
new file mode 100644
index 00000000000..400657132c7
--- /dev/null
+++ b/test/manual/image-tests.el
@@ -0,0 +1,288 @@
+;;; image-tests.el --- tests for image.c -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+;; Author: Stefan Kangas <stefankangas@gmail.com>
+;; Keywords: internal
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; These tests will only run in a GUI session. You must run them
+;; manually in an interactive session with, for example, `M-x
+;; eval-buffer' followed by `M-x ert'.
+;;
+;; To run them from the command line instead, try:
+;; ./src/emacs -Q -l test/manual/image-tests.el -eval "(ert t)"
+
+;;; Code:
+
+(defmacro image-skip-unless (format &rest condition)
+ `(skip-unless (and (and (display-images-p)
+ (image-type-available-p ,format))
+ ,@condition)))
+
+(defconst image-tests--images
+ `((gif . ,(expand-file-name "test/data/image/black.gif"
+ source-directory))
+ (jpeg . ,(expand-file-name "test/data/image/black.jpg"
+ source-directory))
+ (pbm . ,(find-image '((:file "splash.svg" :type svg))))
+ (png . ,(find-image '((:file "splash.png" :type png))))
+ (svg . ,(find-image '((:file "splash.pbm" :type pbm))))
+ (tiff . ,(expand-file-name
+ "nextstep/GNUstep/Emacs.base/Resources/emacs.tiff"
+ source-directory))
+ (webp . ,(expand-file-name "test/data/image/black.webp"
+ source-directory))
+ (xbm . ,(find-image '((:file "gnus/gnus.xbm" :type xbm))))
+ (xpm . ,(find-image '((:file "splash.xpm" :type xpm))))))
+
+
+;;;; Load image
+
+(defmacro image-tests-make-load-image-test (type)
+ `(ert-deftest ,(intern (format "image-tests-load-image/%s"
+ (eval type t)))
+ ()
+ (image-skip-unless ,type)
+ (let* ((img (cdr (assq ,type image-tests--images)))
+ (file (if (listp img)
+ (plist-get (cdr img) :file)
+ img)))
+ (find-file file))
+ (should (equal major-mode 'image-mode))
+ ;; Cleanup
+ (kill-buffer (current-buffer))))
+
+(image-tests-make-load-image-test 'gif)
+(image-tests-make-load-image-test 'jpeg)
+(image-tests-make-load-image-test 'pbm)
+(image-tests-make-load-image-test 'png)
+(image-tests-make-load-image-test 'svg)
+(image-tests-make-load-image-test 'tiff)
+(image-tests-make-load-image-test 'webp)
+(image-tests-make-load-image-test 'xbm)
+(image-tests-make-load-image-test 'xpm)
+
+(ert-deftest image-tests-load-image/svg-too-big ()
+ (with-temp-buffer
+ (let* ((max-image-size 0)
+ (messages-buffer-name (buffer-name (current-buffer)))
+ (img (cdr (assq 'svg image-tests--images)))
+ (file (if (listp img)
+ (plist-get (cdr img) :file)
+ img)))
+ (save-excursion (find-file file))
+ (should (string-match-p "invalid image size" (buffer-string)))
+ ;; no annoying newlines
+ (should-not (string-match-p "^[ \t\n\r]+$" (buffer-string)))
+ ;; no annoying double error reporting
+ (should-not (string-match-p "error parsing" (buffer-string))))))
+
+(ert-deftest image-tests-load-image/svg-invalid ()
+ (with-temp-buffer
+ (let ((messages-buffer-name (buffer-name (current-buffer))))
+ (with-temp-buffer
+ (pop-to-buffer (current-buffer))
+ (insert (propertize " "
+ 'display '(image :data
+ "invalid foo bar"
+ :type svg)))
+ (redisplay))
+ ;; librsvg error: "... Start tag expected, '<' not found [3 times]"
+ (should (string-match-p "[Ee]rror.+Start tag expected" (buffer-string)))
+ ;; no annoying newlines
+ (should-not (string-match-p "^[ \t\n\r]+$" (buffer-string))))))
+
+
+;;;; image-test-size
+
+(declare-function image-size "image.c" (spec &optional pixels frame))
+
+(ert-deftest image-tests-image-size/gif ()
+ (image-skip-unless 'gif)
+ (pcase (image-size (create-image (cdr (assq 'gif image-tests--images))))
+ (`(,a . ,b)
+ (should (floatp a))
+ (should (floatp b)))))
+
+(ert-deftest image-tests-image-size/jpeg ()
+ (image-skip-unless 'jpeg)
+ (pcase (image-size (create-image (cdr (assq 'jpeg image-tests--images))))
+ (`(,a . ,b)
+ (should (floatp a))
+ (should (floatp b)))))
+
+(ert-deftest image-tests-image-size/pbm ()
+ (image-skip-unless 'pbm)
+ (pcase (image-size (cdr (assq 'pbm image-tests--images)))
+ (`(,a . ,b)
+ (should (floatp a))
+ (should (floatp b)))))
+
+(ert-deftest image-tests-image-size/png ()
+ (image-skip-unless 'png)
+ (pcase (image-size (cdr (assq 'png image-tests--images)))
+ (`(,a . ,b)
+ (should (floatp a))
+ (should (floatp b)))))
+
+(ert-deftest image-tests-image-size/svg ()
+ (image-skip-unless 'svg)
+ (pcase (image-size (cdr (assq 'svg image-tests--images)))
+ (`(,a . ,b)
+ (should (floatp a))
+ (should (floatp b)))))
+
+(ert-deftest image-tests-image-size/tiff ()
+ (image-skip-unless 'tiff)
+ (pcase (image-size (create-image (cdr (assq 'tiff image-tests--images))))
+ (`(,a . ,b)
+ (should (floatp a))
+ (should (floatp b)))))
+
+(ert-deftest image-tests-image-size/webp ()
+ (image-skip-unless 'webp)
+ (pcase (image-size (create-image (cdr (assq 'webp image-tests--images))))
+ (`(,a . ,b)
+ (should (floatp a))
+ (should (floatp b)))))
+
+(ert-deftest image-tests-image-size/xbm ()
+ (image-skip-unless 'xbm)
+ (pcase (image-size (cdr (assq 'xbm image-tests--images)))
+ (`(,a . ,b)
+ (should (floatp a))
+ (should (floatp b)))))
+
+(ert-deftest image-tests-image-size/xpm ()
+ (image-skip-unless 'xpm)
+ (pcase (image-size (cdr (assq 'xpm image-tests--images)))
+ (`(,a . ,b)
+ (should (floatp a))
+ (should (floatp b)))))
+
+(ert-deftest image-tests-image-size/error-on-invalid-spec ()
+ (skip-unless (display-images-p))
+ (should-error (image-size 'invalid-spec)))
+
+
+;;;; image-mask-p
+
+(declare-function image-mask-p "image.c" (spec &optional frame))
+
+(ert-deftest image-tests-image-mask-p/gif ()
+ (image-skip-unless 'gif)
+ (should-not (image-mask-p (create-image
+ (cdr (assq 'gif image-tests--images))))))
+
+(ert-deftest image-tests-image-mask-p/jpeg ()
+ (image-skip-unless 'jpeg)
+ (should-not (image-mask-p (create-image
+ (cdr (assq 'jpeg image-tests--images))))))
+
+(ert-deftest image-tests-image-mask-p/pbm ()
+ (image-skip-unless 'pbm)
+ (should-not (image-mask-p (cdr (assq 'pbm image-tests--images)))))
+
+(ert-deftest image-tests-image-mask-p/png ()
+ (image-skip-unless 'png)
+ (should-not (image-mask-p (cdr (assq 'png image-tests--images)))))
+
+(ert-deftest image-tests-image-mask-p/svg ()
+ (image-skip-unless 'svg)
+ (should-not (image-mask-p (cdr (assq 'svg image-tests--images)))))
+
+(ert-deftest image-tests-image-mask-p/tiff ()
+ (image-skip-unless 'tiff)
+ (should-not (image-mask-p (create-image
+ (cdr (assq 'tiff image-tests--images))))))
+
+(ert-deftest image-tests-image-mask-p/webp ()
+ (image-skip-unless 'webp)
+ (should-not (image-mask-p (create-image
+ (cdr (assq 'webp image-tests--images))))))
+
+(ert-deftest image-tests-image-mask-p/xbm ()
+ (image-skip-unless 'xbm)
+ (should-not (image-mask-p (cdr (assq 'xbm image-tests--images)))))
+
+(ert-deftest image-tests-image-mask-p/xpm ()
+ (image-skip-unless 'xpm)
+ (should-not (image-mask-p (cdr (assq 'xpm image-tests--images)))))
+
+(ert-deftest image-tests-image-mask-p/error-on-invalid-spec ()
+ (skip-unless (display-images-p))
+ (should-error (image-mask-p 'invalid-spec)))
+
+
+;;;; image-metadata
+
+(declare-function image-metadata "image.c" (spec &optional frame))
+
+;; TODO: These tests could be expanded with files that actually
+;; contain metadata.
+
+(ert-deftest image-tests-image-metadata/gif ()
+ (image-skip-unless 'gif
+ (not (bound-and-true-p w32-use-native-image-API)))
+ (should (memq 'delay
+ (image-metadata
+ (create-image (cdr (assq 'gif image-tests--images)))))))
+
+(ert-deftest image-tests-image-metadata/jpeg ()
+ (image-skip-unless 'jpeg)
+ (should-not (image-metadata
+ (create-image (cdr (assq 'jpeg image-tests--images))))))
+
+(ert-deftest image-tests-image-metadata/pbm ()
+ (image-skip-unless 'pbm)
+ (should-not (image-metadata (cdr (assq 'pbm image-tests--images)))))
+
+(ert-deftest image-tests-image-metadata/png ()
+ (image-skip-unless 'png)
+ (should-not (image-metadata (cdr (assq 'png image-tests--images)))))
+
+(ert-deftest image-tests-image-metadata/svg ()
+ (image-skip-unless 'svg)
+ (should-not (image-metadata (cdr (assq 'svg image-tests--images)))))
+
+(ert-deftest image-tests-image-metadata/tiff ()
+ (image-skip-unless 'tiff)
+ (should-not (image-metadata
+ (create-image (cdr (assq 'tiff image-tests--images))))))
+
+(ert-deftest image-tests-image-metadata/webp ()
+ (image-skip-unless 'webp)
+ (should (memq 'delay
+ (image-metadata
+ (create-image (cdr (assq 'webp image-tests--images)))))))
+
+(ert-deftest image-tests-image-metadata/xbm ()
+ (image-skip-unless 'xbm)
+ (should-not (image-metadata (cdr (assq 'xbm image-tests--images)))))
+
+(ert-deftest image-tests-image-metadata/xpm ()
+ (image-skip-unless 'xpm)
+ (should-not (image-metadata (cdr (assq 'xpm image-tests--images)))))
+
+(ert-deftest image-tests-image-metadata/nil-on-invalid-spec ()
+ (skip-unless (display-images-p))
+ (should-not (image-metadata 'invalid-spec)))
+
+;;; image-size-tests.el ends here
diff --git a/test/manual/image-transforms-tests.el b/test/manual/image-transforms-tests.el
new file mode 100644
index 00000000000..2f03073ab74
--- /dev/null
+++ b/test/manual/image-transforms-tests.el
@@ -0,0 +1,178 @@
+;;; image-transforms-tests.el --- Test suite for image transforms. -*- lexical-binding: t -*-
+
+;; Copyright (C) 2019-2022 Free Software Foundation, Inc.
+
+;; Author: Alan Third <alan@idiocy.org>
+;; Keywords: internal
+;; Human-Keywords: internal
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Type M-x test-transforms RET to generate the test buffer.
+
+;;; Code:
+
+(defun test-rotation ()
+ (let ((up "<svg height='9' width='9'><polygon points='0,8 4,0 8,8'/></svg>")
+ (down "<svg height='9' width='9'><polygon points='0,0 4,8 8,0'/></svg>")
+ (left "<svg height='9' width='9'><polygon points='8,0 0,4 8,8'/></svg>")
+ (right "<svg height='9' width='9'><polygon points='0,0 8,4 0,8'/></svg>"))
+ (insert-header "Test Rotation: rotating an image")
+ (insert-test "0" up up '(:rotation 0))
+ (insert-test "360" up up '(:rotation 360))
+ (insert-test "180" down up '(:rotation 180))
+ (insert-test "-90" left up '(:rotation -90))
+ (insert-test "90" right up '(:rotation 90))
+ (insert-test "90.0" right up '(:rotation 90.0))
+
+ ;; This should log a message and display the unrotated image.
+ (insert-test "45" up up '(:rotation 45)))
+ (insert "\n\n"))
+
+(defun test-cropping ()
+ (let ((image "<svg height='30' width='30'>
+ <rect x='0' y='0' width='10' height='10'/>
+ <rect x='10' y='10' width='10' height='10'
+ style='fill:none;stroke-width:1;stroke:currentColor'/>
+ <line x1='10' y1='10' x2='20' y2='20' style='stroke:currentColor'/>
+ <line x1='20' y1='10' x2='10' y2='20' style='stroke:currentColor'/>
+ <rect x='20' y='20' width='10' height='10'
+ style='fill:none;stroke-width:1;stroke:currentColor'/>
+ </svg>")
+ (top-left "<svg height='10' width='10'>
+ <rect x='0' y='0' width='10' height='10'/>
+ </svg>")
+ (middle "<svg height='10' width='10'>
+ <rect x='0' y='0' width='10' height='10'
+ style='fill:none;stroke-width:1;stroke:currentColor'/>
+ <line x1='0' y1='0' x2='10' y2='10' style='stroke:currentColor'/>
+ <line x1='10' y1='0' x2='0' y2='10' style='stroke:currentColor'/>
+ </svg>")
+ (bottom-right "<svg height='10' width='10'>
+ <rect x='0' y='0' width='10' height='10'
+ style='fill:none;stroke-width:1;stroke:currentColor'/>
+ </svg>"))
+ (insert-header "Test Crop: cropping an image (only works with ImageMagick)")
+ (insert-test "all params" top-left image '(:crop (10 10 0 0)))
+ (insert-test "width/height only" middle image '(:crop (10 10)))
+ (insert-test "negative x y" middle image '(:crop (10 10 -10 -10)))
+ (insert-test "all params" bottom-right image '(:crop (10 10 20 20))))
+ (insert "\n\n"))
+
+(defun test-scaling ()
+ (let ((image "<svg height='10' width='10'>
+ <rect x='0' y='0' width='10' height='10'
+ style='fill:none;stroke-width:1;stroke:currentColor'/>
+ <line x1='0' y1='0' x2='10' y2='10' style='stroke:currentColor'/>
+ <line x1='10' y1='0' x2='0' y2='10' style='stroke:currentColor'/>
+ </svg>")
+ (large "<svg height='20' width='20'>
+ <rect x='0' y='0' width='20' height='20'
+ style='fill:none;stroke-width:2;stroke:currentColor'/>
+ <line x1='0' y1='0' x2='20' y2='20'
+ style='stroke-width:2;stroke:currentColor'/>
+ <line x1='20' y1='0' x2='0' y2='20'
+ style='stroke-width:2;stroke:currentColor'/>
+ </svg>")
+ (small "<svg height='5' width='5'>
+ <rect x='0' y='0' width='4' height='4'
+ style='fill:none;stroke-width:1;stroke:currentColor'/>
+ <line x1='0' y1='0' x2='4' y2='4' style='stroke:currentColor'/>
+ <line x1='4' y1='0' x2='0' y2='4' style='stroke:currentColor'/>
+ </svg>"))
+ (insert-header "Test Scaling: resize an image (pixelization may occur)")
+ (insert-test "1x" image image '(:scale 1))
+ (insert-test "2x" large image '(:scale 2))
+ (insert-test "0.5x" image large '(:scale 0.5))
+ (insert-test ":max-width" image large '(:max-width 10))
+ (insert-test ":max-height" image large '(:max-height 10))
+ (insert-test "width, height" image large '(:width 10 :height 10)))
+ (insert "\n\n"))
+
+(defun test-scaling-rotation ()
+ (let ((image "<svg height='20' width='20'>
+ <rect x='0' y='0' width='20' height='20'
+ style='fill:none;stroke-width:1;stroke:currentColor'/>
+ <rect x='0' y='0' width='10' height='10'
+ style='fill:currentColor'/>
+ </svg>")
+ (x2-90 "<svg height='40' width='40'>
+ <rect x='0' y='0' width='40' height='40'
+ style='fill:none;stroke-width:1;stroke:currentColor'/>
+ <rect x='20' y='0' width='20' height='20'
+ style='fill:currentColor'/>
+ </svg>")
+ (x2--90 "<svg height='40' width='40'>
+ <rect x='0' y='0' width='40' height='40'
+ style='fill:none;stroke-width:1;stroke:currentColor'/>
+ <rect x='0' y='20' width='20' height='20'
+ style='fill:currentColor'/>
+ </svg>")
+ (x0.5-180 "<svg height='10' width='10'>
+ <rect x='0' y='0' width='10' height='10'
+ style='fill:none;stroke-width:1;stroke:currentColor'/>
+ <rect x='5' y='5' width='5' height='5'
+ style='fill:currentColor'/>
+ </svg>"))
+ (insert-header "Test Scaling and Rotation: resize and rotate an image (pixelization may occur)")
+ (insert-test "1x, 0 degrees" image image '(:scale 1 :rotation 0))
+ (insert-test "2x, 90 degrees" x2-90 image '(:scale 2 :rotation 90.0))
+ (insert-test "2x, -90 degrees" x2--90 image '(:scale 2 :rotation -90.0))
+ (insert-test "0.5x, 180 degrees" x0.5-180 image '(:scale 0.5 :rotation 180.0)))
+ (insert "\n\n"))
+
+(defun insert-header (description)
+ (insert description)
+ (insert "\n")
+ (indent-to 38)
+ (insert "expected")
+ (indent-to 48)
+ (insert "result")
+ (when (fboundp #'imagemagick-types)
+ (indent-to 58)
+ (insert "ImageMagick"))
+ (insert "\n"))
+
+(defun insert-test (description expected image params)
+ (indent-to 2)
+ (insert description)
+ (indent-to 40)
+ (insert-image (create-image expected 'svg t))
+ (indent-to 50)
+ (insert-image (apply #'create-image image 'svg t params))
+ (when (fboundp #'imagemagick-types)
+ (indent-to 60)
+ (insert-image (apply #'create-image image 'imagemagick t params)))
+ (insert "\n"))
+
+(defun test-transforms ()
+ (interactive)
+ (let ((buf (get-buffer "*Image Transform Test*")))
+ (if buf
+ (kill-buffer buf))
+ (switch-to-buffer (get-buffer-create "*Image Transform Test*"))
+ (erase-buffer)
+ (unless #'imagemagick-types
+ (insert "ImageMagick not detected. ImageMagick tests will be skipped.\n\n"))
+ (test-rotation)
+ (test-cropping)
+ (test-scaling)
+ (test-scaling-rotation)
+ (goto-char (point-min))))
+
+;;; image-transforms-tests.el ends here
diff --git a/test/manual/indent/js-jsx.js b/test/manual/indent/js-jsx.js
deleted file mode 100644
index 7401939d282..00000000000
--- a/test/manual/indent/js-jsx.js
+++ /dev/null
@@ -1,85 +0,0 @@
-// -*- mode: js-jsx; -*-
-
-var foo = <div></div>;
-
-return (
- <div>
- </div>
- <div>
- <div></div>
- <div>
- <div></div>
- </div>
- </div>
-);
-
-React.render(
- <div>
- <div></div>
- </div>,
- {
- a: 1
- },
- <div>
- <div></div>
- </div>
-);
-
-return (
- // Sneaky!
- <div></div>
-);
-
-return (
- <div></div>
- // Sneaky!
-);
-
-React.render(
- <input
- />,
- {
- a: 1
- }
-);
-
-return (
- <div>
- {array.map(function () {
- return {
- a: 1
- };
- })}
- </div>
-);
-
-return (
- <div attribute={array.map(function () {
- return {
- a: 1
- };
-
- return {
- a: 1
- };
-
- return {
- a: 1
- };
- })}>
- </div>
-);
-
-// Local Variables:
-// indent-tabs-mode: nil
-// js-indent-level: 2
-// End:
-
-// The following test has intentionally unclosed elements and should
-// be placed below all other tests to prevent awkward indentation.
-
-return (
- <div>
- {array.map(function () {
- return {
- a: 1
diff --git a/test/manual/indent/latex-mode.tex b/test/manual/indent/latex-mode.tex
index 55c8e7033bd..d314b98b483 100644
--- a/test/manual/indent/latex-mode.tex
+++ b/test/manual/indent/latex-mode.tex
@@ -8,4 +8,8 @@ To fix this, remove the \url{sn9c102.ko} from where it appears in
\url{/lib/modules/$(uname -r)}, %bug#11953.
and install the appropriate \url{gspca-modules} package.
+Footnotes and emphasis shouldn't be indented \footnote{as can be seen here,
+for example}, \emph{or there
+as well}.
+
\end{document}
diff --git a/test/manual/indent/less-css-mode.less b/test/manual/indent/less-css-mode.less
index 36c037450cc..b40a2362e28 100644
--- a/test/manual/indent/less-css-mode.less
+++ b/test/manual/indent/less-css-mode.less
@@ -1,3 +1,13 @@
+@var-with-dashes: #428bca;
+@var_with_underscores: 10px;
+@_var-starting-with-underscore: none;
+
+body {
+ background: @var-with-dashes;
+ padding: @var_with_underscores;
+ display: @_var-starting-with-underscore;
+}
+
.desktop-and-old-ie(@rules) {
@media screen and (min-width: 1200) { @rules(); }
html.lt-ie9 & { @rules(); }
diff --git a/test/manual/indent/nxml.xml b/test/manual/indent/nxml.xml
deleted file mode 100644
index 61b84f270b0..00000000000
--- a/test/manual/indent/nxml.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<spocosy version="1.0" responsetime="2011-03-15 13:53:12" exec="0.171">
- <!--
- <query-response requestid="" service="objectquery">
- <sport name="Soccer" enetSportCode="s" del="no" n="1" ut="2009-12-29
- 15:36:24" id="1">
- </sport>
- </query-response>
- -->
-</spocosy>
diff --git a/test/manual/indent/octave.m b/test/manual/indent/octave.m
index 3052a6d3687..76cad09ad1e 100644
--- a/test/manual/indent/octave.m
+++ b/test/manual/indent/octave.m
@@ -14,6 +14,10 @@ function res = tcomp (fn)
until x = ...
y
+ spmd #bug#36703
+ something
+ end
+
%% res = tcomp (fn)
%% imports components and rearranges them.
diff --git a/test/manual/indent/pascal.pas b/test/manual/indent/pascal.pas
index 35e919f00b9..1efd9b83752 100644
--- a/test/manual/indent/pascal.pas
+++ b/test/manual/indent/pascal.pas
@@ -1,6 +1,6 @@
{ GPC demo program for the CRT unit.
-Copyright (C) 1999-2006, 2013-2017 Free Software Foundation, Inc.
+Copyright (C) 1999-2006, 2013-2022 Free Software Foundation, Inc.
Author: Frank Heckenbach <frank@pascal.gnu.de>
diff --git a/test/manual/indent/perl.perl b/test/manual/indent/perl.perl
index 06f32e7f090..b44593da028 100755
--- a/test/manual/indent/perl.perl
+++ b/test/manual/indent/perl.perl
@@ -5,6 +5,12 @@ sub add_funds($) {
return 0;
}
+# qw(...) is a quoted list of words, so we can and should indent its content!
+my @tutu = qw[
+ tata
+ titi
+ ];
+
my $hash = {
foo => 'bar',
format => 'some',
@@ -75,3 +81,29 @@ return 'W' if #/^Not Available on Mobile/m; #W=Web only
# A "y|abc|def|" shouldn't interfere when inside a string!
$toto = " x \" string\"";
$toto = " y \" string\""; # This is not the `y' operator!
+
+
+# Tricky cases from Harald Jörg <haj@posteo.de>
+$_ = "abcabc\n";
+s:abc:def:g; # FIXME: the initial s is fontified like a label, and indented
+
+s'def'ghi'g; # The middle ' should not end the quoting.
+s"ghi"ijk"g; # The middle ' should not end the quoting.
+
+s#ijk#lmn#g; # This is a regular expression substitution.
+
+s #lmn#opq#g; # FIXME: this should be a comment starting with "#lmn"
+ /lmn/rst/g; # and this is the actual regular expression
+print; # prints "rstrst\n"
+
+given ($num) {
+ when ($num>10) {
+ printf "number is greater than 10\n";
+ }
+ when ($num<10) {
+ printf "number is less than 10\n";
+ }
+ default {
+ printf "number is equal to 10\n";
+ }
+}
diff --git a/test/manual/indent/ps-mode.ps b/test/manual/indent/ps-mode.ps
deleted file mode 100644
index 4b4ee0f10cb..00000000000
--- a/test/manual/indent/ps-mode.ps
+++ /dev/null
@@ -1,14 +0,0 @@
-%!PS-2.0
-
-<< 23 45 >> %dictionary
-< 23 > %hex string
-<~a>a%a~> %base85 string
-(%)s
-(sf\(g>a)sdg)
-
-/foo {
- <<
- hello 2
- 3
- >>
-} def
diff --git a/test/manual/indent/scheme.scm b/test/manual/indent/scheme.scm
index 84d0f6d8786..9053a8743e4 100644
--- a/test/manual/indent/scheme.scm
+++ b/test/manual/indent/scheme.scm
@@ -1,9 +1,23 @@
-#!/usr/bin/scheme is this a comment?
-
-;; This one is a comment
-(a)
-#| and this one as #|well|# as this! |#
-(b)
-(cons #;(this is a
- comment)
- head tail)
+;; Testing sexp-comments
+
+(define a #;(hello) there)
+
+(define a #;1 there)
+
+(define a #;"asdf" there)
+
+(define a ;; #;(hello
+ there)
+
+(define a #;(hello
+ there) 2)
+
+(define a #;(hello
+ #;(world))
+ and)
+ there) 2)
+
+(define a #;(hello
+ #;"asdf" (world
+ and)
+ there) 2)
diff --git a/test/manual/indent/scss-mode.scss b/test/manual/indent/scss-mode.scss
index a3dd41eeb47..2cd4adb8d55 100644
--- a/test/manual/indent/scss-mode.scss
+++ b/test/manual/indent/scss-mode.scss
@@ -1,5 +1,7 @@
// Comment!
+@use "sass:math";
+
nav {
ul {
margin: 0; /* More comment */
@@ -41,9 +43,13 @@ p.#{$name} var
article[role="main"] {
$toto: 500 !global;
$var-with-default: 300 !default;
+ $var_with_underscores: #fff;
+ $_var-starting-with-underscore: none;
float: left !important;
- width: 600px / 888px * 100%;
- height: 100px / 888px * 100%;
+ width: math.div(600px, 888px) * 100%;
+ height: math.div(100px, 888px) * 100%;
+ color: $var_with_underscores;
+ display: $_var-starting-with-underscore;
}
%placeholder {
diff --git a/test/manual/indent/shell.sh b/test/manual/indent/shell.sh
index dc184ea0d77..bd4a74f7054 100755
--- a/test/manual/indent/shell.sh
+++ b/test/manual/indent/shell.sh
@@ -6,6 +6,13 @@ setlock -n /tmp/getmail.lock && echo getmail isn\'t running
toto=$(grep hello foo |
wc)
+myfun () {
+ for ((it=0; it<${limit}; ++it))
+ {
+ echo "whatever $it"
+ }
+}
+
# adsgsdg
if foo; then
diff --git a/test/manual/indent/tcl.tcl b/test/manual/indent/tcl.tcl
new file mode 100644
index 00000000000..f055be19663
--- /dev/null
+++ b/test/manual/indent/tcl.tcl
@@ -0,0 +1,26 @@
+# Some sample code that tries to exercise the font-lock
+# of various forms of writing strings.
+
+puts "hello}"; # Top-level strings can contain unescaped closing braces!
+
+puts a"b; # Non-delimited strings can contain quotes!
+puts a""b; # Even several of them!
+
+proc foo1 {} {
+ puts "hello"; # Normal case!
+ puts "hello\}; # This will signal an error when `foo1` is called!
+}
+
+proc foo2 {} {
+ puts "hello; # This will also signal an error when `foo2` is called!
+}
+
+proc foo3 {} {
+ puts a"b; # This will not signal an error!
+ puts a""b"; # And that won't either!
+ puts "a""b"; # But this will!
+}
+
+# FIXME: The [..] interpolation within "..." strings is not properly
+# handled by the current `syntax-propertize-function`!
+set a "Testing: [split "192.168.1.1/24" "/"] address";
diff --git a/test/manual/process-callout-tests.el b/test/manual/process-callout-tests.el
new file mode 100644
index 00000000000..0bb960cf909
--- /dev/null
+++ b/test/manual/process-callout-tests.el
@@ -0,0 +1,64 @@
+;;; process-callout-tests.el --- Testing the process facilities -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'ert)
+
+;;; This test is here in test/manual instead of
+;;; test/src/process-tests.el for two reasons: The test suite
+;;; shouldn't "call home" automatically, because that's against our
+;;; privacy principles, and as a practical matter, the server may have
+;;; problems, and that shouldn't trigger a test error.
+
+(ert-deftest process-async-https-with-delay ()
+ "Bug#49449: asynchronous TLS connection with delayed completion."
+ (skip-unless (and internet-is-working (gnutls-available-p)))
+ (let* ((status nil)
+ (buf (url-http
+ #s(url "https" nil nil "elpa.gnu.org" nil
+ "/packages/archive-contents" nil nil t silent t t)
+ (lambda (s) (setq status s))
+ '(nil) nil 'tls)))
+ (unwind-protect
+ (progn
+ ;; Busy-wait for 1 s to allow for the TCP connection to complete.
+ (let ((delay 1.0)
+ (t0 (float-time)))
+ (while (< (float-time) (+ t0 delay))))
+ ;; Wait for the entire operation to finish.
+ (let ((limit 4.0)
+ (t0 (float-time)))
+ (while (and (null status)
+ (< (float-time) (+ t0 limit)))
+ (sit-for 0.1)))
+ (should status)
+ (should-not (plist-get status ':error))
+ (should buf)
+ (should (> (buffer-size buf) 0))
+ )
+ (when buf
+ (kill-buffer buf)))))
+
+;;; process-callout-tests.el ends here
diff --git a/test/manual/redisplay-testsuite.el b/test/manual/redisplay-testsuite.el
index ea178c33bcc..01b0a895a42 100644
--- a/test/manual/redisplay-testsuite.el
+++ b/test/manual/redisplay-testsuite.el
@@ -1,6 +1,6 @@
-;;; redisplay-testsuite.el --- Test suite for redisplay.
+;;; redisplay-testsuite.el --- Test suite for redisplay. -*- lexical-binding: t; -*-
-;; Copyright (C) 2009-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2022 Free Software Foundation, Inc.
;; Author: Chong Yidong <cyd@stupidchicken.com>
;; Keywords: internal
@@ -350,3 +350,5 @@ static unsigned char x_bits[] = {0xff, 0x81, 0xbd, 0xa5, 0xa5, 0xbd, 0x81, 0xff
(test-redisplay-4)
(test-redisplay-5)
(goto-char (point-min))))
+
+;;; redisplay-testsuite.el ends here
diff --git a/test/manual/scroll-tests.el b/test/manual/scroll-tests.el
index e7f55e136de..e4a9e7cd6f3 100644
--- a/test/manual/scroll-tests.el
+++ b/test/manual/scroll-tests.el
@@ -1,21 +1,21 @@
-;;; scroll-tests.el -- tests for scrolling -*- lexical-binding: t -*-
+;;; scroll-tests.el --- tests for scrolling -*- lexical-binding: t -*-
-;; Copyright (C) 2017 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2022 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
-;; This program is free software; you can redistribute it and/or modify
+;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
-;; This program is distributed in the hope that it will be useful,
+;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
-;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
diff --git a/test/misc/test-custom-deps.el b/test/misc/test-custom-deps.el
new file mode 100644
index 00000000000..7836612bd33
--- /dev/null
+++ b/test/misc/test-custom-deps.el
@@ -0,0 +1,42 @@
+;;; test-custom-deps.el --- Test custom deps -*- lexical-binding:t -*-
+
+;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; The command `cus-test-deps' loads all (!) custom dependencies and
+;; reports about load errors.
+
+;;; Code:
+
+(require 'ert)
+
+(defconst custom-test-admin-cus-test
+ (expand-file-name "admin/cus-test.el" source-directory))
+
+(declare-function cus-test-deps custom-test-admin-cus-test)
+(defvar cus-test-deps-errors) ; from admin/cus-tests.el
+
+(ert-deftest test-custom-deps ()
+ :tags '(:expensive-test)
+ (skip-unless (file-readable-p custom-test-admin-cus-test))
+ (load custom-test-admin-cus-test)
+ (cus-test-deps)
+ (should-not cus-test-deps-errors))
+
+;;; test-custom-deps.el ends here
diff --git a/test/misc/test-custom-libs.el b/test/misc/test-custom-libs.el
new file mode 100644
index 00000000000..d9aa955ccba
--- /dev/null
+++ b/test/misc/test-custom-libs.el
@@ -0,0 +1,48 @@
+;;; test-custom-libs.el --- Test custom loads -*- lexical-binding:t -*-
+
+;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This file runs for all libraries with autoloads separate Emacs
+;; processes of the form "emacs -batch -l LIB".
+
+;;; Code:
+
+(require 'ert)
+
+(defconst custom-test-admin-cus-test
+ (expand-file-name "admin/cus-test.el" source-directory))
+
+(declare-function cus-test-libs custom-test-admin-cus-test)
+(defvar cus-test-libs-errors) ; from admin/cus-tests.el
+
+;; FIXME: Currently fails for:
+;; - lisp/term/ns-win.el
+;; - lisp/org/org-num.el
+(ert-deftest test-custom-libs ()
+ :tags '(:expensive-test)
+ :expected-result :failed ; FIXME: See above.
+ ;; This test is very slow, and IMO not worth the time it takes.
+ (skip-unless (not (getenv "EMACS_HYDRA_CI")))
+ (skip-unless (file-readable-p custom-test-admin-cus-test))
+ (load custom-test-admin-cus-test)
+ (cus-test-libs t)
+ (should-not cus-test-libs-errors))
+
+;;; test-custom-libs.el ends here
diff --git a/test/misc/test-custom-noloads.el b/test/misc/test-custom-noloads.el
new file mode 100644
index 00000000000..15cdbc66238
--- /dev/null
+++ b/test/misc/test-custom-noloads.el
@@ -0,0 +1,45 @@
+;;; test-custom-noloads.el --- Test custom noloads -*- lexical-binding:t -*-
+
+;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; The command `cus-test-noloads' returns a list of variables which
+;; are somewhere declared as custom options, but not loaded by
+;; `custom-load-symbol'.
+
+;;; Code:
+
+(require 'ert)
+
+(defconst custom-test-admin-cus-test
+ (expand-file-name "admin/cus-test.el" source-directory))
+
+(declare-function cus-test-noloads custom-test-admin-cus-test)
+(defvar cus-test-vars-not-cus-loaded) ; from admin/cus-tests.el
+
+;; FIXME: Multiple failures here.
+(ert-deftest custom-test-load ()
+ :tags '(:expensive-test :unstable)
+ :expected-result :failed ; FIXME: See above.
+ (skip-unless (file-readable-p custom-test-admin-cus-test))
+ (load custom-test-admin-cus-test)
+ (cus-test-noloads)
+ (should-not cus-test-vars-not-cus-loaded))
+
+;;; test-custom-noloads.el ends here
diff --git a/test/misc/test-custom-opts.el b/test/misc/test-custom-opts.el
new file mode 100644
index 00000000000..21809a9a971
--- /dev/null
+++ b/test/misc/test-custom-opts.el
@@ -0,0 +1,39 @@
+;;; test-custom-opts.el --- Test custom opts -*- lexical-binding:t -*-
+
+;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; The command `cus-test-opts' tests many (all?) custom options.
+
+;;; Code:
+
+(require 'ert)
+
+(defconst custom-test-admin-cus-test
+ (expand-file-name "admin/cus-test.el" source-directory))
+
+(declare-function cus-test-opts custom-test-admin-cus-test)
+
+(ert-deftest check-for-wrong-custom-opts ()
+ :tags '(:expensive-test)
+ (skip-unless (file-readable-p custom-test-admin-cus-test))
+ (load custom-test-admin-cus-test)
+ (should (null (cus-test-opts t))))
+
+;;; test-custom-opts.el ends here
diff --git a/test/src/alloc-tests.el b/test/src/alloc-tests.el
index aff480c6b66..967833e1903 100644
--- a/test/src/alloc-tests.el
+++ b/test/src/alloc-tests.el
@@ -1,6 +1,6 @@
;;; alloc-tests.el --- alloc tests -*- lexical-binding: t -*-
-;; Copyright (C) 2015-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2022 Free Software Foundation, Inc.
;; Author: Daniel Colascione <dancol@dancol.org>
;; Keywords:
@@ -30,7 +30,7 @@
(require 'cl-lib)
(ert-deftest finalizer-object-type ()
- (should (equal (type-of (make-finalizer nil)) 'finalizer)))
+ (should (equal (type-of (make-finalizer #'ignore)) 'finalizer)))
(ert-deftest record-1 ()
(let ((x (record 'foo 1 2 3)))
@@ -51,3 +51,12 @@
(should-not (eq x y))
(dotimes (i 4)
(should (eql (aref x i) (aref y i))))))
+
+;; Bug#39207
+(ert-deftest aset-nbytes-change ()
+ (let ((s (make-string 1 ?a)))
+ (dolist (c (list 10003 ?b 128 ?c ?d (max-char) ?e))
+ (aset s 0 c)
+ (should (equal s (make-string 1 c))))))
+
+;;; alloc-tests.el ends here
diff --git a/test/src/buffer-tests.el b/test/src/buffer-tests.el
index 153aea3a20b..a12d15bc798 100644
--- a/test/src/buffer-tests.el
+++ b/test/src/buffer-tests.el
@@ -1,6 +1,6 @@
;;; buffer-tests.el --- tests for buffer.c functions -*- lexical-binding: t -*-
-;; Copyright (C) 2015-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2022 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -21,6 +21,201 @@
(require 'ert)
(require 'seq)
+(require 'ert-x)
+(require 'cl-lib)
+(require 'let-alist)
+
+(defun overlay-tests-start-recording-modification-hooks (overlay)
+ "Start recording modification hooks on OVERLAY.
+
+Always overwrites the `insert-in-front-hooks',
+`modification-hooks' and `insert-behind-hooks' properties. Any
+recorded history from a previous call is erased.
+
+The history is stored in a property on the overlay itself. Call
+`overlay-tests-get-recorded-modification-hooks' to retrieve the
+recorded calls conveniently."
+ (dolist (hooks-property '(insert-in-front-hooks
+ modification-hooks
+ insert-behind-hooks))
+ (overlay-put
+ overlay
+ hooks-property
+ (list (lambda (ov &rest args)
+ (message " %S called on %S with args %S" hooks-property ov args)
+ (should inhibit-modification-hooks)
+ (should (eq ov overlay))
+ (push (list hooks-property args)
+ (overlay-get overlay
+ 'recorded-modification-hook-calls)))))
+ (overlay-put overlay 'recorded-modification-hook-calls nil)))
+
+(defun overlay-tests-get-recorded-modification-hooks (overlay)
+ "Extract the recorded calls made to modification hooks on OVERLAY.
+
+Must be preceded by a call to
+`overlay-tests-start-recording-modification-hooks' on OVERLAY.
+
+Returns a list. Each element of the list represents a recorded
+call to a particular modification hook.
+
+Each call is itself a sub-list where the first element is a
+symbol matching the modification hook property (one of
+`insert-in-front-hooks', `modification-hooks' or
+`insert-behind-hooks') and the second element is the list of
+arguments passed to the hook. The first hook argument, the
+overlay itself, is omitted to make test result verification
+easier."
+ (reverse (overlay-get overlay
+ 'recorded-modification-hook-calls)))
+
+(ert-deftest overlay-modification-hooks ()
+ "Test the basic functionality of overlay modification hooks.
+
+This exercises hooks registered on the `insert-in-front-hooks',
+`modification-hooks' and `insert-behind-hooks' overlay
+properties."
+ ;; This is a data driven test loop. Each test case is described
+ ;; by an alist. The test loop initializes a new temporary buffer
+ ;; for each case, creates an overlay, registers modification hooks
+ ;; on the overlay, modifies the buffer, and then verifies which
+ ;; modification hooks (if any) were called for the overlay, as
+ ;; well as which arguments were passed to the hooks.
+ ;;
+ ;; The following keys are available in the alist:
+ ;;
+ ;; `buffer-text': the initial buffer text of the temporary buffer.
+ ;; Defaults to "1234".
+ ;;
+ ;; `overlay-beg' and `overlay-end': the begin and end positions of
+ ;; the overlay under test. Defaults to 2 and 4 respectively.
+ ;;
+ ;; `insert-at': move to the given position and insert the string
+ ;; "x" into the test case's buffer.
+ ;;
+ ;; `replace': replace the first occurrence of the given string in
+ ;; the test case's buffer with "x". The test will fail if the
+ ;; string is not found.
+ ;;
+ ;; `expected-calls': a description of the expected buffer
+ ;; modification hooks. See
+ ;; `overlay-tests-get-recorded-modification-hooks' for the format.
+ ;; May be omitted, in which case the test will insist that no
+ ;; modification hooks are called.
+ ;;
+ ;; The test will fail itself in the degenerate case where no
+ ;; buffer modifications are requested.
+ (dolist (test-case
+ '(
+ ;; Remember that the default buffer text is "1234" and
+ ;; the default overlay begins at position 2 and ends at
+ ;; position 4. Most of the test cases below assume
+ ;; this.
+
+ ;; TODO: (info "(elisp) Special Properties") says this
+ ;; about `modification-hooks': "Furthermore, insertion
+ ;; will not modify any existing character, so this hook
+ ;; will only be run when removing some characters,
+ ;; replacing them with others, or changing their
+ ;; text-properties." So, why are modification-hooks
+ ;; being called when inserting at position 3 below?
+ ((insert-at . 1))
+ ((insert-at . 2)
+ (expected-calls . ((insert-in-front-hooks (nil 2 2))
+ (insert-in-front-hooks (t 2 3 0)))))
+ ((insert-at . 3)
+ (expected-calls . ((modification-hooks (nil 3 3))
+ (modification-hooks (t 3 4 0)))))
+ ((insert-at . 4)
+ (expected-calls . ((insert-behind-hooks (nil 4 4))
+ (insert-behind-hooks (t 4 5 0)))))
+ ((insert-at . 5))
+
+ ;; Replacing text never calls `insert-in-front-hooks'
+ ;; or `insert-behind-hooks'. It calls
+ ;; `modification-hooks' if the overlay covers any text
+ ;; that has changed.
+ ((replace . "1"))
+ ((replace . "2")
+ (expected-calls . ((modification-hooks (nil 2 3))
+ (modification-hooks (t 2 3 1)))))
+ ((replace . "3")
+ (expected-calls . ((modification-hooks (nil 3 4))
+ (modification-hooks (t 3 4 1)))))
+ ((replace . "4"))
+ ((replace . "12")
+ (expected-calls . ((modification-hooks (nil 1 3))
+ (modification-hooks (t 1 2 2)))))
+ ((replace . "23")
+ (expected-calls . ((modification-hooks (nil 2 4))
+ (modification-hooks (t 2 3 2)))))
+ ((replace . "34")
+ (expected-calls . ((modification-hooks (nil 3 5))
+ (modification-hooks (t 3 4 2)))))
+ ((replace . "123")
+ (expected-calls . ((modification-hooks (nil 1 4))
+ (modification-hooks (t 1 2 3)))))
+ ((replace . "234")
+ (expected-calls . ((modification-hooks (nil 2 5))
+ (modification-hooks (t 2 3 3)))))
+ ((replace . "1234")
+ (expected-calls . ((modification-hooks (nil 1 5))
+ (modification-hooks (t 1 2 4)))))
+
+ ;; Inserting at the position of a zero-length overlay
+ ;; calls both `insert-in-front-hooks' and
+ ;; `insert-behind-hooks'.
+ ((buffer-text . "") (overlay-beg . 1) (overlay-end . 1)
+ (insert-at . 1)
+ (expected-calls . ((insert-in-front-hooks
+ (nil 1 1))
+ (insert-behind-hooks
+ (nil 1 1))
+ (insert-in-front-hooks
+ (t 1 2 0))
+ (insert-behind-hooks
+ (t 1 2 0)))))))
+ (message "BEGIN overlay-modification-hooks test-case %S" test-case)
+
+ ;; All three hooks ignore the overlay's `front-advance' and
+ ;; `rear-advance' option, so test both ways while expecting the same
+ ;; result.
+ (dolist (advance '(nil t))
+ (message " advance is %S" advance)
+ (let-alist test-case
+ (with-temp-buffer
+ ;; Set up the temporary buffer and overlay as specified by
+ ;; the test case.
+ (insert (or .buffer-text "1234"))
+ (let ((overlay (make-overlay
+ (or .overlay-beg 2)
+ (or .overlay-end 4)
+ nil
+ advance advance)))
+ (message " (buffer-string) is %S" (buffer-string))
+ (message " overlay is %S" overlay)
+ (overlay-tests-start-recording-modification-hooks overlay)
+
+ ;; Modify the buffer, possibly inducing calls to the
+ ;; overlay's modification hooks.
+ (should (or .insert-at .replace))
+ (when .insert-at
+ (goto-char .insert-at)
+ (insert "x")
+ (message " inserted \"x\" at %S, buffer-string now %S"
+ .insert-at (buffer-string)))
+ (when .replace
+ (goto-char (point-min))
+ (search-forward .replace)
+ (replace-match "x")
+ (message " replaced %S with \"x\"" .replace))
+
+ ;; Verify that the expected and actual modification hook
+ ;; calls match.
+ (should (equal
+ .expected-calls
+ (overlay-tests-get-recorded-modification-hooks
+ overlay)))))))))
(ert-deftest overlay-modification-hooks-message-other-buf ()
"Test for bug#21824.
@@ -46,34 +241,80 @@ with parameters from the *Messages* buffer modification."
(should (eq buf (current-buffer))))
(when msg-ov (delete-overlay msg-ov))))))
+(ert-deftest overlay-modification-hooks-deleted-overlay ()
+ "Test for bug#30823."
+ (let ((check-point nil)
+ (ov-delete nil)
+ (ov-set nil))
+ (with-temp-buffer
+ (insert "abc")
+ (setq ov-set (make-overlay 1 3))
+ (overlay-put ov-set 'modification-hooks
+ (list (lambda (_o after &rest _args)
+ (and after (setq check-point t)))))
+ (setq ov-delete (make-overlay 1 3))
+ (overlay-put ov-delete 'modification-hooks
+ (list (lambda (o after &rest _args)
+ (and (not after) (delete-overlay o)))))
+ (goto-char 2)
+ (insert "1")
+ (should (eq check-point t)))))
+
(ert-deftest test-generate-new-buffer-name-bug27966 ()
(should-not (string-equal "nil"
(progn (get-buffer-create "nil")
(generate-new-buffer-name "nil")))))
-
-;; +===================================================================================+
+(ert-deftest test-buffer-base-buffer-indirect ()
+ (with-temp-buffer
+ (let* ((ind-buf-name (generate-new-buffer-name "indbuf"))
+ (ind-buf (make-indirect-buffer (current-buffer) ind-buf-name)))
+ (should (eq (buffer-base-buffer ind-buf) (current-buffer))))))
+
+(ert-deftest test-buffer-base-buffer-non-indirect ()
+ (with-temp-buffer
+ (should (eq (buffer-base-buffer (current-buffer)) nil))))
+
+(ert-deftest overlay-evaporation-after-killed-buffer ()
+ (let* ((ols (with-temp-buffer
+ (insert "toto")
+ (list
+ (make-overlay (point-min) (point-max))
+ (make-overlay (point-min) (point-max))
+ (make-overlay (point-min) (point-max)))))
+ (ol (nth 1 ols)))
+ (overlay-put ol 'evaporate t)
+ ;; Evaporation within move-overlay of an overlay that was deleted because
+ ;; of a kill-buffer, triggered an assertion failure in unchain_both.
+ (with-temp-buffer
+ (insert "toto")
+ (move-overlay ol (point-min) (point-min)))))
+
+
+;; +==========================================================================+
;; | Overlay test setup
-;; +===================================================================================+
+;; +==========================================================================+
-(eval-when-compile
- (defun make-overlay-test-name (fn x y)
- (intern (format "test-%s-%s-%s" fn x y))))
+(eval-and-compile
+ (defun buffer-tests--make-test-name (fn x y)
+ (intern (format "buffer-tests--%s-%s-%s" fn x y))))
-(defun unmake-ov-test-name (symbol)
+(defun buffer-tests--unmake-test-name (symbol)
(let ((name (if (stringp symbol) symbol (symbol-name symbol))))
- (when (string-match "\\`test-\\(.*\\)-\\(.*\\)-\\(.*\\)\\'" name)
- (list (match-string 1 name) (match-string 2 name) (match-string 3 name)))))
+ (when (string-match "\\`buffer-tests--\\(.*\\)-\\(.*\\)-\\(.*\\)\\'" name)
+ (list (match-string 1 name)
+ (match-string 2 name)
+ (match-string 3 name)))))
(defmacro deftest-make-overlay-1 (id args)
(declare (indent 1))
- `(ert-deftest ,(make-overlay-test-name 'make-overlay 1 id) ()
+ `(ert-deftest ,(buffer-tests--make-test-name 'make-overlay 1 id) ()
(with-temp-buffer
(should ,(cons 'make-overlay args)))))
(defmacro deftest-make-overlay-2 (id args condition)
(declare (indent 1))
- `(ert-deftest ,(make-overlay-test-name 'make-overlay 2 id) ()
+ `(ert-deftest ,(buffer-tests--make-test-name 'make-overlay 2 id) ()
(with-temp-buffer
(should-error
,(cons 'make-overlay args)
@@ -84,7 +325,7 @@ with parameters from the *Messages* buffer modification."
(declare (indent 1))
(cl-destructuring-bind (start end sstart send)
(append start-end-args start-end-should)
- `(ert-deftest ,(make-overlay-test-name 'overlay-start/end 1 id) ()
+ `(ert-deftest ,(buffer-tests--make-test-name 'overlay-start/end 1 id) ()
(with-temp-buffer
(insert (make-string 9 ?\n))
(let ((ov (make-overlay ,start ,end)))
@@ -93,25 +334,26 @@ with parameters from the *Messages* buffer modification."
(defmacro deftest-overlay-buffer-1 (id arg-expr should-expr)
(declare (indent 1))
- `(ert-deftest ,(make-overlay-test-name 'overlay-buffer 1 id) ()
+ `(ert-deftest ,(buffer-tests--make-test-name 'overlay-buffer 1 id) ()
(with-temp-buffer
(should (equal (overlay-buffer (make-overlay 1 1 ,arg-expr))
- ,should-expr)))))
+ ,should-expr)))))
(defmacro deftest-overlayp-1 (id arg-expr should-expr)
(declare (indent 1))
- `(ert-deftest ,(make-overlay-test-name 'overlay-buffer 1 id) ()
+ `(ert-deftest ,(buffer-tests--make-test-name 'overlayp 1 id) ()
(with-temp-buffer
(should (equal ,should-expr (overlayp ,arg-expr))))))
(defmacro deftest-next-overlay-change-1 (id pos result &rest ov-tuple)
- `(ert-deftest ,(make-overlay-test-name 'next-overlay-change 1 id) ()
+ `(ert-deftest ,(buffer-tests--make-test-name 'next-overlay-change 1 id) ()
(let ((tuple (copy-sequence ',ov-tuple)))
(with-temp-buffer
(insert (make-string (max 100 (if tuple
(apply #'max
(mapcar
- (lambda (m) (apply #'max m)) tuple))
+ (lambda (m) (apply #'max m))
+ tuple))
0))
?\n))
(dolist (tup tuple)
@@ -120,13 +362,14 @@ with parameters from the *Messages* buffer modification."
,result))))))
(defmacro deftest-previous-overlay-change-1 (id pos result &rest ov-tuple)
- `(ert-deftest ,(make-overlay-test-name 'previous-overlay-change 1 id) ()
+ `(ert-deftest ,(buffer-tests--make-test-name 'previous-overlay-change 1 id) ()
(let ((tuple ',ov-tuple))
(with-temp-buffer
(insert (make-string (max 100 (if tuple
(apply #'max
(mapcar
- (lambda (m) (apply #'max m)) tuple))
+ (lambda (m) (apply #'max m))
+ tuple))
0))
?\n))
(dolist (tup tuple)
@@ -135,7 +378,7 @@ with parameters from the *Messages* buffer modification."
,result))))))
(defmacro deftest-overlays-at-1 (id pos result &rest ov-triple)
- `(ert-deftest ,(make-overlay-test-name 'overlays-at 1 id) ()
+ `(ert-deftest ,(buffer-tests--make-test-name 'overlays-at 1 id) ()
(let ((pos* ,pos))
(with-temp-buffer
(insert (make-string 100 ?\s))
@@ -150,7 +393,7 @@ with parameters from the *Messages* buffer modification."
(should (memq (overlay-get ov 'tag) ',result))))))))
(defmacro deftest-overlays-in-1 (id beg end result &rest ov-triple)
- `(ert-deftest ,(make-overlay-test-name 'overlays-in 1 id) ()
+ `(ert-deftest ,(buffer-tests--make-test-name 'overlays-in 1 id) ()
(let ((beg* ,beg)
(end* ,end))
(with-temp-buffer
@@ -176,39 +419,42 @@ with parameters from the *Messages* buffer modification."
,@body))))
(defmacro deftest-overlays-equal-1 (id result ov1-args ov2-args)
- `(ert-deftest ,(make-overlay-test-name 'overlays-equal 1 id) ()
- (cl-labels ((create-overlay (args)
- (cl-destructuring-bind (start end &optional fa ra &rest properties)
- args
- (let ((ov (make-overlay start end nil fa ra)))
- (while properties
- (overlay-put ov (pop properties) (pop properties)))
- ov))))
+ `(ert-deftest ,(buffer-tests--make-test-name 'overlays-equal 1 id) ()
+ (cl-flet ((create-overlay (args)
+ (cl-destructuring-bind (start end &optional fa ra
+ &rest properties)
+ args
+ (let ((ov (make-overlay start end nil fa ra)))
+ (while properties
+ (overlay-put ov (pop properties) (pop properties)))
+ ov))))
(with-temp-buffer
(insert (make-string 1024 ?\s))
(should (,(if result 'identity 'not)
(equal (create-overlay ',ov1-args)
(create-overlay ',ov2-args))))))))
-
-(defun find-ert-overlay-test (name)
- (let ((test (unmake-ov-test-name name)))
+
+(defun buffer-tests--find-ert-test (name)
+ (let ((test (buffer-tests--unmake-test-name name)))
(or (and test
(cl-destructuring-bind (fn x y)
test
(let ((regexp (format "deftest-%s-%s +%s" fn x y)))
(re-search-forward regexp nil t))))
(let ((find-function-regexp-alist
- (cl-remove 'find-ert-overlay-test find-function-regexp-alist :key #'cdr)))
- (find-function-do-it name 'ert-deftest 'switch-to-buffer-other-window)))))
+ (cl-remove #'buffer-tests--find-ert-test
+ find-function-regexp-alist :key #'cdr)))
+ (find-function-do-it name 'ert-deftest
+ #'switch-to-buffer-other-window)))))
(add-to-list 'find-function-regexp-alist
- '(ert-deftest . find-ert-overlay-test))
+ `(ert-deftest . ,#'buffer-tests--find-ert-test))
-
-;; +===================================================================================+
+
+;; +==========================================================================+
;; | make-overlay
-;; +===================================================================================+
+;; +==========================================================================+
;; Test if making an overlay succeeds.
(deftest-make-overlay-1 A (1 1))
@@ -237,12 +483,12 @@ with parameters from the *Messages* buffer modification."
(deftest-make-overlay-2 I (1 [1]) wrong-type-argument)
(deftest-make-overlay-2 J (1 1 (with-temp-buffer
(current-buffer)))
- error)
+ error)
-
-;; +===================================================================================+
+
+;; +==========================================================================+
;; | overlay-start/end
-;; +===================================================================================+
+;; +==========================================================================+
;; Test if the overlays return proper positions. point-max of the
;; buffer will equal 10. ARG RESULT
@@ -253,7 +499,8 @@ with parameters from the *Messages* buffer modification."
(deftest-overlay-start/end-1 E (1 11) (1 10))
(deftest-overlay-start/end-1 F (1 most-positive-fixnum) (1 10))
(deftest-overlay-start/end-1 G (most-positive-fixnum 1) (1 10))
-(deftest-overlay-start/end-1 H (most-positive-fixnum most-positive-fixnum) (10 10))
+(deftest-overlay-start/end-1 H (most-positive-fixnum most-positive-fixnum)
+ (10 10))
(deftest-overlay-start/end-1 I (100 11) (10 10))
(deftest-overlay-start/end-1 J (11 100) (10 10))
(deftest-overlay-start/end-1 K (0 1) (1 1))
@@ -264,10 +511,10 @@ with parameters from the *Messages* buffer modification."
(should-not (overlay-start (with-temp-buffer (make-overlay 1 1))))
(should-not (overlay-end (with-temp-buffer (make-overlay 1 1)))))
-
-;; +===================================================================================+
+
+;; +==========================================================================+
;; | overlay-buffer
-;; +===================================================================================+
+;; +==========================================================================+
;; Test if overlay-buffer returns appropriate values.
(deftest-overlay-buffer-1 A (current-buffer) (current-buffer))
@@ -276,10 +523,10 @@ with parameters from the *Messages* buffer modification."
(should-error (make-overlay
1 1 (with-temp-buffer (current-buffer)))))
-
-;; +===================================================================================+
+
+;; +==========================================================================+
;; | overlayp
-;; +===================================================================================+
+;; +==========================================================================+
;; Check the overlay predicate.
(deftest-overlayp-1 A (make-overlay 1 1) t)
@@ -298,10 +545,10 @@ with parameters from the *Messages* buffer modification."
(deftest-overlayp-1 N (selected-window) nil)
(deftest-overlayp-1 O (selected-frame) nil)
-
-;; +===================================================================================+
+
+;; +==========================================================================+
;; | overlay equality
-;; +===================================================================================+
+;; +==========================================================================+
(deftest-overlays-equal-1 A t (1 1) (1 1))
(deftest-overlays-equal-1 B t (5 10) (5 10))
@@ -313,10 +560,10 @@ with parameters from the *Messages* buffer modification."
(deftest-overlays-equal-1 H t (10 20 nil nil foo 42) (10 20 nil nil foo 42))
(deftest-overlays-equal-1 I nil (10 20 nil nil foo 42) (10 20 nil nil foo 43))
-
-;; +===================================================================================+
+
+;; +==========================================================================+
;; | overlay-lists
-;; +===================================================================================+
+;; +==========================================================================+
;; Check whether overlay-lists returns something sensible.
(ert-deftest test-overlay-lists-1 ()
@@ -330,10 +577,10 @@ with parameters from the *Messages* buffer modification."
(should (= 10 (length list)))
(should (seq-every-p #'overlayp list)))))
-
-;; +===================================================================================+
+
+;; +==========================================================================+
;; | overlay-put/get/properties
-;; +===================================================================================+
+;; +==========================================================================+
;; Test if overlay-put properties can be retrieved by overlay-get and
;; overlay-properties.
@@ -361,10 +608,10 @@ with parameters from the *Messages* buffer modification."
;; Check if overlay-properties is a subset.
(should (= (length (overlay-properties ov)) (* n 2))))))
-
-;; +===================================================================================+
+
+;; +==========================================================================+
;; | next-overlay-change
-;; +===================================================================================+
+;; +==========================================================================+
;; Test if next-overlay-change returns RESULT if called with POS in a
;; buffer with overlays corresponding to OVS and point-max >= 100.
@@ -383,14 +630,14 @@ with parameters from the *Messages* buffer modification."
(deftest-next-overlay-change-1 I 10 (point-max) (10 10))
(deftest-next-overlay-change-1 J 20 (point-max) (10 10))
;; 2 non-empty, non-intersecting
-(deftest-next-overlay-change-1 D 10 20 (20 30) (40 50))
-(deftest-next-overlay-change-1 E 35 40 (20 30) (40 50))
-(deftest-next-overlay-change-1 F 60 (point-max) (20 30) (40 50))
-(deftest-next-overlay-change-1 G 30 40 (20 30) (40 50))
-(deftest-next-overlay-change-1 H 50 (point-max) (20 30) (40 50))
+(deftest-next-overlay-change-1 D2 10 20 (20 30) (40 50))
+(deftest-next-overlay-change-1 E2 35 40 (20 30) (40 50))
+(deftest-next-overlay-change-1 F2 60 (point-max) (20 30) (40 50))
+(deftest-next-overlay-change-1 G2 30 40 (20 30) (40 50))
+(deftest-next-overlay-change-1 H2 50 (point-max) (20 30) (40 50))
;; 2 non-empty, intersecting
-(deftest-next-overlay-change-1 I 10 20 (20 30) (25 35))
-(deftest-next-overlay-change-1 J 20 25 (20 30) (25 35))
+(deftest-next-overlay-change-1 I2 10 20 (20 30) (25 35))
+(deftest-next-overlay-change-1 J2 20 25 (20 30) (25 35))
(deftest-next-overlay-change-1 K 23 25 (20 30) (25 35))
(deftest-next-overlay-change-1 L 25 30 (20 30) (25 35))
(deftest-next-overlay-change-1 M 28 30 (20 30) (25 35))
@@ -420,11 +667,11 @@ with parameters from the *Messages* buffer modification."
(deftest-next-overlay-change-1 k 30 (point-max) (20 20) (20 30))
(deftest-next-overlay-change-1 l 40 (point-max) (20 20) (20 30))
;; 1 empty, 1 non-empty, intersecting at end
-(deftest-next-overlay-change-1 h 10 20 (30 30) (20 30))
-(deftest-next-overlay-change-1 i 20 30 (30 30) (20 30))
-(deftest-next-overlay-change-1 j 25 30 (30 30) (20 30))
-(deftest-next-overlay-change-1 k 30 (point-max) (20 20) (20 30))
-(deftest-next-overlay-change-1 l 40 (point-max) (20 20) (20 30))
+(deftest-next-overlay-change-1 h2 10 20 (30 30) (20 30))
+(deftest-next-overlay-change-1 i2 20 30 (30 30) (20 30))
+(deftest-next-overlay-change-1 j2 25 30 (30 30) (20 30))
+(deftest-next-overlay-change-1 k2 30 (point-max) (20 20) (20 30))
+(deftest-next-overlay-change-1 l2 40 (point-max) (20 20) (20 30))
;; 1 empty, 1 non-empty, intersecting in the middle
(deftest-next-overlay-change-1 m 10 20 (25 25) (20 30))
(deftest-next-overlay-change-1 n 20 25 (25 25) (20 30))
@@ -452,10 +699,10 @@ with parameters from the *Messages* buffer modification."
(58 66) (41 10) (9 67) (28 88) (27 43)
(24 27) (48 36) (5 90) (61 9))
-
-;; +===================================================================================+
+
+;; +==========================================================================+
;; | previous-overlay-change.
-;; +===================================================================================+
+;; +==========================================================================+
;; Same for previous-overlay-change.
;; 1 non-empty overlay
@@ -471,14 +718,14 @@ with parameters from the *Messages* buffer modification."
(deftest-previous-overlay-change-1 I 10 1 (10 10))
(deftest-previous-overlay-change-1 J 20 10 (10 10))
;; 2 non-empty, non-intersecting
-(deftest-previous-overlay-change-1 D 10 1 (20 30) (40 50))
-(deftest-previous-overlay-change-1 E 35 30 (20 30) (40 50))
-(deftest-previous-overlay-change-1 F 60 50 (20 30) (40 50))
-(deftest-previous-overlay-change-1 G 30 20 (20 30) (40 50))
-(deftest-previous-overlay-change-1 H 50 40 (20 30) (40 50))
+(deftest-previous-overlay-change-1 D2 10 1 (20 30) (40 50))
+(deftest-previous-overlay-change-1 E2 35 30 (20 30) (40 50))
+(deftest-previous-overlay-change-1 F2 60 50 (20 30) (40 50))
+(deftest-previous-overlay-change-1 G2 30 20 (20 30) (40 50))
+(deftest-previous-overlay-change-1 H2 50 40 (20 30) (40 50))
;; 2 non-empty, intersecting
-(deftest-previous-overlay-change-1 I 10 1 (20 30) (25 35))
-(deftest-previous-overlay-change-1 J 20 1 (20 30) (25 35))
+(deftest-previous-overlay-change-1 I2 10 1 (20 30) (25 35))
+(deftest-previous-overlay-change-1 J2 20 1 (20 30) (25 35))
(deftest-previous-overlay-change-1 K 23 20 (20 30) (25 35))
(deftest-previous-overlay-change-1 L 25 20 (20 30) (25 35))
(deftest-previous-overlay-change-1 M 28 25 (20 30) (25 35))
@@ -513,7 +760,7 @@ with parameters from the *Messages* buffer modification."
(deftest-previous-overlay-change-1 o 25 20 (30 30) (20 30))
(deftest-previous-overlay-change-1 p 30 20 (20 20) (20 30))
(deftest-previous-overlay-change-1 q 40 30 (20 20) (20 30))
-;; 1 empty, 1 non-empty, intersectig in the middle
+;; 1 empty, 1 non-empty, intersecting in the middle
(deftest-previous-overlay-change-1 r 10 1 (25 25) (20 30))
(deftest-previous-overlay-change-1 s 20 1 (25 25) (20 30))
(deftest-previous-overlay-change-1 t 25 20 (25 25) (20 30))
@@ -540,10 +787,10 @@ with parameters from the *Messages* buffer modification."
(58 66) (41 10) (9 67) (28 88) (27 43)
(24 27) (48 36) (5 90) (61 9))
-
-;; +===================================================================================+
+
+;; +==========================================================================+
;; | overlays-at
-;; +===================================================================================+
+;; +==========================================================================+
;; Test whether overlay-at returns RESULT at POS after overlays OVL were
@@ -568,36 +815,36 @@ with parameters from the *Messages* buffer modification."
(deftest-overlays-at-1 P 50 () (a 10 20) (b 30 40))
;; 2 non-empty overlays intersecting
-(deftest-overlays-at-1 G 1 () (a 10 30) (b 20 40))
-(deftest-overlays-at-1 H 10 (a) (a 10 30) (b 20 40))
-(deftest-overlays-at-1 I 15 (a) (a 10 30) (b 20 40))
-(deftest-overlays-at-1 K 20 (a b) (a 10 30) (b 20 40))
-(deftest-overlays-at-1 L 25 (a b) (a 10 30) (b 20 40))
-(deftest-overlays-at-1 M 30 (b) (a 10 30) (b 20 40))
-(deftest-overlays-at-1 N 35 (b) (a 10 30) (b 20 40))
-(deftest-overlays-at-1 O 40 () (a 10 30) (b 20 40))
-(deftest-overlays-at-1 P 50 () (a 10 30) (b 20 40))
+(deftest-overlays-at-1 G2 1 () (a 10 30) (b 20 40))
+(deftest-overlays-at-1 H2 10 (a) (a 10 30) (b 20 40))
+(deftest-overlays-at-1 I2 15 (a) (a 10 30) (b 20 40))
+(deftest-overlays-at-1 K2 20 (a b) (a 10 30) (b 20 40))
+(deftest-overlays-at-1 L2 25 (a b) (a 10 30) (b 20 40))
+(deftest-overlays-at-1 M2 30 (b) (a 10 30) (b 20 40))
+(deftest-overlays-at-1 N2 35 (b) (a 10 30) (b 20 40))
+(deftest-overlays-at-1 O2 40 () (a 10 30) (b 20 40))
+(deftest-overlays-at-1 P2 50 () (a 10 30) (b 20 40))
;; 2 non-empty overlays continuous
-(deftest-overlays-at-1 G 1 () (a 10 20) (b 20 30))
-(deftest-overlays-at-1 H 10 (a) (a 10 20) (b 20 30))
-(deftest-overlays-at-1 I 15 (a) (a 10 20) (b 20 30))
-(deftest-overlays-at-1 K 20 (b) (a 10 20) (b 20 30))
-(deftest-overlays-at-1 L 25 (b) (a 10 20) (b 20 30))
-(deftest-overlays-at-1 M 30 () (a 10 20) (b 20 30))
+(deftest-overlays-at-1 G3 1 () (a 10 20) (b 20 30))
+(deftest-overlays-at-1 H3 10 (a) (a 10 20) (b 20 30))
+(deftest-overlays-at-1 I3 15 (a) (a 10 20) (b 20 30))
+(deftest-overlays-at-1 K3 20 (b) (a 10 20) (b 20 30))
+(deftest-overlays-at-1 L3 25 (b) (a 10 20) (b 20 30))
+(deftest-overlays-at-1 M3 30 () (a 10 20) (b 20 30))
;; overlays-at never returns empty overlays.
-(deftest-overlays-at-1 N 1 (a) (a 1 60) (c 1 1) (b 30 30) (d 50 50))
-(deftest-overlays-at-1 O 20 (a) (a 1 60) (c 1 1) (b 30 30) (d 50 50))
-(deftest-overlays-at-1 P 30 (a) (a 1 60) (c 1 1) (b 30 30) (d 50 50))
+(deftest-overlays-at-1 N3 1 (a) (a 1 60) (c 1 1) (b 30 30) (d 50 50))
+(deftest-overlays-at-1 O3 20 (a) (a 1 60) (c 1 1) (b 30 30) (d 50 50))
+(deftest-overlays-at-1 P3 30 (a) (a 1 60) (c 1 1) (b 30 30) (d 50 50))
(deftest-overlays-at-1 Q 40 (a) (a 1 60) (c 1 1) (b 30 30) (d 50 50))
(deftest-overlays-at-1 R 50 (a) (a 1 60) (c 1 1) (b 30 30) (d 50 50))
(deftest-overlays-at-1 S 60 () (a 1 60) (c 1 1) (b 30 30) (d 50 50))
-;; behaviour at point-min and point-max
+;; behavior at point-min and point-max
(ert-deftest test-overlays-at-2 ()
(cl-macrolet ((should-length (n list)
- `(should (= ,n (length ,list)))))
+ `(should (= ,n (length ,list)))))
(with-temp-buffer
(insert (make-string 100 ?\s))
(make-overlay 1 (point-max))
@@ -613,10 +860,10 @@ with parameters from the *Messages* buffer modification."
(should-length 1 (overlays-at 15))
(should-length 1 (overlays-at (point-max))))))
-
-;; +===================================================================================+
+
+;; +==========================================================================+
;; | overlay-in
-;; +===================================================================================+
+;; +==========================================================================+
;; Test whether overlays-in returns RES in BEG,END after overlays OVL were
@@ -691,10 +938,10 @@ with parameters from the *Messages* buffer modification."
(deftest-overlays-in-1 af 10 11 (a) (a 10 10))
-;; behaviour at point-max
+;; behavior at point-max
(ert-deftest test-overlays-in-2 ()
(cl-macrolet ((should-length (n list)
- `(should (= ,n (length ,list)))))
+ `(should (= ,n (length ,list)))))
(with-temp-buffer
(insert (make-string 100 ?\s))
(make-overlay (point-max) (point-max))
@@ -703,13 +950,13 @@ with parameters from the *Messages* buffer modification."
(should-length 2 (overlays-in 1 (point-max)))
(should-length 1 (overlays-in (point-max) (point-max)))
(narrow-to-region 1 50)
- (should-length 0 (overlays-in 1 (point-max)))
+ (should-length 1 (overlays-in 1 (point-max)))
(should-length 1 (overlays-in (point-max) (point-max))))))
-
-;; +===================================================================================+
+
+;; +==========================================================================+
;; | overlay-recenter
-;; +===================================================================================+
+;; +==========================================================================+
;; This function is a noop in the overlay tree branch.
(ert-deftest test-overlay-recenter ()
@@ -720,10 +967,10 @@ with parameters from the *Messages* buffer modification."
(make-overlay i (1+ i))
(should-not (overlay-recenter i)))))
-
-;; +===================================================================================+
+
+;; +==========================================================================+
;; | move-overlay
-;; +===================================================================================+
+;; +==========================================================================+
;; buffer nil with live overlay
(ert-deftest test-move-overlay-1 ()
@@ -767,23 +1014,9 @@ with parameters from the *Messages* buffer modification."
(should-not (overlay-end ov))
(should-not (overlay-buffer ov))))
-;; This used to fail.
-(ert-deftest test-move-overlay-5 ()
- (skip-unless (fboundp 'overlay-tree))
- (with-temp-buffer
- (insert (make-string 1 ?.))
- (let ((other (make-overlay 1 1)))
- (make-overlay 1 1)
- (insert "()")
- (move-overlay other (point-max) (1+ (point-max)) (current-buffer))
- (delete-overlay other))
- (should (= (plist-get (car (with-no-warnings (overlay-tree))) :limit)
- 1))))
-
-
-;; +===================================================================================+
+;; +==========================================================================+
;; | delete-(all-)overlay
-;; +===================================================================================+
+;; +==========================================================================+
;; delete live overlay
(ert-deftest test-delete-overlay-1 ()
@@ -814,22 +1047,22 @@ with parameters from the *Messages* buffer modification."
(should-not (delete-all-overlays (current-buffer)))
(should-not (delete-all-overlays))))
-
-;; +===================================================================================+
+
+;; +==========================================================================+
;; | get-char-property(-and-overlay)
-;; +===================================================================================+
+;; +==========================================================================+
;; FIXME: TBD
-
-;; +===================================================================================+
+
+;; +==========================================================================+
;; | Moving by insertions
-;; +===================================================================================+
+;; +==========================================================================+
(defmacro deftest-moving-insert-1 (id beg-end insert sbeg-send fa ra)
(cl-destructuring-bind (beg end ipos ilen sbeg send fa ra)
(append beg-end insert sbeg-send (list fa ra) nil)
- `(ert-deftest ,(make-overlay-test-name 'moving-insert 1 id) ()
+ `(ert-deftest ,(buffer-tests--make-test-name 'moving-insert 1 id) ()
(test-with-overlay-in-buffer (ov ,beg ,end ,fa ,ra)
(should (= ,beg (overlay-start ov)))
(should (= ,end (overlay-end ov)))
@@ -931,21 +1164,21 @@ with parameters from the *Messages* buffer modification."
(should (= 25 (overlay-start right)))
(should (= 75 (overlay-end right)))
;; Try to detect the error, by removing left. The should fail
- ;; an eassert, since it won't be found by a reular tree
+ ;; an eassert, since it won't be found by a regular tree
;; traversal - in theory.
(delete-overlay left)
(should (= 2 (length (overlays-in 1 (point-max))))))))
-
-;; +===================================================================================+
+
+;; +==========================================================================+
;; | Moving by deletions
-;; +===================================================================================+
+;; +==========================================================================+
(defmacro deftest-moving-delete-1 (id beg-end delete sbeg-send fa ra)
(cl-destructuring-bind (beg end dpos dlen sbeg send fa ra)
(append beg-end delete sbeg-send (list fa ra) nil)
- `(ert-deftest ,(make-overlay-test-name 'moving-delete 1 id) ()
+ `(ert-deftest ,(buffer-tests--make-test-name 'moving-delete 1 id) ()
(test-with-overlay-in-buffer (ov ,beg ,end ,fa ,ra)
(should (= ,beg (overlay-start ov)))
(should (= ,end (overlay-end ov)))
@@ -1002,12 +1235,12 @@ with parameters from the *Messages* buffer modification."
(deftest-moving-delete-1 e (15 15) (5 5) (10 10) t t)
(deftest-moving-delete-1 f (15 15) (15 3) (15 15) t t)
-
-;; +===================================================================================+
+
+;; +==========================================================================+
;; | make-indirect-buffer
-;; +===================================================================================+
+;; +==========================================================================+
-;; Check if overlays are cloned/seperate from indirect buffer.
+;; Check if overlays are cloned/separate from indirect buffer.
(ert-deftest test-make-indirect-buffer-1 ()
(with-temp-buffer
(dotimes (_ 10) (make-overlay 1 1))
@@ -1045,22 +1278,22 @@ with parameters from the *Messages* buffer modification."
(kill-buffer indirect))))))
-
-;; +===================================================================================+
+
+;; +==========================================================================+
;; | buffer-swap-text
-;; +===================================================================================+
+;; +==========================================================================+
-(defmacro test-with-temp-buffers (vars &rest body)
+(defmacro buffer-tests--with-temp-buffers (vars &rest body)
(declare (indent 1) (debug (sexp &rest form)))
(if (null vars)
`(progn ,@body)
`(with-temp-buffer
(let ((,(car vars) (current-buffer)))
- (test-with-temp-buffers ,(cdr vars) ,@body)))))
+ (buffer-tests--with-temp-buffers ,(cdr vars) ,@body)))))
;; basic
(ert-deftest test-buffer-swap-text-1 ()
- (test-with-temp-buffers (buffer other)
+ (buffer-tests--with-temp-buffers (buffer other)
(with-current-buffer buffer
(let ((ov (make-overlay 1 1)))
(buffer-swap-text other)
@@ -1070,8 +1303,8 @@ with parameters from the *Messages* buffer modification."
(should (eq ov (car (overlays-in 1 1)))))))))
;; properties
-(ert-deftest test-buffer-swap-text-1 ()
- (test-with-temp-buffers (buffer other)
+(ert-deftest test-buffer-swap-text-2 ()
+ (buffer-tests--with-temp-buffers (buffer other)
(with-current-buffer other
(overlay-put (make-overlay 1 1) 'buffer 'other))
(with-current-buffer buffer
@@ -1083,10 +1316,10 @@ with parameters from the *Messages* buffer modification."
(should (= 1 (length (overlays-in 1 1))))
(should (eq (overlay-get (car (overlays-in 1 1)) 'buffer) 'buffer)))))
-
-;; +===================================================================================+
+
+;; +==========================================================================+
;; | priorities
-;; +===================================================================================+
+;; +==========================================================================+
(ert-deftest test-overlay-priorities-1 ()
(with-temp-buffer
@@ -1107,10 +1340,10 @@ with parameters from the *Messages* buffer modification."
(overlay-put ov 'value i)))
(should (eq 9 (get-char-property 1 'value)))))
-
-;; +===================================================================================+
+
+;; +==========================================================================+
;; | Other
-;; +===================================================================================+
+;; +==========================================================================+
(defun test-overlay-regions ()
(sort (mapcar (lambda (ov)
@@ -1226,9 +1459,10 @@ with parameters from the *Messages* buffer modification."
(nonempty-eob (make-overlay 4 5))
(empty-eob (make-overlay 5 5)))
(set-buffer-multibyte nil)
- (cl-macrolet ((ovshould (ov begin end)
- `(should (equal (list (overlay-start ,ov) (overlay-end ,ov))
- (list ,begin ,end)))))
+ (cl-macrolet
+ ((ovshould (ov begin end)
+ `(should (equal (list (overlay-start ,ov) (overlay-end ,ov))
+ (list ,begin ,end)))))
(ovshould nonempty-bob 1 3)
(ovshould empty-bob 1 1)
(ovshould empty 3 3)
@@ -1257,9 +1491,10 @@ with parameters from the *Messages* buffer modification."
(nonempty-eob-end (make-overlay 6 9))
(empty-eob (make-overlay 9 9)))
(set-buffer-multibyte t)
- (cl-macrolet ((ovshould (ov begin end)
- `(should (equal (list (overlay-start ,ov) (overlay-end ,ov))
- (list ,begin ,end)))))
+ (cl-macrolet
+ ((ovshould (ov begin end)
+ `(should (equal (list (overlay-start ,ov) (overlay-end ,ov))
+ (list ,begin ,end)))))
(ovshould nonempty-bob-end 1 2)
(ovshould nonempty-bob-beg 1 2)
(ovshould empty-bob 1 1)
@@ -1280,6 +1515,7 @@ with parameters from the *Messages* buffer modification."
;; | Autogenerated insert/delete/narrow tests
;; +===================================================================================+
+(when nil ;; Let's comment these out for now.
;; (defun test-overlay-generate-test (name)
;; (interactive)
@@ -7733,4 +7969,247 @@ with parameters from the *Messages* buffer modification."
(101 . 138)
(103 . 103))))))
+) ;; End of `when nil' for autogenerated insert/delete/narrow tests.
+
+(ert-deftest buffer-multibyte-overlong-sequences ()
+ (dolist (uni '("\xE0\x80\x80"
+ "\xF0\x80\x80\x80"
+ "\xF8\x8F\xBF\xBF\x80"))
+ (let ((multi (string-to-multibyte uni)))
+ (should
+ (string-equal
+ multi
+ (with-temp-buffer
+ (set-buffer-multibyte nil)
+ (insert uni)
+ (set-buffer-multibyte t)
+ (buffer-string)))))))
+
+;; https://debbugs.gnu.org/33492
+(ert-deftest buffer-tests-buffer-local-variables-undo ()
+ "Test that `buffer-undo-list' appears in `buffer-local-variables'."
+ (with-temp-buffer
+ (should (assq 'buffer-undo-list (buffer-local-variables)))))
+
+(ert-deftest buffer-tests-inhibit-buffer-hooks ()
+ "Test `get-buffer-create' argument INHIBIT-BUFFER-HOOKS."
+ (let* (run-bluh (bluh (lambda () (setq run-bluh t))))
+ (unwind-protect
+ (let* ( run-kbh (kbh (lambda () (setq run-kbh t)))
+ run-kbqf (kbqf (lambda () (setq run-kbqf t))) )
+
+ ;; Inhibited.
+ (add-hook 'buffer-list-update-hook bluh)
+ (with-current-buffer (generate-new-buffer " foo" t)
+ (add-hook 'kill-buffer-hook kbh nil t)
+ (add-hook 'kill-buffer-query-functions kbqf nil t)
+ (kill-buffer))
+ (with-temp-buffer (ignore))
+ (with-output-to-string (ignore))
+ (should-not run-bluh)
+ (should-not run-kbh)
+ (should-not run-kbqf)
+
+ ;; Not inhibited.
+ (with-current-buffer (generate-new-buffer " foo")
+ (should run-bluh)
+ (add-hook 'kill-buffer-hook kbh nil t)
+ (add-hook 'kill-buffer-query-functions kbqf nil t)
+ (kill-buffer))
+ (should run-kbh)
+ (should run-kbqf))
+ (remove-hook 'buffer-list-update-hook bluh))))
+
+(ert-deftest buffer-tests-inhibit-buffer-hooks-indirect ()
+ "Indirect buffers do not call `get-buffer-create'."
+ (dolist (inhibit '(nil t))
+ (let ((base (get-buffer-create "foo" inhibit)))
+ (unwind-protect
+ (dotimes (_i 11)
+ (let* (flag*
+ (flag (lambda () (prog1 t (setq flag* t))))
+ (indirect (make-indirect-buffer base "foo[indirect]" nil
+ inhibit)))
+ (unwind-protect
+ (progn
+ (with-current-buffer indirect
+ (add-hook 'kill-buffer-query-functions flag nil t))
+ (kill-buffer indirect)
+ (if inhibit
+ (should-not flag*)
+ (should flag*)))
+ (let (kill-buffer-query-functions)
+ (when (buffer-live-p indirect)
+ (kill-buffer indirect))))))
+ (let (kill-buffer-query-functions)
+ (when (buffer-live-p base)
+ (kill-buffer base)))))))
+
+(ert-deftest zero-length-overlays-and-not ()
+ (with-temp-buffer
+ (insert "hello")
+ (let ((long-overlay (make-overlay 2 4))
+ (zero-overlay (make-overlay 3 3)))
+ ;; Exclude.
+ (should (= (length (overlays-at 3)) 1))
+ (should (eq (car (overlays-at 3)) long-overlay))
+ ;; Include.
+ (should (= (length (overlays-in 3 3)) 2))
+ (should (memq long-overlay (overlays-in 3 3)))
+ (should (memq zero-overlay (overlays-in 3 3))))))
+
+(ert-deftest test-remove-overlays ()
+ (with-temp-buffer
+ (insert "foo")
+ (make-overlay (point) (point))
+ (should (= (length (overlays-in (point-min) (point-max))) 1))
+ (remove-overlays)
+ (should (= (length (overlays-in (point-min) (point-max))) 0)))
+
+ (with-temp-buffer
+ (insert "foo")
+ (goto-char 2)
+ (make-overlay (point) (point))
+ ;; We only count zero-length overlays at the end of the buffer.
+ (should (= (length (overlays-in 1 2)) 0))
+ (narrow-to-region 1 2)
+ ;; We've now narrowed, so the zero-length overlay is at the end of
+ ;; the (accessible part of the) buffer.
+ (should (= (length (overlays-in 1 2)) 1))
+ (remove-overlays)
+ (should (= (length (overlays-in (point-min) (point-max))) 0))))
+
+(ert-deftest test-kill-buffer-auto-save-default ()
+ (ert-with-temp-file file
+ (let (auto-save)
+ ;; Always answer yes.
+ (cl-letf (((symbol-function #'yes-or-no-p) (lambda (_) t)))
+ (unwind-protect
+ (progn
+ (find-file file)
+ (auto-save-mode t)
+ (insert "foo\n")
+ (should buffer-auto-save-file-name)
+ (setq auto-save buffer-auto-save-file-name)
+ (do-auto-save)
+ (should (file-exists-p auto-save))
+ (kill-buffer (current-buffer))
+ (should (file-exists-p auto-save)))
+ (when auto-save
+ (ignore-errors (delete-file auto-save))))))))
+
+(ert-deftest test-kill-buffer-auto-save-delete ()
+ (ert-with-temp-file file
+ (let (auto-save)
+ (should (file-exists-p file))
+ (setq kill-buffer-delete-auto-save-files t)
+ ;; Always answer yes.
+ (cl-letf (((symbol-function #'yes-or-no-p) (lambda (_) t)))
+ (unwind-protect
+ (progn
+ (find-file file)
+ (auto-save-mode t)
+ (insert "foo\n")
+ (should buffer-auto-save-file-name)
+ (setq auto-save buffer-auto-save-file-name)
+ (do-auto-save)
+ (should (file-exists-p auto-save))
+ ;; This should delete the auto-save file.
+ (kill-buffer (current-buffer))
+ (should-not (file-exists-p auto-save)))
+ (ignore-errors (delete-file file))
+ (when auto-save
+ (ignore-errors (delete-file auto-save)))))
+ ;; Answer no to deletion.
+ (cl-letf (((symbol-function #'yes-or-no-p)
+ (lambda (prompt)
+ (not (string-search "Delete auto-save file" prompt)))))
+ (unwind-protect
+ (progn
+ (find-file file)
+ (auto-save-mode t)
+ (insert "foo\n")
+ (should buffer-auto-save-file-name)
+ (setq auto-save buffer-auto-save-file-name)
+ (do-auto-save)
+ (should (file-exists-p auto-save))
+ ;; This should not delete the auto-save file.
+ (kill-buffer (current-buffer))
+ (should (file-exists-p auto-save)))
+ (when auto-save
+ (ignore-errors (delete-file auto-save))))))))
+
+(ert-deftest test-buffer-modifications ()
+ (ert-with-temp-file file
+ (with-current-buffer (find-file file)
+ (auto-save-mode 1)
+ (should-not (buffer-modified-p))
+ (insert "foo")
+ (should (buffer-modified-p))
+ (should-not (eq (buffer-modified-p) 'autosaved))
+ (do-auto-save nil t)
+ (should (eq (buffer-modified-p) 'autosaved))
+ (with-silent-modifications
+ (put-text-property 1 3 'face 'bold))
+ (should (eq (buffer-modified-p) 'autosaved))
+ (save-buffer)
+ (should-not (buffer-modified-p))
+ (with-silent-modifications
+ (put-text-property 1 3 'face 'italic))
+ (should-not (buffer-modified-p)))))
+
+(ert-deftest test-restore-buffer-modified-p ()
+ (ert-with-temp-file file
+ ;; This avoids the annoying "foo and bar are the same file" on
+ ;; MS-Windows.
+ (setq file (file-truename file))
+ (with-current-buffer (find-file file)
+ (auto-save-mode 1)
+ (should-not (eq (buffer-modified-p) t))
+ (insert "foo")
+ (should (buffer-modified-p))
+ (restore-buffer-modified-p nil)
+ (should-not (buffer-modified-p))
+ (insert "bar")
+ (do-auto-save nil t)
+ (should (eq (buffer-modified-p) 'autosaved))
+ (insert "zot")
+ (restore-buffer-modified-p 'autosaved)
+ (should (eq (buffer-modified-p) 'autosaved))
+
+ ;; Clean up.
+ (when (file-exists-p buffer-auto-save-file-name)
+ (delete-file buffer-auto-save-file-name))))
+
+ (ert-with-temp-file file
+ (setq file (file-truename file))
+ (with-current-buffer (find-file file)
+ (auto-save-mode 1)
+ (should-not (eq (buffer-modified-p) t))
+ (insert "foo")
+ (should (buffer-modified-p))
+ (should-not (eq (buffer-modified-p) 'autosaved))
+ (restore-buffer-modified-p 'autosaved)
+ (should (eq (buffer-modified-p) 'autosaved)))))
+
+(ert-deftest test-buffer-chars-modified-ticks ()
+ "Test `buffer-chars-modified-tick'."
+ (setq temporary-file-directory (file-truename temporary-file-directory))
+ (let ((text "foobar")
+ f1 f2)
+ (unwind-protect
+ (progn
+ (setq f1 (make-temp-file "buf-modiff-tests")
+ f2 (make-temp-file "buf-modiff-tests"))
+ (with-current-buffer (find-file f1)
+ (should (= (buffer-chars-modified-tick) 1))
+ (should (= (buffer-chars-modified-tick) (buffer-modified-tick)))
+ (write-region text nil f2 nil 'silent)
+ (insert-file-contents f2)
+ (should (= (buffer-chars-modified-tick) (buffer-modified-tick)))
+ (should (> (buffer-chars-modified-tick) 1))))
+ (if f1 (delete-file f1))
+ (if f2 (delete-file f2))
+ )))
+
;;; buffer-tests.el ends here
diff --git a/test/src/callint-tests.el b/test/src/callint-tests.el
new file mode 100644
index 00000000000..5a633fdc2bd
--- /dev/null
+++ b/test/src/callint-tests.el
@@ -0,0 +1,68 @@
+;;; callint-tests.el --- unit tests for callint.c -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2018-2022 Free Software Foundation, Inc.
+
+;; Author: Philipp Stephani <phst@google.com>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Unit tests for src/callint.c.
+
+;;; Code:
+
+(require 'ert)
+
+(ert-deftest call-interactively/incomplete-multibyte-sequence ()
+ "Check that Bug#30004 is fixed."
+ (let* ((text-quoting-style 'grave)
+ (data (should-error (call-interactively (lambda () (interactive "\xFF"))))))
+ (should
+ (equal
+ (cdr data)
+ '("Invalid control letter `\u00FF' (#o377, #x00ff) in interactive calling string")))))
+
+(ert-deftest call-interactively/embedded-nulls ()
+ "Check that Bug#30005 is fixed."
+ (should (equal (let ((unread-command-events '(?a ?b)))
+ (call-interactively (lambda (a b)
+ (interactive "ka\0a: \nkb: ")
+ (list a b))))
+ '("a" "b"))))
+
+(ert-deftest call-interactively-prune-command-history ()
+ "Check that Bug#31211 is fixed."
+ (let ((history-length 1)
+ (command-history ()))
+ (dotimes (_ (1+ history-length))
+ (call-interactively #'ignore t))
+ (should (= (length command-history) history-length))))
+
+(defun callint-test-int-args (foo bar &optional zot)
+ (declare (interactive-args
+ (bar 10)
+ (zot 11)))
+ (interactive (list 1 1 1))
+ (+ foo bar zot))
+
+(ert-deftest test-interactive-args ()
+ (let ((history-length 1)
+ (command-history ()))
+ (should (= (call-interactively 'callint-test-int-args t) 3))
+ (should (equal command-history '((callint-test-int-args 1 10 11))))))
+
+;;; callint-tests.el ends here
diff --git a/test/src/callproc-tests.el b/test/src/callproc-tests.el
index fcba6914a5d..f44c7e199f6 100644
--- a/test/src/callproc-tests.el
+++ b/test/src/callproc-tests.el
@@ -1,6 +1,6 @@
;;; callproc-tests.el --- callproc.c tests -*- lexical-binding: t -*-
-;; Copyright (C) 2016-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2022 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -17,6 +17,11 @@
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+;;
+;; Unit tests for src/callproc.c.
+
;;; Code:
(require 'ert)
@@ -37,3 +42,38 @@
(split-string-and-unquote (buffer-string)))
(should (equal initial-shell "nil"))
(should-not (equal initial-shell shell))))
+
+(ert-deftest call-process-w32-debug-spawn-error ()
+ "Check that debugger runs on `call-process' failure (Bug#33016)."
+ (skip-unless (eq system-type 'windows-nt))
+ (let* ((debug-on-error t)
+ (have-called-debugger nil)
+ (debugger (lambda (&rest _)
+ (setq have-called-debugger t)
+ ;; Allow entering the debugger later in the same
+ ;; test run, before going back to the command
+ ;; loop.
+ (setq internal-when-entered-debugger -1))))
+ (should (eq :got-error ;; NOTE: `should-error' would inhibit debugger.
+ (condition-case-unless-debug ()
+ ;; On MS-Windows, "nul.FOO" resolves to the null
+ ;; device, and thus acts like an always-empty
+ ;; file, for any FOO, in any directory. So
+ ;; c:/null.exe passes Emacs' test for the file's
+ ;; existence, and ensures we hit an error in the
+ ;; w32 process spawn code.
+ (call-process "c:/nul.exe")
+ (error :got-error))))
+ (should have-called-debugger)))
+
+(ert-deftest call-process-region-entire-buffer-with-delete ()
+ "Check that Bug#40576 is fixed."
+ (let ((emacs (expand-file-name invocation-name invocation-directory)))
+ (skip-unless (file-executable-p emacs))
+ (with-temp-buffer
+ (insert "Buffer contents\n")
+ (should
+ (eq (call-process-region nil nil emacs :delete nil nil "--version") 0))
+ (should (eq (buffer-size) 0)))))
+
+;;; callproc-tests.el ends here
diff --git a/test/src/casefiddle-tests.el b/test/src/casefiddle-tests.el
index 0a9b6c20ec9..652af417293 100644
--- a/test/src/casefiddle-tests.el
+++ b/test/src/casefiddle-tests.el
@@ -1,6 +1,6 @@
;;; casefiddle-tests.el --- tests for casefiddle.c functions -*- lexical-binding: t -*-
-;; Copyright (C) 2015-2016 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2016, 2018-2022 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -57,7 +57,7 @@
errors)))
(setq expected (cdr expected)))))
(when errors
- (ert-fail (mapconcat (lambda (line) line) (nreverse errors) "")))))
+ (ert-fail (mapconcat #'identity (nreverse errors))))))
(defconst casefiddle-tests--characters
@@ -98,7 +98,7 @@
errors)))
(setq props (cdr props) tabs (cdr tabs) expected (cdr expected)))))
(when errors
- (mapconcat (lambda (line) line) (nreverse errors) "")))))
+ (mapconcat #'identity (nreverse errors))))))
(ert-deftest casefiddle-tests-casing-character ()
@@ -116,7 +116,7 @@
errors)))
(setq funcs (cdr funcs) expected (cdr expected)))))
(when errors
- (mapconcat (lambda (line) line) (nreverse errors) "")))))
+ (mapconcat (lambda (line) line) (nreverse errors))))))
(ert-deftest casefiddle-tests-casing-word ()
@@ -196,7 +196,7 @@
("fish" "FISH" "fish" "Fish" "Fish")
("Straße" "STRASSE" "straße" "Straße" "Straße")
- ;; The word repeated twice to test behaviour at the end of a word
+ ;; The word repeated twice to test behavior at the end of a word
;; inside of an input string as well as at the end of the string.
("ΌΣΟΣ ΌΣΟΣ" "ΌΣΟΣ ΌΣΟΣ" "όσος όσος" "Όσος Όσος" "ΌΣΟΣ ΌΣΟΣ")
;; What should be done with sole sigma? It is ‘final’ but on the
@@ -247,7 +247,8 @@
;; input upcase downcase [titlecase]
(dolist (test '((?a ?A ?a) (?A ?A ?a)
(?ł ?Ł ?ł) (?Ł ?Ł ?ł)
- (?ß ?ß ?ß) (?ẞ ?ẞ ?ß)
+ ;; We char-upcase ß to ẞ; see bug #11309.
+ (?ß ?ẞ ?ß) (?ẞ ?ẞ ?ß)
(?ⅷ ?Ⅷ ?ⅷ) (?Ⅷ ?Ⅷ ?ⅷ)
(?DŽ ?DŽ ?dž ?Dž) (?Dž ?DŽ ?dž ?Dž) (?dž ?DŽ ?dž ?Dž)))
(let ((ch (car test))
@@ -259,5 +260,38 @@
(should (eq tc (capitalize ch)))
(should (eq tc (upcase-initials ch))))))
+(defvar casefiddle-oldfunc region-extract-function)
+
+(defun casefiddle-loopfunc (method)
+ (if (eq method 'bounds)
+ (let ((looping (list '(1 . 1))))
+ (setcdr looping looping))
+ (funcall casefiddle-oldfunc method)))
+
+(defun casefiddle-badfunc (method)
+ (if (eq method 'bounds)
+ '(())
+ (funcall casefiddle-oldfunc method)))
+
+(ert-deftest casefiddle-invalid-region-extract-function ()
+ (dolist (region-extract-function '(casefiddle-badfunc casefiddle-loopfunc))
+ (with-temp-buffer
+ (should-error (upcase-region nil nil t)))))
+
+(ert-deftest casefiddle-turkish ()
+ (skip-unless (member "tr_TR.utf8" (get-locale-names)))
+ ;; See bug#50752. The point is that unibyte and multibyte strings
+ ;; are upcased differently in the "dotless i" case in Turkish,
+ ;; turning ASCII into non-ASCII, which is very unusual.
+ (with-locale-environment "tr_TR.utf8"
+ (should (string-equal (downcase "I ı") "ı ı"))
+ (should (string-equal (downcase "İ i") "i̇ i"))
+ (should (string-equal (downcase "I") "i"))
+ (should (string-equal (capitalize "bIte") "Bite"))
+ (should (string-equal (capitalize "bIté") "Bıté"))
+ (should (string-equal (capitalize "indIa") "India"))
+ ;; This does not work -- it produces "Indıa".
+ ;;(should (string-equal (capitalize "indIá") "İndıa"))
+ ))
;;; casefiddle-tests.el ends here
diff --git a/test/src/character-tests.el b/test/src/character-tests.el
new file mode 100644
index 00000000000..f83bac333d7
--- /dev/null
+++ b/test/src/character-tests.el
@@ -0,0 +1,47 @@
+;;; character-tests.el --- tests for character.c -*- lexical-binding:t -*-
+
+;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+
+(ert-deftest character-test-string-width ()
+ "Test `string-width' with and without compositions."
+ (should (= (string-width "1234") 4))
+ (should (= (string-width "12\t34") (+ 4 tab-width)))
+ (should (= (string-width "áëòç") 4))
+ (should (= (string-width "áëòç") 4))
+ (should (= (string-width "הַרְבֵּה אַהֲבָה") 9))
+ (should (= (string-width "1234" 1 3) 2))
+ (should (= (string-width "1234" nil -1) 3))
+ (should (= (string-width "1234" 2) 2))
+ (should-error (string-width "1234" nil 5))
+ (should-error (string-width "1234" -5))
+ (should (= (string-width "12\t34") (+ 4 tab-width)))
+ (should (= (string-width "1234\t56") (+ 6 tab-width)))
+ (should (= (string-width "áëòç") 4))
+ (should (= (string-width "áëòç" nil 3) 3))
+ (should (= (string-width "áëòç" 1 3) 2))
+ (should (= (string-width "áëòç" nil 2) 1))
+ (should (= (string-width "áëòç" nil 3) 2))
+ (should (= (string-width "áëòç" nil 4) 2))
+ (should (= (string-width "הַרְבֵּה אַהֲבָה") 9))
+ (should (= (string-width "הַרְבֵּה אַהֲבָה" nil 8) 4)))
+
+;;; character-tests.el ends here
diff --git a/test/src/charset-tests.el b/test/src/charset-tests.el
index c3f09ec1a0a..51eb040e77a 100644
--- a/test/src/charset-tests.el
+++ b/test/src/charset-tests.el
@@ -1,26 +1,30 @@
-;;; charset-tests.el --- Tests for charset.c
+;;; charset-tests.el --- Tests for charset.c -*- lexical-binding: t -*-
-;; Copyright 2017 Free Software Foundation, Inc.
+;; Copyright 2017-2022 Free Software Foundation, Inc.
-;; This program is free software; you can redistribute it and/or modify
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
-;; This program is distributed in the hope that it will be useful,
+;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
-;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Code:
(require 'ert)
(ert-deftest charset-decode-char ()
- "Test decode-char."
+ "Test `decode-char'."
(should-error (decode-char 'ascii 0.5)))
(provide 'charset-tests)
+
+;;; charset-tests.el ends here
diff --git a/test/src/chartab-tests.el b/test/src/chartab-tests.el
index 2c57f27ff8b..e4c4b065376 100644
--- a/test/src/chartab-tests.el
+++ b/test/src/chartab-tests.el
@@ -1,21 +1,23 @@
-;;; chartab-tests.el --- Tests for char-tab.c
+;;; chartab-tests.el --- Tests for char-tab.c -*- lexical-binding: t -*-
-;; Copyright (C) 2016-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2022 Free Software Foundation, Inc.
;; Author: Eli Zaretskii <eliz@gnu.org>
-;; This program is free software; you can redistribute it and/or modify
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
-;; This program is distributed in the hope that it will be useful,
+;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
-;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Code:
@@ -47,5 +49,25 @@
(#xe0e00 . #xe0ef6)
)))
+(ert-deftest chartab-test-char-table-p ()
+ (should (char-table-p (make-char-table 'foo)))
+ (should (not (char-table-p (make-hash-table)))))
+
+(ert-deftest chartab-test-char-table-subtype ()
+ (should (eq (char-table-subtype (make-char-table 'foo)) 'foo)))
+
+(ert-deftest chartab-test-char-table-parent ()
+ (should (eq (char-table-parent (make-char-table 'foo)) nil))
+ (let ((parent (make-char-table 'foo))
+ (child (make-char-table 'bar)))
+ (set-char-table-parent child parent)
+ (should (eq (char-table-parent child) parent))))
+
+(ert-deftest chartab-test-char-table-extra-slot ()
+ ;; Use any type with extra slots, e.g. 'case-table.
+ (let ((tbl (make-char-table 'case-table)))
+ (set-char-table-extra-slot tbl 1 'bar)
+ (should (eq (char-table-extra-slot tbl 1) 'bar))))
+
(provide 'chartab-tests)
;;; chartab-tests.el ends here
diff --git a/test/src/cmds-tests.el b/test/src/cmds-tests.el
index a545d0e08b5..73e933eb372 100644
--- a/test/src/cmds-tests.el
+++ b/test/src/cmds-tests.el
@@ -1,22 +1,24 @@
-;;; cmds-tests.el --- Testing some Emacs commands
+;;; cmds-tests.el --- Testing some Emacs commands -*- lexical-binding: t -*-
-;; Copyright (C) 2013-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2022 Free Software Foundation, Inc.
;; Author: Nicolas Richard <youngfrog@members.fsf.org>
;; Keywords:
-;; This program is free software; you can redistribute it and/or modify
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
-;; This program is distributed in the hope that it will be useful,
+;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
-;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
@@ -30,5 +32,13 @@
(let ((last-command-event ?a))
(should-error (self-insert-command -1))))
+(ert-deftest forward-line-with-bignum ()
+ (with-temp-buffer
+ (insert "x\n")
+ (let ((shortage (forward-line (1- most-negative-fixnum))))
+ (should (= shortage most-negative-fixnum)))
+ (let ((shortage (forward-line (+ 2 most-positive-fixnum))))
+ (should (= shortage (1+ most-positive-fixnum))))))
+
(provide 'cmds-tests)
;;; cmds-tests.el ends here
diff --git a/test/src/coding-tests.el b/test/src/coding-tests.el
index e0cefa94356..f65d575d0c2 100644
--- a/test/src/coding-tests.el
+++ b/test/src/coding-tests.el
@@ -1,6 +1,6 @@
-;;; coding-tests.el --- tests for text encoding and decoding
+;;; coding-tests.el --- tests for text encoding and decoding -*- lexical-binding: t -*-
-;; Copyright (C) 2013-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2022 Free Software Foundation, Inc.
;; Author: Eli Zaretskii <eliz@gnu.org>
;; Author: Kenichi Handa <handa@gnu.org>
@@ -56,21 +56,22 @@
(set-buffer-multibyte nil)
(insert (encode-coding-string "あ" 'euc-jp) "\xd" "\n")
(decode-coding-region (point-min) (point-max) 'euc-jp-dos)
- (should-not (string-match-p "\^M" (buffer-string)))))
+ (should-not (string-search "\^M" (buffer-string)))))
;; Return the contents (specified by CONTENT-TYPE; ascii, latin, or
;; binary) of a test file.
(defun coding-tests-file-contents (content-type)
- (let* ((ascii "ABCDEFGHIJKLMNOPQRSTUVWXYZ\n")
- (latin (concat ascii "ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ\n"))
- (binary (string-to-multibyte
- (concat (string-as-unibyte latin)
- (unibyte-string #xC0 #xC1 ?\n)))))
- (cond ((eq content-type 'ascii) ascii)
- ((eq content-type 'latin) latin)
- ((eq content-type 'binary) binary)
- (t
- (error "Invalid file content type: %s" content-type)))))
+ (with-suppressed-warnings ((obsolete string-as-unibyte))
+ (let* ((ascii "ABCDEFGHIJKLMNOPQRSTUVWXYZ\n")
+ (latin (concat ascii "ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ\n"))
+ (binary (string-to-multibyte
+ (concat (string-as-unibyte latin)
+ (unibyte-string #xC0 #xC1 ?\n)))))
+ (cond ((eq content-type 'ascii) ascii)
+ ((eq content-type 'latin) latin)
+ ((eq content-type 'binary) binary)
+ (t
+ (error "Invalid file content type: %s" content-type))))))
;; Generate FILE with CONTENTS encoded by CODING-SYSTEM.
;; whose encoding specified by CODING-SYSTEM.
@@ -143,7 +144,7 @@
;; Optional 5th arg TRANSLATOR is a function to translate the original
;; file contents to match with the expected result of decoding. For
;; instance, when a file of dos eol-type is read by unix eol-type,
-;; `decode-test-lf-to-crlf' must be specified.
+;; `coding-tests-lf-to-crlf' must be specified.
(defun coding-tests (content-type write-coding read-coding detected-coding
&optional translator)
@@ -296,7 +297,7 @@
;;; decoder, not for regression testing.
(defun generate-ascii-file ()
- (dotimes (i 100000)
+ (dotimes (_i 100000)
(insert-char ?a 80)
(insert "\n")))
@@ -309,13 +310,13 @@
(insert "\n")))
(defun generate-mostly-nonascii-file ()
- (dotimes (i 30000)
+ (dotimes (_i 30000)
(insert-char ?a 80)
(insert "\n"))
- (dotimes (i 20000)
+ (dotimes (_i 20000)
(insert-char ?À 80)
(insert "\n"))
- (dotimes (i 10000)
+ (dotimes (_i 10000)
(insert-char ?あ 80)
(insert "\n")))
@@ -359,7 +360,7 @@
(delete-region (point-min) (point))))))
(defun benchmark-decoder ()
- (let ((gc-cons-threshold 4000000))
+ (let ((gc-cons-threshold (max gc-cons-threshold 4000000)))
(insert "Without optimization:\n")
(dolist (files test-file-list)
(dolist (file (cdr files))
@@ -375,9 +376,59 @@
(with-temp-buffer (insert-file-contents (car file))))))
(insert (format "%s: %s\n" (car file) result)))))))
-;; Local Variables:
-;; byte-compile-warnings: (not obsolete)
-;; End:
+(ert-deftest coding-nocopy-trivial ()
+ "Check that the NOCOPY parameter works for the trivial coding system."
+ (let ((s "abc"))
+ (should-not (eq (decode-coding-string s nil nil) s))
+ (should (eq (decode-coding-string s nil t) s))
+ (should-not (eq (encode-coding-string s nil nil) s))
+ (should (eq (encode-coding-string s nil t) s))))
+
+(ert-deftest coding-nocopy-ascii ()
+ "Check that the NOCOPY parameter works for ASCII-only strings."
+ (let* ((uni (apply #'string (number-sequence 0 127)))
+ (multi (string-to-multibyte uni)))
+ (dolist (s (list uni multi))
+ ;; Encodings without EOL conversion.
+ (dolist (coding '(us-ascii-unix iso-latin-1-unix utf-8-unix))
+ (should-not (eq (decode-coding-string s coding nil) s))
+ (should-not (eq (encode-coding-string s coding nil) s))
+ (should (eq (decode-coding-string s coding t) s))
+ (should (eq (encode-coding-string s coding t) s))
+ (should (eq last-coding-system-used coding)))
+
+ ;; With EOL conversion inhibited.
+ (let ((inhibit-eol-conversion t))
+ (dolist (coding '(us-ascii iso-latin-1 utf-8))
+ (should-not (eq (decode-coding-string s coding nil) s))
+ (should-not (eq (encode-coding-string s coding nil) s))
+ (should (eq (decode-coding-string s coding t) s))
+ (should (eq (encode-coding-string s coding t) s))))))
+
+ ;; Check identity decoding with EOL conversion for ASCII except CR.
+ (let* ((uni (apply #'string (delq ?\r (number-sequence 0 127))))
+ (multi (string-to-multibyte uni)))
+ (dolist (s (list uni multi))
+ (dolist (coding '(us-ascii-dos iso-latin-1-dos utf-8-dos mac-roman-mac))
+ (should-not (eq (decode-coding-string s coding nil) s))
+ (should (eq (decode-coding-string s coding t) s)))))
+
+ ;; Check identity encoding with EOL conversion for ASCII except LF.
+ (let* ((uni (apply #'string (delq ?\n (number-sequence 0 127))))
+ (multi (string-to-multibyte uni)))
+ (dolist (s (list uni multi))
+ (dolist (coding '(us-ascii-dos iso-latin-1-dos utf-8-dos mac-roman-mac))
+ (should-not (eq (encode-coding-string s coding nil) s))
+ (should (eq (encode-coding-string s coding t) s))))))
+
+
+(ert-deftest coding-check-coding-systems-region ()
+ (should (equal (check-coding-systems-region "aå" nil '(utf-8))
+ nil))
+ (should (equal (check-coding-systems-region "aåbγc" nil
+ '(utf-8 iso-latin-1 us-ascii))
+ '((iso-latin-1 3) (us-ascii 1 3))))
+ (should-error (check-coding-systems-region "å" nil '(bad-coding-system))))
(provide 'coding-tests)
-;; coding-tests.el ends here
+;;; coding-tests.el ends here
diff --git a/test/src/comp-resources/comp-test-45603.el b/test/src/comp-resources/comp-test-45603.el
new file mode 100644
index 00000000000..65147ee0156
--- /dev/null
+++ b/test/src/comp-resources/comp-test-45603.el
@@ -0,0 +1,29 @@
+;;; -*- lexical-binding: t; -*-
+
+;; Reduced from ivy.el.
+
+(defvar comp-test-45603-last)
+(defvar comp-test-45603-mark-prefix)
+(defvar comp-test-45603-directory)
+(defvar comp-test-45603-marked-candidates)
+
+(defun comp-test-45603--call-marked (_action)
+ (let* ((prefix-len (length comp-test-45603-mark-prefix))
+ (marked-candidates
+ (mapcar
+ (lambda (s)
+ (let ((cand (substring s prefix-len)))
+ (if comp-test-45603-directory
+ (expand-file-name cand comp-test-45603-directory)
+ cand)))
+ comp-test-45603-marked-candidates))
+ (_multi-action (comp-test-45603--get-multi-action comp-test-45603-last)))
+ marked-candidates))
+
+(defalias 'comp-test-45603--file-local-name
+ (if (fboundp 'file-local-name)
+ #'file-local-name
+ (lambda (file)
+ (or (file-remote-p file 'localname) file))))
+
+(provide 'comp-test-45603)
diff --git a/test/src/comp-resources/comp-test-funcs-dyn.el b/test/src/comp-resources/comp-test-funcs-dyn.el
new file mode 100644
index 00000000000..07f8671c6d9
--- /dev/null
+++ b/test/src/comp-resources/comp-test-funcs-dyn.el
@@ -0,0 +1,50 @@
+;;; comp-test-funcs-dyn.el --- compilation unit tested by comp-tests.el -*- lexical-binding: nil; -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+;; Author: Andrea Corallo <akrl@sdf.org>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'cl-lib)
+
+(defun comp-tests-ffuncall-callee-dyn-f (a b)
+ (list a b))
+
+(defun comp-tests-ffuncall-callee-opt-dyn-f (a b &optional c d)
+ (list a b c d))
+
+(defun comp-tests-ffuncall-callee-rest-dyn-f (a b &rest c)
+ (list a b c))
+
+(defun comp-tests-ffuncall-callee-opt-rest-dyn-f (a b &optional c &rest d)
+ (list a b c d))
+
+(defun comp-tests-cl-macro-exp-f ()
+ (cl-loop for xxx in '(a b)
+ for yyy = xxx
+ collect xxx))
+
+(cl-defun comp-tests-cl-uninterned-arg-parse-f (a &optional b &aux)
+ (list a b))
+
+(provide 'comp-test-dyn-funcs)
+
+;;; comp-test-funcs-dyn.el ends here
diff --git a/test/src/comp-resources/comp-test-funcs.el b/test/src/comp-resources/comp-test-funcs.el
new file mode 100644
index 00000000000..9092f040c80
--- /dev/null
+++ b/test/src/comp-resources/comp-test-funcs.el
@@ -0,0 +1,713 @@
+;;; comp-test-funcs.el --- compilation unit tested by comp-tests.el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2019-2022 Free Software Foundation, Inc.
+
+;; Author: Andrea Corallo <akrl@sdf.org>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(defvar comp-tests-var1 3)
+
+(defun comp-tests-varref-f ()
+ comp-tests-var1)
+
+(defun comp-tests-list-f ()
+ (list 1 2 3))
+(defun comp-tests-list2-f (a b c)
+ (list a b c))
+(defun comp-tests-car-f (x)
+ ;; Bcar
+ (car x))
+(defun comp-tests-cdr-f (x)
+ ;; Bcdr
+ (cdr x))
+(defun comp-tests-car-safe-f (x)
+ ;; Bcar_safe
+ (car-safe x))
+(defun comp-tests-cdr-safe-f (x)
+ ;; Bcdr_safe
+ (cdr-safe x))
+
+(defun comp-tests-cons-car-f ()
+ (car (cons 1 2)))
+(defun comp-tests-cons-cdr-f (x)
+ (cdr (cons 'foo x)))
+
+(defun comp-tests-hint-fixnum-f (n)
+ (1+ (comp-hint-fixnum n)))
+
+(defun comp-tests-hint-cons-f (c)
+ (car (comp-hint-cons c)))
+
+(defun comp-tests-varset0-f ()
+ (setq comp-tests-var1 55))
+(defun comp-tests-varset1-f ()
+ (setq comp-tests-var1 66)
+ 4)
+
+(defun comp-tests-length-f ()
+ (length '(1 2 3)))
+
+(defun comp-tests-aref-aset-f ()
+ (let ((vec (make-vector 3 0)))
+ (aset vec 2 100)
+ (aref vec 2)))
+
+(defvar comp-tests-var2 3)
+(defun comp-tests-symbol-value-f ()
+ (symbol-value 'comp-tests-var2))
+
+(defun comp-tests-concat-f (x)
+ (concat "a" "b" "c" "d"
+ (concat "a" "b" "c" (concat "a" "b" (concat "foo" x)))))
+
+(defun comp-tests-ffuncall-callee-f (x y z)
+ (list x y z))
+
+(defun comp-tests-ffuncall-callee-optional-f (a b &optional c d)
+ (list a b c d))
+
+(defun comp-tests-ffuncall-callee-rest-f (a b &rest c)
+ (list a b c))
+
+(defun comp-tests-ffuncall-callee-more8-f (p1 p2 p3 p4 p5 p6 p7 p8 p9 p10)
+ ;; More then 8 args.
+ (list p1 p2 p3 p4 p5 p6 p7 p8 p9 p10))
+
+(defun comp-tests-ffuncall-callee-more8-rest-f (p1 p2 p3 p4 p5 p6 p7 p8 p9 &rest p10)
+ ;; More then 8 args.
+ (list p1 p2 p3 p4 p5 p6 p7 p8 p9 p10))
+
+(defun comp-tests-ffuncall-native-f ()
+ "Call a primitive with no dedicate op."
+ (make-vector 1 nil))
+
+(defun comp-tests-ffuncall-native-rest-f ()
+ "Call a primitive with no dedicate op with &rest."
+ (vector 1 2 3))
+
+(defun comp-tests-ffuncall-apply-many-f (x)
+ (apply #'list x))
+
+(defun comp-tests-ffuncall-lambda-f (x)
+ (let ((fun (lambda (x)
+ (1+ x))))
+ (funcall fun x)))
+
+(defun comp-tests-jump-table-1-f (x)
+ (pcase x
+ ('x 'a)
+ ('y 'b)
+ (_ 'c)))
+
+(defun comp-tests-jump-table-2-f (x)
+ (pcase x
+ ("aaa" 'a)
+ ("bbb" 'b)))
+
+(defun comp-tests-conditionals-1-f (x)
+ ;; Generate goto-if-nil
+ (if x 1 2))
+(defun comp-tests-conditionals-2-f (x)
+ ;; Generate goto-if-nil-else-pop
+ (when x
+ 1340))
+
+(defun comp-tests-fixnum-1-minus-f (x)
+ ;; Bsub1
+ (1- x))
+(defun comp-tests-fixnum-1-plus-f (x)
+ ;; Badd1
+ (1+ x))
+(defun comp-tests-fixnum-minus-f (x)
+ ;; Bnegate
+ (- x))
+
+(defun comp-tests-eqlsign-f (x y)
+ ;; Beqlsign
+ (= x y))
+(defun comp-tests-gtr-f (x y)
+ ;; Bgtr
+ (> x y))
+(defun comp-tests-lss-f (x y)
+ ;; Blss
+ (< x y))
+(defun comp-tests-les-f (x y)
+ ;; Bleq
+ (<= x y))
+(defun comp-tests-geq-f (x y)
+ ;; Bgeq
+ (>= x y))
+
+(defun comp-tests-setcar-f (x y)
+ (setcar x y)
+ x)
+(defun comp-tests-setcdr-f (x y)
+ (setcdr x y)
+ x)
+
+(defun comp-bubble-sort-f (list)
+ (let ((i (length list)))
+ (while (> i 1)
+ (let ((b list))
+ (while (cdr b)
+ (when (< (cadr b) (car b))
+ (setcar b (prog1 (cadr b)
+ (setcdr b (cons (car b) (cddr b))))))
+ (setq b (cdr b))))
+ (setq i (1- i)))
+ list))
+
+(defun comp-tests-consp-f (x)
+ ;; Bconsp
+ (consp x))
+(defun comp-tests-setcar2-f (x)
+ ;; Bsetcar
+ (setcar x 3))
+
+(defun comp-tests-integerp-f (x)
+ ;; Bintegerp
+ (integerp x))
+(defun comp-tests-numberp-f (x)
+ ;; Bnumberp
+ (numberp x))
+
+(defun comp-tests-discardn-f (_x)
+ ;; BdiscardN
+ (1+ (let ((a 1)
+ (_b)
+ (_c))
+ a)))
+(defun comp-tests-insertn-f (a b c d)
+ ;; Binsert
+ (insert a b c d))
+
+(defun comp-tests-err-arith-f ()
+ (/ 1 0))
+(defun comp-tests-err-foo-f ()
+ (error "Foo"))
+
+(defun comp-tests-condition-case-0-f ()
+ ;; Bpushhandler Bpophandler
+ (condition-case
+ err
+ (comp-tests-err-arith-f)
+ (arith-error (concat "arith-error "
+ (error-message-string err)
+ " catched"))
+ (error (concat "error "
+ (error-message-string err)
+ " catched"))))
+(defun comp-tests-condition-case-1-f ()
+ ;; Bpushhandler Bpophandler
+ (condition-case
+ err
+ (comp-tests-err-foo-f)
+ (arith-error (concat "arith-error "
+ (error-message-string err)
+ " catched"))
+ (error (concat "error "
+ (error-message-string err)
+ " catched"))))
+(defun comp-tests-catch-f (f)
+ (catch 'foo
+ (funcall f)))
+(defun comp-tests-throw-f (x)
+ (throw 'foo x))
+
+(defun comp-tests-buff0-f ()
+ (with-temp-buffer
+ (insert "foo")
+ (buffer-string)))
+
+(defun comp-tests-lambda-return-f ()
+ (lambda (x) (1+ x)))
+
+(defun comp-tests-fib-f (n)
+ (cond ((= n 0) 0)
+ ((= n 1) 1)
+ (t (+ (comp-tests-fib-f (- n 1))
+ (comp-tests-fib-f (- n 2))))))
+
+(defmacro comp-tests-macro-m (x)
+ x)
+
+(defun comp-tests-string-trim-f (url)
+ (string-trim url))
+
+(defun comp-tests-trampoline-removal-f ()
+ (make-hash-table))
+
+(defun comp-tests-signal-f ()
+ (signal 'foo t))
+
+(defun comp-tests-func-call-removal-f ()
+ (let ((a 10)
+ (b 3))
+ (% a b)))
+
+(defun comp-tests-doc-f ()
+ "A nice docstring."
+ t)
+
+(defun comp-test-interactive-form0-f (dir)
+ (interactive "D")
+ dir)
+
+(defun comp-test-interactive-form1-f (x y)
+ (interactive '(1 2))
+ (+ x y))
+
+(defun comp-test-interactive-form2-f ()
+ (interactive))
+
+(defun comp-test-40187-2-f ()
+ 'foo)
+
+(defalias 'comp-test-40187-1-f (symbol-function 'comp-test-40187-2-f))
+
+(defun comp-test-40187-2-f ()
+ 'bar)
+
+(defun comp-test-speed--1-f ()
+ (declare (speed -1))
+ 3)
+
+(defun comp-test-42360-f (str end-column
+ &optional start-column padding ellipsis
+ ellipsis-text-property)
+ ;; From `truncate-string-to-width'. A large enough function to
+ ;; potentially use all registers and that is modifying local
+ ;; variables inside condition-case.
+ (let ((str-len (length str))
+ (_str-width 14)
+ (_ellipsis-width 3)
+ (idx 0)
+ (column 0)
+ (head-padding "") (tail-padding "")
+ ch last-column last-idx from-idx)
+ (condition-case nil
+ (while (< column start-column)
+ (setq ch (aref str idx)
+ column (+ column (char-width ch))
+ idx (1+ idx)))
+ (args-out-of-range (setq idx str-len)))
+ (if (< column start-column)
+ (if padding (make-string end-column padding) "")
+ (when (and padding (> column start-column))
+ (setq head-padding (make-string (- column start-column) padding)))
+ (setq from-idx idx)
+ (when (>= end-column column)
+ (condition-case nil
+ (while (< column end-column)
+ (setq last-column column
+ last-idx idx
+ ch (aref str idx)
+ column (+ column (char-width ch))
+ idx (1+ idx)))
+ (args-out-of-range (setq idx str-len)))
+ (when (> column end-column)
+ (setq column last-column
+ idx last-idx))
+ (when (and padding (< column end-column))
+ (setq tail-padding (make-string (- end-column column) padding))))
+ (if (and ellipsis-text-property
+ (not (equal ellipsis ""))
+ idx)
+ (concat head-padding
+ (substring str from-idx idx)
+ (propertize (substring str idx) 'display (or ellipsis "")))
+ (concat head-padding (substring str from-idx idx)
+ tail-padding ellipsis)))))
+
+(defun comp-test-primitive-advice-f (x y)
+ (declare (speed 2))
+ (+ x y))
+
+(defun comp-test-primitive-redefine-f (x y)
+ (declare (speed 2))
+ (- x y))
+
+(defsubst comp-test-defsubst-f ()
+ t)
+
+(defvar comp-test-and-3-var 1)
+(defun comp-test-and-3-f (x)
+ (and (atom x)
+ comp-test-and-3-var
+ 2))
+
+(defun comp-test-copy-insn-f (insn)
+ ;; From `comp-copy-insn'.
+ (if (consp insn)
+ (let (result)
+ (while (consp insn)
+ (let ((newcar (car insn)))
+ (if (or (consp (car insn)) (comp-mvar-p (car insn)))
+ (setf newcar (comp-copy-insn (car insn))))
+ (push newcar result))
+ (setf insn (cdr insn)))
+ (nconc (nreverse result)
+ (if (comp-mvar-p insn) (comp-copy-insn insn) insn)))
+ (if (comp-mvar-p insn)
+ (copy-comp-mvar insn)
+ insn)))
+
+(defun comp-test-cond-rw-1-1-f ())
+
+(defun comp-test-cond-rw-1-2-f ()
+ (let ((it (comp-test-cond-rw-1-1-f))
+ (key 't))
+ (if (or (equal it key)
+ (eq key t))
+ it
+ nil)))
+
+(defun comp-test-44968-f (start end)
+ (let ((dirlist)
+ (dir (expand-file-name start))
+ (end (expand-file-name end)))
+ (while (not (or (equal dir (car dirlist))
+ (file-equal-p dir end)))
+ (push dir dirlist)
+ (setq dir (directory-file-name (file-name-directory dir))))
+ (nreverse dirlist)))
+
+(defun comp-test-45342-f (n)
+ (pcase n
+ (1 " ➊") (2 " ➋") (3 " ➌") (4 " ➍") (5 " ➎") (6 " ➏")
+ (7 " ➐") (8 " ➑") (9 " ➒") (10 " ➓") (_ "")))
+
+(defun comp-test-assume-double-neg-f (collection value)
+ ;; Reduced from `auth-source-search-collection'.
+ (when (atom collection)
+ (setq collection (list collection)))
+ (or (eq value t)
+ ;; value is (not (member t))
+ (eq collection value)
+ ;; collection is t, not (member t)!
+ (member value collection)))
+
+(defun comp-test-assume-in-loop-1-f (arg)
+ ;; Reduced from `comint-delim-arg'.
+ (let ((args nil)
+ (pos 0)
+ (len (length arg)))
+ (while (< pos len)
+ (let ((start pos))
+ (while (< pos len)
+ (setq pos (1+ pos)))
+ (setq args (cons (substring arg start pos) args))))
+ args))
+
+(defun comp-test-45376-1-f ()
+ ;; Reduced from `eshell-ls-find-column-lengths'.
+ (let* (res
+ (len 2)
+ (i 0)
+ (j 0))
+ (while (< j len)
+ (if (= i len)
+ (setq i 0))
+ (setq res (cons i res)
+ j (1+ j)
+ i (1+ i)))
+ res))
+
+(defun comp-test-45376-2-f ()
+ ;; Also reduced from `eshell-ls-find-column-lengths'.
+ (let* ((x 1)
+ res)
+ (while x
+ (let* ((y 4)
+ (i 0))
+ (while (> y 0)
+ (when (= i x)
+ (setq i 0))
+ (setf res (cons i res))
+ (setq y (1- y)
+ i (1+ i)))
+ (if (>= x 3)
+ (setq x nil)
+ (setq x (1+ x)))))
+ res))
+
+(defun comp-test-not-cons-f (x)
+ ;; Reduced from `cl-copy-list'.
+ (if (consp x)
+ (print x)
+ (car x)))
+
+(defun comp-test-45576-f ()
+ ;; Reduced from `eshell-find-alias-function'.
+ (let ((sym (intern-soft "eval")))
+ (if (and (functionp sym)
+ '(eshell-ls eshell-pred eshell-prompt eshell-script
+ eshell-term eshell-unix))
+ sym)))
+
+(defun comp-test-45635-f (&rest args)
+ ;; Reduced from `set-face-attribute'.
+ (let ((spec args)
+ family)
+ (while spec
+ (cond ((eq (car spec) :family)
+ (setq family (cadr spec))))
+ (setq spec (cddr spec)))
+ (when (and (stringp family)
+ (string-match "\\([^-]*\\)-\\([^-]*\\)" family))
+ (setq family (match-string 2 family)))
+ (when (or (stringp family)
+ (eq family 'unspecified))
+ family)))
+
+;; This function doesn't have a doc string on purpose.
+(defun comp-test-46670-1-f (_)
+ "foo")
+
+(defun comp-test-46670-2-f (s)
+ (and (equal (comp-test-46670-1-f (length s)) s)
+ s))
+
+(cl-defun comp-test-46824-1-f ()
+ (let ((next-repos '(1)))
+ (while t
+ (let ((_recipe (car next-repos)))
+ (cl-block loop
+ (while t
+ (let ((err
+ (condition-case e
+ (progn
+ (setq next-repos
+ (cdr next-repos))
+ (cl-return-from loop))
+ (error e))))
+ (format "%S"
+ (error-message-string err))))))
+ (cl-return-from comp-test-46824-1-f))))
+
+(defun comp-test-47868-1-f ()
+ " ")
+
+(defun comp-test-47868-2-f ()
+ #(" " 0 1 (face font-lock-keyword-face)))
+
+(defun comp-test-47868-3-f ()
+ " ")
+
+(defun comp-test-47868-4-f ()
+ #(" " 0 1 (face font-lock-keyword-face)))
+
+(defun comp-test-48029-nonascii-žžž-f (arg)
+ (when arg t))
+
+
+;;;;;;;;;;;;;;;;;;;;
+;; Tromey's tests ;;
+;;;;;;;;;;;;;;;;;;;;
+
+;; Test Bconsp.
+(defun comp-test-consp (x) (consp x))
+
+;; Test Blistp.
+(defun comp-test-listp (x) (listp x))
+
+;; Test Bstringp.
+(defun comp-test-stringp (x) (stringp x))
+
+;; Test Bsymbolp.
+(defun comp-test-symbolp (x) (symbolp x))
+
+;; Test Bintegerp.
+(defun comp-test-integerp (x) (integerp x))
+
+;; Test Bnumberp.
+(defun comp-test-numberp (x) (numberp x))
+
+;; Test Badd1.
+(defun comp-test-add1 (x) (1+ x))
+
+;; Test Bsub1.
+(defun comp-test-sub1 (x) (1- x))
+
+;; Test Bneg.
+(defun comp-test-negate (x) (- x))
+
+;; Test Bnot.
+(defun comp-test-not (x) (not x))
+
+;; Test Bbobp, Beobp, Bpoint, Bpoint_min, Bpoint_max.
+(defun comp-test-bobp () (bobp))
+(defun comp-test-eobp () (eobp))
+(defun comp-test-point () (point))
+(defun comp-test-point-min () (point-min))
+(defun comp-test-point-max () (point-max))
+
+;; Test Bcar and Bcdr.
+(defun comp-test-car (x) (car x))
+(defun comp-test-cdr (x) (cdr x))
+
+;; Test Bcar_safe and Bcdr_safe.
+(defun comp-test-car-safe (x) (car-safe x))
+(defun comp-test-cdr-safe (x) (cdr-safe x))
+
+;; Test Beq.
+(defun comp-test-eq (x y) (eq x y))
+
+;; Test Bgotoifnil.
+(defun comp-test-if (x y) (if x x y))
+
+;; Test Bgotoifnilelsepop.
+(defun comp-test-and (x y) (and x y))
+
+;; Test Bgotoifnonnilelsepop.
+(defun comp-test-or (x y) (or x y))
+
+;; Test Bsave_excursion.
+(defun comp-test-save-excursion ()
+ (save-excursion
+ (insert "XYZ")))
+
+;; Test Bcurrent_buffer.
+(defun comp-test-current-buffer () (current-buffer))
+
+;; Test Bgtr.
+(defun comp-test-> (a b)
+ (> a b))
+
+;; Test Bpushcatch.
+(defun comp-test-catch (&rest l)
+ (catch 'done
+ (dolist (v l)
+ (when (> v 23)
+ (throw 'done v)))))
+
+;; Test Bmemq.
+(defun comp-test-memq (val list)
+ (memq val list))
+
+;; Test BlistN.
+(defun comp-test-listN (x)
+ (list x x x x x x x x x x x x x x x x))
+
+;; Test BconcatN.
+(defun comp-test-concatN (x)
+ (concat x x x x x x))
+
+;; Test optional and rest arguments.
+(defun comp-test-opt-rest (a &optional b &rest c)
+ (list a b c))
+
+;; Test for too many arguments.
+(defun comp-test-opt (a &optional b)
+ (cons a b))
+
+;; Test for unwind-protect.
+(defvar comp-test-up-val nil)
+(defun comp-test-unwind-protect (fun)
+ (setq comp-test-up-val nil)
+ (unwind-protect
+ (progn
+ (setq comp-test-up-val 23)
+ (funcall fun)
+ (setq comp-test-up-val 24))
+ (setq comp-test-up-val 999)))
+
+;; Non tested functions that proved just to be difficult to compile.
+
+(defun comp-test-callee (_ __) t)
+(defun comp-test-silly-frame1 (x)
+ ;; Check robustness against dead code.
+ (cl-case x
+ (0 (comp-test-callee
+ (pcase comp-tests-var1
+ (1 1)
+ (2 2))
+ 3))))
+
+(defun comp-test-silly-frame2 (_token)
+ ;; Check robustness against dead code.
+ (while c
+ (cl-case c
+ (?< 1)
+ (?> 2))))
+
+(defun comp-test-big-interactive (filename &optional force arg load)
+ "Check non trivial interactive form using `byte-recompile-file'."
+ (interactive
+ (let ((file buffer-file-name)
+ (file-name nil)
+ (file-dir nil))
+ (and file
+ (derived-mode-p 'emacs-lisp-mode)
+ (setq file-name (file-name-nondirectory file)
+ file-dir (file-name-directory file)))
+ (list (read-file-name (if current-prefix-arg
+ "Byte compile file: "
+ "Byte recompile file: ")
+ file-dir file-name nil)
+ current-prefix-arg)))
+ (let ((dest (byte-compile-dest-file filename))
+ ;; Expand now so we get the current buffer's defaults
+ (filename (expand-file-name filename)))
+ (if (if (file-exists-p dest)
+ ;; File was already compiled
+ ;; Compile if forced to, or filename newer
+ (or force
+ (file-newer-than-file-p filename dest))
+ (and arg
+ (or (eq 0 arg)
+ (y-or-n-p (concat "Compile "
+ filename "? ")))))
+ (progn
+ (if (and noninteractive (not byte-compile-verbose))
+ (message "Compiling %s..." filename))
+ (byte-compile-file filename))
+ (when load
+ (load (if (file-exists-p dest) dest filename)))
+ 'no-byte-compile)))
+
+(defun comp-test-no-return-1 (x)
+ (while x
+ (error "Foo")))
+
+(defun comp-test-no-return-2 (x)
+ (cond
+ ((eql x '2) t)
+ ((error "Bar") nil)))
+
+(defun comp-test-no-return-3 ())
+(defun comp-test-no-return-4 (x)
+ (when x
+ (error "Foo")
+ (while (comp-test-no-return-3)
+ (comp-test-no-return-3))))
+
+(defun comp-test-=-nan (x)
+ (when (= x 0.0e+NaN)
+ x))
+
+(defun comp-test-=-infinity (x)
+ (when (= x 1.0e+INF)
+ x))
+
+(provide 'comp-test-funcs)
+
+;;; comp-test-funcs.el ends here
diff --git a/test/src/comp-resources/comp-test-pure.el b/test/src/comp-resources/comp-test-pure.el
new file mode 100644
index 00000000000..788739e04cc
--- /dev/null
+++ b/test/src/comp-resources/comp-test-pure.el
@@ -0,0 +1,40 @@
+;;; comp-test-pure.el --- compilation unit tested by comp-tests.el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+;; Author: Andrea Corallo <akrl@sdf.org>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(defun comp-tests-pure-callee-f (x)
+ (1+ x))
+
+(defun comp-tests-pure-caller-f ()
+ (comp-tests-pure-callee-f 3))
+
+(defun comp-tests-pure-fibn-f (a b count)
+ (if (= count 0)
+ b
+ (comp-tests-pure-fibn-f (+ a b) a (- count 1))))
+
+(defun comp-tests-pure-fibn-entry-f ()
+ (comp-tests-pure-fibn-f 1 0 20))
+
+;;; comp-test-pure.el ends here
diff --git a/test/src/comp-tests.el b/test/src/comp-tests.el
new file mode 100644
index 00000000000..1edbd1777c6
--- /dev/null
+++ b/test/src/comp-tests.el
@@ -0,0 +1,1480 @@
+;;; comp-tests.el --- unit tests for src/comp.c -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2019-2022 Free Software Foundation, Inc.
+
+;; Author: Andrea Corallo <akrl@sdf.org>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Unit tests for src/comp.c.
+
+;;; Code:
+
+(require 'ert)
+(require 'ert-x)
+(require 'cl-lib)
+(require 'comp)
+(require 'comp-cstr)
+
+(eval-and-compile
+ (defconst comp-test-src (ert-resource-file "comp-test-funcs.el"))
+ (defconst comp-test-dyn-src (ert-resource-file "comp-test-funcs-dyn.el")))
+
+(when (native-comp-available-p)
+ (message "Compiling tests...")
+ (load (native-compile comp-test-src))
+ (load (native-compile comp-test-dyn-src)))
+
+;; Load the test code here so the compiler can check the function
+;; names used in this file.
+(require 'comp-test-funcs comp-test-src)
+(require 'comp-test-dyn-funcs comp-test-dyn-src) ;Non-standard feature name!
+
+(defmacro comp-deftest (name args &rest docstring-and-body)
+ "Define a test for the native compiler tagging it as :nativecomp."
+ (declare (indent defun)
+ (doc-string 3))
+ `(ert-deftest ,(intern (concat "comp-tests-" (symbol-name name))) ,args
+ :tags '(:nativecomp)
+ ,@(and (stringp (car docstring-and-body))
+ (list (pop docstring-and-body)))
+ ;; Some of the tests leave spill files behind -- so create a
+ ;; sub-dir where native-comp can do its work, and then delete it
+ ;; at the end.
+ (ert-with-temp-directory dir
+ (let ((temporary-file-directory dir))
+ ,@docstring-and-body))))
+
+
+
+(ert-deftest comp-tests-bootstrap ()
+ "Compile the compiler and load it to compile it-self.
+Check that the resulting binaries do not differ."
+ :tags '(:expensive-test :nativecomp)
+ (ert-with-temp-file comp1-src
+ :suffix "-comp-stage1.el"
+ (ert-with-temp-file comp2-src
+ :suffix "-comp-stage2.el"
+ (let* ((byte+native-compile t) ; FIXME HACK
+ (comp-src (expand-file-name "../../../lisp/emacs-lisp/comp.el"
+ (ert-resource-directory)))
+ ;; Can't use debug symbols.
+ (native-comp-debug 0))
+ (copy-file comp-src comp1-src t)
+ (copy-file comp-src comp2-src t)
+ (let ((load-no-native t))
+ (load (concat comp-src "c") nil nil t t))
+ (should-not (subr-native-elisp-p (symbol-function 'native-compile)))
+ (message "Compiling stage1...")
+ (let* ((t0 (current-time))
+ (comp1-eln (native-compile comp1-src)))
+ (message "Done in %d secs" (float-time (time-since t0)))
+ (load comp1-eln nil nil t t)
+ (should (subr-native-elisp-p (symbol-function 'native-compile)))
+ (message "Compiling stage2...")
+ (let ((t0 (current-time))
+ (comp2-eln (native-compile comp2-src)))
+ (message "Done in %d secs" (float-time (time-since t0)))
+ (message "Comparing %s %s" comp1-eln comp2-eln)
+ (should (= (call-process "cmp" nil nil nil comp1-eln comp2-eln) 0))))))))
+
+(comp-deftest provide ()
+ "Testing top level provide."
+ (should (featurep 'comp-test-funcs)))
+
+(comp-deftest varref ()
+ "Testing varref."
+ (should (= (comp-tests-varref-f) 3)))
+
+(comp-deftest list ()
+ "Testing cons car cdr."
+ (should (equal (comp-tests-list-f) '(1 2 3)))
+ (should (equal (comp-tests-list2-f 1 2 3) '(1 2 3)))
+ (should (= (comp-tests-car-f '(1 . 2)) 1))
+ (should (null (comp-tests-car-f nil)))
+ (should-error (comp-tests-car-f 3)
+ :type 'wrong-type-argument)
+ (should (= (comp-tests-cdr-f '(1 . 2)) 2))
+ (should (null (comp-tests-cdr-f nil)))
+ (should-error (comp-tests-cdr-f 3)
+ :type 'wrong-type-argument)
+ (should (= (comp-tests-car-safe-f '(1 . 2)) 1))
+ (should (null (comp-tests-car-safe-f 'a)))
+ (should (= (comp-tests-cdr-safe-f '(1 . 2)) 2))
+ (should (null (comp-tests-cdr-safe-f 'a))))
+
+(comp-deftest comp-tests-cons-car-cdr ()
+ "Testing cons car cdr."
+ (should (= (comp-tests-cons-car-f) 1))
+ (should (= (comp-tests-cons-cdr-f 3) 3)))
+
+(comp-deftest varset ()
+ "Testing varset."
+ (comp-tests-varset0-f)
+ (should (= comp-tests-var1 55))
+
+ (should (= (comp-tests-varset1-f) 4))
+ (should (= comp-tests-var1 66)))
+
+(comp-deftest length ()
+ "Testing length."
+ (should (= (comp-tests-length-f) 3)))
+
+(comp-deftest aref-aset ()
+ "Testing aref and aset."
+ (should (= (comp-tests-aref-aset-f) 100)))
+
+(comp-deftest symbol-value ()
+ "Testing aref and aset."
+ (should (= (comp-tests-symbol-value-f) 3)))
+
+(comp-deftest concat ()
+ "Testing concatX opcodes."
+ (should (string= (comp-tests-concat-f "bar") "abcdabcabfoobar")))
+
+(comp-deftest ffuncall ()
+ "Test calling conventions."
+
+ ;; (defun comp-tests-ffuncall-caller-f ()
+ ;; (comp-tests-ffuncall-callee-f 1 2 3))
+
+ ;; (should (equal (comp-tests-ffuncall-caller-f) '(1 2 3)))
+
+ ;; ;; After it gets compiled
+ ;; (native-compile #'comp-tests-ffuncall-callee-f)
+ ;; (should (equal (comp-tests-ffuncall-caller-f) '(1 2 3)))
+
+ ;; ;; Recompiling the caller once with callee already compiled
+ ;; (defun comp-tests-ffuncall-caller-f ()
+ ;; (comp-tests-ffuncall-callee-f 1 2 3))
+ ;; (should (equal (comp-tests-ffuncall-caller-f) '(1 2 3)))
+
+ (should (equal (comp-tests-ffuncall-callee-optional-f 1 2 3 4)
+ '(1 2 3 4)))
+ (should (equal (comp-tests-ffuncall-callee-optional-f 1 2 3)
+ '(1 2 3 nil)))
+ (should (equal (comp-tests-ffuncall-callee-optional-f 1 2)
+ '(1 2 nil nil)))
+
+ (should (equal (comp-tests-ffuncall-callee-rest-f 1 2)
+ '(1 2 nil)))
+ (should (equal (comp-tests-ffuncall-callee-rest-f 1 2 3)
+ '(1 2 (3))))
+ (should (equal (comp-tests-ffuncall-callee-rest-f 1 2 3 4)
+ '(1 2 (3 4))))
+
+ (should (equal (comp-tests-ffuncall-callee-more8-f 1 2 3 4 5 6 7 8 9 10)
+ '(1 2 3 4 5 6 7 8 9 10)))
+
+ (should (equal (comp-tests-ffuncall-callee-more8-rest-f 1 2 3 4 5 6 7 8 9 10 11)
+ '(1 2 3 4 5 6 7 8 9 (10 11))))
+
+ (should (equal (comp-tests-ffuncall-native-f) [nil]))
+
+ (should (equal (comp-tests-ffuncall-native-rest-f) [1 2 3]))
+
+ (should (equal (comp-tests-ffuncall-apply-many-f '(1 2 3))
+ '(1 2 3)))
+
+ (should (= (comp-tests-ffuncall-lambda-f 1) 2)))
+
+(comp-deftest jump-table ()
+ "Testing jump tables"
+ (should (eq (comp-tests-jump-table-1-f 'x) 'a))
+ (should (eq (comp-tests-jump-table-1-f 'y) 'b))
+ (should (eq (comp-tests-jump-table-1-f 'xxx) 'c))
+
+ ;; Jump table not with eq as test
+ (should (eq (comp-tests-jump-table-2-f "aaa") 'a))
+ (should (eq (comp-tests-jump-table-2-f "bbb") 'b)))
+
+(comp-deftest conditionals ()
+ "Testing conditionals."
+ (should (= (comp-tests-conditionals-1-f t) 1))
+ (should (= (comp-tests-conditionals-1-f nil) 2))
+ (should (= (comp-tests-conditionals-2-f t) 1340))
+ (should (eq (comp-tests-conditionals-2-f nil) nil)))
+
+(comp-deftest fixnum ()
+ "Testing some fixnum inline operation."
+ (should (= (comp-tests-fixnum-1-minus-f 10) 9))
+ (should (= (comp-tests-fixnum-1-minus-f most-negative-fixnum)
+ (1- most-negative-fixnum)))
+ (should-error (comp-tests-fixnum-1-minus-f 'a)
+ :type 'wrong-type-argument)
+ (should (= (comp-tests-fixnum-1-plus-f 10) 11))
+ (should (= (comp-tests-fixnum-1-plus-f most-positive-fixnum)
+ (1+ most-positive-fixnum)))
+ (should-error (comp-tests-fixnum-1-plus-f 'a)
+ :type 'wrong-type-argument)
+ (should (= (comp-tests-fixnum-minus-f 10) -10))
+ (should (= (comp-tests-fixnum-minus-f most-negative-fixnum)
+ (- most-negative-fixnum)))
+ (should-error (comp-tests-fixnum-minus-f 'a)
+ :type 'wrong-type-argument))
+
+(comp-deftest type-hints ()
+ "Just test compiler hints are transparent in this case."
+ ;; FIXME we should really check they are also effective.
+ (should (= (comp-tests-hint-fixnum-f 3) 4))
+ (should (= (comp-tests-hint-cons-f (cons 1 2)) 1)))
+
+(comp-deftest arith-comp ()
+ "Testing arithmetic comparisons."
+ (should (eq (comp-tests-eqlsign-f 4 3) nil))
+ (should (eq (comp-tests-eqlsign-f 3 3) t))
+ (should (eq (comp-tests-eqlsign-f 2 3) nil))
+ (should (eq (comp-tests-gtr-f 4 3) t))
+ (should (eq (comp-tests-gtr-f 3 3) nil))
+ (should (eq (comp-tests-gtr-f 2 3) nil))
+ (should (eq (comp-tests-lss-f 4 3) nil))
+ (should (eq (comp-tests-lss-f 3 3) nil))
+ (should (eq (comp-tests-lss-f 2 3) t))
+ (should (eq (comp-tests-les-f 4 3) nil))
+ (should (eq (comp-tests-les-f 3 3) t))
+ (should (eq (comp-tests-les-f 2 3) t))
+ (should (eq (comp-tests-geq-f 4 3) t))
+ (should (eq (comp-tests-geq-f 3 3) t))
+ (should (eq (comp-tests-geq-f 2 3) nil)))
+
+(comp-deftest setcarcdr ()
+ "Testing setcar setcdr."
+ (should (equal (comp-tests-setcar-f '(10 . 10) 3) '(3 . 10)))
+ (should (equal (comp-tests-setcdr-f '(10 . 10) 3) '(10 . 3)))
+ (should-error (comp-tests-setcar-f 3 10)
+ :type 'wrong-type-argument)
+ (should-error (comp-tests-setcdr-f 3 10)
+ :type 'wrong-type-argument))
+
+(comp-deftest bubble-sort ()
+ "Run bubble sort."
+ (let* ((list1 (mapcar #'random (make-list 1000 most-positive-fixnum)))
+ (list2 (copy-sequence list1)))
+ (should (equal (comp-bubble-sort-f list1)
+ (sort list2 #'<)))))
+
+(comp-deftest apply ()
+ "Test some inlined list functions."
+ (should (eq (comp-tests-consp-f '(1)) t))
+ (should (eq (comp-tests-consp-f 1) nil))
+ (let ((x (cons 1 2)))
+ (should (= (comp-tests-setcar2-f x) 3))
+ (should (equal x '(3 . 2)))))
+
+(comp-deftest num-inline ()
+ "Test some inlined number functions."
+ (should (eq (comp-tests-integerp-f 1) t))
+ (should (eq (comp-tests-integerp-f '(1)) nil))
+ (should (eq (comp-tests-integerp-f 3.5) nil))
+ (should (eq (comp-tests-integerp-f (1+ most-negative-fixnum)) t))
+
+ (should (eq (comp-tests-numberp-f 1) t))
+ (should (eq (comp-tests-numberp-f 'a) nil))
+ (should (eq (comp-tests-numberp-f 3.5) t)))
+
+(comp-deftest stack ()
+ "Test some stack operation."
+ (should (= (comp-tests-discardn-f 10) 2))
+ (should (string= (with-temp-buffer
+ (comp-tests-insertn-f "a" "b" "c" "d")
+ (buffer-string))
+ "abcd")))
+
+(comp-deftest non-locals ()
+ "Test non locals."
+ (should (string= (comp-tests-condition-case-0-f)
+ "arith-error Arithmetic error catched"))
+ (should (string= (comp-tests-condition-case-1-f)
+ "error Foo catched"))
+ (should (= (comp-tests-catch-f
+ (lambda () (throw 'foo 3)))
+ 3))
+ (should (= (catch 'foo
+ (comp-tests-throw-f 3)))))
+
+(comp-deftest gc ()
+ "Try to do some longer computation to let the GC kick in."
+ (dotimes (_ 100000)
+ (comp-tests-cons-cdr-f 3))
+ (should (= (comp-tests-cons-cdr-f 3) 3)))
+
+(comp-deftest buffer ()
+ (should (string= (comp-tests-buff0-f) "foo")))
+
+(comp-deftest lambda-return ()
+ (let ((f (comp-tests-lambda-return-f)))
+ (should (subr-native-elisp-p f))
+ (should (= (funcall f 3) 4))))
+
+(comp-deftest recursive ()
+ (should (= (comp-tests-fib-f 10) 55)))
+
+(comp-deftest macro ()
+ "Just check we can define macros"
+ (should (macrop (symbol-function 'comp-tests-macro-m))))
+
+(comp-deftest string-trim ()
+ (should (string= (comp-tests-string-trim-f "dsaf ") "dsaf")))
+
+(comp-deftest trampoline-removal ()
+ ;; This tests that we can call primitives with no dedicated bytecode.
+ ;; At speed >= 2 the trampoline will not be used.
+ (should (hash-table-p (comp-tests-trampoline-removal-f))))
+
+(comp-deftest signal ()
+ (should (equal (condition-case err
+ (comp-tests-signal-f)
+ (t err))
+ '(foo . t))))
+
+(comp-deftest func-call-removal ()
+ ;; See `comp-propagate-insn' `comp-function-call-remove'.
+ (should (= (comp-tests-func-call-removal-f) 1)))
+
+(comp-deftest doc ()
+ (should (string= (documentation #'comp-tests-doc-f)
+ "A nice docstring."))
+ ;; Check a preloaded function, we can't use `comp-tests-doc-f' now
+ ;; as this is loaded manually with no .elc.
+ (should (string-match "\\.*.elc\\'" (symbol-file #'error))))
+
+(comp-deftest interactive-form ()
+ (should (equal (interactive-form #'comp-test-interactive-form0-f)
+ '(interactive "D")))
+ (should (equal (interactive-form #'comp-test-interactive-form1-f)
+ '(interactive '(1 2))))
+ (should (equal (interactive-form #'comp-test-interactive-form2-f)
+ '(interactive nil)))
+ (should (cl-every #'commandp '(comp-test-interactive-form0-f
+ comp-test-interactive-form1-f
+ comp-test-interactive-form2-f)))
+ (should-not (commandp #'comp-tests-doc-f)))
+
+(declare-function comp-tests-free-fun-f nil)
+
+(comp-deftest free-fun ()
+ "Check we are able to compile a single function."
+ (eval '(defun comp-tests-free-fun-f ()
+ "Some doc."
+ (interactive)
+ 3)
+ t)
+ (native-compile #'comp-tests-free-fun-f)
+
+ (should (subr-native-elisp-p (symbol-function 'comp-tests-free-fun-f)))
+ (should (= (comp-tests-free-fun-f) 3))
+ (should (string= (documentation #'comp-tests-free-fun-f)
+ "Some doc."))
+ (should (commandp #'comp-tests-free-fun-f))
+ (should (equal (interactive-form #'comp-tests-free-fun-f)
+ '(interactive))))
+
+(declare-function comp-tests/free\fun-f nil)
+
+(comp-deftest free-fun-silly-name ()
+ "Check we are able to compile a single function."
+ (eval '(defun comp-tests/free\fun-f ()) t)
+ (native-compile #'comp-tests/free\fun-f)
+ (should (subr-native-elisp-p (symbol-function 'comp-tests/free\fun-f))))
+
+(comp-deftest bug-40187 ()
+ "Check function name shadowing.
+https://lists.gnu.org/archive/html/bug-gnu-emacs/2020-03/msg00914.html."
+ (should (eq (comp-test-40187-1-f) 'foo))
+ (should (eq (comp-test-40187-2-f) 'bar)))
+
+(comp-deftest speed--1 ()
+ "Check that at speed -1 we do not native compile."
+ (should (= (comp-test-speed--1-f) 3))
+ (should-not (subr-native-elisp-p (symbol-function 'comp-test-speed--1-f))))
+
+(comp-deftest bug-42360 ()
+ "<https://lists.gnu.org/archive/html/bug-gnu-emacs/2020-07/msg00418.html>."
+ (should (string= (comp-test-42360-f "Nel mezzo del " 18 0 32 "yyy" nil)
+ "Nel mezzo del yyy")))
+
+(comp-deftest bug-44968 ()
+ "<https://lists.gnu.org/archive/html/bug-gnu-emacs/2020-11/msg02357.html>"
+ (comp-test-44968-f "/tmp/test/foo" "/tmp"))
+
+(comp-deftest bug-45342 ()
+ "Preserve multibyte immediate strings.
+<https://lists.gnu.org/archive/html/bug-gnu-emacs/2020-12/msg01771.html>"
+ (should (string= " ➊" (comp-test-45342-f 1))))
+
+(comp-deftest assume-double-neg ()
+ "In fwprop assumptions (not (not (member x))) /= (member x)."
+ (should-not (comp-test-assume-double-neg-f "bar" "foo")))
+
+(comp-deftest assume-in-loop-1 ()
+ "Broken call args assumptions lead to infinite loop."
+ (should (equal (comp-test-assume-in-loop-1-f "cd") '("cd"))))
+
+(comp-deftest bug-45376-1 ()
+ "<https://lists.gnu.org/archive/html/bug-gnu-emacs/2020-12/msg01883.html>"
+ (should (equal (comp-test-45376-1-f) '(1 0))))
+
+(comp-deftest bug-45376-2 ()
+ "<https://lists.gnu.org/archive/html/bug-gnu-emacs/2020-12/msg01883.html>"
+ (should (equal (comp-test-45376-2-f) '(0 2 1 0 1 0 1 0 0 0 0 0))))
+
+(defvar comp-test-primitive-advice)
+(comp-deftest primitive-advice ()
+ "Test effectiveness of primitive advising."
+ (let (comp-test-primitive-advice
+ (f (lambda (&rest args)
+ (setq comp-test-primitive-advice args))))
+ (advice-add #'+ :before f)
+ (unwind-protect
+ (progn
+ (should (= (comp-test-primitive-advice-f 3 4) 7))
+ (should (equal comp-test-primitive-advice '(3 4))))
+ (advice-remove #'+ f))))
+
+(defvar comp-test-primitive-redefine-args)
+(comp-deftest primitive-redefine ()
+ "Test effectiveness of primitive redefinition."
+ (cl-letf ((comp-test-primitive-redefine-args nil)
+ ((symbol-function '-)
+ (lambda (&rest args)
+ (setq comp-test-primitive-redefine-args args)
+ 'xxx)))
+ (should (eq (comp-test-primitive-redefine-f 10 2) 'xxx))
+ (should (equal comp-test-primitive-redefine-args '(10 2)))))
+
+(comp-deftest compile-forms ()
+ "Verify lambda form native compilation."
+ (should-error (native-compile '(+ 1 foo)))
+ (let ((lexical-binding t)
+ (f (native-compile '(lambda (x) (1+ x)))))
+ (should (subr-native-elisp-p f))
+ (should (= (funcall f 2) 3)))
+ (let* ((lexical-binding nil)
+ (f (native-compile '(lambda (x) (1+ x)))))
+ (should (subr-native-elisp-p f))
+ (should (= (funcall f 2) 3))))
+
+(comp-deftest comp-test-defsubst ()
+ ;; Bug#42664, Bug#43280, Bug#44209.
+ (should-not (subr-native-elisp-p (symbol-function 'comp-test-defsubst-f))))
+
+(comp-deftest primitive-redefine-compile-44221 ()
+ "Test the compiler still works while primitives are redefined (bug#44221)."
+ (cl-letf (((symbol-function 'delete-region)
+ (lambda (_ _))))
+ (should (subr-native-elisp-p
+ (native-compile
+ '(lambda ()
+ (delete-region (point-min) (point-max))))))))
+
+(comp-deftest and-3 ()
+ (should (= (comp-test-and-3-f t) 2))
+ (should (null (comp-test-and-3-f '(1 2)))))
+
+(comp-deftest copy-insn ()
+ (should (equal (comp-test-copy-insn-f '(1 2 3 (4 5 6)))
+ '(1 2 3 (4 5 6))))
+ (should (null (comp-test-copy-insn-f nil))))
+
+(comp-deftest cond-rw-1 ()
+ "Check cond-rw does not break target blocks with multiple predecessor."
+ (should (null (comp-test-cond-rw-1-2-f))))
+
+(comp-deftest not-cons-1 ()
+ (should-not (comp-test-not-cons-f nil)))
+
+(comp-deftest 45576-1 ()
+ "Functionp satisfies also symbols.
+<https://lists.gnu.org/archive/html/bug-gnu-emacs/2021-01/msg00029.html>."
+ (should (eq (comp-test-45576-f) 'eval)))
+
+(comp-deftest 45635-1 ()
+ "<https://lists.gnu.org/archive/html/bug-gnu-emacs/2021-01/msg00158.html>."
+ (should (string= (comp-test-45635-f :height 180 :family "PragmataPro Liga")
+ "PragmataPro Liga")))
+
+(comp-deftest 46670-1 ()
+ "<https://lists.gnu.org/archive/html/bug-gnu-emacs/2021-02/msg01413.html>"
+ (should (string= (comp-test-46670-2-f "foo") "foo"))
+ (should (equal (subr-type (symbol-function 'comp-test-46670-2-f))
+ '(function (t) t))))
+
+(comp-deftest 46824-1 ()
+ "<https://lists.gnu.org/archive/html/bug-gnu-emacs/2021-02/msg01949.html>"
+ (should (equal (comp-test-46824-1-f) nil)))
+
+(comp-deftest comp-test-47868-1 ()
+ "Verify string hash consing strategy.
+
+<https://lists.gnu.org/archive/html/bug-gnu-emacs/2021-04/msg00921.html>"
+ (should-not (equal-including-properties (comp-test-47868-1-f)
+ (comp-test-47868-2-f)))
+ (should (eq (comp-test-47868-1-f) (comp-test-47868-3-f)))
+ (should (eq (comp-test-47868-2-f) (comp-test-47868-4-f))))
+
+(comp-deftest 48029-1 ()
+ "<https://lists.gnu.org/archive/html/bug-gnu-emacs/2022-07/msg00666.html>"
+ (should (subr-native-elisp-p
+ (symbol-function 'comp-test-48029-nonascii-žžž-f))))
+
+
+;;;;;;;;;;;;;;;;;;;;;
+;; Tromey's tests. ;;
+;;;;;;;;;;;;;;;;;;;;;
+
+(comp-deftest consp ()
+ (should-not (comp-test-consp 23))
+ (should-not (comp-test-consp nil))
+ (should (comp-test-consp '(1 . 2))))
+
+(comp-deftest listp ()
+ (should-not (comp-test-listp 23))
+ (should (comp-test-listp nil))
+ (should (comp-test-listp '(1 . 2))))
+
+(comp-deftest stringp ()
+ (should-not (comp-test-stringp 23))
+ (should-not (comp-test-stringp nil))
+ (should (comp-test-stringp "hi")))
+
+(comp-deftest symbolp ()
+ (should-not (comp-test-symbolp 23))
+ (should-not (comp-test-symbolp "hi"))
+ (should (comp-test-symbolp 'whatever)))
+
+(comp-deftest integerp ()
+ (should (comp-test-integerp 23))
+ (should-not (comp-test-integerp 57.5))
+ (should-not (comp-test-integerp "hi"))
+ (should-not (comp-test-integerp 'whatever)))
+
+(comp-deftest numberp ()
+ (should (comp-test-numberp 23))
+ (should (comp-test-numberp 57.5))
+ (should-not (comp-test-numberp "hi"))
+ (should-not (comp-test-numberp 'whatever)))
+
+(comp-deftest add1 ()
+ (should (eq (comp-test-add1 23) 24))
+ (should (eq (comp-test-add1 -17) -16))
+ (should (eql (comp-test-add1 1.0) 2.0))
+ (should-error (comp-test-add1 nil)
+ :type 'wrong-type-argument))
+
+(comp-deftest sub1 ()
+ (should (eq (comp-test-sub1 23) 22))
+ (should (eq (comp-test-sub1 -17) -18))
+ (should (eql (comp-test-sub1 1.0) 0.0))
+ (should-error (comp-test-sub1 nil)
+ :type 'wrong-type-argument))
+
+(comp-deftest negate ()
+ (should (eq (comp-test-negate 23) -23))
+ (should (eq (comp-test-negate -17) 17))
+ (should (eql (comp-test-negate 1.0) -1.0))
+ (should-error (comp-test-negate nil)
+ :type 'wrong-type-argument))
+
+(comp-deftest not ()
+ (should (eq (comp-test-not 23) nil))
+ (should (eq (comp-test-not nil) t))
+ (should (eq (comp-test-not t) nil)))
+
+(comp-deftest bobp-and-eobp ()
+ (with-temp-buffer
+ (should (comp-test-bobp))
+ (should (comp-test-eobp))
+ (insert "hi")
+ (goto-char (point-min))
+ (should (eq (comp-test-point-min) (point-min)))
+ (should (eq (comp-test-point) (point-min)))
+ (should (comp-test-bobp))
+ (should-not (comp-test-eobp))
+ (goto-char (point-max))
+ (should (eq (comp-test-point-max) (point-max)))
+ (should (eq (comp-test-point) (point-max)))
+ (should-not (comp-test-bobp))
+ (should (comp-test-eobp))))
+
+(comp-deftest car-cdr ()
+ (let ((pair '(1 . b)))
+ (should (eq (comp-test-car pair) 1))
+ (should (eq (comp-test-car nil) nil))
+ (should-error (comp-test-car 23)
+ :type 'wrong-type-argument)
+ (should (eq (comp-test-cdr pair) 'b))
+ (should (eq (comp-test-cdr nil) nil))
+ (should-error (comp-test-cdr 23)
+ :type 'wrong-type-argument)))
+
+(comp-deftest car-cdr-safe ()
+ (let ((pair '(1 . b)))
+ (should (eq (comp-test-car-safe pair) 1))
+ (should (eq (comp-test-car-safe nil) nil))
+ (should (eq (comp-test-car-safe 23) nil))
+ (should (eq (comp-test-cdr-safe pair) 'b))
+ (should (eq (comp-test-cdr-safe nil) nil))
+ (should (eq (comp-test-cdr-safe 23) nil))))
+
+(comp-deftest eq ()
+ (should (comp-test-eq 'a 'a))
+ (should (comp-test-eq 5 5))
+ (should-not (comp-test-eq 'a 'b)))
+
+(comp-deftest if ()
+ (should (eq (comp-test-if 'a 'b) 'a))
+ (should (eq (comp-test-if 0 23) 0))
+ (should (eq (comp-test-if nil 'b) 'b)))
+
+(comp-deftest and ()
+ (should (eq (comp-test-and 'a 'b) 'b))
+ (should (eq (comp-test-and 0 23) 23))
+ (should (eq (comp-test-and nil 'b) nil)))
+
+(comp-deftest or ()
+ (should (eq (comp-test-or 'a 'b) 'a))
+ (should (eq (comp-test-or 0 23) 0))
+ (should (eq (comp-test-or nil 'b) 'b)))
+
+(comp-deftest save-excursion ()
+ (with-temp-buffer
+ (comp-test-save-excursion)
+ (should (eq (point) (point-min)))
+ (should (eq (comp-test-current-buffer) (current-buffer)))))
+
+(comp-deftest > ()
+ (should (eq (comp-test-> 0 23) nil))
+ (should (eq (comp-test-> 23 0) t)))
+
+(comp-deftest catch ()
+ (should (eq (comp-test-catch 0 1 2 3 4) nil))
+ (should (eq (comp-test-catch 20 21 22 23 24 25 26 27 28) 24)))
+
+(comp-deftest memq ()
+ (should (equal (comp-test-memq 0 '(5 4 3 2 1 0)) '(0)))
+ (should (eq (comp-test-memq 72 '(5 4 3 2 1 0)) nil)))
+
+(comp-deftest listN ()
+ (should (equal (comp-test-listN 57)
+ '(57 57 57 57 57 57 57 57 57 57 57 57 57 57 57 57))))
+
+(comp-deftest concatN ()
+ (should (equal (comp-test-concatN "x") "xxxxxx")))
+
+(comp-deftest opt-rest ()
+ (should (equal (comp-test-opt-rest 1) '(1 nil nil)))
+ (should (equal (comp-test-opt-rest 1 2) '(1 2 nil)))
+ (should (equal (comp-test-opt-rest 1 2 3) '(1 2 (3))))
+ (should (equal (comp-test-opt-rest 1 2 56 57 58)
+ '(1 2 (56 57 58)))))
+
+(comp-deftest opt ()
+ (should (equal (comp-test-opt 23) '(23)))
+ (should (equal (comp-test-opt 23 24) '(23 . 24)))
+ (should-error (comp-test-opt)
+ :type 'wrong-number-of-arguments)
+ (should-error (comp-test-opt nil 24 97)
+ :type 'wrong-number-of-arguments))
+
+(comp-deftest unwind-protect ()
+ (comp-test-unwind-protect 'ignore)
+ (should (eq comp-test-up-val 999))
+ (condition-case nil
+ (comp-test-unwind-protect (lambda () (error "HI")))
+ (error
+ nil))
+ (should (eq comp-test-up-val 999)))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Tests for dynamic scope. ;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(comp-deftest dynamic-ffuncall ()
+ "Test calling convention for dynamic binding."
+
+ (should (equal (comp-tests-ffuncall-callee-dyn-f 1 2)
+ '(1 2)))
+
+ (should (equal (comp-tests-ffuncall-callee-opt-dyn-f 1 2 3 4)
+ '(1 2 3 4)))
+ (should (equal (comp-tests-ffuncall-callee-opt-dyn-f 1 2 3)
+ '(1 2 3 nil)))
+ (should (equal (comp-tests-ffuncall-callee-opt-dyn-f 1 2)
+ '(1 2 nil nil)))
+
+ (should (equal (comp-tests-ffuncall-callee-rest-dyn-f 1 2)
+ '(1 2 nil)))
+ (should (equal (comp-tests-ffuncall-callee-rest-dyn-f 1 2 3)
+ '(1 2 (3))))
+ (should (equal (comp-tests-ffuncall-callee-rest-dyn-f 1 2 3 4)
+ '(1 2 (3 4))))
+
+ (should (equal (comp-tests-ffuncall-callee-opt-rest-dyn-f 1 2)
+ '(1 2 nil nil)))
+ (should (equal (comp-tests-ffuncall-callee-opt-rest-dyn-f 1 2 3)
+ '(1 2 3 nil)))
+ (should (equal (comp-tests-ffuncall-callee-opt-rest-dyn-f 1 2 3 4)
+ '(1 2 3 (4)))))
+
+(comp-deftest dynamic-arity ()
+ "Test func-arity on dynamic scope functions."
+ (should (equal '(2 . 2)
+ (func-arity #'comp-tests-ffuncall-callee-dyn-f)))
+ (should (equal '(2 . 4)
+ (func-arity #'comp-tests-ffuncall-callee-opt-dyn-f)))
+ (should (equal '(2 . many)
+ (func-arity #'comp-tests-ffuncall-callee-rest-dyn-f)))
+ (should (equal '(2 . many)
+ (func-arity #'comp-tests-ffuncall-callee-opt-rest-dyn-f))))
+
+(comp-deftest dynamic-help-arglist ()
+ "Test `help-function-arglist' works on lisp/d (bug#42572)."
+ (should (equal (help-function-arglist
+ (symbol-function 'comp-tests-ffuncall-callee-opt-rest-dyn-f)
+ t)
+ '(a b &optional c &rest d))))
+
+(comp-deftest cl-macro-exp ()
+ "Verify CL macro expansion (bug#42088)."
+ (should (equal (comp-tests-cl-macro-exp-f) '(a b))))
+
+(comp-deftest cl-uninterned-arg-parse-f ()
+ "Verify the parsing of a lambda list with uninterned symbols (bug#42120)."
+ (should (equal (comp-tests-cl-uninterned-arg-parse-f 1 2)
+ '(1 2))))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Middle-end specific tests. ;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun comp-tests-mentioned-p-1 (x insn)
+ (cl-loop for y in insn
+ when (cond
+ ((consp y) (comp-tests-mentioned-p x y))
+ ((and (comp-mvar-p y) (comp-cstr-imm-vld-p y))
+ (equal (comp-cstr-imm y) x))
+ (t (equal x y)))
+ return t))
+
+(defun comp-tests-mentioned-p (x insn)
+ "Check if X is actively mentioned in INSN."
+ (unless (eq (car-safe insn)
+ 'comment)
+ (comp-tests-mentioned-p-1 x insn)))
+
+(defun comp-tests-map-checker (func-name checker)
+ "Apply CHECKER to each insn of FUNC-NAME.
+Return a list of results."
+ (cl-loop
+ with func-c-name = (comp-c-func-name (or func-name 'anonymous-lambda) "F" t)
+ with f = (gethash func-c-name (comp-ctxt-funcs-h comp-ctxt))
+ for bb being each hash-value of (comp-func-blocks f)
+ nconc
+ (cl-loop
+ for insn in (comp-block-insns bb)
+ collect (funcall checker insn))))
+
+(defun comp-tests-tco-checker (_)
+ "Check that inside `comp-tests-tco-f' we have no recursion."
+ (should
+ (cl-notany
+ #'identity
+ (comp-tests-map-checker
+ 'comp-tests-tco-f
+ (lambda (insn)
+ (or (comp-tests-mentioned-p 'comp-tests-tco-f insn)
+ (comp-tests-mentioned-p (comp-c-func-name 'comp-tests-tco-f "F" t)
+ insn)))))))
+
+(declare-function comp-tests-tco-f nil)
+
+(comp-deftest tco ()
+ "Check for tail recursion elimination."
+ (let ((native-comp-speed 3)
+ ;; Disable ipa-pure otherwise `comp-tests-tco-f' gets
+ ;; optimized-out.
+ (comp-disabled-passes '(comp-ipa-pure))
+ (comp-post-pass-hooks '((comp-tco comp-tests-tco-checker)
+ (comp-final comp-tests-tco-checker))))
+ (eval '(defun comp-tests-tco-f (a b count)
+ (if (= count 0)
+ b
+ (comp-tests-tco-f (+ a b) a (- count 1))))
+ t)
+ (native-compile #'comp-tests-tco-f)
+ (should (subr-native-elisp-p (symbol-function 'comp-tests-tco-f)))
+ (should (= (comp-tests-tco-f 1 0 10) 55))))
+
+(defun comp-tests-fw-prop-checker-1 (_)
+ "Check that inside `comp-tests-fw-prop-f' `concat' and `length' are folded."
+ (should
+ (cl-notany
+ #'identity
+ (comp-tests-map-checker
+ 'comp-tests-fw-prop-1-f
+ (lambda (insn)
+ (or (comp-tests-mentioned-p 'concat insn)
+ (comp-tests-mentioned-p 'length insn)))))))
+
+(declare-function comp-tests-fw-prop-1-f nil)
+
+(comp-deftest fw-prop-1 ()
+ "Some tests for forward propagation."
+ (let ((native-comp-speed 2)
+ (comp-post-pass-hooks '((comp-final comp-tests-fw-prop-checker-1))))
+ (eval '(defun comp-tests-fw-prop-1-f ()
+ (let* ((a "xxx")
+ (b "yyy")
+ (c (concat a b))) ; <= has to optimize
+ (length c))) ; <= has to optimize
+ t)
+ (native-compile #'comp-tests-fw-prop-1-f)
+ (should (subr-native-elisp-p (symbol-function 'comp-tests-fw-prop-1-f)))
+ (should (= (comp-tests-fw-prop-1-f) 6))))
+
+(defun comp-tests-check-ret-type-spec (func-form ret-type)
+ (let ((lexical-binding t)
+ (native-comp-speed 2)
+ (f-name (cl-second func-form)))
+ (eval func-form t)
+ (native-compile f-name)
+ (should (equal (cl-third (subr-type (symbol-function f-name)))
+ ret-type))))
+
+(cl-eval-when (compile eval load)
+ (defconst comp-tests-type-spec-tests
+ ;; Why we quote everything here, you ask? So that values of
+ ;; `most-positive-fixnum' and `most-negative-fixnum', which can be
+ ;; architecture-dependent, do not end up hardcoded in the
+ ;; resulting byte-compiled file, and thus we could run the same
+ ;; .elc file on several architectures without fear.
+ '(
+ ;; 1
+ ((defun comp-tests-ret-type-spec-f (x)
+ x)
+ 't)
+
+ ;; 2
+ ((defun comp-tests-ret-type-spec-f ()
+ 1)
+ '(integer 1 1))
+
+ ;; 3
+ ((defun comp-tests-ret-type-spec-f (x)
+ (if x 1 3))
+ '(or (integer 1 1) (integer 3 3)))
+
+ ;; 4
+ ((defun comp-tests-ret-type-spec-f (x)
+ (let (y)
+ (if x
+ (setf y 1)
+ (setf y 2))
+ y))
+ '(integer 1 2))
+
+ ;; 5
+ ((defun comp-tests-ret-type-spec-f (x)
+ (let (y)
+ (if x
+ (setf y 1)
+ (setf y 3))
+ y))
+ '(or (integer 1 1) (integer 3 3)))
+
+ ;; 6
+ ((defun comp-tests-ret-type-spec-f (x)
+ (if x
+ (list x)
+ 3))
+ '(or cons (integer 3 3)))
+
+ ;; 7
+ ((defun comp-tests-ret-type-spec-f (x)
+ (if x
+ 'foo
+ 3))
+ '(or (member foo) (integer 3 3)))
+
+ ;; 8
+ ((defun comp-tests-ret-type-spec-f (x)
+ (if (eq x 3)
+ x
+ 'foo))
+ '(or (member foo) (integer 3 3)))
+
+ ;; 9
+ ((defun comp-tests-ret-type-spec-f (x)
+ (if (eq 3 x)
+ x
+ 'foo))
+ '(or (member foo) (integer 3 3)))
+
+ ;; 10
+ ((defun comp-tests-ret-type-spec-f (x)
+ (if (eql x 3)
+ x
+ 'foo))
+ '(or (member foo) (integer 3 3)))
+
+ ;; 11
+ ((defun comp-tests-ret-type-spec-f (x)
+ (if (eql 3 x)
+ x
+ 'foo))
+ '(or (member foo) (integer 3 3)))
+
+ ;; 12
+ ((defun comp-tests-ret-type-spec-f (x)
+ (if (eql x 3)
+ 'foo
+ x))
+ '(not (integer 3 3)))
+
+ ;; 13
+ ((defun comp-tests-ret-type-spec-f (x y)
+ (if (= x y)
+ x
+ 'foo))
+ '(or (member foo) marker number))
+
+ ;; 14
+ ((defun comp-tests-ret-type-spec-f (x)
+ (comp-hint-fixnum x))
+ `(integer ,most-negative-fixnum ,most-positive-fixnum))
+
+ ;; 15
+ ((defun comp-tests-ret-type-spec-f (x)
+ (comp-hint-cons x))
+ 'cons)
+
+ ;; 16
+ ((defun comp-tests-ret-type-spec-f (x)
+ (let (y)
+ (when x
+ (setf y 4))
+ y))
+ '(or null (integer 4 4)))
+
+ ;; 17
+ ((defun comp-tests-ret-type-spec-f ()
+ (let (x
+ (y 3))
+ (setf x y)
+ y))
+ '(integer 3 3))
+
+ ;; 18
+ ((defun comp-tests-ret-type-spec-f (x)
+ (let ((y 3))
+ (when x
+ (setf y x))
+ y))
+ 't)
+
+ ;; 19
+ ((defun comp-tests-ret-type-spec-f (x y)
+ (eq x y))
+ 'boolean)
+
+ ;; 20
+ ((defun comp-tests-ret-type-spec-f (x)
+ (when x
+ 'foo))
+ '(or (member foo) null))
+
+ ;; 21
+ ((defun comp-tests-ret-type-spec-f (x)
+ (unless x
+ 'foo))
+ '(or (member foo) null))
+
+ ;; 22
+ ((defun comp-tests-ret-type-spec-f (x)
+ (when (> x 3)
+ x))
+ '(or null float (integer 4 *)))
+
+ ;; 23
+ ((defun comp-tests-ret-type-spec-f (x)
+ (when (>= x 3)
+ x))
+ '(or null float (integer 3 *)))
+
+ ;; 24
+ ((defun comp-tests-ret-type-spec-f (x)
+ (when (< x 3)
+ x))
+ '(or null float (integer * 2)))
+
+ ;; 25
+ ((defun comp-tests-ret-type-spec-f (x)
+ (when (<= x 3)
+ x))
+ '(or null float (integer * 3)))
+
+ ;; 26
+ ((defun comp-tests-ret-type-spec-f (x)
+ (when (> 3 x)
+ x))
+ '(or null float (integer * 2)))
+
+ ;; 27
+ ((defun comp-tests-ret-type-spec-f (x)
+ (when (>= 3 x)
+ x))
+ '(or null float (integer * 3)))
+
+ ;; 28
+ ((defun comp-tests-ret-type-spec-f (x)
+ (when (< 3 x)
+ x))
+ '(or null float (integer 4 *)))
+
+ ;; 29
+ ((defun comp-tests-ret-type-spec-f (x)
+ (when (<= 3 x)
+ x))
+ '(or null float (integer 3 *)))
+
+ ;; 30
+ ((defun comp-tests-ret-type-spec-f (x)
+ (let ((y 3))
+ (when (> x y)
+ x)))
+ '(or null float (integer 4 *)))
+
+ ;; 31
+ ((defun comp-tests-ret-type-spec-f (x)
+ (let ((y 3))
+ (when (> y x)
+ x)))
+ '(or null float (integer * 2)))
+
+ ;; 32
+ ((defun comp-tests-ret-type-spec-f (x)
+ (when (and (> x 3)
+ (< x 10))
+ x))
+ '(or null float (integer 4 9)))
+
+ ;; 33
+ ((defun comp-tests-ret-type-spec-f (x)
+ (when (or (> x 3)
+ (< x 10))
+ x))
+ '(or null float integer))
+
+ ;; 34
+ ((defun comp-tests-ret-type-spec-f (x)
+ (when (or (< x 3)
+ (> x 10))
+ x))
+ '(or null float (integer * 2) (integer 11 *)))
+
+ ;; 35 No float range support.
+ ((defun comp-tests-ret-type-spec-f (x)
+ (when (> x 1.0)
+ x))
+ '(or null marker number))
+
+ ;; 36
+ ((defun comp-tests-ret-type-spec-f (x y)
+ (when (and (> x 3)
+ (> y 2))
+ (+ x y)))
+ '(or null float (integer 7 *)))
+
+ ;; 37
+ ;; SBCL: (OR REAL NULL)
+ ((defun comp-tests-ret-type-spec-f (x y)
+ (when (and (<= x 3)
+ (<= y 2))
+ (+ x y)))
+ '(or null float (integer * 5)))
+
+ ;; 38
+ ((defun comp-tests-ret-type-spec-f (x y)
+ (when (and (< 1 x 5)
+ (< 1 y 5))
+ (+ x y)))
+ '(or null float (integer 4 8)))
+
+ ;; 39
+ ;; SBCL gives: (OR REAL NULL)
+ ((defun comp-tests-ret-type-spec-f (x y)
+ (when (and (<= 1 x 10)
+ (<= 2 y 3))
+ (+ x y)))
+ '(or null float (integer 3 13)))
+
+ ;; 40
+ ;; SBCL: (OR REAL NULL)
+ ((defun comp-tests-ret-type-spec-f (x y)
+ (when (and (<= 1 x 10)
+ (<= 2 y 3))
+ (- x y)))
+ '(or null float (integer -2 8)))
+
+ ;; 41
+ ((defun comp-tests-ret-type-spec-f (x y)
+ (when (and (<= 1 x)
+ (<= 2 y 3))
+ (- x y)))
+ '(or null float (integer -2 *)))
+
+ ;; 42
+ ((defun comp-tests-ret-type-spec-f (x y)
+ (when (and (<= 1 x 10)
+ (<= 2 y))
+ (- x y)))
+ '(or null float (integer * 8)))
+
+ ;; 43
+ ((defun comp-tests-ret-type-spec-f (x y)
+ (when (and (<= x 10)
+ (<= 2 y))
+ (- x y)))
+ '(or null float (integer * 8)))
+
+ ;; 44
+ ((defun comp-tests-ret-type-spec-f (x y)
+ (when (and (<= x 10)
+ (<= y 3))
+ (- x y)))
+ '(or null float integer))
+
+ ;; 45
+ ((defun comp-tests-ret-type-spec-f (x y)
+ (when (and (<= 2 x)
+ (<= 3 y))
+ (- x y)))
+ '(or null float integer))
+
+ ;; 46
+ ;; SBCL: (OR (RATIONAL (6) (30)) (SINGLE-FLOAT 6.0 30.0)
+ ;; (DOUBLE-FLOAT 6.0d0 30.0d0) NULL)
+ ((defun comp-tests-ret-type-spec-f (x y z i j k)
+ (when (and (< 1 x 5)
+ (< 1 y 5)
+ (< 1 z 5)
+ (< 1 i 5)
+ (< 1 j 5)
+ (< 1 k 5))
+ (+ x y z i j k)))
+ '(or null float (integer 12 24)))
+
+ ;; 47
+ ((defun comp-tests-ret-type-spec-f (x)
+ (when (<= 1 x 5)
+ (1+ x)))
+ '(or null float (integer 2 6)))
+
+ ;;48
+ ((defun comp-tests-ret-type-spec-f (x)
+ (when (<= 1 x 5)
+ (1- x)))
+ '(or null float (integer 0 4)))
+
+ ;; 49
+ ((defun comp-tests-ret-type-spec-f ()
+ (error "Foo"))
+ 'nil)
+
+ ;; 50
+ ((defun comp-tests-ret-type-spec-f (x)
+ (if (stringp x)
+ x
+ 'bar))
+ '(or (member bar) string))
+
+ ;; 51
+ ((defun comp-tests-ret-type-spec-f (x)
+ (if (stringp x)
+ 'bar
+ x))
+ '(not string))
+
+ ;; 52
+ ((defun comp-tests-ret-type-spec-f (x)
+ (if (integerp x)
+ x
+ 'bar))
+ '(or (member bar) integer))
+
+ ;; 53
+ ((defun comp-tests-ret-type-spec-f (x)
+ (when (integerp x)
+ x))
+ '(or null integer))
+
+ ;; 54
+ ((defun comp-tests-ret-type-spec-f (x)
+ (unless (symbolp x)
+ x))
+ 't)
+
+ ;; 55
+ ((defun comp-tests-ret-type-spec-f (x)
+ (unless (integerp x)
+ x))
+ '(not integer))
+
+ ;; 56
+ ((defun comp-tests-ret-type-spec-f (x)
+ (cl-ecase x
+ (1 (message "one"))
+ (5 (message "five")))
+ x)
+ 't
+ ;; FIXME improve `comp-cond-cstrs-target-mvar' to cross block
+ ;; boundary if necessary as this should return:
+ ;; (or (integer 1 1) (integer 5 5))
+ )
+
+ ;; 57
+ ((defun comp-tests-ret-type-spec-f (x)
+ (unless (or (eq x 'foo)
+ (eql x 3))
+ (error "Not foo or 3"))
+ x)
+ '(or (member foo) (integer 3 3)))
+
+ ;;58
+ ((defun comp-tests-ret-type-spec-f (x y)
+ (if (and (natnump x)
+ (natnump y)
+ (<= x y))
+ x
+ (error "")))
+ '(integer 0 *))
+
+ ;; 59
+ ((defun comp-tests-ret-type-spec-f (x y)
+ (if (and (>= x 3)
+ (<= y 10)
+ (<= x y))
+ x
+ (error "")))
+ '(or float (integer 3 10)))
+
+ ;; 60
+ ((defun comp-tests-ret-type-spec-f (x y)
+ (if (and (<= x 10)
+ (>= y 3)
+ (>= x y))
+ x
+ (error "")))
+ '(or float (integer 3 10)))
+
+ ;; 61
+ ((defun comp-tests-ret-type-spec-f (x)
+ (if (= x 1.0)
+ x
+ (error "")))
+ '(or (member 1.0) (integer 1 1)))
+
+ ;; 62
+ ((defun comp-tests-ret-type-spec-f (x)
+ (if (= x 1.0)
+ x
+ (error "")))
+ '(or (member 1.0) (integer 1 1)))
+
+ ;; 63
+ ((defun comp-tests-ret-type-spec-f (x)
+ (if (= x 1.1)
+ x
+ (error "")))
+ '(member 1.1))
+
+ ;; 64
+ ((defun comp-tests-ret-type-spec-f (x)
+ (if (= x 1)
+ x
+ (error "")))
+ '(or (member 1.0) (integer 1 1)))
+
+ ;; 65
+ ((defun comp-tests-ret-type-spec-f (x)
+ (if (= x 1)
+ x
+ (error "")))
+ '(or (member 1.0) (integer 1 1)))
+
+ ;; 66
+ ((defun comp-tests-ret-type-spec-f (x)
+ (if (eql x 0.0)
+ x
+ (error "")))
+ 'float)
+
+ ;; 67
+ ((defun comp-tests-ret-type-spec-f (x)
+ (if (equal x '(1 2 3))
+ x
+ (error "")))
+ 'cons)
+
+ ;; 68
+ ((defun comp-tests-ret-type-spec-f (x)
+ (if (and (floatp x)
+ (= x 1))
+ x
+ (error "")))
+ ;; Conservative (see cstr relax in `comp-cstr-=').
+ '(or (member 1.0) (integer 1 1)))
+
+ ;; 69
+ ((defun comp-tests-ret-type-spec-f (x)
+ (if (and (integer x)
+ (= x 1))
+ x
+ (error "")))
+ ;; Conservative (see cstr relax in `comp-cstr-=').
+ '(or (member 1.0) (integer 1 1)))
+
+ ;; 70
+ ((defun comp-tests-ret-type-spec-f (x y)
+ (if (and (floatp x)
+ (integerp y)
+ (= x y))
+ x
+ (error "")))
+ '(or float integer))
+
+ ;; 71
+ ((defun comp-tests-ret-type-spec-f (x)
+ (if (= x 0.0)
+ x
+ (error "")))
+ '(or (member -0.0 0.0) (integer 0 0)))
+
+ ;; 72
+ ((defun comp-tests-ret-type-spec-f (x)
+ (unless (= x 0.0)
+ (error ""))
+ (unless (eql x -0.0)
+ (error ""))
+ x)
+ 'float)
+
+ ;; 73
+ ((defun comp-tests-ret-type-spec-f (x)
+ (when (eql x 1.0)
+ (error ""))
+ x)
+ 't)
+
+ ;; 74
+ ((defun comp-tests-ret-type-spec-f (x)
+ (if (eq x 0)
+ (error "")
+ (1+ x)))
+ 'number)))
+
+ (defun comp-tests-define-type-spec-test (number x)
+ `(comp-deftest ,(intern (format "ret-type-spec-%d" number)) ()
+ ,(format "Type specifier test number %d." number)
+ (let ((comp-ctxt (make-comp-cstr-ctxt)))
+ (comp-tests-check-ret-type-spec ',(car x) ,(cadr x))))))
+
+(defmacro comp-tests-define-type-spec-tests ()
+ "Define all type specifier tests."
+ `(progn
+ ,@(cl-loop
+ for test in comp-tests-type-spec-tests
+ for n from 1
+ collect (comp-tests-define-type-spec-test n test))))
+
+(comp-tests-define-type-spec-tests)
+
+(defun comp-tests-pure-checker-1 (_)
+ "Check that inside `comp-tests-pure-caller-f' `comp-tests-pure-callee-f' is
+folded."
+ (should
+ (cl-notany
+ #'identity
+ (comp-tests-map-checker
+ 'comp-tests-pure-caller-f
+ (lambda (insn)
+ (or (comp-tests-mentioned-p 'comp-tests-pure-callee-f insn)
+ (comp-tests-mentioned-p (comp-c-func-name
+ 'comp-tests-pure-callee-f "F" t)
+ insn)))))))
+
+(defun comp-tests-pure-checker-2 (_)
+ "Check that `comp-tests-pure-fibn-f' is folded."
+ (should
+ (cl-notany
+ #'identity
+ (comp-tests-map-checker
+ 'comp-tests-pure-fibn-entry-f
+ (lambda (insn)
+ (or (comp-tests-mentioned-p 'comp-tests-pure-fibn-f insn)
+ (comp-tests-mentioned-p (comp-c-func-name 'comp-tests-pure-fibn-f "F" t)
+ insn)))))))
+
+(comp-deftest pure ()
+ "Some tests for pure functions optimization."
+ (let ((native-comp-speed 3)
+ (comp-post-pass-hooks '((comp-final comp-tests-pure-checker-1
+ comp-tests-pure-checker-2))))
+ (load (native-compile (ert-resource-file "comp-test-pure.el")))
+ (declare-function comp-tests-pure-caller-f nil)
+ (declare-function comp-tests-pure-fibn-entry-f nil)
+
+ (should (subr-native-elisp-p (symbol-function 'comp-tests-pure-caller-f)))
+ (should (= (comp-tests-pure-caller-f) 4))
+
+ (should (subr-native-elisp-p (symbol-function 'comp-tests-pure-fibn-entry-f)))
+ (should (= (comp-tests-pure-fibn-entry-f) 6765))))
+
+(defvar comp-tests-cond-rw-checked-function nil
+ "Function to be checked.")
+(defun comp-tests-cond-rw-checker-val (_)
+ "Check we manage to propagate the correct return value."
+ (should
+ (cl-some
+ #'identity
+ (comp-tests-map-checker
+ comp-tests-cond-rw-checked-function
+ (lambda (insn)
+ (pcase insn
+ (`(return ,mvar)
+ (and (comp-cstr-imm-vld-p mvar)
+ (eql (comp-cstr-imm mvar) 123)))))))))
+
+(defvar comp-tests-cond-rw-expected-type nil
+ "Type to expect in `comp-tests-cond-rw-checker-type'.")
+(defun comp-tests-cond-rw-checker-type (_)
+ "Check we manage to propagate the correct return type."
+ (should
+ (cl-some
+ #'identity
+ (comp-tests-map-checker
+ comp-tests-cond-rw-checked-function
+ (lambda (insn)
+ (pcase insn
+ (`(return ,mvar)
+ (equal (comp-mvar-typeset mvar)
+ comp-tests-cond-rw-expected-type))))))))
+
+;;; comp-tests.el ends here
diff --git a/test/src/data-tests.el b/test/src/data-tests.el
index 374d1689b9e..463a894d095 100644
--- a/test/src/data-tests.el
+++ b/test/src/data-tests.el
@@ -1,6 +1,6 @@
-;;; data-tests.el --- tests for src/data.c
+;;; data-tests.el --- tests for src/data.c -*- lexical-binding:t -*-
-;; Copyright (C) 2013-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2022 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -23,13 +23,21 @@
(require 'cl-lib)
+(defconst data-tests--float-greater-than-fixnums (+ 1.0 most-positive-fixnum)
+ "A floating-point value that is greater than all fixnums.
+It is also as small as conveniently possible, to make the tests sharper.
+Adding 1.0 to `most-positive-fixnum' should suffice on all
+practical Emacs platforms, since the result is a power of 2 and
+this is exactly representable and is greater than
+`most-positive-fixnum', which is just less than a power of 2.")
+
(ert-deftest data-tests-= ()
(should-error (=))
(should (= 1))
(should (= 2 2))
(should (= 9 9 9 9 9 9 9 9 9))
(should (= most-negative-fixnum (float most-negative-fixnum)))
- (should-not (= most-positive-fixnum (+ 1.0 most-positive-fixnum)))
+ (should-not (= most-positive-fixnum data-tests--float-greater-than-fixnums))
(should-not (apply #'= '(3 8 3)))
(should-error (= 9 9 'foo))
;; Short circuits before getting to bad arg
@@ -40,7 +48,7 @@
(should (< 1))
(should (< 2 3))
(should (< -6 -1 0 2 3 4 8 9 999))
- (should (< 0.5 most-positive-fixnum (+ 1.0 most-positive-fixnum)))
+ (should (< 0.5 most-positive-fixnum data-tests--float-greater-than-fixnums))
(should-not (apply #'< '(3 8 3)))
(should-error (< 9 10 'foo))
;; Short circuits before getting to bad arg
@@ -51,7 +59,7 @@
(should (> 1))
(should (> 3 2))
(should (> 6 1 0 -2 -3 -4 -8 -9 -999))
- (should (> (+ 1.0 most-positive-fixnum) most-positive-fixnum 0.5))
+ (should (> data-tests--float-greater-than-fixnums most-positive-fixnum 0.5))
(should-not (apply #'> '(3 8 3)))
(should-error (> 9 8 'foo))
;; Short circuits before getting to bad arg
@@ -62,7 +70,7 @@
(should (<= 1))
(should (<= 2 3))
(should (<= -6 -1 -1 0 0 0 2 3 4 8 999))
- (should (<= 0.5 most-positive-fixnum (+ 1.0 most-positive-fixnum)))
+ (should (<= 0.5 most-positive-fixnum data-tests--float-greater-than-fixnums))
(should-not (apply #'<= '(3 8 3 3)))
(should-error (<= 9 10 'foo))
;; Short circuits before getting to bad arg
@@ -73,7 +81,7 @@
(should (>= 1))
(should (>= 3 2))
(should (>= 666 1 0 0 -2 -3 -3 -3 -4 -8 -8 -9 -999))
- (should (>= (+ 1.0 most-positive-fixnum) most-positive-fixnum))
+ (should (>= data-tests--float-greater-than-fixnums most-positive-fixnum))
(should-not (apply #'>= '(3 8 3)))
(should-error (>= 9 8 'foo))
;; Short circuits before getting to bad arg
@@ -97,7 +105,7 @@
(should (= 2 (min 3 2)))
(should (= -999 (min 666 1 0 0 -2 -3 -3 -3 -4 -8 -8 -9 -999)))
(should (= most-positive-fixnum
- (min (+ 1.0 most-positive-fixnum) most-positive-fixnum)))
+ (min data-tests--float-greater-than-fixnums most-positive-fixnum)))
(should (= 3 (apply #'min '(3 8 3))))
(should-error (min 9 8 'foo))
(should-error (min (make-marker)))
@@ -105,15 +113,17 @@
(should (isnan (min 0.0e+NaN)))
(should (isnan (min 0.0e+NaN 1 2)))
(should (isnan (min 1.0 0.0e+NaN)))
- (should (isnan (min 1.0 0.0e+NaN 1.1))))
+ (should (isnan (min 1.0 0.0e+NaN 1.1)))
+ (should (isnan (min 1.0 0.0e+NaN 1.1 (1+ most-positive-fixnum))))
+ (should (isnan (max 1.0 0.0e+NaN 1.1 (1+ most-positive-fixnum)))))
(defun data-tests-popcnt (byte)
"Calculate the Hamming weight of BYTE."
(if (< byte 0)
(setq byte (lognot byte)))
- (setq byte (- byte (logand (lsh byte -1) #x55555555)))
- (setq byte (+ (logand byte #x33333333) (logand (lsh byte -2) #x33333333)))
- (lsh (* (logand (+ byte (lsh byte -4)) #x0f0f0f0f) #x01010101) -24))
+ (if (zerop byte)
+ 0
+ (+ (logand byte 1) (data-tests-popcnt (ash byte -1)))))
(ert-deftest data-tests-logcount ()
(should (cl-loop for n in (number-sequence -255 255)
@@ -164,7 +174,7 @@
sum 1))
(defun test-bool-vector-bv-from-hex-string (desc)
- (let (bv nchars nibbles)
+ (let (bv nibbles)
(dolist (c (string-to-list desc))
(push (string-to-number
(char-to-string c)
@@ -176,29 +186,28 @@
(dotimes (_ 4)
(aset bv i (> (logand 1 n) 0))
(cl-incf i)
- (setf n (lsh n -1)))))
+ (setf n (ash n -1)))))
bv))
(defun test-bool-vector-to-hex-string (bv)
(let (nibbles (v (cl-coerce bv 'list)))
(while v
(push (logior
- (lsh (if (nth 0 v) 1 0) 0)
- (lsh (if (nth 1 v) 1 0) 1)
- (lsh (if (nth 2 v) 1 0) 2)
- (lsh (if (nth 3 v) 1 0) 3))
+ (ash (if (nth 0 v) 1 0) 0)
+ (ash (if (nth 1 v) 1 0) 1)
+ (ash (if (nth 2 v) 1 0) 2)
+ (ash (if (nth 3 v) 1 0) 3))
nibbles)
(setf v (nthcdr 4 v)))
(mapconcat (lambda (n) (format "%X" n))
- (nreverse nibbles)
- "")))
+ (nreverse nibbles))))
(defun test-bool-vector-count-consecutive-tc (desc)
- "Run a test case for bool-vector-count-consecutive.
+ "Run a test case for `bool-vector-count-consecutive'.
DESC is a string describing the test. It is a sequence of
hexadecimal digits describing the bool vector. We exhaustively
test all counts at all possible positions in the vector by
-comparing the subr with a much slower lisp implementation."
+comparing the subr with a much slower Lisp implementation."
(let ((bv (test-bool-vector-bv-from-hex-string desc)))
(cl-loop
for lf in '(nil t)
@@ -234,9 +243,9 @@ comparing the subr with a much slower lisp implementation."
(defun test-bool-vector-apply-mock-op (mock a b c)
"Compute (slowly) the correct result of a bool-vector set operation."
- (let (changed nv)
+ (let (changed)
(cl-assert (eql (length b) (length c)))
- (if a (setf nv a)
+ (unless a
(setf a (make-bool-vector (length b) nil))
(setf changed t))
@@ -314,7 +323,7 @@ comparing the subr with a much slower lisp implementation."
(defvar binding-test-some-local 'some)
(with-current-buffer binding-test-buffer-A
- (set (make-local-variable 'binding-test-some-local) 'local))
+ (setq-local binding-test-some-local 'local))
(ert-deftest binding-test-manual ()
"A test case from the elisp manual."
@@ -328,13 +337,55 @@ comparing the subr with a much slower lisp implementation."
(should (eq binding-test-some-local 'local))))
(ert-deftest binding-test-setq-default ()
- "Test that a setq-default has no effect when there is a local binding."
+ "Test that a `setq-default' has no effect when there is a local binding."
(with-current-buffer binding-test-buffer-B
;; This variable is not local in this buffer.
(let ((binding-test-some-local 'something-else))
(setq-default binding-test-some-local 'new-default))
(should (eq binding-test-some-local 'some))))
+(ert-deftest data-tests--let-buffer-local ()
+ (let ((blvar (make-symbol "blvar")))
+ (set-default blvar nil)
+ (make-variable-buffer-local blvar)
+
+ (dolist (var (list blvar 'left-margin))
+ (let ((def (default-value var)))
+ (with-temp-buffer
+ (should (equal def (symbol-value var)))
+ (cl-progv (list var) (list 42)
+ (should (equal (symbol-value var) 42))
+ (should (equal (default-value var) (symbol-value var)))
+ (set var 123)
+ (should (not (local-variable-p var)))
+ (should (equal (symbol-value var) 123))
+ (should (equal (default-value var) (symbol-value var)))) ;bug#44733
+ (should (equal (symbol-value var) def))
+ (should (equal (default-value var) (symbol-value var))))
+ (should (equal (default-value var) def))))))
+
+(ert-deftest data-tests--let-buffer-local-no-unwind-other-buffers ()
+ "Test that a let-binding for a buffer-local unwinds only current-buffer."
+ (let ((blvar (make-symbol "blvar")))
+ (set-default blvar 0)
+ (make-variable-buffer-local blvar)
+ (dolist (var (list blvar 'left-margin))
+ (let* ((def (default-value var))
+ (newdef (+ def 1))
+ (otherbuf (generate-new-buffer "otherbuf")))
+ (with-temp-buffer
+ (cl-progv (list var) (list newdef)
+ (with-current-buffer otherbuf
+ (set var 123)
+ (should (local-variable-p var))
+ (should (equal (symbol-value var) 123))
+ (should (equal (default-value var) newdef))))
+ (with-current-buffer otherbuf
+ (should (local-variable-p var))
+ (should (equal (symbol-value var) 123))
+ (should (equal (default-value var) def)))
+ )))))
+
(ert-deftest binding-test-makunbound ()
"Tests of makunbound, from the manual."
(with-current-buffer binding-test-buffer-B
@@ -347,30 +398,62 @@ comparing the subr with a much slower lisp implementation."
(eq binding-test-some-local 'outer))))))
(ert-deftest binding-test-defvar-bool ()
- "Test DEFVAR_BOOL"
+ "Test DEFVAR_BOOL."
(let ((display-hourglass 5))
(should (eq display-hourglass t))))
(ert-deftest binding-test-defvar-int ()
- "Test DEFVAR_INT"
+ "Test DEFVAR_INT."
(should-error (setq gc-cons-threshold 5.0) :type 'wrong-type-argument))
(ert-deftest binding-test-set-constant-t ()
- "Test setting the constant t"
+ "Test setting the constant t."
(with-no-warnings (should-error (setq t 'bob) :type 'setting-constant)))
(ert-deftest binding-test-set-constant-nil ()
- "Test setting the constant nil"
+ "Test setting the constant nil."
(with-no-warnings (should-error (setq nil 'bob) :type 'setting-constant)))
(ert-deftest binding-test-set-constant-keyword ()
- "Test setting a keyword constant"
+ "Test setting a keyword constant."
(with-no-warnings (should-error (setq :keyword 'bob) :type 'setting-constant)))
-(ert-deftest binding-test-set-constant-nil ()
- "Test setting a keyword to itself"
+(ert-deftest binding-test-set-constant-itself ()
+ "Test setting a keyword to itself."
(with-no-warnings (should (setq :keyword :keyword))))
+(ert-deftest data-tests--set-default-per-buffer ()
+ :expected-result t ;; Not fixed yet!
+ ;; FIXME: Performance tests are inherently unreliable.
+ ;; Using wall-clock time makes it even worse, so don't bother unless
+ ;; we have the primitive to measure cpu-time.
+ (skip-unless (fboundp 'current-cpu-time))
+ ;; Test performance of set-default on DEFVAR_PER_BUFFER variables.
+ ;; More specifically, test the problem seen in bug#41029 where setting
+ ;; the default value of a variable takes time proportional to the
+ ;; number of buffers.
+ (when (fboundp 'current-cpu-time) ; silence byte-compiler
+ (let* ((fun #'error)
+ (test (lambda ()
+ (with-temp-buffer
+ (let ((st (car (current-cpu-time))))
+ (dotimes (_ 1000)
+ (let ((case-fold-search 'data-test))
+ ;; Use an indirection through a mutable var
+ ;; to try and make sure the byte-compiler
+ ;; doesn't optimize away the let bindings.
+ (funcall fun)))
+ ;; FIXME: Handle the wraparound, if any.
+ (- (car (current-cpu-time)) st)))))
+ (_ (setq fun #'ignore))
+ (time1 (funcall test))
+ (bufs (mapcar (lambda (_) (generate-new-buffer " data-test"))
+ (make-list 1000 nil)))
+ (time2 (funcall test)))
+ (mapc #'kill-buffer bufs)
+ ;; Don't divide one time by the other since they may be 0.
+ (should (< time2 (* time1 5))))))
+
;; More tests to write -
;; kill-local-variable
;; defconst; can modify
@@ -474,7 +557,7 @@ comparing the subr with a much slower lisp implementation."
(should-have-watch-data `(data-tests-lvar 3 set ,buf1)))
(should-have-watch-data `(data-tests-lvar 1 unlet ,buf1))
(setq-default data-tests-lvar 4)
- (should-have-watch-data `(data-tests-lvar 4 set nil))
+ (should-have-watch-data '(data-tests-lvar 4 set nil))
(with-temp-buffer
(setq buf2 (current-buffer))
(setq data-tests-lvar 1)
@@ -491,7 +574,7 @@ comparing the subr with a much slower lisp implementation."
(kill-all-local-variables)
(should-have-watch-data `(data-tests-lvar nil makunbound ,buf2)))
(setq-default data-tests-lvar 4)
- (should-have-watch-data `(data-tests-lvar 4 set nil))
+ (should-have-watch-data '(data-tests-lvar 4 set nil))
(makunbound 'data-tests-lvar)
(should-have-watch-data '(data-tests-lvar nil makunbound nil))
(setq data-tests-lvar 5)
@@ -499,3 +582,194 @@ comparing the subr with a much slower lisp implementation."
(remove-variable-watcher 'data-tests-lvar collect-watch-data)
(setq data-tests-lvar 6)
(should (null watch-data)))))
+
+(ert-deftest data-tests-kill-all-local-variables () ;bug#30846
+ (with-temp-buffer
+ (setq-local data-tests-foo1 1)
+ (setq-local data-tests-foo2 2)
+ (setq-local data-tests-foo3 3)
+ (let ((oldfoo2 nil))
+ (add-variable-watcher 'data-tests-foo2
+ (lambda (&rest _)
+ (setq oldfoo2 (bound-and-true-p data-tests-foo2))))
+ (kill-all-local-variables)
+ (should (equal oldfoo2 '2)) ;Watcher is run before changing the var.
+ (should (not (or (bound-and-true-p data-tests-foo1)
+ (bound-and-true-p data-tests-foo2)
+ (bound-and-true-p data-tests-foo3)))))))
+
+(ert-deftest data-tests-bignum ()
+ (should (bignump (+ most-positive-fixnum 1)))
+ (let ((f0 (+ (float most-positive-fixnum) 1))
+ (f-1 (- (float most-negative-fixnum) 1))
+ (b0 (+ most-positive-fixnum 1))
+ (b-1 (- most-negative-fixnum 1)))
+ (should (> b0 -1))
+ (should (> b0 f-1))
+ (should (> b0 b-1))
+ (should (>= b0 -1))
+ (should (>= b0 f-1))
+ (should (>= b0 b-1))
+ (should (>= b-1 b-1))
+
+ (should (< -1 b0))
+ (should (< f-1 b0))
+ (should (< b-1 b0))
+ (should (<= -1 b0))
+ (should (<= f-1 b0))
+ (should (<= b-1 b0))
+ (should (<= b-1 b-1))
+
+ (should (= (+ f0 b0) (+ b0 f0)))
+ (should (= (+ f0 b-1) (+ b-1 f0)))
+ (should (= (+ f-1 b0) (+ b0 f-1)))
+ (should (= (+ f-1 b-1) (+ b-1 f-1)))
+
+ (should (= (* f0 b0) (* b0 f0)))
+ (should (= (* f0 b-1) (* b-1 f0)))
+ (should (= (* f-1 b0) (* b0 f-1)))
+ (should (= (* f-1 b-1) (* b-1 f-1)))
+
+ (should (= b0 f0))
+ (should (= b0 b0))
+
+ (should (/= b0 f-1))
+ (should (/= b0 b-1))
+
+ (should (/= b0 0.0e+NaN))
+ (should (/= b-1 0.0e+NaN))))
+
+(ert-deftest data-tests-+ ()
+ (should-not (fixnump (+ most-positive-fixnum most-positive-fixnum)))
+ (should (> (+ most-positive-fixnum most-positive-fixnum) most-positive-fixnum))
+ (should (eq (- (+ most-positive-fixnum most-positive-fixnum)
+ (+ most-positive-fixnum most-positive-fixnum))
+ 0)))
+
+(ert-deftest data-tests-/ ()
+ (let* ((x (* most-positive-fixnum 8))
+ (y (* most-negative-fixnum 8))
+ (z (- y)))
+ (should (= most-positive-fixnum (/ x 8)))
+ (should (= most-negative-fixnum (/ y 8)))
+ (should (= -1 (/ y z)))
+ (should (= -1 (/ z y)))
+ (should (= 0 (/ x (* 2 x))))
+ (should (= 0 (/ y (* 2 y))))
+ (should (= 0 (/ z (* 2 z))))))
+
+(ert-deftest data-tests-number-predicates ()
+ (should (fixnump 0))
+ (should (fixnump most-negative-fixnum))
+ (should (fixnump most-positive-fixnum))
+ (should (integerp (+ most-positive-fixnum 1)))
+ (should (integer-or-marker-p (+ most-positive-fixnum 1)))
+ (should (numberp (+ most-positive-fixnum 1)))
+ (should (number-or-marker-p (+ most-positive-fixnum 1)))
+ (should (natnump (+ most-positive-fixnum 1)))
+ (should-not (fixnump (+ most-positive-fixnum 1)))
+ (should (bignump (+ most-positive-fixnum 1))))
+
+(ert-deftest data-tests-number-to-string ()
+ (let* ((s "99999999999999999999999999999")
+ (v (read s)))
+ (should (equal (number-to-string v) s))))
+
+(ert-deftest data-tests-1+ ()
+ (should (> (1+ most-positive-fixnum) most-positive-fixnum))
+ (should (fixnump (1+ (1- most-negative-fixnum)))))
+
+(ert-deftest data-tests-1- ()
+ (should (< (1- most-negative-fixnum) most-negative-fixnum))
+ (should (fixnump (1- (1+ most-positive-fixnum)))))
+
+(ert-deftest data-tests-logand ()
+ (should (= -1 (logand) (logand -1) (logand -1 -1)))
+ (let ((n (1+ most-positive-fixnum)))
+ (should (= (logand -1 n) n)))
+ (let ((n (* 2 most-negative-fixnum)))
+ (should (= (logand -1 n) n))))
+
+(ert-deftest data-tests-logcount-2 ()
+ (should (= (logcount (read "#xffffffffffffffffffffffffffffffff")) 128)))
+
+(ert-deftest data-tests-logior ()
+ (should (= -1 (logior -1) (logior -1 -1)))
+ (should (= -1 (logior most-positive-fixnum most-negative-fixnum))))
+
+(ert-deftest data-tests-logxor ()
+ (should (= -1 (logxor -1) (logxor -1 -1 -1)))
+ (let ((n (1+ most-positive-fixnum)))
+ (should (= (logxor -1 n) (lognot n)))))
+
+(ert-deftest data-tests-minmax ()
+ (let ((a (- most-negative-fixnum 1))
+ (b (+ most-positive-fixnum 1))
+ (c 0))
+ (should (= (min a b c) a))
+ (should (= (max a b c) b))))
+
+(defun data-tests-check-sign (x y)
+ (should (eq (cl-signum x) (cl-signum y))))
+
+(ert-deftest data-tests-%-mod ()
+ (let* ((b1 (+ most-positive-fixnum 1))
+ (nb1 (- b1))
+ (b3 (+ most-positive-fixnum 3))
+ (nb3 (- b3)))
+ (data-tests-check-sign (% 1 3) (% b1 b3))
+ (data-tests-check-sign (mod 1 3) (mod b1 b3))
+ (data-tests-check-sign (% 1 -3) (% b1 nb3))
+ (data-tests-check-sign (mod 1 -3) (mod b1 nb3))
+ (data-tests-check-sign (% -1 3) (% nb1 b3))
+ (data-tests-check-sign (mod -1 3) (mod nb1 b3))
+ (data-tests-check-sign (% -1 -3) (% nb1 nb3))
+ (data-tests-check-sign (mod -1 -3) (mod nb1 nb3))))
+
+(ert-deftest data-tests-mod-0 ()
+ (dolist (num (list (1- most-negative-fixnum) -1 0 1
+ (1+ most-positive-fixnum)))
+ (should-error (mod num 0)))
+ (when (ignore-errors (/ 0.0 0))
+ (should (equal (abs (mod 0.0 0)) (abs (- 0.0 (/ 0.0 0)))))))
+
+(ert-deftest data-tests-ash-lsh ()
+ (should (= (ash most-negative-fixnum 1)
+ (* most-negative-fixnum 2)))
+ (should (= (ash 0 (* 2 most-positive-fixnum)) 0))
+ (should (= (ash 1000 (* 2 most-negative-fixnum)) 0))
+ (should (= (ash -1000 (* 2 most-negative-fixnum)) -1))
+ (should (= (ash (* 2 most-negative-fixnum) (* 2 most-negative-fixnum)) -1))
+ (should (= (ash (* 2 most-negative-fixnum) -1)
+ most-negative-fixnum))
+ (with-suppressed-warnings ((suspicious lsh))
+ (should (= (lsh most-negative-fixnum 1)
+ (* most-negative-fixnum 2)))
+ (should (= (lsh most-positive-fixnum -1) (/ most-positive-fixnum 2)))
+ (should (= (lsh most-negative-fixnum -1) (lsh (- most-negative-fixnum) -1)))
+ (should (= (lsh -1 -1) most-positive-fixnum))
+ (should-error (lsh (1- most-negative-fixnum) -1))))
+
+(ert-deftest data-tests-make-local-forwarded-var () ;bug#34318
+ ;; Boy, this bug is tricky to trigger. You need to:
+ ;; - call make-local-variable on a forwarded var (i.e. one that
+ ;; has a corresponding C var linked via DEFVAR_(LISP|INT|BOOL))
+ ;; - cause the C code to modify this variable from the C side of the
+ ;; forwarding, but this needs to happen before the var is accessed
+ ;; from the Lisp side and before we switch to another buffer.
+ ;; The trigger in bug#34318 doesn't exist any more because the C code has
+ ;; changed. Instead I found the trigger below.
+ (with-temp-buffer
+ (setq last-coding-system-used 'bug34318)
+ (make-local-variable 'last-coding-system-used)
+ ;; This should set last-coding-system-used to `no-conversion'.
+ (decode-coding-string "hello" nil)
+ (should (equal (list last-coding-system-used
+ (default-value 'last-coding-system-used))
+ '(no-conversion bug34318)))))
+
+(ert-deftest data-tests-make_symbol_constant ()
+ "Can't set variable marked with 'make_symbol_constant'."
+ (should-error (setq most-positive-fixnum 1) :type 'setting-constant))
+
+;;; data-tests.el ends here
diff --git a/test/src/decompress-tests.el b/test/src/decompress-tests.el
index 8a6f4d1fb95..47d67b7bda4 100644
--- a/test/src/decompress-tests.el
+++ b/test/src/decompress-tests.el
@@ -1,6 +1,6 @@
-;;; decompress-tests.el --- Test suite for decompress.
+;;; decompress-tests.el --- Test suite for decompress. -*- lexical-binding: t -*-
-;; Copyright (C) 2013-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2022 Free Software Foundation, Inc.
;; Author: Lars Ingebrigtsen <larsi@gnus.org>
@@ -23,23 +23,25 @@
(require 'ert)
+(declare-function zlib-decompress-region "decompress.c")
+
(defvar zlib-tests-data-directory
(expand-file-name "data/decompress" (getenv "EMACS_TEST_DIRECTORY"))
"Directory containing zlib test data.")
(ert-deftest zlib--decompress ()
"Test decompressing a gzipped file."
- (when (and (fboundp 'zlib-available-p)
- (zlib-available-p))
- (should (string=
- (with-temp-buffer
- (set-buffer-multibyte nil)
- (insert-file-contents-literally
- (expand-file-name "foo.gz" zlib-tests-data-directory))
- (zlib-decompress-region (point-min) (point-max))
- (buffer-string))
- "foo\n"))))
+ (skip-unless (and (fboundp 'zlib-available-p)
+ (zlib-available-p)))
+ (should (string=
+ (with-temp-buffer
+ (set-buffer-multibyte nil)
+ (insert-file-contents-literally
+ (expand-file-name "foo.gz" zlib-tests-data-directory))
+ (zlib-decompress-region (point-min) (point-max))
+ (buffer-string))
+ "foo\n")))
(provide 'decompress-tests)
-;;; decompress-tests.el ends here.
+;;; decompress-tests.el ends here
diff --git a/test/src/doc-tests.el b/test/src/doc-tests.el
index d8e4320bc6f..ee4f02347ec 100644
--- a/test/src/doc-tests.el
+++ b/test/src/doc-tests.el
@@ -1,92 +1,43 @@
-;;; doc-tests.el --- Tests for doc.c
+;;; doc-tests.el --- tests for doc.c functions -*- lexical-binding: t -*-
-;; Copyright (C) 2016-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2022 Free Software Foundation, Inc.
-;; Author: Eli Zaretskii <eliz@gnu.org>
+;; This file is part of GNU Emacs.
-;; This program is free software; you can redistribute it and/or modify
+;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
-;; This program is distributed in the hope that it will be useful,
+;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
-;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Code:
(require 'ert)
-(ert-deftest doc-test-substitute-command-keys ()
- ;; Bindings.
- (should (string= (substitute-command-keys "foo \\[goto-char]") "foo M-g c"))
- ;; Cannot use string= here, as that compares unibyte and multibyte
- ;; strings not equal.
- (should (compare-strings
- (substitute-command-keys "\200 \\[goto-char]") nil nil
- "\200 M-g c" nil nil))
- ;; Literals.
- (should (string= (substitute-command-keys "foo \\=\\[goto-char]")
- "foo \\[goto-char]"))
- (should (string= (substitute-command-keys "foo \\=\\=")
- "foo \\="))
- ;; Keymaps.
- (should (string= (substitute-command-keys
- "\\{minibuffer-local-must-match-map}")
- "\
-key binding
---- -------
+(ert-deftest doc-tests-documentation/c-primitive ()
+ (should (stringp (documentation 'defalias))))
-C-g abort-recursive-edit
-TAB minibuffer-complete
-C-j minibuffer-complete-and-exit
-RET minibuffer-complete-and-exit
-ESC Prefix Command
-SPC minibuffer-complete-word
-? minibuffer-completion-help
-<C-tab> file-cache-minibuffer-complete
-<XF86Back> previous-history-element
-<XF86Forward> next-history-element
-<down> next-line-or-history-element
-<next> next-history-element
-<prior> switch-to-completions
-<up> previous-line-or-history-element
+(ert-deftest doc-tests-documentation/preloaded ()
+ (should (stringp (documentation 'defun))))
-M-v switch-to-completions
+(ert-deftest doc-tests-documentation/autoloaded-macro ()
+ (skip-unless noninteractive)
+ (should (autoloadp (symbol-function 'benchmark-run)))
+ (should (stringp (documentation 'benchmark-run)))) ; See Bug#52969.
-M-n next-history-element
-M-p previous-history-element
-M-r previous-matching-history-element
-M-s next-matching-history-element
+(ert-deftest doc-tests-documentation/autoloaded-defun ()
+ (skip-unless noninteractive)
+ (should (autoloadp (symbol-function 'tetris)))
+ (should (stringp (documentation 'tetris)))) ; See Bug#52969.
-"))
- (should (string=
- (substitute-command-keys
- "\\<minibuffer-local-must-match-map>\\[abort-recursive-edit]")
- "C-g"))
- ;; Allow any style of quotes, since the terminal might not support
- ;; UTF-8.
- (should (string-match
- "\nUses keymap [`‘']foobar-map['’], which is not currently defined.\n"
- (substitute-command-keys "\\{foobar-map}")))
- ;; Quotes.
- (should (let ((text-quoting-style 'grave))
- (string= (substitute-command-keys "quotes `like this'")
- "quotes `like this'")))
- (should (let ((text-quoting-style 'grave))
- (string= (substitute-command-keys "quotes ‘like this’")
- "quotes ‘like this’")))
- (should (let ((text-quoting-style 'straight))
- (string= (substitute-command-keys "quotes `like this'")
- "quotes 'like this'")))
- ;; Bugs.
- (should (string= (substitute-command-keys "\\[foobar") "\\[foobar"))
- (should (string= (substitute-command-keys "\\=") "\\="))
- )
+(ert-deftest doc-tests-quoting-style ()
+ (should (memq (text-quoting-style) '(grave straight curve))))
-(provide 'doc-tests)
;;; doc-tests.el ends here
diff --git a/test/src/editfns-tests.el b/test/src/editfns-tests.el
index 70dc9372fad..5fe896fbbd1 100644
--- a/test/src/editfns-tests.el
+++ b/test/src/editfns-tests.el
@@ -1,21 +1,21 @@
-;;; editfns-tests.el -- tests for editfns.c
+;;; editfns-tests.el --- tests for editfns.c -*- lexical-binding:t -*-
-;; Copyright (C) 2016-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2022 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
-;; This program is free software; you can redistribute it and/or modify
+;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
-;; This program is distributed in the hope that it will be useful,
+;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
-;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Code:
@@ -23,16 +23,16 @@
(ert-deftest format-properties ()
;; Bug #23730
- (should (ert-equal-including-properties
+ (should (equal-including-properties
(format (propertize "%d" 'face '(:background "red")) 1)
#("1" 0 1 (face (:background "red")))))
- (should (ert-equal-including-properties
+ (should (equal-including-properties
(format (propertize "%2d" 'face '(:background "red")) 1)
#(" 1" 0 2 (face (:background "red")))))
- (should (ert-equal-including-properties
+ (should (equal-including-properties
(format (propertize "%02d" 'face '(:background "red")) 1)
#("01" 0 2 (face (:background "red")))))
- (should (ert-equal-including-properties
+ (should (equal-including-properties
(format (concat (propertize "%2d" 'x 'X)
(propertize "a" 'a 'A)
(propertize "b" 'b 'B))
@@ -40,27 +40,27 @@
#(" 1ab" 0 2 (x X) 2 3 (a A) 3 4 (b B))))
;; Bug #5306
- (should (ert-equal-including-properties
+ (should (equal-including-properties
(format "%.10s"
(concat "1234567890aaaa"
(propertize "12345678901234567890" 'xxx 25)))
"1234567890"))
- (should (ert-equal-including-properties
+ (should (equal-including-properties
(format "%.10s"
(concat "123456789"
(propertize "12345678901234567890" 'xxx 25)))
#("1234567891" 9 10 (xxx 25))))
;; Bug #23859
- (should (ert-equal-including-properties
+ (should (equal-including-properties
(format "%4s" (propertize "hi" 'face 'bold))
#(" hi" 2 4 (face bold))))
;; Bug #23897
- (should (ert-equal-including-properties
+ (should (equal-including-properties
(format "%s" (concat (propertize "01234" 'face 'bold) "56789"))
#("0123456789" 0 5 (face bold))))
- (should (ert-equal-including-properties
+ (should (equal-including-properties
(format "%s" (concat (propertize "01" 'face 'bold)
(propertize "23" 'face 'underline)
"45"))
@@ -68,27 +68,69 @@
;; The last property range is extended to include padding on the
;; right, but the first range is not extended to the left to include
;; padding on the left!
- (should (ert-equal-including-properties
+ (should (equal-including-properties
(format "%12s" (concat (propertize "01234" 'face 'bold) "56789"))
#(" 0123456789" 2 7 (face bold))))
- (should (ert-equal-including-properties
+ (should (equal-including-properties
(format "%-12s" (concat (propertize "01234" 'face 'bold) "56789"))
#("0123456789 " 0 5 (face bold))))
- (should (ert-equal-including-properties
+ (should (equal-including-properties
(format "%10s" (concat (propertize "01" 'face 'bold)
(propertize "23" 'face 'underline)
"45"))
#(" 012345" 4 6 (face bold) 6 8 (face underline))))
- (should (ert-equal-including-properties
+ (should (equal-including-properties
(format "%-10s" (concat (propertize "01" 'face 'bold)
(propertize "23" 'face 'underline)
"45"))
#("012345 " 0 2 (face bold) 2 4 (face underline))))
- (should (ert-equal-including-properties
+ (should (equal-including-properties
(format "%-10s" (concat (propertize "01" 'face 'bold)
(propertize "23" 'face 'underline)
(propertize "45" 'face 'italic)))
- #("012345 " 0 2 (face bold) 2 4 (face underline) 4 10 (face italic)))))
+ #("012345 "
+ 0 2 (face bold) 2 4 (face underline) 4 10 (face italic))))
+ ;; Bug #38191
+ (should (equal-including-properties
+ (format (propertize "‘foo’ %s bar" 'face 'bold) "xxx")
+ #("‘foo’ xxx bar" 0 13 (face bold))))
+ ;; Bug #32404
+ (should (equal-including-properties
+ (format (concat (propertize "%s" 'face 'bold)
+ ""
+ (propertize "%s" 'face 'error))
+ "foo" "bar")
+ #("foobar" 0 3 (face bold) 3 6 (face error))))
+ (should (equal-including-properties
+ (format (concat "%s" (propertize "%s" 'face 'error)) "foo" "bar")
+ #("foobar" 3 6 (face error))))
+ (should (equal-including-properties
+ (format (concat "%s " (propertize "%s" 'face 'error)) "foo" "bar")
+ #("foo bar" 4 7 (face error))))
+ ;; Bug #46317
+ (let ((s (propertize "X" 'prop "val")))
+ (should (equal-including-properties
+ (format (concat "%3s/" s) 12)
+ #(" 12/X" 4 5 (prop "val"))))
+ (should (equal-including-properties
+ (format (concat "%3S/" s) 12)
+ #(" 12/X" 4 5 (prop "val"))))
+ (should (equal-including-properties
+ (format (concat "%3d/" s) 12)
+ #(" 12/X" 4 5 (prop "val"))))
+ (should (equal-including-properties
+ (format (concat "%-3s/" s) 12)
+ #("12 /X" 4 5 (prop "val"))))
+ (should (equal-including-properties
+ (format (concat "%-3S/" s) 12)
+ #("12 /X" 4 5 (prop "val"))))
+ (should (equal-including-properties
+ (format (concat "%-3d/" s) 12)
+ #("12 /X" 4 5 (prop "val"))))))
+
+(ert-deftest propertize/error-even-number-of-args ()
+ "Number of args for `propertize' must be odd."
+ (should-error (propertize "foo" 'bar) :type 'wrong-number-of-arguments))
;; Tests for bug#5131.
(defun transpose-test-reverse-word (start end)
@@ -106,8 +148,8 @@
"Validate character position to byte position translation."
(let ((bytes '()))
(dotimes (pos len)
- (setq bytes (add-to-list 'bytes (position-bytes (1+ pos)) t)))
- bytes))
+ (push (position-bytes (1+ pos)) bytes))
+ (nreverse bytes)))
(ert-deftest transpose-ascii-regions-test ()
(with-temp-buffer
@@ -136,54 +178,59 @@
(ert-deftest format-c-float ()
(should-error (format "%c" 0.5)))
-;;; Check format-time-string with various TZ settings.
-;;; Use only POSIX-compatible TZ values, since the tests should work
-;;; even if tzdb is not in use.
-(ert-deftest format-time-string-with-zone ()
- ;; Don’t use (0 0 0 0) as the test case, as there are too many bugs
- ;; in MS-Windows (and presumably other) C libraries when formatting
- ;; time stamps near the Epoch of 1970-01-01 00:00:00 UTC, and this
- ;; test is for GNU Emacs, not for C runtimes. Instead, look before
- ;; you leap: "look" is the timestamp just before the first leap
- ;; second on 1972-06-30 23:59:60 UTC, so it should format to the
- ;; same string regardless of whether the underlying C library
- ;; ignores leap seconds, while avoiding circa-1970 glitches.
- ;;
- ;; Similarly, stick to the limited set of time zones that are
- ;; supported by both POSIX and MS-Windows: exactly 3 ASCII letters
- ;; in the abbreviation, and no DST.
- (let ((look '(1202 22527 999999 999999))
- (format "%Y-%m-%d %H:%M:%S.%3N %z (%Z)"))
- ;; UTC.
- (should (string-equal
- (format-time-string "%Y-%m-%d %H:%M:%S.%3N %z" look t)
- "1972-06-30 23:59:59.999 +0000"))
- ;; "UTC0".
- (should (string-equal
- (format-time-string format look "UTC0")
- "1972-06-30 23:59:59.999 +0000 (UTC)"))
- ;; Negative UTC offset, as a Lisp list.
- (should (string-equal
- (format-time-string format look '(-28800 "PST"))
- "1972-06-30 15:59:59.999 -0800 (PST)"))
- ;; Negative UTC offset, as a Lisp integer.
- (should (string-equal
- (format-time-string format look -28800)
- ;; MS-Windows build replaces unrecognizable TZ values,
- ;; such as "-08", with "ZZZ".
- (if (eq system-type 'windows-nt)
- "1972-06-30 15:59:59.999 -0800 (ZZZ)"
- "1972-06-30 15:59:59.999 -0800 (-08)")))
- ;; Positive UTC offset that is not an hour multiple, as a string.
- (should (string-equal
- (format-time-string format look "IST-5:30")
- "1972-07-01 05:29:59.999 +0530 (IST)"))))
-
-;;; This should not dump core.
-(ert-deftest format-time-string-with-outlandish-zone ()
- (should (stringp
- (format-time-string "%Y-%m-%d %H:%M:%S.%3N %z" nil
- (concat (make-string 2048 ?X) "0")))))
+;;; Test for Bug#29609.
+(ert-deftest format-sharp-0-x ()
+ (should (string-equal (format "%#08x" #x10) "0x000010"))
+ (should (string-equal (format "%#05X" #x10) "0X010"))
+ (should (string-equal (format "%#04x" 0) "0000")))
+
+
+;;; Tests for Bug#30408.
+
+(ert-deftest format-%d-large-float ()
+ (should (string-equal (format "%d" 18446744073709551616.0)
+ "18446744073709551616"))
+ (should (string-equal (format "%d" -18446744073709551616.0)
+ "-18446744073709551616")))
+
+(ert-deftest format-%x-large-float ()
+ (should (string-equal (format "%x" 18446744073709551616.0)
+ "10000000000000000")))
+(ert-deftest read-large-integer ()
+ (should (eq (type-of (read (format "%d0" most-negative-fixnum))) 'integer))
+ (should (eq (type-of (read (format "%+d" (* -8.0 most-negative-fixnum))))
+ 'integer))
+ (should (eq (type-of (read (substring (format "%d" most-negative-fixnum) 1)))
+ 'integer))
+ (should (eq (type-of (read (format "#x%x" most-negative-fixnum)))
+ 'integer))
+ (should (eq (type-of (read (format "#o%o" most-negative-fixnum)))
+ 'integer))
+ (should (eq (type-of (read (format "#32rG%x" most-positive-fixnum)))
+ 'integer))
+ (dolist (fmt '("%d" "%s" "#o%o" "#x%x"))
+ (dolist (val (list most-negative-fixnum (1+ most-negative-fixnum)
+ -1 0 1
+ (1- most-positive-fixnum) most-positive-fixnum))
+ (should (eq val (read (format fmt val)))))
+ (dolist (val (list (1+ most-positive-fixnum)
+ (* 2 (1+ most-positive-fixnum))
+ (* 4 (1+ most-positive-fixnum))
+ (* 8 (1+ most-positive-fixnum))
+ 18446744073709551616.0))
+ (should (= val (read (format fmt val)))))))
+
+(ert-deftest format-%o-negative-float ()
+ (should (string-equal (format "%o" -1e-37) "0")))
+
+;; Bug#31938
+(ert-deftest format-%d-float ()
+ (should (string-equal (format "%d" -1.1) "-1"))
+ (should (string-equal (format "%d" -0.9) "0"))
+ (should (string-equal (format "%d" -0.0) "0"))
+ (should (string-equal (format "%d" 0.0) "0"))
+ (should (string-equal (format "%d" 0.9) "0"))
+ (should (string-equal (format "%d" 1.1) "1")))
(ert-deftest format-with-field ()
(should (equal (format "First argument %2$s, then %3$s, then %1$s" 1 2 3)
@@ -247,4 +294,136 @@
(buffer-string)
"foo bar baz qux"))))))
+(ert-deftest replace-buffer-contents-bug31837 ()
+ (switch-to-buffer "a")
+ (insert-char (char-from-name "SMILE"))
+ (insert "1234")
+ (switch-to-buffer "b")
+ (insert-char (char-from-name "SMILE"))
+ (insert "5678")
+ (replace-buffer-contents "a")
+ (should (equal (buffer-substring-no-properties (point-min) (point-max))
+ (concat (string (char-from-name "SMILE")) "1234"))))
+
+(ert-deftest delete-region-undo-markers-1 ()
+ "Make sure we don't end up with freed markers reachable from Lisp."
+ ;; https://debbugs.gnu.org/cgi/bugreport.cgi?bug=30931#40
+ (with-temp-buffer
+ (insert "1234567890")
+ (setq buffer-undo-list nil)
+ (narrow-to-region 2 5)
+ ;; `save-restriction' in a narrowed buffer creates two markers
+ ;; representing the current restriction.
+ (save-restriction
+ (widen)
+ ;; Any markers *within* the deleted region are put onto the undo
+ ;; list.
+ (delete-region 1 6))
+ ;; (princ (format "%S" buffer-undo-list) #'external-debugging-output)
+ ;; `buffer-undo-list' is now
+ ;; (("12345" . 1) (#<temp-marker1> . -1) (#<temp-marker2> . 1))
+ ;;
+ ;; If temp-marker1 or temp-marker2 are freed prematurely, calling
+ ;; `type-of' on them will cause Emacs to abort. Calling
+ ;; `garbage-collect' will also abort if it finds any reachable
+ ;; freed objects.
+ (should (eq (type-of (car (nth 1 buffer-undo-list))) 'marker))
+ (should (eq (type-of (car (nth 2 buffer-undo-list))) 'marker))
+ (garbage-collect)))
+
+(ert-deftest delete-region-undo-markers-2 ()
+ "Make sure we don't end up with freed markers reachable from Lisp."
+ ;; https://debbugs.gnu.org/cgi/bugreport.cgi?bug=30931#55
+ (with-temp-buffer
+ (insert "1234567890")
+ (setq buffer-undo-list nil)
+ ;; signal_before_change creates markers delimiting a change
+ ;; region.
+ (let ((before-change-functions
+ (list (lambda (beg end)
+ (delete-region (1- beg) (1+ end))))))
+ (delete-region 2 5))
+ ;; (princ (format "%S" buffer-undo-list) #'external-debugging-output)
+ ;; `buffer-undo-list' is now
+ ;; (("678" . 1) ("12345" . 1) (#<marker in no buffer> . -1)
+ ;; (#<temp-marker1> . -1) (#<temp-marker2> . -4))
+ ;;
+ ;; If temp-marker1 or temp-marker2 are freed prematurely, calling
+ ;; `type-of' on them will cause Emacs to abort. Calling
+ ;; `garbage-collect' will also abort if it finds any reachable
+ ;; freed objects.
+ (should (eq (type-of (car (nth 3 buffer-undo-list))) 'marker))
+ (should (eq (type-of (car (nth 4 buffer-undo-list))) 'marker))
+ (garbage-collect)))
+
+(ert-deftest format-bignum ()
+ (let* ((s1 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")
+ (v1 (read (concat "#x" s1)))
+ (s2 "99999999999999999999999999999999")
+ (v2 (read s2))
+ (v3 #x-3ffffffffffffffe000000000000000))
+ (should (> v1 most-positive-fixnum))
+ (should (equal (format "%X" v1) s1))
+ (should (> v2 most-positive-fixnum))
+ (should (equal (format "%d" v2) s2))
+ (should (equal (format "%d" v3) "-5316911983139663489309385231907684352"))
+ (should (equal (format "%+d" v3) "-5316911983139663489309385231907684352"))
+ (should (equal (format "%+d" (- v3))
+ "+5316911983139663489309385231907684352"))
+ (should (equal (format "% d" (- v3))
+ " 5316911983139663489309385231907684352"))
+ (should (equal (format "%o" v3)
+ "-37777777777777777777600000000000000000000"))
+ (should (equal (format "%#50.40x" v3)
+ " -0x000000003ffffffffffffffe000000000000000"))
+ (should (equal (format "%-#50.40x" v3)
+ "-0x000000003ffffffffffffffe000000000000000 "))))
+
+(ert-deftest test-group-name ()
+ (let ((group-name (group-name (group-gid))))
+ ;; If the GID has no associated entry in /etc/group there's no
+ ;; name for it and `group-name' should return nil!
+ (should (or (null group-name) (stringp group-name))))
+ (should-error (group-name 'foo))
+ (cond
+ ((memq system-type '(windows-nt ms-dos))
+ (should-not (group-name 123456789)))
+ ((executable-find "getent")
+ (with-temp-buffer
+ (let (stat name)
+ (dolist (gid (list 0 1212345 (group-gid)))
+ (erase-buffer)
+ (setq stat (ignore-errors
+ (call-process "getent" nil '(t nil) nil "group"
+ (number-to-string gid))))
+ (setq name (group-name gid))
+ (goto-char (point-min))
+ (cond ((eq stat 0)
+ (if (looking-at "\\([[:alnum:]_-]+\\):")
+ (should (string= (match-string 1) name))))
+ ((eq stat 2)
+ (should-not name)))))))))
+
+(ert-deftest test-translate-region-internal ()
+ (with-temp-buffer
+ (let ((max-char #16r3FFFFF)
+ (tt (make-char-table 'translation-table)))
+ (aset tt max-char ?*)
+ (insert max-char)
+ (translate-region-internal (point-min) (point-max) tt)
+ (should (string-equal (buffer-string) "*")))))
+
+(ert-deftest find-fields ()
+ (with-temp-buffer
+ (insert "foo" (propertize "bar" 'field 'bar) "zot")
+ (goto-char (point-min))
+ (should (= (field-beginning) (point-min)))
+ (should (= (field-end) 4))
+ (goto-char 5)
+ (should (= (field-beginning) 4))
+ (should (= (field-end) 7))
+ (goto-char 8)
+ (should (= (field-beginning) 7))
+ (should (= (field-end) (point-max)))))
+
;;; editfns-tests.el ends here
diff --git a/test/src/emacs-module-resources/mod-test.c b/test/src/emacs-module-resources/mod-test.c
new file mode 100644
index 00000000000..187af821c22
--- /dev/null
+++ b/test/src/emacs-module-resources/mod-test.c
@@ -0,0 +1,868 @@
+/* Test GNU Emacs modules.
+
+Copyright 2015-2022 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or (at
+your option) any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
+
+#include "config.h"
+
+#undef NDEBUG
+#include <assert.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#ifdef WINDOWSNT
+/* Cannot include <process.h> because of the local header by the same
+ name, sigh. */
+uintptr_t _beginthread (void (__cdecl *)(void *), unsigned, void *);
+# if !defined __x86_64__
+# define ALIGN_STACK __attribute__((force_align_arg_pointer))
+# endif
+# include <windows.h> /* for Sleep */
+#else /* !WINDOWSNT */
+# include <pthread.h>
+# include <unistd.h>
+#endif
+
+#include <gmp.h>
+#include <emacs-module.h>
+
+int plugin_is_GPL_compatible;
+
+#if INTPTR_MAX <= 0
+# error "INTPTR_MAX misconfigured"
+#elif INTPTR_MAX <= INT_MAX || INTPTR_MAX <= LONG_MAX
+# define pT "ld"
+# define pZ "lu"
+# define T_TYPE long
+# define Z_TYPE unsigned long
+#elif INTPTR_MAX <= INT64_MAX
+# ifdef __MINGW32__
+# define pT "lld"
+# define pZ "llu"
+# define T_TYPE long long
+# define Z_TYPE unsigned long long
+# else
+# define pT "ld"
+# define pZ "lu"
+# define T_TYPE long
+# define Z_TYPE unsigned long
+# endif
+#else
+# error "INTPTR_MAX too large"
+#endif
+
+/* Always return symbol 't'. */
+static emacs_value
+Fmod_test_return_t (emacs_env *env, ptrdiff_t nargs, emacs_value args[],
+ void *data)
+{
+ return env->intern (env, "t");
+}
+
+/* Expose simple sum function. */
+static intmax_t
+sum (intmax_t a, intmax_t b)
+{
+ return a + b;
+}
+
+static emacs_value
+Fmod_test_sum (emacs_env *env, ptrdiff_t nargs, emacs_value args[], void *data)
+{
+ assert (nargs == 2);
+ assert ((uintptr_t) data == 0x1234);
+
+ intmax_t a = env->extract_integer (env, args[0]);
+ intmax_t b = env->extract_integer (env, args[1]);
+
+ intmax_t r = sum (a, b);
+
+ return env->make_integer (env, r);
+}
+
+
+/* Signal '(error 56). */
+static emacs_value
+Fmod_test_signal (emacs_env *env, ptrdiff_t nargs, emacs_value args[],
+ void *data)
+{
+ assert (env->non_local_exit_check (env) == emacs_funcall_exit_return);
+ env->non_local_exit_signal (env, env->intern (env, "error"),
+ env->make_integer (env, 56));
+ return NULL;
+}
+
+
+/* Throw '(tag 65). */
+static emacs_value
+Fmod_test_throw (emacs_env *env, ptrdiff_t nargs, emacs_value args[],
+ void *data)
+{
+ assert (env->non_local_exit_check (env) == emacs_funcall_exit_return);
+ env->non_local_exit_throw (env, env->intern (env, "tag"),
+ env->make_integer (env, 65));
+ return NULL;
+}
+
+
+/* Call argument function, catch all non-local exists and return
+ either normal result or a list describing the non-local exit. */
+static emacs_value
+Fmod_test_non_local_exit_funcall (emacs_env *env, ptrdiff_t nargs,
+ emacs_value args[], void *data)
+{
+ assert (nargs == 1);
+ emacs_value result = env->funcall (env, args[0], 0, NULL);
+ emacs_value non_local_exit_symbol, non_local_exit_data;
+ enum emacs_funcall_exit code
+ = env->non_local_exit_get (env, &non_local_exit_symbol,
+ &non_local_exit_data);
+ switch (code)
+ {
+ case emacs_funcall_exit_return:
+ return result;
+ case emacs_funcall_exit_signal:
+ {
+ env->non_local_exit_clear (env);
+ emacs_value Flist = env->intern (env, "list");
+ emacs_value list_args[] = {env->intern (env, "signal"),
+ non_local_exit_symbol, non_local_exit_data};
+ return env->funcall (env, Flist, 3, list_args);
+ }
+ case emacs_funcall_exit_throw:
+ {
+ env->non_local_exit_clear (env);
+ emacs_value Flist = env->intern (env, "list");
+ emacs_value list_args[] = {env->intern (env, "throw"),
+ non_local_exit_symbol, non_local_exit_data};
+ return env->funcall (env, Flist, 3, list_args);
+ }
+ }
+
+ /* Never reached. */
+ return env->intern (env, "nil");;
+}
+
+
+/* Return a global reference. */
+static emacs_value
+Fmod_test_globref_make (emacs_env *env, ptrdiff_t nargs, emacs_value args[],
+ void *data)
+{
+ /* Make a big string and make it global. */
+ char str[26 * 100];
+ for (int i = 0; i < sizeof str; i++)
+ str[i] = 'a' + (i % 26);
+
+ /* We don't need to null-terminate str. */
+ emacs_value lisp_str = env->make_string (env, str, sizeof str);
+ return env->make_global_ref (env, lisp_str);
+}
+
+/* Create a few global references from arguments and free them. */
+static emacs_value
+Fmod_test_globref_free (emacs_env *env, ptrdiff_t nargs, emacs_value args[],
+ void *data)
+{
+ emacs_value refs[10];
+ for (int i = 0; i < 10; i++)
+ {
+ refs[i] = env->make_global_ref (env, args[i % nargs]);
+ }
+ for (int i = 0; i < 10; i++)
+ {
+ env->free_global_ref (env, refs[i]);
+ }
+ return env->intern (env, "ok");
+}
+
+/* Treat a local reference as global and free it. Module assertions
+ should detect this case even if a global reference representing the
+ same object also exists. */
+
+static emacs_value
+Fmod_test_globref_invalid_free (emacs_env *env, ptrdiff_t nargs,
+ emacs_value *args, void *data)
+{
+ emacs_value local = env->make_integer (env, 9876);
+ env->make_global_ref (env, local);
+ env->free_global_ref (env, local); /* Not allowed. */
+ return env->intern (env, "nil");
+}
+
+/* Allocate and free global references in a different order. */
+
+static emacs_value
+Fmod_test_globref_reordered (emacs_env *env, ptrdiff_t nargs,
+ emacs_value *args, void *data)
+{
+ emacs_value booleans[2] = {
+ env->intern (env, "nil"),
+ env->intern (env, "t"),
+ };
+ emacs_value local = env->intern (env, "foo");
+ emacs_value globals[4] = {
+ env->make_global_ref (env, local),
+ env->make_global_ref (env, local),
+ env->make_global_ref (env, env->intern (env, "foo")),
+ env->make_global_ref (env, env->intern (env, "bar")),
+ };
+ emacs_value elements[4];
+ for (int i = 0; i < 4; ++i)
+ elements[i] = booleans[env->eq (env, globals[i], local)];
+ emacs_value ret = env->funcall (env, env->intern (env, "list"), 4, elements);
+ env->free_global_ref (env, globals[2]);
+ env->free_global_ref (env, globals[1]);
+ env->free_global_ref (env, globals[3]);
+ env->free_global_ref (env, globals[0]);
+ return ret;
+}
+
+
+/* Return a copy of the argument string where every 'a' is replaced
+ with 'b'. */
+static emacs_value
+Fmod_test_string_a_to_b (emacs_env *env, ptrdiff_t nargs, emacs_value args[],
+ void *data)
+{
+ emacs_value lisp_str = args[0];
+ ptrdiff_t size = 0;
+ char * buf = NULL;
+
+ env->copy_string_contents (env, lisp_str, buf, &size);
+ buf = malloc (size);
+ env->copy_string_contents (env, lisp_str, buf, &size);
+
+ for (ptrdiff_t i = 0; i + 1 < size; i++)
+ if (buf[i] == 'a')
+ buf[i] = 'b';
+
+ emacs_value ret = env->make_string (env, buf, size - 1);
+ free (buf);
+ return ret;
+}
+
+
+/* Return a unibyte string. */
+static emacs_value
+Fmod_test_return_unibyte (emacs_env *env, ptrdiff_t nargs, emacs_value args[],
+ void *data)
+{
+ const char *string = "foo\x00zot";
+ return env->make_unibyte_string (env, string, 7);
+}
+
+
+/* Embedded pointers in lisp objects. */
+
+/* C struct (pointer to) that will be embedded. */
+struct super_struct
+{
+ int amazing_int;
+ char large_unused_buffer[512];
+};
+
+static void signal_errno (emacs_env *, char const *);
+
+/* Return a new user-pointer to a super_struct, with amazing_int set
+ to the passed parameter. */
+static emacs_value
+Fmod_test_userptr_make (emacs_env *env, ptrdiff_t nargs, emacs_value args[],
+ void *data)
+{
+ struct super_struct *p = calloc (1, sizeof *p);
+ if (!p)
+ {
+ signal_errno (env, "calloc");
+ return NULL;
+ }
+ p->amazing_int = env->extract_integer (env, args[0]);
+ return env->make_user_ptr (env, free, p);
+}
+
+/* Return the amazing_int of a passed 'user-pointer to a super_struct'. */
+static emacs_value
+Fmod_test_userptr_get (emacs_env *env, ptrdiff_t nargs, emacs_value args[],
+ void *data)
+{
+ struct super_struct *p = env->get_user_ptr (env, args[0]);
+ return env->make_integer (env, p->amazing_int);
+}
+
+
+/* Fill vector in args[0] with value in args[1]. */
+static emacs_value
+Fmod_test_vector_fill (emacs_env *env, ptrdiff_t nargs, emacs_value args[],
+ void *data)
+{
+ emacs_value vec = args[0];
+ emacs_value val = args[1];
+ ptrdiff_t size = env->vec_size (env, vec);
+ for (ptrdiff_t i = 0; i < size; i++)
+ env->vec_set (env, vec, i, val);
+ return env->intern (env, "t");
+}
+
+
+/* Return whether all elements of vector in args[0] are 'eq' to value
+ in args[1]. */
+static emacs_value
+Fmod_test_vector_eq (emacs_env *env, ptrdiff_t nargs, emacs_value args[],
+ void *data)
+{
+ emacs_value vec = args[0];
+ emacs_value val = args[1];
+ ptrdiff_t size = env->vec_size (env, vec);
+ for (ptrdiff_t i = 0; i < size; i++)
+ if (!env->eq (env, env->vec_get (env, vec, i), val))
+ return env->intern (env, "nil");
+ return env->intern (env, "t");
+}
+
+static emacs_value invalid_stored_value;
+
+/* The next two functions perform a possibly-invalid operation: they
+ store a value in a static variable and load it. This causes
+ undefined behavior if the environment that the value was created
+ from is no longer live. The module assertions check for this
+ error. */
+
+static emacs_value
+Fmod_test_invalid_store (emacs_env *env, ptrdiff_t nargs, emacs_value *args,
+ void *data)
+{
+ return invalid_stored_value = env->make_integer (env, 123);
+}
+
+static emacs_value
+Fmod_test_invalid_load (emacs_env *env, ptrdiff_t nargs, emacs_value *args,
+ void *data)
+{
+ return invalid_stored_value;
+}
+
+/* The next function works in conjunction with the two previous ones.
+ It stows away a copy of the object created by
+ `Fmod_test_invalid_store' in a global reference. Module assertions
+ should still detect the invalid load of the local reference. */
+
+static emacs_value global_copy_of_invalid_stored_value;
+
+static emacs_value
+Fmod_test_invalid_store_copy (emacs_env *env, ptrdiff_t nargs,
+ emacs_value *args, void *data)
+{
+ emacs_value local = Fmod_test_invalid_store (env, 0, NULL, NULL);
+ return global_copy_of_invalid_stored_value
+ = env->make_global_ref (env, local);
+}
+
+/* An invalid finalizer: Finalizers are run during garbage collection,
+ where Lisp code can't be executed. -module-assertions tests for
+ this case. */
+
+static emacs_env *current_env;
+
+static void
+invalid_finalizer (void *ptr)
+{
+ current_env->intern (current_env, "nil");
+}
+
+static emacs_value
+Fmod_test_invalid_finalizer (emacs_env *env, ptrdiff_t nargs, emacs_value *args,
+ void *data)
+{
+ current_env = env;
+ env->make_user_ptr (env, invalid_finalizer, NULL);
+ return env->intern (env, "nil");
+}
+
+static void
+signal_system_error (emacs_env *env, int error, const char *function)
+{
+ const char *message = strerror (error);
+ emacs_value message_value = env->make_string (env, message, strlen (message));
+ emacs_value symbol = env->intern (env, "file-error");
+ emacs_value elements[2]
+ = {env->make_string (env, function, strlen (function)), message_value};
+ emacs_value data = env->funcall (env, env->intern (env, "list"), 2, elements);
+ env->non_local_exit_signal (env, symbol, data);
+}
+
+static void
+signal_errno (emacs_env *env, const char *function)
+{
+ signal_system_error (env, errno, function);
+}
+
+#ifdef CLOCK_REALTIME
+
+/* Whether A <= B. */
+static bool
+timespec_le (struct timespec a, struct timespec b)
+{
+ return (a.tv_sec < b.tv_sec
+ || (a.tv_sec == b.tv_sec && a.tv_nsec <= b.tv_nsec));
+}
+
+/* A long-running operation that occasionally calls `should_quit' or
+ `process_input'. */
+
+static emacs_value
+Fmod_test_sleep_until (emacs_env *env, ptrdiff_t nargs, emacs_value *args,
+ void *data)
+{
+ assert (nargs == 2);
+ const struct timespec until = env->extract_time (env, args[0]);
+ if (env->non_local_exit_check (env))
+ return NULL;
+ const bool process_input = env->is_not_nil (env, args[1]);
+ const struct timespec amount = { .tv_nsec = 10000000 };
+ while (true)
+ {
+ struct timespec now;
+ if (clock_gettime (CLOCK_REALTIME, &now) != 0)
+ return NULL;
+ if (timespec_le (until, now))
+ break;
+ if (nanosleep (&amount, NULL) && errno != EINTR)
+ {
+ signal_errno (env, "nanosleep");
+ return NULL;
+ }
+ if ((process_input
+ && env->process_input (env) == emacs_process_input_quit)
+ || env->should_quit (env))
+ return NULL;
+ }
+ return env->intern (env, "finished");
+}
+#endif
+
+static emacs_value
+Fmod_test_add_nanosecond (emacs_env *env, ptrdiff_t nargs, emacs_value *args,
+ void *data)
+{
+ assert (nargs == 1);
+ struct timespec time = env->extract_time (env, args[0]);
+ assert (time.tv_nsec >= 0);
+ assert (time.tv_nsec < 2000000000); /* possible leap second */
+ time.tv_nsec++;
+ return env->make_time (env, time);
+}
+
+static void
+signal_error (emacs_env *env, const char *message)
+{
+ emacs_value data = env->make_string (env, message, strlen (message));
+ env->non_local_exit_signal (env, env->intern (env, "error"),
+ env->funcall (env, env->intern (env, "list"), 1,
+ &data));
+}
+
+static void
+memory_full (emacs_env *env)
+{
+ signal_error (env, "Memory exhausted");
+}
+
+enum
+{
+ max_count = ((SIZE_MAX < PTRDIFF_MAX ? SIZE_MAX : PTRDIFF_MAX)
+ / sizeof (emacs_limb_t))
+};
+
+static bool
+extract_big_integer (emacs_env *env, emacs_value arg, mpz_t result)
+{
+ int sign;
+ ptrdiff_t count;
+ bool success = env->extract_big_integer (env, arg, &sign, &count, NULL);
+ if (!success)
+ return false;
+ if (sign == 0)
+ {
+ mpz_set_ui (result, 0);
+ return true;
+ }
+ enum { order = -1, size = sizeof (emacs_limb_t), endian = 0, nails = 0 };
+ assert (0 < count && count <= max_count);
+ emacs_limb_t *magnitude = malloc (count * size);
+ if (magnitude == NULL)
+ {
+ memory_full (env);
+ return false;
+ }
+ success = env->extract_big_integer (env, arg, NULL, &count, magnitude);
+ assert (success);
+ mpz_import (result, count, order, size, endian, nails, magnitude);
+ free (magnitude);
+ if (sign < 0)
+ mpz_neg (result, result);
+ return true;
+}
+
+static emacs_value
+make_big_integer (emacs_env *env, const mpz_t value)
+{
+ if (mpz_sgn (value) == 0)
+ return env->make_integer (env, 0);
+ /* See
+ https://gmplib.org/manual/Integer-Import-and-Export.html#index-Export. */
+ enum
+ {
+ order = -1,
+ size = sizeof (emacs_limb_t),
+ endian = 0,
+ nails = 0,
+ numb = 8 * size - nails
+ };
+ size_t count = (mpz_sizeinbase (value, 2) + numb - 1) / numb;
+ if (max_count < count)
+ {
+ memory_full (env);
+ return NULL;
+ }
+ emacs_limb_t *magnitude = malloc (count * size);
+ if (magnitude == NULL)
+ {
+ memory_full (env);
+ return NULL;
+ }
+ size_t written;
+ mpz_export (magnitude, &written, order, size, endian, nails, value);
+ assert (written == count);
+ assert (count <= PTRDIFF_MAX);
+ emacs_value result = env->make_big_integer (env, mpz_sgn (value),
+ (ptrdiff_t) count, magnitude);
+ free (magnitude);
+ return result;
+}
+
+#ifdef CLOCK_REALTIME
+static emacs_value
+Fmod_test_nanoseconds (emacs_env *env, ptrdiff_t nargs, emacs_value *args, void *data) {
+ assert (nargs == 1);
+ struct timespec time = env->extract_time (env, args[0]);
+ mpz_t nanoseconds;
+ assert (LONG_MIN <= time.tv_sec && time.tv_sec <= LONG_MAX);
+ mpz_init_set_si (nanoseconds, time.tv_sec);
+ mpz_mul_ui (nanoseconds, nanoseconds, 1000000000);
+ assert (0 <= time.tv_nsec && time.tv_nsec <= ULONG_MAX);
+ mpz_add_ui (nanoseconds, nanoseconds, time.tv_nsec);
+ emacs_value result = make_big_integer (env, nanoseconds);
+ mpz_clear (nanoseconds);
+ return result;
+}
+#endif
+
+static emacs_value
+Fmod_test_double (emacs_env *env, ptrdiff_t nargs, emacs_value *args,
+ void *data)
+{
+ assert (nargs == 1);
+ emacs_value arg = args[0];
+ mpz_t value;
+ mpz_init (value);
+ extract_big_integer (env, arg, value);
+ mpz_mul_ui (value, value, 2);
+ emacs_value result = make_big_integer (env, value);
+ mpz_clear (value);
+ return result;
+}
+
+static int function_data;
+static int finalizer_calls_with_correct_data;
+static int finalizer_calls_with_incorrect_data;
+
+static void
+finalizer (void *data)
+{
+ if (data == &function_data)
+ ++finalizer_calls_with_correct_data;
+ else
+ ++finalizer_calls_with_incorrect_data;
+}
+
+static emacs_value
+Fmod_test_make_function_with_finalizer (emacs_env *env, ptrdiff_t nargs,
+ emacs_value *args, void *data)
+{
+ emacs_value fun
+ = env->make_function (env, 2, 2, Fmod_test_sum, NULL, &function_data);
+ env->set_function_finalizer (env, fun, finalizer);
+ if (env->get_function_finalizer (env, fun) != finalizer)
+ signal_error (env, "Invalid finalizer");
+ return fun;
+}
+
+static emacs_value
+Fmod_test_function_finalizer_calls (emacs_env *env, ptrdiff_t nargs,
+ emacs_value *args, void *data)
+{
+ emacs_value Flist = env->intern (env, "list");
+ emacs_value list_args[]
+ = {env->make_integer (env, finalizer_calls_with_correct_data),
+ env->make_integer (env, finalizer_calls_with_incorrect_data)};
+ return env->funcall (env, Flist, 2, list_args);
+}
+
+static void
+sleep_for_half_second (void)
+{
+ /* mingw.org's MinGW has nanosleep, but MinGW64 doesn't. */
+#ifdef WINDOWSNT
+ Sleep (500);
+#else
+ const struct timespec sleep = { .tv_nsec = 500000000 };
+ if (nanosleep (&sleep, NULL) != 0)
+ perror ("nanosleep");
+#endif
+}
+
+#ifdef WINDOWSNT
+static void ALIGN_STACK
+#else
+static void *
+#endif
+write_to_pipe (void *arg)
+{
+ /* We sleep a bit to test that writing to a pipe is indeed possible
+ if no environment is active. */
+ sleep_for_half_second ();
+ FILE *stream = arg;
+ /* The string below should be identical to the one we compare with
+ in emacs-module-tests.el:module/async-pipe. */
+ if (fputs ("data from thread", stream) < 0)
+ perror ("fputs");
+ if (fclose (stream) != 0)
+ perror ("close");
+#ifndef WINDOWSNT
+ return NULL;
+#endif
+}
+
+static emacs_value
+Fmod_test_async_pipe (emacs_env *env, ptrdiff_t nargs, emacs_value *args,
+ void *data)
+{
+ assert (nargs == 1);
+ int fd = env->open_channel (env, args[0]);
+ if (env->non_local_exit_check (env) != emacs_funcall_exit_return)
+ return NULL;
+ FILE *stream = fdopen (fd, "w");
+ if (stream == NULL)
+ {
+ signal_errno (env, "fdopen");
+ return NULL;
+ }
+#ifdef WINDOWSNT
+ uintptr_t thd = _beginthread (write_to_pipe, 0, stream);
+ int error = (thd == (uintptr_t)-1L) ? errno : 0;
+#else /* !WINDOWSNT */
+ pthread_t thread;
+ int error
+ = pthread_create (&thread, NULL, write_to_pipe, stream);
+#endif
+ if (error != 0)
+ {
+ signal_system_error (env, error, "thread create");
+ if (fclose (stream) != 0)
+ perror ("fclose");
+ return NULL;
+ }
+ return env->intern (env, "nil");
+}
+
+static emacs_value
+Fmod_test_identity (emacs_env *env, ptrdiff_t nargs, emacs_value *args,
+ void *data)
+{
+ assert (nargs == 1);
+ return args[0];
+}
+
+static emacs_value
+Fmod_test_funcall (emacs_env *env, ptrdiff_t nargs, emacs_value *args,
+ void *data)
+{
+ assert (0 < nargs);
+ return env->funcall (env, args[0], nargs - 1, args + 1);
+}
+
+static emacs_value
+Fmod_test_make_string (emacs_env *env, ptrdiff_t nargs,
+ emacs_value *args, void *data)
+{
+ assert (nargs == 2);
+ intmax_t length_arg = env->extract_integer (env, args[0]);
+ if (env->non_local_exit_check (env) != emacs_funcall_exit_return)
+ return args[0];
+ if (length_arg < 0 || SIZE_MAX < length_arg)
+ {
+ signal_error (env, "Invalid string length");
+ return args[0];
+ }
+ size_t length = (size_t) length_arg;
+ bool multibyte = env->is_not_nil (env, args[1]);
+ char *buffer = length == 0 ? NULL : malloc (length);
+ if (buffer == NULL && length != 0)
+ {
+ memory_full (env);
+ return args[0];
+ }
+ memset (buffer, 'a', length);
+ emacs_value ret = multibyte ? env->make_string (env, buffer, length)
+ : env->make_unibyte_string (env, buffer, length);
+ free (buffer);
+ return ret;
+}
+
+/* Lisp utilities for easier readability (simple wrappers). */
+
+/* Provide FEATURE to Emacs. */
+static void
+provide (emacs_env *env, const char *feature)
+{
+ emacs_value Qfeat = env->intern (env, feature);
+ emacs_value Qprovide = env->intern (env, "provide");
+ emacs_value args[] = { Qfeat };
+
+ env->funcall (env, Qprovide, 1, args);
+}
+
+/* Bind NAME to FUN. */
+static void
+bind_function (emacs_env *env, const char *name, emacs_value Sfun)
+{
+ emacs_value Qdefalias = env->intern (env, "defalias");
+ emacs_value Qsym = env->intern (env, name);
+ emacs_value args[] = { Qsym, Sfun };
+
+ env->funcall (env, Qdefalias, 2, args);
+}
+
+/* Module init function. */
+int
+emacs_module_init (struct emacs_runtime *ert)
+{
+ /* These smoke tests don't use _Static_assert because too many
+ compilers lack support for _Static_assert. */
+ assert (0 < EMACS_LIMB_MAX);
+ assert (1000000000 <= ULONG_MAX);
+
+ /* Check that EMACS_MAJOR_VERSION is defined and an integral
+ constant. */
+ char dummy[EMACS_MAJOR_VERSION];
+ assert (27 <= sizeof dummy);
+
+ if (ert->size < sizeof *ert)
+ {
+ fprintf (stderr, "Runtime size of runtime structure (%"pT" bytes) "
+ "smaller than compile-time size (%"pZ" bytes)",
+ (T_TYPE) ert->size, (Z_TYPE) sizeof (*ert));
+ return 1;
+ }
+
+ emacs_env *env = ert->get_environment (ert);
+
+ if (env->size < sizeof *env)
+ {
+ fprintf (stderr, "Runtime size of environment structure (%"pT" bytes) "
+ "smaller than compile-time size (%"pZ" bytes)",
+ (T_TYPE) env->size, (Z_TYPE) sizeof (*env));
+ return 2;
+ }
+
+#define DEFUN(lsym, csym, amin, amax, doc, data) \
+ bind_function (env, lsym, \
+ env->make_function (env, amin, amax, csym, doc, data))
+
+ DEFUN ("mod-test-return-t", Fmod_test_return_t, 1, 1, NULL, NULL);
+ DEFUN ("mod-test-sum", Fmod_test_sum, 2, 2, "Return A + B\n\n(fn a b)",
+ (void *) (uintptr_t) 0x1234);
+ DEFUN ("mod-test-signal", Fmod_test_signal, 0, 0, NULL, NULL);
+ DEFUN ("mod-test-throw", Fmod_test_throw, 0, 0, NULL, NULL);
+ DEFUN ("mod-test-non-local-exit-funcall", Fmod_test_non_local_exit_funcall,
+ 1, 1, NULL, NULL);
+ DEFUN ("mod-test-globref-make", Fmod_test_globref_make, 0, 0, NULL, NULL);
+ DEFUN ("mod-test-globref-free", Fmod_test_globref_free, 4, 4, NULL, NULL);
+ DEFUN ("mod-test-globref-invalid-free", Fmod_test_globref_invalid_free, 0, 0,
+ NULL, NULL);
+ DEFUN ("mod-test-globref-reordered", Fmod_test_globref_reordered, 0, 0, NULL,
+ NULL);
+ DEFUN ("mod-test-string-a-to-b", Fmod_test_string_a_to_b, 1, 1, NULL, NULL);
+ DEFUN ("mod-test-return-unibyte", Fmod_test_return_unibyte, 0, 0, NULL, NULL);
+ DEFUN ("mod-test-userptr-make", Fmod_test_userptr_make, 1, 1, NULL, NULL);
+ DEFUN ("mod-test-userptr-get", Fmod_test_userptr_get, 1, 1, NULL, NULL);
+ DEFUN ("mod-test-vector-fill", Fmod_test_vector_fill, 2, 2, NULL, NULL);
+ DEFUN ("mod-test-vector-eq", Fmod_test_vector_eq, 2, 2, NULL, NULL);
+ DEFUN ("mod-test-invalid-store", Fmod_test_invalid_store, 0, 0, NULL, NULL);
+ DEFUN ("mod-test-invalid-store-copy", Fmod_test_invalid_store_copy, 0, 0,
+ NULL, NULL);
+ DEFUN ("mod-test-invalid-load", Fmod_test_invalid_load, 0, 0, NULL, NULL);
+ DEFUN ("mod-test-invalid-finalizer", Fmod_test_invalid_finalizer, 0, 0,
+ NULL, NULL);
+#ifdef CLOCK_REALTIME
+ DEFUN ("mod-test-sleep-until", Fmod_test_sleep_until, 2, 2, NULL, NULL);
+#endif
+ DEFUN ("mod-test-add-nanosecond", Fmod_test_add_nanosecond, 1, 1, NULL, NULL);
+#ifdef CLOCK_REALTIME
+ DEFUN ("mod-test-nanoseconds", Fmod_test_nanoseconds, 1, 1, NULL, NULL);
+#endif
+ DEFUN ("mod-test-double", Fmod_test_double, 1, 1, NULL, NULL);
+ DEFUN ("mod-test-make-function-with-finalizer",
+ Fmod_test_make_function_with_finalizer, 0, 0, NULL, NULL);
+ DEFUN ("mod-test-function-finalizer-calls",
+ Fmod_test_function_finalizer_calls, 0, 0, NULL, NULL);
+ DEFUN ("mod-test-async-pipe", Fmod_test_async_pipe, 1, 1, NULL, NULL);
+ DEFUN ("mod-test-funcall", Fmod_test_funcall, 1, emacs_variadic_function,
+ NULL, NULL);
+ DEFUN ("mod-test-make-string", Fmod_test_make_string, 2, 2, NULL, NULL);
+
+#undef DEFUN
+
+ emacs_value constant_fn
+ = env->make_function (env, 0, 0, Fmod_test_return_t, NULL, NULL);
+ env->make_interactive (env, constant_fn, env->intern (env, "nil"));
+ bind_function (env, "mod-test-return-t-int", constant_fn);
+
+ emacs_value identity_fn
+ = env->make_function (env, 1, 1, Fmod_test_identity, NULL, NULL);
+ const char *interactive_spec = "i";
+ env->make_interactive (env, identity_fn,
+ env->make_string (env, interactive_spec,
+ strlen (interactive_spec)));
+ bind_function (env, "mod-test-identity", identity_fn);
+
+ /* We allocate lots of values to trigger bugs in the frame allocator during
+ initialization. */
+ int count = 10000; /* larger than value_frame_size in emacs-module.c */
+ for (int i = 0; i < count; ++i)
+ env->make_integer (env, i);
+
+ provide (env, "mod-test");
+ return 0;
+}
diff --git a/test/src/emacs-module-tests.el b/test/src/emacs-module-tests.el
index 4b41fc21c20..1099fd04678 100644
--- a/test/src/emacs-module-tests.el
+++ b/test/src/emacs-module-tests.el
@@ -1,6 +1,6 @@
-;;; Test GNU Emacs modules.
+;;; emacs-module-tests.el --- Test GNU Emacs modules. -*- lexical-binding: t; -*-
-;; Copyright 2015-2017 Free Software Foundation, Inc.
+;; Copyright 2015-2022 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -17,7 +17,25 @@
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
+;;; Commentary:
+
+;; Unit tests for the dynamic module facility. See Info node `(elisp)
+;; Writing Dynamic Modules'. These tests make use of a small test
+;; module in the "emacs-module-resources" directory.
+
+;;; Code:
+;;; Prelude
+
+(require 'cl-lib)
(require 'ert)
+(require 'ert-x)
+(require 'help-fns)
+(require 'subr-x)
+
+;; Catch information for bug#50902.
+(when (getenv "EMACS_EMBA_CI")
+ (start-process-shell-command
+ "*timeout*" nil (format "sleep 60; kill -ABRT %d" (emacs-pid))))
(defconst mod-test-emacs
(expand-file-name invocation-name invocation-directory)
@@ -25,15 +43,21 @@
(eval-and-compile
(defconst mod-test-file
- (substitute-in-file-name
- "$EMACS_TEST_DIRECTORY/data/emacs-module/mod-test")
+ (expand-file-name "../test/src/emacs-module-resources/mod-test"
+ invocation-directory)
"File name of the module test file."))
(require 'mod-test mod-test-file)
-;;
-;; Basic tests.
-;;
+(cl-defgeneric emacs-module-tests--generic (_))
+
+(cl-defmethod emacs-module-tests--generic ((_ module-function))
+ 'module-function)
+
+(cl-defmethod emacs-module-tests--generic ((_ user-ptr))
+ 'user-ptr)
+
+;;; Basic tests
(ert-deftest mod-test-sum-test ()
(should (= (mod-test-sum 1 2) 3))
@@ -43,8 +67,9 @@
(should (eq 0
(string-match
(concat "#<module function "
- "\\(at \\(0x\\)?[0-9a-fA-F]+\\( from .*\\)?"
- "\\|Fmod_test_sum from .*\\)>")
+ "\\(at \\(0x\\)?[[:xdigit:]]+ "
+ "with data 0x1234\\( from .*\\)?"
+ "\\|Fmod_test_sum with data 0x1234 from .*\\)>")
(prin1-to-string (nth 1 descr)))))
(should (= (nth 2 descr) 3)))
(should-error (mod-test-sum "1" 2) :type 'wrong-type-argument)
@@ -57,12 +82,12 @@
(when (< #x1fffffff most-positive-fixnum)
(should (= (mod-test-sum 1 #x1fffffff)
(1+ #x1fffffff)))
- (should (= (mod-test-sum -1 #x20000000)
+ (should (= (mod-test-sum -1 (1+ #x1fffffff))
#x1fffffff)))
- (should-error (mod-test-sum 1 most-positive-fixnum)
- :type 'overflow-error)
- (should-error (mod-test-sum -1 most-negative-fixnum)
- :type 'overflow-error))
+ (should (= (mod-test-sum 1 most-positive-fixnum)
+ (1+ most-positive-fixnum)))
+ (should (= (mod-test-sum -1 most-negative-fixnum)
+ (1- most-negative-fixnum))))
(ert-deftest mod-test-sum-docstring ()
(should (string= (documentation 'mod-test-sum) "Return A + B\n\n(fn a b)")))
@@ -73,18 +98,19 @@ This test needs to be changed whenever the implementation
changes."
(let ((func (symbol-function #'mod-test-sum)))
(should (module-function-p func))
+ (should (functionp func))
(should (equal (type-of func) 'module-function))
+ (should (eq (emacs-module-tests--generic func) 'module-function))
(should (string-match-p
(rx bos "#<module function "
(or "Fmod_test_sum"
(and "at 0x" (+ hex-digit)))
+ " with data 0x1234"
(? " from " (* nonl) "mod-test" (* nonl) )
">" eos)
(prin1-to-string func)))))
-;;
-;; Non-local exists (throw, signal).
-;;
+;;; Non-local exists (throw, signal)
(ert-deftest mod-test-non-local-exit-signal-test ()
(should-error (mod-test-signal))
@@ -121,14 +147,14 @@ changes."
(should (equal (mod-test-non-local-exit-funcall (lambda () (throw 'tag 32)))
'(throw tag 32))))
-;;
-;; String tests.
-;;
+;;; String tests
(defun multiply-string (s n)
+ "Return N copies of S concatenated together."
(let ((res ""))
- (dotimes (i n res)
- (setq res (concat res s)))))
+ (dotimes (_ n)
+ (setq res (concat res s)))
+ res))
(ert-deftest mod-test-globref-make-test ()
(let ((mod-str (mod-test-globref-make))
@@ -136,12 +162,16 @@ changes."
(garbage-collect) ;; XXX: not enough to really test but it's something..
(should (string= ref-str mod-str))))
+(ert-deftest mod-test-globref-free-test ()
+ (should (eq (mod-test-globref-free 1 'a "test" 'b) 'ok)))
+
+(ert-deftest mod-test-globref-reordered ()
+ (should (equal (mod-test-globref-reordered) '(t t t nil))))
+
(ert-deftest mod-test-string-a-to-b-test ()
(should (string= (mod-test-string-a-to-b "aaa") "bbb")))
-;;
-;; User-pointer tests.
-;;
+;;; User-pointer tests
(ert-deftest mod-test-userptr-fun-test ()
(let* ((n 42)
@@ -149,14 +179,13 @@ changes."
(r (mod-test-userptr-get v)))
(should (eq (type-of v) 'user-ptr))
+ (should (eq (emacs-module-tests--generic v) 'user-ptr))
(should (integerp r))
(should (= r n))))
;; TODO: try to test finalizer
-;;
-;; Vector tests.
-;;
+;;; Vector tests
(ert-deftest mod-test-vector-test ()
(dolist (s '(2 10 100 1000))
@@ -182,20 +211,6 @@ changes."
(should (equal (help-function-arglist #'mod-test-sum)
'(arg1 arg2))))
-(defmacro module--with-temp-directory (name &rest body)
- "Bind NAME to the name of a temporary directory and evaluate BODY.
-NAME must be a symbol. Delete the temporary directory after BODY
-exits normally or non-locally. NAME will be bound to the
-directory name (not the directory file name) of the temporary
-directory."
- (declare (indent 1))
- (cl-check-type name symbol)
- `(let ((,name (file-name-as-directory
- (make-temp-file "emacs-module-test" :directory))))
- (unwind-protect
- (progn ,@body)
- (delete-directory ,name :recursive))))
-
(defmacro module--test-assertion (pattern &rest body)
"Test that PATTERN matches the assertion triggered by BODY.
Run Emacs as a subprocess, load the test module `mod-test-file',
@@ -204,7 +219,7 @@ assertion message that matches PATTERN. PATTERN is evaluated and
must evaluate to a regular expression string."
(declare (indent 1))
;; To contain any core dumps.
- `(module--with-temp-directory tempdir
+ `(ert-with-temp-directory tempdir
(with-temp-buffer
(let* ((default-directory tempdir)
(status (call-process mod-test-emacs nil t nil
@@ -231,10 +246,12 @@ must evaluate to a regular expression string."
(point) (point-max))))))))
(ert-deftest module--test-assertions--load-non-live-object ()
- "Check that -module-assertions verify that non-live objects
-aren’t accessed."
- (skip-unless (file-executable-p mod-test-emacs))
- ;; This doesn’t yet cause undefined behavior.
+ "Check that -module-assertions verify that non-live objects aren't accessed."
+ :tags (if (getenv "EMACS_EMBA_CI") '(:unstable))
+ (skip-unless (or (file-executable-p mod-test-emacs)
+ (and (eq system-type 'windows-nt)
+ (file-executable-p (concat mod-test-emacs ".exe")))))
+ ;; This doesn't yet cause undefined behavior.
(should (eq (mod-test-invalid-store) 123))
(module--test-assertion (rx "Emacs value not found in "
(+ digit) " values of "
@@ -244,12 +261,322 @@ aren’t accessed."
(mod-test-invalid-store)
(mod-test-invalid-load)))
+(ert-deftest module--test-assertions--load-non-live-object-with-global-copy ()
+ "Check that -module-assertions verify that non-live objects aren't accessed.
+This differs from `module--test-assertions-load-non-live-object'
+in that it stows away a global reference. The module assertions
+should nevertheless detect the invalid load."
+ :tags (if (getenv "EMACS_EMBA_CI") '(:unstable))
+ (skip-unless (or (file-executable-p mod-test-emacs)
+ (and (eq system-type 'windows-nt)
+ (file-executable-p (concat mod-test-emacs ".exe")))))
+ ;; This doesn't yet cause undefined behavior.
+ (should (eq (mod-test-invalid-store-copy) 123))
+ (module--test-assertion (rx "Emacs value not found in "
+ (+ digit) " values of "
+ (+ digit) " environments\n")
+ ;; Storing and reloading a local value causes undefined behavior,
+ ;; which should be detected by the module assertions.
+ (mod-test-invalid-store-copy)
+ (mod-test-invalid-load)))
+
(ert-deftest module--test-assertions--call-emacs-from-gc ()
"Check that -module-assertions prevents calling Emacs functions
during garbage collection."
- (skip-unless (file-executable-p mod-test-emacs))
+ :tags (if (getenv "EMACS_EMBA_CI") '(:unstable))
+ (skip-unless (or (file-executable-p mod-test-emacs)
+ (and (eq system-type 'windows-nt)
+ (file-executable-p (concat mod-test-emacs ".exe")))))
(module--test-assertion
(rx "Module function called during garbage collection\n")
- (mod-test-invalid-finalizer)))
+ (mod-test-invalid-finalizer)
+ (garbage-collect)))
+
+(ert-deftest module--test-assertions--globref-invalid-free ()
+ "Check that -module-assertions detects invalid freeing of a
+local reference."
+ :tags (if (getenv "EMACS_EMBA_CI") '(:unstable))
+ (skip-unless (or (file-executable-p mod-test-emacs)
+ (and (eq system-type 'windows-nt)
+ (file-executable-p (concat mod-test-emacs ".exe")))))
+ (module--test-assertion
+ (rx "Global value was not found in list of " (+ digit) " globals")
+ (mod-test-globref-invalid-free)
+ (garbage-collect)))
+
+(ert-deftest module/describe-function-1 ()
+ "Check that Bug#30163 is fixed."
+ (with-temp-buffer
+ (let ((standard-output (current-buffer))
+ (text-quoting-style 'grave)
+ (fill-column 200)) ; prevent line breaks when filling
+ (describe-function-1 #'mod-test-sum)
+ (goto-char (point-min))
+ (while (re-search-forward "`[^']*/src/emacs-module-resources/" nil t)
+ (replace-match "`src/emacs-module-resources/"))
+ (should (equal
+ (buffer-substring-no-properties 1 (point-max))
+ (format "a module function in `src/emacs-module-resources/mod-test%s'.
+
+(mod-test-sum a b)
+
+Return A + B
+
+"
+ module-file-suffix))))))
+
+(ert-deftest module/load-history ()
+ "Check that Bug#30164 is fixed."
+ (load mod-test-file)
+ (cl-destructuring-bind (file &rest entries) (car load-history)
+ (should (equal (file-name-sans-extension file) mod-test-file))
+ (should (member '(provide . mod-test) entries))
+ (should (member '(defun . mod-test-sum) entries))))
+
+(ert-deftest mod-test-sleep-until ()
+ "Check that `mod-test-sleep-until' either returns normally or quits.
+Interactively, you can try hitting \\[keyboard-quit] to quit."
+ (skip-unless (fboundp 'mod-test-sleep-until))
+ (dolist (arg '(nil t))
+ ;; Guard against some caller setting `inhibit-quit'.
+ (with-local-quit
+ (condition-case nil
+ (should (eq (with-local-quit
+ ;; Because `inhibit-quit' is nil here, the next
+ ;; form either quits or returns `finished'.
+ (mod-test-sleep-until
+ ;; Interactively, run for 5 seconds to give the
+ ;; user time to quit. In batch mode, run only
+ ;; briefly since the user can't quit.
+ (time-add nil (if noninteractive 0.1 5))
+ ;; should_quit or process_input
+ arg))
+ 'finished))
+ (quit)))))
+
+(ert-deftest mod-test-add-nanosecond/valid ()
+ (dolist (input (list
+ ;; Some realistic examples.
+ (current-time) (time-to-seconds)
+ (encode-time 12 34 5 6 7 2019 t)
+ ;; Various legacy timestamp forms.
+ '(123 456) '(123 456 789) '(123 456 789 6000)
+ ;; Corner case: this will result in a nanosecond
+ ;; value of 1000000000 after addition. The module
+ ;; code should handle this correctly.
+ '(123 65535 999999 999000)
+ ;; Seconds since the epoch.
+ 123 123.45
+ ;; New (TICKS . HZ) format.
+ '(123456789 . 1000000000)))
+ (ert-info ((format "input: %s" input))
+ (let ((result (mod-test-add-nanosecond input))
+ (desired-result
+ (let ((hz 1000000000))
+ (time-add (time-convert input hz) (cons 1 hz)))))
+ (should (consp result))
+ (should (integerp (car result)))
+ (should (integerp (cdr result)))
+ (should (cl-plusp (cdr result)))
+ (should (time-equal-p result desired-result))))))
+
+(ert-deftest mod-test-add-nanosecond/nil ()
+ (should (<= (float-time (mod-test-add-nanosecond nil))
+ (+ (float-time) 1e-9))))
+
+(ert-deftest mod-test-add-nanosecond/invalid ()
+ (dolist (input '(1.0e+INF 1.0e-INF 0.0e+NaN (123) (123.45 6 7) "foo" [1 2]))
+ (ert-info ((format "input: %s" input))
+ (should-error (mod-test-add-nanosecond input)))))
+
+(ert-deftest mod-test-nanoseconds ()
+ "Test truncation when converting to `struct timespec'."
+ (skip-unless (fboundp 'mod-test-nanoseconds))
+ (dolist (test-case '((0 . 0)
+ (-1 . -1000000000)
+ ((1 . 1000000000) . 1)
+ ((-1 . 1000000000) . -1)
+ ((1 . 1000000000000) . 0)
+ ((-1 . 1000000000000) . -1)
+ ((999 . 1000000000000) . 0)
+ ((-999 . 1000000000000) . -1)
+ ((1000 . 1000000000000) . 1)
+ ((-1000 . 1000000000000) . -1)
+ ((0 0 0 1) . 0)
+ ((0 0 0 -1) . -1)))
+ (let ((input (car test-case))
+ (expected (cdr test-case)))
+ (ert-info ((format "input: %S, expected result: %d" input expected))
+ (should (= (mod-test-nanoseconds input) expected))))))
+
+(ert-deftest mod-test-double ()
+ (skip-unless (fboundp 'mod-test-double))
+ (dolist (input (list 0 1 2 -1 42 12345678901234567890
+ most-positive-fixnum (1+ most-positive-fixnum)
+ most-negative-fixnum (1- most-negative-fixnum)))
+ (ert-info ((format "input: %d" input))
+ (should (= (mod-test-double input) (* 2 input))))))
+
+(ert-deftest module-darwin-secondary-suffix ()
+ "Check that on Darwin, both .so and .dylib suffixes work.
+See Bug#36226."
+ (skip-unless (eq system-type 'darwin))
+ (should (member ".dylib" load-suffixes))
+ (should (member ".so" load-suffixes))
+ ;; Preserve the old `load-history'. This is needed for some of the
+ ;; other unit tests that indirectly rely on `load-history'.
+ (let ((load-history load-history)
+ (dylib (concat mod-test-file ".dylib"))
+ (so (concat mod-test-file ".so")))
+ (should (file-regular-p dylib))
+ (should-not (file-exists-p so))
+ (add-name-to-file dylib so)
+ (unwind-protect
+ (load so nil nil :nosuffix :must-suffix)
+ (delete-file so))))
+
+(ert-deftest module/function-finalizer ()
+ "Test that module function finalizers are properly called."
+ ;; We create and leak a couple of module functions with attached
+ ;; finalizer. Creating only one function risks spilling it to the
+ ;; stack, where it wouldn't be garbage-collected. However, with one
+ ;; hundred functions, there should be at least one that's
+ ;; unreachable.
+ (dotimes (_ 100)
+ (mod-test-make-function-with-finalizer))
+ (cl-destructuring-bind (valid-before invalid-before)
+ (mod-test-function-finalizer-calls)
+ (should (zerop invalid-before))
+ (garbage-collect)
+ (cl-destructuring-bind (valid-after invalid-after)
+ (mod-test-function-finalizer-calls)
+ (should (zerop invalid-after))
+ ;; We don't require exactly 100 invocations of the finalizer,
+ ;; but at least one.
+ (should (> valid-after valid-before)))))
+
+(ert-deftest module/async-pipe ()
+ "Check that writing data from another thread works."
+ (skip-unless (not (eq system-type 'windows-nt))) ; FIXME!
+ (with-temp-buffer
+ (let ((process (make-pipe-process :name "module/async-pipe"
+ :buffer (current-buffer)
+ :coding 'utf-8-unix
+ :noquery t)))
+ (unwind-protect
+ (progn
+ (mod-test-async-pipe process)
+ (should (accept-process-output process 1))
+ ;; The string below must be identical to what
+ ;; mod-test.c:write_to_pipe produces.
+ (should (equal (buffer-string) "data from thread")))
+ (delete-process process)))))
+
+(ert-deftest module/interactive/return-t ()
+ (should (functionp (symbol-function #'mod-test-return-t)))
+ (should (module-function-p (symbol-function #'mod-test-return-t)))
+ (should-not (commandp #'mod-test-return-t))
+ (should-not (commandp (symbol-function #'mod-test-return-t)))
+ (should-not (interactive-form #'mod-test-return-t))
+ (should-not (interactive-form (symbol-function #'mod-test-return-t)))
+ (should-error (call-interactively #'mod-test-return-t)
+ :type 'wrong-type-argument))
+
+(ert-deftest module/interactive/return-t-int ()
+ (should (functionp (symbol-function #'mod-test-return-t-int)))
+ (should (module-function-p (symbol-function #'mod-test-return-t-int)))
+ (should (commandp #'mod-test-return-t-int))
+ (should (commandp (symbol-function #'mod-test-return-t-int)))
+ (should (equal (interactive-form #'mod-test-return-t-int) '(interactive)))
+ (should (equal (interactive-form (symbol-function #'mod-test-return-t-int))
+ '(interactive)))
+ (should (eq (mod-test-return-t-int) t))
+ (should (eq (call-interactively #'mod-test-return-t-int) t)))
+
+(ert-deftest module/interactive/identity ()
+ (should (functionp (symbol-function #'mod-test-identity)))
+ (should (module-function-p (symbol-function #'mod-test-identity)))
+ (should (commandp #'mod-test-identity))
+ (should (commandp (symbol-function #'mod-test-identity)))
+ (should (equal (interactive-form #'mod-test-identity) '(interactive "i")))
+ (should (equal (interactive-form (symbol-function #'mod-test-identity))
+ '(interactive "i")))
+ (should (eq (mod-test-identity 123) 123))
+ (should-not (call-interactively #'mod-test-identity)))
+
+(ert-deftest module/unibyte ()
+ (let ((result (mod-test-return-unibyte)))
+ (should (stringp result))
+ (should (not (multibyte-string-p (mod-test-return-unibyte))))
+ (should (equal result "foo\x00zot"))))
+
+(cl-defstruct (emacs-module-tests--variable
+ (:constructor nil)
+ (:constructor emacs-module-tests--make-variable
+ (name
+ &aux
+ (mutex (make-mutex name))
+ (condvar (make-condition-variable mutex name))))
+ (:copier nil))
+ "A variable that's protected by a mutex."
+ value
+ (mutex nil :read-only t :type mutex)
+ (condvar nil :read-only t :type condition-variable))
+
+(defun emacs-module-tests--wait-for-variable (variable desired)
+ (with-mutex (emacs-module-tests--variable-mutex variable)
+ (while (not (eq (emacs-module-tests--variable-value variable) desired))
+ (condition-wait (emacs-module-tests--variable-condvar variable)))))
+
+(defun emacs-module-tests--change-variable (variable new)
+ (with-mutex (emacs-module-tests--variable-mutex variable)
+ (setf (emacs-module-tests--variable-value variable) new)
+ (condition-notify (emacs-module-tests--variable-condvar variable) :all)))
+
+(ert-deftest emacs-module-tests/interleaved-threads ()
+ (let* ((state-1 (emacs-module-tests--make-variable "1"))
+ (state-2 (emacs-module-tests--make-variable "2"))
+ (thread-1
+ (make-thread
+ (lambda ()
+ (emacs-module-tests--change-variable state-1 'before-module)
+ (mod-test-funcall
+ (lambda ()
+ (emacs-module-tests--change-variable state-1 'in-module)
+ (emacs-module-tests--wait-for-variable state-2 'in-module)))
+ (emacs-module-tests--change-variable state-1 'after-module))
+ "thread 1"))
+ (thread-2
+ (make-thread
+ (lambda ()
+ (emacs-module-tests--change-variable state-2 'before-module)
+ (emacs-module-tests--wait-for-variable state-1 'in-module)
+ (mod-test-funcall
+ (lambda ()
+ (emacs-module-tests--change-variable state-2 'in-module)
+ (emacs-module-tests--wait-for-variable state-1 'after-module)))
+ (emacs-module-tests--change-variable state-2 'after-module))
+ "thread 2")))
+ (thread-join thread-1)
+ (thread-join thread-2)))
+
+(ert-deftest mod-test-make-string/empty ()
+ (dolist (multibyte '(nil t))
+ (ert-info ((format "Multibyte: %s" multibyte))
+ (let ((got (mod-test-make-string 0 multibyte)))
+ (should (stringp got))
+ (should (string-empty-p got))
+ (should (eq (multibyte-string-p got) multibyte))))))
+
+(ert-deftest mod-test-make-string/nonempty ()
+ (dolist (multibyte '(nil t))
+ (ert-info ((format "Multibyte: %s" multibyte))
+ (let ((first (mod-test-make-string 1 multibyte))
+ (second (mod-test-make-string 1 multibyte)))
+ (should (stringp first))
+ (should (eql (length first) 1))
+ (should (eq (multibyte-string-p first) multibyte))
+ (should (string-equal first second))
+ (should-not (eq first second))))))
;;; emacs-module-tests.el ends here
diff --git a/test/src/emacs-tests.el b/test/src/emacs-tests.el
new file mode 100644
index 00000000000..52888135c12
--- /dev/null
+++ b/test/src/emacs-tests.el
@@ -0,0 +1,249 @@
+;;; emacs-tests.el --- unit tests for emacs.c -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published
+;; by the Free Software Foundation, either version 3 of the License,
+;; or (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Unit tests for src/emacs.c.
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'ert)
+(require 'ert-x) ; ert-with-temp-file
+(require 'rx)
+(require 'subr-x)
+
+(defconst emacs-tests--lib-src
+ (substitute-in-file-name "$EMACS_TEST_DIRECTORY/../lib-src/")
+ "Location of the lib-src directory.")
+
+(ert-deftest emacs-tests/seccomp/absent-file ()
+ (skip-unless (string-match-p (rx bow "SECCOMP" eow)
+ system-configuration-features))
+ (let ((emacs
+ (expand-file-name invocation-name invocation-directory))
+ (process-environment nil))
+ (skip-unless (file-executable-p emacs))
+ (should-not (file-exists-p "/does-not-exist.bpf"))
+ (should-not
+ (eql (call-process emacs nil nil nil
+ "--quick" "--batch"
+ "--seccomp=/does-not-exist.bpf")
+ 0))))
+
+(ert-deftest emacs-tests/seccomp/empty-file ()
+ (skip-unless (string-match-p (rx bow "SECCOMP" eow)
+ system-configuration-features))
+ (let ((emacs
+ (expand-file-name invocation-name invocation-directory))
+ (process-environment nil))
+ (skip-unless (file-executable-p emacs))
+ (ert-with-temp-file filter
+ :prefix "seccomp-invalid-" :suffix ".bpf"
+ ;; The --seccomp option is processed early, without filename
+ ;; handlers. Therefore remote or quoted filenames wouldn't
+ ;; work.
+ (should-not (file-remote-p filter))
+ (cl-callf file-name-unquote filter)
+ ;; According to the Seccomp man page, a filter must have at
+ ;; least one element, so Emacs should reject an empty file.
+ (should-not
+ (eql (call-process emacs nil nil nil
+ "--quick" "--batch"
+ (concat "--seccomp=" filter))
+ 0)))))
+
+(ert-deftest emacs-tests/seccomp/file-too-large ()
+ (skip-unless (string-match-p (rx bow "SECCOMP" eow)
+ system-configuration-features))
+ (let ((emacs
+ (expand-file-name invocation-name invocation-directory))
+ (process-environment nil)
+ ;; This value should be correct on all supported systems.
+ (ushort-max #xFFFF)
+ ;; Either 8 or 16, but 16 should be large enough in all cases.
+ (filter-size 16))
+ (skip-unless (file-executable-p emacs))
+ (ert-with-temp-file filter
+ :prefix "seccomp-too-large-" :suffix ".bpf"
+ :text (make-string (* (1+ ushort-max) filter-size) ?a)
+ ;; The --seccomp option is processed early, without filename
+ ;; handlers. Therefore remote or quoted filenames wouldn't
+ ;; work.
+ (should-not (file-remote-p filter))
+ (cl-callf file-name-unquote filter)
+ ;; The filter count must fit into an `unsigned short'. A bigger
+ ;; file should be rejected.
+ (should-not
+ (eql (call-process emacs nil nil nil
+ "--quick" "--batch"
+ (concat "--seccomp=" filter))
+ 0)))))
+
+(ert-deftest emacs-tests/seccomp/invalid-file-size ()
+ (skip-unless (string-match-p (rx bow "SECCOMP" eow)
+ system-configuration-features))
+ (let ((emacs
+ (expand-file-name invocation-name invocation-directory))
+ (process-environment nil))
+ (skip-unless (file-executable-p emacs))
+ (ert-with-temp-file filter
+ :prefix "seccomp-invalid-" :suffix ".bpf" :text "123456"
+ ;; The --seccomp option is processed early, without filename
+ ;; handlers. Therefore remote or quoted filenames wouldn't
+ ;; work.
+ (should-not (file-remote-p filter))
+ (cl-callf file-name-unquote filter)
+ ;; The Seccomp filter file must have a file size that's a
+ ;; multiple of the size of struct sock_filter, which is 8 or 16,
+ ;; but never 6.
+ (should-not
+ (eql (call-process emacs nil nil nil
+ "--quick" "--batch"
+ (concat "--seccomp=" filter))
+ 0)))))
+
+(ert-deftest emacs-tests/seccomp/allows-stdout ()
+ (skip-unless (string-match-p (rx bow "SECCOMP" eow)
+ system-configuration-features))
+ (let ((emacs
+ (expand-file-name invocation-name invocation-directory))
+ (filter (expand-file-name "seccomp-filter.bpf"
+ emacs-tests--lib-src))
+ (process-environment nil))
+ (skip-unless (file-executable-p emacs))
+ (skip-unless (file-readable-p filter))
+ ;; The --seccomp option is processed early, without filename
+ ;; handlers. Therefore remote or quoted filenames wouldn't work.
+ (should-not (file-remote-p filter))
+ (cl-callf file-name-unquote filter)
+ (with-temp-buffer
+ (let ((start-time (current-time))
+ (status (call-process
+ emacs nil t nil
+ "--quick" "--batch"
+ (concat "--seccomp=" filter)
+ (format "--eval=%S" '(message "Hi"))))
+ (end-time (current-time)))
+ (ert-info ((emacs-tests--seccomp-debug start-time end-time))
+ (should (eql status 0)))
+ (should (equal (string-trim (buffer-string)) "Hi"))))))
+
+(ert-deftest emacs-tests/seccomp/forbids-subprocess ()
+ (skip-unless (string-match-p (rx bow "SECCOMP" eow)
+ system-configuration-features))
+ (let ((emacs
+ (expand-file-name invocation-name invocation-directory))
+ (filter (expand-file-name "seccomp-filter.bpf"
+ emacs-tests--lib-src))
+ (process-environment nil))
+ (skip-unless (file-executable-p emacs))
+ (skip-unless (file-readable-p filter))
+ ;; The --seccomp option is processed early, without filename
+ ;; handlers. Therefore remote or quoted filenames wouldn't work.
+ (should-not (file-remote-p filter))
+ (cl-callf file-name-unquote filter)
+ (with-temp-buffer
+ (let ((start-time (current-time))
+ (status
+ (call-process
+ emacs nil t nil
+ "--quick" "--batch"
+ (concat "--seccomp=" filter)
+ (format "--eval=%S" `(call-process ,emacs nil nil nil
+ "--version"))))
+ (end-time (current-time)))
+ (ert-info ((emacs-tests--seccomp-debug start-time end-time))
+ (should-not (eql status 0)))))))
+
+(ert-deftest emacs-tests/bwrap/allows-stdout ()
+ (let ((bash (executable-find "bash"))
+ (bwrap (executable-find "bwrap"))
+ (emacs
+ (expand-file-name invocation-name invocation-directory))
+ (filter (expand-file-name "seccomp-filter-exec.bpf"
+ emacs-tests--lib-src))
+ (process-environment nil))
+ (skip-unless bash)
+ (skip-unless bwrap)
+ (skip-unless (file-executable-p emacs))
+ (skip-unless (file-readable-p filter))
+ (should-not (file-remote-p bwrap))
+ (should-not (file-remote-p emacs))
+ (should-not (file-remote-p filter))
+ (with-temp-buffer
+ (let* ((command
+ (concat
+ (mapconcat #'shell-quote-argument
+ `(,(file-name-unquote bwrap)
+ "--ro-bind" "/" "/"
+ "--seccomp" "20"
+ "--"
+ ,(file-name-unquote emacs)
+ "--quick" "--batch"
+ ,(format "--eval=%S" '(message "Hi")))
+ " ")
+ " 20< "
+ (shell-quote-argument (file-name-unquote filter))))
+ (start-time (current-time))
+ (status (call-process bash nil t nil "-c" command))
+ (end-time (current-time)))
+ (ert-info ((emacs-tests--seccomp-debug start-time end-time))
+ (should (eql status 0)))
+ (should (equal (string-trim (buffer-string)) "Hi"))))))
+
+(defun emacs-tests--seccomp-debug (start-time end-time)
+ "Return potentially useful debugging information for Seccomp.
+Assume that the current buffer contains subprocess output for the
+failing process. START-TIME and END-TIME are time values between
+which the process was running."
+ ;; Add a bit of slack for the timestamps.
+ (cl-callf time-subtract start-time 5)
+ (cl-callf time-add end-time 5)
+ (with-output-to-string
+ (princ "Process output:")
+ (terpri)
+ (princ (buffer-substring-no-properties (point-min) (point-max)))
+ ;; Search audit logs for Seccomp messages.
+ (when-let ((ausearch (executable-find "ausearch")))
+ (terpri)
+ (princ "Potentially relevant Seccomp audit events:")
+ (terpri)
+ (let ((process-environment '("LC_TIME=C")))
+ (call-process ausearch nil standard-output nil
+ "--message" "SECCOMP"
+ "--start"
+ (format-time-string "%D" start-time)
+ (format-time-string "%T" start-time)
+ "--end"
+ (format-time-string "%D" end-time)
+ (format-time-string "%T" end-time)
+ "--interpret")))
+ ;; Print coredump information if available.
+ (when-let ((coredumpctl (executable-find "coredumpctl")))
+ (terpri)
+ (princ "Potentially useful coredump information:")
+ (terpri)
+ (call-process coredumpctl nil standard-output nil
+ "info"
+ "--since" (format-time-string "%F %T" start-time)
+ "--until" (format-time-string "%F %T" end-time)
+ "--no-pager"))))
+
+;;; emacs-tests.el ends here
diff --git a/test/src/eval-tests.el b/test/src/eval-tests.el
index 7ff60dd01c4..bb2f04e8ee1 100644
--- a/test/src/eval-tests.el
+++ b/test/src/eval-tests.el
@@ -1,6 +1,6 @@
;;; eval-tests.el --- unit tests for src/eval.c -*- lexical-binding: t; -*-
-;; Copyright (C) 2016-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2022 Free Software Foundation, Inc.
;; Author: Philipp Stephani <phst@google.com>
@@ -26,28 +26,53 @@
;;; Code:
(require 'ert)
+(eval-when-compile (require 'cl-lib))
+(require 'subr-x)
(ert-deftest eval-tests--bug24673 ()
- "Checks that Bug#24673 has been fixed."
+ "Check that Bug#24673 has been fixed."
;; This should not crash.
(should-error (funcall '(closure)) :type 'invalid-function))
(defvar byte-compile-debug)
(ert-deftest eval-tests--bugs-24912-and-24913 ()
- "Checks that Emacs doesn’t accept weird argument lists.
+ "Check that Emacs doesn't accept weird argument lists.
Bug#24912 and Bug#24913."
- (dolist (args '((&optional) (&rest) (&optional &rest) (&rest &optional)
- (&optional &rest a) (&optional a &rest)
- (&rest a &optional) (&rest &optional a)
- (&optional &optional) (&optional &optional a)
- (&optional a &optional b)
- (&rest &rest) (&rest &rest a)
- (&rest a &rest b)))
- (should-error (eval `(funcall (lambda ,args)) t) :type 'invalid-function)
- (should-error (byte-compile-check-lambda-list args))
- (let ((byte-compile-debug t))
- (should-error (eval `(byte-compile (lambda ,args)) t)))))
+ (dolist (lb '(t false))
+ (ert-info ((prin1-to-string lb) :prefix "lexical-binding: ")
+ (let ((lexical-binding lb))
+ (dolist (args '((&rest &optional)
+ (&rest a &optional) (&rest &optional a)
+ (&optional &optional) (&optional &optional a)
+ (&optional a &optional b)
+ (&rest &rest) (&rest &rest a)
+ (&rest a &rest b)
+ (&rest) (&optional &rest)
+ ))
+ (ert-info ((prin1-to-string args) :prefix "args: ")
+ (should-error
+ (eval `(funcall (lambda ,args)) lb) :type 'invalid-function)
+ (should-error (byte-compile-check-lambda-list args))
+ (let ((byte-compile-debug t))
+ (should-error (eval `(byte-compile (lambda ,args)) lb)))))))))
+
+(ert-deftest eval-tests-accept-empty-optional ()
+ "Check that Emacs accepts empty &optional arglists.
+Bug#24912."
+ (dolist (lb '(t false))
+ (ert-info ((prin1-to-string lb) :prefix "lexical-binding: ")
+ (let ((lexical-binding lb))
+ (dolist (args '((&optional) (&optional &rest a)))
+ (ert-info ((prin1-to-string args) :prefix "args: ")
+ (let ((fun `(lambda ,args 'ok)))
+ (ert-info ("eval")
+ (should (eq (funcall (eval fun lb)) 'ok)))
+ (ert-info ("byte comp check")
+ (byte-compile-check-lambda-list args))
+ (ert-info ("bytecomp")
+ (let ((byte-compile-debug t))
+ (should (eq (funcall (byte-compile fun)) 'ok)))))))))))
(dolist (form '(let let*))
@@ -61,22 +86,165 @@ Bug#24912 and Bug#24913."
(ert-deftest eval-tests--if-dot-string ()
"Check that Emacs rejects (if . \"string\")."
- (should-error (eval '(if . "abc")) :type 'wrong-type-argument)
+ (should-error (eval '(if . "abc") nil) :type 'wrong-type-argument)
+ (should-error (eval '(if . "abc") t) :type 'wrong-type-argument)
(let ((if-tail (list '(setcdr if-tail "abc") t)))
- (should-error (eval (cons 'if if-tail))))
+ (should-error (eval (cons 'if if-tail) nil) :type 'void-variable)
+ (should-error (eval (cons 'if if-tail) t) :type 'void-variable))
(let ((if-tail (list '(progn (setcdr if-tail "abc") nil) t)))
- (should-error (eval (cons 'if if-tail)))))
+ (should-error (eval (cons 'if if-tail) nil) :type 'void-variable)
+ (should-error (eval (cons 'if if-tail) t) :type 'void-variable)))
(ert-deftest eval-tests--let-with-circular-defs ()
"Check that Emacs reports an error for (let VARS ...) when VARS is circular."
(let ((vars (list 'v)))
(setcdr vars vars)
(dolist (let-sym '(let let*))
- (should-error (eval (list let-sym vars))))))
+ (should-error (eval (list let-sym vars) nil)))))
(ert-deftest eval-tests--mutating-cond ()
"Check that Emacs doesn't crash on a cond clause that mutates during eval."
(let ((clauses (list '((progn (setcdr clauses "ouch") nil)))))
- (should-error (eval (cons 'cond clauses)))))
+ (should-error (eval (cons 'cond clauses) nil))
+ (should-error (eval (cons 'cond clauses) t))))
+
+(ert-deftest defvar/bug31072 ()
+ "Check that Bug#31072 is fixed."
+ (should-error (eval '(defvar 1) t) :type 'wrong-type-argument))
+
+(ert-deftest defvaralias-overwrite-warning ()
+ "Test for Bug#5950."
+ (defvar eval-tests--foo)
+ (setq eval-tests--foo 2)
+ (defvar eval-tests--foo-alias)
+ (setq eval-tests--foo-alias 1)
+ (cl-letf (((symbol-function 'display-warning)
+ (lambda (type &rest _)
+ (throw 'got-warning type))))
+ ;; Warn if we lose a value through aliasing.
+ (should (equal
+ '(defvaralias losing-value eval-tests--foo-alias)
+ (catch 'got-warning
+ (defvaralias 'eval-tests--foo-alias 'eval-tests--foo))))
+ ;; Don't warn if we don't.
+ (makunbound 'eval-tests--foo-alias)
+ (should (eq 'no-warning
+ (catch 'got-warning
+ (defvaralias 'eval-tests--foo-alias 'eval-tests--foo)
+ 'no-warning)))))
+
+(ert-deftest eval-tests-byte-code-being-evaluated-is-protected-from-gc ()
+ "Regression test for Bug#33014.
+Check that byte-compiled objects being executed by exec-byte-code
+are found on the stack and therefore not garbage collected."
+ (should (string= (eval-tests-33014-func)
+ "before after: ok foo: (e) bar: (a b c d e) baz: a bop: c")))
+
+(defvar eval-tests-33014-var "ok")
+(defun eval-tests-33014-func ()
+ "A function which has a non-trivial constants vector when byte-compiled."
+ (let ((result "before "))
+ (eval-tests-33014-redefine)
+ (garbage-collect)
+ (setq result (concat result (format "after: %s" eval-tests-33014-var)))
+ (let ((vals '(0 1 2 3))
+ (things '(a b c d e)))
+ (dolist (val vals)
+ (setq result
+ (concat result " "
+ (cond
+ ((= val 0) (format "foo: %s" (last things)))
+ ((= val 1) (format "bar: %s" things))
+ ((= val 2) (format "baz: %s" (car things)))
+ (t (format "bop: %s" (nth 2 things))))))))
+ result))
+
+(defun eval-tests-33014-redefine ()
+ "Remove the Lisp reference to the byte-compiled object."
+ (setf (symbol-function #'eval-tests-33014-func) nil))
+
+(ert-deftest eval-tests-19790-backquote-comma-dot-substitution ()
+ "Regression test for Bug#19790.
+Don't handle destructive splicing in backquote expressions (like
+in Common Lisp). Instead, make sure substitution in backquote
+expressions works for identifiers starting with period."
+ (should (equal (let ((.x 'identity)) (eval `(,.x 'ok) nil)) 'ok))
+ (should (equal (let ((.x 'identity)) (eval `(,.x 'ok) t)) 'ok)))
+
+(ert-deftest eval-tests/backtrace-in-batch-mode ()
+ (let ((emacs (expand-file-name invocation-name invocation-directory)))
+ (skip-unless (file-executable-p emacs))
+ (with-temp-buffer
+ (let ((status (call-process emacs nil t nil
+ "--quick" "--batch"
+ (concat "--eval="
+ (prin1-to-string
+ '(progn
+ (defun foo () (error "Boo"))
+ (foo)))))))
+ (should (natnump status))
+ (should-not (eql status 0)))
+ (goto-char (point-min))
+ (ert-info ((concat "Process output:\n" (buffer-string)))
+ (search-forward " foo()")
+ (search-forward " normal-top-level()")))))
+
+(ert-deftest eval-tests/backtrace-in-batch-mode/inhibit ()
+ (let ((emacs (expand-file-name invocation-name invocation-directory)))
+ (skip-unless (file-executable-p emacs))
+ (with-temp-buffer
+ (let ((status (call-process
+ emacs nil t nil
+ "--quick" "--batch"
+ (concat "--eval="
+ (prin1-to-string
+ '(progn
+ (defun foo () (error "Boo"))
+ (let ((backtrace-on-error-noninteractive nil))
+ (foo))))))))
+ (should (natnump status))
+ (should-not (eql status 0)))
+ (should (equal (string-trim (buffer-string)) "Boo")))))
+
+(ert-deftest eval-tests/backtrace-in-batch-mode/demoted-errors ()
+ (let ((emacs (expand-file-name invocation-name invocation-directory)))
+ (skip-unless (file-executable-p emacs))
+ (with-temp-buffer
+ (should (eql 0 (call-process emacs nil t nil
+ "--quick" "--batch"
+ (concat "--eval="
+ (prin1-to-string
+ '(with-demoted-errors "Error: %S"
+ (error "Boo")))))))
+ (goto-char (point-min))
+ (should (equal (string-trim (buffer-string))
+ "Error: (error \"Boo\")")))))
+
+(ert-deftest eval-tests/funcall-with-delayed-message ()
+ ;; Check that `funcall-with-delayed-message' displays its message before
+ ;; its function terminates iff the timeout is short enough.
+
+ ;; This also serves as regression test for bug#55628 where a short
+ ;; timeout was rounded up to the next whole second.
+ (dolist (params '((0.8 0.4)
+ (0.1 0.8)))
+ (let ((timeout (nth 0 params))
+ (work-time (nth 1 params)))
+ (ert-info ((prin1-to-string params) :prefix "params: ")
+ (with-current-buffer "*Messages*"
+ (let ((inhibit-read-only t))
+ (erase-buffer))
+ (let ((stop (+ (float-time) work-time)))
+ (funcall-with-delayed-message
+ timeout "timed out"
+ (lambda ()
+ (while (< (float-time) stop))
+ (message "finished"))))
+ (let ((expected-messages
+ (if (< timeout work-time)
+ "timed out\nfinished"
+ "finished")))
+ (should (equal (string-trim (buffer-string))
+ expected-messages))))))))
;;; eval-tests.el ends here
diff --git a/test/src/fileio-tests.el b/test/src/fileio-tests.el
index 01c280d2752..08582c8a862 100644
--- a/test/src/fileio-tests.el
+++ b/test/src/fileio-tests.el
@@ -1,6 +1,6 @@
-;;; unit tests for src/fileio.c -*- lexical-binding: t; -*-
+;;; fileio-tests.el --- unit tests for src/fileio.c -*- lexical-binding: t; -*-
-;; Copyright 2017 Free Software Foundation, Inc.
+;; Copyright 2017-2022 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -17,6 +17,8 @@
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+;;; Code:
+
(require 'ert)
(defun try-link (target link)
@@ -95,3 +97,124 @@ Also check that an encoding error can appear in a symlink."
(should (equal (file-name-as-directory "d:/abc/") "d:/abc/"))
(should (equal (file-name-as-directory "D:\\abc/") "d:/abc/"))
(should (equal (file-name-as-directory "D:/abc//") "d:/abc//")))
+
+(ert-deftest fileio-tests--relative-HOME ()
+ "Test that `expand-file-name' works even when HOME is relative."
+ (let ((process-environment (copy-sequence process-environment)))
+ (setenv "HOME" "a/b/c")
+ (should (equal (expand-file-name "~/foo")
+ (expand-file-name "a/b/c/foo")))
+ (when (memq system-type '(ms-dos windows-nt))
+ ;; Test expansion of drive-relative file names.
+ (setenv "HOME" "x:foo")
+ (should (equal (expand-file-name "~/bar") "x:/foo/bar")))))
+
+(ert-deftest fileio-tests--insert-file-interrupt ()
+ (let ((text "-*- coding: binary -*-\n\xc3\xc3help")
+ f)
+ (unwind-protect
+ (progn
+ (setq f (make-temp-file "ftifi"))
+ (write-region text nil f nil 'silent)
+ (with-temp-buffer
+ (catch 'toto
+ (let ((set-auto-coding-function (lambda (&rest _) (throw 'toto nil))))
+ (insert-file-contents f)))
+ (goto-char (point-min))
+ (unless (eobp)
+ (forward-line 1)
+ (let ((c1 (char-after)))
+ (forward-char 1)
+ (should (equal c1 (char-before)))
+ (should (equal c1 (char-after)))))))
+ (if f (delete-file f)))))
+
+(ert-deftest fileio-tests--relative-default-directory ()
+ "Test `expand-file-name' when `default-directory' is relative."
+ (let ((default-directory "some/relative/name"))
+ (should (file-name-absolute-p (expand-file-name "foo"))))
+ (let* ((default-directory "~foo")
+ (name (expand-file-name "bar")))
+ (should (and (file-name-absolute-p name)
+ (not (eq (aref name 0) ?~))))))
+
+(ert-deftest fileio-tests--expand-file-name-null-bytes ()
+ "Test that `expand-file-name' checks for null bytes in filenames."
+ (should-error (expand-file-name (concat "file" (char-to-string ?\0) ".txt"))
+ :type 'wrong-type-argument)
+ (should-error (expand-file-name "file.txt" (concat "dir" (char-to-string ?\0)))
+ :type 'wrong-type-argument)
+ (let ((default-directory (concat "dir" (char-to-string ?\0))))
+ (should-error (expand-file-name "file.txt") :type 'wrong-type-argument)))
+
+(ert-deftest fileio-tests--file-name-absolute-p ()
+ "Test `file-name-absolute-p'."
+ (dolist (suffix '("" "/" "//" "/foo" "/foo/" "/foo//" "/foo/bar"))
+ (unless (string-equal suffix "")
+ (should (file-name-absolute-p suffix)))
+ (should (file-name-absolute-p (concat "~" suffix)))
+ (when (user-full-name user-login-name)
+ (should (file-name-absolute-p (concat "~" user-login-name suffix))))
+ (unless (user-full-name "nosuchuser")
+ (should (not (file-name-absolute-p (concat "~nosuchuser" suffix)))))))
+
+(ert-deftest fileio-tests--circular-after-insert-file-functions ()
+ "Test `after-insert-file-functions' as a circular list."
+ (let ((f (make-temp-file "fileio"))
+ (after-insert-file-functions (list 'identity)))
+ (setcdr after-insert-file-functions after-insert-file-functions)
+ (write-region "hello\n" nil f nil 'silent)
+ (should-error (insert-file-contents f) :type 'circular-list)
+ (delete-file f)))
+
+(ert-deftest fileio-tests/null-character ()
+ (should-error (file-exists-p "/foo\0bar")
+ :type 'wrong-type-argument))
+
+(ert-deftest fileio-tests/file-name-concat ()
+ (should (equal (file-name-concat "foo" "bar") "foo/bar"))
+ (should (equal (file-name-concat "foo" "bar") "foo/bar"))
+ (should (equal (file-name-concat "foo" "bar" "zot") "foo/bar/zot"))
+ (should (equal (file-name-concat "foo/" "bar") "foo/bar"))
+ (should (equal (file-name-concat "foo//" "bar") "foo//bar"))
+ (should (equal (file-name-concat "foo/" "bar/" "zot") "foo/bar/zot"))
+ (should (equal (file-name-concat "fóo" "bar") "fóo/bar"))
+ (should (equal (file-name-concat "foo" "bár") "foo/bár"))
+ (should (equal (file-name-concat "fóo" "bár") "fóo/bár"))
+ (let ((string (make-string 5 ?a)))
+ (should (not (multibyte-string-p string)))
+ (aset string 2 255)
+ (should (not (multibyte-string-p string)))
+ (should (equal (file-name-concat "fóo" string) "fóo/aa\377aa")))
+ (should (equal (file-name-concat "foo") "foo"))
+ (should (equal (file-name-concat "foo/") "foo/"))
+ (should (equal (file-name-concat "foo" "") "foo"))
+ (should (equal (file-name-concat "foo" "" "" "" nil) "foo"))
+ (should (equal (file-name-concat "" "bar") "bar"))
+ (should (equal (file-name-concat "" "") "")))
+
+(ert-deftest fileio-tests--non-regular-insert ()
+ (skip-unless (file-exists-p "/dev/urandom"))
+ (with-temp-buffer
+ (set-buffer-multibyte nil)
+ (should-error (insert-file-contents "/dev/urandom" nil 5 10))
+ (insert-file-contents "/dev/urandom" nil nil 10)
+ (should (= (buffer-size) 10))))
+
+(defun fileio-tests--identity-expand-handler (_ file &rest _)
+ file)
+(put 'fileio-tests--identity-expand-handler 'operations '(expand-file-name))
+
+(ert-deftest fileio--file-name-case-insensitive-p ()
+ ;; Check that we at least don't crash if given nonexisting files
+ ;; without a directory (bug#56443).
+
+ ;; Use an identity file-name handler, as if called by `ffap'.
+ (let* ((file-name-handler-alist
+ '(("^mailto:" . fileio-tests--identity-expand-handler)))
+ (file "mailto:snowball@hell.com"))
+ ;; Check that `expand-file-name' is identity for this name.
+ (should (equal (expand-file-name file nil) file))
+ (file-name-case-insensitive-p file)))
+
+;;; fileio-tests.el ends here
diff --git a/test/src/filelock-tests.el b/test/src/filelock-tests.el
new file mode 100644
index 00000000000..97642669a0d
--- /dev/null
+++ b/test/src/filelock-tests.el
@@ -0,0 +1,217 @@
+;;; filelock-tests.el --- test file locking -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This file tests code in src/filelock.c and, to some extent, the
+;; related code in src/fileio.c.
+;;
+;; See also (info "(emacs)Interlocking") and (info "(elisp)File Locks")
+
+;;; Code:
+
+(require 'cl-macs)
+(require 'ert)
+(require 'ert-x)
+(require 'seq)
+
+(defmacro filelock-tests--fixture (&rest body)
+ "Call BODY under a test fixture.
+Create a test directory and a buffer whose `buffer-file-name' and
+`buffer-file-truename' are a file within it, then call BODY.
+Finally, delete the buffer and the test directory."
+ (declare (debug (body)))
+ `(ert-with-temp-directory temp-dir
+ (let ((name (concat (file-name-as-directory temp-dir)
+ "userfile"))
+ (create-lockfiles t))
+ (with-temp-buffer
+ (setq buffer-file-name name
+ buffer-file-truename name)
+ (unwind-protect
+ (save-current-buffer
+ ,@body)
+ ;; Set `buffer-file-truename' nil to prevent unlocking,
+ ;; which might prompt the user and/or signal errors.
+ (setq buffer-file-name nil
+ buffer-file-truename nil))))))
+
+(defun filelock-tests--make-lock-name (file-name)
+ "Return the lock file name for FILE-NAME.
+Equivalent logic in Emacs proper is implemented in C and
+unavailable to Lisp."
+ (concat (file-name-directory (expand-file-name file-name))
+ ".#"
+ (file-name-nondirectory file-name)))
+
+(defun filelock-tests--spoil-lock-file (file-name)
+ "Spoil the lock file for FILE-NAME.
+Cause Emacs to report errors for various file locking operations
+on FILE-NAME going forward. Create a file that is incompatible
+with Emacs' file locking protocol, but uses the same name as
+FILE-NAME's lock file. A directory file is used, which is
+portable in practice."
+ (make-directory (filelock-tests--make-lock-name file-name)))
+
+(defun filelock-tests--unspoil-lock-file (file-name)
+ "Remove the lock file spoiler for FILE-NAME.
+See `filelock-tests--spoil-lock-file'."
+ (delete-directory (filelock-tests--make-lock-name file-name) t))
+
+(defun filelock-tests--should-be-locked ()
+ "Abort the current test if the current buffer is not locked.
+Exception: on systems without lock file support, aborts the
+current test if the current file is locked (which should never
+the case)."
+ (if (eq system-type 'ms-dos)
+ (should-not (file-locked-p buffer-file-truename))
+ (should (file-locked-p buffer-file-truename))))
+
+(ert-deftest filelock-tests-lock-unlock-no-errors ()
+ "Check that locking and unlocking works without error."
+ (filelock-tests--fixture
+ (should-not (file-locked-p (buffer-file-name)))
+
+ ;; Inserting text should lock the buffer's file.
+ (insert "this locks the buffer's file")
+ (filelock-tests--should-be-locked)
+ (unlock-buffer)
+ (set-buffer-modified-p nil)
+ (should-not (file-locked-p (buffer-file-name)))
+
+ ;; `set-buffer-modified-p' should lock the buffer's file.
+ (set-buffer-modified-p t)
+ (filelock-tests--should-be-locked)
+ (unlock-buffer)
+ (should-not (file-locked-p (buffer-file-name)))
+
+ (should-not (file-locked-p (buffer-file-name)))))
+
+(ert-deftest filelock-tests-lock-spoiled ()
+ "Check `lock-buffer'."
+ (skip-unless (not (eq system-type 'ms-dos))) ; no filelock support
+ (filelock-tests--fixture
+ (filelock-tests--spoil-lock-file buffer-file-truename)
+ ;; FIXME: errors when locking a file are ignored; should they be?
+ (set-buffer-modified-p t)
+ (filelock-tests--unspoil-lock-file buffer-file-truename)
+ (should-not (file-locked-p buffer-file-truename))))
+
+(ert-deftest filelock-tests-file-locked-p-spoiled ()
+ "Check that `file-locked-p' fails if the lockfile is \"spoiled\"."
+ (skip-unless (not (eq system-type 'ms-dos))) ; no filelock support
+ (filelock-tests--fixture
+ (filelock-tests--spoil-lock-file buffer-file-truename)
+ (let ((err (should-error (file-locked-p (buffer-file-name)))))
+ (should (equal (seq-subseq err 0 2)
+ (if (eq system-type 'windows-nt)
+ '(permission-denied "Testing file lock")
+ '(file-error "Testing file lock")))))))
+
+(ert-deftest filelock-tests-unlock-spoiled ()
+ "Check that `unlock-buffer' fails if the lockfile is \"spoiled\"."
+ (skip-unless (not (eq system-type 'ms-dos))) ; no filelock support
+ (filelock-tests--fixture
+ ;; Set the buffer modified with file locking temporarily disabled.
+ (let ((create-lockfiles nil))
+ (set-buffer-modified-p t))
+ (should-not (file-locked-p buffer-file-truename))
+ (filelock-tests--spoil-lock-file buffer-file-truename)
+
+ ;; Errors from `unlock-buffer' should call
+ ;; `userlock--handle-unlock-error' (bug#46397).
+ (cl-letf (((symbol-function 'userlock--handle-unlock-error)
+ (lambda (err) (signal (car err) (cdr err)))))
+ (should (equal
+ (if (eq system-type 'windows-nt)
+ '(permission-denied "Unlocking file")
+ '(file-error "Unlocking file"))
+ (seq-subseq (should-error (unlock-buffer)) 0 2))))))
+
+(ert-deftest filelock-tests-kill-buffer-spoiled ()
+ "Check that `kill-buffer' fails if a lockfile is \"spoiled\"."
+ (skip-unless (not (eq system-type 'ms-dos))) ; no filelock support
+ (filelock-tests--fixture
+ ;; Set the buffer modified with file locking temporarily disabled.
+ (let ((create-lockfiles nil))
+ (set-buffer-modified-p t))
+ (should-not (file-locked-p buffer-file-truename))
+ (filelock-tests--spoil-lock-file buffer-file-truename)
+
+ ;; Kill the current buffer. Because the buffer is modified Emacs
+ ;; will attempt to unlock it. Temporarily bind `yes-or-no-p' to a
+ ;; function that fakes a "yes" answer for the "Buffer modified;
+ ;; kill anyway?" prompt.
+ ;;
+ ;; File errors from unlocking files should call
+ ;; `userlock--handle-unlock-error' (bug#46397).
+ (cl-letf (((symbol-function 'yes-or-no-p) #'always)
+ ((symbol-function 'userlock--handle-unlock-error)
+ (lambda (err) (signal (car err) (cdr err)))))
+ (should (equal
+ (if (eq system-type 'windows-nt)
+ '(permission-denied "Unlocking file")
+ '(file-error "Unlocking file"))
+ (seq-subseq (should-error (kill-buffer)) 0 2))))))
+
+(ert-deftest filelock-tests-detect-external-change ()
+ "Check that an external file modification is reported."
+ (skip-unless (not (eq system-type 'ms-dos))) ; no filelock support
+ (skip-unless (executable-find "touch"))
+ (skip-unless (executable-find "echo"))
+ (dolist (cl '(t nil))
+ (filelock-tests--fixture
+ (let ((create-lockfiles cl))
+ (write-region "foo" nil (buffer-file-name))
+ (revert-buffer nil 'noconfirm)
+ (should-not (file-locked-p (buffer-file-name)))
+
+ ;; Just changing the file modification on disk doesn't hurt,
+ ;; because file contents in buffer and on disk look equal.
+ (shell-command (format "touch %s" (buffer-file-name)))
+ (insert "bar")
+ (when cl (filelock-tests--should-be-locked))
+
+ ;; Bug#53207: with `create-lockfiles' nil, saving the buffer
+ ;; results in a prompt.
+ (cl-letf (((symbol-function 'yes-or-no-p)
+ (lambda (_) (ert-fail "Test failed unexpectedly"))))
+ (save-buffer))
+ (should-not (file-locked-p (buffer-file-name)))
+
+ ;; Changing the file contents on disk hurts when buffer is
+ ;; modified. There shall be a query, which we answer.
+ ;; *Messages* buffer is checked for prompt.
+ (shell-command (format "echo bar >>%s" (buffer-file-name)))
+ (cl-letf (((symbol-function 'read-char-choice)
+ (lambda (prompt &rest _) (message "%s" prompt) ?y)))
+ (ert-with-message-capture captured-messages
+ ;; `ask-user-about-supersession-threat' does not work in
+ ;; batch mode, let's simulate interactiveness.
+ (let (noninteractive)
+ (insert "baz"))
+ (should (string-match-p
+ (format
+ "^%s changed on disk; really edit the buffer\\?"
+ (file-name-nondirectory (buffer-file-name)))
+ captured-messages))))
+ (when cl (filelock-tests--should-be-locked))))))
+
+(provide 'filelock-tests)
+;;; filelock-tests.el ends here
diff --git a/test/src/floatfns-tests.el b/test/src/floatfns-tests.el
index aa4e55e4897..aa709e3c2f5 100644
--- a/test/src/floatfns-tests.el
+++ b/test/src/floatfns-tests.el
@@ -1,6 +1,6 @@
-;;; floatfns-tests.el --- tests for floating point operations
+;;; floatfns-tests.el --- tests for floating point operations -*- lexical-binding: t -*-
-;; Copyright 2017 Free Software Foundation, Inc.
+;; Copyright 2017-2022 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -17,13 +17,77 @@
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+;;; Code:
+
(require 'ert)
+(ert-deftest floatfns-tests-cos ()
+ (should (= (cos 0) 1.0))
+ (should (= (cos float-pi) -1.0)))
+
+(ert-deftest floatfns-tests-sin ()
+ (should (= (sin 0) 0.0)))
+
+(ert-deftest floatfns-tests-tan ()
+ (should (= (tan 0) 0.0)))
+
+(ert-deftest floatfns-tests-isnan ()
+ (should (isnan 0.0e+NaN))
+ (should (isnan -0.0e+NaN))
+ (should-error (isnan "foo") :type 'wrong-type-argument))
+
+(ert-deftest floatfns-tests-exp ()
+ (should (= (exp 0) 1.0)))
+
+(ert-deftest floatfns-tests-expt ()
+ (should (= (expt 2 8) 256)))
+
+(ert-deftest floatfns-tests-log ()
+ (should (= (log 1000 10) 3.0)))
+
+(ert-deftest floatfns-tests-sqrt ()
+ (should (= (sqrt 25) 5)))
+
+(ert-deftest floatfns-tests-abs ()
+ (should (= (abs 10) 10))
+ (should (= (abs -10) 10)))
+
+(ert-deftest floatfns-tests-logb ()
+ (should (= (logb 10000) 13)))
+
+(ert-deftest floatfns-tests-ceiling ()
+ (should (= (ceiling 0.5) 1)))
+
+(ert-deftest floatfns-tests-floor ()
+ (should (= (floor 1.5) 1)))
+
+(ert-deftest floatfns-tests-round ()
+ (should (= (round 1.49999999999) 1))
+ (should (= (round 1.50000000000) 2))
+ (should (= (round 1.50000000001) 2)))
+
+(ert-deftest floatfns-tests-truncate ()
+ (should (= (truncate float-pi) 3)))
+
+(ert-deftest floatfns-tests-fceiling ()
+ (should (= (fceiling 0.5) 1.0)))
+
+(ert-deftest floatfns-tests-ffloor ()
+ (should (= (ffloor 1.5) 1.0)))
+
+(ert-deftest floatfns-tests-fround ()
+ (should (= (fround 1.49999999999) 1.0))
+ (should (= (fround 1.50000000000) 2.0))
+ (should (= (fround 1.50000000001) 2.0)))
+
+(ert-deftest floatfns-tests-ftruncate ()
+ (should (= (ftruncate float-pi) 3.0)))
+
(ert-deftest divide-extreme-sign ()
- (should-error (ceiling most-negative-fixnum -1.0))
- (should-error (floor most-negative-fixnum -1.0))
- (should-error (round most-negative-fixnum -1.0))
- (should-error (truncate most-negative-fixnum -1.0)))
+ (should (= (ceiling most-negative-fixnum -1.0) (- most-negative-fixnum)))
+ (should (= (floor most-negative-fixnum -1.0) (- most-negative-fixnum)))
+ (should (= (round most-negative-fixnum -1.0) (- most-negative-fixnum)))
+ (should (= (truncate most-negative-fixnum -1.0) (- most-negative-fixnum))))
(ert-deftest logb-extreme-fixnum ()
(should (= (logb most-negative-fixnum) (1+ (logb most-positive-fixnum)))))
@@ -34,4 +98,96 @@
(should-error (ftruncate 0) :type 'wrong-type-argument)
(should-error (fround 0) :type 'wrong-type-argument))
+(ert-deftest bignum-to-float ()
+ ;; 122 because we want to go as big as possible to provoke a rounding error,
+ ;; but not too big: 2**122 < 10**37 < 2**123, and the C standard says
+ ;; 10**37 <= DBL_MAX so 2**122 cannot overflow as a double.
+ (let ((a (1- (ash 1 122))))
+ (should (or (eql a (1- (floor (float a))))
+ (eql a (floor (float a))))))
+ (should (eql (float (+ most-positive-fixnum 1))
+ (+ (float most-positive-fixnum) 1))))
+
+(ert-deftest bignum-abs ()
+ (should (= most-positive-fixnum
+ (- (abs most-negative-fixnum) 1))))
+
+(ert-deftest bignum-expt ()
+ (dolist (n (list most-positive-fixnum (1+ most-positive-fixnum)
+ most-negative-fixnum (1- most-negative-fixnum)
+ (* 5 most-negative-fixnum)
+ (* 5 (1+ most-positive-fixnum))
+ -2 -1 0 1 2))
+ (should (or (<= n 0) (= (expt 0 n) 0)))
+ (should (= (expt 1 n) 1))
+ (should (or (< n 0) (= (expt -1 n) (if (zerop (logand n 1)) 1 -1))))
+ (should (= (expt n 0) 1))
+ (should (= (expt n 1) n))
+ (should (= (expt n 2) (* n n)))
+ (should (= (expt n 3) (* n n n)))))
+
+(ert-deftest bignum-logb ()
+ (should (= (+ (logb most-positive-fixnum) 1)
+ (logb (+ most-positive-fixnum 1)))))
+
+(ert-deftest bignum-mod ()
+ (should (= 0 (mod (1+ most-positive-fixnum) 2.0))))
+
+(ert-deftest bignum-round ()
+ (let ((ns (list (* most-positive-fixnum most-negative-fixnum)
+ (1- most-negative-fixnum) most-negative-fixnum
+ (1+ most-negative-fixnum) -2 1 1 2
+ (1- most-positive-fixnum) most-positive-fixnum
+ (1+ most-positive-fixnum)
+ (* most-positive-fixnum most-positive-fixnum))))
+ (dolist (n ns)
+ (should (= n (ceiling n)))
+ (should (= n (floor n)))
+ (should (= n (round n)))
+ (should (= n (truncate n)))
+ (let ((-n (- n))
+ (f (float n))
+ (-f (- (float n))))
+ (should (= 1 (round n f) (round -n -f) (round f n) (round -f -n)))
+ (should (= -1 (round -n f) (round n -f) (round f -n) (round -f n))))
+ (dolist (d ns)
+ (let ((q (/ n d))
+ (r (% n d))
+ (same-sign (eq (< n 0) (< d 0))))
+ (should (= (ceiling n d)
+ (+ q (if (and same-sign (not (zerop r))) 1 0))))
+ (should (= (floor n d)
+ (- q (if (and (not same-sign) (not (zerop r))) 1 0))))
+ (should (= (truncate n d) q))
+ (let ((cdelta (abs (- n (* d (ceiling n d)))))
+ (fdelta (abs (- n (* d (floor n d)))))
+ (rdelta (abs (- n (* d (round n d))))))
+ (should (<= rdelta cdelta))
+ (should (<= rdelta fdelta))
+ (should (if (zerop r)
+ (= 0 cdelta fdelta rdelta)
+ (or (/= cdelta fdelta)
+ (zerop (% (round n d) 2)))))))))))
+
+(ert-deftest special-round ()
+ (dolist (f '(ceiling floor round truncate))
+ (let ((ns '(-1e+INF 1e+INF -1 -0.0 0.0 0 1 -1e+NaN 1e+NaN)))
+ (dolist (n ns)
+ (if (not (<= (abs n) 1))
+ (should-error (funcall f n))
+ (should (= n (funcall f n)))
+ (dolist (d '(-1e+INF 1e+INF))
+ (should (eq 0 (funcall f n d)))))
+ (dolist (d ns)
+ (when (or (zerop d) (= (abs n) 1e+INF) (not (= n n)) (not (= d d)))
+ (should-error (funcall f n d))))))))
+
+(ert-deftest big-round ()
+ (should (= (floor 54043195528445955 3)
+ (floor 54043195528445955 3.0)))
+ (should (= (floor 1.7976931348623157e+308 5e-324)
+ (ash (1- (ash 1 53)) 2045))))
+
(provide 'floatfns-tests)
+
+;;; floatfns-tests.el ends here
diff --git a/test/src/fns-tests.el b/test/src/fns-tests.el
index d751acb7478..fe8df7097a7 100644
--- a/test/src/fns-tests.el
+++ b/test/src/fns-tests.el
@@ -1,21 +1,21 @@
-;;; fns-tests.el --- tests for src/fns.c
+;;; fns-tests.el --- tests for src/fns.c -*- lexical-binding:t -*-
-;; Copyright (C) 2014-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2022 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
-;; This program is free software: you can redistribute it and/or
-;; modify it under the terms of the GNU General Public License as
-;; published by the Free Software Foundation, either version 3 of the
-;; License, or (at your option) any later version.
-;;
-;; This program is distributed in the hope that it will be useful, but
-;; WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-;; General Public License for more details.
-;;
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
;; You should have received a copy of the GNU General Public License
-;; along with this program. If not, see `https://www.gnu.org/licenses/'.
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
@@ -23,6 +23,67 @@
(require 'cl-lib)
+(ert-deftest fns-tests-identity ()
+ (let ((num 12345)) (should (eq (identity num) num)))
+ (let ((str "foo")) (should (eq (identity str) str)))
+ (let ((lst '(11))) (should (eq (identity lst) lst))))
+
+(ert-deftest fns-tests-random ()
+ (should (integerp (random)))
+ (should (>= (random 10) 0))
+ (should (< (random 10) 10)))
+
+(ert-deftest fns-tests-length ()
+ (should (= (length nil) 0))
+ (should (= (length '(1 2 3)) 3))
+ (should (= (length '[1 2 3]) 3))
+ (should (= (length "foo") 3))
+ (should-error (length t)))
+
+(ert-deftest fns-tests-safe-length ()
+ (should (= (safe-length '(1 2 3)) 3)))
+
+(ert-deftest fns-tests-string-bytes ()
+ (should (= (string-bytes "abc") 3)))
+
+;; Test that equality predicates work correctly on NaNs when combined
+;; with hash tables based on those predicates. This was not the case
+;; for eql in Emacs 26.
+(ert-deftest fns-tests-equality-nan ()
+ (dolist (test (list #'eq #'eql #'equal))
+ (let* ((h (make-hash-table :test test))
+ (nan 0.0e+NaN)
+ (-nan (- nan)))
+ (puthash nan t h)
+ (should (eq (funcall test nan -nan) (gethash -nan h))))))
+
+(ert-deftest fns-tests-equal-including-properties ()
+ (should (equal-including-properties "" ""))
+ (should (equal-including-properties "foo" "foo"))
+ (should (equal-including-properties #("foo" 0 3 (a b))
+ (propertize "foo" 'a 'b)))
+ (should (equal-including-properties #("foo" 0 3 (a b c d))
+ (propertize "foo" 'a 'b 'c 'd)))
+ (should (equal-including-properties #("a" 0 1 (k v))
+ #("a" 0 1 (k v))))
+ (should-not (equal-including-properties #("a" 0 1 (k v))
+ #("a" 0 1 (k x))))
+ (should-not (equal-including-properties #("a" 0 1 (k v))
+ #("b" 0 1 (k v))))
+ (should-not (equal-including-properties #("foo" 0 3 (a b c e))
+ (propertize "foo" 'a 'b 'c 'd))))
+
+(ert-deftest fns-tests-equal-including-properties/string-prop-vals ()
+ "Handle string property values. (Bug#6581)"
+ (should (equal-including-properties #("a" 0 1 (k "v"))
+ #("a" 0 1 (k "v"))))
+ (should (equal-including-properties #("foo" 0 3 (a (t)))
+ (propertize "foo" 'a (list t))))
+ (should-not (equal-including-properties #("a" 0 1 (k "v"))
+ #("a" 0 1 (k "x"))))
+ (should-not (equal-including-properties #("a" 0 1 (k "v"))
+ #("b" 0 1 (k "v")))))
+
(ert-deftest fns-tests-reverse ()
(should-error (reverse))
(should-error (reverse 1))
@@ -38,21 +99,21 @@
(should-error (nreverse))
(should-error (nreverse 1))
(should-error (nreverse (make-char-table 'foo)))
- (should (equal (nreverse "xyzzy") "yzzyx"))
- (let ((A []))
+ (should (equal (nreverse (copy-sequence "xyzzy")) "yzzyx"))
+ (let ((A (vector)))
(nreverse A)
(should (equal A [])))
- (let ((A [0]))
+ (let ((A (vector 0)))
(nreverse A)
(should (equal A [0])))
- (let ((A [1 2 3 4]))
+ (let ((A (vector 1 2 3 4)))
(nreverse A)
(should (equal A [4 3 2 1])))
- (let ((A [1 2 3 4]))
+ (let ((A (vector 1 2 3 4)))
(nreverse A)
(nreverse A)
(should (equal A [1 2 3 4])))
- (let* ((A [1 2 3 4])
+ (let* ((A (vector 1 2 3 4))
(B (nreverse (nreverse A))))
(should (equal A B))))
@@ -69,6 +130,49 @@
(should (equal [nil nil nil nil nil t t t t t] (vconcat A)))
(should (equal [t t t t t nil nil nil nil nil] (vconcat (nreverse A))))))
+(defconst fns-tests--string-lessp-cases
+ '((a 97 error)
+ (97 "a" error)
+ ("abc" "abd" t)
+ ("abd" "abc" nil)
+ (abc "abd" t)
+ ("abd" abc nil)
+ (abc abd t)
+ (abd abc nil)
+ ("" "" nil)
+ ("" " " t)
+ (" " "" nil)
+ ("abc" "abcd" t)
+ ("abcd" "abc" nil)
+ ("abc" "abc" nil)
+ (abc abc nil)
+ ("\0" "" nil)
+ ("" "\0" t)
+ ("~" "\x80" t)
+ ("\x80" "\x80" nil)
+ ("\xfe" "\xff" t)
+ ("Munchen" "München" t)
+ ("München" "Munchen" nil)
+ ("München" "München" nil)
+ ("Ré" "Réunion" t)))
+
+
+(ert-deftest fns-tests-string-lessp ()
+ ;; Exercise both `string-lessp' and its alias `string<', both directly
+ ;; and in a function (exercising its bytecode).
+ (dolist (lessp (list #'string-lessp #'string<
+ (lambda (a b) (string-lessp a b))
+ (lambda (a b) (string< a b))))
+ (ert-info ((prin1-to-string lessp) :prefix "function: ")
+ (dolist (case fns-tests--string-lessp-cases)
+ (ert-info ((prin1-to-string case) :prefix "case: ")
+ (pcase case
+ (`(,x ,y error)
+ (should-error (funcall lessp x y)))
+ (`(,x ,y ,expected)
+ (should (equal (funcall lessp x y) expected)))))))))
+
+
(ert-deftest fns-tests-compare-strings ()
(should-error (compare-strings))
(should-error (compare-strings "xyzzy" "xyzzy"))
@@ -119,10 +223,9 @@
;; In POSIX or C locales, collation order is lexicographic.
(should (string-collate-lessp "XYZZY" "xyzzy" "POSIX"))
- ;; In a language specific locale, collation order is different.
- (should (string-collate-lessp
- "xyzzy" "XYZZY"
- (if (eq system-type 'windows-nt) "enu_USA" "en_US.UTF-8")))
+ ;; In a language specific locale on MS-Windows, collation order is different.
+ (when (eq system-type 'windows-nt)
+ (should (string-collate-lessp "xyzzy" "XYZZY" "enu_USA")))
;; Ignore case.
(should (string-collate-equalp "xyzzy" "XYZZY" nil t))
@@ -136,14 +239,84 @@
;; Invalid UTF-8 sequences shall be indicated. How to create such strings?
(ert-deftest fns-tests-sort ()
- (should (equal (sort '(9 5 2 -1 5 3 8 7 4) (lambda (x y) (< x y)))
+ (should (equal (sort (list 9 5 2 -1 5 3 8 7 4) (lambda (x y) (< x y)))
'(-1 2 3 4 5 5 7 8 9)))
- (should (equal (sort '(9 5 2 -1 5 3 8 7 4) (lambda (x y) (> x y)))
+ (should (equal (sort (list 9 5 2 -1 5 3 8 7 4) (lambda (x y) (> x y)))
'(9 8 7 5 5 4 3 2 -1)))
- (should (equal (sort '[9 5 2 -1 5 3 8 7 4] (lambda (x y) (< x y)))
+ (should (equal (sort (vector 9 5 2 -1 5 3 8 7 4) (lambda (x y) (< x y)))
[-1 2 3 4 5 5 7 8 9]))
- (should (equal (sort '[9 5 2 -1 5 3 8 7 4] (lambda (x y) (> x y)))
+ (should (equal (sort (vector 9 5 2 -1 5 3 8 7 4) (lambda (x y) (> x y)))
[9 8 7 5 5 4 3 2 -1]))
+ ;; Sort a reversed list and vector.
+ (should (equal
+ (sort (reverse (number-sequence 1 1000)) (lambda (x y) (< x y)))
+ (number-sequence 1 1000)))
+ (should (equal
+ (sort (reverse (vconcat (number-sequence 1 1000)))
+ (lambda (x y) (< x y)))
+ (vconcat (number-sequence 1 1000))))
+ ;; Sort a constant list and vector.
+ (should (equal
+ (sort (make-vector 100 1) (lambda (x y) (> x y)))
+ (make-vector 100 1)))
+ (should (equal
+ (sort (append (make-vector 100 1) nil) (lambda (x y) (> x y)))
+ (append (make-vector 100 1) nil)))
+ ;; Sort a long list and vector with every pair reversed.
+ (let ((vec (make-vector 100000 nil))
+ (logxor-vec (make-vector 100000 nil)))
+ (dotimes (i 100000)
+ (aset logxor-vec i (logxor i 1))
+ (aset vec i i))
+ (should (equal
+ (sort logxor-vec (lambda (x y) (< x y)))
+ vec))
+ (should (equal
+ (sort (append logxor-vec nil) (lambda (x y) (< x y)))
+ (append vec nil))))
+ ;; Sort a list and vector with seven swaps.
+ (let ((vec (make-vector 100 nil))
+ (swap-vec (make-vector 100 nil)))
+ (dotimes (i 100)
+ (aset vec i (- i 50))
+ (aset swap-vec i (- i 50)))
+ (mapc (lambda (p)
+ (let ((tmp (elt swap-vec (car p))))
+ (aset swap-vec (car p) (elt swap-vec (cdr p)))
+ (aset swap-vec (cdr p) tmp)))
+ '((48 . 94) (75 . 77) (33 . 41) (92 . 52)
+ (10 . 96) (1 . 14) (43 . 81)))
+ (should (equal
+ (sort (copy-sequence swap-vec) (lambda (x y) (< x y)))
+ vec))
+ (should (equal
+ (sort (append swap-vec nil) (lambda (x y) (< x y)))
+ (append vec nil))))
+ ;; Check for possible corruption after GC.
+ (let* ((size 3000)
+ (complex-vec (make-vector size nil))
+ (vec (make-vector size nil))
+ (counter 0)
+ (my-counter (lambda ()
+ (if (< counter 500)
+ (cl-incf counter)
+ (setq counter 0)
+ (garbage-collect))))
+ (rand 1)
+ (generate-random
+ (lambda () (setq rand
+ (logand (+ (* rand 1103515245) 12345) 2147483647)))))
+ ;; Make a complex vector and its sorted version.
+ (dotimes (i size)
+ (let ((r (funcall generate-random)))
+ (aset complex-vec i (cons r "a"))
+ (aset vec i (cons r "a"))))
+ ;; Sort it.
+ (should (equal
+ (sort complex-vec
+ (lambda (x y) (funcall my-counter) (< (car x) (car y))))
+ (sort vec 'car-less-than-car))))
+ ;; Check for sorting stability.
(should (equal
(sort
(vector
@@ -151,45 +324,51 @@
'(9 . "ppp") '(8 . "ttt") '(8 . "eee") '(9 . "fff"))
(lambda (x y) (< (car x) (car y))))
[(8 . "xxx") (8 . "bbb") (8 . "ttt") (8 . "eee")
- (9 . "aaa") (9 . "zzz") (9 . "ppp") (9 . "fff")])))
+ (9 . "aaa") (9 . "zzz") (9 . "ppp") (9 . "fff")]))
+ ;; Bug#34104
+ (should (equal (should-error (sort "cba" #'<) :type 'wrong-type-argument)
+ '(wrong-type-argument list-or-vector-p "cba"))))
+
+(defvar w32-collate-ignore-punctuation)
(ert-deftest fns-tests-collate-sort ()
- ;; See https://lists.gnu.org/archive/html/emacs-devel/2015-10/msg02505.html.
- :expected-result (if (eq system-type 'cygwin) :failed :passed)
(skip-unless (fns-tests--collate-enabled-p))
;; Punctuation and whitespace characters are relevant for POSIX.
(should
(equal
- (sort '("11" "12" "1 1" "1 2" "1.1" "1.2")
+ (sort (list "11" "12" "1 1" "1 2" "1.1" "1.2")
(lambda (a b) (string-collate-lessp a b "POSIX")))
'("1 1" "1 2" "1.1" "1.2" "11" "12")))
;; Punctuation and whitespace characters are not taken into account
- ;; for collation in other locales.
- (should
- (equal
- (sort '("11" "12" "1 1" "1 2" "1.1" "1.2")
- (lambda (a b)
- (let ((w32-collate-ignore-punctuation t))
- (string-collate-lessp
- a b (if (eq system-type 'windows-nt) "enu_USA" "en_US.UTF-8")))))
- '("11" "1 1" "1.1" "12" "1 2" "1.2")))
+ ;; for collation in other locales, on MS-Windows systems.
+ (when (eq system-type 'windows-nt)
+ (should
+ (equal
+ (sort (list "11" "12" "1 1" "1 2" "1.1" "1.2")
+ (lambda (a b)
+ (let ((w32-collate-ignore-punctuation t))
+ (string-collate-lessp
+ a b "enu_USA"))))
+ '("11" "1 1" "1.1" "12" "1 2" "1.2"))))
;; Diacritics are different letters for POSIX, they sort lexicographical.
(should
(equal
- (sort '("Ævar" "Agustín" "Adrian" "Eli")
+ (sort (list "Ævar" "Agustín" "Adrian" "Eli")
(lambda (a b) (string-collate-lessp a b "POSIX")))
'("Adrian" "Agustín" "Eli" "Ævar")))
- ;; Diacritics are sorted between similar letters for other locales.
- (should
- (equal
- (sort '("Ævar" "Agustín" "Adrian" "Eli")
- (lambda (a b)
- (let ((w32-collate-ignore-punctuation t))
- (string-collate-lessp
- a b (if (eq system-type 'windows-nt) "enu_USA" "en_US.UTF-8")))))
- '("Adrian" "Ævar" "Agustín" "Eli"))))
+ ;; Diacritics are sorted between similar letters for other locales,
+ ;; on MS-Windows systems.
+ (when (eq system-type 'windows-nt)
+ (should
+ (equal
+ (sort (list "Ævar" "Agustín" "Adrian" "Eli")
+ (lambda (a b)
+ (let ((w32-collate-ignore-punctuation t))
+ (string-collate-lessp
+ a b "enu_USA"))))
+ '("Adrian" "Ævar" "Agustín" "Eli")))))
(ert-deftest fns-tests-string-version-lessp ()
(should (string-version-lessp "foo2.png" "foo12.png"))
@@ -198,7 +377,7 @@
(should (not (string-version-lessp "foo20000.png" "foo12.png")))
(should (string-version-lessp "foo.png" "foo2.png"))
(should (not (string-version-lessp "foo2.png" "foo.png")))
- (should (equal (sort '("foo12.png" "foo2.png" "foo1.png")
+ (should (equal (sort (list "foo12.png" "foo2.png" "foo1.png")
'string-version-lessp)
'("foo1.png" "foo2.png" "foo12.png")))
(should (string-version-lessp "foo2" "foo1234"))
@@ -214,11 +393,200 @@
(should (equal (func-arity 'format) '(1 . many)))
(require 'info)
(should (equal (func-arity 'Info-goto-node) '(1 . 3)))
- (should (equal (func-arity (lambda (&rest x))) '(0 . many)))
- (should (equal (func-arity (eval (lambda (x &optional y)) nil)) '(1 . 2)))
- (should (equal (func-arity (eval (lambda (x &optional y)) t)) '(1 . 2)))
+ (should (equal (func-arity (lambda (&rest _x))) '(0 . many)))
+ (should (equal (func-arity (eval '(lambda (_x &optional y)) nil)) '(1 . 2)))
+ (should (equal (func-arity (eval '(lambda (_x &optional y)) t)) '(1 . 2)))
(should (equal (func-arity 'let) '(1 . unevalled))))
+(defun fns-tests--string-repeat (s o)
+ (apply 'concat (make-list o s)))
+
+(defmacro fns-tests--with-region (funcname string &rest args)
+ "Apply FUNCNAME in a temp buffer on the region produced by STRING."
+ (declare (indent 1))
+ `(with-temp-buffer
+ (insert ,string)
+ (,funcname (point-min) (point-max) ,@args)
+ (buffer-string)))
+
+(ert-deftest fns-tests-base64-encode-region ()
+ ;; standard variant RFC2045
+ (should (equal (fns-tests--with-region base64-encode-region "") ""))
+ (should (equal (fns-tests--with-region base64-encode-region "f") "Zg=="))
+ (should (equal (fns-tests--with-region base64-encode-region "fo") "Zm8="))
+ (should (equal (fns-tests--with-region base64-encode-region "foo") "Zm9v"))
+ (should (equal (fns-tests--with-region base64-encode-region "foob") "Zm9vYg=="))
+ (should (equal (fns-tests--with-region base64-encode-region "fooba") "Zm9vYmE="))
+ (should (equal (fns-tests--with-region base64-encode-region "foobar") "Zm9vYmFy"))
+ (should (equal (fns-tests--with-region base64-encode-region "\x14\xfb\x9c\x03\xd9\x7e") "FPucA9l+"))
+ (should (equal (fns-tests--with-region base64-encode-region "\x14\xfb\x9c\x03\xd9\x7f") "FPucA9l/")))
+
+(ert-deftest fns-tests-base64-encode-string ()
+ ;; standard variant RFC2045
+ (should (equal (base64-encode-string "") ""))
+ (should (equal (base64-encode-string "f") "Zg=="))
+ (should (equal (base64-encode-string "fo") "Zm8="))
+ (should (equal (base64-encode-string "foo") "Zm9v"))
+ (should (equal (base64-encode-string "foob") "Zm9vYg=="))
+ (should (equal (base64-encode-string "fooba") "Zm9vYmE="))
+ (should (equal (base64-encode-string "foobar") "Zm9vYmFy"))
+ (should (equal (base64-encode-string "\x14\xfb\x9c\x03\xd9\x7e") "FPucA9l+"))
+ (should (equal (base64-encode-string "\x14\xfb\x9c\x03\xd9\x7f") "FPucA9l/"))
+
+ (should-error (base64-encode-string "ƒ"))
+ (should-error (base64-encode-string "ü")))
+
+(ert-deftest fns-test-base64url-encode-region ()
+ ;; url variant with padding
+ (should (equal (fns-tests--with-region base64url-encode-region "") ""))
+ (should (equal (fns-tests--with-region base64url-encode-region "f") "Zg=="))
+ (should (equal (fns-tests--with-region base64url-encode-region "fo") "Zm8="))
+ (should (equal (fns-tests--with-region base64url-encode-region "foo") "Zm9v"))
+ (should (equal (fns-tests--with-region base64url-encode-region "foob") "Zm9vYg=="))
+ (should (equal (fns-tests--with-region base64url-encode-region "fooba") "Zm9vYmE="))
+ (should (equal (fns-tests--with-region base64url-encode-region "foobar") "Zm9vYmFy"))
+ (should (equal (fns-tests--with-region base64url-encode-region "\x14\xfb\x9c\x03\xd9\x7e") "FPucA9l-"))
+ (should (equal (fns-tests--with-region base64url-encode-region "\x14\xfb\x9c\x03\xd9\x7f") "FPucA9l_"))
+
+ ;; url variant no padding
+ (should (equal (fns-tests--with-region base64url-encode-region "" t) ""))
+ (should (equal (fns-tests--with-region base64url-encode-region "f" t) "Zg"))
+ (should (equal (fns-tests--with-region base64url-encode-region "fo" t) "Zm8"))
+ (should (equal (fns-tests--with-region base64url-encode-region "foo" t) "Zm9v"))
+ (should (equal (fns-tests--with-region base64url-encode-region "foob" t) "Zm9vYg"))
+ (should (equal (fns-tests--with-region base64url-encode-region "fooba" t) "Zm9vYmE"))
+ (should (equal (fns-tests--with-region base64url-encode-region "foobar" t) "Zm9vYmFy"))
+ (should (equal (fns-tests--with-region base64url-encode-region "\x14\xfb\x9c\x03\xd9\x7e" t) "FPucA9l-"))
+ (should (equal (fns-tests--with-region base64url-encode-region "\x14\xfb\x9c\x03\xd9\x7f" t) "FPucA9l_"))
+
+
+ ;; url variant no line break no padding
+ (should (equal (fns-tests--with-region base64url-encode-region (fns-tests--string-repeat "f" 100) t)
+ (concat (fns-tests--string-repeat "Zm" 66) "Zg")))
+ (should (equal (fns-tests--with-region base64url-encode-region (fns-tests--string-repeat "fo" 50) t)
+ (concat (fns-tests--string-repeat "Zm9mb2Zv" 16) "Zm9mbw")))
+ (should (equal (fns-tests--with-region base64url-encode-region (fns-tests--string-repeat "foo" 25) t)
+ (fns-tests--string-repeat "Zm9v" 25)))
+ (should (equal (fns-tests--with-region base64url-encode-region (fns-tests--string-repeat "foob" 15) t)
+ (fns-tests--string-repeat "Zm9vYmZvb2Jmb29i" 5)))
+ (should (equal (fns-tests--with-region base64url-encode-region (fns-tests--string-repeat "fooba" 15) t)
+ (fns-tests--string-repeat "Zm9vYmFmb29iYWZvb2Jh" 5)))
+ (should (equal (fns-tests--with-region base64url-encode-region (fns-tests--string-repeat "foobar" 15) t)
+ (concat (fns-tests--string-repeat "Zm9vYmFyZm9vYmFy" 7) "Zm9vYmFy")))
+ (should (equal (fns-tests--with-region base64url-encode-region (fns-tests--string-repeat "\x14\xfb\x9c\x03\xd9\x7e" 10) t)
+ (fns-tests--string-repeat "FPucA9l-" 10)))
+ (should (equal (fns-tests--with-region base64url-encode-region (fns-tests--string-repeat "\x14\xfb\x9c\x03\xd9\x7f" 10) t)
+ (fns-tests--string-repeat "FPucA9l_" 10)))
+
+ (should-error (fns-tests--with-region base64url-encode-region "ƒ"))
+ (should-error (fns-tests--with-region base64url-encode-region "ü")))
+
+
+(ert-deftest fns-test-base64url-encode-string ()
+ ;; url variant with padding
+ (should (equal (base64url-encode-string "") ""))
+ (should (equal (base64url-encode-string "f") "Zg=="))
+ (should (equal (base64url-encode-string "fo") "Zm8="))
+ (should (equal (base64url-encode-string "foo") "Zm9v"))
+ (should (equal (base64url-encode-string "foob") "Zm9vYg=="))
+ (should (equal (base64url-encode-string "fooba") "Zm9vYmE="))
+ (should (equal (base64url-encode-string "foobar") "Zm9vYmFy"))
+ (should (equal (base64url-encode-string "\x14\xfb\x9c\x03\xd9\x7e") "FPucA9l-"))
+ (should (equal (base64url-encode-string "\x14\xfb\x9c\x03\xd9\x7f") "FPucA9l_"))
+
+ ;; url variant no padding
+ (should (equal (base64url-encode-string "" t) ""))
+ (should (equal (base64url-encode-string "f" t) "Zg"))
+ (should (equal (base64url-encode-string "fo" t) "Zm8"))
+ (should (equal (base64url-encode-string "foo" t) "Zm9v"))
+ (should (equal (base64url-encode-string "foob" t) "Zm9vYg"))
+ (should (equal (base64url-encode-string "fooba" t) "Zm9vYmE"))
+ (should (equal (base64url-encode-string "foobar" t) "Zm9vYmFy"))
+ (should (equal (base64url-encode-string "\x14\xfb\x9c\x03\xd9\x7e" t) "FPucA9l-"))
+ (should (equal (base64url-encode-string "\x14\xfb\x9c\x03\xd9\x7f" t) "FPucA9l_"))
+
+
+ ;; url variant no line break no padding
+ (should (equal (base64url-encode-string (fns-tests--string-repeat "f" 100) t) (concat (fns-tests--string-repeat "Zm" 66) "Zg")))
+ (should (equal (base64url-encode-string (fns-tests--string-repeat "fo" 50) t) (concat (fns-tests--string-repeat "Zm9mb2Zv" 16) "Zm9mbw")))
+ (should (equal (base64url-encode-string (fns-tests--string-repeat "foo" 25) t) (fns-tests--string-repeat "Zm9v" 25)))
+ (should (equal (base64url-encode-string (fns-tests--string-repeat "foob" 15) t) (fns-tests--string-repeat "Zm9vYmZvb2Jmb29i" 5)))
+ (should (equal (base64url-encode-string (fns-tests--string-repeat "fooba" 15) t) (fns-tests--string-repeat "Zm9vYmFmb29iYWZvb2Jh" 5)))
+ (should (equal (base64url-encode-string (fns-tests--string-repeat "foobar" 15) t) (concat (fns-tests--string-repeat "Zm9vYmFyZm9vYmFy" 7) "Zm9vYmFy")))
+ (should (equal (base64url-encode-string (fns-tests--string-repeat "\x14\xfb\x9c\x03\xd9\x7e" 10) t) (fns-tests--string-repeat "FPucA9l-" 10)))
+ (should (equal (base64url-encode-string (fns-tests--string-repeat "\x14\xfb\x9c\x03\xd9\x7f" 10) t) (fns-tests--string-repeat "FPucA9l_" 10)))
+
+ (should-error (base64url-encode-string "ƒ"))
+ (should-error (base64url-encode-string "ü")))
+
+(ert-deftest fns-tests-base64-decode-string ()
+ ;; standard variant RFC2045
+ (should (equal (base64-decode-string "") ""))
+ (should (equal (base64-decode-string "Zg==") "f"))
+ (should (equal (base64-decode-string "Zm8=") "fo"))
+ (should (equal (base64-decode-string "Zm9v") "foo"))
+ (should (equal (base64-decode-string "Zm9vYg==") "foob"))
+ (should (equal (base64-decode-string "Zm9vYmE=") "fooba"))
+ (should (equal (base64-decode-string "Zm9vYmFy") "foobar"))
+ (should (equal (base64-decode-string "FPucA9l+") "\x14\xfb\x9c\x03\xd9\x7e"))
+ (should (equal (base64-decode-string "FPucA9l/") "\x14\xfb\x9c\x03\xd9\x7f"))
+
+ ;; no padding
+ (should (equal (base64-decode-string "" t) ""))
+ (should (equal (base64-decode-string "Zg" t) "f"))
+ (should (equal (base64-decode-string "Zm8" t) "fo"))
+ (should (equal (base64-decode-string "Zm9v" t) "foo"))
+ (should (equal (base64-decode-string "Zm9vYg" t) "foob"))
+ (should (equal (base64-decode-string "Zm9vYmE" t) "fooba"))
+ (should (equal (base64-decode-string "Zm9vYmFy" t) "foobar"))
+
+ ;; url variant with padding
+ (should (equal (base64-decode-string "") ""))
+ (should (equal (base64-decode-string "Zg==" t) "f") )
+ (should (equal (base64-decode-string "Zm8=" t) "fo"))
+ (should (equal (base64-decode-string "Zm9v" t) "foo"))
+ (should (equal (base64-decode-string "Zm9vYg==" t) "foob"))
+ (should (equal (base64-decode-string "Zm9vYmE=" t) "fooba"))
+ (should (equal (base64-decode-string "Zm9vYmFy" t) "foobar"))
+ (should (equal (base64-decode-string "FPucA9l-" t) "\x14\xfb\x9c\x03\xd9\x7e"))
+ (should (equal (base64-decode-string "FPucA9l_" t) "\x14\xfb\x9c\x03\xd9\x7f"))
+
+ ;; url variant no padding
+ (should (equal (base64-decode-string "") ""))
+ (should (equal (base64-decode-string "Zg" t) "f"))
+ (should (equal (base64-decode-string "Zm8" t) "fo"))
+ (should (equal (base64-decode-string "Zm9v" t) "foo"))
+ (should (equal (base64-decode-string "Zm9vYg" t) "foob"))
+ (should (equal (base64-decode-string "Zm9vYmE" t) "fooba"))
+ (should (equal (base64-decode-string "Zm9vYmFy" t) "foobar"))
+ (should (equal (base64-decode-string "FPucA9l-" t) "\x14\xfb\x9c\x03\xd9\x7e"))
+ (should (equal (base64-decode-string "FPucA9l_" t) "\x14\xfb\x9c\x03\xd9\x7f"))
+
+
+ ;; url variant no line break no padding
+ (should (equal (base64-decode-string (concat (fns-tests--string-repeat "Zm" 66) "Zg") t)
+ (fns-tests--string-repeat "f" 100)))
+ (should (equal (base64-decode-string (concat (fns-tests--string-repeat "Zm9mb2Zv" 16) "Zm9mbw") t)
+ (fns-tests--string-repeat "fo" 50)))
+ (should (equal (base64-decode-string (fns-tests--string-repeat "Zm9v" 25) t)
+ (fns-tests--string-repeat "foo" 25)))
+ (should (equal (base64-decode-string (fns-tests--string-repeat "Zm9vYmZvb2Jmb29i" 5) t)
+ (fns-tests--string-repeat "foob" 15)))
+ (should (equal (base64-decode-string (fns-tests--string-repeat "Zm9vYmFmb29iYWZvb2Jh" 5) t)
+ (fns-tests--string-repeat "fooba" 15)))
+ (should (equal (base64-decode-string (concat (fns-tests--string-repeat "Zm9vYmFyZm9vYmFy" 7) "Zm9vYmFy") t)
+ (fns-tests--string-repeat "foobar" 15)))
+ (should (equal (base64-decode-string (fns-tests--string-repeat "FPucA9l-" 10) t)
+ (fns-tests--string-repeat "\x14\xfb\x9c\x03\xd9\x7e" 10)))
+ (should (equal (base64-decode-string (fns-tests--string-repeat "FPucA9l_" 10) t)
+ (fns-tests--string-repeat "\x14\xfb\x9c\x03\xd9\x7f" 10)))
+
+ ;; errors check
+ (should (eq :got-error (condition-case () (base64-decode-string "Zg=") (error :got-error))))
+ (should (eq :got-error (condition-case () (base64-decode-string "Zm9vYmE") (error :got-error))))
+ (should (eq :got-error (condition-case () (base64-decode-string "Zm9vYmFy=") (error :got-error))))
+ (should (eq :got-error (condition-case () (base64-decode-string "Zg=Zg=") (error :got-error)))))
+
(ert-deftest fns-tests-hash-buffer ()
(should (equal (sha1 "foo") "0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33"))
(should (equal (with-temp-buffer
@@ -235,13 +603,30 @@
(buffer-hash))
(sha1 "foo"))))
+(ert-deftest fns-tests-mapconcat ()
+ (should (string= (mapconcat #'identity '()) ""))
+ (should (string= (mapconcat #'identity '("a" "b")) "ab"))
+ (should (string= (mapconcat #'identity '() "_") ""))
+ (should (string= (mapconcat #'identity '("A") "_") "A"))
+ (should (string= (mapconcat #'identity '("A" "B") "_") "A_B"))
+ (should (string= (mapconcat #'identity '("A" "B" "C") "_") "A_B_C"))
+ ;; non-ASCII strings
+ (should (string= (mapconcat #'identity '("Ä" "ø" "☭" "தமிழ்") "_漢字_")
+ "Ä_漢字_ø_漢字_☭_漢字_தமிழ்"))
+ ;; vector
+ (should (string= (mapconcat #'identity ["a" "b"]) "ab"))
+ ;; bool-vector
+ (should (string= (mapconcat #'identity [nil nil]) ""))
+ (should-error (mapconcat #'identity [nil nil t])
+ :type 'wrong-type-argument))
+
(ert-deftest fns-tests-mapcan ()
(should-error (mapcan))
(should-error (mapcan #'identity))
(should-error (mapcan #'identity (make-char-table 'foo)))
- (should (equal (mapcan #'list '(1 2 3)) '(1 2 3)))
+ (should (equal (mapcan #'list (list 1 2 3)) '(1 2 3)))
;; `mapcan' is destructive
- (let ((data '((foo) (bar))))
+ (let ((data (list (list 'foo) (list 'bar))))
(should (equal (mapcan #'identity data) '(foo bar)))
(should (equal data '((foo bar) (bar))))))
@@ -467,24 +852,6 @@
(should-not (plist-get d1 3))
(should-not (plist-get d2 3))))
-(ert-deftest test-cycle-lax-plist-get ()
- (let ((c1 (cyc1 1))
- (c2 (cyc2 1 2))
- (d1 (dot1 1))
- (d2 (dot2 1 2)))
- (should (lax-plist-get c1 1))
- (should (lax-plist-get c2 1))
- (should (lax-plist-get d1 1))
- (should (lax-plist-get d2 1))
- (should-error (lax-plist-get c1 2) :type 'circular-list)
- (should (lax-plist-get c2 2))
- (should-error (lax-plist-get d1 2) :type 'wrong-type-argument)
- (should (lax-plist-get d2 2))
- (should-error (lax-plist-get c1 3) :type 'circular-list)
- (should-error (lax-plist-get c2 3) :type 'circular-list)
- (should-error (lax-plist-get d1 3) :type 'wrong-type-argument)
- (should-error (lax-plist-get d2 3) :type 'wrong-type-argument)))
-
(ert-deftest test-cycle-plist-member ()
(let ((c1 (cyc1 1))
(c2 (cyc2 1 2))
@@ -521,24 +888,6 @@
(should-error (plist-put d1 3 3) :type 'wrong-type-argument)
(should-error (plist-put d2 3 3) :type 'wrong-type-argument)))
-(ert-deftest test-cycle-lax-plist-put ()
- (let ((c1 (cyc1 1))
- (c2 (cyc2 1 2))
- (d1 (dot1 1))
- (d2 (dot2 1 2)))
- (should (lax-plist-put c1 1 1))
- (should (lax-plist-put c2 1 1))
- (should (lax-plist-put d1 1 1))
- (should (lax-plist-put d2 1 1))
- (should-error (lax-plist-put c1 2 2) :type 'circular-list)
- (should (lax-plist-put c2 2 2))
- (should-error (lax-plist-put d1 2 2) :type 'wrong-type-argument)
- (should (lax-plist-put d2 2 2))
- (should-error (lax-plist-put c1 3 3) :type 'circular-list)
- (should-error (lax-plist-put c2 3 3) :type 'circular-list)
- (should-error (lax-plist-put d1 3 3) :type 'wrong-type-argument)
- (should-error (lax-plist-put d2 3 3) :type 'wrong-type-argument)))
-
(ert-deftest test-cycle-equal ()
(should-error (equal (cyc1 1) (cyc1 1)))
(should-error (equal (cyc2 1 2) (cyc2 1 2))))
@@ -548,31 +897,529 @@
(should-error (nconc (cyc2 1 2) 'tail) :type 'circular-list))
(ert-deftest plist-get/odd-number-of-elements ()
- "Test that ‘plist-get’ doesn’t signal an error on degenerate plists."
+ "Test that `plist-get' doesn't signal an error on degenerate plists."
(should-not (plist-get '(:foo 1 :bar) :bar)))
-(ert-deftest lax-plist-get/odd-number-of-elements ()
- "Check for https://debbugs.gnu.org/cgi/bugreport.cgi?bug=27726."
- (should (equal (should-error (lax-plist-get '(:foo 1 :bar) :bar)
- :type 'wrong-type-argument)
- '(wrong-type-argument plistp (:foo 1 :bar)))))
-
(ert-deftest plist-put/odd-number-of-elements ()
"Check for https://debbugs.gnu.org/cgi/bugreport.cgi?bug=27726."
(should (equal (should-error (plist-put '(:foo 1 :bar) :zot 2)
:type 'wrong-type-argument)
'(wrong-type-argument plistp (:foo 1 :bar)))))
-(ert-deftest lax-plist-put/odd-number-of-elements ()
- "Check for https://debbugs.gnu.org/cgi/bugreport.cgi?bug=27726."
- (should (equal (should-error (lax-plist-put '(:foo 1 :bar) :zot 2)
- :type 'wrong-type-argument)
- '(wrong-type-argument plistp (:foo 1 :bar)))))
-
(ert-deftest plist-member/improper-list ()
"Check for https://debbugs.gnu.org/cgi/bugreport.cgi?bug=27726."
(should (equal (should-error (plist-member '(:foo 1 . :bar) :qux)
:type 'wrong-type-argument)
'(wrong-type-argument plistp (:foo 1 . :bar)))))
-(provide 'fns-tests)
+(ert-deftest test-string-distance ()
+ "Test `string-distance' behavior."
+ ;; ASCII characters are always fine
+ (should (equal 1 (string-distance "heelo" "hello")))
+ (should (equal 2 (string-distance "aeelo" "hello")))
+ (should (equal 0 (string-distance "ab" "ab" t)))
+ (should (equal 1 (string-distance "ab" "abc" t)))
+
+ ;; string containing hanzi character, compare by byte
+ (should (equal 6 (string-distance "ab" "ab我她" t)))
+ (should (equal 3 (string-distance "ab" "a我b" t)))
+ (should (equal 3 (string-distance "我" "她" t)))
+
+ ;; string containing hanzi character, compare by character
+ (should (equal 2 (string-distance "ab" "ab我她")))
+ (should (equal 1 (string-distance "ab" "a我b")))
+ (should (equal 1 (string-distance "我" "她")))
+
+ ;; correct behavior with empty strings
+ (should (equal 0 (string-distance "" "")))
+ (should (equal 0 (string-distance "" "" t)))
+ (should (equal 1 (string-distance "x" "")))
+ (should (equal 1 (string-distance "x" "" t)))
+ (should (equal 1 (string-distance "" "x")))
+ (should (equal 1 (string-distance "" "x" t))))
+
+(ert-deftest test-bignum-eql ()
+ "Test that `eql' works for bignums."
+ (let ((x (+ most-positive-fixnum 1))
+ (y (+ most-positive-fixnum 1)))
+ (should (eq x x))
+ (should (eql x y))
+ (should (equal x y))
+ (should-not (eql x 0.0e+NaN))
+ (should (memql x (list y)))))
+
+(ert-deftest test-bignum-hash ()
+ "Test that hash tables work for bignums."
+ ;; Make two bignums that are eql but not eq.
+ (let ((b1 (1+ most-positive-fixnum))
+ (b2 (1+ most-positive-fixnum)))
+ (dolist (test '(eq eql equal))
+ (let ((hash (make-hash-table :test test)))
+ (puthash b1 t hash)
+ (should (eq (gethash b2 hash)
+ (funcall test b1 b2)))))))
+
+(ert-deftest test-nthcdr-simple ()
+ (should (eq (nthcdr 0 'x) 'x))
+ (should (eq (nthcdr 1 '(x . y)) 'y))
+ (should (eq (nthcdr 2 '(x y . z)) 'z)))
+
+(ert-deftest test-nthcdr-circular ()
+ (dolist (len '(1 2 5 37 120 997 1024))
+ (let ((cycle (make-list len nil)))
+ (setcdr (last cycle) cycle)
+ (dolist (n (list (1- most-negative-fixnum) most-negative-fixnum
+ -1 0 1
+ (1- len) len (1+ len)
+ most-positive-fixnum (1+ most-positive-fixnum)
+ (* 2 most-positive-fixnum)
+ (* most-positive-fixnum most-positive-fixnum)
+ (ash 1 12345)))
+ (let ((a (nthcdr n cycle))
+ (b (if (<= n 0) cycle (nthcdr (mod n len) cycle))))
+ (should (equal (list (eq a b) n len)
+ (list t n len))))))))
+
+(ert-deftest test-proper-list-p ()
+ "Test `proper-list-p' behavior."
+ (dotimes (length 4)
+ ;; Proper and dotted lists.
+ (let ((list (make-list length 0)))
+ (should (= (proper-list-p list) length))
+ (should (not (proper-list-p (nconc list 0)))))
+ ;; Circular lists.
+ (dotimes (n (1+ length))
+ (let ((circle (make-list (1+ length) 0)))
+ (should (not (proper-list-p (nconc circle (nthcdr n circle))))))))
+ ;; Atoms.
+ (should (not (proper-list-p 0)))
+ (should (not (proper-list-p "")))
+ (should (not (proper-list-p [])))
+ (should (not (proper-list-p (make-bool-vector 0 nil))))
+ (should (not (proper-list-p (make-symbol "a")))))
+
+(ert-deftest test-hash-function-that-mutates-hash-table ()
+ (define-hash-table-test 'badeq 'eq 'bad-hash)
+ (let ((h (make-hash-table :test 'badeq :size 1 :rehash-size 1)))
+ (defun bad-hash (k)
+ (if (eq k 100)
+ (clrhash h))
+ (sxhash-eq k))
+ (should-error
+ (dotimes (k 200)
+ (puthash k k h)))
+ (should (= 100 (hash-table-count h)))))
+
+(ert-deftest test-sxhash-equal ()
+ (should (= (sxhash-equal (* most-positive-fixnum most-negative-fixnum))
+ (sxhash-equal (* most-positive-fixnum most-negative-fixnum))))
+ (should (= (sxhash-equal (make-string 1000 ?a))
+ (sxhash-equal (make-string 1000 ?a))))
+ (should (= (sxhash-equal (point-marker))
+ (sxhash-equal (point-marker))))
+ (should (= (sxhash-equal (make-vector 1000 (make-string 10 ?a)))
+ (sxhash-equal (make-vector 1000 (make-string 10 ?a)))))
+ (should (= (sxhash-equal (make-bool-vector 1000 t))
+ (sxhash-equal (make-bool-vector 1000 t))))
+ (should (= (sxhash-equal (make-char-table nil (make-string 10 ?a)))
+ (sxhash-equal (make-char-table nil (make-string 10 ?a)))))
+ (should (= (sxhash-equal (record 'a (make-string 10 ?a)))
+ (sxhash-equal (record 'a (make-string 10 ?a))))))
+
+(ert-deftest test-secure-hash ()
+ (should (equal (secure-hash 'md5 "foobar")
+ "3858f62230ac3c915f300c664312c63f"))
+ (should (equal (secure-hash 'sha1 "foobar")
+ "8843d7f92416211de9ebb963ff4ce28125932878"))
+ (should (equal (secure-hash 'sha224 "foobar")
+ "de76c3e567fca9d246f5f8d3b2e704a38c3c5e258988ab525f941db8"))
+ (should (equal (secure-hash 'sha256 "foobar")
+ (concat "c3ab8ff13720e8ad9047dd39466b3c89"
+ "74e592c2fa383d4a3960714caef0c4f2")))
+ (should (equal (secure-hash 'sha384 "foobar")
+ (concat "3c9c30d9f665e74d515c842960d4a451c83a0125fd3de739"
+ "2d7b37231af10c72ea58aedfcdf89a5765bf902af93ecf06")))
+ (should (equal (secure-hash 'sha512 "foobar")
+ (concat "0a50261ebd1a390fed2bf326f2673c145582a6342d5"
+ "23204973d0219337f81616a8069b012587cf5635f69"
+ "25f1b56c360230c19b273500ee013e030601bf2425")))
+ ;; Test that a call to getrandom returns the right format.
+ ;; This does not test randomness; it's merely a format check.
+ (should (string-match "\\`[0-9a-f]\\{128\\}\\'"
+ (secure-hash 'sha512 'iv-auto 100))))
+
+(ert-deftest test-vector-delete ()
+ (let ((v1 (make-vector 1000 1)))
+ (should (equal (delete t [nil t]) [nil]))
+ (should (equal (delete 1 v1) (vector)))
+ (should (equal (delete 2 v1) v1))))
+
+(ert-deftest string-search ()
+ (should (equal (string-search "zot" "foobarzot") 6))
+ (should (equal (string-search "foo" "foobarzot") 0))
+ (should (not (string-search "fooz" "foobarzot")))
+ (should (not (string-search "zot" "foobarzo")))
+ (should (equal (string-search "ab" "ab") 0))
+ (should (equal (string-search "ab\0" "ab") nil))
+ (should (equal (string-search "ab" "abababab" 3) 4))
+ (should (equal (string-search "ab" "ababac" 3) nil))
+ (should (equal (string-search "aaa" "aa") nil))
+ (let ((case-fold-search t))
+ (should (equal (string-search "ab" "AB") nil)))
+
+ (should (equal
+ (string-search (make-string 2 130)
+ (concat "helló" (make-string 5 130 t) "bár"))
+ 5))
+ (should (equal
+ (string-search (make-string 2 127)
+ (concat "helló" (make-string 5 127 t) "bár"))
+ 5))
+
+ (should (equal (string-search "\377" "a\377ø") 1))
+ (should (equal (string-search "\377" "a\377a") 1))
+
+ (should (not (string-search (make-string 1 255) "a\377ø")))
+ (should (not (string-search (make-string 1 255) "a\377a")))
+
+ (should (equal (string-search "fóo" "zotfóo") 3))
+
+ (should (equal (string-search (string-to-multibyte "\377") "ab\377c") 2))
+ (should (equal (string-search "\303" "aøb") nil))
+ (should (equal (string-search "\270" "aøb") nil))
+ (should (equal (string-search "ø" "\303\270") nil))
+ (should (equal (string-search "ø" (make-string 32 ?a)) nil))
+ (should (equal (string-search "ø" (string-to-multibyte (make-string 32 ?a)))
+ nil))
+ (should (equal (string-search "o" (string-to-multibyte
+ (apply #'string
+ (number-sequence ?a ?z))))
+ 14))
+
+ (should (equal (string-search "a\U00010f98z" "a\U00010f98a\U00010f98z") 2))
+
+ (should-error (string-search "a" "abc" -1))
+ (should-error (string-search "a" "abc" 4))
+ (should-error (string-search "a" "abc" 100000000000))
+
+ (should (equal (string-search "a" "aaa" 3) nil))
+ (should (equal (string-search "aa" "aa" 1) nil))
+ (should (equal (string-search "\0" "") nil))
+
+ (should (equal (string-search "" "") 0))
+ (should-error (string-search "" "" 1))
+ (should (equal (string-search "" "abc") 0))
+ (should (equal (string-search "" "abc" 2) 2))
+ (should (equal (string-search "" "abc" 3) 3))
+ (should-error (string-search "" "abc" 4))
+ (should-error (string-search "" "abc" -1))
+
+ (should-not (string-search "ø" "foo\303\270"))
+ (should-not (string-search "\303\270" "ø"))
+ (should-not (string-search "\370" "ø"))
+ (should-not (string-search (string-to-multibyte "\370") "ø"))
+ (should-not (string-search "ø" "\370"))
+ (should-not (string-search "ø" (string-to-multibyte "\370")))
+ (should-not (string-search "\303\270" "\370"))
+ (should-not (string-search (string-to-multibyte "\303\270") "\370"))
+ (should-not (string-search "\303\270" (string-to-multibyte "\370")))
+ (should-not (string-search (string-to-multibyte "\303\270")
+ (string-to-multibyte "\370")))
+ (should-not (string-search "\370" "\303\270"))
+ (should-not (string-search (string-to-multibyte "\370") "\303\270"))
+ (should-not (string-search "\370" (string-to-multibyte "\303\270")))
+ (should-not (string-search (string-to-multibyte "\370")
+ (string-to-multibyte "\303\270")))
+ (should (equal (string-search (string-to-multibyte "o\303\270") "foo\303\270")
+ 2))
+ (should (equal (string-search "\303\270" "foo\303\270") 3)))
+
+(ert-deftest object-intervals ()
+ (should (equal (object-intervals (propertize "foo" 'bar 'zot))
+ '((0 3 (bar zot)))))
+ (should (equal (object-intervals (concat (propertize "foo" 'bar 'zot)
+ (propertize "foo" 'gazonk "gazonk")))
+ '((0 3 (bar zot)) (3 6 (gazonk "gazonk")))))
+ (should (equal
+ (with-temp-buffer
+ (insert "foobar")
+ (put-text-property 1 3 'foo 1)
+ (put-text-property 3 6 'bar 2)
+ (put-text-property 2 5 'zot 3)
+ (object-intervals (current-buffer)))
+ '((0 1 (foo 1)) (1 2 (zot 3 foo 1)) (2 4 (zot 3 bar 2))
+ (4 5 (bar 2)) (5 6 nil)))))
+
+(ert-deftest length-equals-tests ()
+ (should-not (length< (list 1 2 3) 2))
+ (should-not (length< (list 1 2 3) 3))
+ (should (length< (list 1 2 3) 4))
+
+ (should-not (length< "abc" 2))
+ (should-not (length< "abc" 3))
+ (should (length< "abc" 4))
+
+ (should (length> (list 1 2 3) 2))
+ (should-not (length> (list 1 2 3) 3))
+ (should-not (length> (list 1 2 3) 4))
+
+ (should (length> "abc" 2))
+ (should-not (length> "abc" 3))
+ (should-not (length> "abc" 4))
+
+ (should-not (length= (list 1 2 3) 2))
+ (should (length= (list 1 2 3) 3))
+ (should-not (length= (list 1 2 3) 4))
+
+ (should-not (length= "abc" 2))
+ (should (length= "abc" 3))
+ (should-not (length= "abc" 4))
+
+ (should-not (length< (list 1 2 3) -1))
+ (should-not (length< (list 1 2 3) 0))
+ (should-not (length< (list 1 2 3) -10))
+
+ (should (length> (list 1 2 3) -1))
+ (should (length> (list 1 2 3) 0))
+
+ (should-not (length= (list 1 2 3) -1))
+ (should-not (length= (list 1 2 3) 0))
+ (should-not (length= (list 1 2 3) 1))
+
+ (should-error
+ (let ((list (list 1)))
+ (setcdr list list)
+ (length< list #x1fffe))))
+
+(defun approx-equal (list1 list2)
+ (and (equal (length list1) (length list2))
+ (cl-loop for v1 in list1
+ for v2 in list2
+ when (not (or (= v1 v2)
+ (< (abs (- v1 v2)) 0.1)))
+ return nil
+ finally return t)))
+
+(ert-deftest test-buffer-line-stats-nogap ()
+ (with-temp-buffer
+ (insert "")
+ (should (approx-equal (buffer-line-statistics) '(0 0 0))))
+ (with-temp-buffer
+ (insert "123\n")
+ (should (approx-equal (buffer-line-statistics) '(1 3 3))))
+ (with-temp-buffer
+ (insert "123\n12345\n123\n")
+ (should (approx-equal (buffer-line-statistics) '(3 5 3.66))))
+ (with-temp-buffer
+ (insert "123\n12345\n123")
+ (should (approx-equal (buffer-line-statistics) '(3 5 3.66))))
+ (with-temp-buffer
+ (insert "123\n12345")
+ (should (approx-equal (buffer-line-statistics) '(2 5 4))))
+
+ (with-temp-buffer
+ (insert "123\n12é45\n123\n")
+ (should (approx-equal (buffer-line-statistics) '(3 6 4))))
+
+ (with-temp-buffer
+ (insert "\n\n\n")
+ (should (approx-equal (buffer-line-statistics) '(3 0 0)))))
+
+(ert-deftest test-buffer-line-stats-gap ()
+ (with-temp-buffer
+ (dotimes (_ 1000)
+ (insert "12345678901234567890123456789012345678901234567890\n"))
+ (goto-char (point-min))
+ ;; This should make a gap appear.
+ (insert "123\n")
+ (delete-region (point-min) (point))
+ (should (approx-equal (buffer-line-statistics) '(1000 50 50.0))))
+ (with-temp-buffer
+ (dotimes (_ 1000)
+ (insert "12345678901234567890123456789012345678901234567890\n"))
+ (goto-char (point-min))
+ (insert "123\n")
+ (should (approx-equal (buffer-line-statistics) '(1001 50 49.9))))
+ (with-temp-buffer
+ (dotimes (_ 1000)
+ (insert "12345678901234567890123456789012345678901234567890\n"))
+ (goto-char (point-min))
+ (insert "123\n")
+ (goto-char (point-max))
+ (insert "fóo")
+ (should (approx-equal (buffer-line-statistics) '(1002 50 49.9)))))
+
+(ert-deftest test-line-number-at-position ()
+ (with-temp-buffer
+ (insert (make-string 10 ?\n))
+ (should (= (line-number-at-pos (point)) 11))
+ (should (= (line-number-at-pos nil) 11))
+ (should-error (line-number-at-pos -1))
+ (should-error (line-number-at-pos 100))))
+
+(defun fns-tests-concat (&rest args)
+ ;; Dodge the byte-compiler's partial evaluation of `concat' with
+ ;; constant arguments.
+ (apply #'concat args))
+
+(ert-deftest fns-concat ()
+ (should (equal (fns-tests-concat) ""))
+ (should (equal (fns-tests-concat "") ""))
+ (should (equal (fns-tests-concat nil) ""))
+ (should (equal (fns-tests-concat []) ""))
+ (should (equal (fns-tests-concat [97 98]) "ab"))
+ (should (equal (fns-tests-concat '(97 98)) "ab"))
+ (should (equal (fns-tests-concat "ab" '(99 100) nil [101 102] "gh")
+ "abcdefgh"))
+ (should (equal (fns-tests-concat "Ab" "\200" "cd") "Ab\200cd"))
+ (should (equal (fns-tests-concat "aB" "\200" "çd") "aB\200çd"))
+ (should (equal (fns-tests-concat "AB" (string-to-multibyte "\200") "cd")
+ (string-to-multibyte "AB\200cd")))
+ (should (equal (fns-tests-concat "ab" '(#xe5) [255] "cd") "abåÿcd"))
+ (should (equal (fns-tests-concat '(#x3fffff) [#x3fff80] "xy") "\377\200xy"))
+ (should (equal (fns-tests-concat '(#x3fffff) [#x3fff80] "xy§") "\377\200xy§"))
+ (should (equal-including-properties
+ (fns-tests-concat #("abc" 0 3 (a 1)) #("de" 0 2 (a 1)))
+ #("abcde" 0 5 (a 1))))
+ (should (equal-including-properties
+ (fns-tests-concat #("abc" 0 3 (a 1)) "§ü" #("çå" 0 2 (b 2)))
+ #("abc§üçå" 0 3 (a 1) 5 7 (b 2))))
+ (should-error (fns-tests-concat "a" '(98 . 99))
+ :type 'wrong-type-argument)
+ (let ((loop (list 66 67)))
+ (setcdr (cdr loop) loop)
+ (should-error (fns-tests-concat "A" loop)
+ :type 'circular-list)))
+
+(ert-deftest fns-vconcat ()
+ (should (equal (vconcat) []))
+ (should (equal (vconcat nil) []))
+ (should (equal (vconcat "") []))
+ (should (equal (vconcat [1 2 3]) [1 2 3]))
+ (should (equal (vconcat '(1 2 3)) [1 2 3]))
+ (should (equal (vconcat "ABC") [65 66 67]))
+ (should (equal (vconcat "ü§") [252 167]))
+ (should (equal (vconcat [1 2 3] nil '(4 5) "AB" "å"
+ "\377" (string-to-multibyte "\377")
+ (bool-vector t nil nil t nil))
+ [1 2 3 4 5 65 66 #xe5 255 #x3fffff t nil nil t nil]))
+ (should-error (vconcat [1] '(2 . 3))
+ :type 'wrong-type-argument)
+ (let ((loop (list 1 2)))
+ (setcdr (cdr loop) loop)
+ (should-error (vconcat [1] loop)
+ :type 'circular-list)))
+
+(ert-deftest fns-append ()
+ (should (equal (append) nil))
+ (should (equal (append 'tail) 'tail))
+ (should (equal (append [1 2 3] nil '(4 5) "AB" "å"
+ "\377" (string-to-multibyte "\377")
+ (bool-vector t nil nil t nil)
+ '(9 10))
+ '(1 2 3 4 5 65 66 #xe5 255 #x3fffff t nil nil t nil 9 10)))
+ (should (equal (append '(1 2) '(3 4) 'tail)
+ '(1 2 3 4 . tail)))
+ (should-error (append '(1 . 2) '(3))
+ :type 'wrong-type-argument)
+ (let ((loop (list 1 2)))
+ (setcdr (cdr loop) loop)
+ (should-error (append loop '(end))
+ :type 'circular-list)))
+
+(ert-deftest test-plist ()
+ (let ((plist '(:a "b")))
+ (setq plist (plist-put plist :b "c"))
+ (should (equal (plist-get plist :b) "c"))
+ (should (equal (plist-member plist :b) '(:b "c"))))
+
+ (let ((plist '("1" "2" "a" "b")))
+ (setq plist (plist-put plist (copy-sequence "a") "c"))
+ (should-not (equal (plist-get plist (copy-sequence "a")) "c"))
+ (should-not (equal (plist-member plist (copy-sequence "a")) '("a" "c"))))
+
+ (let ((plist '("1" "2" "a" "b")))
+ (setq plist (plist-put plist (copy-sequence "a") "c" #'equal))
+ (should (equal (plist-get plist (copy-sequence "a") #'equal) "c"))
+ (should (equal (plist-member plist (copy-sequence "a") #'equal)
+ '("a" "c")))))
+
+(ert-deftest fns--string-to-unibyte-multibyte ()
+ (dolist (str (list "" "a" "abc" "a\x00\x7fz" "a\xaa\xbbz" "\x80\xdd\xff"
+ (apply #'unibyte-string (number-sequence 0 255))))
+ (ert-info ((prin1-to-string str) :prefix "str: ")
+ (should-not (multibyte-string-p str))
+ (let* ((u (string-to-unibyte str)) ; should be identity
+ (m (string-to-multibyte u)) ; lossless conversion
+ (mm (string-to-multibyte m)) ; should be identity
+ (uu (string-to-unibyte m)) ; also lossless
+ (ml (mapcar (lambda (c) (if (<= c #x7f) c (+ c #x3fff00))) u)))
+ (should-not (multibyte-string-p u))
+ (should (multibyte-string-p m))
+ (should (multibyte-string-p mm))
+ (should-not (multibyte-string-p uu))
+ (should (equal str u))
+ (should (equal m mm))
+ (should (equal str uu))
+ (should (equal (append m nil) ml)))))
+ (should-error (string-to-unibyte "å"))
+ (should-error (string-to-unibyte "ABC∀BC")))
+
+(defun fns-tests--take-ref (n list)
+ "Reference implementation of `take'."
+ (named-let loop ((m n) (tail list) (ac nil))
+ (if (and (> m 0) tail)
+ (loop (1- m) (cdr tail) (cons (car tail) ac))
+ (nreverse ac))))
+
+(ert-deftest fns--take-ntake ()
+ "Test `take' and `ntake'."
+ ;; Check errors and edge cases.
+ (should-error (take 'x '(a)))
+ (should-error (ntake 'x '(a)))
+ (should-error (take 1 'a))
+ (should-error (ntake 1 'a))
+ (should-error (take 2 '(a . b)))
+ (should-error (ntake 2 '(a . b)))
+ ;; Tolerate non-lists for a count of zero.
+ (should (equal (take 0 'a) nil))
+ (should (equal (ntake 0 'a) nil))
+ ;; But not non-numbers for empty lists.
+ (should-error (take 'x nil))
+ (should-error (ntake 'x nil))
+
+ (dolist (list '(nil (a) (a b) (a b c) (a b c d) (a . b) (a b . c)))
+ (ert-info ((prin1-to-string list) :prefix "list: ")
+ (let ((max (if (proper-list-p list)
+ (+ 2 (length list))
+ (safe-length list))))
+ (dolist (n (number-sequence -1 max))
+ (ert-info ((prin1-to-string n) :prefix "n: ")
+ (let* ((l (copy-tree list))
+ (ref (fns-tests--take-ref n l)))
+ (should (equal (take n l) ref))
+ (should (equal l list))
+ (should (equal (ntake n l) ref))))))))
+
+ ;; Circular list.
+ (let ((list (list 'a 'b 'c)))
+ (setcdr (nthcdr 2 list) (cdr list)) ; list now (a b c b c b c ...)
+ (should (equal (take 0 list) nil))
+ (should (equal (take 1 list) '(a)))
+ (should (equal (take 2 list) '(a b)))
+ (should (equal (take 3 list) '(a b c)))
+ (should (equal (take 4 list) '(a b c b)))
+ (should (equal (take 5 list) '(a b c b c)))
+ (should (equal (take 10 list) '(a b c b c b c b c b)))
+
+ (should (equal (ntake 10 list) '(a b))))
+
+ ;; Bignum N argument.
+ (let ((list (list 'a 'b 'c)))
+ (should (equal (take (+ most-positive-fixnum 1) list) '(a b c)))
+ (should (equal (take (- most-negative-fixnum 1) list) nil))
+ (should (equal (ntake (+ most-positive-fixnum 1) list) '(a b c)))
+ (should (equal (ntake (- most-negative-fixnum 1) list) nil))
+ (should (equal list '(a b c)))))
+
+;;; fns-tests.el ends here
diff --git a/test/src/font-tests.el b/test/src/font-tests.el
index d86139b0f19..7e9669c6513 100644
--- a/test/src/font-tests.el
+++ b/test/src/font-tests.el
@@ -1,6 +1,6 @@
-;;; font-tests.el --- Test suite for font-related functions.
+;;; font-tests.el --- Test suite for font-related functions. -*- lexical-binding: t -*-
-;; Copyright (C) 2011-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2022 Free Software Foundation, Inc.
;; Author: Chong Yidong <cyd@stupidchicken.com>
;; Keywords: internal
@@ -96,8 +96,7 @@ expected font properties from parsing NAME.")
(put 'font-parse-check 'ert-explainer 'font-parse-explain)
(defun font-parse-explain (name prop expected)
- (let ((result (font-get (font-spec :name name) prop))
- (propname (symbol-name prop)))
+ (let ((propname (symbol-name prop)))
(format "Parsing `%s': expected %s `%s', got `%s'."
name (substring propname 1) expected
(font-get (font-spec :name name) prop))))
@@ -159,9 +158,30 @@ expected font properties from parsing NAME.")
(insert "\n"))))
(goto-char (point-min)))
-;; Local Variables:
-;; no-byte-compile: t
-;; End:
+(ert-deftest font-parse-xlfd-test ()
+ ;; Normal number of segments.
+ (should (equal (font-get
+ (font-spec :name "-GNU -FreeSans-semibold-italic-normal-*-*-*-*-*-*-0-iso10646-1")
+ :family)
+ 'FreeSans))
+ (should (equal (font-get
+ (font-spec :name "-GNU -FreeSans-semibold-italic-normal-*-*-*-*-*-*-0-iso10646-1")
+ :foundry)
+ 'GNU\ ))
+ ;; Dash in the family name.
+ (should (equal (font-get
+ (font-spec :name "-Take-mikachan-PS-normal-normal-normal-*-*-*-*-*-*-0-iso10646-1")
+ :family)
+ 'mikachan-PS))
+ (should (equal (font-get
+ (font-spec :name "-Take-mikachan-PS-normal-normal-normal-*-*-*-*-*-*-0-iso10646-1")
+ :weight)
+ 'normal))
+ ;; Synthetic test.
+ (should (equal (font-get
+ (font-spec :name "-foundry-name-with-lots-of-dashes-normal-normal-normal-*-*-*-*-*-*-0-iso10646-1")
+ :family)
+ 'name-with-lots-of-dashes)))
(provide 'font-tests)
;;; font-tests.el ends here.
diff --git a/test/src/image-tests.el b/test/src/image-tests.el
new file mode 100644
index 00000000000..d1a4dad37b9
--- /dev/null
+++ b/test/src/image-tests.el
@@ -0,0 +1,69 @@
+;;; image-tests.el --- Tests for image.c -*- lexical-binding: t -*-
+
+;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+;; Author: Stefan Kangas <stefankangas@gmail.com>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+
+(declare-function image-size "image.c" (spec &optional pixels frame))
+(declare-function image-mask-p "image.c" (spec &optional frame))
+(declare-function image-metadata "image.c" (spec &optional frame))
+
+(defconst image-tests--images
+ `((gif . ,(expand-file-name "test/data/image/black.gif"
+ source-directory))
+ (jpeg . ,(expand-file-name "test/data/image/black.jpg"
+ source-directory))
+ (pbm . ,(find-image '((:file "splash.svg" :type svg))))
+ (png . ,(find-image '((:file "splash.png" :type png))))
+ (svg . ,(find-image '((:file "splash.pbm" :type pbm))))
+ (tiff . ,(expand-file-name
+ "nextstep/GNUstep/Emacs.base/Resources/emacs.tiff"
+ source-directory))
+ (webp . ,(expand-file-name "test/data/image/black.webp"
+ source-directory))
+ (xbm . ,(find-image '((:file "gnus/gnus.xbm" :type xbm))))
+ (xpm . ,(find-image '((:file "splash.xpm" :type xpm))))))
+
+(ert-deftest image-tests-image-size/error-on-nongraphical-display ()
+ (skip-unless (not (display-images-p)))
+ (should-error (image-size 'invalid-spec)))
+
+(ert-deftest image-tests-image-mask-p/error-on-nongraphical-display ()
+ (skip-unless (not (display-images-p)))
+ (should-error (image-mask-p (cdr (assq 'xpm image-tests--images)))))
+
+(ert-deftest image-tests-image-metadata/error-on-nongraphical-display ()
+ (skip-unless (not (display-images-p)))
+ (should-error (image-metadata (cdr (assq 'xpm image-tests--images)))))
+
+(ert-deftest image-tests-imagemagick-types ()
+ (skip-unless (fboundp 'imagemagick-types))
+ (when (fboundp 'imagemagick-types)
+ (should (listp (imagemagick-types)))))
+
+(ert-deftest image-tests-init-image-library ()
+ (skip-unless (fboundp 'init-image-library))
+ (declare-function init-image-library "image.c" (type))
+ (should (init-image-library 'pbm)) ; built-in
+ (should-not (init-image-library 'invalid-image-type)))
+
+;;; image-tests.el ends here
diff --git a/test/src/indent-tests.el b/test/src/indent-tests.el
new file mode 100644
index 00000000000..e6b1fde6e18
--- /dev/null
+++ b/test/src/indent-tests.el
@@ -0,0 +1,61 @@
+;;; indent-tests.el --- tests for src/indent.c -*- lexical-binding:t -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(ert-deftest indent-tests-move-to-column-invis-1tab ()
+ "Test `move-to-column' when a TAB is followed by invisible text."
+ (should
+ (string=
+ (with-temp-buffer
+ (insert "\tLine starting with INVISIBLE text after TAB\n")
+ (add-text-properties 2 21 '(invisible t))
+ (goto-char (point-min))
+ (move-to-column 7 t)
+ (buffer-substring-no-properties 1 8))
+ " ")))
+
+(ert-deftest indent-tests-move-to-column-invis-2tabs ()
+ "Test `move-to-column' when 2 TABs are followed by invisible text."
+ (should
+ (string=
+ (with-temp-buffer
+ (insert "\t\tLine starting with INVISIBLE text after TAB\n")
+ (add-text-properties 3 22 '(invisible t))
+ (goto-char (point-min))
+ (move-to-column 12 t)
+ (buffer-substring-no-properties 1 11))
+ "\t \tLine")))
+
+(ert-deftest indent-tests-move-to-column-invis-between-tabs ()
+ "Test `move-to-column' when 2 TABs are mixed with invisible text."
+ (should
+ (string=
+ (with-temp-buffer
+ (insert "\txxx\tLine starting with INVISIBLE text after TAB\n")
+ (add-text-properties 6 25 '(invisible t))
+ (add-text-properties 2 5 '(invisible t))
+ (goto-char (point-min))
+ (move-to-column 12 t)
+ (buffer-substring-no-properties 1 14))
+ "\txxx \tLine")))
+
+;;; indent-tests.el ends here
diff --git a/test/src/inotify-tests.el b/test/src/inotify-tests.el
index 9f8abb0ffdb..295b184be0e 100644
--- a/test/src/inotify-tests.el
+++ b/test/src/inotify-tests.el
@@ -1,6 +1,6 @@
;;; inotify-tests.el --- Test suite for inotify. -*- lexical-binding: t -*-
-;; Copyright (C) 2012-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2022 Free Software Foundation, Inc.
;; Author: Rüdiger Sonderfeld <ruediger@c-plusplus.de>
;; Keywords: internal
@@ -24,9 +24,11 @@
;;; Code:
(require 'ert)
+(require 'ert-x)
(declare-function inotify-add-watch "inotify.c" (file-name aspect callback))
(declare-function inotify-rm-watch "inotify.c" (watch-descriptor))
+(declare-function inotify-valid-p "inotify.c" (watch-descriptor))
(ert-deftest inotify-valid-p-simple ()
"Simple tests for `inotify-valid-p'."
@@ -37,8 +39,7 @@
;; (ert-deftest filewatch-file-watch-aspects-check ()
;; "Test whether `file-watch' properly checks the aspects."
-;; (let ((temp-file (make-temp-file "filewatch-aspects")))
-;; (should (stringp temp-file))
+;; (ert-with-temp-file temp-file
;; (should-error (file-watch temp-file 'wrong nil)
;; :type 'error)
;; (should-error (file-watch temp-file '(modify t) nil)
@@ -50,24 +51,22 @@
(ert-deftest inotify-file-watch-simple ()
"Test if watching a normal file works."
-
(skip-unless (featurep 'inotify))
- (let ((temp-file (make-temp-file "inotify-simple"))
- (events 0))
- (let ((wd
- (inotify-add-watch temp-file t (lambda (_ev)
- (setq events (1+ events))))))
- (unwind-protect
- (progn
- (with-temp-file temp-file
- (insert "Foo\n"))
- (read-event nil nil 5)
- (should (> events 0)))
- (should (inotify-valid-p wd))
- (inotify-rm-watch wd)
- (should-not (inotify-valid-p wd))
- (delete-file temp-file)))))
+ (ert-with-temp-file temp-file
+ (let ((events 0))
+ (let ((wd
+ (inotify-add-watch temp-file t (lambda (_ev)
+ (setq events (1+ events))))))
+ (unwind-protect
+ (progn
+ (with-temp-file temp-file
+ (insert "Foo\n"))
+ (read-event nil nil 5)
+ (should (> events 0)))
+ (should (inotify-valid-p wd))
+ (inotify-rm-watch wd)
+ (should-not (inotify-valid-p wd)))))))
(provide 'inotify-tests)
-;;; inotify-tests.el ends here.
+;;; inotify-tests.el ends here
diff --git a/test/src/json-tests.el b/test/src/json-tests.el
new file mode 100644
index 00000000000..3560e1abc96
--- /dev/null
+++ b/test/src/json-tests.el
@@ -0,0 +1,343 @@
+;;; json-tests.el --- unit tests for json.c -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2017-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Unit tests for src/json.c.
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'map)
+
+(declare-function json-serialize "json.c" (object &rest args))
+(declare-function json-insert "json.c" (object &rest args))
+(declare-function json-parse-string "json.c" (string &rest args))
+(declare-function json-parse-buffer "json.c" (&rest args))
+
+(define-error 'json-tests--error "JSON test error")
+
+(ert-deftest json-serialize/roundtrip ()
+ (skip-unless (fboundp 'json-serialize))
+ ;; The noncharacter U+FFFF should be passed through,
+ ;; cf. https://www.unicode.org/faq/private_use.html#noncharacters.
+ (let ((lisp [:null :false t 0 123 -456 3.75 "abc\uFFFFαβγ𝔸𝐁𝖢\"\\"])
+ (json "[null,false,true,0,123,-456,3.75,\"abc\uFFFFαβγ𝔸𝐁𝖢\\\"\\\\\"]"))
+ (should (equal (json-serialize lisp) json))
+ (with-temp-buffer
+ (json-insert lisp)
+ (should (equal (buffer-string) json))
+ (should (eobp)))
+ (should (equal (json-parse-string json) lisp))
+ (with-temp-buffer
+ (insert json)
+ (goto-char 1)
+ (should (equal (json-parse-buffer) lisp))
+ (should (eobp)))))
+
+(ert-deftest json-serialize/roundtrip-scalars ()
+ "Check that Bug#42994 is fixed."
+ (skip-unless (fboundp 'json-serialize))
+ (dolist (case '((:null "null")
+ (:false "false")
+ (t "true")
+ (0 "0")
+ (123 "123")
+ (-456 "-456")
+ (3.75 "3.75")
+ ;; The noncharacter U+FFFF should be passed through,
+ ;; cf. https://www.unicode.org/faq/private_use.html#noncharacters.
+ ("abc\uFFFFαβγ𝔸𝐁𝖢\"\\"
+ "\"abc\uFFFFαβγ𝔸𝐁𝖢\\\"\\\\\"")))
+ (cl-destructuring-bind (lisp json) case
+ (ert-info ((format "%S ↔ %S" lisp json))
+ (should (equal (json-serialize lisp) json))
+ (with-temp-buffer
+ (json-insert lisp)
+ (should (equal (buffer-string) json))
+ (should (eobp)))
+ (should (equal (json-parse-string json) lisp))
+ (with-temp-buffer
+ (insert json)
+ (goto-char 1)
+ (should (equal (json-parse-buffer) lisp))
+ (should (eobp)))))))
+
+(ert-deftest json-serialize/object ()
+ (skip-unless (fboundp 'json-serialize))
+ (let ((table (make-hash-table :test #'equal)))
+ (puthash "abc" [1 2 t] table)
+ (puthash "def" :null table)
+ (should (equal (json-serialize table)
+ "{\"abc\":[1,2,true],\"def\":null}")))
+ (should (equal (json-serialize '((abc . [1 2 t]) (def . :null)))
+ "{\"abc\":[1,2,true],\"def\":null}"))
+ (should (equal (json-serialize nil) "{}"))
+ (should (equal (json-serialize '((abc))) "{\"abc\":{}}"))
+ (should (equal (json-serialize '((a . 1) (b . 2) (a . 3)))
+ "{\"a\":1,\"b\":2}"))
+ (should-error (json-serialize '(abc)) :type 'wrong-type-argument)
+ (should-error (json-serialize '((a 1))) :type 'wrong-type-argument)
+ (should-error (json-serialize '((1 . 2))) :type 'wrong-type-argument)
+ (should-error (json-serialize '((a . 1) . b)) :type 'wrong-type-argument)
+ (should-error (json-serialize '#1=((a . 1) . #1#)) :type 'circular-list)
+ (should-error (json-serialize '(#1=(a #1#))))
+
+ (should (equal (json-serialize '(:abc [1 2 t] :def :null))
+ "{\"abc\":[1,2,true],\"def\":null}"))
+ (should (equal (json-serialize '(abc [1 2 t] :def :null))
+ "{\"abc\":[1,2,true],\"def\":null}"))
+ (should-error (json-serialize '#1=(:a 1 . #1#)) :type 'circular-list)
+ (should-error (json-serialize '#1=(:a 1 :b . #1#))
+ :type '(circular-list wrong-type-argument))
+ (should-error (json-serialize '(:foo "bar" (unexpected-alist-key . 1)))
+ :type 'wrong-type-argument)
+ (should-error (json-serialize '((abc . "abc") :unexpected-plist-key "key"))
+ :type 'wrong-type-argument)
+ (should-error (json-serialize '(:foo bar :odd-numbered))
+ :type 'wrong-type-argument)
+ (should (equal
+ (json-serialize
+ (list :detect-hash-table #s(hash-table test equal data ("bla" "ble"))
+ :detect-alist '((bla . "ble"))
+ :detect-plist '(:bla "ble")))
+ "\
+{\
+\"detect-hash-table\":{\"bla\":\"ble\"},\
+\"detect-alist\":{\"bla\":\"ble\"},\
+\"detect-plist\":{\"bla\":\"ble\"}\
+}")))
+
+(ert-deftest json-serialize/object-with-duplicate-keys ()
+ (skip-unless (fboundp 'json-serialize))
+ (let ((table (make-hash-table :test #'eq)))
+ (puthash (copy-sequence "abc") [1 2 t] table)
+ (puthash (copy-sequence "abc") :null table)
+ (should (equal (hash-table-count table) 2))
+ (should-error (json-serialize table) :type 'wrong-type-argument)))
+
+(ert-deftest json-parse-string/object ()
+ (skip-unless (fboundp 'json-parse-string))
+ (let ((input
+ "{ \"abc\" : [1, 2, true], \"def\" : null, \"abc\" : [9, false] }\n"))
+ (let ((actual (json-parse-string input)))
+ (should (hash-table-p actual))
+ (should (equal (hash-table-count actual) 2))
+ (should (equal (cl-sort (map-pairs actual) #'string< :key #'car)
+ '(("abc" . [9 :false]) ("def" . :null)))))
+ (should (equal (json-parse-string input :object-type 'alist)
+ '((abc . [9 :false]) (def . :null))))
+ (should (equal (json-parse-string input :object-type 'plist)
+ '(:abc [9 :false] :def :null)))))
+
+(ert-deftest json-parse-string/array ()
+ (skip-unless (fboundp 'json-parse-string))
+ (let ((input "[\"a\", 1, [\"b\", 2]]"))
+ (should (equal (json-parse-string input)
+ ["a" 1 ["b" 2]]))
+ (should (equal (json-parse-string input :array-type 'list)
+ '("a" 1 ("b" 2))))))
+
+(ert-deftest json-parse-string/string ()
+ (skip-unless (fboundp 'json-parse-string))
+ (should-error (json-parse-string "[\"formfeed\f\"]") :type 'json-parse-error)
+ (should (equal (json-parse-string "[\"foo \\\"bar\\\"\"]") ["foo \"bar\""]))
+ (should (equal (json-parse-string "[\"abcαβγ\"]") ["abcαβγ"]))
+ (should (equal (json-parse-string "[\"\\nasd\\u0444\\u044b\\u0432fgh\\t\"]")
+ ["\nasdфывfgh\t"]))
+ (should (equal (json-parse-string "[\"\\uD834\\uDD1E\"]") ["\U0001D11E"]))
+ (should-error (json-parse-string "foo") :type 'json-parse-error)
+ ;; FIXME: Is this the right behavior?
+ (should (equal (json-parse-string "[\"\u00C4\xC3\x84\"]") ["\u00C4\u00C4"])))
+
+(ert-deftest json-serialize/string ()
+ (skip-unless (fboundp 'json-serialize))
+ (should (equal (json-serialize ["foo"]) "[\"foo\"]"))
+ (should (equal (json-serialize ["a\n\fb"]) "[\"a\\n\\fb\"]"))
+ (should (equal (json-serialize ["\nasdфыв\u001f\u007ffgh\t"])
+ "[\"\\nasdфыв\\u001F\u007ffgh\\t\"]"))
+ (should (equal (json-serialize ["a\0b"]) "[\"a\\u0000b\"]"))
+ ;; FIXME: Is this the right behavior?
+ (should (equal (json-serialize ["\u00C4\xC3\x84"]) "[\"\u00C4\u00C4\"]")))
+
+(ert-deftest json-serialize/invalid-unicode ()
+ (skip-unless (fboundp 'json-serialize))
+ (should-error (json-serialize ["a\uDBBBb"]) :type 'wrong-type-argument)
+ (should-error (json-serialize ["u\x110000v"]) :type 'wrong-type-argument)
+ (should-error (json-serialize ["u\x3FFFFFv"]) :type 'wrong-type-argument)
+ (should-error (json-serialize ["u\xCCv"]) :type 'wrong-type-argument)
+ (should-error (json-serialize ["u\u00C4\xCCv"]) :type 'wrong-type-argument))
+
+(ert-deftest json-parse-string/null ()
+ (skip-unless (fboundp 'json-parse-string))
+ (should-error (json-parse-string "\x00") :type 'wrong-type-argument)
+ (should (json-parse-string "[\"a\\u0000b\"]"))
+ (let* ((string "{\"foo\":\"this is a string including a literal \\u0000\"}")
+ (data (json-parse-string string)))
+ (should (hash-table-p data))
+ (should (equal string (json-serialize data)))))
+
+(ert-deftest json-parse-string/invalid-unicode ()
+ "Some examples from
+https://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt.
+Test with both unibyte and multibyte strings."
+ (skip-unless (fboundp 'json-parse-string))
+ ;; Invalid UTF-8 code unit sequences.
+ (should-error (json-parse-string "[\"\x80\"]") :type 'json-parse-error)
+ (should-error (json-parse-string "[\"\u00C4\x80\"]") :type 'json-parse-error)
+ (should-error (json-parse-string "[\"\xBF\"]") :type 'json-parse-error)
+ (should-error (json-parse-string "[\"\u00C4\xBF\"]") :type 'json-parse-error)
+ (should-error (json-parse-string "[\"\xFE\"]") :type 'json-parse-error)
+ (should-error (json-parse-string "[\"\u00C4\xFE\"]") :type 'json-parse-error)
+ (should-error (json-parse-string "[\"\xC0\xAF\"]") :type 'json-parse-error)
+ (should-error (json-parse-string "[\"\u00C4\xC0\xAF\"]")
+ :type 'json-parse-error)
+ (should-error (json-parse-string "[\"\u00C4\xC0\x80\"]")
+ :type 'json-parse-error)
+ ;; Surrogates.
+ (should-error (json-parse-string "[\"\uDB7F\"]")
+ :type 'json-parse-error)
+ (should-error (json-parse-string "[\"\xED\xAD\xBF\"]")
+ :type 'json-parse-error)
+ (should-error (json-parse-string "[\"\u00C4\xED\xAD\xBF\"]")
+ :type 'json-parse-error)
+ (should-error (json-parse-string "[\"\uDB7F\uDFFF\"]")
+ :type 'json-parse-error)
+ (should-error (json-parse-string "[\"\xED\xAD\xBF\xED\xBF\xBF\"]")
+ :type 'json-parse-error)
+ (should-error (json-parse-string "[\"\u00C4\xED\xAD\xBF\xED\xBF\xBF\"]")
+ :type 'json-parse-error))
+
+(ert-deftest json-parse-string/incomplete ()
+ (skip-unless (fboundp 'json-parse-string))
+ (should-error (json-parse-string "[123") :type 'json-end-of-file))
+
+(ert-deftest json-parse-string/trailing ()
+ (skip-unless (fboundp 'json-parse-string))
+ (should-error (json-parse-string "[123] [456]") :type 'json-trailing-content))
+
+(ert-deftest json-parse-buffer/incomplete ()
+ (skip-unless (fboundp 'json-parse-buffer))
+ (with-temp-buffer
+ (insert "[123")
+ (goto-char 1)
+ (should-error (json-parse-buffer) :type 'json-end-of-file)
+ (should (bobp))))
+
+(ert-deftest json-parse-buffer/trailing ()
+ (skip-unless (fboundp 'json-parse-buffer))
+ (with-temp-buffer
+ (insert "[123] [456]")
+ (goto-char 1)
+ (should (equal (json-parse-buffer) [123]))
+ (should-not (bobp))
+ (should (looking-at-p (rx " [456]" eos)))))
+
+(ert-deftest json-parse-with-custom-null-and-false-objects ()
+ (skip-unless (and (fboundp 'json-serialize)
+ (fboundp 'json-parse-string)))
+ (let* ((input
+ "{ \"abc\" : [9, false] , \"def\" : null }")
+ (output
+ (string-replace " " "" input)))
+ (should (equal (json-parse-string input
+ :object-type 'plist
+ :null-object :json-null
+ :false-object :json-false)
+ '(:abc [9 :json-false] :def :json-null)))
+ (should (equal (json-parse-string input
+ :object-type 'plist
+ :false-object :json-false)
+ '(:abc [9 :json-false] :def :null)))
+ (should (equal (json-parse-string input
+ :object-type 'alist
+ :null-object :zilch)
+ '((abc . [9 :false]) (def . :zilch))))
+ (should (equal (json-parse-string input
+ :object-type 'alist
+ :false-object nil
+ :null-object nil)
+ '((abc . [9 nil]) (def))))
+ (let* ((thingy '(1 2 3))
+ (retval (json-parse-string input
+ :object-type 'alist
+ :false-object thingy
+ :null-object nil)))
+ (should (equal retval `((abc . [9 ,thingy]) (def))))
+ (should (eq (elt (cdr (car retval)) 1) thingy)))
+ (should (equal output
+ (json-serialize '((abc . [9 :myfalse]) (def . :mynull))
+ :false-object :myfalse
+ :null-object :mynull)))
+ ;; :object-type is not allowed in json-serialize
+ (should-error (json-serialize '() :object-type 'alist))))
+
+(ert-deftest json-insert/signal ()
+ (skip-unless (fboundp 'json-insert))
+ (with-temp-buffer
+ (let ((calls 0))
+ (add-hook 'after-change-functions
+ (lambda (_begin _end _length)
+ (cl-incf calls)
+ (signal 'json-tests--error
+ '("Error in `after-change-functions'")))
+ :local)
+ (should-error
+ (json-insert '((a . "b") (c . 123) (d . [1 2 t :false])))
+ :type 'json-tests--error)
+ (should (equal calls 1)))))
+
+(ert-deftest json-insert/throw ()
+ (skip-unless (fboundp 'json-insert))
+ (with-temp-buffer
+ (let ((calls 0))
+ (add-hook 'after-change-functions
+ (lambda (_begin _end _length)
+ (cl-incf calls)
+ (throw 'test-tag 'throw-value))
+ :local)
+ (should
+ (equal
+ (catch 'test-tag
+ (json-insert '((a . "b") (c . 123) (d . [1 2 t :false]))))
+ 'throw-value))
+ (should (equal calls 1)))))
+
+(ert-deftest json-serialize/bignum ()
+ (skip-unless (fboundp 'json-serialize))
+ (should (equal (json-serialize (vector (1+ most-positive-fixnum)
+ (1- most-negative-fixnum)))
+ (format "[%d,%d]"
+ (1+ most-positive-fixnum)
+ (1- most-negative-fixnum)))))
+
+(ert-deftest json-parse-string/wrong-type ()
+ "Check that Bug#42113 is fixed."
+ (skip-unless (fboundp 'json-parse-string))
+ (should-error (json-parse-string 1) :type 'wrong-type-argument))
+
+(ert-deftest json-serialize/wrong-hash-key-type ()
+ "Check that Bug#42113 is fixed."
+ (skip-unless (fboundp 'json-serialize))
+ (let ((table (make-hash-table :test #'eq)))
+ (puthash 1 2 table)
+ (should-error (json-serialize table) :type 'wrong-type-argument)))
+
+(provide 'json-tests)
+;;; json-tests.el ends here
diff --git a/test/src/keyboard-tests.el b/test/src/keyboard-tests.el
new file mode 100644
index 00000000000..d17c9d96a63
--- /dev/null
+++ b/test/src/keyboard-tests.el
@@ -0,0 +1,74 @@
+;;; keyboard-tests.el --- Tests for keyboard.c -*- lexical-binding: t -*-
+
+;; Copyright (C) 2017-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+
+(ert-deftest keyboard-unread-command-events ()
+ "Test `unread-command-events'."
+ (let ((unread-command-events nil))
+ (should (equal (progn (push ?\C-a unread-command-events)
+ (read-event nil nil 1))
+ ?\C-a))
+ (should (equal (progn (run-with-timer
+ 1 nil
+ (lambda () (push '(t . ?\C-b) unread-command-events)))
+ (read-event nil nil 2))
+ ?\C-b))))
+
+(ert-deftest keyboard-lossage-size ()
+ "Test `lossage-size'."
+ (let ((min-value 100)
+ (lossage-orig (lossage-size)))
+ (dolist (factor (list 1 3 4 5 10 7 3))
+ (let ((new-lossage (* factor min-value)))
+ (should (= new-lossage (lossage-size new-lossage)))))
+ ;; Wrong type
+ (should-error (lossage-size -5))
+ (should-error (lossage-size "200"))
+ ;; Less that minimum value
+ (should-error (lossage-size (1- min-value)))
+ (should (= lossage-orig (lossage-size lossage-orig)))))
+
+;; FIXME: This test doesn't currently work :-(
+;; (ert-deftest keyboard-tests--echo-keystrokes-bug15332 ()
+;; (let ((msgs '())
+;; (unread-command-events nil)
+;; (redisplay--interactive t)
+;; (echo-keystrokes 2))
+;; (setq unread-command-events '(?\C-u))
+;; (let* ((timer1
+;; (run-with-timer 3 1
+;; (lambda ()
+;; (setq unread-command-events '(?5)))))
+;; (timer2
+;; (run-with-timer 2.5 1
+;; (lambda ()
+;; (push (current-message) msgs)))))
+;; (run-with-timer 5 nil
+;; (lambda ()
+;; (cancel-timer timer1)
+;; (cancel-timer timer2)
+;; (throw 'exit msgs)))
+;; (recursive-edit)
+;; (should (equal msgs '("C-u 55-" "C-u 5-" "C-u-"))))))
+
+(provide 'keyboard-tests)
+;;; keyboard-tests.el ends here
diff --git a/test/src/keymap-tests.el b/test/src/keymap-tests.el
index bc2b424a639..ce96be6869e 100644
--- a/test/src/keymap-tests.el
+++ b/test/src/keymap-tests.el
@@ -1,8 +1,9 @@
-;;; keymap-tests.el --- Test suite for src/keymap.c
+;;; keymap-tests.el --- Test suite for src/keymap.c -*- lexical-binding: t -*-
-;; Copyright (C) 2015-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2022 Free Software Foundation, Inc.
;; Author: Juanma Barranquero <lekktu@gmail.com>
+;; Stefan Kangas <stefankangas@gmail.com>
;; This file is part of GNU Emacs.
@@ -23,6 +24,188 @@
(require 'ert)
+(defun keymap-tests--make-keymap-test (fun)
+ (should (eq (car (funcall fun)) 'keymap))
+ (should (proper-list-p (funcall fun)))
+ (should (equal (car (last (funcall fun "foo"))) "foo")))
+
+(ert-deftest keymap-make-keymap ()
+ (keymap-tests--make-keymap-test #'make-keymap)
+ (should (char-table-p (cadr (make-keymap)))))
+
+(ert-deftest keymap-make-sparse-keymap ()
+ (keymap-tests--make-keymap-test #'make-sparse-keymap))
+
+(ert-deftest keymap-keymapp ()
+ (should (keymapp (make-keymap)))
+ (should (keymapp (make-sparse-keymap)))
+ (should-not (keymapp '(foo bar))))
+
+(ert-deftest keymap-keymap-parent ()
+ (should-not (keymap-parent (make-keymap)))
+ (should-not (keymap-parent (make-sparse-keymap)))
+ (let ((map (make-keymap)))
+ (set-keymap-parent map help-mode-map)
+ (should (equal (keymap-parent map) help-mode-map))))
+
+(ert-deftest keymap-copy-keymap/is-equal ()
+ (should (equal (copy-keymap help-mode-map) help-mode-map)))
+
+(ert-deftest keymap-copy-keymap/is-not-eq ()
+ (should-not (eq (copy-keymap help-mode-map) help-mode-map)))
+
+(ert-deftest keymap---get-keyelt/runs-menu-item-filter ()
+ (let* (menu-item-filter-ran
+ (object `(menu-item "2" identity
+ :filter ,(lambda (cmd)
+ (setq menu-item-filter-ran t)
+ cmd))))
+ (keymap--get-keyelt object t)
+ (should menu-item-filter-ran)))
+
+(ert-deftest keymap-define-key/undefined ()
+ ;; nil (means key is undefined in this keymap),
+ (let ((map (make-keymap)))
+ (define-key map [?a] nil)
+ (should-not (lookup-key map [?a]))))
+
+(ert-deftest keymap-define-key/keyboard-macro ()
+ ;; a string (treated as a keyboard macro),
+ (let ((map (make-keymap)))
+ (define-key map [?a] "abc")
+ (should (equal (lookup-key map [?a]) "abc"))))
+
+(ert-deftest keymap-define-key/lambda ()
+ (let ((map (make-keymap)))
+ (define-key map [?a] (lambda () (interactive) nil))
+ (should (functionp (lookup-key map [?a])))))
+
+(ert-deftest keymap-define-key/keymap ()
+ ;; a keymap (to define a prefix key),
+ (let ((map (make-keymap))
+ (map2 (make-keymap)))
+ (define-key map [?a] map2)
+ (define-key map2 [?b] 'foo)
+ (should (eq (lookup-key map [?a ?b]) 'foo))))
+
+(ert-deftest keymap-define-key/menu-item ()
+ ;; or an extended menu item definition.
+ ;; (See info node ‘(elisp)Extended Menu Items’.)
+ (let ((map (make-sparse-keymap))
+ (menu (make-sparse-keymap)))
+ (define-key menu [new-file]
+ '(menu-item "Visit New File..." find-file
+ :enable (menu-bar-non-minibuffer-window-p)
+ :help "Specify a new file's name, to edit the file"))
+ (define-key map [menu-bar file] (cons "File" menu))
+ (should (eq (lookup-key map [menu-bar file new-file]) 'find-file))))
+
+(ert-deftest keymap-lookup-key ()
+ (let ((map (make-keymap)))
+ (define-key map [?a] 'foo)
+ (should (eq (lookup-key map [?a]) 'foo))
+ (should-not (lookup-key map [?b]))))
+
+(ert-deftest keymap-lookup-key/list-of-keymaps ()
+ (let ((map1 (make-keymap))
+ (map2 (make-keymap)))
+ (define-key map1 [?a] 'foo)
+ (define-key map2 [?b] 'bar)
+ (should (eq (lookup-key (list map1 map2) [?a]) 'foo))
+ (should (eq (lookup-key (list map1 map2) [?b]) 'bar))
+ (should-not (lookup-key (list map1 map2) [?c]))))
+
+(ert-deftest keymap-lookup-key/too-long ()
+ (let ((map (make-keymap)))
+ (define-key map (kbd "C-c f") 'foo)
+ (should (= (lookup-key map (kbd "C-c f x")) 2))))
+
+;; TODO: Write test for the ACCEPT-DEFAULT argument.
+;; (ert-deftest keymap-lookup-key/accept-default ()
+;; ...)
+
+(ert-deftest keymap-lookup-key/mixed-case ()
+ "Backwards compatibility behavior (Bug#50752)."
+ (let ((map (make-keymap)))
+ (define-key map [menu-bar foo bar] 'foo)
+ (should (eq (lookup-key map [menu-bar foo bar]) 'foo))
+ (should (eq (lookup-key map [menu-bar Foo Bar]) 'foo)))
+ (let ((map (make-keymap)))
+ (define-key map [menu-bar i-bar] 'foo)
+ (should (eq (lookup-key map [menu-bar I-bar]) 'foo))))
+
+(ert-deftest keymap-lookup-key/mixed-case-multibyte ()
+ "Backwards compatibility behavior (Bug#50752)."
+ (let ((map (make-keymap)))
+ ;; (downcase "Åäö") => "åäö"
+ (define-key map [menu-bar åäö bar] 'foo)
+ (should (eq (lookup-key map [menu-bar åäö bar]) 'foo))
+ (should (eq (lookup-key map [menu-bar Åäö Bar]) 'foo))
+ ;; (downcase "Γ") => "γ"
+ (define-key map [menu-bar γ bar] 'baz)
+ (should (eq (lookup-key map [menu-bar γ bar]) 'baz))
+ (should (eq (lookup-key map [menu-bar Γ Bar]) 'baz))))
+
+(ert-deftest keymap-lookup-key/menu-non-symbol ()
+ "Test for Bug#51527."
+ (let ((map (make-keymap)))
+ (define-key map [menu-bar buffer 1] 'foo)
+ (should (eq (lookup-key map [menu-bar buffer 1]) 'foo))))
+
+(ert-deftest keymap-lookup-keymap/with-spaces ()
+ "Backwards compatibility behavior (Bug#50752)."
+ (let ((map (make-keymap)))
+ (define-key map [menu-bar foo-bar] 'foo)
+ (should (eq (lookup-key map [menu-bar Foo\ Bar]) 'foo))))
+
+(ert-deftest keymap-lookup-keymap/with-spaces-multibyte ()
+ "Backwards compatibility behavior (Bug#50752)."
+ (let ((map (make-keymap)))
+ (define-key map [menu-bar åäö-bar] 'foo)
+ (should (eq (lookup-key map [menu-bar Åäö\ Bar]) 'foo))))
+
+(ert-deftest keymap-lookup-keymap/with-spaces-multibyte-lang-env ()
+ "Backwards compatibility behavior (Bug#50752)."
+ (let ((lang-env current-language-environment))
+ (set-language-environment "Turkish")
+ (let ((map (make-keymap)))
+ (define-key map [menu-bar i-bar] 'foo)
+ (should (eq (lookup-key map [menu-bar I-bar]) 'foo)))
+ (set-language-environment lang-env)))
+
+(ert-deftest describe-buffer-bindings/header-in-current-buffer ()
+ "Header should be inserted into the current buffer.
+https://debbugs.gnu.org/39149#31"
+ (with-temp-buffer
+ (describe-buffer-bindings (current-buffer))
+ (should (string-match (rx bol "key" (+ space) "binding" eol)
+ (buffer-string)))))
+
+(ert-deftest describe-buffer-bindings/returns-nil ()
+ "Should return nil."
+ (with-temp-buffer
+ (should (eq (describe-buffer-bindings (current-buffer)) nil))))
+
+(defun keymap-tests--test-menu-item-filter (show filter-fun)
+ (unwind-protect
+ (progn
+ (define-key global-map (kbd "C-c C-l r")
+ `(menu-item "2" identity :filter ,filter-fun))
+ (with-temp-buffer
+ (describe-buffer-bindings (current-buffer))
+ (goto-char (point-min))
+ (if (eq show 'show)
+ (should (search-forward "C-c C-l r" nil t))
+ (should-not (search-forward "C-c C-l r" nil t)))))
+ (define-key global-map (kbd "C-c C-l r") nil)
+ (define-key global-map (kbd "C-c C-l") nil)))
+
+(ert-deftest describe-buffer-bindings/menu-item-filter-show-binding ()
+ (keymap-tests--test-menu-item-filter 'show (lambda (cmd) cmd)))
+
+(ert-deftest describe-buffer-bindings/menu-item-filter-hide-binding ()
+ (keymap-tests--test-menu-item-filter 'hide (lambda (_) nil)))
+
(ert-deftest keymap-store_in_keymap-XFASTINT-on-non-characters ()
"Check for bug fixed in \"Fix assertion violation in define-key\",
commit 86c19714b097aa477d339ed99ffb5136c755a046."
@@ -38,13 +221,227 @@ commit 86c19714b097aa477d339ed99ffb5136c755a046."
(should (eq (lookup-key Buffer-menu-mode-map [32]) 'undefined)))
(define-key Buffer-menu-mode-map [32] def))))
-(ert-deftest keymap-where-is-internal-test ()
+
+;;;; where-is-internal
+
+(defun keymap-tests--command-1 () (interactive) nil)
+(defun keymap-tests--command-2 () (interactive) nil)
+(put 'keymap-tests--command-1 :advertised-binding [?y])
+
+(ert-deftest keymap-where-is-internal ()
+ (let ((map (make-sparse-keymap)))
+ (define-key map "x" 'keymap-tests--command-1)
+ (define-key map "y" 'keymap-tests--command-1)
+ (should (equal (where-is-internal 'keymap-tests--command-1 map)
+ '([?y] [?x])))))
+
+(ert-deftest keymap-where-is-internal/firstonly-t ()
+ (let ((map (make-sparse-keymap)))
+ (define-key map "x" 'keymap-tests--command-1)
+ (define-key map "y" 'keymap-tests--command-1)
+ (should (equal (where-is-internal 'keymap-tests--command-1 map t)
+ [?y]))))
+
+(ert-deftest keymap-where-is-internal/menu-item ()
+ (let ((map (make-sparse-keymap)))
+ (define-key map [menu-bar foobar cmd1]
+ '(menu-item "Run Command 1" keymap-tests--command-1
+ :help "Command 1 Help"))
+ (define-key map "x" 'keymap-tests--command-1)
+ (should (equal (where-is-internal 'keymap-tests--command-1 map)
+ '([?x] [menu-bar foobar cmd1])))
+ (should (equal (where-is-internal 'keymap-tests--command-1 map t) [?x]))))
+
+
+(ert-deftest keymap-where-is-internal/advertised-binding ()
+ ;; Make sure order does not matter.
+ (dolist (keys '(("x" . "y") ("y" . "x")))
+ (let ((map (make-sparse-keymap)))
+ (define-key map (car keys) 'keymap-tests--command-1)
+ (define-key map (cdr keys) 'keymap-tests--command-1)
+ (should (equal (where-is-internal 'keymap-tests--command-1 map t) [121])))))
+
+(ert-deftest keymap-where-is-internal/advertised-binding-respect-remap ()
+ (let ((map (make-sparse-keymap)))
+ (define-key map "x" 'next-line)
+ (define-key map [remap keymap-tests--command-1] 'next-line)
+ (define-key map "y" 'keymap-tests--command-1)
+ (should (equal (where-is-internal 'keymap-tests--command-1 map t) [?x]))))
+
+(ert-deftest keymap-where-is-internal/remap ()
+ (let ((map (make-keymap)))
+ (define-key map (kbd "x") 'foo)
+ (define-key map (kbd "y") 'bar)
+ (define-key map [remap foo] 'bar)
+ (should (equal (where-is-internal 'foo map t) [?y]))
+ (should (equal (where-is-internal 'bar map t) [?y]))))
+
+(defvar-keymap keymap-tests-minor-mode-map
+ "x" 'keymap-tests--command-2)
+
+(defvar-keymap keymap-tests-major-mode-map
+ "x" 'keymap-tests--command-1)
+
+(define-minor-mode keymap-tests-minor-mode "Test.")
+
+(define-derived-mode keymap-tests-major-mode nil "Test.")
+
+(ert-deftest keymap-where-is-internal/shadowed ()
+ (with-temp-buffer
+ (keymap-tests-major-mode)
+ (keymap-tests-minor-mode)
+ (should-not (where-is-internal 'keymap-tests--command-1 nil t))
+ (should (equal (where-is-internal 'keymap-tests--command-2 nil t) [120]))))
+
+(ert-deftest keymap-where-is-internal/preferred-modifier-is-a-string ()
"Make sure we don't crash when `where-is-preferred-modifier' is not a symbol."
(should
(equal (let ((where-is-preferred-modifier "alt"))
(where-is-internal 'execute-extended-command global-map t))
[#x8000078])))
+
+;;;; describe_vector
+
+(ert-deftest help--describe-vector/bug-9293-one-shadowed-in-range ()
+ "Check that we only show a range if shadowed by the same command."
+ (let ((orig-map (let ((map (make-keymap)))
+ (define-key map "e" 'foo)
+ (define-key map "f" 'foo)
+ (define-key map "g" 'foo)
+ (define-key map "h" 'foo)
+ map))
+ (shadow-map (let ((map (make-keymap)))
+ (define-key map "f" 'bar)
+ map))
+ (text-quoting-style 'grave)
+ (describe-bindings-check-shadowing-in-ranges 'ignore-self-insert))
+ (with-temp-buffer
+ (help--describe-vector (cadr orig-map) nil #'help--describe-command
+ t shadow-map orig-map t)
+ (should (equal (buffer-substring-no-properties (point-min) (point-max))
+ (string-replace "\t" "" "
+e foo
+f foo (currently shadowed by `bar')
+g .. h foo
+"))))))
+
+(ert-deftest help--describe-vector/bug-9293-same-command-does-not-shadow ()
+ "Check that a command can't be shadowed by the same command."
+ (let ((range-map
+ (let ((map (make-keymap)))
+ (define-key map "0" 'foo)
+ (define-key map "1" 'foo)
+ (define-key map "2" 'foo)
+ (define-key map "3" 'foo)
+ map))
+ (shadow-map
+ (let ((map (make-keymap)))
+ (define-key map "0" 'foo)
+ (define-key map "1" 'foo)
+ (define-key map "2" 'foo)
+ (define-key map "3" 'foo)
+ map)))
+ (with-temp-buffer
+ (help--describe-vector (cadr range-map) nil #'help--describe-command
+ t shadow-map range-map t)
+ (should (equal (buffer-substring-no-properties (point-min) (point-max))
+ (string-replace "\t" "" "
+0 .. 3 foo
+"))))))
+
+(ert-deftest keymap--key-description ()
+ (should (equal (key-description [right] [?\C-x])
+ "C-x <right>"))
+ (should (equal (key-description [M-H-right] [?\C-x])
+ "C-x M-H-<right>"))
+ (should (equal (single-key-description 'home)
+ "<home>"))
+ (should (equal (single-key-description 'home t)
+ "home"))
+ (should (equal (single-key-description 'C-s-home)
+ "C-s-<home>")))
+
+(ert-deftest keymap-test-lookups ()
+ (should (eq (lookup-key (current-global-map) "\C-x\C-f") 'find-file))
+ (should (eq (lookup-key (current-global-map) [(control x) (control f)])
+ 'find-file))
+ (should (eq (lookup-key (current-global-map) ["C-x C-f"]) 'find-file))
+ (should (eq (lookup-key (current-global-map) [?\C-x ?\C-f]) 'find-file)))
+
+(ert-deftest keymap-removal ()
+ ;; Set to nil.
+ (let ((map (define-keymap "a" 'foo)))
+ (should (equal map '(keymap (97 . foo))))
+ (define-key map "a" nil)
+ (should (equal map '(keymap (97)))))
+ ;; Remove.
+ (let ((map (define-keymap "a" 'foo)))
+ (should (equal map '(keymap (97 . foo))))
+ (define-key map "a" nil t)
+ (should (equal map '(keymap)))))
+
+(ert-deftest keymap-removal-inherit ()
+ ;; Set to nil.
+ (let ((parent (make-sparse-keymap))
+ (child (make-keymap)))
+ (set-keymap-parent child parent)
+ (define-key parent [?a] 'foo)
+ (define-key child [?a] 'bar)
+
+ (should (eq (lookup-key child [?a]) 'bar))
+ (define-key child [?a] nil)
+ (should (eq (lookup-key child [?a]) nil)))
+ ;; Remove.
+ (let ((parent (make-sparse-keymap))
+ (child (make-keymap)))
+ (set-keymap-parent child parent)
+ (define-key parent [?a] 'foo)
+ (define-key child [?a] 'bar)
+
+ (should (eq (lookup-key child [?a]) 'bar))
+ (define-key child [?a] nil t)
+ (should (eq (lookup-key child [?a]) 'foo))))
+
+(ert-deftest keymap-text-char-description ()
+ (should (equal (text-char-description ?a) "a"))
+ (should (equal (text-char-description ?\s) " "))
+ (should (equal (text-char-description ?\t) "^I"))
+ (should (equal (text-char-description ?\^C) "^C"))
+ (should (equal (text-char-description ?\^?) "^?"))
+ (should (equal (text-char-description #x80) "€"))
+ (should (equal (text-char-description ?å) "å"))
+ (should (equal (text-char-description ?Ş) "Ş"))
+ (should (equal (text-char-description ?Ā) "Ā"))
+ (should-error (text-char-description "c"))
+ (should-error (text-char-description [?\C-x ?l]))
+ (should-error (text-char-description ?\M-c))
+ (should-error (text-char-description ?\s-c)))
+
+(ert-deftest test-non-key-events ()
+ ;; Dummy command.
+ (declare-function keymap-tests-command nil)
+ (should (null (where-is-internal 'keymap-tests-command)))
+ (keymap-set global-map "C-c g" #'keymap-tests-command)
+ (should (equal (where-is-internal 'keymap-tests-command) '([3 103])))
+ (keymap-set global-map "<keymap-tests-event>" #'keymap-tests-command)
+ (should (equal (where-is-internal 'keymap-tests-command)
+ '([keymap-tests-event] [3 103])))
+ (make-non-key-event 'keymap-tests-event)
+ (should (equal (where-is-internal 'keymap-tests-command) '([3 103]))))
+
+(ert-deftest keymap-test-duplicate-definitions ()
+ "Check that defvar-keymap rejects duplicate key definitions."
+ (should-error
+ (defvar-keymap
+ ert-keymap-duplicate
+ "a" #'next-line
+ "a" #'previous-line))
+ (should-error
+ (define-keymap
+ "a" #'next-line
+ "a" #'previous-line)))
+
(provide 'keymap-tests)
;;; keymap-tests.el ends here
diff --git a/test/src/lcms-tests.el b/test/src/lcms-tests.el
index cc324af68ba..1829a7ea1f1 100644
--- a/test/src/lcms-tests.el
+++ b/test/src/lcms-tests.el
@@ -1,6 +1,6 @@
;;; lcms-tests.el --- tests for Little CMS interface -*- lexical-binding: t -*-
-;; Copyright (C) 2017 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2022 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
@@ -35,6 +35,13 @@
(require 'ert)
(require 'color)
+(declare-function lcms-jab->jch "lcms.c")
+(declare-function lcms-jch->jab "lcms.c")
+(declare-function lcms-xyz->jch "lcms.c")
+(declare-function lcms-jch->xyz "lcms.c")
+(declare-function lcms-temp->white-point "lcms.c")
+(declare-function lcms-cam02-ucs "lcms.c")
+
(defconst lcms-colorspacious-d65 '(0.95047 1.0 1.08883)
"D65 white point from colorspacious.")
@@ -95,7 +102,7 @@ B is considered the exact value."
'(0.29902 0.31485 1.0))))
(ert-deftest lcms-roundtrip ()
- "Test accuracy of converting to and from different color spaces"
+ "Test accuracy of converting to and from different color spaces."
(skip-unless (featurep 'lcms2))
(should
(let ((color '(.5 .3 .7)))
@@ -109,7 +116,7 @@ B is considered the exact value."
0.0001))))
(ert-deftest lcms-ciecam02-gold ()
- "Test CIE CAM02 JCh gold values"
+ "Test CIE CAM02 JCh gold values."
(skip-unless (featurep 'lcms2))
(should
(lcms-triple-approx-p
diff --git a/test/src/lread-resources/lazydoc.el b/test/src/lread-resources/lazydoc.el
new file mode 100644
index 00000000000..cb434c239b5
--- /dev/null
+++ b/test/src/lread-resources/lazydoc.el
Binary files differ
diff --git a/test/data/somelib.el b/test/src/lread-resources/somelib.el
index 7b8d4037396..7b8d4037396 100644
--- a/test/data/somelib.el
+++ b/test/src/lread-resources/somelib.el
diff --git a/test/data/somelib2.el b/test/src/lread-resources/somelib2.el
index 05156145a22..05156145a22 100644
--- a/test/data/somelib2.el
+++ b/test/src/lread-resources/somelib2.el
diff --git a/test/src/lread-tests.el b/test/src/lread-tests.el
index ac730b4f005..57143dd81e5 100644
--- a/test/src/lread-tests.el
+++ b/test/src/lread-tests.el
@@ -1,23 +1,23 @@
;;; lread-tests.el --- tests for lread.c -*- lexical-binding: t; -*-
-;; Copyright (C) 2016-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2022 Free Software Foundation, Inc.
;; Author: Philipp Stephani <phst@google.com>
;; This file is part of GNU Emacs.
-;; This program is free software; you can redistribute it and/or modify
+;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
-;; This program is distributed in the hope that it will be useful,
+;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
-;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
@@ -25,6 +25,9 @@
;;; Code:
+(require 'ert)
+(require 'ert-x)
+
(ert-deftest lread-char-number ()
(should (equal (read "?\\N{U+A817}") #xA817)))
@@ -112,59 +115,37 @@
(should-error (read "#24r") :type 'invalid-read-syntax)
(should-error (read "#") :type 'invalid-read-syntax))
+(ert-deftest lread-char-modifiers ()
+ (should (eq ?\C-\M-é (+ (- ?\M-a ?a) ?\C-é)))
+ (should (eq (- ?\C-ŗ ?ŗ) (- ?\C-é ?é))))
+
(ert-deftest lread-record-1 ()
(should (equal '(#s(foo) #s(foo))
(read "(#1=#s(foo) #1#)"))))
-(defmacro lread-tests--with-temp-file (file-name-var &rest body)
- (declare (indent 1))
- (cl-check-type file-name-var symbol)
- `(let ((,file-name-var (make-temp-file "emacs")))
- (unwind-protect
- (progn ,@body)
- (delete-file ,file-name-var))))
-
(defun lread-tests--last-message ()
(with-current-buffer "*Messages*"
(save-excursion
(goto-char (point-max))
(skip-chars-backward "\n")
- (buffer-substring (line-beginning-position) (point)))))
+ (buffer-substring (pos-bol) (point)))))
(ert-deftest lread-tests--unescaped-char-literals ()
"Check that loading warns about unescaped character
literals (Bug#20852)."
- (lread-tests--with-temp-file file-name
+ (ert-with-temp-file file-name
(write-region "?) ?( ?; ?\" ?[ ?]" nil file-name)
(should (equal (load file-name nil :nomessage :nosuffix) t))
(should (equal (lread-tests--last-message)
(concat (format-message "Loading `%s': " file-name)
"unescaped character literals "
- "`?\"', `?(', `?)', `?;', `?[', `?]' detected!")))))
-
-(ert-deftest lread-tests--funny-quote-symbols ()
- "Check that 'smart quotes' or similar trigger errors in symbol names."
- (dolist (quote-char
- '(#x2018 ;; LEFT SINGLE QUOTATION MARK
- #x2019 ;; RIGHT SINGLE QUOTATION MARK
- #x201B ;; SINGLE HIGH-REVERSED-9 QUOTATION MARK
- #x201C ;; LEFT DOUBLE QUOTATION MARK
- #x201D ;; RIGHT DOUBLE QUOTATION MARK
- #x201F ;; DOUBLE HIGH-REVERSED-9 QUOTATION MARK
- #x301E ;; DOUBLE PRIME QUOTATION MARK
- #xFF02 ;; FULLWIDTH QUOTATION MARK
- #xFF07 ;; FULLWIDTH APOSTROPHE
- ))
- (let ((str (format "%cfoo" quote-char)))
- (should-error (read str) :type 'invalid-read-syntax)
- (should (eq (read (concat "\\" str)) (intern str))))))
+ "`?\"', `?(', `?)', `?;', `?[', `?]' detected, "
+ "`?\\\"', `?\\(', `?\\)', `?\\;', `?\\[', `?\\]' "
+ "expected!")))))
(ert-deftest lread-test-bug26837 ()
"Test for https://debbugs.gnu.org/26837 ."
- (let ((load-path (cons
- (file-name-as-directory
- (expand-file-name "data" (getenv "EMACS_TEST_DIRECTORY")))
- load-path)))
+ (let ((load-path (cons (ert-resource-directory) load-path)))
(load "somelib" nil t)
(should (string-suffix-p "/somelib.el" (caar load-history)))
(load "somelib2" nil t)
@@ -172,19 +153,190 @@ literals (Bug#20852)."
(load "somelib" nil t)
(should (string-suffix-p "/somelib.el" (caar load-history)))))
-(ert-deftest lread-tests--old-style-backquotes ()
- "Check that loading warns about old-style backquotes."
- (lread-tests--with-temp-file file-name
- (write-region "(` (a b))" nil file-name)
- (should (equal (load file-name nil :nomessage :nosuffix) t))
- (should (equal (lread-tests--last-message)
- (concat (format-message "Loading `%s': " file-name)
- "old-style backquotes detected!")))))
-
(ert-deftest lread-lread--substitute-object-in-subtree ()
(let ((x (cons 0 1)))
(setcar x x)
(lread--substitute-object-in-subtree x 1 t)
(should (eq x (cdr x)))))
+(ert-deftest lread-long-hex-integer ()
+ (should (bignump (read "#xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"))))
+
+(ert-deftest lread-test-bug-31186 ()
+ (with-temp-buffer
+ (insert ";; -*- -:*-")
+ (should-not
+ ;; This used to crash in lisp_file_lexically_bound_p before the
+ ;; bug was fixed.
+ (eval-buffer))))
+
+(ert-deftest lread-invalid-bytecodes ()
+ (should-error
+ (let ((load-force-doc-strings t)) (read "#[0 \"\"]"))))
+
+(ert-deftest lread-string-to-number-trailing-dot ()
+ (dolist (n (list (* most-negative-fixnum most-negative-fixnum)
+ (1- most-negative-fixnum) most-negative-fixnum
+ (1+ most-negative-fixnum) -1 0 1
+ (1- most-positive-fixnum) most-positive-fixnum
+ (1+ most-positive-fixnum)
+ (* most-positive-fixnum most-positive-fixnum)))
+ (should (= n (string-to-number (format "%d." n))))))
+
+(ert-deftest lread-circular-hash ()
+ (should-error (read "#s(hash-table data #0=(#0# . #0#))")))
+
+(ert-deftest test-inhibit-interaction ()
+ (let ((inhibit-interaction t))
+ (should-error (read-char "foo: "))
+ (should-error (read-event "foo: "))
+ (should-error (read-char-exclusive "foo: "))))
+
+(ert-deftest lread-float ()
+ (should (equal (read "13") 13))
+ (should (equal (read "+13") 13))
+ (should (equal (read "-13") -13))
+ (should (equal (read "13.") 13))
+ (should (equal (read "+13.") 13))
+ (should (equal (read "-13.") -13))
+ (should (equal (read "13.25") 13.25))
+ (should (equal (read "+13.25") 13.25))
+ (should (equal (read "-13.25") -13.25))
+ (should (equal (read ".25") 0.25))
+ (should (equal (read "+.25") 0.25))
+ (should (equal (read "-.25") -0.25))
+ (should (equal (read "13e4") 130000.0))
+ (should (equal (read "+13e4") 130000.0))
+ (should (equal (read "-13e4") -130000.0))
+ (should (equal (read "13e+4") 130000.0))
+ (should (equal (read "+13e+4") 130000.0))
+ (should (equal (read "-13e+4") -130000.0))
+ (should (equal (read "625e-4") 0.0625))
+ (should (equal (read "+625e-4") 0.0625))
+ (should (equal (read "-625e-4") -0.0625))
+ (should (equal (read "1.25e2") 125.0))
+ (should (equal (read "+1.25e2") 125.0))
+ (should (equal (read "-1.25e2") -125.0))
+ (should (equal (read "1.25e+2") 125.0))
+ (should (equal (read "+1.25e+2") 125.0))
+ (should (equal (read "-1.25e+2") -125.0))
+ (should (equal (read "1.25e-1") 0.125))
+ (should (equal (read "+1.25e-1") 0.125))
+ (should (equal (read "-1.25e-1") -0.125))
+ (should (equal (read "4.e3") 4000.0))
+ (should (equal (read "+4.e3") 4000.0))
+ (should (equal (read "-4.e3") -4000.0))
+ (should (equal (read "4.e+3") 4000.0))
+ (should (equal (read "+4.e+3") 4000.0))
+ (should (equal (read "-4.e+3") -4000.0))
+ (should (equal (read "5.e-1") 0.5))
+ (should (equal (read "+5.e-1") 0.5))
+ (should (equal (read "-5.e-1") -0.5))
+ (should (equal (read "0") 0))
+ (should (equal (read "+0") 0))
+ (should (equal (read "-0") 0))
+ (should (equal (read "0.") 0))
+ (should (equal (read "+0.") 0))
+ (should (equal (read "-0.") 0))
+ (should (equal (read "0.0") 0.0))
+ (should (equal (read "+0.0") 0.0))
+ (should (equal (read "-0.0") -0.0))
+ (should (equal (read "0e5") 0.0))
+ (should (equal (read "+0e5") 0.0))
+ (should (equal (read "-0e5") -0.0))
+ (should (equal (read "0e-5") 0.0))
+ (should (equal (read "+0e-5") 0.0))
+ (should (equal (read "-0e-5") -0.0))
+ (should (equal (read ".0e-5") 0.0))
+ (should (equal (read "+.0e-5") 0.0))
+ (should (equal (read "-.0e-5") -0.0))
+ (should (equal (read "0.0e-5") 0.0))
+ (should (equal (read "+0.0e-5") 0.0))
+ (should (equal (read "-0.0e-5") -0.0))
+ (should (equal (read "0.e-5") 0.0))
+ (should (equal (read "+0.e-5") 0.0))
+ (should (equal (read "-0.e-5") -0.0))
+ )
+
+(defun lread-test-read-and-print (str)
+ (let* ((read-circle t)
+ (print-circle t)
+ (val (read-from-string str)))
+ (if (consp val)
+ (prin1-to-string (car val))
+ (error "reading %S failed: %S" str val))))
+
+(defconst lread-test-circle-cases
+ '("#1=(#1# . #1#)"
+ "#1=[#1# a #1#]"
+ "#1=(#2=[#1# #2#] . #1#)"
+ "#1=(#2=[#1# #2#] . #2#)"
+ "#1=[#2=(#1# . #2#)]"
+ "#1=(#2=[#3=(#1# . #2#) #4=(#3# . #4#)])"
+ ))
+
+(ert-deftest lread-circle ()
+ (dolist (str lread-test-circle-cases)
+ (ert-info (str :prefix "input: ")
+ (should (equal (lread-test-read-and-print str) str))))
+ (should-error (read-from-string "#1=#1#") :type 'invalid-read-syntax))
+
+(ert-deftest lread-deeply-nested ()
+ ;; Check that we can read a deeply nested data structure correctly.
+ (let ((levels 10000)
+ (prefix nil)
+ (suffix nil))
+ (dotimes (_ levels)
+ (push "([#s(r " prefix)
+ (push ")])" suffix))
+ (let ((str (concat (apply #'concat prefix)
+ "a"
+ (apply #'concat suffix))))
+ (let* ((read-circle t)
+ (result (read-from-string str)))
+ (should (equal (cdr result) (length str)))
+ ;; Check the result. (We can't build a reference value and compare
+ ;; using `equal' because that function is currently depth-limited.)
+ (named-let check ((x (car result)) (level 0))
+ (if (equal level levels)
+ (should (equal x 'a))
+ (should (and (consp x) (null (cdr x))))
+ (let ((x2 (car x)))
+ (should (and (vectorp x2) (equal (length x2) 1)))
+ (let ((x3 (aref x2 0)))
+ (should (and (recordp x3) (equal (length x3) 2)
+ (equal (aref x3 0) 'r)))
+ (check (aref x3 1) (1+ level))))))))))
+
+(ert-deftest lread-misc ()
+ ;; Regression tests for issues found and fixed in bug#55676:
+ ;; Non-breaking space after a dot makes it a dot token.
+ (should (equal (read-from-string "(a .\u00A0b)")
+ '((a . b) . 7)))
+ ;; #_ without symbol following is the interned empty symbol.
+ (should (equal (read-from-string "#_")
+ '(## . 2))))
+
+(ert-deftest lread-escaped-lf ()
+ ;; ?\LF should signal an error; \LF is ignored inside string literals.
+ (should-error (read-from-string "?\\\n x"))
+ (should (equal (read-from-string "\"a\\\nb\"") '("ab" . 6))))
+
+(ert-deftest lread-force-load-doc-strings ()
+ ;; Verify that lazy doc strings are loaded lazily by default,
+ ;; but eagerly with `force-load-doc-strings' set.
+ (let ((file (expand-file-name "lazydoc.el" (ert-resource-directory))))
+ (fmakunbound 'lazydoc-fun)
+ (load file)
+ (let ((f (symbol-function 'lazydoc-fun)))
+ (should (byte-code-function-p f))
+ (should (equal (aref f 4) (cons file 87))))
+
+ (fmakunbound 'lazydoc-fun)
+ (let ((load-force-doc-strings t))
+ (load file)
+ (let ((f (symbol-function 'lazydoc-fun)))
+ (should (byte-code-function-p f))
+ (should (equal (aref f 4) "My little\ndoc string\nhere"))))))
+
;;; lread-tests.el ends here
diff --git a/test/src/marker-tests.el b/test/src/marker-tests.el
index 2540f157e76..32e4804fe7d 100644
--- a/test/src/marker-tests.el
+++ b/test/src/marker-tests.el
@@ -1,6 +1,6 @@
;;; marker-tests.el --- tests for marker.c functions -*- lexical-binding: t -*-
-;; Copyright (C) 2016-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2022 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -57,4 +57,4 @@
(set-marker marker-2 marker-1)
(should (goto-char marker-2))))
-;;; marker-tests.el ends here.
+;;; marker-tests.el ends here
diff --git a/test/src/minibuf-tests.el b/test/src/minibuf-tests.el
index aba5ca51707..68800729502 100644
--- a/test/src/minibuf-tests.el
+++ b/test/src/minibuf-tests.el
@@ -1,6 +1,6 @@
;;; minibuf-tests.el --- tests for minibuf.c functions -*- lexical-binding: t -*-
-;; Copyright (C) 2016-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2022 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -399,5 +399,31 @@
(minibuf-tests--test-completion-regexp
#'minibuf-tests--strings-to-symbol-hashtable))
+(ert-deftest test-try-completion-ignore-case ()
+ (let ((completion-ignore-case t))
+ (should (equal (try-completion "bar" '("bAr" "barfoo")) "bAr"))
+ (should (equal (try-completion "bar" '("bArfoo" "barbaz")) "bar"))
+ (should (equal (try-completion "bar" '("bArfoo" "barbaz"))
+ (try-completion "bar" '("barbaz" "bArfoo"))))
+ ;; bug#11339
+ (should (equal (try-completion "baz" '("baz" "bAz")) "baz")) ;And not t!
+ (should (equal (try-completion "baz" '("bAz" "baz"))
+ (try-completion "baz" '("baz" "bAz"))))))
+
+(ert-deftest test-inhibit-interaction ()
+ (let ((inhibit-interaction t))
+ (should-error (read-from-minibuffer "foo: ") :type 'inhibited-interaction)
+
+ (should-error (y-or-n-p "Foo?") :type 'inhibited-interaction)
+ (should-error (yes-or-no-p "Foo?") :type 'inhibited-interaction)
+ (should-error (read-no-blanks-input "foo: ") :type 'inhibited-interaction)
+
+ ;; See that we get the expected error.
+ (should (eq (condition-case nil
+ (read-from-minibuffer "foo: ")
+ (inhibited-interaction 'inhibit)
+ (error nil))
+ 'inhibit))))
+
;;; minibuf-tests.el ends here
diff --git a/test/src/print-tests.el b/test/src/print-tests.el
index b8f6c797dab..faab196f22f 100644
--- a/test/src/print-tests.el
+++ b/test/src/print-tests.el
@@ -1,32 +1,112 @@
;;; print-tests.el --- tests for src/print.c -*- lexical-binding: t; -*-
-;; Copyright (C) 2014-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2022 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
-;; This program is free software; you can redistribute it and/or modify
+;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
-;; This program is distributed in the hope that it will be useful,
+;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
-;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Code:
(require 'ert)
-(ert-deftest print-hex-backslash ()
+;; Support sharing test code with cl-print-tests.
+
+(defalias 'print-tests--prin1-to-string #'identity
+ "The function to print to a string which is under test.")
+
+(defmacro print-tests--deftest (name arg &rest docstring-keys-and-body)
+ "Test both print.c and cl-print.el at once."
+ (declare (debug ert-deftest)
+ (doc-string 3)
+ (indent 2))
+ (let ((clname (intern (concat (symbol-name name) "-cl-print")))
+ (doc (when (stringp (car-safe docstring-keys-and-body))
+ (list (pop docstring-keys-and-body))))
+ (keys-and-values nil))
+ (while (keywordp (car-safe docstring-keys-and-body))
+ (let ((key (pop docstring-keys-and-body))
+ (val (pop docstring-keys-and-body)))
+ (push val keys-and-values)
+ (push key keys-and-values)))
+ `(progn
+ ;; Set print-tests--prin1-to-string at both declaration and
+ ;; runtime, so that it can be used by the :expected-result
+ ;; keyword.
+ (cl-letf (((symbol-function #'print-tests--prin1-to-string)
+ #'prin1-to-string))
+ (ert-deftest ,name ,arg
+ ,@doc
+ ,@keys-and-values
+ (cl-letf (((symbol-function #'print-tests--prin1-to-string)
+ #'prin1-to-string))
+ ,@docstring-keys-and-body)))
+ (cl-letf (((symbol-function #'print-tests--prin1-to-string)
+ #'cl-prin1-to-string))
+ (ert-deftest ,clname ,arg
+ ,@doc
+ ,@keys-and-values
+ (cl-letf (((symbol-function #'print-tests--prin1-to-string)
+ #'cl-prin1-to-string))
+ ,@docstring-keys-and-body))))))
+
+(print-tests--deftest print-hex-backslash ()
(should (string= (let ((print-escape-multibyte t)
(print-escape-newlines t))
- (prin1-to-string "\u00A2\ff"))
+ (print-tests--prin1-to-string "\u00A2\ff"))
"\"\\x00a2\\ff\"")))
+(defun print-tests--prints-with-charset-p (ch odd-charset)
+ "Return t if print function being tested prints CH with the `charset' property.
+CH is propertized with a `charset' value according to
+ODD-CHARSET: if nil, then use the one returned by `char-charset',
+otherwise, use a different charset."
+ (integerp
+ (string-match
+ "charset"
+ (print-tests--prin1-to-string
+ (propertize (string ch)
+ 'charset
+ (if odd-charset
+ (cl-find (char-charset ch) charset-list :test-not #'eq)
+ (char-charset ch)))))))
+
+(print-tests--deftest print-charset-text-property-nil ()
+ :expected-result (if (eq (symbol-function #'print-tests--prin1-to-string)
+ #'cl-prin1-to-string) :failed :passed)
+ (let ((print-charset-text-property nil))
+ (should-not (print-tests--prints-with-charset-p ?\xf6 t)) ; Bug#31376.
+ (should-not (print-tests--prints-with-charset-p ?a t))
+ (should-not (print-tests--prints-with-charset-p ?\xf6 nil))
+ (should-not (print-tests--prints-with-charset-p ?a nil))))
+
+(print-tests--deftest print-charset-text-property-default ()
+ :expected-result (if (eq (symbol-function #'print-tests--prin1-to-string)
+ #'cl-prin1-to-string) :failed :passed)
+ (let ((print-charset-text-property 'default))
+ (should (print-tests--prints-with-charset-p ?\xf6 t))
+ (should-not (print-tests--prints-with-charset-p ?a t))
+ (should-not (print-tests--prints-with-charset-p ?\xf6 nil))
+ (should-not (print-tests--prints-with-charset-p ?a nil))))
+
+(print-tests--deftest print-charset-text-property-t ()
+ (let ((print-charset-text-property t))
+ (should (print-tests--prints-with-charset-p ?\xf6 t))
+ (should (print-tests--prints-with-charset-p ?a t))
+ (should (print-tests--prints-with-charset-p ?\xf6 nil))
+ (should (print-tests--prints-with-charset-p ?a nil))))
+
(ert-deftest terpri ()
(should (string= (with-output-to-string
(princ 'abc)
@@ -58,5 +138,411 @@
(buffer-string))
"--------\n"))))
+(print-tests--deftest print-read-roundtrip ()
+ (let ((syms (list '## '& '* '+ '- '/ '0E '0e '< '= '> 'E 'E0 'NaN '\"
+ '\# '\#x0 '\' '\'\' '\( '\) '\+00 '\, '\-0 '\. '\.0
+ '\0 '\0.0 '\0E0 '\0e0 '\1E+ '\1E+NaN '\1e+ '\1e+NaN
+ '\; '\? '\[ '\\ '\] '\` '_ 'a 'e 'e0 'x
+ '{ '| '} '~ : '\’ '\’bar
+ (intern "\t") (intern "\n") (intern " ")
+ (intern "\N{NO-BREAK SPACE}")
+ (intern "\N{ZERO WIDTH SPACE}")
+ (intern "\0"))))
+ (dolist (sym syms)
+ (should (eq (read (print-tests--prin1-to-string sym)) sym))
+ (dolist (sym1 syms)
+ (let ((sym2 (intern (concat (symbol-name sym) (symbol-name sym1)))))
+ (should (eq (read (print-tests--prin1-to-string sym2)) sym2)))))))
+
+(print-tests--deftest print-bignum ()
+ (let* ((str "999999999999999999999999999999999")
+ (val (read str)))
+ (should (> val most-positive-fixnum))
+ (should (equal (print-tests--prin1-to-string val) str))))
+
+(print-tests--deftest print-tests-print-gensym ()
+ "Printing observes `print-gensym'."
+ (let* ((sym1 (gensym))
+ (syms (list sym1 (gensym "x") (make-symbol "y") sym1)))
+ (let* ((print-circle nil)
+ (printed-with (let ((print-gensym t))
+ (print-tests--prin1-to-string syms)))
+ (printed-without (let ((print-gensym nil))
+ (print-tests--prin1-to-string syms))))
+ (should (string-match
+ "(#:\\(g[[:digit:]]+\\) #:x[[:digit:]]+ #:y #:\\(g[[:digit:]]+\\))$"
+ printed-with))
+ (should (string= (match-string 1 printed-with)
+ (match-string 2 printed-with)))
+ (should (string-match "(g[[:digit:]]+ x[[:digit:]]+ y g[[:digit:]]+)$"
+ printed-without)))
+ (let* ((print-circle t)
+ (printed-with (let ((print-gensym t))
+ (print-tests--prin1-to-string syms)))
+ (printed-without (let ((print-gensym nil))
+ (print-tests--prin1-to-string syms))))
+ (should (string-match "(#1=#:g[[:digit:]]+ #:x[[:digit:]]+ #:y #1#)$"
+ printed-with))
+ (should (string-match "(g[[:digit:]]+ x[[:digit:]]+ y g[[:digit:]]+)$"
+ printed-without)))))
+
+(print-tests--deftest print-tests-continuous-numbering ()
+ "Printing observes `print-continuous-numbering'."
+ ;; cl-print does not support print-continuous-numbering.
+ :expected-result (if (eq (symbol-function #'print-tests--prin1-to-string)
+ #'cl-prin1-to-string)
+ :failed :passed)
+ (let* ((x (list 1))
+ (y "hello")
+ (g (gensym))
+ (g2 (gensym))
+ (print-circle t)
+ (print-gensym t))
+ (let ((print-continuous-numbering t)
+ (print-number-table nil))
+ (should (string-match
+ "(#1=(1) #1# #2=\"hello\" #2#)(#3=#:g[[:digit:]]+ #3#)(#1# #2# #3#)#2#$"
+ (mapconcat #'print-tests--prin1-to-string
+ `((,x ,x ,y ,y) (,g ,g) (,x ,y ,g) ,y)))))
+
+ ;; This is the special case for byte-compile-output-docform
+ ;; mentioned in a comment in print_preprocess. When
+ ;; print-continuous-numbering and print-circle and print-gensym
+ ;; are all non-nil, print all gensyms with numbers even if they
+ ;; only occur once.
+ (let ((print-continuous-numbering t)
+ (print-number-table nil))
+ (should (string-match
+ "(#1=#:g[[:digit:]]+ #2=#:g[[:digit:]]+)$"
+ (print-tests--prin1-to-string (list g g2)))))))
+
+(cl-defstruct print--test a b)
+
+(print-tests--deftest print-tests-1 ()
+ "Test print code."
+ (let ((x (make-print--test :a 1 :b 2))
+ (rec (cond
+ ((eq (symbol-function #'print-tests--prin1-to-string) 'prin1-to-string)
+ "#s(print--test 1 2)")
+ ((eq (symbol-function #'print-tests--prin1-to-string) 'cl-prin1-to-string)
+ "#s(print--test :a 1 :b 2)")
+ (t (cl-assert nil)))))
+
+ (let ((print-circle nil))
+ (should (equal (print-tests--prin1-to-string `((x . ,x) (y . ,x)))
+ (format "((x . %s) (y . %s))" rec rec))))
+ (let ((print-circle t))
+ (should (equal (print-tests--prin1-to-string `((x . ,x) (y . ,x)))
+ (format "((x . #1=%s) (y . #1#))" rec))))))
+
+(print-tests--deftest print-tests-2 ()
+ (let ((x (record 'foo 1 2 3)))
+ (should (equal
+ x
+ (car (read-from-string (with-output-to-string (prin1 x))))))
+ (let ((print-circle t))
+ (should (string-match
+ "\\`(#1=#s(foo 1 2 3) #1#)\\'"
+ (print-tests--prin1-to-string (list x x)))))))
+
+(cl-defstruct (print-tests-struct
+ (:constructor print-tests-con))
+ a b c d e)
+
+(print-tests--deftest print-tests-3 ()
+ "Printing observes `print-length'."
+ (let ((long-list (make-list 5 'a))
+ (long-vec (make-vector 5 'b))
+ ;; (long-struct (print-tests-con))
+ ;; (long-string (make-string 5 ?a))
+ (print-length 4))
+ (should (equal "(a a a a ...)" (print-tests--prin1-to-string long-list)))
+ (should (equal "[b b b b ...]" (print-tests--prin1-to-string long-vec)))
+ ;; This one only prints 3 nils. Should it print 4?
+ ;; (should (equal "#s(print-tests-struct nil nil nil nil ...)"
+ ;; (print-tests--prin1-to-string long-struct)))
+ ;; This one is only supported by cl-print
+ ;; (should (equal "\"aaaa...\"" (cl-print-tests--prin1-to-string long-string)))
+ ))
+
+(print-tests--deftest print-tests-4 ()
+ "Printing observes `print-level'."
+ (let* ((deep-list '(a (b (c (d (e))))))
+ (buried-vector '(a (b (c (d [e])))))
+ (deep-struct (print-tests-con))
+ (buried-struct `(a (b (c (d ,deep-struct)))))
+ (buried-string '(a (b (c (d #("hello" 0 5 (print-test t)))))))
+ (buried-simple-string '(a (b (c (d "hello")))))
+ (print-level 4))
+ (setf (print-tests-struct-a deep-struct) deep-list)
+ (should (equal "(a (b (c (d ...))))" (print-tests--prin1-to-string deep-list)))
+ (should (equal "(a (b (c (d \"hello\"))))"
+ (print-tests--prin1-to-string buried-simple-string)))
+ (cond
+ ((eq (symbol-function #'print-tests--prin1-to-string) #'prin1-to-string)
+ (should (equal "(a (b (c (d [e]))))" (print-tests--prin1-to-string buried-vector)))
+ (should (equal "(a (b (c (d #s(print-tests-struct ... nil nil nil nil)))))"
+ (print-tests--prin1-to-string buried-struct)))
+ (should (equal "(a (b (c (d #(\"hello\" 0 5 ...)))))"
+ (print-tests--prin1-to-string buried-string)))
+ (should (equal "#s(print-tests-struct (a (b (c ...))) nil nil nil nil)"
+ (print-tests--prin1-to-string deep-struct))))
+
+ ((eq (symbol-function #'print-tests--prin1-to-string) #'cl-prin1-to-string)
+ (should (equal "(a (b (c (d ...))))" (print-tests--prin1-to-string buried-vector)))
+ (should (equal "(a (b (c (d ...))))" (print-tests--prin1-to-string buried-struct)))
+ (should (equal "(a (b (c (d ...))))" (print-tests--prin1-to-string buried-string)))
+ (should (equal "#s(print-tests-struct :a (a (b (c ...))) :b nil :c nil :d nil :e nil)"
+ (print-tests--prin1-to-string deep-struct))))
+ (t (cl-assert nil)))))
+
+(print-tests--deftest print-tests-5 ()
+ "Printing observes `print-quoted'."
+ (let ((quoted-stuff '('a #'b `(,c ,@d))))
+ (let ((print-quoted t))
+ (should (equal "('a #'b `(,c ,@d))"
+ (print-tests--prin1-to-string quoted-stuff))))
+ (let ((print-quoted nil))
+ (should (equal "((quote a) (function b) (\\` ((\\, c) (\\,@ d))))"
+ (print-tests--prin1-to-string quoted-stuff))))))
+
+(print-tests--deftest print-tests-strings ()
+ "Can print strings and propertized strings."
+ (let* ((str1 "abcdefghij")
+ (str2 #("abcdefghij" 3 6 (bold t) 7 9 (italic t)))
+ (str3 #("abcdefghij" 0 10 (test t)))
+ (obj '(a b))
+ ;; Since the byte compiler reuses string literals,
+ ;; and the put-text-property call is destructive, use
+ ;; copy-sequence to make a new string.
+ (str4 (copy-sequence "abcdefghij")))
+ (put-text-property 0 5 'test obj str4)
+ (put-text-property 7 10 'test obj str4)
+
+ (should (equal "\"abcdefghij\"" (print-tests--prin1-to-string str1)))
+ (should (equal "#(\"abcdefghij\" 3 6 (bold t) 7 9 (italic t))"
+ (print-tests--prin1-to-string str2)))
+ (should (equal "#(\"abcdefghij\" 0 10 (test t))"
+ (print-tests--prin1-to-string str3)))
+ (let ((print-circle nil))
+ (should
+ (equal
+ "#(\"abcdefghij\" 0 5 (test (a b)) 7 10 (test (a b)))"
+ (print-tests--prin1-to-string str4))))
+ (let ((print-circle t))
+ (should
+ (equal
+ "#(\"abcdefghij\" 0 5 (test #1=(a b)) 7 10 (test #1#))"
+ (print-tests--prin1-to-string str4))))))
+
+(print-tests--deftest print-circle ()
+ (let ((x '(#1=(a . #1#) #1#)))
+ (let ((print-circle nil))
+ (should (string-match "\\`((a . #[0-9]) (a . #[0-9]))\\'"
+ (print-tests--prin1-to-string x))))
+ (let ((print-circle t))
+ (should (equal "(#1=(a . #1#) #1#)" (print-tests--prin1-to-string x))))))
+
+(print-tests--deftest print-circle-2 ()
+ ;; Bug#31146.
+ (let ((x '(0 . #1=(0 . #1#))))
+ (let ((print-circle nil))
+ (should (string-match "\\`(0\\( 0\\)* . #[0-9]+)\\'"
+ (print-tests--prin1-to-string x))))
+ (let ((print-circle t))
+ (should (equal "(0 . #1=(0 . #1#))" (print-tests--prin1-to-string x))))))
+
+(print-tests--deftest error-message-string-circular ()
+ (let ((err (list 'error)))
+ (setcdr err err)
+ (should-error (error-message-string err) :type 'circular-list)))
+
+(print-tests--deftest print-hash-table-test ()
+ (should
+ (string-match
+ "data (2 3)"
+ (let ((h (make-hash-table)))
+ (puthash 1 2 h)
+ (puthash 2 3 h)
+ (remhash 1 h)
+ (format "%S" h))))
+
+ (should
+ (string-match
+ "data ()"
+ (let ((h (make-hash-table)))
+ (let ((print-length 0))
+ (format "%S" h)))))
+
+ (should
+ (string-match
+ "data (99 99)"
+ (let ((h (make-hash-table)))
+ (dotimes (i 100)
+ (puthash i i h))
+ (dotimes (i 99)
+ (remhash i h))
+ (let ((print-length 1))
+ (format "%S" h))))))
+
+(print-tests--deftest print-integers-as-characters ()
+ ;; Bug#44155.
+ (let* ((print-integers-as-characters t)
+ (chars '(?? ?\; ?\( ?\) ?\{ ?\} ?\[ ?\] ?\" ?\' ?\\ ?f ?~ ?Á 32
+ ?\n ?\r ?\t ?\b ?\f ?\a ?\v ?\e ?\d))
+ (nums '(-1 -65 0 1 31 #x80 #x9f #x110000 #x3fff80 #x3fffff))
+ (nonprints '(#xd800 #xdfff #x030a #xffff #x2002 #x200c))
+ (printed-chars (print-tests--prin1-to-string chars))
+ (printed-nums (print-tests--prin1-to-string nums))
+ (printed-nonprints (print-tests--prin1-to-string nonprints)))
+ (should (equal (read printed-chars) chars))
+ (should (equal
+ printed-chars
+ (concat
+ "(?? ?\\; ?\\( ?\\) ?\\{ ?\\} ?\\[ ?\\] ?\\\" ?\\' ?\\\\"
+ " ?f ?~ ?Á ?\\s ?\\n ?\\r ?\\t ?\\b ?\\f 7 11 27 127)")))
+ (should (equal (read printed-nums) nums))
+ (should (equal printed-nums
+ "(-1 -65 0 1 31 128 159 1114112 4194176 4194303)"))
+ (should (equal (read printed-nonprints) nonprints))
+ (should (equal printed-nonprints
+ "(55296 57343 778 65535 8194 8204)"))))
+
+(ert-deftest test-unreadable ()
+ (should (equal (prin1-to-string (make-marker)) "#<marker in no buffer>"))
+ (let ((print-unreadable-function
+ (lambda (_object _escape)
+ "hello")))
+ (should (equal (prin1-to-string (make-marker)) "hello")))
+ (let ((print-unreadable-function
+ (lambda (_object _escape)
+ t)))
+ (should (equal (prin1-to-string (make-marker)) ""))))
+
+(ert-deftest test-dots ()
+ (should (equal (prin1-to-string 'foo.bar) "foo.bar"))
+ (should (equal (prin1-to-string '.foo) "\\.foo"))
+ (should (equal (prin1-to-string '.foo.) "\\.foo."))
+ (should (equal (prin1-to-string 'bar?bar) "bar?bar"))
+ (should (equal (prin1-to-string '\?bar) "\\?bar"))
+ (should (equal (prin1-to-string '\?bar?) "\\?bar?")))
+
+(ert-deftest test-prin1-overrides ()
+ (with-temp-buffer
+ (let ((print-length 10))
+ (prin1 (make-list 20 t) (current-buffer) t)
+ (should (= print-length 10)))
+ (goto-char (point-min))
+ (should (= (length (read (current-buffer))) 20)))
+
+ (with-temp-buffer
+ (let ((print-length 10))
+ (prin1 (make-list 20 t) (current-buffer) '((length . 5)))
+ (should (= print-length 10)))
+ (goto-char (point-min))
+ (should (= (length (read (current-buffer))) 6)))
+
+ (with-temp-buffer
+ (let ((print-length 10))
+ (prin1 (make-list 20 t) (current-buffer) '(t (length . 5)))
+ (should (= print-length 10)))
+ (goto-char (point-min))
+ (should (= (length (read (current-buffer))) 6))))
+
+(ert-deftest test-prin1-to-string-overrides ()
+ (let ((print-length 10))
+ (should
+ (= (length (car (read-from-string
+ (prin1-to-string (make-list 20 t) nil t))))
+ 20)))
+
+ (let ((print-length 10))
+ (should
+ (= (length (car (read-from-string
+ (prin1-to-string (make-list 20 t) nil
+ '((length . 5))))))
+ 6)))
+
+ (should-error (prin1-to-string 'foo nil 'a))
+ (should-error (prin1-to-string 'foo nil '(a)))
+ (should-error (prin1-to-string 'foo nil '(t . b)))
+ (should-error (prin1-to-string 'foo nil '(t b)))
+ (should-error (prin1-to-string 'foo nil '((a . b) b)))
+ (should-error (prin1-to-string 'foo nil '((length . 10) . b))))
+
+(ert-deftest print-deeply-nested ()
+ ;; Check that we can print a deeply nested data structure correctly.
+ (let ((print-circle t))
+ (let ((levels 10000)
+ (x 'a)
+ (prefix nil)
+ (suffix nil))
+ (dotimes (_ levels)
+ (setq x (list (vector (record 'r x))))
+ (push "([#s(r " prefix)
+ (push ")])" suffix))
+ (let ((expected (concat (apply #'concat prefix)
+ "a"
+ (apply #'concat suffix))))
+ (should (equal (prin1-to-string x) expected))))))
+
+(defun print-test-rho (lead loop)
+ "A circular iota list with LEAD elements followed by LOOP in circle."
+ (let ((l (number-sequence 1 (+ lead loop))))
+ (setcdr (nthcdr (+ lead loop -1) l) (nthcdr lead l))
+ l))
+
+(ert-deftest print-circular ()
+ ;; Check printing of rho-shaped circular lists such as (1 2 3 4 5 4 5 4 . #6)
+ ;; when `print-circle' is nil. The exact output may differ since the number
+ ;; of elements printed of the looping part can vary depending on when the
+ ;; circularity was detected.
+ (dotimes (lead 7)
+ (ert-info ((prin1-to-string lead) :prefix "lead: ")
+ (dolist (loop (number-sequence 1 7))
+ (ert-info ((prin1-to-string loop) :prefix "loop: ")
+ (let* ((rho (print-test-rho lead loop))
+ (print-circle nil)
+ (str (prin1-to-string rho)))
+ (should (string-match (rx "("
+ (group (+ (+ digit) " "))
+ ". #" (group (+ digit)) ")")
+ str))
+ (let* ((g1 (match-string 1 str))
+ (g2 (match-string 2 str))
+ (numbers (mapcar #'string-to-number (split-string g1)))
+ (loopback-index (string-to-number g2)))
+ ;; Split the numbers in the lead and loop part.
+ (should (< lead (length numbers)))
+ (should (<= lead loopback-index))
+ (should (< loopback-index (length numbers)))
+ (let ((lead-part (take lead numbers))
+ (loop-part (nthcdr lead numbers)))
+ ;; The lead part must match exactly.
+ (should (equal lead-part (number-sequence 1 lead)))
+ ;; The loop part is at least LOOP long: make sure it matches.
+ (should (>= (length loop-part) loop))
+ (let ((expected-loop-part
+ (mapcar (lambda (x) (+ lead 1 (% x loop)))
+ (number-sequence 0 (1- (length loop-part))))))
+ (should (equal loop-part expected-loop-part))
+ ;; The loopback index must match the length of the
+ ;; loop part.
+ (should (equal (% (- (length numbers) loopback-index) loop)
+ 0)))))))))))
+
+(ert-deftest test-print-unreadable-function-buffer ()
+ (let* ((buffer nil)
+ (callback-buffer nil)
+ (str (with-temp-buffer
+ (setq buffer (current-buffer))
+ (let ((print-unreadable-function
+ (lambda (_object _escape)
+ (setq callback-buffer (current-buffer))
+ "tata")))
+ (prin1-to-string (make-marker))))))
+ (should (eq callback-buffer buffer))
+ (should (equal str "tata"))))
+
(provide 'print-tests)
;;; print-tests.el ends here
diff --git a/test/src/process-tests.el b/test/src/process-tests.el
index b26f9391909..7d3d9eb72b8 100644
--- a/test/src/process-tests.el
+++ b/test/src/process-tests.el
@@ -1,19 +1,21 @@
-;;; process-tests.el --- Testing the process facilities
+;;; process-tests.el --- Testing the process facilities -*- lexical-binding: t -*-
-;; Copyright (C) 2013-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2022 Free Software Foundation, Inc.
-;; This program is free software; you can redistribute it and/or modify
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
-;; This program is distributed in the hope that it will be useful,
+;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
-;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
@@ -21,61 +23,74 @@
;;; Code:
+(require 'cl-lib)
(require 'ert)
+(require 'ert-x) ; ert-with-temp-directory
+(require 'puny)
+(require 'subr-x)
+(require 'dns)
+(require 'url-http)
+
+(declare-function thread-last-error "thread.c")
+(declare-function thread-join "thread.c")
+(declare-function make-thread "thread.c")
;; Timeout in seconds; the test fails if the timeout is reached.
(defvar process-test-sentinel-wait-timeout 2.0)
-;; Start a process that exits immediately. Call WAIT-FUNCTION,
-;; possibly multiple times, to wait for the process to complete.
-(defun process-test-sentinel-wait-function-working-p (wait-function)
- (let ((proc (start-process "test" nil "bash" "-c" "exit 20"))
+(defun process-test-wait-for-sentinel (proc exit-status &optional wait-function)
+ "Set a sentinel on PROC and wait for it to be called with EXIT-STATUS.
+Call WAIT-FUNCTION, possibly multiple times, to wait for the
+process to complete."
+ (let ((wait-function (or wait-function #'accept-process-output))
(sentinel-called nil)
(start-time (float-time)))
- (set-process-sentinel proc (lambda (proc msg)
+ (set-process-sentinel proc (lambda (_proc _msg)
(setq sentinel-called t)))
(while (not (or sentinel-called
(> (- (float-time) start-time)
process-test-sentinel-wait-timeout)))
(funcall wait-function))
- (cl-assert (eq (process-status proc) 'exit))
- (cl-assert (= (process-exit-status proc) 20))
- sentinel-called))
+ (should sentinel-called)
+ (should (eq (process-status proc) 'exit))
+ (should (= (process-exit-status proc) exit-status))))
(ert-deftest process-test-sentinel-accept-process-output ()
(skip-unless (executable-find "bash"))
- (should (process-test-sentinel-wait-function-working-p
- #'accept-process-output)))
+ (with-timeout (60 (ert-fail "Test timed out"))
+ (let ((proc (start-process "test" nil "bash" "-c" "exit 20")))
+ (should (process-test-wait-for-sentinel proc 20)))))
(ert-deftest process-test-sentinel-sit-for ()
(skip-unless (executable-find "bash"))
- (should
- (process-test-sentinel-wait-function-working-p (lambda () (sit-for 0.01 t)))))
+ (with-timeout (60 (ert-fail "Test timed out"))
+ (let ((proc (start-process "test" nil "bash" "-c" "exit 20")))
+ (should (process-test-wait-for-sentinel
+ proc 20 (lambda () (sit-for 0.01 t)))))))
(when (eq system-type 'windows-nt)
(ert-deftest process-test-quoted-batfile ()
"Check that Emacs hides CreateProcess deficiency (bug#18745)."
- (let (batfile)
- (unwind-protect
- (progn
- ;; CreateProcess will fail when both the bat file and 1st
- ;; argument are quoted, so include spaces in both of those
- ;; to force quoting.
- (setq batfile (make-temp-file "echo args" nil ".bat"))
- (with-temp-file batfile
- (insert "@echo arg1=%1, arg2=%2\n"))
- (with-temp-buffer
- (call-process batfile nil '(t t) t "x &y")
- (should (string= (buffer-string) "arg1=\"x &y\", arg2=\n")))
- (with-temp-buffer
- (call-process-shell-command
- (mapconcat #'shell-quote-argument (list batfile "x &y") " ")
- nil '(t t) t)
- (should (string= (buffer-string) "arg1=\"x &y\", arg2=\n"))))
- (when batfile (delete-file batfile))))))
+ (ert-with-temp-file batfile
+ ;; CreateProcess will fail when both the bat file and 1st
+ ;; argument are quoted, so include spaces in both of those
+ ;; to force quoting.
+ :prefix "echo args"
+ :suffix ".bat"
+ (with-temp-file batfile
+ (insert "@echo arg1=%1, arg2=%2\n"))
+ (with-temp-buffer
+ (call-process batfile nil '(t t) t "x &y")
+ (should (string= (buffer-string) "arg1=\"x &y\", arg2=\n")))
+ (with-temp-buffer
+ (call-process-shell-command
+ (mapconcat #'shell-quote-argument (list batfile "x &y") " ")
+ nil '(t t) t)
+ (should (string= (buffer-string) "arg1=\"x &y\", arg2=\n"))))))
(ert-deftest process-test-stderr-buffer ()
(skip-unless (executable-find "bash"))
+ (with-timeout (60 (ert-fail "Test timed out"))
(let* ((stdout-buffer (generate-new-buffer "*stdout*"))
(stderr-buffer (generate-new-buffer "*stderr*"))
(proc (make-process :name "test"
@@ -84,28 +99,19 @@
"echo hello stderr! >&2; "
"exit 20"))
:buffer stdout-buffer
- :stderr stderr-buffer))
- (sentinel-called nil)
- (start-time (float-time)))
- (set-process-sentinel proc (lambda (proc msg)
- (setq sentinel-called t)))
- (while (not (or sentinel-called
- (> (- (float-time) start-time)
- process-test-sentinel-wait-timeout)))
- (accept-process-output))
- (cl-assert (eq (process-status proc) 'exit))
- (cl-assert (= (process-exit-status proc) 20))
+ :stderr stderr-buffer)))
+ (process-test-wait-for-sentinel proc 20)
(should (with-current-buffer stdout-buffer
(goto-char (point-min))
(looking-at "hello stdout!")))
(should (with-current-buffer stderr-buffer
(goto-char (point-min))
- (looking-at "hello stderr!")))))
+ (looking-at "hello stderr!"))))))
(ert-deftest process-test-stderr-filter ()
(skip-unless (executable-find "bash"))
- (let* ((sentinel-called nil)
- (stderr-sentinel-called nil)
+ (with-timeout (60 (ert-fail "Test timed out"))
+ (let* ((stderr-sentinel-called nil)
(stdout-output nil)
(stderr-output nil)
(stdout-buffer (generate-new-buffer "*stdout*"))
@@ -117,36 +123,62 @@
(concat "echo hello stdout!; "
"echo hello stderr! >&2; "
"exit 20"))
- :stderr stderr-proc))
- (start-time (float-time)))
- (set-process-filter proc (lambda (proc input)
+ :stderr stderr-proc)))
+ (set-process-filter proc (lambda (_proc input)
(push input stdout-output)))
- (set-process-sentinel proc (lambda (proc msg)
- (setq sentinel-called t)))
- (set-process-filter stderr-proc (lambda (proc input)
+ (set-process-filter stderr-proc (lambda (_proc input)
(push input stderr-output)))
- (set-process-sentinel stderr-proc (lambda (proc input)
+ (set-process-sentinel stderr-proc (lambda (_proc _input)
(setq stderr-sentinel-called t)))
- (while (not (or sentinel-called
- (> (- (float-time) start-time)
- process-test-sentinel-wait-timeout)))
- (accept-process-output))
- (cl-assert (eq (process-status proc) 'exit))
- (cl-assert (= (process-exit-status proc) 20))
- (should sentinel-called)
+ (process-test-wait-for-sentinel proc 20)
(should (equal 1 (with-current-buffer stdout-buffer
(point-max))))
(should (equal "hello stdout!\n"
- (mapconcat #'identity (nreverse stdout-output) "")))
+ (mapconcat #'identity (nreverse stdout-output))))
(should stderr-sentinel-called)
(should (equal 1 (with-current-buffer stderr-buffer
(point-max))))
(should (equal "hello stderr!\n"
- (mapconcat #'identity (nreverse stderr-output) "")))))
+ (mapconcat #'identity (nreverse stderr-output)))))))
+
+(ert-deftest set-process-filter-t ()
+ "Test setting process filter to t and back." ;; Bug#36591
+ (with-timeout (60 (ert-fail "Test timed out"))
+ (with-temp-buffer
+ (let* ((print-level nil)
+ (print-length nil)
+ (proc (start-process
+ "test proc" (current-buffer)
+ (concat invocation-directory invocation-name)
+ "-Q" "--batch" "--eval"
+ (prin1-to-string
+ '(let ((s nil) (count 0))
+ (while (setq s (read-from-minibuffer
+ (format "%d> " count)))
+ (princ s)
+ (princ "\n")
+ (setq count (1+ count))))))))
+ (set-process-query-on-exit-flag proc nil)
+ (send-string proc "one\n")
+ (while (not (equal (buffer-substring (pos-bol) (point-max))
+ "1> "))
+ (accept-process-output proc)) ; Read "one".
+ (should (equal (buffer-string) "0> one\n1> "))
+ (set-process-filter proc t) ; Stop reading from proc.
+ (send-string proc "two\n")
+ (should-not
+ (accept-process-output proc 1)) ; Can't read "two" yet.
+ (should (equal (buffer-string) "0> one\n1> "))
+ (set-process-filter proc nil) ; Resume reading from proc.
+ (while (not (equal (buffer-substring (pos-bol) (point-max))
+ "2> "))
+ (accept-process-output proc)) ; Read "Two".
+ (should (equal (buffer-string) "0> one\n1> two\n2> "))))))
(ert-deftest start-process-should-not-modify-arguments ()
"`start-process' must not modify its arguments in-place."
;; See bug#21831.
+ (with-timeout (60 (ert-fail "Test timed out"))
(let* ((path (pcase system-type
((or 'windows-nt 'ms-dos)
;; Make sure the file name uses forward slashes.
@@ -160,7 +192,832 @@
(should (process-live-p (condition-case nil
(start-process "" nil path)
(error nil))))
- (should (equal path samepath))))
+ (should (equal path samepath)))))
+
+(ert-deftest make-process/noquery-stderr ()
+ "Checks that Bug#30031 is fixed."
+ (skip-unless (executable-find "sleep"))
+ (with-timeout (60 (ert-fail "Test timed out"))
+ (with-temp-buffer
+ (let* ((previous-processes (process-list))
+ (process (make-process :name "sleep"
+ :command '("sleep" "1h")
+ :noquery t
+ :connection-type 'pipe
+ :stderr (current-buffer))))
+ (unwind-protect
+ (let ((new-processes (cl-set-difference (process-list)
+ previous-processes
+ :test #'eq)))
+ (should new-processes)
+ (dolist (process new-processes)
+ (should-not (process-query-on-exit-flag process))))
+ (kill-process process))))))
+
+;; Return t if OUTPUT could have been generated by merging the INPUTS somehow.
+(defun process-tests--mixable (output &rest inputs)
+ (while (and output (let ((ins inputs))
+ (while (and ins (not (eq (car (car ins)) (car output))))
+ (setq ins (cdr ins)))
+ (if ins
+ (setcar ins (cdr (car ins))))
+ ins))
+ (setq output (cdr output)))
+ (not (apply #'append output inputs)))
+
+(ert-deftest make-process/mix-stderr ()
+ "Check that `make-process' mixes the output streams if STDERR is nil."
+ (skip-unless (executable-find "bash"))
+ (with-timeout (60 (ert-fail "Test timed out"))
+ ;; Frequent random (?) failures on hydra.nixos.org, with no process output.
+ ;; Maybe this test should be tagged unstable? See bug#31214.
+ (skip-unless (not (getenv "EMACS_HYDRA_CI")))
+ (with-temp-buffer
+ (let ((process (make-process
+ :name "mix-stderr"
+ :command (list "bash" "-c"
+ "echo stdout && echo stderr >&2")
+ :buffer (current-buffer)
+ :sentinel #'ignore
+ :noquery t
+ :connection-type 'pipe)))
+ (while (or (accept-process-output process)
+ (process-live-p process)))
+ (should (eq (process-status process) 'exit))
+ (should (eq (process-exit-status process) 0))
+ (should (process-tests--mixable (string-to-list (buffer-string))
+ (string-to-list "stdout\n")
+ (string-to-list "stderr\n")))))))
+
+(ert-deftest make-process-w32-debug-spawn-error ()
+ "Check that debugger runs on `make-process' failure (Bug#33016)."
+ (skip-unless (eq system-type 'windows-nt))
+ (with-timeout (60 (ert-fail "Test timed out"))
+ (let* ((debug-on-error t)
+ (have-called-debugger nil)
+ (debugger (lambda (&rest _)
+ (setq have-called-debugger t)
+ ;; Allow entering the debugger later in the same
+ ;; test run, before going back to the command
+ ;; loop.
+ (setq internal-when-entered-debugger -1))))
+ (should (eq :got-error ;; NOTE: `should-error' would inhibit debugger.
+ (condition-case-unless-debug ()
+ ;; Emacs doesn't search for absolute filenames, so
+ ;; the error will be hit in the w32 process spawn
+ ;; code.
+ (make-process :name "test" :command '("c:/No-Such-Command"))
+ (error :got-error))))
+ (should have-called-debugger))))
+
+(defun make-process/test-connection-type (ttys &rest args)
+ "Make a process and check whether its standard streams match TTYS.
+This calls `make-process', passing ARGS to adjust how the process
+is created. TTYS should be a list of 3 boolean values,
+indicating whether the subprocess's stdin, stdout, and stderr
+should be a TTY, respectively."
+ (declare (indent 1))
+ (let* (;; MS-Windows doesn't support communicating via pty.
+ (ttys (if (eq system-type 'windows-nt) '(nil nil nil) ttys))
+ (expected-output (concat (and (nth 0 ttys) "stdin\n")
+ (and (nth 1 ttys) "stdout\n")
+ (and (nth 2 ttys) "stderr\n")))
+ (stdout-buffer (generate-new-buffer "*stdout*"))
+ (proc (apply
+ #'make-process
+ :name "test"
+ :command (list "sh" "-c"
+ (concat "if [ -t 0 ]; then echo stdin; fi; "
+ "if [ -t 1 ]; then echo stdout; fi; "
+ "if [ -t 2 ]; then echo stderr; fi"))
+ :buffer stdout-buffer
+ args)))
+ (should (eq (and (process-tty-name proc 'stdin) t) (nth 0 ttys)))
+ (should (eq (and (process-tty-name proc 'stdout) t) (nth 1 ttys)))
+ (should (eq (and (process-tty-name proc 'stderr) t) (nth 2 ttys)))
+ (process-test-wait-for-sentinel proc 0)
+ (should (equal (with-current-buffer stdout-buffer (buffer-string))
+ expected-output))))
+
+(ert-deftest make-process/connection-type/pty ()
+ (skip-unless (executable-find "sh"))
+ (make-process/test-connection-type '(t t t)
+ :connection-type 'pty))
+
+(ert-deftest make-process/connection-type/pty-2 ()
+ (skip-unless (executable-find "sh"))
+ (make-process/test-connection-type '(t t t)
+ :connection-type '(pty . pty)))
+
+(ert-deftest make-process/connection-type/pipe ()
+ (skip-unless (executable-find "sh"))
+ (make-process/test-connection-type '(nil nil nil)
+ :connection-type 'pipe))
+
+(ert-deftest make-process/connection-type/pipe-2 ()
+ (skip-unless (executable-find "sh"))
+ (make-process/test-connection-type '(nil nil nil)
+ :connection-type '(pipe . pipe)))
+
+(ert-deftest make-process/connection-type/in-pty ()
+ (skip-unless (executable-find "sh"))
+ (make-process/test-connection-type '(t nil nil)
+ :connection-type '(pty . pipe)))
+
+(ert-deftest make-process/connection-type/out-pty ()
+ (skip-unless (executable-find "sh"))
+ (make-process/test-connection-type '(nil t t)
+ :connection-type '(pipe . pty)))
+
+(ert-deftest make-process/connection-type/pty-with-stderr-buffer ()
+ (skip-unless (executable-find "sh"))
+ (let ((stderr-buffer (generate-new-buffer "*stderr*")))
+ (make-process/test-connection-type '(t t nil)
+ :connection-type 'pty :stderr stderr-buffer)))
+
+(ert-deftest make-process/connection-type/out-pty-with-stderr-buffer ()
+ (skip-unless (executable-find "sh"))
+ (let ((stderr-buffer (generate-new-buffer "*stderr*")))
+ (make-process/test-connection-type '(nil t nil)
+ :connection-type '(pipe . pty) :stderr stderr-buffer)))
+
+(ert-deftest make-process/file-handler/found ()
+ "Check that the `:file-handler’ argument of `make-process’
+works as expected if a file name handler is found."
+ (with-timeout (60 (ert-fail "Test timed out"))
+ (let ((file-handler-calls 0))
+ (cl-flet ((file-handler
+ (&rest args)
+ (should (equal default-directory "test-handler:/dir/"))
+ (should (equal args '(make-process :name "name"
+ :command ("/some/binary")
+ :file-handler t)))
+ (cl-incf file-handler-calls)
+ 'fake-process))
+ (let ((file-name-handler-alist (list (cons (rx bos "test-handler:")
+ #'file-handler)))
+ (default-directory "test-handler:/dir/"))
+ (should (eq (make-process :name "name"
+ :command '("/some/binary")
+ :file-handler t)
+ 'fake-process))
+ (should (= file-handler-calls 1)))))))
+
+(ert-deftest make-process/file-handler/not-found ()
+ "Check that the `:file-handler’ argument of `make-process’
+works as expected if no file name handler is found."
+ (with-timeout (60 (ert-fail "Test timed out"))
+ (let ((file-name-handler-alist ())
+ (default-directory invocation-directory)
+ (program (expand-file-name invocation-name invocation-directory)))
+ (should (processp (make-process :name "name"
+ :command (list program "--version")
+ :file-handler t))))))
+
+(ert-deftest make-process/file-handler/disable ()
+ "Check `make-process’ works as expected if it shouldn’t use the
+file name handler."
+ (with-timeout (60 (ert-fail "Test timed out"))
+ (let ((file-name-handler-alist (list (cons (rx bos "test-handler:")
+ #'process-tests--file-handler)))
+ (default-directory "test-handler:/dir/")
+ (program (expand-file-name invocation-name invocation-directory)))
+ (should (processp (make-process :name "name"
+ :command (list program "--version")))))))
+
+(defun process-tests--file-handler (operation &rest _args)
+ (cl-ecase operation
+ (unhandled-file-name-directory "/")
+ (make-process (ert-fail "file name handler called unexpectedly"))))
+
+(put #'process-tests--file-handler 'operations
+ '(unhandled-file-name-directory make-process))
+
+(ert-deftest make-process/stop ()
+ "Check that `make-process' doesn't accept a `:stop' key.
+See Bug#30460."
+ (with-timeout (60 (ert-fail "Test timed out"))
+ (should-error
+ (make-process :name "test"
+ :command (list (expand-file-name invocation-name
+ invocation-directory))
+ :stop t))))
+
+;; The following tests require working DNS
+
+;; This will need updating when IANA assign more IPv6 global ranges.
+(defun ipv6-is-available ()
+ (and (featurep 'make-network-process '(:family ipv6))
+ (cl-rassoc-if
+ (lambda (elt)
+ (and (eq 9 (length elt))
+ (= (logand (aref elt 0) #xe000) #x2000)))
+ (network-interface-list))))
+
+;; Check if the Internet seems to be working. Mainly to pacify
+;; Debian's CI system.
+(defvar internet-is-working
+ (progn
+ (require 'dns)
+ (dns-query "google.com")))
+
+(ert-deftest lookup-family-specification ()
+ "`network-lookup-address-info' should only accept valid family symbols."
+ (skip-unless internet-is-working)
+ (with-timeout (60 (ert-fail "Test timed out"))
+ (should-error (network-lookup-address-info "localhost" 'both))
+ (should (network-lookup-address-info "localhost" 'ipv4))
+ (when (ipv6-is-available)
+ (should (network-lookup-address-info "localhost" 'ipv6)))))
+
+(ert-deftest lookup-hints-specification ()
+ "`network-lookup-address-info' should only accept valid hints arg."
+ (should-error (network-lookup-address-info "1.1.1.1" nil t))
+ (should-error (network-lookup-address-info "1.1.1.1" 'ipv4 t))
+ (should (network-lookup-address-info "1.1.1.1" nil 'numeric))
+ (should (network-lookup-address-info "1.1.1.1" 'ipv4 'numeric))
+ (when (ipv6-is-available)
+ (should-error (network-lookup-address-info "::1" nil t))
+ (should-error (network-lookup-address-info "::1" 'ipv6 't))
+ (should (network-lookup-address-info "::1" nil 'numeric))
+ (should (network-lookup-address-info "::1" 'ipv6 'numeric))))
+
+(ert-deftest lookup-hints-values ()
+ "`network-lookup-address-info' should succeed/fail in looking up various numeric IP addresses."
+ (let ((ipv4-invalid-addrs
+ '("localhost" "343.1.2.3" "1.2.3.4.5"))
+ ;; These are valid for IPv4 but invalid for IPv6
+ (ipv4-addrs
+ '("127.0.0.1" "127.0.1" "127.1" "127" "1" "0"
+ "0xe3010203" "0xe3.1.2.3" "227.0x1.2.3"
+ "034300201003" "0343.1.2.3" "227.001.2.3"))
+ (ipv6-only-invalid-addrs
+ '("fe80:1" "e301:203:1" "e301::203::1"
+ "1:2:3:4:5:6:7:8:9" "0xe301:203::1"
+ "343:10001:2::3"
+ ;; "00343:1:2::3" is invalid on GNU/Linux and FreeBSD, but
+ ;; valid on macOS. macOS is wrong here, but such is life.
+ ))
+ ;; These are valid for IPv6 but invalid for IPv4
+ (ipv6-addrs
+ '("fe80::1" "e301::203:1" "e301:203::1"
+ "e301:0203::1" "::1" "::0"
+ "0343:1:2::3" "343:001:2::3")))
+ (dolist (a ipv4-invalid-addrs)
+ (should-not (network-lookup-address-info a nil 'numeric))
+ (should-not (network-lookup-address-info a 'ipv4 'numeric)))
+ (dolist (a ipv6-addrs)
+ (should-not (network-lookup-address-info a 'ipv4 'numeric)))
+ (dolist (a ipv4-addrs)
+ (should (network-lookup-address-info a nil 'numeric))
+ (should (network-lookup-address-info a 'ipv4 'numeric)))
+ (when (ipv6-is-available)
+ (dolist (a ipv4-addrs)
+ (should-not (network-lookup-address-info a 'ipv6 'numeric)))
+ (dolist (a ipv6-only-invalid-addrs)
+ (should-not (network-lookup-address-info a 'ipv6 'numeric)))
+ (dolist (a ipv6-addrs)
+ (should (network-lookup-address-info a nil 'numeric))
+ (should (network-lookup-address-info a 'ipv6 'numeric))
+ (should (network-lookup-address-info (upcase a) nil 'numeric))
+ (should (network-lookup-address-info (upcase a) 'ipv6 'numeric))))))
+
+(ert-deftest lookup-unicode-domains ()
+ "Unicode domains should fail."
+ (skip-unless internet-is-working)
+ (with-timeout (60 (ert-fail "Test timed out"))
+ (should-error (network-lookup-address-info "faß.de"))
+ (should (network-lookup-address-info (puny-encode-domain "faß.de")))))
+
+(ert-deftest unibyte-domain-name ()
+ "Unibyte domain names should work."
+ (skip-unless internet-is-working)
+ (with-timeout (60 (ert-fail "Test timed out"))
+ (should (network-lookup-address-info (string-to-unibyte "google.com")))))
+
+(ert-deftest lookup-google ()
+ "Check that we can look up google IP addresses."
+ (skip-unless internet-is-working)
+ (with-timeout (60 (ert-fail "Test timed out"))
+ (let ((addresses-both (network-lookup-address-info "google.com"))
+ (addresses-v4 (network-lookup-address-info "google.com" 'ipv4)))
+ (should addresses-both)
+ (should addresses-v4))
+ (when (and (ipv6-is-available)
+ (dns-query "google.com" 'AAAA))
+ (should (network-lookup-address-info "google.com" 'ipv6)))))
+
+(ert-deftest non-existent-lookup-failure ()
+ "Check that looking up non-existent domain returns nil."
+ (skip-unless internet-is-working)
+ (with-timeout (60 (ert-fail "Test timed out"))
+ (should (eq nil (network-lookup-address-info "emacs.invalid")))))
+
+;; End of tests requiring DNS
+
+(defmacro process-tests--ignore-EMFILE (&rest body)
+ "Evaluate BODY, ignoring EMFILE errors."
+ (declare (indent 0) (debug t))
+ (let ((err (make-symbol "err"))
+ (message (make-symbol "message")))
+ `(let ((,message (process-tests--EMFILE-message)))
+ (condition-case ,err
+ ,(macroexp-progn body)
+ (file-error
+ ;; If we couldn't determine the EMFILE message, just ignore
+ ;; all `file-error' signals.
+ (and ,message
+ (not (string-equal (caddr ,err) ,message))
+ (signal (car ,err) (cdr ,err))))))))
+
+(defmacro process-tests--with-buffers (var &rest body)
+ "Bind VAR to nil and evaluate BODY.
+Afterwards, kill all buffers in the list VAR. BODY should add
+some buffer objects to VAR."
+ (declare (indent 1) (debug (symbolp body)))
+ (cl-check-type var symbol)
+ `(let ((,var nil))
+ (unwind-protect
+ ,(macroexp-progn body)
+ (mapc #'kill-buffer ,var))))
+
+(defmacro process-tests--with-processes (var &rest body)
+ "Bind VAR to nil and evaluate BODY.
+Afterwards, delete all processes in the list VAR. BODY should
+add some process objects to VAR."
+ (declare (indent 1) (debug (symbolp body)))
+ (cl-check-type var symbol)
+ `(let ((,var nil))
+ (unwind-protect
+ ,(macroexp-progn body)
+ (mapc #'delete-process ,var))))
+
+(defmacro process-tests--with-raised-rlimit (&rest body)
+ "Evaluate BODY using a higher limit for the number of open files.
+Attempt to set the resource limit for the number of open files
+temporarily to the highest possible value."
+ (declare (indent 0) (debug t))
+ (let ((prlimit (make-symbol "prlimit"))
+ (soft (make-symbol "soft"))
+ (hard (make-symbol "hard"))
+ (pid-arg (make-symbol "pid-arg")))
+ `(let ((,prlimit (executable-find "prlimit"))
+ (,pid-arg (format "--pid=%d" (emacs-pid)))
+ (,soft nil) (,hard nil))
+ (cl-flet ((set-limit
+ (value)
+ (cl-check-type value natnum)
+ (when ,prlimit
+ (call-process ,prlimit nil nil nil
+ ,pid-arg
+ (format "--nofile=%d:" value)))))
+ (when ,prlimit
+ (with-temp-buffer
+ (when (eql (call-process ,prlimit nil t nil
+ ,pid-arg "--nofile"
+ "--raw" "--noheadings"
+ "--output=SOFT,HARD")
+ 0)
+ (goto-char (point-min))
+ (when (looking-at (rx (group (+ digit)) (+ blank)
+ (group (+ digit)) ?\n))
+ (setq ,soft (string-to-number
+ (match-string-no-properties 1))
+ ,hard (string-to-number
+ (match-string-no-properties 2))))))
+ (and ,soft ,hard (< ,soft ,hard)
+ (set-limit ,hard)))
+ (unwind-protect
+ ,(macroexp-progn body)
+ (when ,soft (set-limit ,soft)))))))
+
+(defmacro process-tests--fd-setsize-test (&rest body)
+ "Run BODY as a test for FD_SETSIZE overflow.
+Try to generate pipe processes until we are close to the
+FD_SETSIZE limit. Within BODY, only a small number of file
+descriptors should still be available. Furthermore, raise the
+maximum number of open files in the Emacs process above
+FD_SETSIZE."
+ (declare (indent 0) (debug t))
+ (let ((process (make-symbol "process"))
+ (processes (make-symbol "processes"))
+ (buffer (make-symbol "buffer"))
+ (buffers (make-symbol "buffers"))
+ ;; FD_SETSIZE is typically 1024 on Unix-like systems. On
+ ;; MS-Windows we artificially limit FD_SETSIZE to 64, see the
+ ;; commentary in w32proc.c.
+ (fd-setsize (if (eq system-type 'windows-nt) 64 1024)))
+ `(process-tests--with-raised-rlimit
+ (process-tests--with-buffers ,buffers
+ (process-tests--with-processes ,processes
+ ;; First, allocate enough pipes to definitely exceed the
+ ;; FD_SETSIZE limit.
+ (cl-loop for i from 1 to ,(1+ fd-setsize)
+ for ,buffer = (generate-new-buffer
+ (format " *pipe %d*" i))
+ do (push ,buffer ,buffers)
+ for ,process = (process-tests--ignore-EMFILE
+ (make-pipe-process
+ :name (format "pipe %d" i)
+ ;; Prevent delete-process from
+ ;; trying to read from pipe
+ ;; processes that didn't exit
+ ;; yet, because no one is
+ ;; writing to those pipes, and
+ ;; the read will stall.
+ :stop (eq system-type 'windows-nt)
+ :buffer ,buffer
+ :coding 'no-conversion
+ :noquery t))
+ while ,process
+ do (push ,process ,processes))
+ (unless (cddr ,processes)
+ (ert-fail "Couldn't allocate enough pipes"))
+ ;; Delete two pipes to test more edge cases.
+ (delete-process (pop ,processes))
+ (delete-process (pop ,processes))
+ ,@body)))))
+
+;; Tests for FD_SETSIZE overflow (Bug#24325). The following tests
+;; generate lots of process objects of the various kinds. Running the
+;; tests with assertions enabled should not result in any crashes due
+;; to file descriptor set overflow. These tests first generate lots
+;; of unused pipe processes to fill up the file descriptor space.
+;; Then, they create a few instances of the process type under test.
+
+(ert-deftest process-tests/fd-setsize-no-crash/make-process ()
+ "Check that Emacs doesn't crash when trying to use more than
+FD_SETSIZE file descriptors (Bug#24325)."
+ (with-timeout (60 (ert-fail "Test timed out"))
+ (let ((cat (executable-find "cat")))
+ (skip-unless cat)
+ (dolist (conn-type '(pipe pty))
+ (ert-info ((format "Connection type `%s'" conn-type))
+ (process-tests--fd-setsize-test
+ (process-tests--with-processes processes
+ ;; Start processes until we exhaust the file descriptor
+ ;; set size. We assume that each process requires at
+ ;; least one file descriptor.
+ (dotimes (i 10)
+ (let ((process
+ ;; Failure to allocate more file descriptors
+ ;; should signal `file-error', but not crash.
+ ;; Since we don't know the exact limit, we
+ ;; ignore `file-error'.
+ (process-tests--ignore-EMFILE
+ (make-process :name (format "test %d" i)
+ :command (list cat)
+ :connection-type conn-type
+ :coding 'no-conversion
+ :noquery t))))
+ (when process (push process processes))))
+ ;; We should have managed to start at least one process.
+ (should processes)
+ (dolist (process processes)
+ ;; The process now should either be running, or have
+ ;; already failed before `exec'.
+ (should (memq (process-status process) '(run exit)))
+ (when (process-live-p process)
+ (process-send-eof process))
+ (while (accept-process-output process))
+ (should (eq (process-status process) 'exit))
+ ;; If there's an error between fork and exec, Emacs
+ ;; will use exit statuses between 125 and 127, see
+ ;; process.h. This can happen if the child process
+ ;; tries to set up terminal device but fails due to
+ ;; file number limits. We don't treat this as an
+ ;; error.
+ (should (memql (process-exit-status process)
+ '(0 125 126 127)))))))))))
+
+(ert-deftest process-tests/fd-setsize-no-crash/make-pipe-process ()
+ "Check that Emacs doesn't crash when trying to use more than
+FD_SETSIZE file descriptors (Bug#24325)."
+ (with-timeout (60 (ert-fail "Test timed out"))
+ (process-tests--fd-setsize-test
+ (process-tests--with-buffers buffers
+ (process-tests--with-processes processes
+ ;; Start processes until we exhaust the file descriptor set
+ ;; size. We assume that each process requires at least one
+ ;; file descriptor.
+ (dotimes (i 10)
+ (let ((buffer (generate-new-buffer (format " *%d*" i))))
+ (push buffer buffers)
+ (let ((process
+ ;; Failure to allocate more file descriptors
+ ;; should signal `file-error', but not crash.
+ ;; Since we don't know the exact limit, we ignore
+ ;; `file-error'.
+ (process-tests--ignore-EMFILE
+ (make-pipe-process :name (format "test %d" i)
+ :buffer buffer
+ :coding 'no-conversion
+ :noquery t))))
+ (when process (push process processes)))))
+ ;; We should have managed to start at least one process.
+ (should processes))))))
+
+(ert-deftest process-tests/fd-setsize-no-crash/make-network-process ()
+ "Check that Emacs doesn't crash when trying to use more than
+FD_SETSIZE file descriptors (Bug#24325)."
+ (skip-unless (featurep 'make-network-process '(:server t)))
+ (skip-unless (featurep 'make-network-process '(:family local)))
+ ;; Avoid hang due to connect/accept handshake on Cygwin (bug#49496).
+ (skip-unless (not (eq system-type 'cygwin)))
+ (with-timeout (60 (ert-fail "Test timed out"))
+ (ert-with-temp-directory directory
+ (process-tests--with-processes processes
+ (let* ((num-clients 10)
+ (socket-name (expand-file-name "socket" directory))
+ ;; Run a UNIX server to connect to.
+ (server (make-network-process :name "server"
+ :server num-clients
+ :buffer nil
+ :service socket-name
+ :family 'local
+ :coding 'no-conversion
+ :noquery t)))
+ (push server processes)
+ (process-tests--fd-setsize-test
+ ;; Start processes until we exhaust the file descriptor
+ ;; set size. We assume that each process requires at
+ ;; least one file descriptor.
+ (dotimes (i num-clients)
+ (let ((client
+ ;; Failure to allocate more file descriptors
+ ;; should signal `file-error', but not crash.
+ ;; Since we don't know the exact limit, we ignore
+ ;; `file-error'.
+ (process-tests--ignore-EMFILE
+ (make-network-process
+ :name (format "client %d" i)
+ :service socket-name
+ :family 'local
+ :coding 'no-conversion
+ :noquery t))))
+ (when client (push client processes))))
+ ;; We should have managed to start at least one process.
+ (should processes)))))))
+
+(ert-deftest process-tests/fd-setsize-no-crash/make-serial-process ()
+ "Check that Emacs doesn't crash when trying to use more than
+FD_SETSIZE file descriptors (Bug#24325)."
+ ;; This test cannot be run if PTYs aren't supported.
+ (skip-unless (not (eq system-type 'windows-nt)))
+ (with-timeout (60 (ert-fail "Test timed out"))
+ (process-tests--with-processes processes
+ ;; In order to use `make-serial-process', we need to create some
+ ;; pseudoterminals. The easiest way to do that is to start a
+ ;; normal process using the `pty' connection type. We need to
+ ;; ensure that the terminal stays around while we connect to it.
+ ;; Create the host processes before the dummy pipes so we have a
+ ;; high chance of succeeding here.
+ (let ((sleep (executable-find "sleep"))
+ (tty-names ()))
+ (skip-unless sleep)
+ (dotimes (i 10)
+ (let* ((host (make-process :name (format "tty host %d" i)
+ :command (list sleep "60")
+ :buffer nil
+ :coding 'utf-8-unix
+ :connection-type 'pty
+ :noquery t))
+ (tty-name (process-tty-name host)))
+ (should (processp host))
+ (push host processes)
+ ;; FIXME: The assumption below that using :connection 'pty
+ ;; in make-process necessarily produces a process with PTY
+ ;; connection is unreliable and non-portable.
+ ;; make-process can legitimately and silently fall back on
+ ;; pipes if allocating a PTY fails (and on MS-Windows it
+ ;; always fails). The following code also assumes that
+ ;; process-tty-name produces a file name that can be
+ ;; passed to 'stat' and to make-serial-process, which is
+ ;; also non-portable.
+ (should tty-name)
+ (should (file-exists-p tty-name))
+ (should-not (member tty-name tty-names))
+ (push tty-name tty-names)))
+ (process-tests--fd-setsize-test
+ (process-tests--with-processes processes
+ (process-tests--with-buffers buffers
+ (dolist (tty-name tty-names)
+ (let ((buffer (generate-new-buffer
+ (format " *%s*" tty-name))))
+ (push buffer buffers)
+ ;; Failure to allocate more file descriptors should
+ ;; signal `file-error', but not crash. Since we
+ ;; don't know the exact limit, we ignore
+ ;; `file-error'.
+ (let ((process (process-tests--ignore-EMFILE
+ (make-serial-process
+ :name (format "test %s" tty-name)
+ :port tty-name
+ :speed 9600
+ :buffer buffer
+ :coding 'no-conversion
+ :noquery t))))
+ (when process (push process processes))))))
+ ;; We should have managed to start at least one process.
+ (should processes)))))))
+
+(defvar process-tests--EMFILE-message :unknown
+ "Cached result of the function `process-tests--EMFILE-message'.")
+
+(defun process-tests--EMFILE-message ()
+ "Return the error message for the EMFILE POSIX error.
+Return nil if that can't be determined."
+ (when (eq process-tests--EMFILE-message :unknown)
+ (setq process-tests--EMFILE-message
+ (with-temp-buffer
+ (when (eql (ignore-error 'file-error
+ (call-process "errno" nil t nil "EMFILE"))
+ 0)
+ (goto-char (point-min))
+ (when (looking-at (rx "EMFILE" (+ blank) (+ digit)
+ (+ blank) (group (+ nonl))))
+ (match-string-no-properties 1))))))
+ process-tests--EMFILE-message)
+
+(ert-deftest process-tests/sentinel-called ()
+ "Check that sentinels are called after processes finish."
+ (let ((command (process-tests--emacs-command)))
+ (skip-unless command)
+ (dolist (conn-type '(pipe pty))
+ (ert-info ((format "Connection type: %s" conn-type))
+ (process-tests--with-processes processes
+ (let* ((calls ())
+ (process (make-process
+ :name "echo"
+ :command (process-tests--eval
+ command '(print "first"))
+ :noquery t
+ :connection-type conn-type
+ :coding 'utf-8-unix
+ :sentinel (lambda (process message)
+ (push (list process message)
+ calls)))))
+ (push process processes)
+ (while (accept-process-output process))
+ (should (equal calls
+ (list (list process "finished\n"))))))))))
+
+(ert-deftest process-tests/sentinel-with-multiple-processes ()
+ "Check that sentinels are called in time even when other processes
+have written output."
+ (let ((command (process-tests--emacs-command)))
+ (skip-unless command)
+ (dolist (conn-type '(pipe pty))
+ (ert-info ((format "Connection type: %s" conn-type))
+ (process-tests--with-processes processes
+ (let* ((calls ())
+ (process (make-process
+ :name "echo"
+ :command (process-tests--eval
+ command '(print "first"))
+ :noquery t
+ :connection-type conn-type
+ :coding 'utf-8-unix
+ :sentinel (lambda (process message)
+ (push (list process message)
+ calls)))))
+ (push process processes)
+ (push (make-process
+ :name "bash"
+ :command (process-tests--eval
+ command
+ '(progn (sleep-for 10) (print "second")))
+ :noquery t
+ :connection-type conn-type)
+ processes)
+ (while (accept-process-output process))
+ (should (equal calls
+ (list (list process "finished\n"))))))))))
+
+(ert-deftest process-tests/multiple-threads-waiting ()
+ :tags (if (getenv "EMACS_EMBA_CI") '(:unstable))
+ (skip-unless (fboundp 'make-thread))
+ (with-timeout (60 (ert-fail "Test timed out"))
+ (process-tests--with-processes processes
+ (let ((threads ())
+ (cat (executable-find "cat")))
+ (skip-unless cat)
+ (dotimes (i 10)
+ (let* ((name (format "test %d" i))
+ (process (make-process :name name
+ :command (list cat)
+ :coding 'no-conversion
+ :noquery t
+ :connection-type 'pipe)))
+ (push process processes)
+ (set-process-thread process nil)
+ (push (make-thread
+ (lambda ()
+ (while (accept-process-output process)))
+ name)
+ threads)))
+ (mapc #'process-send-eof processes)
+ (cl-loop for process in processes
+ and thread in threads
+ do
+ (should-not (thread-join thread))
+ (should-not (thread-last-error))
+ (should (eq (process-status process) 'exit))
+ (should (eql (process-exit-status process) 0)))))))
+
+(defun process-tests--eval (command form)
+ "Return a command that evaluates FORM in an Emacs subprocess.
+COMMAND must be a list returned by
+`process-tests--emacs-command'."
+ (let ((print-gensym t)
+ (print-circle t)
+ (print-length nil)
+ (print-level nil)
+ (print-escape-control-characters t)
+ (print-escape-newlines t)
+ (print-escape-multibyte t)
+ (print-escape-nonascii t))
+ `(,@command "--quick" "--batch" ,(format "--eval=%S" form))))
+
+(defun process-tests--emacs-command ()
+ "Return a command to reinvoke the current Emacs instance.
+Return nil if that doesn't appear to be possible."
+ (when-let ((binary (process-tests--emacs-binary))
+ (dump (process-tests--dump-file)))
+ (cons binary
+ (unless (eq dump :not-needed)
+ (list (concat "--dump-file="
+ (file-name-unquote dump)))))))
+
+(defun process-tests--emacs-binary ()
+ "Return the filename of the currently running Emacs binary.
+Return nil if that can't be determined."
+ (and (stringp invocation-name)
+ (not (file-remote-p invocation-name))
+ (not (file-name-absolute-p invocation-name))
+ (stringp invocation-directory)
+ (not (file-remote-p invocation-directory))
+ (file-name-absolute-p invocation-directory)
+ (when-let ((file (process-tests--usable-file-for-reinvoke
+ (expand-file-name invocation-name
+ invocation-directory))))
+ (and (file-executable-p file) file))))
+
+(defun process-tests--dump-file ()
+ "Return the filename of the dump file used to start Emacs.
+Return nil if that can't be determined. Return `:not-needed' if
+Emacs wasn't started with a dump file."
+ (if-let ((stats (and (fboundp 'pdumper-stats) (pdumper-stats))))
+ (when-let ((file (process-tests--usable-file-for-reinvoke
+ (cdr (assq 'dump-file-name stats)))))
+ (and (file-readable-p file) file))
+ :not-needed))
+
+(defun process-tests--usable-file-for-reinvoke (filename)
+ "Return a version of FILENAME that can be used to reinvoke Emacs.
+Return nil if FILENAME doesn't exist."
+ (when (and (stringp filename)
+ (not (file-remote-p filename)))
+ (cl-callf file-truename filename)
+ (and (stringp filename)
+ (not (file-remote-p filename))
+ (file-name-absolute-p filename)
+ (file-regular-p filename)
+ filename)))
+
+;; Bug#46284
+(ert-deftest process-sentinel-interrupt-event ()
+ "Test that interrupting a process on Windows sends \"interrupt\" to sentinel."
+ (skip-unless (eq system-type 'windows-nt))
+ (with-temp-buffer
+ (let* ((proc-buf (current-buffer))
+ ;; Start a new emacs process to wait idly until interrupted.
+ (cmd "emacs -batch --eval=\"(sit-for 50000)\"")
+ (proc (start-file-process-shell-command
+ "test/process-sentinel-signal-event" proc-buf cmd))
+ (events '()))
+
+ ;; Capture any incoming events.
+ (set-process-sentinel proc
+ (lambda (_prc event)
+ (push event events)))
+ ;; Wait for the process to start.
+ (sleep-for 2)
+ (should (equal 'run (process-status proc)))
+ ;; Interrupt the sub-process and wait for it to die.
+ (interrupt-process proc)
+ (sleep-for 2)
+ ;; Should have received SIGINT...
+ (should (equal 'signal (process-status proc)))
+ (should (equal 2 (process-exit-status proc)))
+ ;; ...and the change description should be "interrupt".
+ (should (equal '("interrupt\n") events)))))
+
+(ert-deftest process-num-processors ()
+ "Sanity checks for num-processors."
+ (should (equal (num-processors) (num-processors)))
+ (should (integerp (num-processors)))
+ (should (< 0 (num-processors))))
(provide 'process-tests)
-;; process-tests.el ends here.
+;;; process-tests.el ends here
diff --git a/test/src/regex-tests.el b/test/src/regex-emacs-tests.el
index b1f1ea71cef..ff0d6be3f5d 100644
--- a/test/src/regex-tests.el
+++ b/test/src/regex-emacs-tests.el
@@ -1,6 +1,6 @@
-;;; regex-tests.el --- tests for regex.c functions -*- lexical-binding: t -*-
+;;; regex-emacs-tests.el --- tests for regex-emacs.c -*- lexical-binding: t -*-
-;; Copyright (C) 2015-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2022 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -24,16 +24,16 @@
(defvar regex-tests--resources-dir
(concat (concat (file-name-directory (or load-file-name buffer-file-name))
"/regex-resources/"))
- "Path to regex-resources directory next to the \"regex-tests.el\" file.")
+ "Path to regex-resources directory next to the \"regex-emacs-tests.el\" file.")
(ert-deftest regex-word-cc-fallback-test ()
- "Test that ‘[[:cc:]]*x’ matches ‘x’ (bug#24020).
+ "Test that \"[[:cc:]]*x\" matches \"x\" (bug#24020).
Test that a regex of the form \"[[:cc:]]*x\" where CC is
a character class which matches a multibyte character X, matches
string \"x\".
-For example, ‘[[:word:]]*\u2620’ regex (note: \u2620 is a word
+For example, \"[[:word:]]*\u2620\" regex (note: \u2620 is a word
character) must match a string \"\u2420\"."
(dolist (class '("[[:word:]]" "\\sw"))
(dolist (repeat '("*" "+"))
@@ -157,18 +157,18 @@ are known failures, and are skipped."
(defun regex-tests-compare (string what-failed bounds-ref &optional substring-ref)
"I just ran a search, looking at STRING. WHAT-FAILED describes
-what failed, if anything; valid values are 'search-failed,
-'compilation-failed and nil. I compare the beginning/end of each
+what failed, if anything; valid values are `search-failed',
+`compilation-failed' and nil. I compare the beginning/end of each
group with their expected values. This is done with either
BOUNDS-REF or SUBSTRING-REF; one of those should be non-nil.
-BOUNDS-REF is a sequence \[start-ref0 end-ref0 start-ref1
+BOUNDS-REF is a sequence [start-ref0 end-ref0 start-ref1
end-ref1 ....] while SUBSTRING-REF is the expected substring
obtained by indexing the input string by start/end-ref.
If the search was supposed to fail then start-ref0/substring-ref0
-is 'search-failed. If the search wasn't even supposed to compile
+is `search-failed'. If the search wasn't even supposed to compile
successfully, then start-ref0/substring-ref0 is
-'compilation-failed. If I only care about a match succeeding,
+`compilation-failed'. If I only care about a match succeeding,
this can be set to t.
This function returns a string that describes the failure, or nil
@@ -259,8 +259,8 @@ BOUNDS-REF is a sequence [start-ref0 end-ref0 start-ref1 end-ref1
....].
If the search was supposed to fail then start-ref0 is
-'search-failed. If the search wasn't even supposed to compile
-successfully, then start-ref0 is 'compilation-failed.
+`search-failed'. If the search wasn't even supposed to compile
+successfully, then start-ref0 is `compilation-failed'.
This function returns a string that describes the failure, or nil
on success"
@@ -278,12 +278,12 @@ on success"
(defconst regex-tests-re-even-escapes
- "\\(?:^\\|[^\\\\]\\)\\(?:\\\\\\\\\\)*"
- "Regex that matches an even number of \\ characters")
+ "\\(?:^\\|[^\\]\\)\\(?:\\\\\\\\\\)*"
+ "Regex that matches an even number of \\ characters.")
(defconst regex-tests-re-odd-escapes
(concat regex-tests-re-even-escapes "\\\\")
- "Regex that matches an odd number of \\ characters")
+ "Regex that matches an odd number of \\ characters.")
(defun regex-tests-unextend (pattern)
@@ -327,7 +327,7 @@ emacs requires an extra symbol character"
(defun regex-tests-BOOST-frob-escapes (s ispattern)
"Mangle \\ the way it is done in frob_escapes() in
regex-tests-BOOST.c in glibc: \\t, \\n, \\r are interpreted;
-\\\\, \\^, \{, \\|, \} are unescaped for the string (not
+\\\\, \\^, \\{, \\|, \\} are unescaped for the string (not
pattern)"
;; this is all similar to (regex-tests-unextend)
@@ -396,9 +396,9 @@ pattern)"
;; emacs matches non-greedy regex ab.*? non-greedily
639 677 712
]
- "Line numbers in the boost test that should be skipped. These
-are false-positive test failures that represent known/benign
-differences in behavior.")
+ "Line numbers in the boost test that should be skipped.
+These are false-positive test failures that represent
+known/benign differences in behavior.")
;; - Format
;; - Comments are lines starting with ;
@@ -480,9 +480,9 @@ differences in behavior.")
;; ambiguous groupings are ambiguous
610 611 1154 1157 1160 1168 1171 1176 1179 1182 1185 1188 1193 1196 1203
]
- "Line numbers in the PCRE test that should be skipped. These
-are false-positive test failures that represent known/benign
-differences in behavior.")
+ "Line numbers in the PCRE test that should be skipped.
+These are false-positive test failures that represent
+known/benign differences in behavior.")
;; - Format
;;
@@ -505,7 +505,7 @@ differences in behavior.")
(cond
;; pattern
- ((save-excursion (re-search-forward "^/\\(.*\\)/\\(.*i?\\)$" nil t))
+ ((save-excursion (re-search-forward "^/\\(.*\\)/\\(.*\\)$" nil t))
(setq icase (string= "i" (match-string 2))
pattern (regex-tests-unextend (match-string 1))))
@@ -555,16 +555,16 @@ differences in behavior.")
(defconst regex-tests-PTESTS-whitelist
[
- ;; emacs doesn't barf on weird ranges such as [b-a], but simply
- ;; fails to match
+ ;; emacs doesn't see DEL (0x7f) as a [:cntrl:] character
138
- ;; emacs doesn't see DEL (0x78) as a [:cntrl:] character
+ ;; emacs doesn't barf on weird ranges such as [b-a], but simply
+ ;; fails to match
168
]
- "Line numbers in the PTESTS test that should be skipped. These
-are false-positive test failures that represent known/benign
-differences in behavior.")
+ "Line numbers in the PTESTS test that should be skipped.
+These are false-positive test failures that represent
+known/benign differences in behavior.")
;; - Format
;; - fields separated by ¦ (note: this is not a |)
@@ -621,9 +621,9 @@ differences in behavior.")
;; emacs is more stringent with regexes involving unbalanced )
67
]
- "Line numbers in the TESTS test that should be skipped. These
-are false-positive test failures that represent known/benign
-differences in behavior.")
+ "Line numbers in the TESTS test that should be skipped.
+These are false-positive test failures that represent
+known/benign differences in behavior.")
;; - Format
;; - fields separated by :. Watch for [\[:xxx:]]
@@ -677,4 +677,194 @@ This evaluates the PTESTS test cases from glibc."
This evaluates the TESTS test cases from glibc."
(should-not (regex-tests-TESTS)))
-;;; regex-tests.el ends here
+(ert-deftest regex-repeat-limit ()
+ "Test the #xFFFF repeat limit."
+ (should (string-match "\\`x\\{65535\\}" (make-string 65535 ?x)))
+ (should-not (string-match "\\`x\\{65535\\}" (make-string 65534 ?x)))
+ (should-error (string-match "\\`x\\{65536\\}" "X") :type 'invalid-regexp))
+
+(ert-deftest regexp-unibyte-unibyte ()
+ "Test matching a unibyte regexp against a unibyte string."
+ ;; Sanity check
+ (should-not (multibyte-string-p "ab"))
+ (should-not (multibyte-string-p "\xff"))
+ ;; ASCII
+ (should (string-match "a[b]" "ab"))
+ ;; Raw
+ (should (string-match "\xf1" "\xf1"))
+ (should-not (string-match "\xf1" "\xc1\xb1"))
+ ;; Raw, char alt
+ (should (string-match "[\xf1]" "\xf1"))
+ (should-not (string-match "[\xf1]" "\xc1\xb1"))
+ ;; Raw range
+ (should (string-match "[\x82-\xd3]" "\xbb"))
+ (should-not (string-match "[\x82-\xd3]" "a"))
+ (should-not (string-match "[\x82-\xd3]" "\x81"))
+ (should-not (string-match "[\x82-\xd3]" "\xd4"))
+ ;; ASCII-raw range
+ (should (string-match "[f-\xd3]" "q"))
+ (should (string-match "[f-\xd3]" "\xbb"))
+ (should-not (string-match "[f-\xd3]" "e"))
+ (should-not (string-match "[f-\xd3]" "\xd4")))
+
+(ert-deftest regexp-multibyte-multibyte ()
+ "Test matching a multibyte regexp against a multibyte string."
+ ;; Sanity check
+ (should (multibyte-string-p "åü"))
+ ;; ASCII
+ (should (string-match (string-to-multibyte "a[b]")
+ (string-to-multibyte "ab")))
+ ;; Unicode
+ (should (string-match "å[ü]z" "åüz"))
+ (should-not (string-match "ü" (string-to-multibyte "\xc3\xbc")))
+ ;; Raw
+ (should (string-match (string-to-multibyte "\xf1")
+ (string-to-multibyte "\xf1")))
+ (should-not (string-match (string-to-multibyte "\xf1")
+ (string-to-multibyte "\xc1\xb1")))
+ (should-not (string-match (string-to-multibyte "\xc1\xb1")
+ (string-to-multibyte "\xf1")))
+ ;; Raw, char alt
+ (should (string-match (string-to-multibyte "[\xf1]")
+ (string-to-multibyte "\xf1")))
+ ;; Raw range
+ (should (string-match (string-to-multibyte "[\x82-\xd3]")
+ (string-to-multibyte "\xbb")))
+ (should-not (string-match (string-to-multibyte "[\x82-\xd3]") "a"))
+ (should-not (string-match (string-to-multibyte "[\x82-\xd3]") "Å"))
+ (should-not (string-match (string-to-multibyte "[\x82-\xd3]") "ü"))
+ (should-not (string-match (string-to-multibyte "[\x82-\xd3]") "\x81"))
+ (should-not (string-match (string-to-multibyte "[\x82-\xd3]") "\xd4"))
+ ;; ASCII-raw range: should exclude U+0100..U+10FFFF
+ (should (string-match (string-to-multibyte "[f-\xd3]")
+ (string-to-multibyte "q")))
+ (should (string-match (string-to-multibyte "[f-\xd3]")
+ (string-to-multibyte "\xbb")))
+ (should-not (string-match (string-to-multibyte "[f-\xd3]") "e"))
+ (should-not (string-match (string-to-multibyte "[f-\xd3]") "Å"))
+ (should-not (string-match (string-to-multibyte "[f-\xd3]") "ü"))
+ (should-not (string-match (string-to-multibyte "[f-\xd3]") "\xd4"))
+ ;; Unicode-raw range: should be empty
+ (should-not (string-match "[å-\xd3]" "å"))
+ (should-not (string-match "[å-\xd3]" (string-to-multibyte "\xd3")))
+ (should-not (string-match "[å-\xd3]" (string-to-multibyte "\xbb")))
+ (should-not (string-match "[å-\xd3]" "ü"))
+ ;; No equivalence between raw bytes and latin-1
+ (should-not (string-match "å" (string-to-multibyte "\xe5")))
+ (should-not (string-match "[å]" (string-to-multibyte "\xe5")))
+ (should-not (string-match "\xe5" "å"))
+ (should-not (string-match "[\xe5]" "å")))
+
+(ert-deftest regexp-unibyte-multibyte ()
+ "Test matching a unibyte regexp against a multibyte string."
+ ;; ASCII
+ (should (string-match "a[b]" (string-to-multibyte "ab")))
+ ;; Unicode
+ (should (string-match "a.[^b]c" (string-to-multibyte "aåüc")))
+ ;; Raw
+ (should (string-match "\xf1" (string-to-multibyte "\xf1")))
+ (should-not (string-match "\xc1\xb1" (string-to-multibyte "\xf1")))
+ ;; Raw, char alt
+ (should (string-match "[\xf1]" (string-to-multibyte "\xf1")))
+ (should-not (string-match "[\xc1][\xb1]" (string-to-multibyte "\xf1")))
+ ;; ASCII-raw range: should exclude U+0100..U+10FFFF
+ (should (string-match "[f-\xd3]" (string-to-multibyte "q")))
+ (should (string-match "[f-\xd3]" (string-to-multibyte "\xbb")))
+ (should-not (string-match "[f-\xd3]" "e"))
+ (should-not (string-match "[f-\xd3]" "Å"))
+ (should-not (string-match "[f-\xd3]" "ü"))
+ (should-not (string-match "[f-\xd3]" "\xd4"))
+ ;; No equivalence between raw bytes and latin-1
+ (should-not (string-match "\xe5" "å"))
+ (should-not (string-match "[\xe5]" "å")))
+
+(ert-deftest regexp-multibyte-unibyte ()
+ "Test matching a multibyte regexp against a unibyte string."
+ ;; ASCII
+ (should (string-match (string-to-multibyte "a[b]") "ab"))
+ ;; Unicode
+ (should (string-match "a[^ü]c" "abc"))
+ (should-not (string-match "ü" "\xc3\xbc"))
+ ;; Raw
+ (should (string-match (string-to-multibyte "\xf1") "\xf1"))
+ (should-not (string-match (string-to-multibyte "\xf1") "\xc1\xb1"))
+ ;; Raw, char alt
+ (should (string-match (string-to-multibyte "[\xf1]") "\xf1"))
+ (should-not (string-match (string-to-multibyte "[\xf1]") "\xc1\xb1"))
+ ;; ASCII-raw range: should exclude U+0100..U+10FFFF
+ (should (string-match (string-to-multibyte "[f-\xd3]") "q"))
+ (should (string-match (string-to-multibyte "[f-\xd3]") "\xbb"))
+ (should-not (string-match (string-to-multibyte "[f-\xd3]") "e"))
+ (should-not (string-match (string-to-multibyte "[f-\xd3]") "\xd4"))
+ ;; Unicode-raw range: should be empty
+ (should-not (string-match "[å-\xd3]" "\xd3"))
+ (should-not (string-match "[å-\xd3]" "\xbb"))
+ ;; No equivalence between raw bytes and latin-1
+ (should-not (string-match "å" "\xe5"))
+ (should-not (string-match "[å]" "\xe5")))
+
+(ert-deftest regexp-case-fold ()
+ "Test case-sensitive and case-insensitive matching."
+ (let ((case-fold-search nil))
+ (should (equal (string-match "aB" "ABaB") 2))
+ (should (equal (string-match "åÄ" "ÅäåäÅÄåÄ") 6))
+ (should (equal (string-match "λΛ" "lΛλλΛ") 3))
+ (should (equal (string-match "шШ" "zШшшШ") 3))
+ (should (equal (string-match "[[:alpha:]]+" ".3aBåÄßλΛшШ中﷽") 2))
+ (should (equal (match-end 0) 12))
+ (should (equal (string-match "[[:alnum:]]+" ".3aBåÄßλΛшШ中﷽") 1))
+ (should (equal (match-end 0) 12))
+ (should (equal (string-match "[[:upper:]]+" ".3aåλшBÄΛШ中﷽") 6))
+ (should (equal (match-end 0) 10))
+ (should (equal (string-match "[[:lower:]]+" ".3BÄΛШaåλш中﷽") 6))
+ (should (equal (match-end 0) 10)))
+ (let ((case-fold-search t))
+ (should (equal (string-match "aB" "ABaB") 0))
+ (should (equal (string-match "åÄ" "ÅäåäÅÄåÄ") 0))
+ (should (equal (string-match "λΛ" "lΛλλΛ") 1))
+ (should (equal (string-match "шШ" "zШшшШ") 1))
+ (should (equal (string-match "[[:alpha:]]+" ".3aBåÄßλΛшШ中﷽") 2))
+ (should (equal (match-end 0) 12))
+ (should (equal (string-match "[[:alnum:]]+" ".3aBåÄßλΛшШ中﷽") 1))
+ (should (equal (match-end 0) 12))
+ (should (equal (string-match "[[:upper:]]+" ".3aåλшBÄΛШ中﷽") 2))
+ (should (equal (match-end 0) 10))
+ (should (equal (string-match "[[:lower:]]+" ".3BÄΛШaåλш中﷽") 2))
+ (should (equal (match-end 0) 10))))
+
+(ert-deftest regexp-eszett ()
+ "Test matching of ß and ẞ."
+ ;; Sanity checks.
+ (should (equal (upcase "ß") "SS"))
+ (should (equal (downcase "ß") "ß"))
+ (should (equal (capitalize "ß") "Ss")) ; undeutsch...
+ (should (equal (upcase "ẞ") "ẞ"))
+ (should (equal (downcase "ẞ") "ß"))
+ (should (equal (capitalize "ẞ") "ẞ"))
+ ;; ß is a lower-case letter (Ll); ẞ is an upper-case letter (Lu).
+ (let ((case-fold-search nil))
+ (should (equal (string-match "ß" "ß") 0))
+ (should (equal (string-match "ß" "ẞ") nil))
+ (should (equal (string-match "ẞ" "ß") nil))
+ (should (equal (string-match "ẞ" "ẞ") 0))
+ (should (equal (string-match "[[:alpha:]]" "ß") 0))
+ ;; bug#11309
+ (should (equal (string-match "[[:lower:]]" "ß") 0))
+ (should (equal (string-match "[[:upper:]]" "ß") nil))
+ (should (equal (string-match "[[:alpha:]]" "ẞ") 0))
+ (should (equal (string-match "[[:lower:]]" "ẞ") nil))
+ (should (equal (string-match "[[:upper:]]" "ẞ") 0)))
+ (let ((case-fold-search t))
+ (should (equal (string-match "ß" "ß") 0))
+ (should (equal (string-match "ß" "ẞ") 0))
+ (should (equal (string-match "ẞ" "ß") 0))
+ (should (equal (string-match "ẞ" "ẞ") 0))
+ (should (equal (string-match "[[:alpha:]]" "ß") 0))
+ ;; bug#11309
+ (should (equal (string-match "[[:lower:]]" "ß") 0))
+ (should (equal (string-match "[[:upper:]]" "ß") 0))
+ (should (equal (string-match "[[:alpha:]]" "ẞ") 0))
+ (should (equal (string-match "[[:lower:]]" "ẞ") 0))
+ (should (equal (string-match "[[:upper:]]" "ẞ") 0))))
+
+;;; regex-emacs-tests.el ends here
diff --git a/test/src/regex-resources/BOOST.tests b/test/src/regex-resources/BOOST.tests
index 98fd3b6abf3..756fa00486b 100644
--- a/test/src/regex-resources/BOOST.tests
+++ b/test/src/regex-resources/BOOST.tests
@@ -93,7 +93,7 @@ aa\) !
. \0 0 1
;
-; now move on to the repetion ops,
+; now move on to the repetition ops,
; starting with operator *
- match_default normal REG_EXTENDED
a* b 0 0
@@ -275,7 +275,7 @@ a(b*)c\1d abbcbbbd -1 -1
^(.)\1 abc -1 -1
a([bc])\1d abcdabbd 4 8 5 6
; strictly speaking this is at best ambiguous, at worst wrong, this is what most
-; re implimentations will match though.
+; re implementations will match though.
a(([bc])\2)*d abbccd 0 6 3 5 3 4
a(([bc])\2)*d abbcbd -1 -1
diff --git a/test/src/search-tests.el b/test/src/search-tests.el
new file mode 100644
index 00000000000..2fa23842841
--- /dev/null
+++ b/test/src/search-tests.el
@@ -0,0 +1,42 @@
+;;; search-tests.el --- tests for search.c functions -*- lexical-binding: t -*-
+
+;; Copyright (C) 2015-2016, 2018-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+
+(ert-deftest test-replace-match-modification-hooks ()
+ (let ((ov-set nil))
+ (with-temp-buffer
+ (insert "1 abc")
+ (setq ov-set (make-overlay 3 5))
+ (overlay-put
+ ov-set 'modification-hooks
+ (list (lambda (_o after &rest _args)
+ (when after
+ (let ((inhibit-modification-hooks t))
+ (save-excursion
+ (goto-char 2)
+ (insert "234")))))))
+ (goto-char 3)
+ (if (search-forward "bc")
+ (replace-match "bcd"))
+ (should (= (point) 10)))))
+
+;;; search-tests.el ends here
diff --git a/test/src/sqlite-tests.el b/test/src/sqlite-tests.el
new file mode 100644
index 00000000000..5af43923012
--- /dev/null
+++ b/test/src/sqlite-tests.el
@@ -0,0 +1,244 @@
+;;; sqlite-tests.el --- Tests for sqlite.el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;
+
+;;; Code:
+
+(require 'ert)
+(require 'ert-x)
+
+(declare-function sqlite-execute "sqlite.c")
+(declare-function sqlite-close "sqlite.c")
+(declare-function sqlitep "sqlite.c")
+(declare-function sqlite-available-p "sqlite.c")
+(declare-function sqlite-finalize "sqlite.c")
+(declare-function sqlite-next "sqlite.c")
+(declare-function sqlite-more-p "sqlite.c")
+(declare-function sqlite-select "sqlite.c")
+(declare-function sqlite-open "sqlite.c")
+(declare-function sqlite-load-extension "sqlite.c")
+
+(ert-deftest sqlite-select ()
+ (skip-unless (sqlite-available-p))
+ (let ((db (sqlite-open)))
+ (should (eq (type-of db) 'sqlite))
+ (should (sqlitep db))
+ (should-not (sqlitep 'foo))
+
+ (should
+ (zerop
+ (sqlite-execute
+ db "create table if not exists test1 (col1 text, col2 integer, col3 float, col4 blob)")))
+
+ (should-error
+ (sqlite-execute
+ db "insert into test1 (col1, col2, col3, col4) values ('foo', 2, 9.45, 'bar', 'zot')"))
+
+ (should
+ (=
+ (sqlite-execute
+ db "insert into test1 (col1, col2, col3, col4) values ('foo', 2, 9.45, 'bar')")
+ 1))
+
+ (should
+ (equal
+ (sqlite-select db "select * from test1" nil 'full)
+ '(("col1" "col2" "col3" "col4") ("foo" 2 9.45 "bar"))))))
+
+(ert-deftest sqlite-set ()
+ (skip-unless (sqlite-available-p))
+ (let ((db (sqlite-open))
+ set)
+ (should
+ (zerop
+ (sqlite-execute
+ db "create table if not exists test1 (col1 text, col2 integer)")))
+
+ (should
+ (=
+ (sqlite-execute db "insert into test1 (col1, col2) values ('foo', 1)")
+ 1))
+ (should
+ (=
+ (sqlite-execute db "insert into test1 (col1, col2) values ('bar', 2)")
+ 1))
+
+ (setq set (sqlite-select db "select * from test1" nil 'set))
+ (should (sqlitep set))
+ (should (sqlite-more-p set))
+ (should (equal (sqlite-next set)
+ '("foo" 1)))
+ (should (equal (sqlite-next set)
+ '("bar" 2)))
+ (should-not (sqlite-next set))
+ (should-not (sqlite-more-p set))
+ (sqlite-finalize set)
+ (should-error (sqlite-next set))))
+
+(ert-deftest sqlite-chars ()
+ (skip-unless (sqlite-available-p))
+ (let (db)
+ (setq db (sqlite-open))
+ (sqlite-execute
+ db "create table if not exists test2 (col1 text, col2 integer)")
+ (sqlite-execute
+ db "insert into test2 (col1, col2) values ('fóo', 3)")
+ (sqlite-execute
+ db "insert into test2 (col1, col2) values ('fó‚o', 3)")
+ (sqlite-execute
+ db "insert into test2 (col1, col2) values ('f‚o', 4)")
+ (should
+ (equal (sqlite-select db "select * from test2" nil 'full)
+ '(("col1" "col2") ("fóo" 3) ("fó‚o" 3) ("f‚o" 4))))))
+
+(ert-deftest sqlite-numbers ()
+ (skip-unless (sqlite-available-p))
+ (let (db)
+ (setq db (sqlite-open))
+ (sqlite-execute
+ db "create table if not exists test3 (col1 integer)")
+ (let ((big (expt 2 50))
+ (small (expt 2 10)))
+ (sqlite-execute db (format "insert into test3 values (%d)" small))
+ (sqlite-execute db (format "insert into test3 values (%d)" big))
+ (should
+ (equal
+ (sqlite-select db "select * from test3")
+ (list (list small) (list big)))))))
+
+(ert-deftest sqlite-param ()
+ (skip-unless (sqlite-available-p))
+ (let (db)
+ (setq db (sqlite-open))
+ (sqlite-execute
+ db "create table if not exists test4 (col1 text, col2 number)")
+ (sqlite-execute db "insert into test4 values (?, ?)" (list "foo" 1))
+ (should
+ (equal
+ (sqlite-select db "select * from test4 where col2 = ?" '(1))
+ '(("foo" 1))))
+ (should
+ (equal
+ (sqlite-select db "select * from test4 where col2 = ?" [1])
+ '(("foo" 1))))))
+
+(ert-deftest sqlite-binary ()
+ (skip-unless (sqlite-available-p))
+ (let (db)
+ (setq db (sqlite-open))
+ (sqlite-execute
+ db "create table if not exists test5 (col1 text, col2 number)")
+ (let ((string (with-temp-buffer
+ (set-buffer-multibyte nil)
+ (insert 0 1 2)
+ (buffer-string))))
+ (should-not (multibyte-string-p string))
+ (sqlite-execute
+ db "insert into test5 values (?, ?)" (list string 2))
+ (let ((out (caar
+ (sqlite-select db "select col1 from test5 where col2 = 2"))))
+ (should (equal out string))))))
+
+(ert-deftest sqlite-different-dbs ()
+ (skip-unless (sqlite-available-p))
+ (let (db1 db2)
+ (setq db1 (sqlite-open))
+ (setq db2 (sqlite-open))
+ (sqlite-execute
+ db1 "create table if not exists test6 (col1 text, col2 number)")
+ (sqlite-execute
+ db2 "create table if not exists test6 (col1 text, col2 number)")
+ (sqlite-execute
+ db1 "insert into test6 values (?, ?)" '("foo" 2))
+ (should (sqlite-select db1 "select * from test6"))
+ (should-not (sqlite-select db2 "select * from test6"))))
+
+(ert-deftest sqlite-close-dbs ()
+ (skip-unless (sqlite-available-p))
+ (let (db)
+ (setq db (sqlite-open))
+ (sqlite-execute
+ db "create table if not exists test6 (col1 text, col2 number)")
+ (sqlite-execute db "insert into test6 values (?, ?)" '("foo" 2))
+ (should (sqlite-select db "select * from test6"))
+ (sqlite-close db)
+ (should-error (sqlite-select db "select * from test6"))))
+
+(ert-deftest sqlite-load-extension ()
+ (skip-unless (sqlite-available-p))
+ (skip-unless (fboundp 'sqlite-load-extension))
+ (let (db)
+ (setq db (sqlite-open))
+ (should-error
+ (sqlite-load-extension db "/usr/lib/sqlite3/notpcre.so"))
+ (should-error
+ (sqlite-load-extension db "/usr/lib/sqlite3/n"))
+ (should-error
+ (sqlite-load-extension db "/usr/lib/sqlite3/"))
+ (should-error
+ (sqlite-load-extension db "/usr/lib/sqlite3"))
+ (should
+ (memq
+ (sqlite-load-extension db "/usr/lib/sqlite3/pcre.so")
+ '(nil t)))
+
+ (should-error
+ (sqlite-load-extension
+ db "/usr/lib/x86_64-linux-gnu/libsqlite3_mod_notcsvtable.so"))
+ (should-error
+ (sqlite-load-extension
+ db "/usr/lib/x86_64-linux-gnu/libsqlite3_mod_csvtablen.so"))
+ (should-error
+ (sqlite-load-extension
+ db "/usr/lib/x86_64-linux-gnu/libsqlite3_mod_csvtable"))
+ (should
+ (memq
+ (sqlite-load-extension
+ db "/usr/lib/x86_64-linux-gnu/libsqlite3_mod_csvtable.so")
+ '(nil t)))))
+
+(ert-deftest sqlite-blob ()
+ (skip-unless (sqlite-available-p))
+ (let (db)
+ (progn
+ (setq db (sqlite-open))
+ (sqlite-execute
+ db "create table if not exists test10 (col1 text, col2 blob, col3 numbre)")
+ (let ((string (with-temp-buffer
+ (set-buffer-multibyte nil)
+ (insert 0 1 2)
+ (buffer-string))))
+ (should-not (multibyte-string-p string))
+ (sqlite-execute
+ db "insert into test10 values (?, ?, 1)"
+ (list string
+ (propertize string
+ 'coding-system 'binary)))
+ (cl-destructuring-bind
+ (c1 c2 _)
+ (car (sqlite-select db "select * from test10 where col3 = 1"))
+ (should (equal c1 string))
+ (should (equal c2 string))
+ (should (multibyte-string-p c1))
+ (should-not (multibyte-string-p c2)))))))
+
+;;; sqlite-tests.el ends here
diff --git a/test/src/syntax-resources/syntax-comments.txt b/test/src/syntax-resources/syntax-comments.txt
new file mode 100644
index 00000000000..a292d816b9d
--- /dev/null
+++ b/test/src/syntax-resources/syntax-comments.txt
@@ -0,0 +1,94 @@
+/* This file is a test file for tests of the comment handling in src/syntax.c.
+ This includes the testing of comments which figure in parse-partial-sexp
+ and scan-lists. */
+
+/* Straight C comments */
+1/* comment */1
+2/**/2
+3// comment
+3
+4//
+4
+5/*/5
+6*/6
+7/* \*/7
+8*/8
+9/* \\*/9
+10*/10
+11// \
+12
+11
+13// \\
+14
+13
+15/* /*/15
+
+/* C Comments within lists */
+59}59
+50{ /*70 comment */71 }50
+51{ /**/ }51
+52{ //72 comment
+73}52
+53{ //
+}53
+54{ //74 \
+}54
+55{/* */}55
+56{ /*76 \*/ }56
+57*/77
+58}58
+60{ /*78 \\*/79}60
+
+
+/* Straight Pascal comments (not nested) */
+20}20
+21{ Comment }21
+22{}22
+23{
+}23
+24{
+25{25
+}24
+26{ \}26
+
+
+/* Straight Lisp comments (not nested) */
+30
+30
+31; Comment
+31
+32;;;;;;;;;
+32
+33; \
+33
+
+/* Lisp comments within lists */
+40)40
+41(;90 comment
+91)41
+42(;92\
+93)42
+43( ;94
+95
+
+/* Nested Lisp comments */
+100|#100
+101#|#
+102#||#102
+103#| Comment |#103
+104#| Comment
+|#104
+105#|#|#105
+106#| #| Comment |# |#106
+107#|#|#|#|#|#|#|#|#| Comment |#|#|#|#|#|#|#|#|#107
+
+/* Mixed Lisp comments */
+110; #|
+110
+111#| ; |#111
+
+Local Variables:
+mode: fundamental
+eval: (set-syntax-table (make-syntax-table))
+End:
+999 \ No newline at end of file
diff --git a/test/src/syntax-tests.el b/test/src/syntax-tests.el
index 67e7ec32517..751a900a23e 100644
--- a/test/src/syntax-tests.el
+++ b/test/src/syntax-tests.el
@@ -1,6 +1,6 @@
;;; syntax-tests.el --- tests for syntax.c functions -*- lexical-binding: t -*-
-;; Copyright (C) 2017 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2022 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -20,6 +20,8 @@
;;; Code:
(require 'ert)
+(require 'ert-x)
+(require 'cl-lib)
(ert-deftest parse-partial-sexp-continue-over-comment-marker ()
"Continue a parse that stopped in the middle of a comment marker."
@@ -55,6 +57,16 @@
(should (equal (parse-partial-sexp aftC pointX nil nil pps-aftC)
ppsX)))))
+(ert-deftest syntax-class-character-test ()
+ (cl-loop for char across " .w_()'\"$\\/<>@!|"
+ for i from 0
+ do (should (= char (syntax-class-to-char i)))
+ when (string-to-syntax (string char))
+ do (should (= char (syntax-class-to-char
+ (car (string-to-syntax (string char)))))))
+ (should-error (syntax-class-to-char -1))
+ (should-error (syntax-class-to-char 200)))
+
(ert-deftest parse-partial-sexp-paren-comments ()
"Test syntax parsing with paren comment markers.
Specifically, where the first character of the comment marker is
@@ -82,4 +94,431 @@ also has open paren syntax (see Bug#24870)."
(should (equal (parse-partial-sexp pointC pointX nil nil ppsC)
ppsX)))))
+
+;;; Commentary:
+;; The next bit tests the handling of comments in syntax.c, in
+;; particular the functions `forward-comment' and `scan-lists' and
+;; `parse-partial-sexp' (in so far as they relate to comments).
+
+;; It is intended to enhance this bit to test nested comments
+;; (2020-10-01).
+
+;; This bit uses the data file syntax-resources/syntax-comments.txt.
+
+(defun syntax-comments-point (n forw)
+ "Return the buffer offset corresponding to the \"label\" N.
+N is a decimal number which appears in the data file, usually
+twice, as \"labels\". It can also be a negative number or zero.
+FORW is t when we're using the label at BOL, nil for the one at EOL.
+
+If the label N doesn't exist in the current buffer, an exception
+is thrown.
+
+When FORW is t and N positive, we return the position after the
+first occurrence of label N at BOL in the data file. With FORW
+nil, we return the position before the last occurrence of the
+label at EOL in the data file.
+
+When N is negative, we return instead the position of the end of
+line that the -N label is on. When it is zero, we return POINT."
+ (if (zerop n)
+ (point)
+ (let ((str (format "%d" (abs n))))
+ (save-excursion
+ (if forw
+ (progn
+ (goto-char (point-min))
+ (re-search-forward
+ (concat "^\\(" str "\\)\\([^0-9\n]\\|$\\)"))
+ (if (< n 0)
+ (progn (end-of-line) (point))
+ (match-end 1)))
+ (goto-char (point-max))
+ (re-search-backward
+ (concat "\\(^\\|[^0-9]\\)\\(" str "\\)$"))
+ (if (< n 0)
+ (progn (end-of-line) (point))
+ (match-beginning 2)))))))
+
+(defun syntax-comments-midpoint (n)
+ "Return the buffer offset corresponding to the \"label\" N.
+N is a positive decimal number which should appear in the buffer
+exactly once. The label need not be at the beginning or end of a
+line.
+
+The return value is the position just before the label.
+
+If the label N doesn't exist in the current buffer, an exception
+is thrown."
+ (let ((str (format "%d" n)))
+ (save-excursion
+ (goto-char (point-min))
+ (re-search-forward
+ (concat "\\(^\\|[^0-9]\\)\\(" str "\\)\\([^0-9\n]\\|$\\)"))
+ (match-beginning 2))))
+
+(eval-and-compile
+ (defvar syntax-comments-section))
+
+(defmacro syntax-comments (-type- -dir- res start &optional stop)
+ "Create an ERT test to test (forward-comment 1/-1).
+The test uses a fixed name data file, which it visits. It calls
+entry and exit functions to set up and tear down syntax entries
+for comment characters. The test is given a name based on the
+global variable `syntax-comments-section', the direction of
+movement and the value of START.
+
+-TYPE- (unquoted) is a symbol from whose name the entry and exit
+function names are derived by appending \"-in\" and \"-out\".
+
+-DIR- (unquoted) is `forward' or `backward', the direction
+`forward-comment' is attempted.
+
+RES, t or nil, is the expected result from `forward-comment'.
+
+START and STOP are decimal numbers corresponding to labels in the
+data file marking the start and expected stop positions. See
+`syntax-comments-point' for a precise specification. If STOP is
+missing or nil, the value of START is assumed for it."
+ (declare (debug t))
+ (let ((forw
+ (cond
+ ((eq -dir- 'forward) t)
+ ((eq -dir- 'backward) nil)
+ (t (error "Invalid -dir- argument \"%s\" to `syntax-comments'" -dir-))))
+ (start-str (format "%d" (abs start)))
+ (type -type-))
+ `(ert-deftest ,(intern (concat "syntax-comments-"
+ syntax-comments-section
+ (if forw "-f" "-b") start-str))
+ ()
+ (with-current-buffer
+ (find-file
+ ,(ert-resource-file "syntax-comments.txt"))
+ (,(intern (concat (symbol-name type) "-in")))
+ (goto-char (syntax-comments-point ,start ,forw))
+ (let ((stop (syntax-comments-point ,(or stop start) ,(not forw))))
+ (should (eq (forward-comment ,(if forw 1 -1)) ,res))
+ (should (eq (point) stop)))
+ (,(intern (concat (symbol-name type) "-out")))))))
+
+(defmacro syntax-br-comments (-type- -dir- res -start- &optional stop)
+ "Create an ERT test to test (scan-lists <position> 1/-1 0).
+This is to test the interface between scan-lists and the internal
+comment routines in syntax.c.
+
+The test uses a fixed name data file, which it visits. It calls
+entry and exit functions to set up and tear down syntax entries
+for comment and paren characters. The test is given a name based
+on the global variable `syntax-comments-section', the direction
+of movement and the value of -START-.
+
+-TYPE- (unquoted) is a symbol from whose name the entry and exit
+function names are derived by appending \"-in\" and \"-out\".
+
+-DIR- (unquoted) is `forward' or `backward', the direction
+`scan-lists' is attempted.
+
+RES is t if `scan-lists' is expected to return, nil if it is
+expected to raise a `scan-error' exception.
+
+-START- and STOP are decimal numbers corresponding to labels in the
+data file marking the start and expected stop positions. See
+`syntax-comments-point' for a precise specification. If STOP is
+missing or nil, the value of -START- is assumed for it."
+ (declare (debug t))
+ (let* ((forw
+ (cond
+ ((eq -dir- 'forward) t)
+ ((eq -dir- 'backward) nil)
+ (t (error "Invalid -dir- argument \"%s\" to `syntax-br-comments'" -dir-))))
+ (start -start-)
+ (start-str (format "%d" (abs start)))
+ (type -type-))
+ `(ert-deftest ,(intern (concat "syntax-br-comments-"
+ syntax-comments-section
+ (if forw "-f" "-b") start-str))
+ ()
+ (with-current-buffer
+ (find-file
+ ,(ert-resource-file "syntax-comments.txt"))
+ (,(intern (concat (symbol-name type) "-in")))
+ (let ((start-pos (syntax-comments-point ,start ,forw))
+ ,@(if res
+ `((stop-pos (syntax-comments-point
+ ,(or stop start) ,(not forw))))))
+ ,(if res
+ `(should
+ (eq (scan-lists start-pos ,(if forw 1 -1) 0)
+ stop-pos))
+ `(should-error (scan-lists start-pos ,(if forw 1 -1) 0)
+ :type 'scan-error)))
+ (,(intern (concat (symbol-name type) "-out")))))))
+
+(defmacro syntax-pps-comments (-type- -start- open close &optional -stop-)
+ "Create an ERT test to test `parse-partial-sexp' with comments.
+This is to test the interface between `parse-partial-sexp' and
+the internal comment routines in syntax.c.
+
+The test uses a fixed name data file, which it visits. It calls
+entry and exit functions to set up and tear down syntax entries
+for comment and paren characters. The test is given a name based
+on the global variable `syntax-comments-section', and the value
+of -START-.
+
+The generated test calls `parse-partial-sexp' three times, the
+first two with COMMENTSTOP set to `syntax-table' so as to stop
+after the start and end of the comment. The third call is
+expected to stop at the brace/paren matching the one where the
+test started.
+
+-TYPE- (unquoted) is a symbol from whose name the entry and exit
+function names are derived by appending \"-in\" and \"-out\".
+
+-START- and -STOP- are decimal numbers corresponding to labels in
+the data file marking the start and expected stop positions. See
+`syntax-comments-point' for a precise specification. If -STOP-
+is missing or nil, the value of -START- is assumed for it.
+
+OPEN and CLOSE are decimal numbers corresponding to labels in the
+data file marking just after the comment opener and closer where
+the `parse-partial-sexp's are expected to stop. See
+`syntax-comments-midpoint' for a precise specification."
+ (declare (debug t))
+ (let* ((type -type-)
+ (start -start-)
+ (start-str (format "%d" start))
+ (stop (or -stop- start)))
+ `(ert-deftest ,(intern (concat "syntax-pps-comments-"
+ syntax-comments-section
+ "-" start-str))
+ ()
+ (with-current-buffer
+ (find-file
+ ,(ert-resource-file "syntax-comments.txt"))
+ (,(intern (concat (symbol-name type) "-in")))
+ (let ((start-pos (syntax-comments-point ,start t))
+ (open-pos (syntax-comments-midpoint ,open))
+ (close-pos (syntax-comments-midpoint ,close))
+ (stop-pos (syntax-comments-point ,stop nil))
+ s)
+ (setq s (parse-partial-sexp
+ start-pos (point-max) 0 nil nil 'syntax-table))
+ (should (eq (point) open-pos))
+ (setq s (parse-partial-sexp
+ (point) (point-max) 0 nil s 'syntax-table))
+ (should (eq (point) close-pos))
+ (setq s (parse-partial-sexp (point) (point-max) 0 nil s))
+ (should (eq (point) stop-pos)))
+ (,(intern (concat (symbol-name type) "-out")))))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; "Pascal" style comments - single character delimiters, the closing
+;; delimiter not being newline.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+(defun {-in ()
+ (setq parse-sexp-ignore-comments t)
+ (setq comment-end-can-be-escaped nil)
+ (modify-syntax-entry ?{ "<")
+ (modify-syntax-entry ?} ">"))
+(defun {-out ()
+ (modify-syntax-entry ?{ "(}")
+ (modify-syntax-entry ?} "){"))
+(eval-and-compile
+ (setq syntax-comments-section "pascal"))
+
+(syntax-comments { forward nil 20 0)
+(syntax-comments { backward nil 20 0)
+(syntax-comments { forward t 21)
+(syntax-comments { backward t 21)
+(syntax-comments { forward t 22)
+(syntax-comments { backward t 22)
+
+(syntax-comments { forward t 23)
+(syntax-comments { backward t 23)
+(syntax-comments { forward t 24)
+(syntax-comments { backward t 24)
+(syntax-comments { forward t 26)
+(syntax-comments { backward t 26)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; "Lisp" style comments - single character opening delimiters on line
+;; comments.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+(defun \;-in ()
+ (setq parse-sexp-ignore-comments t)
+ (setq comment-end-can-be-escaped nil)
+ (modify-syntax-entry ?\n ">")
+ (modify-syntax-entry ?\; "<")
+ (modify-syntax-entry ?{ ".")
+ (modify-syntax-entry ?} "."))
+(defun \;-out ()
+ (modify-syntax-entry ?\n " ")
+ (modify-syntax-entry ?\; ".")
+ (modify-syntax-entry ?{ "(}")
+ (modify-syntax-entry ?} "){"))
+(eval-and-compile
+ (setq syntax-comments-section "lisp"))
+
+(syntax-comments \; backward nil 30 30)
+(syntax-comments \; forward t 31)
+(syntax-comments \; backward t 31)
+(syntax-comments \; forward t 32)
+(syntax-comments \; backward t 32)
+(syntax-comments \; forward t 33)
+(syntax-comments \; backward t 33)
+
+;; "Lisp" style comments inside lists.
+(syntax-br-comments \; backward nil 40)
+(syntax-br-comments \; forward t 41)
+(syntax-br-comments \; backward t 41)
+(syntax-br-comments \; forward t 42)
+(syntax-br-comments \; backward t 42)
+(syntax-br-comments \; forward nil 43)
+
+;; "Lisp" style comments parsed by `parse-partial-sexp'.
+(syntax-pps-comments \; 41 90 91)
+(syntax-pps-comments \; 42 92 93)
+(syntax-pps-comments \; 43 94 95 -999)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; "Lisp" style nested comments: between delimiters #| |#.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+(defun \#|-in ()
+ (setq parse-sexp-ignore-comments t)
+ (modify-syntax-entry ?# ". 14")
+ (modify-syntax-entry ?| ". 23n")
+ (modify-syntax-entry ?\; "< b")
+ (modify-syntax-entry ?\n "> b"))
+(defun \#|-out ()
+ (modify-syntax-entry ?# ".")
+ (modify-syntax-entry ?| ".")
+ (modify-syntax-entry ?\; ".")
+ (modify-syntax-entry ?\n " "))
+(eval-and-compile
+ (setq syntax-comments-section "lisp-n"))
+
+(syntax-comments \#| forward nil 100 0)
+(syntax-comments \#| backward nil 100 0)
+(syntax-comments \#| forward nil 101 -999)
+(syntax-comments \#| forward t 102)
+(syntax-comments \#| backward t 102)
+
+(syntax-comments \#| forward t 103)
+(syntax-comments \#| backward t 103)
+(syntax-comments \#| forward t 104)
+(syntax-comments \#| backward t 104)
+
+(syntax-comments \#| forward nil 105 -999)
+(syntax-comments \#| backward t 105)
+(syntax-comments \#| forward t 106)
+(syntax-comments \#| backward t 106)
+(syntax-comments \#| forward t 107)
+(syntax-comments \#| backward t 107)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Mixed "Lisp" style (nested and unnested) comments.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+(syntax-comments \#| forward t 110)
+(syntax-comments \#| backward t 110)
+(syntax-comments \#| forward t 111)
+(syntax-comments \#| backward t 111)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Emacs 27 "C" style comments - `comment-end-can-be-escaped' is non-nil.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+(defun /*-in ()
+ (setq parse-sexp-ignore-comments t)
+ (setq comment-end-can-be-escaped t)
+ (modify-syntax-entry ?/ ". 124b")
+ (modify-syntax-entry ?* ". 23")
+ (modify-syntax-entry ?\n "> b"))
+(defun /*-out ()
+ (setq comment-end-can-be-escaped nil)
+ (modify-syntax-entry ?/ ".")
+ (modify-syntax-entry ?* ".")
+ (modify-syntax-entry ?\n " "))
+(eval-and-compile
+ (setq syntax-comments-section "c"))
+
+(syntax-comments /* forward t 1)
+(syntax-comments /* backward t 1)
+(syntax-comments /* forward t 2)
+(syntax-comments /* backward t 2)
+(syntax-comments /* forward t 3)
+(syntax-comments /* backward t 3)
+
+(syntax-comments /* forward t 4)
+(syntax-comments /* backward t 4)
+(syntax-comments /* forward t 5 6)
+(syntax-comments /* backward nil 5 0)
+(syntax-comments /* forward nil 6 0)
+(syntax-comments /* backward t 6 5)
+
+(syntax-comments /* forward t 7 8)
+(syntax-comments /* backward nil 7 0)
+(syntax-comments /* forward nil 8 0)
+(syntax-comments /* backward t 8 7)
+(syntax-comments /* forward t 9)
+(syntax-comments /* backward t 9)
+
+(syntax-comments /* forward nil 10 0)
+(syntax-comments /* backward nil 10 0)
+(syntax-comments /* forward t 11)
+(syntax-comments /* backward t 11)
+
+(syntax-comments /* forward t 13 14)
+(syntax-comments /* backward nil 13 -14)
+(syntax-comments /* forward t 15)
+(syntax-comments /* backward t 15)
+
+;; Emacs 27 "C" style comments inside brace lists.
+(syntax-br-comments /* forward t 50)
+(syntax-br-comments /* backward t 50)
+(syntax-br-comments /* forward t 51)
+(syntax-br-comments /* backward t 51)
+(syntax-br-comments /* forward t 52)
+(syntax-br-comments /* backward t 52)
+
+(syntax-br-comments /* forward t 53)
+(syntax-br-comments /* backward t 53)
+(syntax-br-comments /* forward t 54 20)
+(syntax-br-comments /* backward t 54)
+(syntax-br-comments /* forward t 55)
+(syntax-br-comments /* backward t 55)
+
+(syntax-br-comments /* forward t 56 58)
+(syntax-br-comments /* backward t 58 56)
+(syntax-br-comments /* backward nil 59)
+(syntax-br-comments /* forward t 60)
+(syntax-br-comments /* backward t 60)
+
+;; Emacs 27 "C" style comments parsed by `parse-partial-sexp'.
+(syntax-pps-comments /* 50 70 71)
+(syntax-pps-comments /* 52 72 73)
+(syntax-pps-comments /* 54 74 55 20)
+(syntax-pps-comments /* 56 76 77 58)
+(syntax-pps-comments /* 60 78 79)
+
+(ert-deftest test-from-to-parse-partial-sexp ()
+ (with-temp-buffer
+ (insert "foo")
+ (should (parse-partial-sexp 1 1))
+ (should-error (parse-partial-sexp 2 1))))
+
+(ert-deftest syntax-char-syntax ()
+ ;; Verify that char-syntax behaves identically in interpreted and
+ ;; byte-compiled code (bug#53260).
+ (let ((cs (byte-compile (lambda (x) (char-syntax x)))))
+ ;; Use a unibyte buffer with a syntax table using symbol syntax
+ ;; for raw byte 128.
+ (with-temp-buffer
+ (set-buffer-multibyte nil)
+ (let ((st (make-syntax-table)))
+ (modify-syntax-entry (unibyte-char-to-multibyte 128) "_" st)
+ (set-syntax-table st)
+ (should (equal (eval '(char-syntax 128) t) ?_))
+ (should (equal (funcall cs 128) ?_))))
+ (list (char-syntax 128) (funcall cs 128))))
+
;;; syntax-tests.el ends here
diff --git a/test/src/textprop-tests.el b/test/src/textprop-tests.el
index 1dcfa8ea29d..d6cee6b6cbe 100644
--- a/test/src/textprop-tests.el
+++ b/test/src/textprop-tests.el
@@ -1,6 +1,6 @@
-;;; textprop-tests.el --- Test suite for text properties.
+;;; textprop-tests.el --- Test suite for text properties. -*- lexical-binding: t -*-
-;; Copyright (C) 2015-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2022 Free Software Foundation, Inc.
;; Author: Wolfgang Jenkner <wjenkner@inode.at>
;; Keywords: internal
@@ -69,4 +69,4 @@
(null stack)))))
(provide 'textprop-tests)
-;; textprop-tests.el ends here.
+;;; textprop-tests.el ends here
diff --git a/test/src/thread-tests.el b/test/src/thread-tests.el
index 10b2f0761df..75d67140a90 100644
--- a/test/src/thread-tests.el
+++ b/test/src/thread-tests.el
@@ -1,6 +1,6 @@
-;;; threads.el --- tests for threads.
+;;; thread-tests.el --- tests for threads. -*- lexical-binding: t -*-
-;; Copyright (C) 2012-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2022 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -19,39 +19,74 @@
;;; Code:
+(require 'thread)
+
+;; Declare the functions in case Emacs has been configured --without-threads.
+(declare-function all-threads "thread.c" ())
+(declare-function condition-mutex "thread.c" (cond))
+(declare-function condition-name "thread.c" (cond))
+(declare-function condition-notify "thread.c" (cond &optional all))
+(declare-function condition-wait "thread.c" (cond))
+(declare-function current-thread "thread.c" ())
+(declare-function make-condition-variable "thread.c" (mutex &optional name))
+(declare-function make-mutex "thread.c" (&optional name))
+(declare-function make-thread "thread.c" (function &optional name))
+(declare-function mutex-lock "thread.c" (mutex))
+(declare-function mutex-unlock "thread.c" (mutex))
+(declare-function thread--blocker "thread.c" (thread))
+(declare-function thread-live-p "thread.c" (thread))
+(declare-function thread-join "thread.c" (thread))
+(declare-function thread-last-error "thread.c" (&optional cleanup))
+(declare-function thread-name "thread.c" (thread))
+(declare-function thread-signal "thread.c" (thread error-symbol data))
+(declare-function thread-yield "thread.c" ())
+(defvar main-thread)
+
(ert-deftest threads-is-one ()
- "test for existence of a thread"
+ "Test for existence of a thread."
+ (skip-unless (featurep 'threads))
(should (current-thread)))
(ert-deftest threads-threadp ()
- "test of threadp"
+ "Test of threadp."
+ (skip-unless (featurep 'threads))
(should (threadp (current-thread))))
(ert-deftest threads-type ()
- "test of thread type"
+ "Test of thread type."
+ (skip-unless (featurep 'threads))
(should (eq (type-of (current-thread)) 'thread)))
(ert-deftest threads-name ()
- "test for name of a thread"
+ "Test for name of a thread."
+ (skip-unless (featurep 'threads))
(should
(string= "hi bob" (thread-name (make-thread #'ignore "hi bob")))))
-(ert-deftest threads-alive ()
- "test for thread liveness"
+(ert-deftest threads-live ()
+ "Test for thread liveness."
+ (skip-unless (featurep 'threads))
(should
- (thread-alive-p (make-thread #'ignore))))
+ (thread-live-p (make-thread #'ignore))))
(ert-deftest threads-all-threads ()
- "simple test for all-threads"
+ "Simple test for `all-threads'."
+ (skip-unless (featurep 'threads))
(should (listp (all-threads))))
+(ert-deftest threads-main-thread ()
+ "Simple test for `all-threads'."
+ (skip-unless (featurep 'threads))
+ (should (eq main-thread (car (all-threads)))))
+
(defvar threads-test-global nil)
(defun threads-test-thread1 ()
(setq threads-test-global 23))
(ert-deftest threads-basic ()
- "basic thread test"
+ "Basic thread test."
+ (skip-unless (featurep 'threads))
(should
(progn
(setq threads-test-global nil)
@@ -61,19 +96,30 @@
threads-test-global)))
(ert-deftest threads-join ()
- "test of thread-join"
+ "Test of `thread-join'."
+ (skip-unless (featurep 'threads))
(should
(progn
(setq threads-test-global nil)
(let ((thread (make-thread #'threads-test-thread1)))
- (thread-join thread)
- (and threads-test-global
- (not (thread-alive-p thread)))))))
+ (and (= (thread-join thread) 23)
+ (= threads-test-global 23)
+ (not (thread-live-p thread)))))))
(ert-deftest threads-join-self ()
- "cannot thread-join the current thread"
+ "Cannot `thread-join' the current thread."
+ (skip-unless (featurep 'threads))
(should-error (thread-join (current-thread))))
+(ert-deftest threads-join-error ()
+ "Test of error signaling from `thread-join'."
+ :tags '(:unstable)
+ (skip-unless (featurep 'threads))
+ (let ((thread (make-thread #'threads-call-error)))
+ (while (thread-live-p thread)
+ (thread-yield))
+ (should-error (thread-join thread))))
+
(defvar threads-test-binding nil)
(defun threads-test-thread2 ()
@@ -82,7 +128,8 @@
(setq threads-test-global 23))
(ert-deftest threads-let-binding ()
- "simple test of threads and let bindings"
+ "Simple test of threads and let bindings."
+ (skip-unless (featurep 'threads))
(should
(progn
(setq threads-test-global nil)
@@ -93,19 +140,23 @@
threads-test-global))))
(ert-deftest threads-mutexp ()
- "simple test of mutexp"
+ "Simple test of `mutexp'."
+ (skip-unless (featurep 'threads))
(should-not (mutexp 'hi)))
(ert-deftest threads-mutexp-2 ()
- "another simple test of mutexp"
+ "Another simple test of `mutexp'."
+ (skip-unless (featurep 'threads))
(should (mutexp (make-mutex))))
(ert-deftest threads-mutex-type ()
- "type-of mutex"
+ "type-of mutex."
+ (skip-unless (featurep 'threads))
(should (eq (type-of (make-mutex)) 'mutex)))
(ert-deftest threads-mutex-lock-unlock ()
- "test mutex-lock and unlock"
+ "Test `mutex-lock' and unlock."
+ (skip-unless (featurep 'threads))
(should
(let ((mx (make-mutex)))
(mutex-lock mx)
@@ -113,7 +164,8 @@
t)))
(ert-deftest threads-mutex-recursive ()
- "test mutex-lock and unlock"
+ "Test mutex recursion."
+ (skip-unless (featurep 'threads))
(should
(let ((mx (make-mutex)))
(mutex-lock mx)
@@ -133,7 +185,8 @@
(mutex-unlock threads-mutex))
(ert-deftest threads-mutex-contention ()
- "test of mutex contention"
+ "Test of mutex contention."
+ (skip-unless (featurep 'threads))
(should
(progn
(setq threads-mutex (make-mutex))
@@ -153,8 +206,9 @@
(mutex-lock threads-mutex))
(ert-deftest threads-mutex-signal ()
- "test signaling a blocked thread"
- (should
+ "Test signaling a blocked thread."
+ (skip-unless (featurep 'threads))
+ (should-error
(progn
(setq threads-mutex (make-mutex))
(setq threads-mutex-key nil)
@@ -163,14 +217,17 @@
(while (not threads-mutex-key)
(thread-yield))
(thread-signal thr 'quit nil)
- (thread-join thr))
- t)))
+ ;; `quit' is not catched by `should-error'. We must indicate it.
+ (condition-case nil
+ (thread-join thr)
+ (quit (signal 'error nil)))))))
(defun threads-test-io-switch ()
(setq threads-test-global 23))
(ert-deftest threads-io-switch ()
- "test that accept-process-output causes thread switch"
+ "Test that `accept-process-output' causes thread switch."
+ (skip-unless (featurep 'threads))
(should
(progn
(setq threads-test-global nil)
@@ -180,60 +237,72 @@
threads-test-global)))
(ert-deftest threads-condvarp ()
- "simple test of condition-variable-p"
+ "Simple test of `condition-variable-p'."
+ (skip-unless (featurep 'threads))
(should-not (condition-variable-p 'hi)))
(ert-deftest threads-condvarp-2 ()
- "another simple test of condition-variable-p"
+ "Another simple test of `condition-variable-p'."
+ (skip-unless (featurep 'threads))
(should (condition-variable-p (make-condition-variable (make-mutex)))))
(ert-deftest threads-condvar-type ()
"type-of condvar"
+ (skip-unless (featurep 'threads))
(should (eq (type-of (make-condition-variable (make-mutex)))
'condition-variable)))
(ert-deftest threads-condvar-mutex ()
- "simple test of condition-mutex"
+ "Simple test of `condition-mutex'."
+ (skip-unless (featurep 'threads))
(should
(let ((m (make-mutex)))
(eq m (condition-mutex (make-condition-variable m))))))
(ert-deftest threads-condvar-name ()
- "simple test of condition-name"
+ "Simple test of `condition-name'."
+ (skip-unless (featurep 'threads))
(should
(eq nil (condition-name (make-condition-variable (make-mutex))))))
(ert-deftest threads-condvar-name-2 ()
- "another simple test of condition-name"
+ "Another simple test of `condition-name'."
+ (skip-unless (featurep 'threads))
(should
(string= "hi bob"
(condition-name (make-condition-variable (make-mutex)
"hi bob")))))
-(defun call-error ()
+
+(defun threads-call-error ()
"Call `error'."
(error "Error is called"))
;; This signals an error internally; the error should be caught.
-(defun thread-custom ()
- (defcustom thread-custom-face 'highlight
+(defun threads-custom ()
+ (defcustom threads-custom-face 'highlight
"Face used for thread customizations."
:type 'face
:group 'widget-faces))
-(ert-deftest thread-errors ()
+(ert-deftest threads-errors ()
"Test what happens when a thread signals an error."
+ (skip-unless (featurep 'threads))
(let (th1 th2)
- (setq th1 (make-thread #'call-error "call-error"))
+ (setq th1 (make-thread #'threads-call-error "call-error"))
(should (threadp th1))
- (while (thread-alive-p th1)
+ (while (thread-live-p th1)
(thread-yield))
(should (equal (thread-last-error)
'(error "Error is called")))
- (setq th2 (make-thread #'thread-custom "thread-custom"))
+ (should (equal (thread-last-error 'cleanup)
+ '(error "Error is called")))
+ (should-not (thread-last-error))
+ (setq th2 (make-thread #'threads-custom "threads-custom"))
(should (threadp th2))))
-(ert-deftest thread-sticky-point ()
+(ert-deftest threads-sticky-point ()
"Test bug #25165 with point movement in cloned buffer."
+ (skip-unless (featurep 'threads))
(with-temp-buffer
(insert "Lorem ipsum dolor sit amet, consectetur adipiscing elit.")
(goto-char (point-min))
@@ -242,16 +311,36 @@
(sit-for 1)
(should (= (point) 21))))
-(ert-deftest thread-signal-early ()
+(ert-deftest threads-signal-early ()
"Test signaling a thread as soon as it is started by the OS."
+ (skip-unless (featurep 'threads))
(let ((thread
- (make-thread #'(lambda ()
- (while t (thread-yield))))))
+ (make-thread (lambda ()
+ (while t (thread-yield))))))
(thread-signal thread 'error nil)
(sit-for 1)
- (should-not (thread-alive-p thread))
+ (should-not (thread-live-p thread))
(should (equal (thread-last-error) '(error)))))
+(ert-deftest threads-signal-main-thread ()
+ "Test signaling the main thread."
+ (skip-unless (featurep 'threads))
+ ;; We cannot use `ert-with-message-capture', because threads do not
+ ;; know let-bound variables.
+ (with-current-buffer "*Messages*"
+ (let (buffer-read-only)
+ (erase-buffer))
+ (let ((thread
+ (make-thread (lambda () (thread-signal main-thread 'error nil)))))
+ (while (thread-live-p thread)
+ (thread-yield))
+ (read-event nil nil 0.1)
+ ;; No error has been raised, which is part of the test.
+ (should
+ (string-match
+ (format-message "Error %s: (error nil)" thread)
+ (buffer-string ))))))
+
(defvar threads-condvar nil)
(defun threads-test-condvar-wait ()
@@ -263,7 +352,8 @@
(condition-wait threads-condvar)))
(ert-deftest threads-condvar-wait ()
- "test waiting on conditional variable"
+ "Test waiting on conditional variable."
+ (skip-unless (featurep 'threads))
(let ((cv-mutex (make-mutex))
new-thread)
;; We could have spurious threads from the previous tests still
@@ -274,7 +364,7 @@
(setq new-thread (make-thread #'threads-test-condvar-wait))
;; Make sure new-thread is alive.
- (should (thread-alive-p new-thread))
+ (should (thread-live-p new-thread))
(should (= (length (all-threads)) 2))
;; Wait for new-thread to become blocked on the condvar.
(while (not (eq (thread--blocker new-thread) threads-condvar))
@@ -287,7 +377,7 @@
(sleep-for 0.1)
;; Make sure the thread is still there. This used to fail due to
;; a bug in thread.c:condition_wait_callback.
- (should (thread-alive-p new-thread))
+ (should (thread-live-p new-thread))
(should (= (length (all-threads)) 2))
(should (eq (thread--blocker new-thread) threads-condvar))
@@ -298,4 +388,34 @@
(should (= (length (all-threads)) 1))
(should (equal (thread-last-error) '(error "Die, die, die!")))))
-;;; threads.el ends here
+(ert-deftest threads-test-bug33073 ()
+ (skip-unless (fboundp 'make-thread))
+ (let ((th (make-thread 'ignore)))
+ (should-not (equal th main-thread))))
+
+(defvar threads-test--var 'global)
+
+(ert-deftest threads-test-bug48990 ()
+ (skip-unless (fboundp 'make-thread))
+ (let ((buf1 (generate-new-buffer " thread-test"))
+ (buf2 (generate-new-buffer " thread-test")))
+ (with-current-buffer buf1
+ (setq-local threads-test--var 'local1))
+ (with-current-buffer buf2
+ (setq-local threads-test--var 'local2))
+ (let ((seen nil))
+ (with-current-buffer buf1
+ (should (eq threads-test--var 'local1))
+ (make-thread (lambda () (setq seen threads-test--var))))
+ (with-current-buffer buf2
+ (should (eq threads-test--var 'local2))
+ (let ((threads-test--var 'let2))
+ (should (eq threads-test--var 'let2))
+ (while (not seen)
+ (thread-yield))
+ (should (eq threads-test--var 'let2))
+ (should (eq seen 'local1)))
+ (should (eq threads-test--var 'local2)))
+ (should (eq threads-test--var 'global)))))
+
+;;; thread-tests.el ends here
diff --git a/test/src/timefns-tests.el b/test/src/timefns-tests.el
new file mode 100644
index 00000000000..24f9000ffbd
--- /dev/null
+++ b/test/src/timefns-tests.el
@@ -0,0 +1,264 @@
+;;; timefns-tests.el --- tests for timefns.c -*- lexical-binding: t -*-
+
+;; Copyright (C) 2016-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+
+(defun timefns-tests--decode-time (look zone decoded-time)
+ (should (equal (decode-time look zone t) decoded-time))
+ (should (equal (decode-time look zone 'integer)
+ (cons (time-convert (car decoded-time) 'integer)
+ (cdr decoded-time)))))
+
+;;; Check format-time-string and decode-time with various TZ settings.
+;;; Use only POSIX-compatible TZ values, since the tests should work
+;;; even if tzdb is not in use.
+(ert-deftest format-time-string-with-zone ()
+ ;; Don’t use (0 0 0 0) as the test case, as there are too many bugs
+ ;; in MS-Windows (and presumably other) C libraries when formatting
+ ;; time stamps near the Epoch of 1970-01-01 00:00:00 UTC, and this
+ ;; test is for GNU Emacs, not for C runtimes. Instead, look before
+ ;; you leap: "look" is the timestamp just before the first leap
+ ;; second on 1972-06-30 23:59:60 UTC, so it should format to the
+ ;; same string regardless of whether the underlying C library
+ ;; ignores leap seconds, while avoiding circa-1970 glitches.
+ ;;
+ ;; Similarly, stick to the limited set of time zones that are
+ ;; supported by both POSIX and MS-Windows: exactly 3 ASCII letters
+ ;; in the abbreviation, and no DST.
+ (let ((format "%Y-%m-%d %H:%M:%S.%3N %z (%Z)"))
+ (dolist (look '((1202 22527 999999 999999)
+ (7879679999900 . 100000)
+ (78796799999999999999 . 1000000000000)))
+ ;; UTC.
+ (let* ((look-ticks-hz (time-convert look t))
+ (hz (cdr look-ticks-hz))
+ (look-integer (time-convert look 'integer))
+ (sec (time-add (time-convert 59 hz)
+ (time-subtract look-ticks-hz
+ (time-convert look-integer hz)))))
+ (should (string-equal
+ (format-time-string "%Y-%m-%d %H:%M:%S.%3N %z" look t)
+ "1972-06-30 23:59:59.999 +0000"))
+ (timefns-tests--decode-time look t
+ (list sec 59 23 30 6 1972 5 nil 0))
+ ;; "UTC0".
+ (should (string-equal
+ (format-time-string format look "UTC0")
+ "1972-06-30 23:59:59.999 +0000 (UTC)"))
+ (timefns-tests--decode-time look "UTC0"
+ (list sec 59 23 30 6 1972 5 nil 0))
+ ;; Negative UTC offset, as a Lisp list.
+ (should (string-equal
+ (format-time-string format look '(-28800 "PST"))
+ "1972-06-30 15:59:59.999 -0800 (PST)"))
+ (timefns-tests--decode-time look '(-28800 "PST")
+ (list sec 59 15 30 6 1972 5 nil -28800))
+ ;; Negative UTC offset, as a Lisp integer.
+ (should (string-equal
+ (format-time-string format look -28800)
+ ;; MS-Windows build replaces unrecognizable TZ values,
+ ;; such as "-08", with "ZZZ".
+ (if (eq system-type 'windows-nt)
+ "1972-06-30 15:59:59.999 -0800 (ZZZ)"
+ "1972-06-30 15:59:59.999 -0800 (-08)")))
+ (timefns-tests--decode-time look -28800
+ (list sec 59 15 30 6 1972 5 nil -28800))
+ ;; Positive UTC offset that is not an hour multiple, as a string.
+ (should (string-equal
+ (format-time-string format look "IST-5:30")
+ "1972-07-01 05:29:59.999 +0530 (IST)"))
+ (timefns-tests--decode-time look "IST-5:30"
+ (list sec 29 5 1 7 1972 6 nil 19800))))))
+
+(ert-deftest decode-then-encode-time ()
+ (let ((time-values (list 0 -2 1 0.0 -0.0 -2.0 1.0
+ most-negative-fixnum most-positive-fixnum
+ (1- most-negative-fixnum)
+ (1+ most-positive-fixnum)
+ '(0 1 0 0) '(1 0 0 0) '(-1 0 0 0)
+ '(123456789000000 . 1000000)
+ (cons (1+ most-positive-fixnum) 1000000000000)
+ (cons 1000000000000 (1+ most-positive-fixnum)))))
+ (dolist (a time-values)
+ (let* ((d (ignore-errors (decode-time a t t)))
+ (d-integer (ignore-errors (decode-time a t 'integer)))
+ (e (if d (encode-time d)))
+ (e-integer (if d-integer (encode-time d-integer))))
+ (should (or (not d) (time-equal-p a e)))
+ (should (or (not d-integer) (time-equal-p (time-convert a 'integer)
+ e-integer)))))))
+
+;;; This should not dump core.
+(ert-deftest format-time-string-with-outlandish-zone ()
+ (should (stringp
+ (format-time-string "%Y-%m-%d %H:%M:%S.%3N %z" nil
+ (concat (make-string 2048 ?X) "0")))))
+
+(defun timefns-tests--have-leap-seconds ()
+ (string-equal (format-time-string "%Y-%m-%d %H:%M:%S" 78796800 t)
+ "1972-06-30 23:59:60"))
+
+(ert-deftest format-time-string-with-bignum-on-32-bit ()
+ (should (or (string-equal
+ (format-time-string "%Y-%m-%d %H:%M:%S" (- (ash 1 31) 3600) t)
+ "2038-01-19 02:14:08")
+ (timefns-tests--have-leap-seconds))))
+
+;;; Tests of format-time-string padding
+
+(ert-deftest format-time-string-padding-minimal-deletes-unneeded-zeros ()
+ (let ((ref-time (encode-time '((123450 . 1000000) 0 0 15 2 2000 - - t))))
+ (should (equal (format-time-string "%-:::z" ref-time "FJT-12") "+12"))
+ (should (equal (format-time-string "%-N" ref-time t) "12345"))
+ (should (equal (format-time-string "%-6N" ref-time t) "12345"))
+ (should (equal (format-time-string "%-m" ref-time t) "2")))) ;not "02"
+
+(ert-deftest format-time-string-padding-minimal-retains-needed-zeros ()
+ (let ((ref-time (encode-time '((3450 . 1000000) 0 0 20 10 2000 - - t))))
+ (should (equal (format-time-string "%-z" ref-time "IST-5:30") "+530"))
+ (should (equal (format-time-string "%-4z" ref-time "IST-5:30") "+530"))
+ (should (equal (format-time-string "%4z" ref-time "IST-5:30") "+530"))
+ (should (equal (format-time-string "%-N" ref-time t) "00345"))
+ (should (equal (format-time-string "%-3N" ref-time t) "003"))
+ (should (equal (format-time-string "%3N" ref-time t) "003"))
+ (should (equal (format-time-string "%-m" ref-time t) "10")) ;not "1"
+ (should (equal (format-time-string "%-1m" ref-time t) "10")) ;not "1"
+ (should (equal (format-time-string "%1m" ref-time t) "10")))) ;not "1"
+
+(ert-deftest format-time-string-padding-spaces ()
+ (let ((ref-time (encode-time '((123000 . 1000000) 0 0 10 12 2000 - - t))))
+ (should (equal (format-time-string "%_7z" ref-time "CHA-12:45") " +1245"))
+ (should (equal (format-time-string "%_6N" ref-time t) "123 "))
+ (should (equal (format-time-string "%_9N" ref-time t) "123 "))
+ (should (equal (format-time-string "%_12N" ref-time t) "123 "))
+ (should (equal (format-time-string "%_m" ref-time t) "12"))
+ (should (equal (format-time-string "%_2m" ref-time t) "12"))
+ (should (equal (format-time-string "%_3m" ref-time t) " 12"))))
+
+(ert-deftest format-time-string-padding-zeros-adds-on-insignificant-side ()
+ "Fractional seconds have a fixed place on the left,
+and any padding must happen on the right. All other numbers have
+a fixed place on the right and are padded on the left."
+ (let ((ref-time (encode-time '((123000 . 1000000) 0 0 10 12 2000 - - t))))
+ (should (equal (format-time-string "%3m" ref-time t) "012"))
+ (should (equal (format-time-string "%7z" ref-time "CHA-12:45") "+001245"))
+ (should (equal (format-time-string "%12N" ref-time t) "123000000000"))
+ (should (equal (format-time-string "%9N" ref-time t) "123000000"))
+ (should (equal (format-time-string "%6N" ref-time t) "123000"))))
+
+
+(ert-deftest time-equal-p-nil-nil ()
+ (should (time-equal-p nil nil)))
+
+(ert-deftest time-arith-tests ()
+ (let ((time-values (list 0 -1 1 0.0 -0.0 -1.0 1.0
+ most-negative-fixnum most-positive-fixnum
+ (1- most-negative-fixnum)
+ (1+ most-positive-fixnum)
+ 1e1 -1e1 1e-1 -1e-1
+ 1e8 -1e8 1e-8 -1e-8
+ 1e9 -1e9 1e-9 -1e-9
+ 1e10 -1e10 1e-10 -1e-10
+ 1e16 -1e16 1e-16 -1e-16
+ 1e37 -1e37 1e-37 -1e-37
+ '(0 0 0 1) '(0 0 1 0) '(0 1 0 0) '(1 0 0 0)
+ '(-1 0 0 0) '(1 2 3 4) '(-1 2 3 4)
+ '(-123456789 . 100000) '(123456789 . 1000000)
+ (cons (1+ most-positive-fixnum) 1000000000000)
+ (cons 1000000000000 (1+ most-positive-fixnum)))))
+ (dolist (a time-values)
+ (should-error (time-add a 'ouch))
+ (should-error (time-add 'ouch a))
+ (should-error (time-subtract a 'ouch))
+ (should-error (time-subtract 'ouch a))
+ (dolist (b time-values)
+ (let ((aa (time-subtract (time-add a b) b)))
+ (should (or (time-equal-p a aa) (and (floatp aa) (isnan aa)))))
+ (should (= 1 (+ (if (time-less-p a b) 1 0)
+ (if (time-equal-p a b) 1 0)
+ (if (time-less-p b a) 1 0)
+ (if (or (and (floatp a) (isnan a))
+ (and (floatp b) (isnan b)))
+ 1 0))))
+ (should (or (not (time-less-p 0 b))
+ (time-less-p a (time-add a b))
+ (time-equal-p a (time-add a b))
+ (and (floatp (time-add a b)) (isnan (time-add a b)))))
+ (let ((x (float-time (time-add a b)))
+ (y (+ (float-time a) (float-time b))))
+ (should (or (and (isnan x) (isnan y))
+ (= x y)
+ (< 0.99 (/ x y) 1.01)
+ (< 0.99 (/ (- (float-time a)) (float-time b))
+ 1.01))))))))
+
+(ert-deftest time-rounding-tests ()
+ (should (time-equal-p 1e-13 (time-add 0 1e-13))))
+
+(ert-deftest encode-time-dst-numeric-zone ()
+ "Check for Bug#35502."
+ (should (time-equal-p
+ (encode-time '(29 31 17 30 4 2019 2 t 7200))
+ '(23752 27217))))
+
+(ert-deftest encode-time-alternate-apis ()
+ (let* ((time '(30 30 12 15 6 1970))
+ (time-1 (append time '(nil -1 nil)))
+ (etime (encode-time time)))
+ (should (time-equal-p etime (encode-time time-1)))
+ (should (time-equal-p etime (apply #'encode-time time)))
+ (should (time-equal-p etime (apply #'encode-time time-1)))
+ (should (time-equal-p etime (apply #'encode-time (append time '(nil)))))))
+
+(ert-deftest float-time-precision ()
+ (should (= (float-time '(0 1 0 4025)) 1.000000004025))
+ (should (= (float-time '(1000000004025 . 1000000000000)) 1.000000004025))
+
+ (should (< 0 (float-time '(1 . 10000000000))))
+ (should (< (float-time '(-1 . 10000000000)) 0))
+
+ (let ((x 1.0))
+ (while (not (zerop x))
+ (dolist (multiplier '(-1.9 -1.5 -1.1 -1 1 1.1 1.5 1.9))
+ (let ((xmult (* x multiplier)))
+ (should (= xmult (float-time (time-convert xmult t))))))
+ (setq x (/ x 2))))
+
+ (let ((x 1.0))
+ (while (ignore-errors (time-convert x t))
+ (dolist (divisor '(-1.9 -1.5 -1.1 -1 1 1.1 1.5 1.9))
+ (let ((xdiv (/ x divisor)))
+ (should (= xdiv (float-time (time-convert xdiv t))))))
+ (setq x (* x 2)))))
+
+(ert-deftest time-convert-forms ()
+ ;; These computations involve numbers that should have exact
+ ;; representations on any Emacs platform.
+ (dolist (time '(-86400 -1 0 1 86400))
+ (dolist (delta '(0 0.0 0.25 3.25 1000 1000.25))
+ (let ((time+ (+ time delta))
+ (time- (- time delta)))
+ (dolist (form '(nil t list 4 1000 1000000 1000000000))
+ (should (time-equal-p time (time-convert time form)))
+ (should (time-equal-p time- (time-convert time- form)))
+ (should (time-equal-p time+ (time-convert time+ form))))))))
+
+;;; timefns-tests.el ends here
diff --git a/test/src/undo-tests.el b/test/src/undo-tests.el
index 3ff75ae68d5..cb0822fb1b9 100644
--- a/test/src/undo-tests.el
+++ b/test/src/undo-tests.el
@@ -1,21 +1,23 @@
-;;; undo-tests.el --- Tests of primitive-undo
+;;; undo-tests.el --- Tests of primitive-undo -*- lexical-binding: t -*-
-;; Copyright (C) 2012-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2022 Free Software Foundation, Inc.
;; Author: Aaron S. Hawley <aaron.s.hawley@gmail.com>
-;; This program is free software: you can redistribute it and/or
+;; This file is part of GNU Emacs.
+;;
+;; GNU Emacs is free software: you can redistribute it and/or
;; modify it under the terms of the GNU General Public License as
;; published by the Free Software Foundation, either version 3 of the
;; License, or (at your option) any later version.
;;
-;; This program is distributed in the hope that it will be useful, but
+;; GNU Emacs is distributed in the hope that it will be useful, but
;; WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
;; General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
-;; along with this program. If not, see `https://www.gnu.org/licenses/'.
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
@@ -44,6 +46,8 @@
;;; Code:
(require 'ert)
+(require 'ert-x)
+(require 'facemenu)
(ert-deftest undo-test0 ()
"Test basics of \\[undo]."
@@ -72,7 +76,7 @@
(undo-boundary)
(put-text-property (point-min) (point-max) 'face 'bold)
(undo-boundary)
- (remove-text-properties (point-min) (point-max) '(face default))
+ (remove-list-of-text-properties (point-min) (point-max) '(face))
(undo-boundary)
(set-buffer-multibyte (not enable-multibyte-characters))
(undo-boundary)
@@ -85,6 +89,7 @@
(ert-deftest undo-test1 ()
"Test undo of \\[undo] command (redo)."
+ (require 'facemenu)
(with-temp-buffer
(buffer-enable-undo)
(undo-boundary)
@@ -214,17 +219,14 @@
(ert-deftest undo-test-file-modified ()
"Test undoing marks buffer visiting file unmodified."
- (let ((tempfile (make-temp-file "undo-test")))
- (unwind-protect
- (progn
- (with-current-buffer (find-file-noselect tempfile)
- (insert "1")
- (undo-boundary)
- (set-buffer-modified-p nil)
- (insert "2")
- (undo)
- (should-not (buffer-modified-p))))
- (delete-file tempfile))))
+ (ert-with-temp-file tempfile
+ (with-current-buffer (find-file-noselect tempfile)
+ (insert "1")
+ (undo-boundary)
+ (set-buffer-modified-p nil)
+ (insert "2")
+ (undo)
+ (should-not (buffer-modified-p)))))
(ert-deftest undo-test-region-not-most-recent ()
"Test undo in region of an edit not the most recent."
@@ -255,7 +257,7 @@
(insert "12345")
(search-backward "4")
(undo-boundary)
- (delete-forward-char 1)
+ (funcall-interactively 'delete-forward-char 1)
(search-backward "1")
(undo-boundary)
(insert "xxxx")
@@ -299,7 +301,7 @@ undo-make-selective-list."
(insert "ddd")
(search-backward "ad")
(undo-boundary)
- (delete-forward-char 2)
+ (funcall-interactively 'delete-forward-char 2)
(undo-boundary)
;; Select "dd"
(push-mark (point) t t)
@@ -348,7 +350,7 @@ undo-make-selective-list."
(let ((m (make-marker)))
(set-marker m 2 (current-buffer))
(goto-char (point-min))
- (delete-forward-char 3)
+ (funcall-interactively 'delete-forward-char 3)
(undo-boundary)
(should (= (point-min) (marker-position m)))
(undo)
@@ -369,7 +371,7 @@ undo-make-selective-list."
(push-mark (point) t t)
(setq mark-active t)
(goto-char (point-min))
- (delete-forward-char 1) ;; delete region covering "ab"
+ (funcall-interactively 'delete-forward-char 1) ; delete region covering "ab"
(undo-boundary)
(should (= (point-min) (marker-position m)))
;; Resurrect "ab". m's insertion type means the reinsertion
@@ -389,7 +391,7 @@ Demonstrates bug 16818."
(let ((m (make-marker)))
(set-marker m 2 (current-buffer)) ; m at b
(goto-char (point-min))
- (delete-forward-char 3) ; m at d
+ (funcall-interactively 'delete-forward-char 3) ; m at d
(undo-boundary)
(set-marker m 4) ; m at g
(undo)
@@ -422,7 +424,7 @@ Demonstrates bug 16818."
(push-mark (point) t t)
(setq mark-active t)
(goto-char (- (point) 3))
- (delete-forward-char 1)
+ (funcall-interactively 'delete-forward-char 1)
(undo-boundary)
(insert "bbb")
@@ -452,17 +454,16 @@ Demonstrates bug 25599."
(insert ";; aaaaaaaaa
;; bbbbbbbb")
(let ((overlay-modified
- (lambda (ov after-p _beg _end &optional length)
+ (lambda (ov after-p _beg _end &optional _length)
(unless after-p
(when (overlay-buffer ov)
(delete-overlay ov))))))
(save-excursion
(goto-char (point-min))
- (let ((ov (make-overlay (line-beginning-position 2)
- (line-end-position 2))))
+ (let ((ov (make-overlay (pos-bol 2) (pos-eol 2))))
(overlay-put ov 'insert-in-front-hooks
(list overlay-modified)))))
- (kill-region (point-min) (line-beginning-position 2))
+ (kill-region (point-min) (pos-bol 2))
(undo-boundary)
(undo)))
diff --git a/test/src/xdisp-tests.el b/test/src/xdisp-tests.el
new file mode 100644
index 00000000000..6ff64d0431a
--- /dev/null
+++ b/test/src/xdisp-tests.el
@@ -0,0 +1,182 @@
+;;; xdisp-tests.el --- tests for xdisp.c functions -*- lexical-binding: t -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+
+(defmacro xdisp-tests--in-minibuffer (&rest body)
+ (declare (debug t) (indent 0))
+ `(catch 'result
+ (minibuffer-with-setup-hook
+ (lambda ()
+ (let ((redisplay-skip-initial-frame nil)
+ (executing-kbd-macro nil)) ;Don't skip redisplay
+ (throw 'result (progn . ,body))))
+ (let ((executing-kbd-macro t)) ;Force real minibuffer in `read-string'.
+ (read-string "toto: ")))))
+
+(ert-deftest xdisp-tests--minibuffer-resizing () ;; bug#43519
+ (should
+ (equal
+ t
+ (xdisp-tests--in-minibuffer
+ (insert "hello")
+ (let ((ol (make-overlay (point) (point)))
+ (max-mini-window-height 1)
+ (text "askdjfhaklsjdfhlkasjdfhklasdhflkasdhflkajsdhflkashdfkljahsdlfkjahsdlfkjhasldkfhalskdjfhalskdfhlaksdhfklasdhflkasdhflkasdhflkajsdhklajsdgh"))
+ ;; (save-excursion (insert text))
+ ;; (sit-for 2)
+ ;; (delete-region (point) (point-max))
+ (put-text-property 0 1 'cursor t text)
+ (overlay-put ol 'after-string text)
+ (redisplay 'force)
+ ;; Make sure we do the see "hello" text.
+ (prog1 (equal (window-start) (point-min))
+ ;; (list (window-start) (window-end) (window-width))
+ (delete-overlay ol)))))))
+
+(ert-deftest xdisp-tests--minibuffer-scroll () ;; bug#44070
+ (let ((posns
+ (xdisp-tests--in-minibuffer
+ (let ((max-mini-window-height 4))
+ (dotimes (_ 80) (insert "\nhello"))
+ (goto-char (point-min))
+ (redisplay 'force)
+ (goto-char (point-max))
+ ;; A simple edit like removing the last `o' shouldn't cause
+ ;; the rest of the minibuffer's text to move.
+ (list
+ (progn (redisplay 'force) (window-start))
+ (progn (delete-char -1)
+ (redisplay 'force) (window-start))
+ (progn (goto-char (point-min)) (redisplay 'force)
+ (goto-char (point-max)) (redisplay 'force)
+ (window-start)))))))
+ (should (equal (nth 0 posns) (nth 1 posns)))
+ (should (equal (nth 1 posns) (nth 2 posns)))))
+
+(ert-deftest xdisp-tests--window-text-pixel-size () ;; bug#45748
+ (with-temp-buffer
+ (insert "xxx")
+ (switch-to-buffer (current-buffer))
+ (let* ((char-width (frame-char-width))
+ (size (window-text-pixel-size nil t t))
+ (width-in-chars (/ (car size) char-width)))
+ (should (equal width-in-chars 3)))))
+
+(ert-deftest xdisp-tests--window-text-pixel-size-leading-space () ;; bug#45748
+ (with-temp-buffer
+ (insert " xx")
+ (switch-to-buffer (current-buffer))
+ (let* ((char-width (frame-char-width))
+ (size (window-text-pixel-size nil t t))
+ (width-in-chars (/ (car size) char-width)))
+ (should (equal width-in-chars 3)))))
+
+(ert-deftest xdisp-tests--window-text-pixel-size-trailing-space () ;; bug#45748
+ (with-temp-buffer
+ (insert "xx ")
+ (switch-to-buffer (current-buffer))
+ (let* ((char-width (frame-char-width))
+ (size (window-text-pixel-size nil t t))
+ (width-in-chars (/ (car size) char-width)))
+ (should (equal width-in-chars 3)))))
+
+(ert-deftest xdisp-tests--find-directional-overrides-case-1 ()
+ (with-temp-buffer
+ (insert "\
+int main() {
+ bool isAdmin = false;
+ /*‮ }⁦if (isAdmin)⁩ ⁦ begin admins only */
+ printf(\"You are an admin.\\n\");
+ /* end admins only ‮ { ⁦*/
+ return 0;
+}")
+ (goto-char (point-min))
+ (should (eq (bidi-find-overridden-directionality (point-min) (point-max)
+ nil)
+ 46))))
+
+(ert-deftest xdisp-tests--find-directional-overrides-case-2 ()
+ (with-temp-buffer
+ (insert "\
+#define is_restricted_user(user) \\
+ !strcmp (user, \"root\") ? 0 : \\
+ !strcmp (user, \"admin\") ? 0 : \\
+ !strcmp (user, \"superuser‮⁦? 0 : 1⁩ ⁦\")⁩‬
+
+int main () {
+ printf (\"root: %d\\n\", is_restricted_user (\"root\"));
+ printf (\"admin: %d\\n\", is_restricted_user (\"admin\"));
+ printf (\"superuser: %d\\n\", is_restricted_user (\"superuser\"));
+ printf (\"luser: %d\\n\", is_restricted_user (\"luser\"));
+ printf (\"nobody: %d\\n\", is_restricted_user (\"nobody\"));
+}")
+ (goto-char (point-min))
+ (should (eq (bidi-find-overridden-directionality (point-min) (point-max)
+ nil)
+ 138))))
+
+(ert-deftest xdisp-tests--find-directional-overrides-case-3 ()
+ (with-temp-buffer
+ (insert "\
+#define is_restricted_user(user) \\
+ !strcmp (user, \"root\") ? 0 : \\
+ !strcmp (user, \"admin\") ? 0 : \\
+ !strcmp (user, \"superuser‮⁦? '#' : '!'⁩ ⁦\")⁩‬
+
+int main () {
+ printf (\"root: %d\\n\", is_restricted_user (\"root\"));
+ printf (\"admin: %d\\n\", is_restricted_user (\"admin\"));
+ printf (\"superuser: %d\\n\", is_restricted_user (\"superuser\"));
+ printf (\"luser: %d\\n\", is_restricted_user (\"luser\"));
+ printf (\"nobody: %d\\n\", is_restricted_user (\"nobody\"));
+}")
+ (goto-char (point-min))
+ (should (eq (bidi-find-overridden-directionality (point-min) (point-max)
+ nil)
+ 138))))
+
+(ert-deftest test-get-display-property ()
+ (with-temp-buffer
+ (insert (propertize "foo" 'face 'bold 'display '(height 2.0)))
+ (should (equal (get-display-property 2 'height) 2.0)))
+ (with-temp-buffer
+ (insert (propertize "foo" 'face 'bold 'display '((height 2.0)
+ (space-width 2.0))))
+ (should (equal (get-display-property 2 'height) 2.0))
+ (should (equal (get-display-property 2 'space-width) 2.0)))
+ (with-temp-buffer
+ (insert (propertize "foo bar" 'face 'bold
+ 'display '[(height 2.0)
+ (space-width 20)]))
+ (should (equal (get-display-property 2 'height) 2.0))
+ (should (equal (get-display-property 2 'space-width) 20))))
+
+(ert-deftest test-messages-buffer-name ()
+ (should
+ (equal
+ (let ((messages-buffer-name "test-message"))
+ (message "foo")
+ (with-current-buffer messages-buffer-name
+ (buffer-string)))
+ "foo\n")))
+
+;;; xdisp-tests.el ends here
diff --git a/test/src/xfaces-tests.el b/test/src/xfaces-tests.el
new file mode 100644
index 00000000000..16f16537918
--- /dev/null
+++ b/test/src/xfaces-tests.el
@@ -0,0 +1,57 @@
+;;; xfaces-tests.el --- tests for xfaces.c -*- lexical-binding: t -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+
+(ert-deftest xfaces-color-distance ()
+ ;; Check symmetry (bug#41544).
+ (should (equal (color-distance "#222222" "#ffffff")
+ (color-distance "#ffffff" "#222222"))))
+
+(ert-deftest xfaces-internal-color-values-from-color-spec ()
+ (should (equal (color-values-from-color-spec "#f05")
+ '(#xffff #x0000 #x5555)))
+ (should (equal (color-values-from-color-spec "#1fb0C5")
+ '(#x1f1f #xb0b0 #xc5c5)))
+ (should (equal (color-values-from-color-spec "#1f8b0AC5e")
+ '(#x1f81 #xb0aa #xc5eb)))
+ (should (equal (color-values-from-color-spec "#1f83b0ADC5e2")
+ '(#x1f83 #xb0ad #xc5e2)))
+ (should (equal (color-values-from-color-spec "#1f83b0ADC5e2g") nil))
+ (should (equal (color-values-from-color-spec "#1f83b0ADC5e20") nil))
+ (should (equal (color-values-from-color-spec "#12345") nil))
+ (should (equal (color-values-from-color-spec "rgb:f/23/28a")
+ '(#xffff #x2323 #x28a2)))
+ (should (equal (color-values-from-color-spec "rgb:1234/5678/09ab")
+ '(#x1234 #x5678 #x09ab)))
+ (should (equal (color-values-from-color-spec "rgb:0//0") nil))
+ (should (equal (color-values-from-color-spec "rgbi:0/0.5/0.1")
+ '(0 32768 6554)))
+ (should (equal (color-values-from-color-spec "rgbi:1e-3/1.0e-2/1e0")
+ '(66 655 65535)))
+ (should (equal (color-values-from-color-spec "rgbi:0/0.5/10") nil))
+ (should (equal (color-values-from-color-spec "rgbi:0/0/ 0") nil))
+ (should (equal (color-values-from-color-spec "rgbi:0/0x0/0") nil))
+ (should (equal (color-values-from-color-spec "rgbi:0/+0x1/0") nil)))
+
+(provide 'xfaces-tests)
+
+;;; xfaces-tests.el ends here
diff --git a/test/src/xml-tests.el b/test/src/xml-tests.el
index 557e6da4524..6a8290bd0c8 100644
--- a/test/src/xml-tests.el
+++ b/test/src/xml-tests.el
@@ -1,6 +1,6 @@
-;;; libxml-parse-tests.el --- Test suite for libxml parsing.
+;;; xml-tests.el --- Test suite for libxml parsing. -*- lexical-binding: t -*-
-;; Copyright (C) 2014-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2022 Free Software Foundation, Inc.
;; Author: Ulf Jasper <ulf.jasper@web.de>
;; Keywords: internal
@@ -27,6 +27,8 @@
(require 'ert)
+(declare-function libxml-parse-xml-region "xml.c")
+
(defvar libxml-tests--data-comments-preserved
`(;; simple case
("<?xml version=\"1.0\"?><foo baz=\"true\">bar</foo>"
@@ -42,33 +44,14 @@
(comment nil "comment-b") (comment nil "comment-c"))))
"Alist of XML strings and their expected parse trees for preserved comments.")
-(defvar libxml-tests--data-comments-discarded
- `(;; simple case
- ("<?xml version=\"1.0\"?><foo baz=\"true\">bar</foo>"
- . (foo ((baz . "true")) "bar"))
- ;; toplevel comments -- first document child must not get lost
- (,(concat "<?xml version=\"1.0\"?><foo>bar</foo><!--comment-1-->"
- "<!--comment-2-->")
- . (foo nil "bar"))
- (,(concat "<?xml version=\"1.0\"?><!--comment-a--><foo a=\"b\">"
- "<bar>blub</bar></foo><!--comment-b--><!--comment-c-->")
- . (foo ((a . "b")) (bar nil "blub"))))
- "Alist of XML strings and their expected parse trees for discarded comments.")
-
-
(ert-deftest libxml-tests ()
"Test libxml."
- (when (fboundp 'libxml-parse-xml-region)
- (with-temp-buffer
- (dolist (test libxml-tests--data-comments-preserved)
- (erase-buffer)
- (insert (car test))
- (should (equal (cdr test)
- (libxml-parse-xml-region (point-min) (point-max)))))
- (dolist (test libxml-tests--data-comments-discarded)
- (erase-buffer)
- (insert (car test))
- (should (equal (cdr test)
- (libxml-parse-xml-region (point-min) (point-max) nil t)))))))
-
-;;; libxml-tests.el ends here
+ (skip-unless (fboundp 'libxml-parse-xml-region))
+ (with-temp-buffer
+ (dolist (test libxml-tests--data-comments-preserved)
+ (erase-buffer)
+ (insert (car test))
+ (should (equal (cdr test)
+ (libxml-parse-xml-region (point-min) (point-max)))))))
+
+;;; xml-tests.el ends here